pwaS eht tirsf dna tasl setterl fo hace dorw

30

Ou, "Échangez les première et dernière lettres de chaque mot"

Votre défi consiste à, étant donné une chaîne de caractères alphabétiques ASCII ainsi qu'un autre caractère à utiliser comme délimiteur (pour séparer chaque mot), permuter les première et dernière lettres de chaque mot. S'il y a un mot à un caractère, laissez-le tranquille.

Les exemples / testcases utilisent les lettres minuscules et l'espace comme délimiteur.

Vous n'avez pas besoin de gérer la ponctuation; toutes les entrées seront uniquement constituées des lettres a à z, séparées par un délimiteur, toutes dans un cas uniforme.

Par exemple, avec la chaîne "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"

REMARQUE: le délimiteur n'a pas besoin d'être entré séparément. Le délimiteur est juste le caractère utilisé pour séparer les mots. Ça peut être n'importe quoi. Je voulais laisser les options ouvertes aux golfeurs créatifs, donc je ne voulais pas la limiter aux seuls espaces ou aux nouvelles lignes. Le délimiteur est juste un caractère qui sépare les mots dans la chaîne d'entrée.

Cas de test:

"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"
Camarade SparklePony
la source
3
Comment traiter la ponctuation? Hello, world!devient ,elloH !orldw(permutation de la ponctuation en lettre) ou oellH, dorlw!(maintien de la ponctuation en place)?
Phelype Oleinik
3
@PhelypeOleinik Vous n'avez pas besoin de gérer la ponctuation; toutes les entrées ne seront constituées que des lettres a à z et toutes d'un cas uniforme.
Camarade SparklePony
4
Le deuxième paragraphe lit ainsi qu'un autre caractère à utiliser comme délimiteur tandis que le quatrième lit séparé par des espaces . Laquelle est-ce?
Adám
@ Adám N'importe quel caractère non alphabétique. Je vais modifier pour clarifier.
Camarade SparklePony
1
@BenjaminUrquhart Oui. Vous pouvez également prendre l'entrée comme argument de fonction si vous le souhaitez.
Camarade SparklePony

Réponses:

59

TeX, 216 octets (4 lignes, 54 caractères chacune)

Parce qu'il ne s'agit pas du nombre d'octets, il s'agit de la qualité de la sortie de composition :-)

{\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 }}

Essayez-le en ligne! (Au verso; je ne sais pas comment cela fonctionne)

Fichier de test complet:

{\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

Sortie:

entrez la description de l'image ici


Pour LaTeX, vous avez juste besoin du passe-partout:

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

Explication

TeX est une étrange bête. Lire du code normal et le comprendre est un exploit en soi. La compréhension du code TeX obscurci va plus loin. Je vais essayer de rendre cela compréhensible pour les personnes qui ne connaissent pas aussi TeX, donc avant de commencer, voici quelques concepts sur TeX pour rendre les choses plus faciles à suivre:

Pour (pas tellement) les débutants absolus de TeX

  • Tout d' abord, et élément le plus important dans cette liste: le code ne pas avoir à être en forme rectangulaire, même si la culture pop pourrait vous amener à penser .

  • TeX est un langage d'expansion de macro. Vous pouvez, par exemple, définir \def\sayhello#1{Hello, #1!}puis écrire \sayhello{Code Golfists}pour que TeX s'imprime Hello, Code Golfists!. C'est ce qu'on appelle une «macro non délimitée», et pour lui donner le premier (et seulement, dans ce cas) paramètre, vous la mettez entre accolades. TeX supprime ces accolades lorsque la macro prend l'argument. Vous pouvez utiliser jusqu'à 9 paramètres: \def\say#1#2{#1, #2!}alors \say{Good news}{everyone}.

  • La contrepartie de macros sont non délimitées, sans surprise, les délimité :) Vous pouvez faire la définition précédente un peu plus sémantiquement : \def\say #1 to #2.{#1, #2!}. Dans ce cas, les paramètres sont suivis d'un texte dit de paramètres . Un tel texte de paramètre délimite l'argument de la macro ( #1est délimité par ␣to␣, espaces inclus et #2est délimité par .). Après cette définition, vous pouvez écrire \say Good news to everyone., qui se développera Good news, everyone!. Sympa, non? :) Cependant, un argument délimité est (en citant le TeXbook ) "la séquence de jetons la plus courte (éventuellement vide) avec des {...}groupes correctement imbriqués qui est suivie en entrée par cette liste particulière de jetons non paramétriques". Cela signifie que l'expansion de\say Let's go to the mall to Martinproduira une phrase bizarre. Dans ce cas , vous auriez besoin de « cacher » la première ␣to␣avec {...}: \say {Let's go to the mall} to Martin.

  • Jusqu'ici tout va bien. Maintenant, les choses commencent à devenir bizarres. Lorsque TeX lit un caractère (qui est défini par un «code de caractère»), il attribue à ce caractère un «code de catégorie» (catcode, pour les amis :) qui définit ce que ce caractère signifie. Cette combinaison de caractères et de code de catégorie fait un jeton (plus d'informations ici , par exemple). Ceux qui nous intéressent ici sont essentiellement:

    • catcode 11 , qui définit des jetons qui peuvent constituer une séquence de contrôle (un nom chic pour une macro). Par défaut, toutes les lettres [a-zA-Z] sont catcode 11, donc je peux écrire \hello, qui est une seule séquence de contrôle, tandis que \he11ola séquence de contrôle est \hesuivie de deux caractères 1, suivie de la lettre o, car ce 1n'est pas le catcode 11. Si je a \catcode`1=11, à partir de ce moment-là \he11oserait une séquence de contrôle. Une chose importante est que les catcodes sont définis lorsque TeX voit pour la première fois le personnage à portée de main, et ce catcode est gelé ... POUR TOUJOURS ! (Les termes et conditions peuvent s'appliquer)

    • catcode 12 , qui sont la plupart des autres caractères, tels que 0"!@*(?,.-+/et ainsi de suite. Ils sont le type de catcode le moins spécial car ils ne servent qu'à écrire des trucs sur le papier. Mais bon, qui utilise TeX pour écrire?!? (encore une fois, des conditions générales peuvent s'appliquer)

    • catcode 13 , qui est l'enfer :) Vraiment. Arrêtez de lire et allez faire quelque chose de votre vie. Vous ne voulez pas savoir ce qu'est le catcode 13. Avez-vous déjà entendu parler du vendredi 13? Devinez d'où il tire son nom! Continuez à vos risques et périls! Un caractère catcode 13, également appelé caractère «actif», n'est plus seulement un caractère, c'est une macro en soi! Vous pouvez le définir pour avoir des paramètres et développer quelque chose comme nous l'avons vu ci-dessus. Une fois que vous le faites , \catcode`e=13vous pensez que vous pouvez faire \def e{I am the letter e!}, MAIS. TOI. NE PEUX PAS! en'est plus une lettre, donc ce \defn'est pas ce que \defvous savez, ça l'est \d e f! Oh, choisissez une autre lettre que vous dites? D'accord! \catcode`R=13 \def R{I am an ARRR!}. Très bien, Jimmy, essaye! J'ose vous faire ça et écrire un Rdans votre code! C'est ce qu'est un catcode 13. JE SUIS CALME! Allons-nous en.

  • D'accord, maintenant au regroupement. C'est assez simple. Quelles que soient les affectations (il \defs'agit d'une opération d'affectation \let(nous y reviendrons) en est une autre) effectuées dans un groupe sont restaurées à ce qu'elles étaient avant le démarrage de ce groupe, sauf si cette affectation est globale. Il existe plusieurs façons de démarrer des groupes, l'un d'eux est avec les caractères catcode 1 et 2 (oh, catcodes à nouveau). Par défaut {est catcode 1, ou begin-group, et }est catcode 2, ou end-group. Un exemple: \def\a{1} \a{\def\a{2} \a} \acela s'imprime 1 2 1. En dehors du groupe \aétait 1, puis à l' intérieur , il a été redéfinie 2, et quand le groupe a pris fin, il a été restauré 1.

  • L' \letopération est une autre opération d'affectation comme \def, mais plutôt différente. Avec \defvous définissez des macros qui se développeront en choses, avec \letvous créez des copies de choses déjà existantes. Après \let\blub=\def(le =est facultatif), vous pouvez changer le début de l' eexemple de l'élément catcode 13 ci-dessus pour \blub e{...vous amuser avec celui-ci. Ou mieux, au lieu de casser des choses que vous pouvez fixer (chercheriez-vous à cela!) L' Rexemple: \let\newr=R \catcode`R=13 \def R{I am an A\newr\newr\newr!}. Question rapide: pourriez-vous renommer \newR?

  • Enfin, les soi-disant «espaces parasites». C'est une sorte de sujet tabou car il y a des gens qui prétendent que la réputation gagnée dans l' échange de piles TeX - LaTeX en répondant à des questions sur les «espaces parasites» ne devrait pas être prise en compte, tandis que d'autres sont en désaccord sans réserve. Avec qui êtes-vous d'accord? Placez vos paris! Pendant ce temps: TeX comprend un saut de ligne comme un espace. Essayez d'écrire plusieurs mots avec un saut de ligne (pas une ligne vide ) entre eux. Ajoutez maintenant un %à la fin de ces lignes. C'est comme si vous «commentiez» ces espaces de fin de ligne. C'est ça :)

(Sorte de) dé-golfer le code

Faisons de ce rectangle quelque chose (sans doute) plus facile à suivre:

{
\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 }
}

Explication de chaque étape

chaque ligne contient une seule instruction. Allons un par un, les disséquant:

{
Tout d'abord, nous commençons un groupe pour garder certaines modifications (à savoir les modifications de code de cat) locales afin qu'elles ne gâchent pas le texte d'entrée.

\let~\catcode
Fondamentalement, tous les codes d'obscurcissement TeX commencent par cette instruction. Par défaut, à la fois dans TeX simple et LaTeX, le ~caractère est le seul caractère actif qui peut être transformé en macro pour une utilisation ultérieure. Et le meilleur outil pour étrangler le code TeX sont les changements de catcode, c'est donc généralement le meilleur choix. Maintenant, au lieu de \catcode`A=13nous pouvons écrire ~`A13(le =est facultatif):

~`A13
Maintenant, la lettre Aest un caractère actif, et nous pouvons le définir pour faire quelque chose:

\defA#1{~`#113\gdef}
Aest maintenant une macro qui prend un argument (qui devrait être un autre caractère). Tout d'abord, le code cat de l'argument est changé en 13 pour le rendre actif: ~`#113(remplacez le ~par \catcodeet ajoutez un =et vous avez :) \catcode`#1=13. Enfin, il laisse un \gdef(global \def) dans le flux d'entrée. En bref, Arend un autre personnage actif et commence sa définition. Essayons:

AGG#1{~`#113\global\let}
AGle premier «s'active» Get le fait \gdef, ce qui, suivi du suivant, Gdémarre la définition. La définition de Gest très similaire à celle de A, sauf qu'au lieu de \gdefcela, il y a un \global\let(il n'y en a pas \gletcomme le \gdef). En bref, Gactive un personnage et en fait quelque chose d'autre. Faisons des raccourcis pour deux commandes que nous utiliserons plus tard:

GFF\else
GHH\fi
Maintenant, au lieu de \elseet \finous pouvons simplement utiliser Fet H. Plus court :)

AQQ{Q}
Maintenant , nous utilisons à Anouveau pour définir une autre macro, Q. La déclaration ci-dessus fait essentiellement (dans un langage moins obscur) \def\Q{\Q}. Ce n'est pas une définition terriblement intéressante, mais elle a une fonctionnalité intéressante. À moins que vous ne vouliez casser du code, la seule macro qui se développe Qest Qelle - même, elle agit donc comme un marqueur unique (on l'appelle un quark ). Vous pouvez utiliser le \ifxconditionnel pour tester si l'argument d'une macro est tel quark avec \ifx Q#1:

AII{\ifxQ}
vous pouvez donc être sûr que vous avez trouvé un tel marqueur. Notez que dans cette définition, j'ai supprimé l'espace entre \ifxet Q. Habituellement, cela entraînerait une erreur (notez que la mise en évidence de la syntaxe pense que \ifxQc'est une chose), mais comme il Qs'agit maintenant de catcode 13, il ne peut pas former une séquence de contrôle. Attention, cependant, à ne pas étendre ce quark ou vous serez coincé dans une boucle infinie car se Qdilate vers Qlequel se développe vers Qlequel ...

Maintenant que les préliminaires sont terminés, nous pouvons passer à l'algorithme approprié pour pwas eht setterl. En raison de la tokenisation de TeX, l'algorithme doit être écrit à l'envers. En effet, au moment où vous faites une définition, TeX va tokenize (attribuer des catcodes) aux caractères de la définition en utilisant les paramètres actuels, par exemple, si je le fais:

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

la sortie est E1, alors que si je change l'ordre des définitions:

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

la sortie est 11. En effet, dans le premier exemple, la Edéfinition a été symbolisée sous forme de lettre (catcode 11) avant le changement de catcode, ce sera donc toujours une lettre E. Dans le deuxième exemple, cependant, a Eété rendu actif pour la première fois, et seulement alors a \oneété défini, et maintenant la définition contient le code cat 13 Equi se développe 1.

Je vais cependant ignorer ce fait et réorganiser les définitions pour avoir un ordre logique (mais pas fonctionnel). Dans les paragraphes qui suivent , vous pouvez supposer que les lettres B, C, Det Esont actifs.

\gdef\S#1{\iftrueBH#1 Q }
(remarquez qu'il y avait un petit bug dans la version précédente, il ne contenait pas l'espace final dans la définition ci-dessus. Je l'ai seulement remarqué en écrivant ceci. Lisez la suite et vous verrez pourquoi nous avons besoin de celui-ci pour terminer correctement la macro. ) Tout d'
abord , nous définissons la macro-niveau utilisateur, \S. Celui-ci ne doit pas être un caractère actif pour avoir une syntaxe conviviale (?), Donc la macro pour gwappins eht setterl est \S. La macro commence par un conditionnel toujours vrai \iftrue(il sera bientôt clair pourquoi), puis appelle la Bmacro suivie de H(que nous avons définie précédemment comme étant \fi) pour correspondre à \iftrue. Ensuite, nous laissons l'argument de la macro #1suivi d'un espace et du quark Q. Supposons que nous utilisons \S{hello world}, alors le flux d'entréedevrait ressembler à ceci:\iftrue BHhello world Q␣(J'ai remplacé le dernier espace par un pour que le rendu du site ne le mange pas, comme je le faisais dans la version précédente du code). \iftrueest vrai, donc il se développe et nous nous retrouvons avec BHhello world Q␣. TeX ne supprime pas le \fi( H) après l'évaluation du conditionnel, mais le laisse là jusqu'à ce que le \fisoit réellement développé. Maintenant, la Bmacro est développée:

ABBH#1 {HI#1FC#1|BH}
Best une macro délimitée dont le texte du paramètre est H#1␣, donc l'argument est tout ce qui est entre Het un espace. Poursuivant l'exemple au-dessus du flux d'entrée avant l'expansion de Bis BHhello world Q␣. Best suivi H, comme il se doit (sinon TeX soulèverait une erreur), alors l'espace suivant est entre helloet world, #1le mot aussi hello. Et ici, nous devons diviser le texte d'entrée dans les espaces. Yay: D L'expansion de BEnlève tout jusqu'au premier espace à partir du flux d'entrée et remplace par HI#1FC#1|BHd' #1être hello: HIhelloFChello|BHworld Q␣. Notez qu'il y a un nouveau BHplus tard dans le flux d'entrée, pour faire une récursion de queue deBet traiter les mots ultérieurs. Une fois ce mot traité, il Btraite le mot suivant jusqu'à ce que le mot à traiter soit le quark Q. Le dernier espace après Qest nécessaire car la macro délimitée en B requiert un à la fin de l'argument. Avec la version précédente (voir l'historique des modifications), le code se comporterait mal si vous l'utilisiez \S{hello world}abc abc(l'espace entre les abcs disparaîtrait).

OK, retour au flux d'entrée: HIhelloFChello|BHworld Q␣. Il y a d'abord le H( \fi) qui complète l'initiale \iftrue. Maintenant, nous avons ceci (pseudocodé):

I
  hello
F
  Chello|B
H
world Q␣

La I...F...Hréflexion est en fait une \ifx Q...\else...\fistructure. Le \ifxtest vérifie si le (premier jeton du) mot saisi est le Qquark. S'il est il n'y a rien d' autre à faire et les termine d'exécution, sinon ce qui reste est: Chello|BHworld Q␣. Maintenant Cest développé:

ACC#1#2|{D#2Q|#1 }
Le premier argument de Cest non délimité, de sorte que si contreventés ce sera un jeton unique, le second argument est délimitée par |, donc après l'expansion de la C(avec #1=het #2=ello) le flux d'entrée est la suivante : DelloQ|h BHworld Q␣. Remarquez qu'un autre |est mis là, et le hof helloest mis après. La moitié de l'échange est effectuée; la première lettre est à la fin. Dans TeX, il est facile de récupérer le premier jeton d'une liste de jetons. Une macro simple \def\first#1#2|{#1}obtient la première lettre lorsque vous utilisez \first hello|. Le dernier est un problème car TeX saisit toujours la liste de jetons "la plus petite, éventuellement vide" comme argument, nous avons donc besoin de quelques solutions. L'élément suivant dans la liste des jetons est D:

ADD#1#2|{I#1FE{}#1#2|H}
Cette Dmacro est l'une des solutions de contournement et elle est utile dans le seul cas où le mot a une seule lettre. Supposons qu'au lieu de hellonous x. Dans ce cas , le flux d'entrée serait DQ|xalors Délargirait (avec #1=Qet #2vide) à: IQFE{}Q|Hx. Ceci est similaire au bloc I...F...H( \ifx Q...\else...\fi) dans B, qui verra que l'argument est le quark et interrompra l'exécution en ne laissant que la xcomposition. Dans d' autres cas (retour à l' helloexemple), Délargirait (avec #1=eet #2=lloQ) à: IeFE{}elloQ|Hh BHworld Q␣. Encore une fois, le I...F...Hvérifiera Qmais échouera et prendre la \elsebranche: E{}elloQ|Hh BHworld Q␣. Maintenant, le dernier morceau de cette chose, leE la macro se développerait:

AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
Le texte du paramètre ici est assez similaire à Cet D; les premier et deuxième arguments ne sont pas délimités et le dernier est délimité par |. Le flux d'entrée ressemble à ceci: E{}elloQ|Hh BHworld Q␣, puis se Edilate (avec #1vide, #2=e, et #3=lloQ): IlloQeFE{e}lloQ|HHh BHworld Q␣. Un autre I...F...Hbloc vérifie pour le quark (qui voit let retourne false): E{e}lloQ|HHh BHworld Q␣. Maintenant , se Edéveloppe à nouveau (avec #1=evide, #2=let #3=loQ): IloQleFE{el}loQ|HHHh BHworld Q␣. Et encore I...F...H. La macro effectue quelques itérations supplémentaires jusqu'à ce que le Qsoit finalement trouvé et que la truebranche soit prise: E{el}loQ|HHHh BHworld Q␣-> IoQlelFE{ell}oQ|HHHHh BHworld Q␣-> E{ell}oQ|HHHHh BHworld Q␣-> IQoellFE{ello}Q|HHHHHh BHworld Q␣. Maintenant , le quark se trouve et les conditionnels à se dilate: oellHHHHh BHworld Q␣. Phew.

Oh, attendez, qu'est-ce que c'est? LETTRES NORMALES? Oh mec! Les lettres sont finalement trouvés et TeX écrit vers le bas oell, puis un tas de H( \fi) se trouvent et étendu (rien) en laissant le flux d'entrée avec: oellh BHworld Q␣. Maintenant, le premier mot a la première et la dernière lettres échangées et ce que TeX trouve ensuite est l'autre Bpour répéter tout le processus pour le mot suivant.

}
Enfin, nous terminons le groupe commencé là-bas afin que toutes les affectations locales soient annulées. Les missions locales sont les changements de catcode des lettres A, B, C... qui ont été faites des macros pour qu'ils reviennent à leur signification normale de lettre et peuvent être utilisés en toute sécurité dans le texte. Et c'est tout. Maintenant, la \Smacro définie là-bas déclenchera le traitement du texte comme ci-dessus.

Une chose intéressante à propos de ce code est qu'il est entièrement extensible. Autrement dit, vous pouvez l'utiliser en toute sécurité pour déplacer des arguments sans craindre qu'il explose. Vous pouvez même utiliser le code pour vérifier si la dernière lettre d'un mot est la même que la seconde (pour une raison quelconque, vous en aurez besoin) dans un \iftest:

\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

Désolé pour l'explication (probablement beaucoup trop) verbeuse. J'ai essayé de le rendre aussi clair que possible pour les non TeXies :)

Résumé pour les impatients

La macro \Sajoute à l'entrée un caractère actif Bqui récupère les listes de jetons délimités par un espace final et les transmet à C. Cprend le premier jeton de cette liste et le déplace à la fin de la liste de jetons et se développe Davec ce qui reste. Dvérifie si «ce qui reste» est vide, auquel cas un mot d'une seule lettre a été trouvé, puis ne fait rien; sinon se développe E. Eparcourt la liste des jetons jusqu'à ce qu'il trouve la dernière lettre du mot, lorsqu'il le trouve, il laisse cette dernière lettre, suivi du milieu du mot, qui est ensuite suivi de la première lettre laissée à la fin du flux de jetons par C.

Phelype Oleinik
la source
2
J'aimerais une explication complète de celui-ci. Je suis très curieux de savoir comment cela fonctionne!
LambdaBeta
1
@LambdaBeta Je peux le faire, mais pas pour le moment. Attendez et je vous
cinglerai
1
@LambdaBeta terminé! Désolé, je suis parfois trop verbeux :-)
Phelype Oleinik
13

JavaScript (ES6),  39  36 octets

Enregistré 3 octets grâce à @FryAmTheEggman

Utilise un saut de ligne comme séparateur.

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

Essayez-le en ligne!

Arnauld
la source
5
(.)(.*)(.)est-ce l'émoticône Total Recall?
MikeTheLiar
1
@MikeTheLiar En quelque sorte, je suppose. : D
Arnauld
L'affectation spécifie que la chaîne contient le séparateur.
Cees Timmerman
@CeesTimmerman Je ne sais pas ce que tu veux dire. Ce code attend un saut de ligne comme séparateur et prend donc des chaînes avec des sauts de ligne en entrée. (Le pied de page du lien TIO convertit les espaces en sauts de ligne, puis de nouveau en espaces pour plus de lisibilité.)
Arnauld
"étant donné une chaîne de caractères alphabétiques ASCII ainsi qu'un autre caractère à utiliser comme délimiteur (pour séparer chaque mot) " - Nm, je pensais que c'était un paramètre distinct.
Cees Timmerman
11

Retina ,8 5 octets

,V,,`

Essayez-le en ligne!

Enregistré 3 octets grâce à Kevin Cruijssen !

Utilise une nouvelle ligne comme séparateur. Nous utilisons l'étape inverse de Retina et certaines limites. La première limite est celle qui correspond à laquelle appliquer l'inversion, nous les choisissons donc tous avec ,. Ensuite, nous voulons que la première et la dernière lettre de chaque correspondance soient échangées, nous prenons donc chaque lettre dans la plage ,,qui se traduit par une plage du début à la fin avec une taille de pas zéro.

FryAmTheEggman
la source
Dangit, je cherchais juste à travers les documents pour quelque chose comme ça pour mettre à jour ma réponse, mais tu m'as battu. Je savaisV , mais ne savais pas qu'il pouvait être utilisé avec des indices 1,-2comme ça. Joli!
Kevin Cruijssen
1
@KevinCruijssen J'ai un peu triché et j'ai passé en revue le fonctionnement des plages limites alors que c'était dans le bac à sable :) Je pense toujours qu'il devrait y avoir un meilleur moyen que d'inverser une plage mais je n'ai pas pu trouver quelque chose de plus court.
FryAmTheEggman
2
Vous avez en effet raison qu'il peut être plus court sans plage de limites, car il semble que ce 5 octets fonctionne (donné comme exemple au bas des limites de pas dans la documentation).
Kevin Cruijssen
@KevinCruijssen Nice! Je ne peux pas croire que j'ai raté ça.
FryAmTheEggman
3
Donc, 5 octets et seulement 3 caractères différents? C'est minimaliste.
Cœur
9

Pepe , 107 105 octets

REEeREeeEeeeeerEEreREEEeREEEEEEeREEEErEEREEEEEEEreererEEEeererEEEerEEeERrEEEeerEEeerereeerEEEEeEEEReEeree

Essayez-le en ligne!

Explication:

Notation sur les commentaires: 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
indéfini
la source
Comment cela marche-t-il?
lirtosiast
Explication @lirtosiast ajoutée
u_ndefined
7

Python 3 , 72 58 octets

print(*[x[-1]+x[1:-1]+x[:x>x[0]]for x in input().split()])

Essayez-le en ligne!

alexz02
la source
Ne fonctionne pas pour les mots d'une lettre (par exemple a)
TFeld
@TFeld, corrigé ..
alexz02
6

laskelH , 71 octets

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

Essayez-le en ligne!

Exemple d'entrée / sortie:

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
```
Cubique
la source
1
L'affectation dans la whereclause peut être déplacée vers une liaison en garde pour économiser 5 octets: Essayez-la en ligne!
Laikoni
1
Je vois ce que vous y avez fait avec le nom "Haskell" dans le titre. J'ai fait la même chose sur ma réponse PHP.
640 Ko
5

05AB1E , 10 octets

#vyRćsRćðJ

Essayez-le en ligne!


-3 Merci à @Kevin Cruijssen .

#           | Split into words.
 vy         | For each word...
   RćsRć    | Reverse, split head, swap, reverse, split tail
        ðJ  | Join by spaces.
Urne de poulpe magique
la source
1
10 octets
Kevin Cruijssen
1
@KevinCruijssen Je veux honnêtement le supprimer et vous le donner, c'était 99% de votre cerveau sur l'ordre des arguments haha.
Urne de poulpe magique
1
Trouvé un 9 octets, mais cela ne fonctionne que dans la version héritée:|ʒRćsRćJ,
Kevin Cruijssen
1
Dommage que nous n'en ayons pas loop_as_long_as_there_are_inputs, alors j'aurais connu un 8 octets: [RćsRćJ,ce 8 octets n'utilisant [jamais de sorties en théorie cependant, uniquement lorsque vous êtes à court de mémoire ou que vous expirez comme sur TIO (et qu'il nécessite un suivi retour à la ligne dans l'entrée, sinon il continuera à utiliser le dernier mot) ..
Kevin Cruijssen
1
Malheureusement, vous avez besoin ð¡d'une entrée de mot unique, mais ð¡εćsÁì}ðýelle fonctionne également à 10 octets.
Emigna
5

J , 23 17 octets

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

Essayez-le en ligne!

FrownyFrog
la source
Très bonne astuce pour permuter les premières / dernières lettres en les faisant tourner et en les appliquant 1 A.!
Galen Ivanov
1
1&A.&.(1&|.)-> ({:,1|.}:)puis vous pouvez supprimer le::]
ngn
Incroyable, merci
FrownyFrog
Vraiment incroyable! Encore une fois, je suis étonné de voir à quel point la solution peut être simple et élégante, mais seulement après l'avoir vue faite par quelqu'un d'autre.
Galen Ivanov
4

Rubis avec -p, 42 41 29 octets

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

Essayez-le en ligne!

Encre de valeur
la source
@Shaggy merci pour les avertissements. Si vous regardez l'historique de mes messages, cela montre que j'étais absent pendant 8 mois sans aucune réponse, donc j'ai probablement raté quelques mémos pendant ce temps, haha
Value Ink
Je suis sûr que le consensus a changé il y a plus de 8 mois, mais juste au cas où vous l'auriez manqué: "non-concurrent" n'est plus une chose non plus.
Shaggy
Bien fait. Je pense qu'en vertu des règles, vous pouvez utiliser des sauts de ligne comme délimiteur et remplacer le \ws par le .s.
histocrate
4

Haskell, 54 octets

unwords.map f.words
f[a]=[a]
f(a:b)=last b:init b++[a]

Essayez-le en ligne!

nimi
la source
4

Japt -S , 7 octets

¸®ÎiZÅé

Essayez-le

Oliver
la source
1
Agréable! Je savais qu'il y aurait un moyen plus court.
Shaggy
1
Je suis impressionné. Bravo
Incarnation de l'ignorance
3

Espace , 179 octets

[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]

Lettres S(espace), T(tabulation) et N(nouvelle ligne) ajoutées uniquement en surbrillance.
[..._some_action]ajouté à titre d'explication uniquement.

Tab comme délimiteur. L'entrée doit contenir un retour à la ligne (ou un onglet), sinon le programme ne sait pas quand s'arrêter, car la saisie dans l'espace blanc ne peut être effectuée qu'un caractère à la fois.

Essayez-le en ligne (avec des espaces bruts, des tabulations et des nouvelles lignes uniquement).

Explication en pseudo-code:

L'espace blanc n'a qu'une pile et un tas, où le tas est une carte avec une clé et une valeur (les deux entiers). Les entrées ne peuvent être lues qu'un seul entier ou caractère à la fois, qui sont toujours placés dans le tas en tant qu'entiers, et peuvent ensuite être reçues et poussées vers la pile avec leurs adresses de tas définies (clés de carte). Dans mon approche, je stocke le mot entier aux adresses de tas (clés de carte)[0,...,longueur_mot], puis récupérez les caractères à imprimer un par un dans l'ordre souhaité après qu'un onglet (ou une nouvelle ligne) soit rencontré comme délimiteur.

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

Le programme se termine avec une erreur lorsqu'il essaie de lire un caractère alors qu'aucun n'est donné dans TIO (ou il se bloque en attendant une entrée dans certains compilateurs d' espaces comme vii5ard ).

Kevin Cruijssen
la source
3

Wolfram Language (Mathematica) , 58 octets

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

Essayez-le en ligne!

-22 octets de @attinat

-12 octets de @ M.Stern

J42161217
la source
70 octets en utilisant StringReplaceavec StringExpressions
attinat
1
64 octets utilisant StringTakeau lieu de StringReplace:StringRiffle[StringSplit@##~StringTake~{{-1},{2,-2},{1}},#2,""]&
Roman
2
Voici une approche plus directe:StringReplace[#, a : u ~~ w : u .. ~~ b : u :> b <> w <> a /. {u -> Except@#2}] &
M. Stern
1
{et} sont facultatifs :)
M. Stern
1
55 octets , corrige également les mots de 2 caractères
attinat
2

QuadR , 20 octets

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

Créez simplement trois groupes de capture composés de 1, 0 ou plus, et 1 mot-caractères, puis inverse leur ordre.

Essayez-le en ligne!

Adam
la source
2

Japt -S , 10 octets

Convaincu qu'il doit y avoir une approche plus courte (et j'avais raison ) mais cela suffira pour l'instant.

¸ËhJDg)hDÌ

Essayez-le

¸Ë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
Hirsute
la source
Beaucoup plus court que mon 12 octets:¸®Ì+Zs1J +Zg
Incarnation de l'ignorance
@EmbodimentofIgnorance, c'est là que j'ai commencé aussi, mais cela aurait échoué sur les mots à un seul caractère. Vous pouvez cependant économiser un octet avec ¸®ÎiZÌ+Zs1J.
Shaggy
1
@EmbodimentofIgnorance Trouvé sur 7 octets
Oliver
2

sed, 64 octets

sed -E 's/\b([[:alpha:]])([[:alpha:]]*)([[:alpha:]])\b/\3\2\1/g'
Riches
la source
Sure, we could use . instead of [[:alpha:]], but it would actually have to be [^ ], which reduces it to 43, but breaks on punctuation and such. Using [a-zA-Z] brings it up to 55, by which point I'm just hankering after those sweet, sweet human readable entities...
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. In other words, you don't need to worry about punctuation "breaking" your code and can just safely go for [^ ] ;)
Value Ink
@ValueInk Yeah, but then [^ ] should be [^[:space:]] which brings it to 67 chars.
Rich
"a delimiter" means you can ensure that the delimiter is always a regular space. Who uses tabs in a sentence anyways??
Value Ink
Okay. Seems like "code golf" is a game where you're meant to find ways to get a drone to drop the ball in the hole instead of actually doing the work. Thanks for the shitty welcome.
Rich
2

sed, 34 bytes

And presumably the pattern idea will work with most RE tools (and I do know there are differences between standard RE and extended RE).

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

Try it online!

PJF
la source
1
Welcome to PPCG! Methinks that the greedy nature of regex matches means you can cut the \b from the match: Try it online!
Value Ink
Agreed @ValueInk -- but I was being accurate with the match. Removing the \b will lead to 30 bytes.
PJF
Use -E for advanced regex and you can use unescaped parentheses. Use . for the swapped chars and you can lose another two chars. This brings yours down to 26 bytes; one of the smallest readable solutions. s,\b(.)(\w*)(.)\b,\3\2\1,g
Rich
1
- nope, I'm wrong, you need the \ws at the ends. s,\b(\w)(\w*)(\w)\b,\3\2\1,g 28 chars.
Rich
Nice work @rich, but as I said I know about standard and extended RE. I just chose to make it standard and readable. The anchors would be required which I neglected to mention in my reply to ValueInk.
PJF
2

Ruby, 53 bytes

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

I tried it without regex. The output prints each word on a new line. If that's against the rules, let me know and I'll fix it.

Ungolfed:

gets.split(" ").map {|z|
    print z[-1] + z[1..-2] + z[0], " "
}
83338
la source
Welcome to PPCG! Printing each word on a new line should be fine, but your old solution of p was no good because that added quotes to the output. You could always use puts instead since that one auto-appends the newline and is shorter than print! Also, if you call split with no arguments it automatically splits on spaces.
Value Ink
2

8088 Assembly, IBM PC DOS, 39 38 bytes

$ 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

Unassembled:

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 

Standalone PC DOS executable. Input via command line args, output to screen.

enter image description here

Download and test PWAS.COM.

640KB
la source
1

Batch, 141 bytes

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

Takes input as command-line parameters. String manipulation is dire in Batch at best, and having to special-case single-letter words doesn't help.

Neil
la source
1

C# (Visual C# Interactive Compiler), 90 bytes

n=>n.Split().Any(x=>WriteLine(x.Length<2?x:x.Last()+x.Substring(1,x.Length-2)+x[0])is int)

Uses newline as delimiter, though really any whitespace can be used.

Try it online!

Embodiment of Ignorance
la source
SelectMany (that is, map and flatten) for 84 bytes, but outputs a single trailing space. Try it online!
my pronoun is monicareinstate
1

Java, 110 109 bytes

-1 bytes by using a newline for a delimeter

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

Benjamin Urquhart
la source
Does this work for single-letter words?
Neil
@Neil no because I'm bad. I'll fix later.
Benjamin Urquhart
109 by using newline as delimiter
Embodiment of Ignorance
1

Haskell, 75 74 bytes

Fixed a bug pointed at by Cubic and also golfed down 1 byte.

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

Try it online!

Max Yekhlakov
la source
map g is shorter than (g<$>)
Cubic
1
Also, if you look at your test case you'll see it doesn't work for one letter words, it turns a into aa
Cubic
1

Scala, 100 bytes

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

T-SQL, 126 bytes

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

Input is via a pre-existing table t with varchar field v, per our IO standards.

Reading from back to front, STRING_SPLIT breaks a string into individual rows via a delimiter, STUFF modifies the characters at the specified positions, then STRING_AGG mashes them back together again.

BradC
la source