O mundo acaba em

21

Retirado diretamente do ACM Winter Programming Contest 2013. Você é uma pessoa que gosta de interpretar as coisas literalmente. Portanto, para você, o fim do mundo é ed; as últimas letras de "O" e "Mundo" concatenaram.

Faça um programa que use uma frase e imprima a última letra de cada palavra nessa frase no menor espaço possível (menos bytes). As palavras são separadas por qualquer coisa, exceto letras do alfabeto (65 - 90, 97 - 122 na tabela ASCII.) Isso significa sublinhados, til, sepulturas, chaves, etc. são separadores. Pode haver mais de um separador entre cada palavra.

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

beary605
fonte
Você poderia adicionar um caso de teste incluindo dígitos e sublinhados?
grc 12/03
10
O mundo acaba em algo? Eu sabia que o vim e o Emacs não conseguiam se adaptar!
Joe Z.
Bem, o ensaio “homens de verdade usam ed” faz parte da distribuição do Emacs desde que me lembro.
JB
As entradas serão apenas ASCII?
26718 Phil H

Respostas:

16

Perl 5, 18 bytes

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

Requer uma -popção de linha de comando. A propriedade nomeada Lcorresponde apenas aos caracteres da letra A-Za-z. Existem várias centenas dessas propriedades nomeadas, mas ao lidar com texto ASCII, muito poucas são interessantes. Além disso \pL, a única outra nota real é a \pPque corresponde à pontuação.

Experimente online!


Perl 5, 17 bytes

Uma melhoria de um byte por Dom Hastings

print/\pL*(\pL)/g

Requer -n(e -lpara suportar várias entradas).

Experimente online!


Uso da amostra

$ 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
primo
fonte
Eu acho que \wtambém combina dígitos e sublinhados.
grc 11/03/13
Hmm, de fato. Isso precisará ser atualizado.
Primo
2
Brilhante. Regex era uma solução óbvia, mas |.não era óbvia (para mim, pelo menos).
Peter Taylor
11
Só notei que um -1in print/\pL*(\pL)/g, parece produzir o mesmo para seus casos de teste!
Dom Hastings
18

ed, 35 caracteres

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

Então, o mundo termina em ed. Como gosto de ser literal demais, decidi escrever para escrever a solução com ed - e, aparentemente, é realmente uma linguagem de programação . É surpreendentemente curto, mesmo considerando que muitas soluções mais curtas já existem neste segmento. Seria melhor se eu pudesse usar algo diferente [a-zA-Z], mas considerando que ed não é uma linguagem de programação, é realmente bom o suficiente.

Primeiro, eu gostaria de dizer que isso apenas analisa a última linha do arquivo. Seria possível analisar mais, basta digitar ,no início das duas primeiras linhas (isso especificou o intervalo "tudo", em oposição ao intervalo padrão da última linha), mas isso aumentaria o tamanho do código para 37 caracteres.

Agora, para explicações. A primeira linha faz exatamente o que a solução Perl faz (exceto sem suporte para caracteres Unicode). Não copiei a solução Perl, apenas inventei algo semelhante por coincidência.

A segunda linha imprime a última linha, para que você possa ver a saída. As forças da terceira linha são encerradas - eu tenho que fazer isso, caso contrário, edseria impresso ?para lembrá-lo de que você não salvou o arquivo.

Agora, como executá-lo. Bem, é muito simples. Basta executar edcom o arquivo que contém o caso de teste, enquanto canaliza meu programa, assim.

ed -s testcase < program

-sé silencioso. Isso impede a edsaída de um tamanho de arquivo feio no início. Afinal, eu o uso como um script, não como editor, portanto não preciso de metadados. Se eu não fizesse isso, ed mostraria o tamanho do arquivo que não poderia impedir de outra forma.

Konrad Borowski
fonte
Eu instalei o ed apenas para tentar isso.
primo
6

Javascript, 49

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

Ele usa uma expressão regular para remover todos os caracteres anteriores a uma letra, bem como todos os caracteres que não são da letra. Então ficamos com a última letra de cada palavra.

Obrigado a tomsmeding por uma boa melhoria.

grc
fonte
3
Provavelmente, você pode melhorar esta fazendo a regex case-insensitive, como em:alert(prompt().replace(/.(?=[a-z])|[^a-z]/gi,''))
tomsmeding
6

C, 78

Golfe:

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

Com espaço em branco:

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

Saída:

insira a descrição da imagem aqui

JoeFish
fonte
11
Você pode salvar 4 bytes usando a declaração K&R e o padrão 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

Teste

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

Executar sed:

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

Saída:

flvmrp
ststbts
citwR

Explicação

A primeira substituição substitui todos os limites de palavras precedidos pelo grupo de correspondência desejado por uma nova linha. Isso facilita a remoção de todos os caracteres estranhos na segunda substituição.

Editar

  • Use sinalizador sem distinção entre maiúsculas e minúsculas (-2), graças a manatwork .
  • Não conte com espaço em branco (-1).
Thor
fonte
sed's scomando tem ibandeira para casos de correspondência insensível: s/[a-z]\b/&\n/gi.
manatwork
@manatwork: bom ponto, isso tornaria o GNU sed apenas, mas parece que já é, obrigado.
Thor
\bconsidera _s para ser letras, por isso, se qualquer palavra no teste END com _, última carta que sua palavra não está incluído na saída
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 for necessária uma nova linha final, substitua tr -d \\npor paste -sd ''.

Editar

  • Use grep que não diferencia maiúsculas de minúsculas (-2), graças ao manatwork .
  • Use em trvez de paste(-4), obrigado manatwork .
  • Não conte espaço em branco ao redor do pipe (-2).
Thor
fonte
Bastante criativo com isso paste -sd '', mas tr -d \\né mais curto. No que diz respeito grep, tem -iinterruptor significado “ignorar caso”, o que pode torná-lo mais curto: grep -io '[a-z]\b'.
manatwork
@manatwork, trtambém exclua a nova linha final. O modo que não diferencia maiúsculas de minúsculas é obviamente mais curto, obrigado.
Thor
não há regra que exija nova linha final.
manatwork
@ manatwork: Posso concordar com isso, resposta atualizada.
Thor
3

sed, 37 caracteres

Comprimento igual à resposta de Thor , mas, eu acho, mais simples.

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

A lógica é bastante trivial - substitua as seqüências de letras pela última letra e exclua todas as não letras.

Ugoren
fonte
3

Mathematica, 39

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

Teste:

""<>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"}
Mr.Wizard
fonte
Um bom. LetterQdeve ser chamado LettersQ:) Eu não pensei nisso para testar seqüências de caracteres inteiras.
Dr. belisarius
@belisarius Na verdade, com essa construção, ela é aplicada em caracteres, para que possa ser uma "LetterQ" literal e ainda funcione.
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"
tmartin
fonte
2

Scala, 59 (ou 43)

Supondo que a string já esteja em s:

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

Se você precisa ler a partir de um prompt e imprimir ao invés de usar a saída REPL, convertido spara readLinee embrulhe em println()para 59.

Rex Kerr
fonte
2

x86: 54 bytes

Assuma uma rotina de cdecl com a assinatura 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
user1354557
fonte
11
A propósito, percebo que a pergunta pede um programa e não uma rotina , mas eu queria fazer algo diferente. Ao contrário da declaração do problema, acho que não sou uma "pessoa que gosta de interpretar as coisas literalmente", afinal. : P
user1354557
2

Xi, 32

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

O Xi é um idioma ainda em fase beta, mas parece funcionar bem com o código golf, então imaginei que também poderia mostrar outra solução curta e funcional (e anunciar um pouco o idioma :-)).

arshajii
fonte
2

Mathematica 62 57 52

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

Teste

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}*)
Dr. belisarius
fonte
Editei por engano o seu, mas o revirei. Opa.
DavidC
2

Python3, 59 caracteres

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

Lida corretamente com letras maiúsculas e sublinhados. O 2 é para passar re.suba re.IGNORECASEbandeira sem ter que usar re.I.

Realeza Nolen
fonte
2

Python, 76 caracteres

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

indrajeet
fonte
Você pode remover o espaço depois print.
Flornquake 29/03
Reduza portando para Python 3:import re;print(*re.findall("([a-zA-Z])(?=$|[^a-zA-Z])",input()),sep='')
Steven Rumbalski 29/03
1

Python 3.x, 64 bytes

import re;print(''.join(a[-1] for a in re.split('\W+',input())))
Michael0x2a
fonte
2
O último exemplo não está funcionando. Além disso, ocorre um erro se a linha começar ou terminar com um separador
AMK
Você pode remover o espaço antes for.
Bakuriu
1

Lua, 42

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

Exemplo de uso: lua script.lua "asdf jkl;__zxcv~< vbnm,.qwer| |uiop"

Egor Skriptunoff
fonte
1

Mathematica 71 47 45 61

De volta à prancheta, depois que o @belisarius encontrou um erro no código.

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

Teste

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

DavidC
fonte
\\wcorresponde _, portanto, não funciona (por exemplo)"asdf jkl__zxcv~<vbnm,.qwer| |uiop"
Dr. belisarius 13/03
A espera Row@StringTake[ StringCases[#, LetterCharacter ..], -1] &@"asdf jkl__zxcv~<vbnm,.qwer| |uiop"me dá flvmrp, mas #~StringCases~RegularExpression@"\\w\\b" <> "" &@"asdf jkl__zxcv~<vbnm,.qwer| |uiop"retorna fvmrpaqui. Estamos obtendo os mesmos resultados?
Dr. belisarius
@belisarius Você estava certo sobre o erro na minha versão anterior. Eu estava testando com a corda errada!
DavidC
Hehe, +1 novamente
Dr. belisarius
pessoal @belisarius, por favor, veja a resposta que eu postei. Se estiver correto, é mais curto.
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

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

Saída: CodeGolf


Esta solução pode ser reduzida para 67 caracteres se você permitir que a saída inclua caracteres de backspace (código ASCII 8) no início. A saída será visualmente idêntica.

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

Mesma entrada, (visualmente) mesma saída. <BS>deve ser o caractere de backspace.

flornquake
fonte
1

C #

Método, 105 bytes: (assume utilizações para 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()));}

Programa, 211 bytes:

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())));}}
It'sNotALie.
fonte
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
Gaffi
fonte
1

Caracteres Ruby 2.0, 25 (+1)

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

Deve ser executado com o -pcomutador:

 $ ruby -p ed.rb <<< "asdf jkl;__zxcv~< vbnm,.qwer| |uiop"
flvmrp
daniero
fonte
Por favor especifique a rubyversão. 1.9.2 gera "# <Enumerador: 0x9f65e10> # <Enumerador: 0x9f65d98> # <Enumerador: 0x9f65d34> # <Enumerador: 0x9f65cd0>".
manatwork
Você está certo. Eu tinha esquecido completamente que o instalei, mas minha versão atual do Ruby é 2.0 ( ruby 2.0.0p0 (2013-02-24 revision 39474). Ao executar o programa com a versão 1.8.7, ele gera um valor ASCII! Não sabia que havia tantas diferenças entre as versões.
Daniero 15/06
Obrigado, definitivamente terei que atualizar meu Ruby. (. Tanto o intérprete e o conhecimento) O segundo grupo de captura não é necessária: gsub(/(\w+)\W*/){$1[-1]}.
manatwork
Ah, claro que não é. Obrigado, atualizado :)
daniero
1

Retina , 16 bytes

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

Experimente online!

Explicação

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
Leo
fonte
1

Java 8, 43 bytes

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

Porto da resposta Retina de @ mbomb007 .

Explicação:

Experimente 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

Explicação adicional para a 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
Kevin Cruijssen
fonte
11
Isso é realmente (?i)para a bandeira.
Jakob
0

Smalltalk , Squeak / Pharo sabor
122 char com formatação tradicional para este método adicionado à String:

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

62 caracteres no Pharo 1.4, com regex e formatação estranha

endOfWords^''join:(self regex:'[a-zA-Z]+'matchesCollect:#last)
aka.nice
fonte
0

J: 60 caracteres (ou 38 caracteres para uma versão menos correta)

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

Se quisermos que o programa seja interrompido sempre que houver palavras que terminem em dois-pontos ou sublinhado, podemos simplificá-lo para 38 caracteres.

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

Exemplo de execução:

    (#~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
SL2
fonte
11
38 Bytes (para a versão correcta): (#~[:2&|64 90 96 122&I.@(u:inv)){:&>;:ou 43 bytes para uma versão não-explícita: (#~[:2&|64 90 96 122&I.@(u:inv))@:({:@>)@;:. Isso usa o verbo do índice de intervalo I., que interpreta 64 90 96 122como o conjunto de intervalos (__, 64] (64, 90], (90, 96], (96, 122], (122, _)e retorna o índice do iterval ao qual seu argumento, o código ascii do caractere, pertence. Se esse índice é ímpar, não é alfabético.
Bolce Bussiere
O @BolceBussiere não funciona com sublinhados por algum motivo (último caso de teste).
FrownyFrog
@FrownyFrog ah, vejo o porquê, ;:interpreta abc_como uma palavra, pois os nomes das variáveis ​​podem conter sublinhados. +10 bytes para adicionar (#~~:&'_'), provavelmente uma correção ineficiente
Bolce Bussiere
@BolceBussiere que é justo '_'-.~ou algo parecido.
FrownyFrog
0

Está em PHP . 197 bytes :( eu sou iniciante

$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;
  }
}

EDITADO Agora são 171 bytes

<?$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;}}
Sasori
fonte
11
Para o golfe, você deve reduzir o máximo possível os nomes das variáveis ​​para caracteres únicos, no mínimo.
Gaffi
11
Agradeço o seu contato e fico à total disposição para futuras dúvidas.
Sasori
Certo. Você também pode procurar aqui uma ajuda adicional específica do 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 funcionar.
Magic Octopus Urn
\W|_exclui dígitos; então você deve adicionar \dao seu regex ou usar #/[^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"
rrr
fonte
0

Japt v2, 16 bytes

r/\L*\l+)\L*/@YÌ

Tente

Shaggy
fonte
Eu acho que você pode simplesmente fazer f"%l(?!%l)" q(não funciona na v2 porque o analisador não gosta do (?)
ETHproductions