Transpozycja Cambridge

21

Jestem pewien, że większość, jeśli nie wszyscy, spotkała się z tym w pewnym momencie:

Aoccdrnig do rscheearch w Cmabrigde Uinervtisy, to nie jest mttaer w waht orer lte w wrod, olny iprmoetnt tihng to taht the frist and lsat be at the rghit pclae. Rset może być toat msem i możesz siedzieć na nim wouthit porbelm. Tihs to bcuseae, huamn mnid deos nie raed ervey lteter by istlef, ale wrod jak wlohe.

  • Utwórz program, który wprowadza dowolną ilość tekstu. Do celów testowych użyj nieszyfrowanej wersji powyższego tekstu, znalezionej poniżej.

  • Program musi następnie losowo transponować litery każdego słowa o długości 4 lub więcej liter, z wyjątkiem pierwszej i ostatniej litery każdego słowa.

  • Wszystkie pozostałe formatowanie musi pozostać takie samo (wielkie litery i znaki interpunkcyjne itp.).

Testowanie tekstu:

Według naukowca z Cambridge University nie ma znaczenia, w jakiej kolejności są litery w słowie, jedyną ważną rzeczą jest to, że pierwsza i ostatnia litera są na właściwym miejscu. Reszta może być totalnym bałaganem i nadal możesz go przeczytać bez problemu. Wynika to z faktu, że ludzki umysł nie czyta każdej litery samodzielnie, ale słowo jako całość.

Jak zwykle jest to golf golfowy. Najkrótszy kod wygrywa.

jdstankosky
źródło
2
Podobnie jak w przypadku losowego wybierania liter w słowie , chociaż w tym jednym tylko jedno słowo musi być zakodowane, podczas gdy tutaj jest to każde słowo w zdaniu.
Gareth,
Zgadzam się. Pytania są na tyle podobne, że rozwiązania jednego problemu można zastosować prawie bezpośrednio w przypadku drugiego.
primo,
1
Ostatnia litera jest niepoprawna w rscheearchprzykładowym tekście.
daniero
10
Byłbym pod większym wrażeniem programu, który wykonał operację odwrotną (tzn. Wejście to zaszyfrowany tekst).
Pan Lister
1
Czy pozycja apostrofu musi don'tpozostać na tej samej pozycji? Specyfikacja mówi, All other formatting must remain the same (capitalization and punctuation, etc.).ale nie jestem pewien, jak to tutaj działa ...
Gaffi

Odpowiedzi:

9

Ruby - 50 48 znaków plus -pparametr wiersza poleceń.

gsub(/(?<=\w)\w+(?=\w)/){[*$&.chars].shuffle*''}

Dzięki @primo za -2 znaki.

Test

➜  codegolf git:(master) ruby -p 9261-cambridge-transposition.rb < 9261.in
Acdrcinog to a racreseher at Cagribmde Ursvetniiy, it dsoen't mttaer in waht odrer the leertts in a word are, the olny ionarpmtt tnhig is that the fsirt and last letetr be at the rghit pcale. The rset can be a taotl mses and you can slitl raed it wthiuot perlbom. Tihs is buaecse the hmuan mind does not raed ervey lteetr by ietlsf but the word as a wlhoe.
Dogbert
źródło
1
Ruby nie obsługuje \Ktwierdzenia o zerowej szerokości? Ponadto, najbardziej wewnętrzne grupowanie jest niepotrzebne, używając $&zamiast $1.
primo,
@primo, myślę, że nie, to nie działa i nie znalazłem go na żadnej stronie referencyjnej. Dzięki za $&wskazówkę :)
Dogbert,
Masz rację. Chyba założyłem, że wzięli perl regex bezpośrednio, tak jak php;)
primo,
3
powiedz mi więcej o tym codegolfskrypcie
Sparr
1
Wiele lat później, ale: Nie ma potrzeby tworzenia nowej tablicy przed losowaniem: [*$&.chars]=> $&.chars, oszczędzając 3 bajty.
daniero
5

Python, 118

Python jest strasznie niezręczny dla takich rzeczy!

from random import*
for w in raw_input().split():l=len(w)-2;print l>0and w[0]+''.join((sample(w[1:-1],l)))+w[-1]or w,

Premia

Próbowałem kilku innych rzeczy, które moim zdaniem byłyby sprytne, ale musisz zaimportować różne rzeczy, a wiele metod nie ma wartości zwracanych, ale trzeba je wywoływać osobno jako własną instrukcję. Najgorsze jest to, że musisz przekonwertować ciąg na listę, a następnie ponownie joinumieścić go w łańcuchu.

W każdym razie oto kilka rzeczy, które próbowałem:

Regex!
import re,random
def f(x):a,b,c=x.group(1,2,3);return a+''.join(random.sample(b,len(b)))+c
print re.sub('(\w)(\w+)(\w)',f,raw_input())
Permutacje!
import itertools as i,random as r
for w in raw_input().split():print''.join(r.choice([x for x in i.permutations(w)if w[0]+w[-1]==x[0]+x[-1]])),
Nie można losowo podzielić partycji listy i shufflezwraca None, tak!
from random import*
for w in raw_input().split():
 w=list(w)
 if len(w)>3:v=w[1:-1];shuffle(v);w[1:-1]=v
 print ''.join(w),
daniero
źródło
4

PHP 84 bajty

<?for(;$s=fgets(STDIN);)echo preg_filter('/\w\K\w+(?=\w)/e','str_shuffle("\0")',$s);

Używanie wyrażenia regularnego do przechwytywania słów o długości co najmniej 4 3 litery i tasowanie wewnętrznych znaków. Ten kod obsługuje również dane wejściowe z wieloma wierszami.

Jeśli wymagany jest tylko jeden wiersz danych wejściowych (jak w przykładzie), można go zmniejszyć do 68 bajtów

<?=preg_filter('/\w\K\w+(?=\w)/e','str_shuffle("\0")',fgets(STDIN));

Na środku jest tylko jedna litera, więc nie ma znaczenia, czy ją przetasujesz.

primo
źródło
3

J (48)

''[1!:2&4('\w(\w+)\w';,1)({~?~@#)rxapply 1!:1[3

Wyjaśnienie:

  • 1!:1[3: czytaj wszystkie dane wejściowe ze standardowego wejścia
  • rxapply: zastosuj daną funkcję do części danych wejściowych, które pasują do wyrażenia regularnego
  • ({~?~@#): ciąg czasownika, który przetasowuje dane wejściowe: #liczy długość, stosuje się to do obu stron, ?podając N odrębnych liczb od 0 do N, {a następnie wybiera elementy przy tych indeksach z tablicy wejściowej.
  • ('\w(\w+)\w';,1): użyj tego wyrażenia regularnego, ale używaj tylko wartości z pierwszej grupy
  • [1!:2&4: wyślij niesformatowane wyjście na standardowe wyjście
  • ''[: pomija sformatowane dane wyjściowe. Jest to konieczne, ponieważ w przeciwnym razie wyświetla tylko tę część wyjścia, która pasuje do linii terminala, a następnie kończy się na ....
marinus
źródło
3

Siatkówka , 10 bajtów

?V`\B\w+\B

Wypróbuj online!

Hej, to stare wyzwanie zostało stworzone dla nowej Retiny!

Wyjaśnienie

\B\w+\Bdopasowuje grupy liter między granicami, to znaczy grupy liter, które nie rozpoczynają ani nie kończą słowa. Ponieważ wyrażenia regularne są zachłanne, dopasuje to wszystkie litery słowa oprócz pierwszej i ostatniej.

Vjest etapem „odwrotnym”, który odwraca kolejność znaków w każdym dopasowaniu wyrażenia regularnego. Dzięki ?opcji to szyfruje je zamiast.

Lew
źródło
Zdarzyło mi się to po znalezieniu innego 10-bajtowego rozwiązania .
FryAmTheEggman
1

APL 107

Niestety mój interpreter APL nie obsługuje wyrażeń regularnych, więc oto wersja domowa, w której tekst do zaszyfrowania jest przechowywany w zmiennej t:

⎕av[((~z)\(∊y)[∊(+\0,¯1↓n)+¨n?¨n←⍴¨y←(~z←×(~x)+(x>¯1↓0,x)+x>1↓(x←~53≤(∊(⊂⍳26)+¨65 97)⍳v←⎕av⍳,t),0)⊂v])+z×v]

Zasadniczo kod dzieli tekst na słowa oparte tylko na literach alfabetu, a następnie na litery między pierwszą a ostatnią literą tych słów. Litery te są następnie mieszane i cały ciąg znaków jest składany ponownie.

Graham
źródło
1

APL, 58 49

Wierzę, że to działa w IBM APL2 (nie mam IBM APL)

({⍵[⌽∪t,⌽∪1,?⍨t←⍴⍵]}¨x⊂⍨~b),.,x⊂⍨b←' ,.'∊⍨x←⍞,' '

Jeśli nie, to w aplikacji Dyalog APL dodaj do przodu:

 ⎕ML←3⋄

co dodaje 6 znaków


Zakłada się, że jedynymi znakami innymi niż słowa są spacja, przecinek i kropka.

TwiNight
źródło
Nadal można grać w golfa, ale nie mam symboli APL na iPhonie ...
TwiNight,
1

VBA, 351 373 /409

Sub v(g)
m=1:Z=Split(g," "):j=UBound(Z)
For u=0 To j
t=Z(u):w=Len(t):l=Right(t,1):If Not l Like"[A-Za-z]" Then w=w-1:t=Left(t,w):e=l Else e=""
If w>3 Then
n=Left(t,1):p=w-1:s=Right(t,p):f=Right(t,1)
For p=1 To p-1
q=w-p:r=Int((q-1)*Rnd())+1:n=n & Mid(s,r,1):s=Left(s,r-1) & Right(s,q-r)
Next
Else
n=t:f=""
End If
d=d & n & f & e & " "
Next
g=d
End Sub

Metoda alternatywna (większa):

Sub v(g)
m=1:Z=Split(g," "):j=UBound(Z)
For u=0 To j
t=Split(StrConv(Z(u),64),Chr(0)):w=UBound(t)-1:l=Asc(t(w)):If l<64 Or (l>90 And l<97) Or l>122 Then e=t(w):w=w-1 Else e=""
If w>3 Then
n=t(0):p=w-1:s=""
For i=-p To -1
s=t(-i) & s
Next
f=t(w)
For p=1 To p-1
r=Int((w-p)*Rnd())+1:n=n & Mid(s,r,1):s=Left(s,r-1) & Right(s,w-p-r)
Next
n=n & s
Else
n=Z(u):f="":e=""
End If
d=d & n & f & e & " "
Next
g=d
End Sub

Obie te metody zmieniają wartość zmiennej przekazywanej do Sub. to znaczy

Sub Test()
strTestString = "This is a test."
v strTestString
Debug.Print strTestString
End Sub

wyświetli coś takiego:

"Tihs is a tset."

Ponadto losowo interpunkcja między słowami jest losowa, więc może nie pasować do specyfikacji w 100%.

Gaffi
źródło
1

APL NARS 172 znaki

r←g x;i;s;d;k
s←⎕AV[98..123]∪⎕A
i←1⋄v←''⋄r←''⋄k←⍴x
A:d←''⋄→C×⍳i>k⋄d←x[i]⋄→C×⍳∼d∊s⋄v←v,d⋄i+←1⋄→A
C:v←{t←¯2+⍴r←⍵⋄t≤1:r⋄r[1+t?t]←⍵[1+⍳t]⋄r}v
r←∊r,v,d
v←''⋄i+←1⋄→A×⍳i≤k
g x←⍞

13 + 17 + 18 + 44 + 41 + 8 + 17 + 5 + 9 = 172; Ta funkcja g () ma dane wejściowe w postaci łańcucha; ma dane wyjściowe jako ciąg. Dodałem polecenie wejściowe, ponieważ nie wiem, jak wstawić \ w cudzysłowie. Skomentował

∇r←g x;i;s;d;k
   ⍝ words are element of  a-zA-Z separed from all other
   s←⎕AV[98..123]∪⎕A ⍝a-zA-Z ascii ⎕IO = 1
   i←1⋄v←''⋄r←''⋄k←⍴x
A:   d←''⋄→C×⍳i>k⋄d←x[i]⋄→C×⍳∼d∊s⋄v←v,d⋄i+←1⋄→A
C:      v←{t←¯2+⍴r←⍵⋄t≤1:r⋄r[1+t?t]←⍵[1+⍳t]⋄r}v
        r←∊r,v,d
        v←''⋄i+←1⋄→A×⍳i≤k
∇

wynik

g x←⍞
According to a researcher at Cambridge University, it doesn't matter in what order the letters in a word are, the only important thing is that the first and last letter be at the right place. The rest can be a total mess and you can still read it without problem. This is because the human mind does not read every letter by itself but the word as a whole.
  Androiccg to a rhraeecser at Cgirbdmae Uirevtsiny, it deson't mtetar in waht oderr the ltrtees in a wrod are, the olny intro
  apmt tinhg is taht the frsit and lsat lteter be at the rghit pacle. The rset can be a ttaol mses and you can siltl rae
  d it wtuhoit poeblrm. Tihs is bcsauee the hmaun mnid deos not raed eervy lteter by isletf but the wrod as a wolhe.
RosLuP
źródło
1

PHP 7.1, nie konkuruje, 80 bajtów

for(;$w=$argv[++$i];)echo$w[3]?$w[0].str_shuffle(substr($w,1,-1)).$w[-1]:$w," ";

pobiera dane wejściowe z argumentów wiersza poleceń. Uruchom z -nr. (oczywiście przestanie działać po interpunkcji)

Tytus
źródło
1

PHP, 94 + 1 bajtów

+1 za -Rflagę

<?=preg_replace_callback("/(?<=\w)\w+(?=\w)/",function($m){return str_shuffle($m[0]);},$argn);

Wprowadzanie rur przez php -nR '<code>'.

Uwaga: preg_replace_callbackprzyszedł do PHP w wersji 4.0.5; zamknięcia zostały wprowadzone w php 5.3;
więc wymaga to PHP 5.3 lub nowszego.

Niestety, dopasowanie jest zawsze wysyłane jako tablica, nawet jeśli nie ma pod wzorców,
dlatego nie mogę po prostu użyć str_shufflejako wywołania zwrotnego, co pozwoliłoby zaoszczędzić 29 bajtów.

Tytus
źródło
1

JavaScript, 76 67 bajtów

dzięki Arnauldowi za -9 bajtów.

t=>t.replace(/\B\w+\B/g,m=>[...m].sort(_=>Math.random()-.5).join``)

Wypróbuj online!


Nie golfił

t =>                  // function with a single argument
     t.replace(       // Replace ...
         /\B\w+\B/g,  // every match of the regex
         m => ...     // with the return value of the replacement function
     )

/       /g            // Match all occurences of
   \w+                // 1 or more word chars ...
 \B   \B              // ... that aren't on the beginning or end of the word

m =>                  // Replacement function
     [...m]           // convert matched string to a list of chars
       .sort(_ => Math.random()-.5) // sort with a random comparision function
       .join``        // join the list into a single string
ovs
źródło
Zauważ, że „ tasowanie w taki sposób nie jest jednolite
202729,
Możesz użyć /\B\w+\B/g . (Ale jeśli chodzi o nagrodę, zwróć uwagę, że długość kodu nie jest ważna. )
Arnauld
1
@Arnauld wielkie dzięki. Ponieważ jest to nadal kodegolf, każdy bajt się liczy.
ovs
@Arnauld Poważna reguła nadal obowiązuje.
user202729,
1
@trejder Dodałem wyjaśnienie, które powinno pomóc w modyfikacji kodu do własnych potrzeb. W obecnej formie kod powinien działać dobrze w większości przeglądarek. Jeśli chcesz użyć tego w prawdziwym kodzie, prawdopodobnie powinieneś zmienić sposób, w jaki przetasowuje znaki do jednolitego algorytmu.
ovs
0

R 179

Używając funkcji, którą napisałem dla losowych liter w zadaniu tekstowym :

Wkład:

s <- "According to a researcher at Cambridge University, it doesn't matter in what order the letters in a word are, the only important thing is that the first and last letter be at the right place. The rest can be a total mess and you can still read it without problem. This is because the human mind does not read every letter by itself but the word as a whole."

Rozwiązanie:

f=function(w){l=length;s=strsplit(w,"")[[1]];ifelse(l(s)<3,w,paste(c(s[1],sample(s[2:(l(s)-1)]),s[l(s)]),collapse=""))}
g=Vectorize(f)
paste(g(strsplit(s," ")[[1]]), collapse=" ")

Wynik:

[1] "Arioccdng to a reehaecrsr at Cabrgimde Uveirisnyt, it des'not mttear in waht odrer the lttrees in a wrod are, the olny inpotmart thnig is that the fsrit and lsat letetr be at the right palce. The rset can be a toatl mses and you can stlil raed it wutioht pmrlebo. This is bsuceae the hmuan mnid deos not read ervey lteetr by iesltf but the word as a wleho."
Paolo
źródło
0

Pyth, 23 bajty

jdm?gld4++hd.<Ptd1eddcz

Nie konkuruje, ponieważ Pyth powstał po opublikowaniu tego wyzwania.

Wypróbuj online

Downgoat
źródło
0

Japt , 32 bajty

m@Xl ¨4?Xg0 +Xs1J ö(x) +XgJ:X}" 

Wypróbuj online!

Bejofo
źródło
Czy mogę uruchomić Japt bezpośrednio w przeglądarce? Bez żadnych zewnętrznych bibliotek, kompilatorów itp.? Jeśli nie, to niestety nie liczy się to zgodnie z regułami nagród (potrzebujesz rozwiązania, które działa w czystej przeglądarce internetowej). Po drugie, jak sądzę, pierwotne zasady dotyczące transpozycji Cambridge były nieco inne niż te przedstawione tutaj (w pytaniu OP). Czy można zmodyfikować kod, aby mieszał słowa o długości 5+ liter (zamiast 4+ liter, jak w pytaniu OP)?
trejder
1
@trejder Wszystkie zgłoszenia muszą być zgodne z zasadami zawartymi w pierwotnym pytaniu. Modyfikowanie go w ten sposób spowoduje, że będzie on nieważny.
user202729,
1
@trejder Japt nie może działać bezpośrednio w przeglądarce bez kompilatora. Po drugie, jeśli zamienisz 4 w kodzie na 5, to powinno mieszać tylko dłuższe słowa o długości 5+.
Bejofo,
0

Java, 1557 834 bajtów Dzięki @JoKing za wskazówki.

Trochę za późno na zawody. Zapomniałem, że zacząłem od tego problemu.

Grał w golfa

import java.util.*;public class s{ public static void main(String[] args){ Scanner s=new Scanner(System.in);String a=s.next();String[] q=a.split("\\s+");for (int i=0;i<q.length;i++) { q[i]=q[i].replaceAll("[^\\w]", ""); }String f="";for (String z:q) { f+=scramble(z);f+=" "; }System.out.print(f); }private static String scramble(String w){if(w.length()==1||w.length()==2){return w;}char[]l=w.toCharArray();char q=l[w.length()-1];String e=Character.toString(l[0]);char[]n=new char[l.length-2];for(int i=0;i<l.length-2;i++){n[i]=l[i+1];}HashMap<Integer,Character>s=new HashMap<>();int c=1;for(char p:n){s.put(c,p);c++;}HashMap<Integer,Integer>o=new HashMap<>();Random z=new Random();for(int i=0;i<w.length()-2;i++){int m=z.nextInt(n.length);while(o.getOrDefault(m,0) == 1){m=z.nextInt(n.length);}e+=s.get(m+1);o.put(m,1);}return e+=q;}}

Nie golfa

import java.util.HashMap;
import java.util.Random;

public class SentenceTransposition {
    public static void main(String[] args) {
        String input = "According to a researcher at Cambridge University, it doesn't matter in what order the letters in a word are, the only important thing is that the first and last letter be at the right place. The rest can be a total mess and you can still read it without problem. This is because the human mind does not read every letter by itself but the word as a whole.";
        String[] words = input.split("\\s+");
        for (int i = 0; i < words.length; i++) {
            words[i] = words[i].replaceAll("[^\\w]", "");
        }
        String finalsentence = "";
        for (String word : words) {
            finalsentence += scramble(word);
            finalsentence += " ";
        }
        System.out.println(finalsentence);
    }

    private static String scramble(String word) {
        if (word.length() == 1 || word.length() == 2) {
            return word;
        }
        char[] letters = word.toCharArray();
        char lletter = letters[word.length()-1];
        String endword = Character.toString(letters[0]);
        char[] nletters = new char[letters.length-2];
        for (int i = 0; i < letters.length-2; i++) {
            nletters[i] = letters[i+1];
        }
        HashMap<Integer, Character> set = new HashMap<>();
        int count = 1;
        for (char nletter : nletters) {
            set.put(count, nletter);
            count++;
        }
        HashMap<Integer, Integer> chosen = new HashMap<>();
        Random random = new Random();
        for (int i = 0; i < word.length()-2; i++) {
            int cur = random.nextInt(nletters.length);
            while (chosen.getOrDefault(cur,0) == 1) {
                cur = random.nextInt(nletters.length);
            }
            endword += set.get(cur+1);
            chosen.put(cur, 1);
        }
        return endword += lletter;
    }
}
Jaden Lee
źródło
Wygląda na to, że można usunąć wiele białych znaków. Czy znasz już porady dotyczące gry w golfa w Javie ? edycja: wydaje się, że wejście jest zakodowane na stałe. Zamiast tego powinieneś brać wkład od użytkownika
Jo King,
@JoKing ah ok. Wezmę wkład od użytkownika.
Jaden Lee,
Udało mi się zagrać w golfa do 650 bajtów, zanim zdałem sobie sprawę, że to nie działa.
Quintec
@Quintec masz na myśli, że mój kod nie działa?
Jaden Lee,
0

Sidef , 89 85 bajtów

Blokowanie (anonimowe wywołanie):

{.words.map{[_[0],(_.len-1?([_[1..^(_.len-1)]].shuffle...,_[1]):'')].join}.join(' ')}

Dane wyjściowe, gdy są używane jak { ... }('..'):

 I hvae nveer not ocne in my life slleepd nhedatarnel crtreolcy
 I have never not once in my lfie sepelld naetadenrhl ccrtloery

Nieco golfa

.words.map{
  [
    .first,
    (_.len-1
      ? (  [ _[1..^(_.len-1)] ].shuffle..., .last )
      : '')
  ].join
}.join(' ')
kot
źródło