Il mondo finisce in ed


21

Tratto direttamente dall'ACM Winter Programming Contest 2013. Sei una persona a cui piace prendere le cose alla lettera. Pertanto, per te, la fine di The World è ed; le ultime lettere di "Il" e "Mondo" concatenate.

Crea un programma che prende una frase e genera l'ultima lettera di ogni parola in quella frase nel minor spazio possibile (meno byte). Le parole sono separate con qualsiasi cosa tranne le lettere dell'alfabeto (65 - 90, 97 - 122 nella tabella ASCII). Ciò significa che caratteri di sottolineatura, tilde, tombe, parentesi graffe, ecc. Sono separatori. Tra ogni parola può esserci più di un separatore.

asdf jkl;__zxcv~< vbnm,.qwer| |uiop-> flvmrp
pigs, eat dogs; eat Bob: eat pigs-> ststbts
looc si siht ,gnitirw esreveR-> citwR
99_bottles_of_beer_on_the_wall->sfrnel


Potresti aggiungere un caso di test che includa cifre e caratteri di sottolineatura?
grc

10
Il mondo finisce in ed? Io sapevo vim e Emacs non sono riuscito a misurare fino!
Joe Z.

Bene, il saggio "uomini veri usa ed" è stato parte della distribuzione di Emacs per tutto il tempo che posso ricordare.
JB

Gli ingressi saranno solo ASCII?
Phil H,

Risposte:


16

Perl 5, 18 byte

s/\pL*(\pL)|./$1/g

Richiede -pun'opzione della riga di comando. La proprietà denominata Lcorrisponde solo ai caratteri lettera A-Za-z. Esistono diverse centinaia di tali proprietà con nome, ma quando si tratta di testo ASCII, pochissime sono interessanti. Inoltre \pL, l'unica altra di qualsiasi nota reale è \pP, che corrisponde alla punteggiatura.

Provalo online!


Perl 5, 17 byte

Un miglioramento di un byte di Dom Hastings

print/\pL*(\pL)/g

Richiede -n(e -lper supportare più input).

Provalo online!


Utilizzo del campione

$ more in.dat
asdf jkl;__zxcv~< vbnm,.qwer| |uiop
pigs, eat dogs; eat Bob: eat pigs
looc si siht ,gnitirw esreveR
99_bottles_of_beer_on_the_wall

$ perl -p ends-in-ed.pl < in.dat
flvmrp
ststbts
citwR
sfrnel

Penso che \wcorrisponda anche a cifre e caratteri di sottolineatura.
grc

Hmm, davvero. Questo dovrà essere aggiornato.
primo

2
Brillante. Regex era una soluzione ovvia, ma |.non era ovvio (almeno per me).
Peter Taylor,

1
Ho appena notato un -1in print/\pL*(\pL)/g, sembra emettere lo stesso per i tuoi casi di test!
Dom Hastings,

18

ed, 35 caratteri

s/[a-zA-Z]*\([a-zA-Z]\)\|./\1/g
p
Q

Quindi, il mondo finisce in ed. Dato che mi piace essere troppo letterale, ho deciso di scrivere per scrivere la soluzione con ed - e apparentemente è in realtà un linguaggio di programmazione . È sorprendentemente breve, anche considerando che in questo thread esistono già molte soluzioni più brevi. Sarebbe più bello se potessi usare qualcosa di diverso [a-zA-Z], ma considerando che non è un linguaggio di programmazione, in realtà è abbastanza buono.

Innanzitutto, vorrei dire che analizza solo l'ultima riga del file. Sarebbe possibile analizzare di più, basta digitare ,all'inizio di due prime righe (questo intervallo "tutto" specificato, al contrario dell'intervallo dell'ultima riga standard), ma ciò aumenterebbe la dimensione del codice a 37 caratteri.

Ora per spiegazioni. La prima riga fa esattamente quello che fa la soluzione Perl (tranne senza supporto per i caratteri Unicode). Non ho copiato la soluzione Perl, ho appena inventato qualcosa di simile per coincidenza.

La seconda riga stampa l'ultima riga, in modo da poter vedere l'output. La terza riga forza la chiusura - Devo farlo, altrimenti edverrebbe stampato ?per ricordarti che non hai salvato il file.

Ora per come eseguirlo. Bene, è molto semplice. Esegui semplicemente edil file contenente il test case, mentre esegui il piping del mio programma, in questo modo.

ed -s testcase < program

-sè silenzioso. Questo impedisce eddi produrre file di dimensioni brutte all'inizio. Dopotutto, lo uso come script, non come editor, quindi non ho bisogno di metadati. Se non lo facessi, ed mostrerebbe la dimensione del file che altrimenti non avrei potuto impedire.


Ho installato ed solo per provare questo.
primo

6

Javascript, 49

alert(prompt().replace(/.(?=[a-z])|[^a-z]/gi,''))

Utilizza un'espressione regolare per rimuovere tutti i caratteri che precedono una lettera, nonché tutti i caratteri non lettera. Quindi restiamo con l'ultima lettera di ogni parola.

Grazie a tomsmeding per un bel miglioramento.


3
Probabilmente puoi migliorarlo rendendo il regex insensibile alle maiuscole, come in:alert(prompt().replace(/.(?=[a-z])|[^a-z]/gi,''))
tomsmeding

6

C, 78

golfed:

main(int c,char**s){for(;c=*s[1]++;)isalpha(c)&&!isalpha(*s[1])?putchar(c):0;}

Con spazi bianchi:

main(int c,char**s)
{
  for(;c=*s[1]++;)
    isalpha(c)&&!isalpha(*s[1])?putchar(c):0;
}

Produzione:

inserisci qui la descrizione dell'immagine


1
Puoi salvare 4 byte usando la dichiarazione K&R e il default c:main(c,s)char**s;{for
Toby Speight

5

GNU Sed, 40 38 37

s/[a-z]\b/&\n/g; s/[^\n]*\(.\)\n/\1/g

analisi

cat << EOF > data.txt
asdf jkl;__zxcv~< vbnm,.qwer| |uiop
pigs, eat dogs; eat Bob: eat pigs
looc si siht ,gnitirw esreveR
EOF

Esegui sed:

sed 's/[A-Za-z]\b/&\n/gi; s/[^\n]*\(.\)\n/\1/g' data.txt

Produzione:

flvmrp
ststbts
citwR

Spiegazione

La prima sostituzione sostituisce tutti i limiti di parole, preceduti dal gruppo di corrispondenze desiderato, con una nuova riga. Ciò semplifica la rimozione di tutti i caratteri estranei nella seconda sostituzione.

modificare

  • Usa la bandiera senza distinzione tra maiuscole e minuscole (-2), grazie manatwork .
  • Non contare gli spazi bianchi (-1).

sed's scomando non ha ibandiera per i casi di corrispondenza insensibile: s/[a-z]\b/&\n/gi.
arte

@manatwork: buon punto, questo renderebbe GNU solo sed, ma sembra che lo sia già, grazie.
Thor

\bconsidera _s per essere lettere, quindi se tutte le parole nel test END con _, l'ultima lettera di quella parola non è incluso nell'output
Marty Neal

3

Grep and Paste, 36 34 28

> echo 'asdf jkl;__zxcv~< vbnm,.qwer| |uiop' | grep -io '[a-z]\b' | tr -d \\n
flvmrp

> echo 'pigs, eat dogs; eat Bob: eat pigs'   | grep -io '[a-z]\b' | tr -d \\n
ststbts

echo 'looc si siht ,gnitirw esreveR'         | grep -io '[a-z]\b' | tr -d \\n
citwR

Se è necessaria una nuova riga finale, sostituirla tr -d \\ncon paste -sd ''.

modificare

  • Usa grep senza distinzione tra maiuscole e minuscole (-2), grazie a Manatwork .
  • Usa trinvece di paste(-4), grazie manatwork .
  • Non contare gli spazi bianchi attorno alla pipe (-2).

Abbastanza creativo paste -sd '', ma tr -d \\nè più breve. Per quanto riguarda grep, ha -isignificato interruttore “ignora caso”, che può renderlo più breve: grep -io '[a-z]\b'.
arte

@manatwork, trelimina anche la nuova riga finale. La modalità insensibile alle maiuscole è ovviamente più breve, grazie.
Thor

non esiste una regola che richiede la nuova riga finale.
arte

@manatwork: posso essere d'accordo, risposta aggiornata.
Thor

3

sed, 37 caratteri

Uguale lunghezza alla risposta di Thor , ma, credo, più semplice.

s/[a-z]*\([a-z]\)/\1/ig;s/[^a-z]*//ig

La logica è piuttosto banale: sostituisci le sequenze di lettere con l'ultima lettera, quindi elimina tutte le non lettere.


3

Mathematica, 39

""<>StringCases[#,(__~~x_)?LetterQ:>x]&

Test:

""<>StringCases[#,(__~~x_)?LetterQ:>x]& /@
 {"asdf jkl;__zxcv~< vbnm,.qwer| |uiop",
  "pigs, eat dogs; eat Bob: eat pigs",
  "looc si siht ,gnitirw esreveR",
  "99_bottles_of_beer_on_the_wall"}
{"flvmrp", "ststbts", "citwR", "sfrnel"}

Buona LetterQdovrebbe essere chiamato LettersQ:) Non ci ho pensato per testare intere stringhe.
Dr. belisarius,

@belisarius In realtà, con questo costrutto viene applicato dal punto di vista del carattere, quindi potrebbe essere un letterale "LetterQ" e funzionare ancora.
Mr.Wizard,

2

K, 49

{last'f@&"b"$#:'f:"|"\:@[x;&~x in,/.Q`a`A;:;"|"]}

.

k){last'f@&"b"$#:'f:"|"\:@[x;&~x in,/.Q`a`A;:;"|"]}"asdf jkl;__zxcv~< vbnm,.qwer| |uiop"
"flvmrp"
k){last'f@&"b"$#:'f:"|"\:@[x;&~x in,/.Q`a`A;:;"|"]}"pigs, eat dogs; eat Bob: eat pigs"
"ststbts"
k){last'f@&"b"$#:'f:"|"\:@[x;&~x in,/.Q`a`A;:;"|"]}"looc si siht ,gnitirw esreveR"
"citwR"

2

Scala, 59 (o 43)

Supponendo che la stringa sia già in s:

s.split("[^a-zA-Z]+").map(_.last).mkString

Se è necessario leggere da un prompt e stampare anziché utilizzare l'output REPL, convertire sin readLinee completare println()per 59.


2

x86: 54 byte

Assumi una routine cdecl con la firma void world_end(char *input, char *output):

60 8b 74 24 24 8b 7c 24 28 33 d2 8a 0e 8a c1 24
df 3c 41 72 08 3c 5a 77 04 8a d1 eb 09 84 d2 74
05 88 17 47 33 d2 46 84 c9 75 e0 84 d2 74 03 88
17 47 88 0f 61 c3

1
A proposito, mi rendo conto che la domanda richiede un programma e non una routine , ma volevo fare qualcosa di diverso. Contrariamente all'affermazione del problema, suppongo di non essere una "persona a cui piace prendere le cose alla lettera" dopo tutto. : P
user1354557

2

Xi, 32

println$ @{=>.-1}<>input re"\W+"

Xi è una lingua ancora nella sua fase beta, ma sembra funzionare bene con il golf del codice, quindi ho pensato che potrei anche mostrare un'altra soluzione breve e funzionale (e pubblicizzare un po 'la lingua :-)).


2

Mathematica 62 57 52

Row@StringTake[StringCases[#,LetterCharacter..],-1]&

analisi

l = {"asdf jkl;__zxcv~<vbnm,.qwer| |uiop", 
     "pigs,eat dogs;eat Bob:eat pigs", 
     "looc si siht,gnitirw esreveR"}

Row@StringTake[StringCases[#,LetterCharacter..],-1]&/@ l
(*{flvmrp,ststbts,citwR}*)

Ho erroneamente modificato il tuo, ma poi l'ho ripristinato. Ooops.
DavidC

2

Python3, 59 caratteri

import re;print(re.sub('.(?=[a-z])|[^a-z]','',input(),0,2))

Gestisce correttamente lettere maiuscole e caratteri di sottolineatura. Il 2 è quello di passare re.subla re.IGNORECASEbandiera senza dover usare re.I.


2

Python, 76 caratteri

import re;print "".join(re.findall("([a-zA-Z])(?=$|[^a-zA-Z])",raw_input()))


È possibile rimuovere lo spazio dopo print.
terremoto del

Accorciare import re;print(*re.findall("([a-zA-Z])(?=$|[^a-zA-Z])",input()),sep='')
eseguendo il

1

Python 3.x, 64 byte

import re;print(''.join(a[-1] for a in re.split('\W+',input())))

2
L'ultimo esempio non funziona. Inoltre, si verifica un errore se la riga inizia o termina con un separatore
AMK

È possibile rimuovere lo spazio prima for.
Bakuriu,

1

Lua, 42

print(((...):gsub('.-(.)%f[%A]%A*','%1')))

Esempio di utilizzo: lua script.lua "asdf jkl;__zxcv~< vbnm,.qwer| |uiop"


1

Mathematica 71 47 45 61

Torna al tavolo da disegno, dopo che @belisarius ha trovato un errore nel codice.

StringCases[#, RegularExpression["[A-Za-z](?![A-Za-z])"]] <> "" &

analisi

l = {"asdf jkl;__zxcv~<vbnm,.qwer| |uiop", "asdf jkl__zxcv~<vbnm,.qwer| |uiop", 
"pigs,eat dogs;eat Bob:eat pigs", "looc si siht,gnitirw esreveR"};

StringCases[#, RegularExpression["[A-Za-z](?![A-Za-z])"]] <> "" & /@ l

{"flvmrp", "flvmrp", "ststbts", "citwR"}


\\wcorrisponde _, quindi non funziona per (ad esempio)"asdf jkl__zxcv~<vbnm,.qwer| |uiop"
Dr. belisarius

Aspetta Row@StringTake[ StringCases[#, LetterCharacter ..], -1] &@"asdf jkl__zxcv~<vbnm,.qwer| |uiop"mi dà flvmrp, ma #~StringCases~RegularExpression@"\\w\\b" <> "" &@"asdf jkl__zxcv~<vbnm,.qwer| |uiop"ritorna fvmrpqui. Stiamo ottenendo gli stessi risultati ??
Dr. belisarius,

@belisarius Avevi ragione sull'errore nella mia versione precedente. Lo stavo testando con la stringa sbagliata!
DavidC

Hehe, di nuovo +1
Dr. belisarius

@belisarius ragazzi, per favore vedi la risposta che ho pubblicato. Se è corretto, è più corto.
Mr.Wizard,

1

Python 2, 88 80 75 69 68

s=p=''
for c in raw_input()+' ':a=c.isalpha();s+=p[a:];p=c*a
print s

Ingresso: 435_ASDC__uio;|d re;fG o55677jkl..f

Produzione: CodeGolf


Questa soluzione può essere ridotta a 67 caratteri se si consente all'output di includere caratteri backspace (codice ASCII 8) all'inizio. L'output sarà visivamente identico.

s=p='<BS>'
for c in raw_input()+p:a=c.isalpha();s+=p[a:];p=c*a
print s

Stesso input, (visivamente) stesso output. <BS>è pensato per essere il personaggio del backspace.


1

C #

Metodo, 105 byte: (presuppone l'utilizzo per System, System.Text.RegularExpressions e System.Linq)

string R(string i){return string.Concat(Regex.Split(i,"[^a-zA-Z]").Where(x=>x!="").Select(n=>n.Last()));}

Programma, 211 byte:

using System;using System.Text.RegularExpressions;using System.Linq;class A{static void Main(){Console.WriteLine(string.Concat(Regex.Split(Console.ReadLine(),"[^a-zA-Z]").Where(x=>x!="").Select(n=>n.Last())));}}

1

VBA, 147 161

Sub a(s)
For n=0 To 255:m=Chr(n):s=Replace(s,IIf(m Like"[A-Za-z]","",m)," "):Next
For Each r In Split(s," "):t=t & Right(r,1):Next
MsgBox t
End Sub

1

Ruby 2.0, 25 (+1) caratteri

gsub(/(\w+)\W*/){$1[-1]}

Deve essere eseguito con l' -pinterruttore:

 $ ruby -p ed.rb <<< "asdf jkl;__zxcv~< vbnm,.qwer| |uiop"
flvmrp

Si prega di specificare la rubyversione. 1.9.2 genera "# <Enumeratore: 0x9f65e10> # <Enumeratore: 0x9f65d98> # <Enumeratore: 0x9f65d34> # <Enumeratore: 0x9f65cd0>”.
arte

Hai ragione. Mi ero completamente dimenticato di averlo installato, ma la mia attuale versione di Ruby è 2.0 ( ruby 2.0.0p0 (2013-02-24 revision 39474). Quando si esegue il programma con la versione 1.8.7, viene emesso un valore ASCII! Non sapevo che ci fossero così tante differenze tra le versioni.
daniero,

Grazie, dovrò sicuramente aggiornare il mio Ruby. (. Sia l'interprete e la conoscenza) Il secondo gruppo di cattura non è necessaria: gsub(/(\w+)\W*/){$1[-1]}.
arte

Oh, certo che no. Grazie, aggiornato :)
daniero,

1

Retina , 16 byte

Li, -1|""`[a-z]+

Provalo online!

Spiegazione

Li, -1|""`[a-z]+
L         [a-z]+        List all the sequences of letters in the input
 i                      case insensitive
  ,                     Keep all the results
    -1                  but only the last character for each of them
      |""               Use the empty string as separator


1

Java 8, 43 byte

s->s.replaceAll("(?i).(?=[a-z])|[^a-z]","")

Porta della risposta Retina di @ mbomb007 .

Spiegazione:

Provalo online.

s->  // Method with String as both parameter and return-type
  s.replaceAll("(?i).(?=[a-z])|[^a-z]","")
     //  Remove every match of this regex, and return as result

Spiegazione aggiuntiva per la regex:

"(?i).(?=[a-z])|[^a-z]"  // Main regex to match
 (?i)                    //  Case insensitive
     .                   //   Any character
      (?=[a-z])          //   Followed by a letter (as positive look-ahead)
               |[^a-z]   //   or a non-letter

""                       // Replace it with: nothing

1
Questo è in realtà (?i)per la bandiera.
Jakob,

0

Carattere Smalltalk , Squeak / Pharo
122 con formattazione tradizionale per questo metodo aggiunto a String:

endOfWords
    ^(self subStrings: (CharacterSet allCharacters select: #isLetter) complement) collect: #last as: String

62 caratteri in Pharo 1.4, con regex e strana formattazione

endOfWords^''join:(self regex:'[a-zA-Z]+'matchesCollect:#last)

0

J: 60 caratteri (o 38 caratteri per una versione meno corretta)

(#~e.&(,26&{.&(}.&a.)"0(97 65))){:&>;:]`(' '"_)@.(e.&'_:')"0

Se vogliamo lasciare che il programma si interrompa ogni volta che ci sono parole che terminano in due punti o un trattino basso, allora possiamo semplificare questo a 38 caratteri.

(#~e.&(,26&{.&(}.&a.)"0(97 65))){:&>;:

Esecuzione di esempio:

    (#~e.&(,26&{.&(}.&a.)"0(97 65))){:&>;:]`(' '"_)@.(e.&'_:')"0'asdf jkl;__zxcv~< vbnm,.qwer| |uiop'
flvmrp
    (#~e.&(,26&{.&(}.&a.)"0(97 65))){:&>;:]`(' '"_)@.(e.&'_:')"0'pigs, eat dogs; eat Bob: eat pigs'
ststbts
    (#~e.&(,26&{.&(}.&a.)"0(97 65))){:&>;:]`(' '"_)@.(e.&'_:')"0'99_bottles_of_beer_on_the_wall'
sfrnel

1
38 byte (per una versione corretta): (#~[:2&|64 90 96 122&I.@(u:inv)){:&>;:o 43 byte per una versione non esplicito: (#~[:2&|64 90 96 122&I.@(u:inv))@:({:@>)@;:. Questo utilizza il verbo dell'indice di intervallo I., che interpreta 64 90 96 122come l'insieme di intervalli (__, 64] (64, 90], (90, 96], (96, 122], (122, _)e restituisce l'indice dell'itervale a cui appartiene il suo argomento, il codice ascii del carattere. Se questo indice è dispari, non è alfabetico.
Bolce Bussiere,

@BolceBussiere non funziona con caratteri di sottolineatura per qualche motivo (ultimo caso di test).
FrownyFrog

@FrownyFrog ah, capisco perché, ;:interpreta abc_una parola poiché i nomi delle variabili possono contenere caratteri di sottolineatura. +10 byte da aggiungere (#~~:&'_'), probabilmente una soluzione inefficiente
Bolce Bussiere

@BolceBussiere è giusto '_'-.~o qualcosa di simile.
FrownyFrog,

0

È in PHP . 197 byte :( Sono principiante

$l=$_GET['line'];
$l=preg_replace('/(\W|_)+/',' ',$l);
$s=explode(' ',$l);
foreach($s as $d){
$a=substr($d,-1,1);
$o=ORD($a);
if(($o>=97 && $o<=122) || ($o>=65 && $o<=90)){
echo $a;
  }
}

MODIFICATO Ora sono 171 byte

<?$l=$_GET['l'];$l=preg_replace('/(\W|_)+/',' ',$l);$s=explode(' ',$l);foreach($s as $d){$a=substr($d,-1,1);$o=ORD($a);if(($o>=97&&$o<=122)||($o>=65&&$o<=90)){echo$a;}}

1
Per il golf, dovresti ridurre il più possibile i nomi delle tue variabili a singoli caratteri.
Gaffi,

1
Grazie per avermelo detto. Sono nuovo qui.
Sasori,

Sicuro. Puoi anche cercare qui qualche aiuto aggiuntivo specifico per PHP.
Gaffi,

foreach((' ',preg_replace('/(\W|_)+/',' ',$_GET['line'])) as $d){$a=substr($d,-1,1);$o=ORD();if(($o>=97 && $o<=122) || ($o>=65 && $o<=90)){echo $a;}}è 149, se funziona.
Magic Octopus Urn

\W|_esclude le cifre; quindi dovresti aggiungere \dal tuo regex o usare/[^a-z]+/i
Titus

0

K 30

q)k)f:{x@&-1=-':(1_x," ")in,/.Q`a`A}
q)f "asdf jkl;__zxcv~< vbnm,.qwer| |uiop"
"flvmrp"
q)f "pigs, eat dogs; eat Bob: eat pigs"
"ststbts"
q)f "looc si siht ,gnitirw esreveR"
"citwR"
q)f "99_bottles_of_beer_on_the_wall"
"sfrnel"

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.