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.


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.

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),

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.


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 ....

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.


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.


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.


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%.


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.

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)


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.


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


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."


0

Japt , 32 bajty

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

Wypróbuj online!


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;
    }
}

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(' ')
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.