pwaS eht tirsf dna tasl setterl fo hace dorw


30

O "Intercambie la primera y la última letra de cada palabra"

Su desafío es, dada una cadena de caracteres ASCII alfabéticos, así como otro carácter para usar como delimitador (para separar cada palabra), intercambiar la primera y la última letra de cada palabra. Si hay una palabra de un carácter, déjela en paz.

Los ejemplos / casos de prueba usan las letras minúsculas y el espacio como delimitador.

No necesita manejar la puntuación; todas las entradas solo consistirán en las letras a a z, separadas por un delimitador, todas en mayúsculas y minúsculas.

Por ejemplo, con la cadena "hola mundo":

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"

NOTA: el delimitador no necesita ser ingresado por separado. El delimitador es solo el carácter utilizado para separar las palabras. Puede ser cualquier cosa. Quería dejar opciones abiertas para golfistas creativos, así que no quería limitarlo solo a espacios o nuevas líneas. El delimitador es solo un carácter que separa las palabras en la cadena de entrada.

Casos de prueba:

"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
¿Cómo se debe tratar la puntuación? Hello, world!se convierte ,elloH !orldw(intercambiando la puntuación como una letra) o oellH, dorlw!(manteniendo la puntuación en su lugar)?
Phelype Oleinik

3
@PhelypeOleinik No necesita manejar la puntuación; todas las entradas solo consistirán en las letras de la a a la z, y todas en mayúsculas y minúsculas.
Camarada SparklePony

44
El segundo párrafo se lee tan bien como otro personaje para usar como delimitador, mientras que el cuarto se lee separado por espacios . ¿Cuál es?
Adám

@ Adám Cualquier carácter no alfabético. Lo editaré para aclarar.
Camarada SparklePony

1
@BenjaminUrquhart Sí. Puede tomar la entrada como argumento de función si lo desea también.
Camarada SparklePony

Respuestas:


59

TeX, 216 bytes (4 líneas, 54 caracteres cada una)

Debido a que no se trata del conteo de bytes, se trata de la calidad de la salida tipográfica :-)

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

Pruébalo en línea! (Al dorso; no estoy seguro de cómo funciona)

Archivo de prueba completo:

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

Salida:

ingrese la descripción de la imagen aquí


Para LaTeX solo necesitas el repetitivo:

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

Explicación

TeX es una bestia extraña. Leer el código normal y comprenderlo es una hazaña en sí mismo. Comprender el código TeX ofuscado va unos pasos más allá. Trataré de hacer esto comprensible para las personas que no conocen TeX también, así que antes de comenzar, aquí hay algunos conceptos sobre TeX para que las cosas sean más fáciles de seguir:

Para principiantes de TeX (no tan)

  • Primero, y el elemento más importante en esta lista: el código no tiene que estar en forma de rectángulo, a pesar de que la cultura pop podría llevarlo a pensar que sí .

  • TeX es un lenguaje de macro expansión. Puede, como ejemplo, definir \def\sayhello#1{Hello, #1!}y luego escribir \sayhello{Code Golfists}para que TeX imprima Hello, Code Golfists!. Esto se llama una "macro no delimitada", y para alimentarlo el primer parámetro (y solo, en este caso) lo encierra entre llaves. TeX elimina esas llaves cuando la macro toma el argumento. Puede usar hasta 9 parámetros: \def\say#1#2{#1, #2!}entonces \say{Good news}{everyone}.

  • La contrapartida de macros no delimitada son, como era de esperar, los delimitado :) Se podría hacer que la definición anterior un poco más semántica : \def\say #1 to #2.{#1, #2!}. En este caso, los parámetros son seguidos por el llamado texto de parámetro . Tal texto parámetro delimita el argumento de la macro ( #1está delimitada por ␣to␣, espacios incluidos, y #2está delimitada por .). Después de esa definición puedes escribir \say Good news to everyone., que se expandirá a Good news, everyone!. Bien, ¿no es así? :) Sin embargo, un argumento delimitado es (citando el TeXbook ) "la secuencia más corta (posiblemente vacía) de tokens con {...}grupos correctamente anidados que se sigue en la entrada de esta lista particular de tokens sin parámetros". Esto significa que la expansión de\say Let's go to the mall to Martinproducirá una oración extraña. En este caso lo que se necesita para “ocultar” el primero ␣to␣con {...}: \say {Let's go to the mall} to Martin.

  • Hasta aquí todo bien. Ahora las cosas comienzan a ponerse raras. Cuando TeX lee un carácter (que se define mediante un "código de carácter"), asigna a ese carácter un "código de categoría" (código de gato, para amigos :) que define lo que significará ese carácter. Esta combinación de caracteres y código de categoría hace un token (más sobre eso aquí , por ejemplo). Los que nos interesan aquí son básicamente:

    • catcode 11 , que define tokens que pueden formar una secuencia de control (un nombre elegante para una macro). Por defecto, todas las letras [a-zA-Z] son ​​código de gato 11, por lo que puedo escribir \hello, que es una secuencia de control única, mientras que \he11oes la secuencia de control \heseguida de dos caracteres 1, seguidos de la letra o, porque 1no es el código de gato 11. Si yo lo hizo \catcode`1=11, a partir de ese momento \he11osería una secuencia de control. Una cosa importante es que los códigos de gato se establecen cuando TeX ve por primera vez al personaje a mano, y ese código de gato se congela ... ¡PARA SIEMPRE! (Se pueden aplicar términos y condiciones)

    • catcode 12 , que son la mayoría de los otros caracteres, como, 0"!@*(?,.-+/etc. Son el tipo de código de gato menos especial, ya que solo sirven para escribir cosas en el papel. Pero oye, ¿quién usa TeX para escribir? (nuevamente, pueden aplicarse términos y condiciones)

    • catcode 13 , que es el infierno :) En serio. Deja de leer y ve a hacer algo fuera de tu vida. No quieres saber qué es el código de cat. 13. ¿Has oído hablar del viernes 13? ¡Adivina de dónde obtuvo su nombre! ¡Continúa bajo tu propia responsabilidad! Un carácter de código de gato 13, también llamado carácter "activo", ya no es solo un carácter, ¡es una macro en sí misma! Puede definirlo para que tenga parámetros y expandirlo a algo como vimos anteriormente. Después de lo \catcode`e=13que crees que puedes hacer \def e{I am the letter e!}, PERO. TÚ. ¡NO PODER! eya no es una carta, así \defque no es lo \defque sabes, ¡lo es \d e f! Oh, elige otra letra que dices? ¡Bueno! \catcode`R=13 \def R{I am an ARRR!}. Muy bien, Jimmy, ¡pruébalo! ¡Me atrevo a hacer eso y escribir un Ren su código! Eso es lo que es un catcode 13. ¡ESTOY CALMADO! Vamonos.

  • Bien, ahora a la agrupación. Esto es bastante sencillo. Cualesquiera asignaciones ( \defes una operación de asignación, \let(entraremos en ella) es otra) que se realizan en un grupo se restauran a lo que eran antes de que ese grupo comenzara a menos que esa asignación sea global. Hay varias formas de iniciar grupos, una de ellas es con los códigos de cat 1 y 2 caracteres (oh, catcodes nuevamente). Por defecto {es el código de gato 1, o grupo de inicio, y }es el código de gato 2, o grupo de finalización. Un ejemplo: \def\a{1} \a{\def\a{2} \a} \aesto imprime 1 2 1. Fuera del grupo \aera 1, a continuación, en su interior se redefinió a 2, y cuando el grupo terminó, fue restaurado a 1.

  • La \letoperación es otra operación de asignación similar \def, pero bastante diferente. Con \defusted define macros que se expandirán a cosas, con\let usted crea copias de cosas ya existentes. Después \let\blub=\def(el =es opcional) puede cambiar el inicio del eejemplo del elemento del código de cat. 13 anterior \blub e{...y divertirse con ese. O mejor, en lugar de romper cosas que se pueden arreglar (le mira eso!) Del Rejemplo: \let\newr=R \catcode`R=13 \def R{I am an A\newr\newr\newr!}. Pregunta rápida: ¿podrías cambiarle el nombre \newR?

  • Finalmente, los llamados "espacios espurios". Este es un tema tabú porque hay personas que afirman que la reputación ganada en TeX - LaTeX Stack Exchange al responder preguntas de "espacios espurios" no debe considerarse, mientras que otros están totalmente en desacuerdo. ¿Con quién estás de acuerdo? ¡Haga sus apuestas! Mientras tanto: TeX entiende un salto de línea como un espacio. Intente escribir varias palabras con un salto de línea (no una línea vacía ) entre ellas. Ahora agregue un %al final de estas líneas. Es como si estuvieras "comentando" estos espacios de fin de línea. Eso es :)

(Más o menos) descifrando el código

Hagamos que ese rectángulo se convierta en algo (posiblemente) más fácil de seguir:

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

Explicación de cada paso.

Cada línea contiene una sola instrucción. Vamos uno por uno, diseccionándolos:

{
Primero comenzamos un grupo para mantener algunos cambios (es decir, cambios de código de gato) locales para que no alteren el texto de entrada.

\let~\catcode
Básicamente, todos los códigos de ofuscación TeX comienzan con esta instrucción. Por defecto, tanto en TeX como en LaTeX, el ~carácter es el único carácter activo que puede convertirse en una macro para su uso posterior. Y la mejor herramienta para extrañar el código TeX son los cambios de código de gato, por lo que generalmente es la mejor opción. Ahora en lugar de \catcode`A=13podemos escribir ~`A13(el =es opcional):

~`A13
Ahora la letra Aes un carácter activo, y podemos definirla para hacer algo:

\defA#1{~`#113\gdef}
Aahora es una macro que toma un argumento (que debería ser otro carácter). Primero, el código de gato del argumento se cambia a 13 para activarlo: ~`#113(reemplace ~by \catcodey agregue an =y tiene :) \catcode`#1=13. Finalmente deja un \gdef(global \def) en la secuencia de entrada. En resumen, Aactiva otro personaje y comienza su definición. Vamos a intentarlo:

AGG#1{~`#113\global\let}
AGprimero "se activa" Gy lo hace \gdef, que luego sigue el siguiente Gcomienza la definición. La definición de Ges muy similar a la de A, excepto que en lugar de \gdefeso hace un \global\let(no hay un \gletcomo el \gdef). En resumen, Gactiva un personaje y lo convierte en otra cosa. Hagamos atajos para dos comandos que usaremos más adelante:

GFF\else
GHH\fi
Ahora en lugar de \elsey \fisimplemente podemos usar Fy H. Mucho más corto :)

AQQ{Q}
Ahora usamos Ade nuevo para definir otra macro, Q. La declaración anterior básicamente lo hace (en un lenguaje menos ofuscado) \def\Q{\Q}. Esta no es una definición terriblemente interesante, pero tiene una característica interesante. A menos que desee romper algún código, la única macro que se expande Qes a Qsí misma, por lo que actúa como un marcador único (se llama quark ). Puede usar el \ifxcondicional para probar si el argumento de una macro es tal quark con \ifx Q#1:

AII{\ifxQ}
así que puedes estar bastante seguro de haber encontrado ese marcador. Tenga en cuenta que en esta definición eliminé el espacio entre \ifxy Q. Por lo general, esto llevaría a un error (tenga en cuenta que el resaltado de sintaxis cree que \ifxQes una cosa), pero como ahora Qes el código de cat. 13, no puede formar una secuencia de control. Sin embargo, tenga cuidado de no expandir este quark o se quedará atrapado en un bucle infinito porque se Qexpande aQ que se expande a lo Qque ...

Ahora que los preliminares están terminados, podemos ir al algoritmo apropiado para establecer la configuración. Debido a la tokenización de TeX, el algoritmo debe escribirse al revés. Esto se debe a que en el momento en que realiza una definición, TeX tokenizará (asignará códigos de barras) a los caracteres de la definición utilizando la configuración actual, por ejemplo, si lo hago:

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

la salida es E1, mientras que si cambio el orden de las definiciones:

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

la salida es 11. Esto se debe a que en el primer ejemplo, Een la definición se tokenizó como una letra (catcode 11) antes del cambio de catcode, por lo que siempre será una letra E. Sin embargo, en el segundo ejemplo, Eprimero se activó, y solo entonces \onese definió, y ahora la definición contiene el código de cat. 13E que se expande a 1.

Sin embargo, pasaré por alto este hecho y reordenaré las definiciones para que tengan un orden lógico (pero que no funcione). En los siguientes párrafos se puede asumir que las letras B, C, D, y Eson activos.

\gdef\S#1{\iftrueBH#1 Q }
(observe que había un pequeño error en la versión anterior, no contenía el espacio final en la definición anterior. Solo lo noté mientras escribía esto. Siga leyendo y verá por qué necesitamos ese para terminar correctamente la macro. )
En primer lugar se define la macro-nivel de usuario, \S. Este no debe ser un personaje activo para tener una sintaxis amigable (?), Por lo que la macro para gwappins eht setterl es \S. La macro comienza con un condicional siempre verdadero \iftrue(pronto quedará claro por qué), y luego llama a la Bmacro seguida de H(que definimos anteriormente como \fi) para que coincida con \iftrue. Luego dejamos el argumento de la macro #1seguido de un espacio y el quark Q. Supongamos que usamos \S{hello world}, luego el flujo de entradadebería verse así: \iftrue BHhello world Q␣(Reemplacé el último espacio por unpara que la representación del sitio no lo coma, como hice en la versión anterior del código). \iftruees cierto, entonces se expande y nos quedamos BHhello world Q␣. TeX no no retire la \fi( H) después de evaluar el condicional, en cambio, deja allí hasta que el \fiestá realmente expandieron. Ahora la Bmacro se expande:

ABBH#1 {HI#1FC#1|BH}
Bes una macro delimitada cuyo texto de parámetro es H#1␣, por lo que el argumento es lo que sea que esté entre Hy un espacio. Continuando con el ejemplo anterior a la secuencia de entrada antes de la expansión de Bis BHhello world Q␣. Bes seguido por H, como debería (de lo contrario, TeX generaría un error), entonces el siguiente espacio está entre helloy world, también lo #1es la palabra hello. Y aquí tenemos que dividir el texto de entrada en los espacios. Yay: D La expansión de Bquita todo hasta el primer espacio de la corriente de entrada y la sustituye por HI#1FC#1|BHla #1de serhello : HIhelloFChello|BHworld Q␣. Observe que hay un nuevo BHmás adelante en la secuencia de entrada, para hacer una recursión de cola deBy procesar palabras posteriores. Después de que esta palabra se procesa, Bprocesa la siguiente palabra hasta que la palabra a procesar sea el quark Q. Se Qnecesita el último espacio después porque la macro delimitada B requiere uno al final del argumento. Con la versión anterior (ver historial de edición) el código se comportaría mal si lo usara \S{hello world}abc abc(el espacio entre los abcs se desvanecería).

OK, de vuelta a la corriente de entrada: HIhelloFChello|BHworld Q␣. Primero está el H( \fi) que completa la inicial \iftrue. Ahora tenemos esto (pseudocodificado):

I
  hello
F
  Chello|B
H
world Q␣

El I...F...Hpensar es en realidad una \ifx Q...\else...\fiestructura. La \ifxprueba verifica si la (primera señal de) la palabra tomada es el Qquark. Si es que no hay nada más que hacer y las termina la ejecución, de lo contrario lo que queda es: Chello|BHworld Q␣. Ahora Cse expande:

ACC#1#2|{D#2Q|#1 }
El primer argumento de Cque se no delimitada, por lo menos se preparó será de un solo símbolo, el segundo argumento está delimitado por |, por lo que después de la expansión de C(con #1=hy #2=ello) del flujo de entrada es: DelloQ|h BHworld Q␣. Observe que |se coloca otro , y el hde hellose pone después de eso. La mitad del intercambio está hecho; La primera letra está al final. En TeX es fácil tomar el primer token de una lista de tokens. Una macro simple \def\first#1#2|{#1}obtiene la primera letra cuando la usa \first hello|. El último es un problema porque TeX siempre toma la lista de tokens "más pequeña, posiblemente vacía" como argumento, por lo que necesitamos algunas soluciones. El siguiente elemento en la lista de tokens es D:

ADD#1#2|{I#1FE{}#1#2|H}
Esta Dmacro es una de las soluciones y es útil en el único caso donde la palabra tiene una sola letra. Supongamos que en lugar de hellotener x. En este caso el flujo de entrada sería DQ|x, entonces Dse ampliaría (con #1=Q, y #2vaciar) a: IQFE{}Q|Hx. Esto es similar al bloque I...F...H( \ifx Q...\else...\fi) B, que verá que el argumento es el quark e interrumpirá la ejecución dejando solo la xcomposición tipográfica. En otros casos (volviendo al helloejemplo), Dse expandiría (con #1=ey #2=lloQ) a: IeFE{}elloQ|Hh BHworld Q␣. Una vez más, la I...F...Hcomprobará si hay Qpero se producirá un error y tomar la \elserama: E{}elloQ|Hh BHworld Q␣. Ahora la última pieza de esta cosa, elE la macro se expandiría:

AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
El texto del parámetro aquí es bastante similar a Cy D; los argumentos primero y segundo no están delimitados, y el último está delimitado por |. El aspecto de flujo de entrada como esta: E{}elloQ|Hh BHworld Q␣, a continuación, Ese expande (con #1vacío, #2=ey #3=lloQ): IlloQeFE{e}lloQ|HHh BHworld Q␣. Otro de I...F...Hlos controles de bloque para el quark (que ve ly regresa false): E{e}lloQ|HHh BHworld Q␣. Ahora Ese expande de nuevo (con #1=evacío, #2=ly #3=loQ): IloQleFE{el}loQ|HHHh BHworld Q␣. Y otra vez I...F...H. La macro hace algunas iteraciones más hasta Qque finalmente se encuentra y truese toma la rama: E{el}loQ|HHHh BHworld Q␣-> IoQlelFE{ell}oQ|HHHHh BHworld Q␣-> E{ell}oQ|HHHHh BHworld Q␣-> IQoellFE{ello}Q|HHHHHh BHworld Q␣. Ahora el quark se encuentra y se expande condicionales a: oellHHHHh BHworld Q␣. Uf.

Oh, espera, ¿qué son estos? CARTAS NORMALES? ¡Oh chico! Las letras son finalmente encontraron y Tex escribe oell, entonces un montón de H( \fi) se encuentran y se expande (o nada) que sale de la corriente de entrada con: oellh BHworld Q␣. Ahora la primera palabra tiene la primera y la última letra intercambiadas y lo que TeX encuentra a continuación es la otra Bpara repetir todo el proceso para la siguiente palabra.

}
Finalmente terminamos el grupo que comenzó allí para que se deshagan todas las tareas locales. Las tareas locales son los cambios catcode de las letras A, B, C, ... que se hicieron las macros para que vuelvan a su significado normal letra y pueden ser utilizados con seguridad en el texto. Y eso es. Ahora la \Smacro definida allí activará el procesamiento del texto como se indicó anteriormente.

Una cosa interesante sobre este código es que es completamente expandible. Es decir, puede usarlo de manera segura para mover argumentos sin preocuparse de que explote. Incluso puede usar el código para verificar si la última letra de una palabra es la misma que la segunda (por cualquier razón que lo necesite) en una \ifprueba:

\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

Perdón por la explicación (probablemente demasiado) prolija. Traté de hacerlo lo más claro posible para los que no son TeXies también :)

Resumen para los impacientes

La macro \Santepone la entrada con un carácter activo Bque toma listas de tokens delimitados por un espacio final y los pasa a C. Ctoma el primer token en esa lista y lo mueve al final de la lista de tokens y se expande Dcon lo que queda. Dcomprueba si "lo que queda" está vacío, en cuyo caso se encontró una palabra de una sola letra, luego no hace nada; de lo contrario se expande E. Erecorre la lista de tokens hasta que encuentra la última letra de la palabra, cuando se encuentra, deja esa última letra, seguida de la mitad de la palabra, que luego es seguida por la primera letra que queda al final del flujo de tokens C.


2
Me encantaría una explicación completa de este. Tengo mucha curiosidad sobre cómo funciona.
LambdaBeta

1
@LambdaBeta Puedo hacerlo, pero no ahora. Espera y te enviaré un ping cuando lo haga :)
Phelype Oleinik

1
@LambdaBeta Hecho! Lo siento, a veces soy demasiado prolijo :-)
Phelype Oleinik

13

JavaScript (ES6),  39  36 bytes

Guardado 3 bytes gracias a @FryAmTheEggman

Utiliza un salto de línea como separador.

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

Pruébalo en línea!


55
(.)(.*)(.)¿Es ese el emoticono de Total Recall?
MikeTheLiar

1
@MikeTheLiar Tipo de, supongo. : D
Arnauld

La asignación especifica que la cadena contiene el separador.
Cees Timmerman

@CeesTimmerman No estoy seguro de lo que quieres decir. Este código espera un salto de línea como separador y, por lo tanto, toma cadenas con saltos de línea como entrada. (El pie de página del enlace TIO convierte los espacios en saltos de línea y luego de nuevo a espacios para facilitar la lectura.)
Arnauld

"dada una cadena de caracteres ASCII alfabéticos , así como otro carácter para usar como delimitador (para separar cada palabra) " - Nm, pensé que era un parámetro separado.
Cees Timmerman

11

retina ,8 5 bytes

,V,,`

Pruébalo en línea!

¡Guardado 3 bytes gracias a Kevin Cruijssen !

Utiliza una nueva línea como separador. Hacemos uso de la etapa inversa de Retina y algunos límites. El primer límite es a qué coincidencias para aplicar la inversión, por lo que las elegimos todas ,. Luego, queremos intercambiar la primera y la última letra de cada coincidencia, por lo que tomamos cada letra en el rango ,,que se traduce en un rango desde el principio hasta el final con el tamaño de paso cero.


Dangit, solo estaba buscando en los documentos algo como esto para actualizar mi respuesta, pero me ganaste. Lo sabía V, pero no sabía que podría usarse con índices 1,-2como ese. ¡Buena esa!
Kevin Cruijssen

1
@KevinCruijssen Hice un poco de trampa y revisé cómo funcionaban los rangos de límite mientras estaba en el sandbox :) Todavía siento que debería haber una mejor manera que invertir un rango, pero no he podido encontrar nada más corto.
FryAmTheEggman

2
De hecho, tiene razón en que puede ser más corto sin un rango límite, porque parece que este 5 bytes funciona (dado como ejemplo en la parte inferior de los Límites de paso en los documentos).
Kevin Cruijssen

@KevinCruijssen ¡Agradable! No puedo creer que me haya perdido eso.
FryAmTheEggman

3
Entonces, ¿5 bytes y solo 3 caracteres diferentes? Eso es minimalista.
Coeur

9

Pepe , 107105 bytes

REEeREeeEeeeeerEEreREEEeREEEEEEeREEEErEEREEEEEEEreererEEEeererEEEerEEeERrEEEeerEEeerereeerEEEEeEEEReEeree

Pruébalo en línea!

Explicación:

Notación en comentarios: 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

¿Como funciona esto?
lirtosiast

Explicación de @lirtosiast agregada
u_ndefined


6

laskelH , 71 bytes

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

Pruébalo en línea!

Ejemplo en / salida:

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
La asignación en la wherecláusula se puede mover a un enlace en guardia para guardar 5 bytes: ¡ Pruébelo en línea!
Laikoni

1
Veo lo que hiciste allí con el nombre "Haskell" en el título. Hice lo mismo en mi respuesta PHP.
640 KB

5

05AB1E , 10 bytes

#vyRćsRćðJ

Pruébalo en línea!


-3 Gracias a @Kevin Cruijssen .

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


1
@KevinCruijssen Sinceramente, quiero eliminarlo y dárselo, eso fue 99% de su capacidad intelectual para ordenar los argumentos, jaja.
Urna de pulpo mágico

1
Encontré un 9-byter, pero solo funciona en la versión heredada:|ʒRćsRćJ,
Kevin Cruijssen

1
Lástima que no tengamos un loop_as_long_as_there_are_inputs, entonces hubiera conocido un 8-byter: sin embargo, [RćsRćJ,este 8-byter [nunca usa salidas en teoría, solo cuando no tiene memoria o se agota el tiempo como en TIO (y requiere un seguimiento nueva línea en la entrada, de lo contrario seguirá usando la última palabra) ..
Kevin Cruijssen

1
Desafortunadamente, necesita ð¡una entrada de una sola palabra, pero ð¡εćsÁì}ðýtambién funciona a 10 bytes.
Emigna

5

J , 23 17 bytes

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

Pruébalo en línea!


¡Muy buen truco para intercambiar las primeras / últimas letras girando y aplicando 1 A.!
Galen Ivanov

1
1&A.&.(1&|.)-> ({:,1|.}:)y luego se puede quitar el::]
NGN

Increíble, gracias
FrownyFrog

¡Realmente increíble! Una vez más, me sorprende lo simple y elegante que puede ser la solución, pero solo después de que otra persona la vea.
Galen Ivanov

4

Ruby con -p, 42 41 29 bytes

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

Pruébalo en línea!



@ Shaggy gracias por el aviso. Si miras el historial de mis publicaciones, muestra que estuve ausente durante 8 meses sin ninguna respuesta, por lo que es probable que me haya perdido algunas notas durante ese tiempo, jaja
Value Ink

Estoy bastante seguro de que el consenso cambió hace más de 8 meses, pero por si acaso te lo perdiste: "no competir" ya no es una cosa.
Shaggy

Bien hecho. Creo que, según las reglas, puede usar nuevas líneas como delimitador y reemplazar la \ws con .s.
histocrat





3

Espacio en blanco , 179 bytes

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

Letras S(espacio),TN agregaron (tabulación) y (nueva línea) solo como resaltado.
[..._some_action]agregado solo como explicación.

Tabulador como delimitador. La entrada debe contener una nueva línea (o pestaña) al final, de lo contrario el programa no sabe cuándo detenerse, ya que la entrada en el espacio en blanco solo se puede hacer un carácter a la vez.

Pruébalo en línea (solo con espacios en bruto, pestañas y nuevas líneas).

Explicación en pseudocódigo:

[0 0,...,longitud de palabra]

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

El programa termina con un error cuando intenta leer un carácter cuando no se proporciona ninguno en TIO (o se cuelga esperando una entrada en algunos compiladores de espacios en blanco como vii5ard ).


3

Wolfram Language (Mathematica) , 58 bytes

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

Pruébalo en línea!

-22 bytes de @attinat

-12 bytes de @ M.Stern


70 bytes usando StringReplacecon StringExpressions
attinat

1
64 bytes usando StringTake lugar de StringReplace:StringRiffle[StringSplit@##~StringTake~{{-1},{2,-2},{1}},#2,""]&
Roman

2
Aquí hay un enfoque más directo:StringReplace[#, a : u ~~ w : u .. ~~ b : u :> b <> w <> a /. {u -> Except@#2}] &
M. Stern

1
{y} son opcionales :)
M. Stern

1
55 bytes , también corrige palabras de 2 caracteres
attinat

2

QuadR , 20 bytes

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

Simplemente haga tres grupos de captura que consisten en 1, 0 o más y 1 caracteres de palabras, luego invierta su orden.

Pruébalo en línea!



2

Japt -S , 10 bytes

Convencido de que tiene que haber un enfoque más corto (y tenía razón ), pero esto lo hará por ahora.

¸ËhJDg)hDÌ

Intentalo

¸Ë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

Mucho más corto que mi 12 byter:¸®Ì+Zs1J +Zg
Encarnación de la ignorancia

@EmbodimentofIgnorance, ahí es donde comencé también, pero habría fallado en palabras de un solo carácter. Sin embargo, podría guardar un byte en eso con ¸®ÎiZÌ+Zs1J.
Shaggy

1
@EmbodimentofIgnorance Encontrado un byter 7
Oliver

2

sed, 64 bytes

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

Claro, podríamos usarlo en .lugar de [[:alpha:]], pero en realidad debería serlo [^ ], lo que lo reduce a 43, pero rompe con la puntuación y demás. El uso lo [a-zA-Z]lleva a 55, momento en el que estoy ansiando esas dulces, dulces entidades legibles para los humanos ...
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.En otras palabras, no necesita preocuparse por los signos de puntuación que "rompen" su código y simplemente puede hacerlo con seguridad [^ ];)
Value Ink

@ValueInk Sí, pero [^ ]debería ser lo [^[:space:]]que lo lleva a 67 caracteres.
Rico

"un delimitador" significa que puede asegurarse de que el delimitador sea siempre un espacio regular. ¿Quién usa las pestañas en una oración de todos modos?
Value Ink

Bueno. Parece que el "código de golf" es un juego en el que debes encontrar formas de hacer que un dron deje caer la pelota en el hoyo en lugar de hacer el trabajo. Gracias por la mierda de bienvenida.
Rico

2

sed , 34 bytes

Y presumiblemente, la idea del patrón funcionará con la mayoría de las herramientas RE (y sé que hay diferencias entre RE estándar y RE extendida).

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

Pruébalo en línea!


1
Bienvenido a PPCG! Creo que la naturaleza codiciosa de las coincidencias de expresiones regulares significa que puedes eliminar \bel partido: ¡ Pruébalo en línea!
Value Ink

Acepté @ValueInk, pero estaba siendo precisa con la coincidencia. Eliminarlo \bconducirá a 30 bytes.
PJF

Use -E para expresiones regulares avanzadas y puede usar paréntesis sin escape. Úselo .para los caracteres intercambiados y puede perder otros dos caracteres. Esto reduce el suyo a 26 bytes; Una de las soluciones legibles más pequeñas. s,\b(.)(\w*)(.)\b,\3\2\1,g
Rico

1
- No, me equivoco, necesitas la \ws al final. s,\b(\w)(\w*)(\w)\b,\3\2\1,g28 caracteres
Rico

Buen trabajo @rich, pero como dije, sé acerca de RE estándar y extendido. Simplemente elegí hacerlo estándar y legible. Se requerirían las anclas que no mencioné en mi respuesta a ValueInk.
PJF

2

Ruby, 53 bytes

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

Lo intenté sin expresiones regulares. La salida imprime cada palabra en una nueva línea. Si eso va en contra de las reglas, avíseme y lo arreglaré.

Sin golf:

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

Bienvenido a PPCG! Imprimir cada palabra en una nueva línea debería estar bien, pero su solución anterior pno era buena porque eso agregaba comillas a la salida. Siempre se puede usar putsen su lugar, ya que agrega automáticamente la nueva línea y es más corta que print! Además, si llama splitsin argumentos, se divide automáticamente en espacios.
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

Desmontado:

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 

PC independiente ejecutable de DOS. Entrada a través de la línea de comando args, salida a la pantalla.

ingrese la descripción de la imagen aquí

Descargue y pruebe PWAS.COM .



1

Lote, 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%

Toma datos como parámetros de línea de comandos. La manipulación de cadenas es extrema en Batch en el mejor de los casos, y tener que usar palabras especiales de una sola letra no ayuda.





1

Haskell , 75 74 bytes

Se corrigió un error señalado por Cubic y también bajó 1 byte.

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

Pruébalo en línea!


map ges más corto que(g<$>)
Cubic

1
Además, si observa su caso de prueba, verá que no funciona para palabras de una letra, se convierte aenaa
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

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

La entrada se realiza a través de una tabla t preexistente con campo varchar v , según nuestros estándares IO .

Leyendo de atrás hacia adelante, STRING_SPLITdivide una cadena en filas individuales mediante un delimitador, STUFFmodifica los caracteres en las posiciones especificadas y luego STRING_AGGlos vuelve a unir.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.