pwaS eht tirsf dna tasl setterl para hace dorw

30

Ou "Troque a primeira e a última letras de cada palavra"

Seu desafio é, dada uma sequência de caracteres alfabéticos ASCII e outro caractere para usar como delimitador (para separar cada palavra), trocar a primeira e a última letra de cada palavra. Se houver uma palavra de um caractere, deixe-a em paz.

Os exemplos / casos de teste usam as letras minúsculas e o espaço como delimitador.

Você não precisa lidar com pontuação; todas as entradas consistirão apenas nas letras de a a z, separadas por um delimitador, em maiúsculas e minúsculas.

Por exemplo, com a cadeia "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"

NOTA: o delimitador não precisa ser inserido separadamente. O delimitador é apenas o caractere usado para separar as palavras. Pode ser qualquer coisa. Eu queria deixar opções em aberto para jogadores criativos, por isso não queria limitá-la apenas a espaços ou novas linhas. O delimitador é apenas um caractere que separa as palavras na sequência de entrada.

Casos de teste:

"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"
Camarada SparklePony
fonte
3
Como a pontuação deve ser tratada? Hello, world!torna-se ,elloH !orldw(trocando pontuação como uma letra) ou oellH, dorlw!(mantendo a pontuação no lugar)?
Phelype Oleinik
3
@PhelypeOleinik Você não precisa lidar com pontuação; todas as entradas consistirão apenas nas letras de a a z e em maiúsculas e minúsculas.
Camarada SparklePony
4
O segundo parágrafo lê , bem como um outro caractere para usar como delimitador, enquanto o quarto lê separado por espaços . Qual é esse?
Adám
@ Adám Qualquer caractere não alfabético. Vou editar para esclarecer.
Camarada SparklePony
1
@BenjaminUrquhart Yes. Você pode considerar a entrada como argumento de função, se desejar.
Camarada SparklePony

Respostas:

59

TeX, 216 bytes (4 linhas, 54 caracteres cada)

Porque não se trata da contagem de bytes, é sobre a qualidade da saída digitada :-)

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

Experimente Online! (No verso; não tenho certeza de como funciona)

Arquivo de teste 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

Saída:

insira a descrição da imagem aqui


Para o LaTeX, você só precisa do padrão:

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

Explicação

TeX é uma fera estranha. Ler o código normal e entendê-lo é um feito por si só. Compreender o código TeX ofuscado vai alguns passos adiante. Vou tentar tornar isso compreensível para as pessoas que também não conhecem o TeX. Portanto, antes de começar, aqui estão alguns conceitos sobre o TeX para facilitar o acompanhamento:

Para iniciantes (não tão) absolutos em TeX

  • Primeiro, e o item mais importante nesta lista: o código não precisa estar em forma de retângulo, mesmo que a cultura pop possa levá-lo a pensar isso .

  • TeX é uma linguagem de expansão de macro. Você pode, por exemplo, definir \def\sayhello#1{Hello, #1!}e escrever \sayhello{Code Golfists}para fazer o TeX imprimir Hello, Code Golfists!. Isso é chamado de “macro não limitada” e, para alimentá-lo como o primeiro (e único, neste caso) parâmetro, você o coloca entre chaves. O TeX remove esses chavetas quando a macro pega o argumento. Você pode usar até 9 parâmetros: \def\say#1#2{#1, #2!}então \say{Good news}{everyone}.

  • A contrapartida de macros undelimited são, sem surpresa, os delimitado :) Você poderia fazer a definição anterior um pouco mais semântico : \def\say #1 to #2.{#1, #2!}. Nesse caso, os parâmetros são seguidos pelo chamado texto do parâmetro . Esse texto de parâmetro delimita o argumento da macro ( #1é delimitado por ␣to␣, espaços incluídos e #2delimitado por .). Após essa definição, você pode escrever \say Good news to everyone.e expandir para Good news, everyone!. Legal, não é? :) No entanto, um argumento delimitado é (citando o TeXbook ) "a sequência mais curta (possivelmente vazia) de tokens com {...}grupos aninhados corretamente que é seguida na entrada por esta lista específica de tokens sem parâmetros". Isso significa que a expansão de\say Let's go to the mall to Martinproduzirá uma frase estranha. Neste caso, você precisa de “esconder” o primeiro ␣to␣com {...}: \say {Let's go to the mall} to Martin.

  • Por enquanto, tudo bem. Agora as coisas começam a ficar estranhas. Quando o TeX lê um caractere (que é definido por um "código de caractere"), ele atribui a esse caractere um "código de categoria" (código de categoria para amigos :) que define o que esse caractere significa. Essa combinação de código de caractere e categoria cria um token (mais sobre isso aqui , por exemplo). Os que nos interessam aqui são basicamente:

    • catcode 11 , que define tokens que podem compor uma sequência de controle (um nome elegante para uma macro). Por padrão, todas as letras [a-zA-Z] são catcode 11, para que eu possa escrever \hello, que é uma única sequência de controle, enquanto \he11oé a sequência de controle \heseguida por dois caracteres 1, seguida pela letra o, porque 1não é o código 11. Se eu a \catcode`1=11partir desse momento \he11oseria uma sequência de controle. Uma coisa importante é que os códigos de código são definidos quando o TeX vê o personagem pela primeira vez, e esse código de código é congelado ... PARA SEMPRE! (Termos e condições podem ser aplicadas)

    • catcode 12 , que são a maioria dos outros caracteres, como 0"!@*(?,.-+/e assim por diante. Eles são o tipo menos especial de código de gato, pois servem apenas para escrever coisas no papel. Mas ei, quem usa o TeX para escrever?!? (novamente, termos e condições podem ser aplicados)

    • catcode 13 , que é o inferno :) Realmente. Pare de ler e faça algo fora de sua vida. Você não quer saber o que é o catcode 13. Já ouviu falar da sexta-feira, 13? Adivinhe de onde veio esse nome! Continue por sua conta e risco! Um caractere catcode 13, também chamado de "ativo", não é mais apenas um personagem, é uma macro em si! Você pode defini-lo para ter parâmetros e expandir para algo como vimos acima. Depois que \catcode`e=13você acha que pode fazer \def e{I am the letter e!}, MAS. VOCÊS. NÃO PODES! enão é mais uma carta, então \defnão é o que \defvocê sabe, é \d e f! Oh, escolha outra letra que você diz? OK! \catcode`R=13 \def R{I am an ARRR!}. Muito bem, Jimmy, tente! Ouso fazer isso e escrevo um Rno seu código! Isso é o que é um código de gato 13. EU ESTOU CALMO! Vamos continuar.

  • Ok, agora ao agrupamento. Isso é bastante direto. Quaisquer que sejam as atribuições ( \defé uma operação de atribuição \let(entraremos nela)) são feitas em um grupo e são restauradas para o que eram antes do início do grupo, a menos que a atribuição seja global. Existem várias maneiras de iniciar grupos, um deles com os códigos de gato 1 e 2 (oh, códigos de gato novamente). Por padrão, {é catcode 1, ou begin-group, e }é catcode 2, ou end-group. Um exemplo: \def\a{1} \a{\def\a{2} \a} \aIsso imprime 1 2 1. Fora do grupo \aestava 1, em seguida, foi redefinido para dentro 2e, quando o grupo terminou, foi restaurado para 1.

  • A \letoperação é outra operação de atribuição como \def, mas bastante diferente. Com \defvocê, defina macros que serão expandidas para outras coisas, e \letcrie cópias de coisas já existentes. Após \let\blub=\def(o =é opcional), você pode alterar o início do eexemplo do item de código de gato 13 acima para \blub e{...e se divertir com esse. Ou melhor, em vez de quebrar coisas que você pode corrigir (se você olhar para isso!) O Rexemplo: \let\newr=R \catcode`R=13 \def R{I am an A\newr\newr\newr!}. Pergunta rápida: você poderia renomear para \newR?

  • Finalmente, os chamados "espaços espúrios". Esse é um tópico tabu, porque há pessoas que afirmam que a reputação conquistada no TeX - LaTeX Stack Exchange , respondendo a perguntas de "espaços espúrios", não deve ser considerada, enquanto outras discordam de todo o coração. Com quem você concorda? Faça suas apostas! Enquanto isso: o TeX entende uma quebra de linha como um espaço. Tente escrever várias palavras com uma quebra de linha (não uma linha vazia ) entre elas. Agora adicione um %no final dessas linhas. É como se você estivesse “comentando” esses espaços de fim de linha. É isso aí :)

(Mais ou menos) desregulamentando o código

Vamos tornar esse retângulo em algo (sem dúvida) mais 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 }
}

Explicação de cada etapa

cada linha contém uma única instrução. Vamos um por um, dissecando-os:

{
Primeiro, iniciamos um grupo para manter algumas alterações (ou seja, alterações no código do gato) local, para que elas não atrapalhem o texto de entrada.

\let~\catcode
Basicamente, todos os códigos de ofuscação TeX começam com esta instrução. Por padrão, no TeX e no LaTeX, o ~caractere é o caractere ativo que pode ser transformado em macro para uso posterior. E a melhor ferramenta para esquisitificar o código TeX são as alterações no código do gato, portanto essa geralmente é a melhor escolha. Agora, em vez de \catcode`A=13podermos escrever ~`A13(o =é opcional):

~`A13
Agora a letra Aé um caractere ativo, e podemos defini-la para fazer algo:

\defA#1{~`#113\gdef}
Aagora é uma macro que recebe um argumento (que deve ser outro caractere). Primeiro, o código do argumento é alterado para 13 para torná-lo ativo: ~`#113(substitua ~por \catcodee adicione um =e você tem :) \catcode`#1=13. Finalmente, deixa um \gdef(global \def) no fluxo de entrada. Em resumo, Aativa outro personagem e inicia sua definição. Vamos tentar:

AGG#1{~`#113\global\let}
AGprimeiro "ativa" Ge faz \gdef, que seguido pelo próximo Ginicia a definição. A definição de Gé muito semelhante à de A, exceto que, em vez disso \gdef, faz a \global\let(não há \gletcomo o \gdef). Em resumo, Gativa um personagem e faz com que seja outra coisa. Vamos criar atalhos para dois comandos que usaremos mais adiante:

GFF\else
GHH\fi
Agora, em vez de \elsee \fipodemos simplesmente usar Fe H. Muito mais curto :)

AQQ{Q}
Agora usamos Anovamente para definir outra macro Q,. A declaração acima basicamente funciona (em um idioma menos ofuscado) \def\Q{\Q}. Esta não é uma definição muito interessante, mas tem um recurso interessante. A menos que você queira quebrar algum código, a única macro que se expande Qé Qela mesma, então ela age como um marcador exclusivo (é chamado de quark ). Você pode usar o \ifxcondicional para testar se o argumento de uma macro é tão quark com \ifx Q#1:

AII{\ifxQ}
para ter certeza de que encontrou esse marcador. Observe que nesta definição eu removi o espaço entre \ifxe Q. Normalmente, isso levaria a um erro (observe que o destaque da sintaxe acha que isso \ifxQé uma coisa), mas como agora Qé o código de código 13, não pode formar uma sequência de controle. Tenha cuidado, no entanto, para não expandir esse quark ou você ficará preso em um loop infinito, porque se Qexpande para Qqual se expande para Qqual ...

Agora que as preliminares estão concluídas, podemos ir ao algoritmo apropriado para pwas eht setterl. Devido à tokenização do TeX, o algoritmo deve ser escrito ao contrário. Isso ocorre porque, no momento em que você faz uma definição, o TeX tokeniza (atribui códigos de gato) aos caracteres na definição usando as configurações atuais; por exemplo, se eu fizer:

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

a saída é E1, enquanto que se eu alterar a ordem das definições:

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

a saída é 11. Isso ocorre porque no primeiro exemplo E, a definição foi simbolizada como uma letra (código 11) antes da alteração do código, portanto sempre será uma letra E. No segundo exemplo, no entanto, Efoi ativado pela primeira vez e somente então \onefoi definido, e agora a definição contém o código de gato 13 ao Equal se expande 1.

No entanto, ignorarei esse fato e reordenarei as definições para ter uma ordem lógica (mas não funcionando). Nos parágrafos seguintes, você pode assumir que as letras B, C, D, e Esão ativos.

\gdef\S#1{\iftrueBH#1 Q }
(observe que houve um pequeno bug na versão anterior, ele não continha o espaço final na definição acima. Eu só o notei enquanto escrevia isso. Continue lendo e você verá por que precisamos desse para finalizar corretamente a macro. )
Primeiro, definimos a macro no nível do usuário \S,. Esse não deve ser um caractere ativo para ter uma sintaxe amigável (?); Portanto, a macro para gwappins eht setterl é \S. A macro começa com uma condicional sempre verdadeira \iftrue(em breve ficará claro o porquê) e depois chama a Bmacro seguida por H(que definimos anteriormente \fi) para corresponder a \iftrue. Então deixamos o argumento da macro #1seguido por um espaço e pelo quark Q. Suponha que usamos \S{hello world}, então o fluxo de entradadeve ficar assim: \iftrue BHhello world Q␣(Substituí o último espaço por um para que a renderização do site não o coma, como fiz na versão anterior do código). \iftrueé verdade, então se expande e nos resta BHhello world Q␣. O TeX não remove o \fi( H) depois que a condicional é avaliada; em vez disso, deixa-o lá até que ele \fiseja realmente expandido. Agora a Bmacro está expandida:

ABBH#1 {HI#1FC#1|BH}
Bé uma macro delimitada cujo texto do parâmetro é H#1␣, portanto, o argumento é o que estiver entre He um espaço. Continuando o exemplo acima do fluxo de entrada antes da expansão de Bis BHhello world Q␣. Bé seguido por H, como deveria (caso contrário, o TeX geraria um erro), então o próximo espaço é entre helloe world, assim #1é a palavra hello. E aqui temos que dividir o texto de entrada nos espaços. Yay: D A expansão da Bremove tudo acima para o primeiro espaço a partir do fluxo de entrada e substitui por HI#1FC#1|BHcom #1sendo hello: HIhelloFChello|BHworld Q␣. Observe que há um novo BHposteriormente no fluxo de entrada para fazer uma recursão final deBe processe palavras posteriores. Depois que essa palavra é processada, Bprocessa a próxima palavra até que a palavra a ser processada seja o quark Q. O último espaço a seguir Qé necessário porque a macro delimitada B requer um no final do argumento. Com a versão anterior (consulte o histórico de edições), o código se comportaria mal se você o usasse \S{hello world}abc abc(o espaço entre os abcs desapareceria).

OK, de volta para o fluxo de entrada: HIhelloFChello|BHworld Q␣. Primeiro, há o H( \fi) que completa a inicial \iftrue. Agora temos o seguinte (pseudocodificado):

I
  hello
F
  Chello|B
H
world Q␣

O I...F...Hpensamento é realmente uma \ifx Q...\else...\fiestrutura. O \ifxteste verifica se o (primeiro símbolo da) palavra capturada é o Qquark. Se é não há mais nada a fazer e os termina a execução, caso contrário, o que resta é: Chello|BHworld Q␣. Agora Cé expandido:

ACC#1#2|{D#2Q|#1 }
O primeiro argumento de Cse não delimitado, de modo a não ser que se preparou-lo será um único modo, o segundo argumento é delimitado por |, assim, após a expansão de C(com #1=he #2=ello) o fluxo de entrada é: DelloQ|h BHworld Q␣. Observe que outro |é colocado lá, e o hde helloé colocado depois disso. Metade da troca é feita; a primeira letra está no final. No TeX, é fácil pegar o primeiro token de uma lista de tokens. Uma macro simples \def\first#1#2|{#1}recebe a primeira letra quando você usa \first hello|. O último é um problema, porque o TeX sempre pega a lista de tokens “menor, possivelmente vazia” como argumento, por isso precisamos de algumas soluções alternativas. O próximo item na lista de tokens é D:

ADD#1#2|{I#1FE{}#1#2|H}
Essa Dmacro é uma das soluções alternativas e é útil no único caso em que a palavra tem uma única letra. Suponha que ao invés de hellonós tivéssemos x. Neste caso o fluxo de entrada seria DQ|x, em seguida, Dse expandir (com #1=Q, e #2esvaziar) a: IQFE{}Q|Hx. Isso é semelhante ao bloco I...F...H( \ifx Q...\else...\fi) B, que verá que o argumento é o quark e interromperá a execução, deixando apenas xpara a digitação. Em outros casos (voltando ao helloexemplo), Dseria expandir (com #1=ee #2=lloQ) para: IeFE{}elloQ|Hh BHworld Q␣. Novamente, o I...F...Hirá verificar se há Q, mas irá falhar e levar o \elseramo: E{}elloQ|Hh BHworld Q␣. Agora, o último pedaço dessa coisa, oE a macro expandiria:

AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
O texto do parâmetro aqui é bastante semelhante a Ce D; o primeiro e o segundo argumentos não são limitados e o último é delimitado por |. A aparência do fluxo de entrada, como este: E{}elloQ|Hh BHworld Q␣, em seguida, Eexpande-se (com #1vazio, #2=e, e #3=lloQ): IlloQeFE{e}lloQ|HHh BHworld Q␣. Outro I...F...Hbloco de cheques para o quark (que vê le volta false): E{e}lloQ|HHh BHworld Q␣. Agora Ese expande novamente (com #1=evazio, #2=le #3=loQ): IloQleFE{el}loQ|HHHh BHworld Q␣. E mais uma vez I...F...H. A macro faz mais algumas iterações até que Qfinalmente seja encontrada e a trueramificação seja obtida: E{el}loQ|HHHh BHworld Q␣-> IoQlelFE{ell}oQ|HHHHh BHworld Q␣-> E{ell}oQ|HHHHh BHworld Q␣-> IQoellFE{ello}Q|HHHHHh BHworld Q␣. Agora, o quark é encontrado e se expande condicionais para: oellHHHHh BHworld Q␣. Ufa.

Oh, espere, o que são esses? CARTAS NORMAIS? Oh garoto! As letras estão finalmente encontrado e TeX escreve para baixo oell, em seguida, um monte de H( \fi) são encontrados e expandido (ou nada), deixando o fluxo de entrada com: oellh BHworld Q␣. Agora, a primeira palavra tem a primeira e a última letras trocadas e o que o TeX encontra a seguir é o outro Bpara repetir todo o processo para a próxima palavra.

}
Finalmente, terminamos o grupo iniciado lá, para que todas as tarefas locais sejam desfeitas. As atribuições locais são as mudanças catcode das letras A, B, C, ... que foram feitas macros para que eles retornam à sua carta significado normal e pode ser usado com segurança no texto. E é isso. Agora, a \Smacro definida lá atrás acionará o processamento do texto como acima.

Uma coisa interessante sobre esse código é que ele é totalmente expansível. Ou seja, você pode usá-lo com segurança na movimentação de argumentos sem se preocupar com a explosão. Você pode até usar o código para verificar se a última letra de uma palavra é igual à segunda (por qualquer motivo que você precise) em um \ifteste:

\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

Desculpe pela (provavelmente muito) explicação detalhada. Tentei deixar o mais claro possível também para os não TeXies :)

Resumo para o impaciente

A macro \Sprecede a entrada com um caractere ativo Bque pega listas de tokens delimitadas por um espaço final e as passa para C. Cpega o primeiro token nessa lista e o move para o final da lista de tokens e expande Dcom o que resta. Dverifica se "o que resta" está vazio; nesse caso, uma palavra de uma letra foi encontrada, então não faça nada; caso contrário, se expande E. Epercorre a lista de tokens até encontrar a última letra da palavra, quando é encontrada deixa a última letra, seguida pelo meio da palavra, seguida pela primeira letra deixada no final do fluxo de tokens por C.

Phelype Oleinik
fonte
2
Eu adoraria uma explicação completa deste. Estou muito curioso para saber como funciona!
LambdaBeta
1
@LambdaBeta Eu posso fazer isso, mas não agora. Espere e eu vou fazer ping quando você fizer :) :)
Phelype Oleinik
1
@LambdaBeta Done! Desculpe, às vezes sou muito prolixo :-)
Phelype Oleinik
13

JavaScript (ES6),  39  36 bytes

Guardado 3 bytes graças a @FryAmTheEggman

Usa um avanço de linha como separador.

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

Experimente online!

Arnauld
fonte
5
(.)(.*)(.)é esse emoticon Total Recall?
MikeTheLiar
1
@MikeTheLiar Mais ou menos, eu acho. : D
Arnauld
A atribuição especifica que a sequência contém o separador.
Cees Timmerman
@CeesTimmerman Não sei o que você quer dizer. Esse código espera um avanço de linha como separador e, portanto, recebe seqüências de caracteres com avanço de linha como entrada. (O rodapé do link TIO converte espaços em feeds de linha e depois volta a espaços para facilitar a leitura.)
Arnauld
"dada uma sequência de caracteres ASCII alfabéticos , bem como outro caractere para usar como delimitador (para separar cada palavra) " - Nm, eu pensei que era um parâmetro separado.
Cees Timmerman
11

Retina ,8 5 bytes

,V,,`

Experimente online!

Guardado 3 bytes graças a Kevin Cruijssen !

Usa uma nova linha como separador. Utilizamos o estágio reverso da Retina e alguns limites. O primeiro limite é o que corresponde ao qual aplicar a reversão, por isso escolhemos todos eles ,. Então, queremos que a primeira e a última letra de cada correspondência sejam trocadas, para que cada letra seja ,,convertida em um intervalo do começo ao fim com o tamanho da etapa zero.

FryAmTheEggman
fonte
Dangit, eu estava apenas pesquisando nos documentos algo assim para atualizar minha resposta, mas você me venceu. Eu sabia V, mas não sabia que poderia ser usado com índices 1,-2assim. Agradável!
Kevin Cruijssen
1
@KevinCruijssen Eu trapacei um pouco e revi como os intervalos de limite funcionavam enquanto isso estava na caixa de areia :) Ainda sinto que deveria haver uma maneira melhor do que inverter um intervalo, mas não consegui encontrar nada mais curto.
FryAmTheEggman
2
Você está realmente certo de que pode ser mais curto sem um intervalo de limite, porque parece que esse número de 5 bytes funciona (dado como exemplo na parte inferior dos Limites de Etapas nos documentos).
Kevin Cruijssen
@KevinCruijssen Nice! Não acredito que perdi isso.
FryAmTheEggman
3
Então, 5 bytes e apenas 3 caracteres diferentes? Isso é minimalista.
Cœur
9

Pepe , 107 105 bytes

REEeREeeEeeeeerEEreREEEeREEEEEEeREEEErEEREEEEEEEreererEEEeererEEEerEEeERrEEEeerEEeerereeerEEEEeEEEReEeree

Experimente online!

Explicação:

Notação nos comentários: 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
Indefinido
fonte
Como é que isso funciona?
lirtosiast
@lirtosiast explanação adicionada
u_ndefined
7

Python 3 , 72 58 bytes

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

Experimente online!

alexz02
fonte
Não funciona para palavras com uma letra (por exemplo a)
TFeld
@TFeld, fixed ..
alexz02
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

Experimente online!

Exemplo de entrada / saída:

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
```
Cúbico
fonte
1
A atribuição na wherecláusula pode ser movida para uma ligação em guarda para economizar 5 bytes: Experimente online!
Laikoni
1
Eu vejo o que você fez lá com o nome "Haskell" no título. Eu fiz a mesma coisa na minha resposta PHP.
640KB
5

05AB1E , 10 bytes

#vyRćsRćðJ

Experimente online!


-3 Agradecimentos a @Kevin Cruijssen .

#           | Split into words.
 vy         | For each word...
   RćsRć    | Reverse, split head, swap, reverse, split tail
        ðJ  | Join by spaces.
Urna de polvo mágico
fonte
1
10 bytes
Kevin Cruijssen
1
@KevinCruijssen Sinceramente, quero excluí-lo e entregá-lo a você, que foi 99% da sua capacidade intelectual para ordenar os argumentos, haha.
Magic Octopus Urn
1
Encontrei um 9-byter, mas ele só funciona na versão legacy:|ʒRćsRćJ,
Kevin Cruijssen
1
Pena que não temos um loop_as_long_as_there_are_inputs, então eu teria conhecido um 8-byter: [RćsRćJ,Este 8-byter [nunca usa saídas na teoria, no entanto, apenas quando você está com falta de memória ou com um tempo limite como no TIO (e isso requer um rastreamento). nova linha na entrada, caso contrário continuará usando a última palavra) ..
Kevin Cruijssen
1
Infelizmente, você precisa ð¡que a entrada de uma única palavra seja possível, mas ð¡εćsÁì}ðýtambém funciona com 10 bytes.
Emigna
5

J , 23 17 bytes

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

Experimente online!

FrownyFrog
fonte
Truque muito bom para trocar as primeiras / últimas letras girando e aplicando 1 A.!
Galen Ivanov
1
1&A.&.(1&|.)-> ({:,1|.}:)e, em seguida, você pode remover o::]
ngn
Incrível, obrigado
FrownyFrog
Realmente incrível! Mais uma vez, fico impressionada com o quão simples e elegante pode ser a solução, mas somente depois que a vejo feita por outra pessoa.
Galen Ivanov
4

Ruby com -p, 42 41 29 bytes

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

Experimente online!

Value Ink
fonte
@ Shaggy obrigado pela atenção. Se você olhar para o meu histórico de postagens, isso mostra que fiquei 8 meses sem respostas, então provavelmente perdi alguns memorandos durante esse período, haha
Value Ink
Certamente o consenso foi alterado há mais de 8 meses, mas caso você tenha perdido: "não competir" também não é mais uma coisa.
Shaggy
Bem feito. Acho que, de acordo com as regras, você pode usar novas linhas como seu delimitador e substituir os \wpor .s.
histocrat
4

Haskell, 54 bytes

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

Experimente online!

nimi
fonte
4

Japonês -S , 7 bytes

¸®ÎiZÅé

Tente

Oliver
fonte
1
Agradável! Eu sabia que haveria um caminho mais curto.
Shaggy
1
Eu estou impressionado. Bem feito
Modalidade de Ignorância
3

Espaço em branco , 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(espaço), T(tabulação) e N(nova linha) adicionadas apenas como destaque.
[..._some_action]adicionado apenas como explicação.

Guia como delimitador. A entrada deve conter uma nova linha (ou guia) à direita, caso contrário, o programa não sabe quando parar, pois a entrada no espaço em branco só pode ser executada um caractere de cada vez.

Experimente online (apenas com espaços brutos, tabulações e novas linhas).

Explicação em pseudo-código:

[0 0,...,comprimento da palavra]

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

O programa termina com um erro quando tenta ler um caractere quando nenhum é fornecido no TIO (ou fica aguardando uma entrada em alguns compiladores do Whitespace, como o vii5ard ).

Kevin Cruijssen
fonte
3

Wolfram Language (Mathematica) , 58 bytes

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

Experimente online!

-22 bytes de @attinat

-12 bytes de @ M.Stern

J42161217
fonte
70 bytes usando StringReplacecom StringExpressions
attinat
1
64 bytes usando em StringTakevez de StringReplace:StringRiffle[StringSplit@##~StringTake~{{-1},{2,-2},{1}},#2,""]&
Roman
2
Aqui está uma abordagem mais direta:StringReplace[#, a : u ~~ w : u .. ~~ b : u :> b <> w <> a /. {u -> Except@#2}] &
M. Stern
1
{e} são opcionais :)
M. Stern
1
55 bytes , também corrige palavras de 2 caracteres
attinat
2

QuadR , 20 bytes

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

Simplesmente faça três grupos de captura que consistem em 1, 0 ou mais e 1 palavra e depois inverta a ordem deles.

Experimente online!

Adão
fonte
2

Japonês -S , 10 bytes

Convencido de que deve haver uma abordagem mais curta (e eu estava certo ), mas isso servirá por enquanto.

¸ËhJDg)hDÌ

Tente

¸Ë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
Shaggy
fonte
Muito menor do que o meu 12 byter:¸®Ì+Zs1J +Zg
Modalidade de Ignorância
@EmbodimentofIgnorance, foi aí que eu comecei também, mas teria falhado nas palavras de um único caractere. Você pode salvar um byte nisso, no entanto, com ¸®ÎiZÌ+Zs1J.
Shaggy
1
@EmbodimentofIgnorance Encontrei 7 byter
Oliver
2

sed, 64 bytes

sed -E 's/\b([[:alpha:]])([[:alpha:]]*)([[:alpha:]])\b/\3\2\1/g'
Rico
fonte
Claro, poderíamos usar em .vez de [[:alpha:]], mas teria que ser [^ ], o que reduz para 43, mas quebra na pontuação e tal. O uso [a-zA-Z]aumenta para 55, altura em que estou apenas desejando aquelas entidades doces e agradáveis ​​de leitura humana ...
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.Em outras palavras, você não precisa se preocupar com a pontuação "violando" seu código e pode ir com segurança [^ ];)
Value Ink
@ ValueInk Sim, mas [^ ]deve ser o [^[:space:]]que o leva a 67 caracteres.
Rich
"um delimitador" significa que você pode garantir que o delimitador seja sempre um espaço regular. Quem usa tabs em uma frase de qualquer maneira ??
Value Ink
OK. Parece que "code golf" é um jogo em que você deve encontrar maneiras de fazer com que um drone jogue a bola no buraco em vez de realmente fazer o trabalho. Obrigado pela merda de boas-vindas.
Rich
2

sed , 34 bytes

E, presumivelmente, a ideia do padrão funcionará com a maioria das ferramentas de ER (e eu sei que existem diferenças entre o ER padrão e o ER estendido).

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

Experimente online!

PJF
fonte
1
Bem-vindo ao PPCG! Parece que a natureza gananciosa das correspondências regex significa que você pode cortar a \bpartir da correspondência: Experimente on-line!
Value Ink
Concordou com @ValueInk - mas eu estava sendo preciso com a partida. A remoção do arquivo \bresultará em 30 bytes.
PJF
Use -E para regex avançado e você pode usar parênteses sem escape. Use .para os caracteres trocados e você poderá perder outros dois caracteres. Isso reduz o seu para 26 bytes; uma das menores soluções legíveis. s,\b(.)(\w*)(.)\b,\3\2\1,g
Rich
1
- Não, eu estou errado, você precisa dos \ws nos extremos. s,\b(\w)(\w*)(\w)\b,\3\2\1,g28 caracteres.
Rich
Bom trabalho @rich, mas como eu disse, eu sei sobre RE padrão e estendido. Eu apenas escolhi torná-lo padrão e legível. Seriam necessárias as âncoras que eu deixei de mencionar na minha resposta ao ValueInk.
PJF
2

Ruby, 53 bytes

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

Eu tentei sem regex. A saída imprime cada palavra em uma nova linha. Se isso for contra as regras, avise-me e eu o corrigirei.

Ungolfed:

gets.split(" ").map {|z|
    print z[-1] + z[1..-2] + z[0], " "
}
83338
fonte
Bem-vindo ao PPCG! Imprimir cada palavra em uma nova linha deve ser bom, mas sua solução antiga pnão era boa, porque isso adicionava aspas à saída. Você sempre pode usar, putspois ele anexa automaticamente a nova linha e é menor que print! Além disso, se você chamar splitsem argumentos, ele será dividido automaticamente em espaços.
Value Ink
2

Conjunto 8088, 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 

Executável autônomo do PC DOS. Entrada via linha de comando args, saída para tela.

insira a descrição da imagem aqui

Faça o download e teste o PWAS.COM .

640KB
fonte
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%

Recebe a entrada como parâmetros da linha de comando. A manipulação de strings é péssima no Lote, na melhor das hipóteses, e ter que usar letras maiúsculas e minúsculas não ajuda.

Neil
fonte
1

C # (compilador interativo do Visual C #) , 90 bytes

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

Usa nova linha como delimitador, embora realmente possa ser usado qualquer espaço em branco.

Experimente online!

Modalidade de ignorância
fonte
SelectMany (isto é, mapear e nivelar) por 84 bytes, mas gera um único espaço à direita. Experimente online!
meu pronome é monicareinstate
1

Java, 110 109 bytes

-1 bytes usando uma nova linha para um delímetro

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
fonte
Isso funciona para palavras de uma letra?
Neil
@ Neil não, porque eu sou ruim. Eu vou consertar mais tarde.
Benjamin Urquhart
109 usando a nova linha como delimitador
Modalidade de ignorância
1

Haskell , 75 74 bytes

Corrigido um bug apontado pelo Cubic e também reduzia em 1 byte.

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

Experimente online!

Max Yekhlakov
fonte
map gé mais curto que(g<$>)
Cúbico
1
Além disso, se você olhar para o seu caso de teste, verá que ele não funciona com palavras de uma letra, ele se atransformaaa
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
Ensaboado
fonte
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),' ')

A entrada é feita através de uma tabela preexistente t com o campo varchar v , de acordo com nossos padrões de IO .

A leitura de trás para frente, STRING_SPLITdivide uma sequência em linhas individuais por meio de um delimitador, STUFFmodifica os caracteres nas posições especificadas e depois STRING_AGGos junta novamente.

BradC
fonte