pwaS eht tirsf dna tasl setterl fo hace dorw


30

Lub „Zamień pierwszą i ostatnią literę każdego słowa”

Twoim wyzwaniem jest, biorąc pod uwagę ciąg znaków alfabetycznych ASCII, a także jeden inny znak, który będzie używany jako separator (do oddzielenia każdego słowa), zamień pierwszą i ostatnią literę każdego słowa. Jeśli istnieje słowo składające się z jednego znaku, zostaw je w spokoju.

Przykłady / przypadki testowe używają małych liter i spacji jako separatora.

Nie musisz obsługiwać interpunkcji; wszystkie dane wejściowe będą składały się wyłącznie z liter od a do z, oddzielonych separatorem, wszystkie w jednolitej wielkości.

Na przykład ciąg „hello world”:

Input string: "hello world"
Identify each word: "[hello] [world]"
Identify the first and last letters of each word: "[[h]ell[o]] [[w]orl[d]]"
Swap the first letters of each word: "[[o]ell[h]] [[d]orl[w]]"
Final string: "oellh dorlw"

UWAGA: separatora nie trzeba wprowadzać osobno. Separator to po prostu znak używany do oddzielania słów. To może być wszystko. Chciałem pozostawić otwarte opcje dla kreatywnych golfistów, więc nie chciałem ograniczać go do samych spacji lub nowych linii. Separator to tylko znak, który oddziela słowa w ciągu wejściowym.

Przypadki testowe:

"swap the first and last letters of each word" -> "pwas eht tirsf dna tasl setterl fo hace dorw"
"hello world" -> "oellh dorlw"
"test cases" -> "test sasec"
"programming puzzles and code golf" -> "grogramminp suzzlep dna eodc folg"
"in a green meadow" -> "ni a nreeg weadom"
"yay racecar" -> "yay racecar"

3
Jak należy traktować interpunkcję? Hello, world!staje się ,elloH !orldw(zamiana interpunkcji na literę) lub oellH, dorlw!(utrzymanie interpunkcji na miejscu)?
Phelype Oleinik

3
@PhelypeOleinik Nie musisz obsługiwać interpunkcji; wszystkie dane wejściowe będą składały się tylko z liter od a do z i wszystkich jednolitych liter.
Towarzysz SparklePony

4
Drugi akapit czyta, jak również jeden inny znak, który ma być używany jako separator, podczas gdy czwarty akapit jest oddzielony spacjami . Który to?
Adám

@ Adám Dowolny znak niealfabetyczny. Przeredaguję, aby wyjaśnić.
Towarzysz SparklePony

1
@BenjaminUrquhart Tak. Możesz również wziąć dane wejściowe jako argument funkcji, jeśli chcesz.
Towarzyszu SparklePony

Odpowiedzi:


59

TeX, 216 bajtów (4 linie, po 54 znaki każda)

Ponieważ nie chodzi o liczbę bajtów, chodzi o jakość wydruku składu :-)

{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}

Wypróbuj online! (Na odwrocie; nie jestem pewien, jak to działa)

Pełny plik testowy:

{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}

\S{swap the a first and last letters of each word}

pwas eht a tirsf dna tasl setterl fo hace dorw

\S{SWAP THE A FIRST AND LAST LETTERS OF EACH WORD}

\bye

Wydajność:

wprowadź opis zdjęcia tutaj


Do LaTeX potrzebujesz tylko płyty grzewczej:

\documentclass{article}
\begin{document}

{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}

\S{swap the a first and last letters of each word}

pwas eht a tirsf dna tasl setterl fo hace dorw

\S{SWAP THE A FIRST AND LAST LETTERS OF EACH WORD}

\end{document}

Wyjaśnienie

TeX to dziwna bestia. Czytanie normalnego kodu i rozumienie go jest wyczynem samym w sobie. Zrozumienie zaciemnionego kodu TeX idzie o kilka kroków dalej. Spróbuję uczynić to zrozumiałym dla osób, które również nie znają TeXa, więc zanim zaczniemy, oto kilka pomysłów na temat TeXa, aby ułatwić śledzenie:

Dla (nie) absolutnych początkujących TeX-ów

  • Pierwszy i najważniejszy element tej listy: kod ma nie być w kształcie prostokąta, choć popkultura może prowadzić cię tak myśleć .

  • TeX to język rozwijania makr. Możesz na przykład zdefiniować, \def\sayhello#1{Hello, #1!}a następnie napisać, \sayhello{Code Golfists}aby TeX wydrukował Hello, Code Golfists!. Nazywa się to „nieelimitowanym makrem” i aby podać mu pierwszy (i tylko w tym przypadku) parametr, umieść go w nawiasach klamrowych. TeX usuwa te nawiasy klamrowe, gdy makro pobiera argument. Możesz użyć do 9 parametrów: \def\say#1#2{#1, #2!}wtedy \say{Good news}{everyone}.

  • Odpowiednikiem undelimited makra są, nic dziwnego, rozdzielany te :) Można zrobić poprzednia definicja odrobinę bardziej semantyczne : \def\say #1 to #2.{#1, #2!}. W takim przypadku po parametrach następuje tak zwany tekst parametru . Taki tekst parametru ogranicza argument makra ( #1jest ograniczony przez ␣to␣spacje i #2jest ograniczony przez .). Po tej definicji możesz napisać \say Good news to everyone., która rozwinie się do Good news, everyone!. Fajnie, prawda? :) Jednak ograniczonym argumentem jest (cytując TeXbooka ) „najkrótszą (być może pustą) sekwencję tokenów z odpowiednio zagnieżdżonymi {...}grupami, po której następuje na wejściu ta konkretna lista tokenów nieparametrycznych”. Oznacza to, że rozszerzenie\say Let's go to the mall to Martinwyda dziwne zdanie. W tym przypadku trzeba by „ukryć” Pierwszy ␣to␣z {...}: \say {Let's go to the mall} to Martin.

  • Jak na razie dobrze. Teraz zaczyna się robić dziwnie. Kiedy TeX odczytuje znak (który jest zdefiniowany przez „kod znaku”), przypisuje temu znakowi „kod kategorii” (catcode, dla znajomych :), który określa, co ten znak będzie oznaczał. Ta kombinacja znaków i kod kategorii sprawia tokena (więcej na ten temat tutaj , na przykład). Te, które są dla nas tutaj interesujące, to w zasadzie:

    • catcode 11 , który definiuje tokeny, które mogą tworzyć sekwencję kontrolną (szykowna nazwa makra). Domyślnie wszystkie litery [a-zA-Z] są kodem kat. 11, więc mogę napisać \hello, że jest to jedna pojedyncza sekwencja kontrolna, podczas \he11ogdy sekwencja kontrolna, \hepo której następują dwa znaki 1, a następnie litera o, ponieważ 1nie jest to kod kat. 11. Jeśli I tak \catcode`1=11, od tego momentu \he11obędzie jedna sekwencja kontrolna. Jedną ważną rzeczą jest to, że kody te są ustawiane, gdy TeX po raz pierwszy widzi postać pod ręką, a taki kod jest zamrożony ... NA ZAWSZE! (mogą obowiązywać warunki)

    • catcode 12 , które są większością innych znaków, takich jak 0"!@*(?,.-+/i tak dalej. Są najmniej specjalnym typem kodu, ponieważ służą tylko do pisania rzeczy na papierze. Ale hej, kto używa TeXa do pisania?!? (ponownie mogą obowiązywać warunki)

    • catcode 13 , co jest piekłem :) Naprawdę. Przestań czytać i zrób coś ze swojego życia. Nie chcesz wiedzieć, co to jest catcode 13. Słyszałeś kiedyś o piątku, 13? Zgadnij, skąd wzięła się jego nazwa! Kontynuuj na własne ryzyko! Znak catcode 13, zwany również „aktywnym” znakiem, nie jest już tylko znakiem, to samo makro! Możesz to zdefiniować, aby mieć parametry i rozwinąć do czegoś takiego, jak widzieliśmy powyżej. Po tym \catcode`e=13, jak myślisz, że możesz \def e{I am the letter e!}, ALE. TY. NIE MOŻE! enie jest już listem, więc \defnie \defwiesz, to jest \d e f! Och, wybierz inny list, który mówisz? W porządku! \catcode`R=13 \def R{I am an ARRR!}. Bardzo dobrze, Jimmy, spróbuj! Odważę się to zrobić i napisać Rw kodzie! To właśnie jest catcode 13. JESTEM SPOKOJNY! Przejdźmy dalej.

  • OK, teraz do grupowania. Jest to dość proste. Jakiekolwiek przypisania ( \defjest to operacja przypisania \let(przejdziemy do niej)) jest inna) wykonywane w grupie, są przywracane do stanu sprzed rozpoczęcia grupy, chyba że przypisanie ma charakter globalny. Istnieje kilka sposobów zakładania grup, jeden z nich zawiera kod 1 i 2 znaki (och, znowu kody). Domyślnie {jest to catcode 1 lub grupa }początkowa , a catcode 2 lub grupa końcowa. Przykład: \def\a{1} \a{\def\a{2} \a} \ato drukuje 1 2 1. Na zewnątrz \abyła grupa 1, potem wewnątrz została na nowo zdefiniowana 2, a kiedy grupa się zakończyła, została przywrócona 1.

  • Ta \letoperacja jest kolejną operacją przypisania \def, ale raczej inną. Z \defty definiować makra, które rozwinie się rzeczy, o \letutworzeniu kopii już istniejących rzeczy. Po \let\blub=\def( =opcja jest opcjonalna) możesz zmienić początek eprzykładu z powyższego elementu catcode 13 na \blub e{...i bawić się z nim. Albo lepiej, zamiast zerwania rzeczy można naprawić (by spojrzeć na to!) Na Rprzykład: \let\newr=R \catcode`R=13 \def R{I am an A\newr\newr\newr!}. Szybkie pytanie: czy możesz zmienić nazwę \newR?

  • Wreszcie tak zwane „przestrzenie fałszywe”. Jest to rodzaj tematu tabu, ponieważ są ludzie, którzy twierdzą, że reputacja zdobyta w TeX - LaTeX Stack Exchange , odpowiadając na pytania „fałszywych spacji”, nie powinna być brana pod uwagę, podczas gdy inni całkowicie się nie zgadzają. Z kim się zgadzasz? Postaw zakłady! Tymczasem: TeX rozumie podział linii jako spację. Spróbuj napisać kilka słów z podziałem linii (nie pustą linią ) między nimi. Teraz dodaj %na końcu tych wierszy. To tak, jakbyś „komentował” te przestrzenie na końcu linii. To jest to :)

(Trochę) odhaczanie kodu

Zróbmy z tego prostokąta coś (prawdopodobnie) łatwiejszego do naśladowania:

{
\let~\catcode
~`A13
\defA#1{~`#113\gdef}
AGG#1{~`#113\global\let}
GFF\else
GHH\fi
AQQ{Q}
AII{\ifxQ}
AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
ADD#1#2#3|{I#2FE{#1}#2#3|H}
ACC#1#2|{D{}#2Q|#1 }
ABBH#1 {HI#1FC#1|BH}
\gdef\S#1{\iftrueBH#1 Q }
}

Objaśnienie każdego kroku

każda linia zawiera jedną instrukcję. Chodźmy jeden po drugim, analizując je:

{
Najpierw zakładamy grupę, aby niektóre zmiany (mianowicie zmiany kodu źródłowego) były lokalne, aby nie zakłócały tekstu wejściowego.

\let~\catcode
Zasadniczo wszystkie kody zaciemniania TeX-a zaczynają się od tej instrukcji. Domyślnie, zarówno w zwykłym TeX-ie, jak i LaTeX-u, ~znak jest jedną aktywną postacią, którą można przekształcić w makro do dalszego wykorzystania. A najlepszym narzędziem do dziwnego kodowania TeXa są zmiany kodu cat, więc ogólnie jest to najlepszy wybór. Teraz zamiast \catcode`A=13możemy napisać ~`A13( =jest opcjonalne):

~`A13
Teraz litera Ajest aktywną postacią i możemy ją zdefiniować, aby coś zrobić:

\defA#1{~`#113\gdef}
Ajest teraz makrem, które przyjmuje jeden argument (który powinien być innym znakiem). Najpierw kotokodu argumentu zostaje zmieniona na 13, aby ją uaktywnić: ~`#113(zastąpienie ~przez \catcodei dodaj =i masz: \catcode`#1=13). Wreszcie pozostawia \gdef(globalny \def) w strumieniu wejściowym. Krótko mówiąc, Aaktywuje inną postać i rozpoczyna jej definicję. Spróbujmy:

AGG#1{~`#113\global\let}
AGpierwsza „aktywuje” Gi robi \gdef, a następnie następna Grozpoczyna definicję. Definicja Gjest bardzo podobna do tej A, z tą różnicą, że zamiast \gdefniej robi \global\let(nie ma takiej \gletjak \gdef). Krótko mówiąc, Gaktywuje postać i sprawia, że ​​staje się czymś innym. Zróbmy skróty do dwóch poleceń, których użyjemy później:

GFF\else
GHH\fi
Teraz zamiast \elsei \fimożemy po prostu użyć Fi H. Znacznie krótszy :)

AQQ{Q}
Teraz używamy Aponownie zdefiniować inny makra Q. Powyższe stwierdzenie w zasadzie ma (w mniej zaciemnionym języku) \def\Q{\Q}. To nie jest strasznie interesująca definicja, ale ma ciekawą funkcję. Jeśli nie chcesz złamać jakiegoś kodu, jedynym makrem, które się rozwija, Qjest Qsamo, więc działa jak unikalny znacznik (nazywa się kwark ). Możesz użyć \ifxwarunkowego do sprawdzenia, czy argumentem makra jest taki kwark z \ifx Q#1:

AII{\ifxQ}
więc możesz być całkiem pewien, że znalazłeś taki znacznik. Zauważ, że w tej definicji usunąłem spację między \ifxi Q. Zwykle prowadziłoby to do błędu (zwróć uwagę, że podświetlanie składni uważa, że \ifxQto jedno), ale ponieważ teraz Qjest catcode 13, nie może utworzyć sekwencji kontrolnej. Uważaj jednak, aby nie rozwinąć tego kwarka, w przeciwnym razie utkniesz w nieskończonej pętli, ponieważ Qrozwija się do Qktórego rozwija się do Qktórego ...

Po zakończeniu wstępnych przygotowań możemy przejść do właściwego algorytmu pwas eht setterl. Z powodu tokenizacji TeX-a algorytm musi być zapisany wstecz. Wynika to z tego, że w momencie tworzenia definicji TeX będzie tokenizował (przypisywał kody) do znaków w definicji przy użyciu bieżących ustawień, na przykład, jeśli:

\def\one{E}
\catcode`E=13\def E{1}
\one E

dane wyjściowe są E1, natomiast jeśli zmienię kolejność definicji:

\catcode`E=13\def E{1}
\def\one{E}
\one E

wyjście jest 11. Jest tak, ponieważ w pierwszym przykładzie Edefinicja była tokenizowana jako litera (kod 11) przed zmianą kodu, więc zawsze będzie to litera E. W drugim przykładzie Ezostał jednak najpierw uaktywniony, a dopiero potem \onezostał zdefiniowany, a teraz definicja zawiera kod kat. 13, Ektóry rozwija się 1.

Przeoczę jednak ten fakt i zmienię kolejność definicji, aby uzyskać logiczną (ale nie działającą) kolejność. W poniższych akapitach można założyć, że litery B, C, D, i Esą aktywne.

\gdef\S#1{\iftrueBH#1 Q }
(zauważ, że w poprzedniej wersji był mały błąd, nie zawierał on końcowego miejsca w powyższej definicji. Zauważyłem to tylko podczas pisania tego. Czytaj dalej, a zobaczysz, dlaczego potrzebujemy tego, aby poprawnie zakończyć makro. )
Najpierw musimy zdefiniować makro poziomie użytkownika \S. Ten nie powinien być aktywną postacią, aby mieć przyjazną (?) Składnię, więc makro dla gwappins eht setterl to \S. Makro zaczyna się od zawsze prawdziwego warunku \iftrue(wkrótce będzie jasne, dlaczego), a następnie wywołuje Bmakro, po Hktórym następuje (które wcześniej zdefiniowaliśmy \fi) w celu dopasowania do \iftrue. Następnie pozostawiamy argument makra, #1po którym następuje spacja i kwark Q. Załóżmy, że używamy \S{hello world}, a następnie strumienia wejściowegopowinien wyglądać tak: \iftrue BHhello world Q␣(ostatnie miejsce zastąpiłem tak, aby renderowanie strony go nie zjadło, tak jak w poprzedniej wersji kodu). \iftruejest prawdą, więc się rozszerza i zostajemy z tym BHhello world Q␣. TeX czy nie usunąć \fi( H) po warunkowe ocenia się, zamiast tego pozostawia go tam, dopóki \fijest faktycznie rozszerzony. Teraz Bmakro jest rozwinięte:

ABBH#1 {HI#1FC#1|BH}
Bjest ograniczonym makrem, którego tekstem parametru jest H#1␣, więc argumentem jest cokolwiek pomiędzy Hspacją. Kontynuując przykład powyżej strumienia wejściowego przed rozszerzeniem Bjest BHhello world Q␣. Bpo nim następuje H, tak jak powinien (w przeciwnym razie TeX spowodowałby błąd), następnie następna spacja znajduje się pomiędzy helloi world, podobnie #1jak słowo hello. I tutaj musimy podzielić tekst wejściowy na spacje. Yay: D Ekspansja Busuwa wszystko aż do pierwszego miejsca ze strumienia wejściowego i zastępuje przez HI#1FC#1|BHz #1bycia hello: HIhelloFChello|BHworld Q␣. Zauważ, że BHw strumieniu wejściowym pojawiło się nowe , aby wykonać rekursję ogonaBi przetwarzaj późniejsze słowa. Po przetworzeniu tego słowa przetwarza Bnastępne słowo, dopóki słowem do przetworzenia nie będzie kwark Q. QPotrzebna jest ostatnia spacja po , ponieważ rozdzielane makro B wymaga jednego na końcu argumentu. W poprzedniej wersji (patrz historia edycji) kod byłby źle zachowany, gdyby go używałeś \S{hello world}abc abc(odstęp między abcliterami zniknąłby).

OK, z powrotem do strumienia wejściowego: HIhelloFChello|BHworld Q␣. Najpierw jest H( \fi), który kończy inicjał \iftrue. Teraz mamy to (pseudokodowane):

I
  hello
F
  Chello|B
H
world Q␣

I...F...HZdaniem jest rzeczywiście \ifx Q...\else...\fistruktura. Na \ifxtest sprawdza, czy (pierwszy znak w słowie) chwycił jest Qtwaróg. Jeśli to nie ma nic innego do roboty, a kończy wykonanie, w przeciwnym razie, co pozostaje, to: Chello|BHworld Q␣. Teraz Cjest rozwinięty:

ACC#1#2|{D#2Q|#1 }
Pierwszy argument Cjest undelimited, więc jeśli usztywnione będzie pojedynczy element drugi argument jest ograniczona |, więc po rozszerzeniu C(z #1=ha #2=ello) strumień wejściowy: DelloQ|h BHworld Q␣. Zauważ, że inny |jest tam umieścić, a hod hellokładzie się po tym. Połowa zamiany jest zakończona; pierwsza litera jest na końcu. W TeX łatwo jest zdobyć pierwszy token z listy tokenów. Proste makro \def\first#1#2|{#1}otrzymuje pierwszą literę, gdy używasz \first hello|. Ten ostatni stanowi problem, ponieważ TeX zawsze pobiera jako argument argument „najmniejszą, być może pustą” listę tokenów, dlatego potrzebujemy kilku obejść. Kolejnym elementem na liście tokenów jest D:

ADD#1#2|{I#1FE{}#1#2|H}
To Dmakro jest jednym z obejść i jest przydatne w jedynym przypadku, gdy słowo ma jedną literę. Załóżmy, że zamiast tego hellomieliśmy x. W takim przypadku strumień wejściowy byłby DQ|xwtedyD rozszerzy (z #1=Qi #2opróżniania) i: IQFE{}Q|Hx. Jest to podobne do bloku I...F...H( \ifx Q...\else...\fi) w B, który zobaczy, że argumentem jest kwark i przerwie wykonywanie pozostawiając tylko xdo składu. W innych przypadkach (powracających na helloprzykład), Dby poszerzyć (z #1=ea #2=lloQ) na adres: IeFE{}elloQ|Hh BHworld Q␣. Ponownie, I...F...Hbędzie sprawdzał Q, ale nie powiedzie się i podjąć \elseoddział: E{}elloQ|Hh BHworld Q␣. Teraz ostatni kawałek tej rzeczy,E makro rozwinąłoby się:

AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
Tekst parametru tutaj jest dość podobny do Ci D; pierwszy i drugi argument są nieograniczone, a ostatni jest ograniczony przez |. Wygląda jak ten strumień wejściowy: E{}elloQ|Hh BHworld Q␣, a następnie Erozszerza się (z #1pusta #2=e, i #3=lloQ): IlloQeFE{e}lloQ|HHh BHworld Q␣. Kolejny I...F...Hblok sprawdza kwark (który widzi li zwraca false):E{e}lloQ|HHh BHworld Q␣ . Teraz Eponownie się rozszerza (z #1=epuste, #2=li #3=loQ) IloQleFE{el}loQ|HHHh BHworld Q␣. I znowu I...F...H. Makro wykonuje jeszcze kilka iteracji, aż w Qkońcu zostanie znalezione i truebrana jest gałąź: E{el}loQ|HHHh BHworld Q␣-> IoQlelFE{ell}oQ|HHHHh BHworld Q␣-> E{ell}oQ|HHHHh BHworld Q␣-> IQoellFE{ello}Q|HHHHHh BHworld Q␣. Teraz kwark został odnaleziony i warunkowe rozszerza się do: oellHHHHh BHworld Q␣. Uff

Och, czekaj, co to jest? NORMALNE LITERY? O chłopie! Litery są w końcu znaleźć i TeX spisuje oell, to banda H( \fi) znajdują i rozszerzony (do zera), pozostawiając strumień wejściowy z: oellh BHworld Q␣. Teraz pierwsze słowo zamienia pierwszą i ostatnią literę, a TeX znajduje następne, Baby powtórzyć cały proces dla następnego słowa.

}
W końcu kończymy grupę, która zaczęła się tam ponownie, aby wszystkie zadania lokalne zostały cofnięte. Lokalne zadania są zmiany kotokodu liter A, B, C, ..., które zostały wykonane makra tak, że wracają do normalnego literę znaczenia i może być bezpiecznie stosowany w tekście. I to wszystko. Teraz \Szdefiniowane tam makro uruchomi przetwarzanie tekstu jak wyżej.

Jedną interesującą rzeczą w tym kodzie jest to, że można go w pełni rozbudowywać. Oznacza to, że możesz bezpiecznie używać go do przenoszenia argumentów bez obawy, że wybuchnie. Możesz nawet użyć kodu, aby sprawdzić, czy ostatnia litera słowa jest taka sama jak druga (z dowolnego powodu, którego byś potrzebował) w \ifteście:

\if\S{here} true\else false\fi % prints true (plus junk, which you would need to handle)
\if\S{test} true\else false\fi % prints false

Przepraszam za (prawdopodobnie zdecydowanie zbyt) mylące wyjaśnienie. Starałem się, aby było to tak jasne, jak to możliwe, również dla TeXies :)

Podsumowanie dla niecierpliwych

Makro \Suzupełnia dane wejściowe aktywną postacią, Bktóra chwyta listy tokenów rozdzielonych spacją i przekazuje je do C. Cbierze pierwszy token z tej listy i przenosi go na koniec listy tokenów i rozwija Dwraz z resztą. Dsprawdza, czy „to, co pozostaje” jest puste, w którym to przypadku znaleziono jedno literowe słowo, a następnie nic nie rób; w przeciwnym razie rozszerza się E. Ezapętla listę tokenów, aż znajdzie ostatnią literę w słowie, po znalezieniu pozostawia ostatnią literę, a następnie środek słowa, a następnie pierwszą literę pozostawioną na końcu strumienia tokenu przez C.


2
Chciałbym uzyskać pełne wyjaśnienie tego. Jestem bardzo ciekawy, jak to działa!
LambdaBeta

1
@LambdaBeta Mogę to zrobić, ale nie teraz. Poczekaj, a kiedy to zrobię,
wyślemy

1
@LambdaBeta Gotowe! Przepraszam, czasami jestem zbyt
pracowity

13

JavaScript (ES6),  39  36 bajtów

Zaoszczędź 3 bajty dzięki @FryAmTheEggman

Używa kanału jako separatora.

s=>s.replace(/(.)(.*)(.)/g,'$3$2$1')

Wypróbuj online!


5
(.)(.*)(.)czy to jest emotikon Total Recall?
MikeTheLiar

1
@MikeTheLiar Rodzaj, tak myślę. : D
Arnauld

Przypisanie określa, że ​​ciąg zawiera separator.
Cees Timmerman

@CeesTimmerman Nie jestem pewien, co masz na myśli. Ten kod oczekuje, że separator jest podawany jako linia, a zatem pobiera ciągi znaków z liniowymi danymi wejściowymi. (Stopka łącza TIO przekształca spacje w linie, a następnie z powrotem w spacje dla czytelności.)
Arnauld

„biorąc pod uwagę ciąg znaków alfabetycznych ASCII, a także jeden inny znak, który ma być używany jako separator (do oddzielenia każdego słowa) ” - Nm, myślałem, że to osobny parametr.
Cees Timmerman

11

Siatkówka ,8 5 bajtów

,V,,`

Wypróbuj online!

Zaoszczędzono 3 bajty dzięki Kevin Cruijssen !

Używa nowej linii jako separatora. Korzystamy z odwrotnego etapu Retiny i niektórych ograniczeń. Pierwszym limitem jest to, do którego dopasowania zostanie zastosowane odwrócenie, więc wybieramy je wszystkie ,. Następnie chcemy, aby pierwsza i ostatnia litera każdego dopasowania została zamieniona, więc bierzemy każdą literę z zakresu, ,,który przekłada się na zakres od początku do końca z krokiem wielkości zero.


Cholera, właśnie przeszukiwałem dokumenty w poszukiwaniu czegoś takiego, aby zaktualizować moją odpowiedź, ale pobiłaś mnie. Wiedziałem o tym V, ale nie wiedziałem, że można go używać z 1,-2takimi wskaźnikami . Niezłe!
Kevin Cruijssen

1
@KevinCruijssen Oszukałem trochę i sprawdziłem, jak działają zakresy graniczne, gdy był w piaskownicy :) Nadal uważam, że powinien istnieć lepszy sposób niż odwrócenie zakresu, ale nie znalazłem nic krótszego.
FryAmTheEggman

2
Rzeczywiście masz rację, że może być krótszy bez limitu zakresu, ponieważ wydaje się, że ten 5-bajtowy działa (podany jako przykład na dole Step Limits w dokumentacji).
Kevin Cruijssen

@KevinCruijssen Nice! Nie mogę uwierzyć, że to przegapiłem.
FryAmTheEggman

3
5 bajtów i tylko 3 różne znaki? To minimalistyczne.
Cœur

9

Pepe , 107 105 bajtów

REEeREeeEeeeeerEEreREEEeREEEEEEeREEEErEEREEEEEEEreererEEEeererEEEerEEeERrEEEeerEEeerereeerEEEEeEEEReEeree

Wypróbuj online!

Wyjaśnienie:

Notacja na komentarzach: command-explanation -> (stack) // explanation

REEe # input -> (R)
REeeEeeeee # push space to last -> (R) // this prevents an infinite loop

rEE # create loop labeled 0 and automatically push 0 
  re # pop 0 -> (r)
  REEEe # go to last item -> (R)
  REEEEEEe # ...then copy the char to other stack
  REEEE # go to first item -> (R)

  rEE # create loop labeled 32 // detect space
    REEEEEEE # move item to other stack (R)
  ree # do this while char != 32

  re # pop 32 -> (r)
  rEEEee # push item (dup to end) -> (r)
  re # ...then pop -> (r)
  rEEEe rEEeE # go to 2nd to last item -> (r)
  RrEEEee # push the item (R flag: dup to first) -> (r)
  rEEee # go to next -> (r) //
  re # ...then pop -> (r)
  reee rEEEEeEEE # out all as char then clear -> (r)
  ReEe # out 32 as char -> (R)
ree # do this while stack != 0

Jak to działa?
lirtosiast

Dodano wyjaśnienie @lirtosiast
zdefiniowano


6

laskelH , 71 bajtów

h=reverse
s(x:y:o)=a:h(x:r)where(a:r)=h$y:o
s o=o
f=unwords.map s.words

Wypróbuj online!

Przykład wejścia / wyjścia:

Swap the first and last letter in each word
This also works with single letter words like a

It is basically just a straight up implementation in which
I for words consisting of two or more letters cons the head
of the reversed tail on the reverse of the original head consed
on the reversed tail

Note that the rules say that we only have to support one kind
of separator - I am choosing spaces Technically it works with
other whitespace as well, but it will turn everything into spaces
in the end Line endings in this example usage are handled separately
to make the example output look nicer
pwaS eht tirsf dna tasl rettel ni hace dorw
shiT olsa sorkw hitw eingls rettel sordw eikl a

tI si yasicallb tusj a ttraighs pu nmplementatioi ni hhicw
I rof sordw gonsistinc fo owt ro eorm setterl sonc eht deah
fo eht deverser lait no eht eeversr fo eht lriginao deah donsec
no eht deverser lait

eotN that eht suler yas that ew ynlo eavh ot tuppors eno dink
fo reparatos - I ma ghoosinc spaces yechnicallT ti sorkw hitw
rtheo ehitespacw sa ,ellw tub ti lilw nurt gverythine onti spaces
ni eht dne einL sndinge ni shit example esagu era dandleh yeparatels
ot eakm eht example tutpuo kool ricen
```

1
Przypisanie w whereklauzuli można przenieść do wiązania na straży, aby zaoszczędzić 5 bajtów: Wypróbuj online!
Laikoni

1
Widzę, co tam zrobiłeś z nazwą „Haskell” w tytule. Zrobiłem to samo w odpowiedzi na PHP.
640 KB

5

05AB1E , 10 bajtów

#vyRćsRćðJ

Wypróbuj online!


-3 Dzięki @Kevin Cruijssen .

#           | Split into words.
 vy         | For each word...
   RćsRć    | Reverse, split head, swap, reverse, split tail
        ðJ  | Join by spaces.


1
@KevinCruijssen Szczerze chcę go usunąć i dać ci, to było 99% twojej siły mózgowej na uporządkowanie argumentów haha.
Magic Octopus Urn

1
Znaleziono 9 bajtów, ale działa tylko w starszej wersji:|ʒRćsRćJ,
Kevin Cruijssen

1
Szkoda, że ​​nie mamy loop_as_long_as_there_are_inputs, wtedy wiedziałbym, że 8-bajtowy: [RćsRćJ,Ten 8-bajtowy używa[ nigdy wyjść w teorii, tylko wtedy, gdy brakuje Ci pamięci lub masz czas, jak na TIO (i wymaga to końca nowa linia w danych wejściowych, w przeciwnym razie będzie używać ostatniego słowa) ..
Kevin Cruijssen

1
Niestety potrzebujesz ð¡tylko jednego słowa, aleð¡εćsÁì}ðý działa również z 10 bajtami.
Emigna

5

J , 23 17 bajtów

({:,1|.}:)&.>&.;:

Wypróbuj online!


Bardzo fajna sztuczka, aby zamienić pierwsze / ostatnie litery, obracając i aplikując 1 A.!
Galen Iwanow

1
1&A.&.(1&|.)->, ({:,1|.}:)a następnie możesz usunąć::]
ngn

Niesamowite, dziękuję
FrownyFrog

Naprawdę niesamowite! Po raz kolejny jestem zdumiony, jak proste i eleganckie może być to rozwiązanie, ale dopiero wtedy, gdy widzę, że zrobiło to ktoś inny.
Galen Iwanow

4

Rubin z -p, 42 41 29 bajtów

gsub /(\w)(\w*)(\w)/,'\3\2\1'

Wypróbuj online!



@ Shaggy dzięki za heads up. Jeśli spojrzysz na moją historię postów, pokazuje, że nie było mnie przez 8 miesięcy bez odpowiedzi, więc prawdopodobnie przegapiłem kilka notatek w tym czasie, haha
Value Ink

Jestem pewien, że konsensus został zmieniony ponad 8 miesięcy temu, ale na wypadek, gdybyś go przegapił: „niekonkurowanie” też nie jest już czymś.
Kudłaty

Ładnie wykonane. Myślę, że zgodnie z zasadami możesz używać znaku nowej linii jako ogranicznika i zastępować \ws literą .s.
histocrat





3

Biała spacja , 179 bajtów

[N
S S S N
_Create_Label_OUTER_LOOP][S S S N
_Push_n=0][N
S S T   N
_Create_Label_INNER_LOOP][S N
S _Duplicate_n][S N
S _Duplicate_n][S N
S _Duplicate_n][T   N
T   S _Read_STDIN_as_character][T   T   T   _Retrieve_input][S S S T    S T T   N
_Push_11][T S S T   _Subtract_t=input-11][N
T   T   S S N
_If_t<0_jump_to_Label_PRINT][S S S T    N
_Push_1][T  S S S _Add_n=n+1][N
S N
T   N
_Jump_to_Label_INNER_LOOP][N
S S S S N
_Create_Label_PRINT][S S S T    N
_Push_1][T  S S T   _Subtract_n=n-1][S N
S _Duplicate_n][S N
S _Duplicate_n][N
T   S N
_If_n==0_jump_to_Label_PRINT_TRAILING][T    T   T   _Retrieve][T    N
S S _Print_as_character][S S S N
_Push_s=0][N
S S S T N
_Create_Label_PRINT_LOOP][S S S T   N
_Push_1][T  S S S _Add_s=s+1][S N
S _Duplicate_s][S T S S T   S N
_Copy_0-based_2nd_n][T  S S T   _Subtract_i=s-n][N
T   S N
_If_0_Jump_to_Label_PRINT_TRAILING][S N
S _Duplicate_s][T   T   T   _Retrieve][T    N
S S _Print_as_character][N
S T S T N
_Jump_to_Label_PRINT_LOOP][N
S S N
_Create_Label_PRINT_TRAILING][S S S N
_Push_0][T  T   T   _Retrieve][T    N
S S _Print_as_character][S S S T    S S T   N
_Push_9_tab][T  N
S S _Print_as_character][N
S N
S N
_Jump_to_Label_OUTER_LOOP]

Litery S(spacja), T(tab) i N(nowa linia) dodane tylko jako wyróżnienia.
[..._some_action]dodano tylko jako wyjaśnienie.

Tab jako separator. Dane wejściowe powinny zawierać końcowy znak nowej linii (lub tabulatora), w przeciwnym razie program nie będzie wiedział, kiedy zatrzymać, ponieważ wprowadzanie danych w spacji może być wykonywane tylko jeden znak na raz.

Wypróbuj online (tylko z surowymi spacjami, tabulatorami i nowymi wierszami).

Objaśnienie w pseudo-kodzie:

[0,...,długość słowa]

Start OUTER_LOOP:
  Integer n = 0
  Start INNER_LOOP:
    Character c = STDIN as character, saved at heap-address n
    If(c == '\t' OR c == '\n'):
      Jump to PRINT
    n = n + 1
    Go to next iteration of INNER_LOOP

  PRINT:
    n = n - 1
    If(n == 0): (this means it was a single-letter word)
      Jump to PRINT_TRAILING
    Character c = get character from heap-address n
    Print c as character
    Integer s = 0

    Start PRINT_LOOP:
      s = s + 1
      If(s - n == 0):
        Jump to PRINT_TRAILING
      Character c = get character from heap-address s
      Print c as character
      Go to next iteration of PRINT_LOOP

    PRINT_TRAILING:
      Character c = get character from heap-address 0
      Print c as character
      Print '\t'
      Go to next iteration of OUTER_LOOP

Program kończy się z błędem, gdy próbuje odczytać znak, gdy żaden nie jest podany w TIO (lub zawiesza się, czekając na dane wejściowe w niektórych kompilatorach Whitespace, takich jak vii5ard ).


3

Wolfram Language (Mathematica) , 58 bajtów

StringReplace[#,a:u~~w:u..~~b:u:>b<>w<>a/.{u->Except@#2}]&

Wypróbuj online!

-22 bajty od @attinat

-12 bajtów od @ M.Stern


70 bajtów za pomocą StringReplacez StringExpressionS
attinat

1
64 bajty StringTakezamiast StringReplace:StringRiffle[StringSplit@##~StringTake~{{-1},{2,-2},{1}},#2,""]&
Roman

2
Oto bardziej bezpośrednie podejście:StringReplace[#, a : u ~~ w : u .. ~~ b : u :> b <> w <> a /. {u -> Except@#2}] &
M. Stern

1
{i} są opcjonalne :)
M. Stern

1
55 bajtów , także poprawia 2-znakowe słowa
attinat

2

QuadR , 20 bajtów

(\w)(\w*)(\w)
\3\2\1

Po prostu utwórz trzy grupy przechwytywania składające się z 1, 0 lub więcej i 1 znaków słów, a następnie odwróci ich kolejność.

Wypróbuj online!



2

Japt -S , 10 bajtów

Przekonany, że musi być krótsze podejście (i miałem rację ), ale na razie to wystarczy .

¸ËhJDg)hDÌ

Spróbuj

¸ËhJDg)hDÌ     :Implicit input of string
¸              :Split on spaces
 Ë             :Map each D
  h            :  Set the character at
   J           :    Index -1 to
    Dg         :    The first character in D
      )        :  End set
       h       :  Set the first character to
        DÌ     :    The last character in D
               :Implicit output, joined by spaces

Znacznie krótszy niż mój 12 bajt:¸®Ì+Zs1J +Zg
of Ignorance

@EmbodimentofIgnorance, tam też zacząłem, ale nie udałoby się to w przypadku pojedynczych znaków. Możesz jednak zaoszczędzić na tym bajt za pomocą ¸®ÎiZÌ+Zs1J.
Kudłaty

1
@EmbodimentofIgnorance Znaleziono 7 bajtów
Oliver

2

sed, 64 bajty

sed -E 's/\b([[:alpha:]])([[:alpha:]]*)([[:alpha:]])\b/\3\2\1/g'

Jasne, moglibyśmy użyć .zamiast [[:alpha:]], ale tak naprawdę musiałoby być [^ ], co zmniejsza go do 43, ale psuje interpunkcję i tak dalej. Używanie [a-zA-Z]zwiększa go do 55, w którym momencie po prostu tęsknię za tymi słodkimi, słodkimi, czytelnymi dla człowieka istotami ...
Rich

2
You do not need to handle punctuation; all of the inputs will only consist of the letters a through z, separated by a delimiter, all of a uniform case.Innymi słowy, nie musisz martwić się o to, że interpunkcja „zepsuje” Twój kod i możesz po prostu bezpiecznie iść [^ ];)
Value Ink

@ValueInk Tak, ale wtedy [^ ]powinno być, [^[:space:]]co prowadzi do 67 znaków.
Bogaty

„separator” oznacza, że ​​możesz upewnić się, że separator jest zawsze regularną spacją. Kto i tak używa kart w zdaniu?
Wartość tuszu

W porządku. Wygląda na to, że „code golf” to gra, w której chcesz znaleźć sposób, aby dron rzucił piłkę do dołka zamiast faktycznie wykonywać pracę. Dzięki za gówniane powitanie.
Bogaty

2

sed , 34 bajty

I prawdopodobnie koncepcja wzorca będzie działać z większością narzędzi RE (i wiem, że istnieją różnice między standardową RE a rozszerzoną RE).

s,\b\(\w\)\(\w*\)\(\w\)\b,\3\2\1,g

Wypróbuj online!


1
Witamy w PPCG! Uważa, że ​​chciwość dopasowań wyrażeń regularnych oznacza, że ​​możesz odciąć się \bod dopasowania: Wypróbuj online!
Wartość tuszu

Zgoda @ValueInk - ale byłem dokładny w meczu. Usunięcie \bprowadzi do 30 bajtów.
PJF

Użyj -E dla zaawansowanego wyrażenia regularnego i możesz użyć nieskalowanych nawiasów. Użyj .do zamiany znaków, a możesz stracić kolejne dwa znaki. To sprowadza twoje do 26 bajtów; jedno z najmniejszych czytelnych rozwiązań. s,\b(.)(\w*)(.)\b,\3\2\1,g
Bogaty

1
- nie, mylę się, potrzebujesz \ws na końcach. s,\b(\w)(\w*)(\w)\b,\3\2\1,g28 znaków.
Bogaty

Dobra robota @rich, ale jak powiedziałem, wiem o standardowym i rozszerzonym RE. Po prostu wybrałem, aby był standardowy i czytelny. Wymagane będą kotwice, których nie wspomniałem w swojej odpowiedzi na ValueInk.
PJF

2

Rubin, 53 bajty

gets.split(" ").map{|z|print z[-1]+z[1..-2]+z[0]," "}

Próbowałem bez wyrażenia regularnego. Wyjście wypisuje każde słowo w nowym wierszu. Jeśli jest to niezgodne z zasadami, daj mi znać, a ja to naprawię.

Nie golfowany:

gets.split(" ").map {|z|
    print z[-1] + z[1..-2] + z[0], " "
}

Witamy w PPCG! Drukowanie każdego słowa w nowym wierszu powinno być w porządku, ale twoje stare rozwiązanie pnie było dobre, ponieważ dodawało to cudzysłowy do wyniku. Zawsze możesz użyć putszamiast tego, ponieważ ten automatycznie dołącza nowy wiersz i jest krótszy niż print! Ponadto, jeśli wywołujesz splitbez argumentów, automatycznie dzieli się na spacje.
Wartość tuszu

2

8088 Montaż, IBM PC DOS, 39 38 bajtów

$ xxd pwas.com
00000000: d1ee ac8a c8fd 03f1 c604 244e 8bfe ac3c  ..........$N...<
00000010: 2075 098a 2586 6402 8825 8bfe e2f0 b409   u..%.d..%......
00000020: ba82 00cd 21c3

Niezmontowane:

D1 EE       SHR  SI, 1          ; point SI to DOS PSP (080H) 
AC          LODSB               ; load string length into AL 
8A C8       MOV  CL, AL         ; load string length into CX for loop
FD          STD                 ; set LODSB to decrement 
03 F1       ADD  SI, CX         ; point SI to end of string 
C6 04 24    MOV  BYTE PTR[SI], '$' ; put a '$' DOS string terminator at end 
4E          DEC  SI             ; start at last char of word 
8B FE       MOV  DI, SI         ; point DI to last char of word 
        CHR_LOOP: 
AC          LODSB               ; load next (previous?) char into AL 
3C 20       CMP  AL, ' '        ; is it a space? 
75 0A       JNE  END_CHR        ; if so, continue loop 
8A 25       MOV  AH, [DI]       ; put last char in AH 
86 64 02    XCHG AH, [SI][2]    ; swap memory contents of first char with last 
                                ; (unfortunately XCHG cannot swap mem to mem)
88 25       MOV  [DI], AH       ; put first char value into last char position 
8B FE       MOV  DI, SI         ; point DI last char of word 
        END_CHR:
E2 EF       LOOP CHR_LOOP       ; continue loop 
B4 09       MOV  AH, 9          ; DOS display string function 
BA 0082     MOV  DX, 082H       ; output string is at memory address 82H 
CD 21       INT  21H            ; display string to screen 
C3          RET                 ; return to DOS 

Samodzielny plik wykonywalny DOS dla komputera PC. Wejście za pomocą argumentów wiersza poleceń, wyjście na ekran.

wprowadź opis zdjęcia tutaj

Pobierz i przetestuj PWAS.COM .



1

Partia, 141 bajtów

@set t=
@for %%w in (%*)do @call:c %%w
@echo%t%
@exit/b
:c
@set s=%1
@if not %s%==%s:~,1% set s=%s:~-1%%s:~1,-1%%s:~,1%
@set t=%t% %s%

Pobiera dane wejściowe jako parametry wiersza polecenia. Manipulowanie ciągami jest w najlepszym wypadku tragiczne w Batch, a konieczność stosowania pojedynczych liter w szczególnych przypadkach nie pomaga.




1

Java, 110 109 bajtów

-1 bajtów przy użyciu nowego wiersza dla ogranicznika

s->{int l;for(var i:s.split("\n"))System.out.println(i.charAt(l=i.length()-1)+i.substring(1,l)+i.charAt(0));}

TIO


Czy to działa na słowa jednoliterowe?
Neil

@Neil nie, bo jestem zły. Naprawię później.
Benjamin Urquhart

109 , używając znaku nowej linii jako separatora
Embodiment of Ignorance

1

Haskell , 75 74 bajtów

Naprawiono błąd wskazywany przez Cubic, a także zmniejszany o 1 bajt.

f=unwords.map(#v).words
x#g=g(r$tail x)++[x!!0]
r=reverse
v[]=[]
v x=r$x#r

Wypróbuj online!


map gjest krótszy niż(g<$>)
Cubic

1
Ponadto, jeśli spojrzysz na swoją skrzynkę testową, zobaczysz, że nie działa ona na słowa z jedną literą, zamienia się awaa
Cubic

1

Scala, 100 bajtów

(b:String,c:String)=>b.split(c)map(f=>f.tail.lastOption++:(f.drop(1).dropRight(1)+f.head))mkString c

1

T-SQL, 126 bajtów

SELECT STRING_AGG(STUFF(STUFF(value,1,1,RIGHT(value,1)),LEN(value),1,LEFT(value,1)),' ')
FROM STRING_SPLIT((SELECT*FROM t),' ')

Dane wejściowe pochodzą z wcześniej istniejącej tabeli t z polem varchar v , zgodnie z naszymi standardami IO .

Czytanie od tyłu do przodu, STRING_SPLITdzieli ciąg na pojedyncze rzędy za pomocą separatora, STUFFmodyfikuje znaki w określonych pozycjach, a następnie STRING_AGGponownie je łączy.

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.