pwaS eht tirsf dna tasl setterl fo hace dorw


30

Oppure "Scambia la prima e l'ultima lettera di ogni parola"

La tua sfida è, data una stringa di caratteri alfabetici ASCII e un altro carattere da usare come delimitatore (per separare ogni parola), scambiare la prima e l'ultima lettera di ogni parola. Se c'è una parola di un carattere, lasciarla sola.

Gli esempi / testcase usano le lettere minuscole e lo spazio come delimitatore.

Non è necessario gestire la punteggiatura; tutti gli input saranno costituiti solo dalle lettere dalla a alla z, separate da un delimitatore, tutto in un caso uniforme.

Ad esempio, con la stringa "ciao mondo":

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: il delimitatore non deve essere inserito separatamente. Il delimitatore è solo il carattere utilizzato per separare le parole. Può essere qualsiasi cosa. Volevo lasciare le opzioni aperte per i golfisti creativi, quindi non volevo limitarlo a soli spazi o nuove linee. Il delimitatore è solo un carattere che separa le parole nella stringa di input.

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

3
Come deve essere trattata la punteggiatura? Hello, world!diventa ,elloH !orldw(scambiando punteggiatura come una lettera) o oellH, dorlw!(mantenendo la punteggiatura in posizione)?
Phelype Oleinik,

3
@PhelypeOleinik Non è necessario gestire la punteggiatura; tutti gli input saranno costituiti solo dalle lettere dalla a alla z e da un caso uniforme.
Compagno SparklePony,

4
Il secondo paragrafo legge così come un altro carattere da utilizzare come delimitatore mentre il quarto legge separato da spazi . Qual é?
Adám,

@ Adám Qualsiasi carattere non alfabetico. Modificherò per chiarire.
Compagno SparklePony,

1
@BenjaminUrquhart Sì. Se lo desideri, puoi prendere input come argomento di funzione.
Compagno SparklePony,

Risposte:


59

TeX, 216 byte (4 righe, 54 caratteri ciascuno)

Poiché non si tratta del conteggio dei byte, si tratta della qualità dell'output composto :-)

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

Provalo online! (Sul retro; non sono sicuro di come funzioni)

File di test 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

Produzione:

inserisci qui la descrizione dell'immagine


Per LaTeX hai solo bisogno della piastra della caldaia:

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

Spiegazione

TeX è una strana bestia. Leggere il codice normale e comprenderlo è di per sé un'impresa. La comprensione del codice TeX offuscato va oltre. Cercherò di renderlo comprensibile anche per le persone che non conoscono TeX, quindi prima di iniziare ecco alcuni concetti su TeX per rendere le cose più facili da seguire:

Per (non così) principianti assoluti TeX

  • In primo luogo, e l'elemento più importante in questo elenco: il codice non deve essere in forma rettangolare, anche se la cultura pop potrebbe indurti a pensarlo .

  • TeX è un linguaggio di espansione macro. È possibile, ad esempio, definire \def\sayhello#1{Hello, #1!}e quindi scrivere \sayhello{Code Golfists}per ottenere la stampa di TeX Hello, Code Golfists!. Questa è chiamata "macro non delimitata" e per alimentare il primo (e unico, in questo caso) parametro lo racchiudi tra parentesi graffe. TeX rimuove quelle parentesi graffe quando la macro afferra l'argomento. È possibile utilizzare fino a 9 parametri: \def\say#1#2{#1, #2!}quindi \say{Good news}{everyone}.

  • La controparte di macro undelimited sono, ovviamente, quelli delimitati :) Si potrebbe fare la precedente definizione un po 'più semantico : \def\say #1 to #2.{#1, #2!}. In questo caso i parametri sono seguiti dal cosiddetto testo del parametro . Tale testo di parametro delimita l'argomento della macro ( #1è delimitato da ␣to␣, spazi inclusi ed #2è delimitato da .). Dopo quella definizione puoi scrivere \say Good news to everyone., che si espanderà a Good news, everyone!. Bello no? :) Tuttavia, un argomento delimitato è (citando il TeXbook ) "la sequenza più breve (possibilmente vuota) di token con {...}gruppi nidificati correttamente che è seguita nell'input da questo particolare elenco di token non parametrici". Ciò significa che l'espansione di\say Let's go to the mall to Martinprodurrà una strana frase. In questo caso si avrebbe bisogno di “nascondere” il primo ␣to␣con {...}: \say {Let's go to the mall} to Martin.

  • Fin qui tutto bene. Ora le cose iniziano a diventare strane. Quando TeX legge un carattere (che è definito da un "codice carattere"), assegna a quel carattere un "codice categoria" (codice cat, per gli amici :) che definisce cosa significherà quel carattere. Questa combinazione di carattere e codice categoria crea un token (ne parleremo qui , per esempio). Quelli che ci interessano qui sono fondamentalmente:

    • catcode 11 , che definisce i token che possono costituire una sequenza di controllo (un nome elegante per una macro). Per impostazione predefinita, tutte le lettere [a-zA-Z] sono catcode 11, quindi posso scrivere \hello, che è una singola sequenza di controllo, mentre \he11ola sequenza di controllo è \heseguita da due caratteri 1, seguita dalla lettera o, perché 1non è il catcode 11. Se I fatto \catcode`1=11, da quel momento in poi \he11osarebbe una sequenza di controllo. Una cosa importante è che i codici cat vengono impostati quando TeX vede per la prima volta il personaggio a portata di mano e tale codice cat viene bloccato ... PER SEMPRE! (possono essere applicati termini e condizioni)

    • catcode 12 , che sono la maggior parte degli altri caratteri, come 0"!@*(?,.-+/e così via. Sono il tipo meno speciale di catcode in quanto servono solo per scrivere cose sulla carta. Ma hey, chi usa TeX per scrivere?!? (di nuovo, possono essere applicati termini e condizioni)

    • catcode 13 , che è un inferno :) Davvero. Smetti di leggere e vai a fare qualcosa fuori dalla tua vita. Non vuoi sapere cos'è il catcode 13. Hai mai sentito parlare di venerdì 13? Indovina da dove prende il nome! Continua a tuo rischio e pericolo! Un carattere catcode 13, chiamato anche carattere "attivo", non è più solo un personaggio, è una macro stessa! Puoi definirlo per avere parametri ed espandersi a qualcosa come abbiamo visto sopra. Dopo aver fatto \catcode`e=13si pensa che si può fare \def e{I am the letter e!}, MA. TU. NON PUÒ! enon è più una lettera, quindi \defnon lo \defsai, lo è \d e f! Oh, scegli un'altra lettera che dici? Va bene! \catcode`R=13 \def R{I am an ARRR!}. Molto bene, Jimmy, provalo! Ti sfido a farlo e scrivere un Rnel tuo codice! Ecco cos'è un catcode 13. SONO CALMO! Andiamo avanti.

  • Bene, ora al raggruppamento. Questo è abbastanza semplice. Qualunque incarico ( \defè un'operazione di incarico, \let(entreremo in esso) è un altro) fatto in un gruppo viene ripristinato a quello che era prima dell'inizio di quel gruppo a meno che quell'assegnazione non fosse globale. Esistono diversi modi per avviare gruppi, uno di questi è con catcode 1 e 2 caratteri (oh, di nuovo catcode). Per impostazione predefinita {è catcode 1, o gruppo iniziale, ed }è catcode 2 o gruppo finale. Un esempio: \def\a{1} \a{\def\a{2} \a} \aquesto stampa 1 2 1. All'esterno il gruppo è \astato 1, quindi all'interno è stato ridefinito 2e, quando il gruppo è terminato, è stato ripristinato 1.

  • L' \letoperazione è un'altra operazione di assegnazione simile \def, ma piuttosto diversa. Con \defte definisci le macro che si espanderanno in cose, con \lette crei copie di cose già esistenti. Dopo \let\blub=\def( =è facoltativo) puoi cambiare l'inizio edell'esempio dall'elemento catcode 13 sopra a \blub e{...e divertirti con quello. O meglio, invece di rompere roba che si può risolvere (vuoi guardare quella!) L' Resempio \let\newr=R \catcode`R=13 \def R{I am an A\newr\newr\newr!}. Domanda veloce: potresti rinominare \newR?

  • Infine, i cosiddetti "spazi spuri". Questo è un tipo di argomento tabù perché ci sono persone che affermano che la reputazione guadagnata nel TeX - LaTeX Stack Exchange rispondendo a domande su "spazi spuri" non dovrebbe essere presa in considerazione, mentre altri non sono assolutamente d'accordo. Con chi sei d'accordo? Fate le vostre puntate! Nel frattempo: TeX comprende un'interruzione di linea come spazio. Prova a scrivere più parole con un'interruzione di riga (non una riga vuota ) tra loro. Ora aggiungi %a alla fine di queste righe. È come se stessi “commentando” questi spazi di fine linea. Questo è tutto :)

(Sorta di) annullamento della memorizzazione del codice

Trasformiamo quel rettangolo in qualcosa (probabilmente) più facile da seguire:

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

Spiegazione di ogni passaggio

ogni riga contiene una singola istruzione. Andiamo uno per uno, dissezionandoli:

{
Innanzitutto iniziamo un gruppo per mantenere locali alcuni cambiamenti (vale a dire i cambiamenti di catcode) in modo che non rovinino il testo di input.

\let~\catcode
Fondamentalmente tutti i codici di offuscamento TeX iniziano con questa istruzione. Per impostazione predefinita, sia in TeX che in LaTeX, il ~personaggio è l'unico personaggio attivo che può essere trasformato in una macro per un ulteriore utilizzo. E lo strumento migliore per personalizzare il codice TeX sono le modifiche al codice cat, quindi questa è generalmente la scelta migliore. Ora invece di \catcode`A=13scrivere ~`A13( =è facoltativo):

~`A13
Ora la lettera Aè un personaggio attivo e possiamo definirla per fare qualcosa:

\defA#1{~`#113\gdef}
Aè ora una macro che accetta un argomento (che dovrebbe essere un altro carattere). Per prima cosa il catcode dell'argomento viene modificato in 13 per renderlo attivo: ~`#113(sostituisci ~da \catcodee aggiungi un =e hai :) \catcode`#1=13. Infine lascia un \gdef(globale \def) nel flusso di input. In breve, Arende attivo un altro personaggio e inizia la sua definizione. Proviamolo:

AGG#1{~`#113\global\let}
AGprima "attiva" Ge fa \gdef, che seguito dalla successiva Ginizia la definizione. La definizione di Gè molto simile a quella di A, tranne che invece di \gdefun \global\let(non c'è un \gletsimile al \gdef). In breve, Gattiva un personaggio e lo rende qualcos'altro. Facciamo scorciatoie per due comandi che useremo in seguito:

GFF\else
GHH\fi
Ora invece di \elsee \fipossiamo semplicemente usare Fe H. Molto più breve :)

AQQ{Q}
Ora usiamo Adi nuovo per definire un'altra macro, Q. L'affermazione di cui sopra sostanzialmente funziona (in una lingua meno offuscata) \def\Q{\Q}. Questa non è una definizione terribilmente interessante, ma ha una caratteristica interessante. A meno che tu non voglia rompere un po 'di codice, l'unica macro che si espande Qè Qse stessa, quindi si comporta come un marcatore univoco (si chiama quark ). È possibile utilizzare il \ifxcondizionale per verificare se l'argomento di una macro è tale quark con \ifx Q#1:

AII{\ifxQ}
quindi puoi essere abbastanza sicuro di aver trovato un tale marker. Si noti che in questa definizione ho rimosso lo spazio tra \ifxe Q. Di solito questo porta a un errore (notare che l'evidenziazione della sintassi pensa che \ifxQsia una cosa), ma poiché ora Qè il catcode 13 non può formare una sequenza di controllo. Fai attenzione, tuttavia, a non espandere questo quark o rimarrai bloccato in un ciclo infinito perché si Qespande a Qquale si espande a Qquale ...

Ora che i preliminari sono terminati, possiamo passare all'algoritmo corretto per essere pronti. A causa della tokenizzazione di TeX, l'algoritmo deve essere scritto al contrario. Questo perché al momento in cui si effettua una definizione TeX tokenizzerà (assegnando i codici cat) ai caratteri nella definizione utilizzando le impostazioni correnti, quindi, ad esempio, se lo faccio:

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

l'output è E1, mentre se cambio l'ordine delle definizioni:

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

l'uscita è 11. Questo perché nel primo esempio Enella definizione è stato tokenizzato come una lettera (catcode 11) prima della modifica del catcode, quindi sarà sempre una lettera E. Nel secondo esempio, tuttavia, è Estato prima reso attivo e solo allora è \onestato definito, e ora la definizione contiene il catcode 13 Eche si espande a 1.

Tuttavia, trascurerò questo fatto e riordinerò le definizioni per avere un ordine logico (ma non funzionante). Nei paragrafi che seguono si può presumere che le lettere B, C, De Esono attivi.

\gdef\S#1{\iftrueBH#1 Q }
(nota che c'era un piccolo bug nella versione precedente, non conteneva lo spazio finale nella definizione sopra. L'ho notato solo mentre scrivevo questo. Continua a leggere e vedrai perché ne abbiamo bisogno per terminare correttamente la macro. )
Per prima cosa definire la macro-livello utente, \S. Questo non dovrebbe essere un personaggio attivo per avere una sintassi amichevole (?), Quindi la macro per gwappins eht setterl è \S. La macro inizia con un condizionale sempre vero \iftrue(sarà presto chiaro il perché), quindi chiama la Bmacro seguita da H(che abbiamo definito in precedenza \fi) per corrispondere a \iftrue. Quindi lasciamo l'argomento della macro #1seguito da uno spazio e dal quark Q. Supponiamo di usare \S{hello world}, quindi il flusso di inputdovrebbe apparire così: \iftrue BHhello world Q␣(ho sostituito l'ultimo spazio con un in modo che il rendering del sito non lo mangi, come ho fatto nella versione precedente del codice). \iftrueè vero, quindi si espande e ci rimane BHhello world Q␣. TeX non rimuove il \fi( H) dopo aver valutato il condizionale, invece lo lascia lì fino a quando non \fiviene effettivamente espanso. Ora la Bmacro è espansa:

ABBH#1 {HI#1FC#1|BH}
Bè una macro delimitata il cui parametro è il testo H#1␣, quindi l'argomento è qualunque sia tra He uno spazio. Continuando l'esempio sopra il flusso di input prima dell'espansione di Bis BHhello world Q␣. Bè seguito da H, come dovrebbe (altrimenti TeX genererebbe un errore), quindi lo spazio successivo è tra helloe world, così #1è la parola hello. E qui dobbiamo dividere il testo di input negli spazi. Yay: D L'espansione Brimuove tutto fino al primo spazio dal flusso di input e sostituisce da HI#1FC#1|BHcon #1essere hello: HIhelloFChello|BHworld Q␣. Si noti che è disponibile una nuova versione BHsuccessiva nel flusso di input, per eseguire una ricorsione della codaBed elaborare le parole successive. Dopo che questa parola è stata elaborata Belabora la parola successiva fino a quando la parola da elaborare è il quark Q. L'ultimo spazio dopo Qè necessario perché la macro delimitata B richiede uno alla fine dell'argomento. Con la versione precedente (vedi cronologia delle modifiche) il codice si comporterebbe in modo errato se lo utilizzassi \S{hello world}abc abc(lo spazio tra le abcs svanirebbe).

OK, torniamo al flusso di input: HIhelloFChello|BHworld Q␣. Innanzitutto c'è il H( \fi) che completa l'iniziale \iftrue. Ora abbiamo questo (pseudocodificato):

I
  hello
F
  Chello|B
H
world Q␣

Il I...F...Hpensiero è in realtà una \ifx Q...\else...\fistruttura. Il \ifxtest verifica se la parola (primo token della) catturata è il Qquark. Se è non c'è niente altro da fare e le termina l'esecuzione, altrimenti ciò che rimane è: Chello|BHworld Q␣. Ora Cè espanso:

ACC#1#2|{D#2Q|#1 }
Il primo argomento della Cè undelimited, quindi a meno rinforzato sarà un unico token, il secondo argomento è delimitato da |, così dopo l'espansione C(con #1=he #2=ello) il flusso di ingresso è: DelloQ|h BHworld Q␣. Si noti che un altro |è messo lì, e il hdi helloè messo dopo. La metà dello scambio è fatta; la prima lettera è alla fine. In TeX è facile afferrare il primo token di un elenco di token. Una semplice macro \def\first#1#2|{#1}ottiene la prima lettera quando si utilizza \first hello|. L'ultimo è un problema perché TeX afferra sempre la lista di token “più piccola, possibilmente vuota” come argomento, quindi abbiamo bisogno di qualche soluzione. L'elemento successivo nell'elenco token è D:

ADD#1#2|{I#1FE{}#1#2|H}
Questa Dmacro è una delle soluzioni alternative ed è utile nel solo caso in cui la parola ha una sola lettera. Supponiamo invece di helloaverlo fatto x. In questo caso il flusso di ingresso sarebbe DQ|x, allora Ddovrebbe espandere (con #1=Qe #2svuotare) a: IQFE{}Q|Hx. Questo è simile al blocco I...F...H( \ifx Q...\else...\fi) in B, che vedrà che l'argomento è il quark e interromperà l'esecuzione lasciando solo xper la composizione. In altri casi (tornando alla helloesempio), Ddovrebbe espandere (con #1=ee #2=lloQ) a: IeFE{}elloQ|Hh BHworld Q␣. Anche in questo caso, la I...F...Hverifica la presenza di Q, ma non riuscirà e prendere la \elsefiliale: E{}elloQ|Hh BHworld Q␣. Ora l'ultimo pezzo di questa cosa, ilE la macro si espanderebbe:

AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
Il testo del parametro qui è abbastanza simile a Ce D; il primo e il secondo argomento non sono delimitati e l'ultimo è delimitato da |. L'aspetto del flusso di ingresso di questo tipo: E{}elloQ|Hh BHworld Q␣, poi Esi espande (con #1vuoto, #2=e, e #3=lloQ): IlloQeFE{e}lloQ|HHh BHworld Q␣. Un'altra I...F...Hverifica di blocco del quark (che vede le ritorna false): E{e}lloQ|HHh BHworld Q␣. Ora Esi espande nuovamente (con #1=evuoto, #2=le #3=loQ): IloQleFE{el}loQ|HHHh BHworld Q␣. E ancora I...F...H. La macro esegue alcune altre iterazioni fino a quando non Qviene finalmente trovata e il trueramo viene preso: E{el}loQ|HHHh BHworld Q␣-> IoQlelFE{ell}oQ|HHHHh BHworld Q␣-> E{ell}oQ|HHHHh BHworld Q␣-> IQoellFE{ello}Q|HHHHHh BHworld Q␣. Ora il quark viene trovato e si espande condizionali a: oellHHHHh BHworld Q␣. Uff.

Oh, aspetta, cosa sono questi? LETTERE NORMALI? Oh ragazzo! Le lettere sono finalmente trovato e TeX scrive oell, poi un gruppo di H( \fi) si trovano e ampliato (per niente) lasciando il flusso di input con: oellh BHworld Q␣. Ora la prima parola ha la prima e l'ultima lettera scambiate e ciò che TeX trova dopo è l'altra Bper ripetere l'intero processo per la parola successiva.

}
Alla fine finiamo il gruppo ricominciato lì in modo che tutti gli incarichi locali vengano annullati. Le assegnazioni locali sono i cambiamenti catcode delle lettere A, B, C, ... che sono state fatte delle macro in modo che restituiscano alla loro lettera normale significato e possono essere utilizzati in modo sicuro nel testo. E questo è tutto. Ora la \Smacro definita lì attiverà l'elaborazione del testo come sopra.

Una cosa interessante di questo codice è che è completamente espandibile. Cioè, puoi tranquillamente usarlo per spostare argomenti senza preoccuparti che esploderà. Puoi anche utilizzare il codice per verificare se l'ultima lettera di una parola è uguale alla seconda (per qualsiasi motivo che ti servirà) in 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

Ci scusiamo per la spiegazione prolissa (probabilmente troppo lontana). Ho cercato di renderlo il più chiaro possibile anche per i non TeXies :)

Riepilogo per l'impaziente

La macro \Santepone l'input con un carattere attivo Bche prende gli elenchi di token delimitati da uno spazio finale e li passa a C. Cprende il primo token in quell'elenco e lo sposta alla fine dell'elenco di token e si espande Dcon ciò che rimane. Dcontrolla se “ciò che rimane” è vuoto, nel qual caso è stata trovata una parola di una sola lettera, quindi non fa nulla; altrimenti si espande E. Escorre l'elenco token fino a quando non trova l'ultima lettera nella parola, quando viene trovata lascia l'ultima lettera, seguita dal centro della parola, seguita dalla prima lettera lasciata alla fine del flusso di token da C.


2
Mi piacerebbe una spiegazione completa di questo. Sono molto curioso di sapere come funziona!
LambdaBeta,

1
@LambdaBeta Posso farcela, ma non ora. Aspetta e ti faccio un rumore metallico quando lo faccio :)
Phelype Oleinik

1
@LambdaBeta Done! Scusa, a volte sono troppo prolisso :-)
Phelype Oleinik,

13

JavaScript (ES6),  39  36 byte

Salvato 3 byte grazie a @FryAmTheEggman

Utilizza un avanzamento riga come separatore.

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

Provalo online!


5
(.)(.*)(.)è quella l'emoticon Total Recall?
MikeTheLiar,

1
@MikeTheLiar Tipo di, immagino. : D
Arnauld

L'assegnazione specifica che la stringa contiene il separatore.
Cees Timmerman,

@CeesTimmerman Non sono sicuro di cosa intendi. Questo codice prevede un avanzamento riga come separatore e pertanto accetta stringhe con avanzamenti riga come input. (Il piè di pagina del collegamento TIO converte gli spazi in avanzamenti di riga e quindi di nuovo in spazi per la leggibilità.)
Arnauld

"data una stringa di caratteri alfabetici ASCII e un altro carattere da usare come delimitatore (per separare ogni parola) " - Nm, ho pensato che fosse un parametro separato.
Cees Timmerman,

11

Retina ,8 5 byte

,V,,`

Provalo online!

Salvato 3 byte grazie a Kevin Cruijssen !

Utilizza una nuova riga come separatore. Facciamo uso dello stadio inverso di Retina e di alcuni limiti. Il primo limite è quello a cui applicare l'inversione, quindi selezioniamo tutti ,. Quindi vogliamo che la prima e l'ultima lettera di ogni corrispondenza vengano scambiate, quindi prendiamo ogni lettera nell'intervallo ,,che si traduce in un intervallo dall'inizio alla fine con dimensione del passo zero.


Dangit, stavo solo cercando nei documenti qualcosa del genere per aggiornare la mia risposta, ma mi hai battuto. Lo sapevo V, ma non sapevo che potesse essere usato con indici del 1,-2genere. Ben fatto!
Kevin Cruijssen,

1
@KevinCruijssen Ho tradito un po 'e ho rivisto il funzionamento dei range limite mentre questo era nella sandbox :) Sento ancora che dovrebbe esserci un modo migliore che invertire un range ma non sono riuscito a trovare qualcosa di più breve.
FryAmTheEggman,

2
Hai davvero ragione sul fatto che può essere più breve senza un intervallo di limiti, perché sembra che questo 5 byte funzioni (indicato come esempio nella parte inferiore dei limiti di passaggio nei documenti).
Kevin Cruijssen,

@KevinCruijssen Nice! Non riesco a credere che mi sia perso.
FryAmTheEggman,

3
Quindi, 5 byte e solo 3 caratteri diversi? Questo è minimalista.
Cœur

9

Pepe , 107 105 byte

REEeREeeEeeeeerEEreREEEeREEEEEEeREEEErEEREEEEEEEreererEEEeererEEEerEEeERrEEEeerEEeerereeerEEEEeEEEReEeree

Provalo online!

Spiegazione:

Notazione sui commenti: 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

Come funziona?
lirtosiast

@lirtosiast spiegazione aggiunta
u_ndefined


6

laskelH , 71 byte

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

Provalo online!

Esempio in / output:

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
L'assegnazione nella whereclausola può essere spostata in un binding di guardia per salvare 5 byte: provalo online!
Laikoni,

1
Vedo cosa hai fatto lì con il nome "Haskell" nel titolo. Ho fatto la stessa cosa sulla mia risposta PHP.
640 KB

5

05AB1E , 10 byte

#vyRćsRćðJ

Provalo online!


-3 Grazie 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 Voglio sinceramente cancellarlo e dartelo, che era il 99% della tua capacità di cervello sull'ordinamento degli argomenti ahah.
Magic Octopus Urn

1
Trovato un 9-byte, ma funziona solo nella versione precedente:|ʒRćsRćJ,
Kevin Cruijssen,

1
Peccato che non ne abbiamo loop_as_long_as_there_are_inputs, quindi avrei conosciuto un 8-byte: [RćsRćJ,questo 8-byte [non utilizza mai output in teoria, tuttavia, solo quando hai esaurito la memoria o il timeout come su TIO (e richiede un trailing newline nell'input, altrimenti continuerà a usare l'ultima parola) ..
Kevin Cruijssen,

1
Purtroppo è necessario ð¡come input di una sola parola è possibile, ma ð¡εćsÁì}ðýfunziona anche a 10 byte.
Emigna

5

J , 23 17 byte

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

Provalo online!


Molto bello il trucco per scambiare le prime / ultime lettere ruotando e applicando 1 A.!
Galen Ivanov,

1
1&A.&.(1&|.)-> ({:,1|.}:)e quindi puoi rimuovere::]
ngn

Incredibile, grazie
FrownyFrog

Davvero sorprendente! Ancora una volta mi stupisco di quanto possa essere semplice ed elegante la soluzione, ma solo dopo che la vedo eseguita da qualcun altro.
Galen Ivanov,

4

Rubino con -p, 42 41 29 byte

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

Provalo online!



@Shaggy grazie per il testa a testa. Se dai un'occhiata alla cronologia dei miei post mostra che sono stato via per 8 mesi senza risposte, quindi probabilmente ho perso alcuni memo durante quel periodo, haha
Value Ink

Abbastanza sicuro il consenso è stato cambiato più di 8 mesi fa, ma nel caso in cui te lo fossi perso: anche "non competere" non è più una cosa.
Shaggy,

Ben fatto. Penso che, secondo le regole, puoi usare le nuove righe come delimitatore e sostituire le \ws con .s.
istocratico





3

Spazio bianco , 179 byte

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

Lettere S(spazio), T(scheda) e N(nuova riga) aggiunti solo come evidenziazione.
[..._some_action]aggiunto solo come spiegazione.

Scheda come delimitatore. L'input dovrebbe contenere una nuova riga (o una scheda) finale, altrimenti il ​​programma non sa quando fermarsi, poiché prendere input in Whitespace può essere fatto solo un carattere alla volta.

Provalo online (solo con spazi non elaborati, schede e nuove righe).

Spiegazione in pseudo-codice:

[0,...,word_length]

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

Il programma termina con un errore quando tenta di leggere un carattere quando nessuno è dato in TIO (o si blocca in attesa di un input in alcuni compilatori di Whitespace come vii5ard ).


3

Wolfram Language (Mathematica) , 58 byte

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

Provalo online!

-22 byte da @attinat

-12 byte da @ M.Stern


70 byte usando StringReplacecon StringExpressions
attinat

1
64 byte usando StringTakeinvece di StringReplace:StringRiffle[StringSplit@##~StringTake~{{-1},{2,-2},{1}},#2,""]&
Roman

2
Ecco un approccio più diretto:StringReplace[#, a : u ~~ w : u .. ~~ b : u :> b <> w <> a /. {u -> Except@#2}] &
M. Stern,

1
{e} sono facoltativi :)
M. Stern

1
55 byte , corregge anche parole di 2 caratteri
attinat

2

QuadR , 20 byte

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

Crea semplicemente tre gruppi di acquisizione composti da 1, 0 o più caratteri e 1 carattere di parole, quindi inverte il loro ordine.

Provalo online!



2

Japt -S , 10 byte

Convinto che ci debba essere un approccio più breve (e avevo ragione ), ma per ora lo farà.

¸ËhJDg)hDÌ

Provalo

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

Molto più breve del mio 12 byter:¸®Ì+Zs1J +Zg
Incarnazione dell'ignoranza

@EmbodimentofIgnorance, è anche lì che ho iniziato, ma non avrebbe funzionato con le parole a carattere singolo. È possibile salvare un byte su quello, però, con ¸®ÎiZÌ+Zs1J.
Shaggy,

1
@EmbodimentofIgnorance Trovato 7 byter
Oliver

2

sed, 64 byte

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

Certo, potremmo usare .invece di [[:alpha:]], ma in realtà dovrebbe esserlo [^ ], il che lo riduce a 43, ma si interrompe sulla punteggiatura e così via. Usare lo [a-zA-Z]porta fino a 55, a quel punto sto solo desiderando ardentemente quelle dolci, dolci entità leggibili dall'uomo ...
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 altre parole, non devi preoccuparti che la punteggiatura "rompa" il tuo codice e puoi tranquillamente cercare [^ ];)
Value Ink

@ValueInk Sì, ma [^ ]dovrebbe essere quello [^[:space:]]che lo porta a 67 caratteri.
Ricco

"un delimitatore" significa che puoi assicurarti che il delimitatore sia sempre uno spazio regolare. Chi usa comunque le schede in una frase ??
Value Ink

Va bene. Sembra che "code golf" sia un gioco in cui devi trovare un modo per far cadere un pallone nel drone invece di fare il lavoro. Grazie per l'accoglienza di merda.
Rich

2

sed , 34 byte

E presumibilmente l'idea del modello funzionerà con la maggior parte degli strumenti di RE (e so che ci sono differenze tra RE standard e RE esteso).

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

Provalo online!


1
Benvenuti in PPCG! Pensa che la natura avida delle partite regex significhi che puoi tagliare \bla partita: provala online!
Value Ink

Concordato @ValueInk - ma ero preciso con la partita. La rimozione di \bporterà a 30 byte.
PJF,

Usa -E per regex avanzato e puoi usare parentesi senza escape. Utilizzare .per i caratteri scambiati e si possono perdere altri due caratteri. Questo porta il tuo fino a 26 byte; una delle più piccole soluzioni leggibili. s,\b(.)(\w*)(.)\b,\3\2\1,g
Ricco

1
- no, mi sbaglio, hai bisogno della \ws alle estremità. s,\b(\w)(\w*)(\w)\b,\3\2\1,g28 caratteri.
Ricco

Bel lavoro @rich, ma come ho già detto so di RE standard ed esteso. Ho appena scelto di renderlo standard e leggibile. Le ancore sarebbero richieste che ho trascurato di menzionare nella mia risposta a ValueInk.
PJF,

2

Rubino, 53 byte

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

L'ho provato senza regex. L'output stampa ogni parola su una nuova riga. Se questo è contro le regole, fammi sapere e lo risolverò.

Ungolfed:

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

Benvenuti in PPCG! Stampare ogni parola su una nuova riga dovrebbe andare bene, ma la tua vecchia soluzione pnon era buona perché aggiungeva virgolette all'output. Puoi sempre usare putsinvece poiché si aggiunge automaticamente la nuova riga ed è più breve di print! Inoltre, se si chiama splitsenza argomenti, si divide automaticamente negli spazi.
Value Ink

2

8088 Assembly, IBM PC DOS, 39 38 byte

$ 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

smontato:

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 

Eseguibile DOS per PC autonomo. Input tramite args della riga di comando, output sullo schermo.

inserisci qui la descrizione dell'immagine

Scarica e prova PWAS.COM .



1

Lotto, 141 byte

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

Accetta input come parametri della riga di comando. La manipolazione delle stringhe è terribile in Batch nella migliore delle ipotesi, e non è necessario dover ricorrere a parole singole con lettere maiuscole.





1

Haskell , 75 74 byte

Risolto un bug a cui puntava Cubic e anche golfato di 1 byte.

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

Provalo online!


map gè più corto di(g<$>)
Cubic

1
Inoltre, se guardi il tuo caso di test vedrai che non funziona per parole di una lettera, si trasforma ainaa
Cubic

1

Scala, 100 byte

(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 byte

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

L'input avviene tramite una tabella preesistente t con varchar field v , secondo i nostri standard IO .

Leggendo da dietro in avanti, STRING_SPLITspezza una stringa in singole righe tramite un delimitatore, STUFFmodifica i caratteri nelle posizioni specificate, quindi STRING_AGGli rimette insieme.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.