Le monde se termine en ed


21

Tiré directement du Concours de programmation d'hiver ACM 2013. Vous êtes une personne qui aime prendre les choses au pied de la lettre. Par conséquent, pour vous, la fin du Monde est finie; les dernières lettres de "The" et "World" concaténées.

Créez un programme qui prend une phrase et affichez la dernière lettre de chaque mot de cette phrase dans le moins d'espace possible (le moins d'octets). Les mots sont séparés par autre chose que des lettres de l'alphabet (65 - 90, 97 - 122 sur la table ASCII.) Cela signifie que les traits de soulignement, les tildes, les tombes, les accolades, etc. sont des séparateurs. Il peut y avoir plus d'un séparateur entre chaque mot.

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


Pourriez-vous ajouter un cas de test comprenant des chiffres et des traits de soulignement?
grc

10
Le monde se termine en ed? Je savais que Vim et Emacs ne pouvaient pas mesurer!
Joe Z.

Eh bien, l'essai «les vrais hommes utilisent ed» fait partie de la distribution d'Emacs depuis aussi longtemps que je me souvienne.
JB

Les entrées seront-elles uniquement ASCII?
Phil H

Réponses:


16

Perl 5, 18 octets

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

Nécessite un -pcommutateur de ligne de commande. La propriété nommée Lcorrespond uniquement aux caractères de lettre A-Za-z. Il existe plusieurs centaines de ces propriétés nommées, mais quand il s'agit de texte ASCII, très peu d'entre elles sont intéressantes. En outre \pL, la seule autre note réelle est\pP qui correspond à la ponctuation.

Essayez-le en ligne!


Perl 5, 17 octets

Une amélioration d'un octet par Dom Hastings

print/\pL*(\pL)/g

Nécessite -n(et -lpour prendre en charge plusieurs entrées).

Essayez-le en ligne!


Exemple d'utilisation

$ 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

Je pense que cela \wcorrespond également aux chiffres et aux traits de soulignement.
grc

Hmm, en effet. Cela devra être mis à jour.
primo

2
Brillant. Regex était une solution évidente, mais |.n'était pas évidente (du moins pour moi).
Peter Taylor

1
Je viens de remarquer un -1in print/\pL*(\pL)/g, semble produire la même chose pour vos cas de test!
Dom Hastings

18

ed, 35 caractères

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

Ainsi, le monde se termine en éd. Comme j'aime être trop littéral, j'ai décidé d'écrire pour écrire la solution avec ed - et apparemment c'est en fait un langage de programmation . C'est étonnamment court, même si de nombreuses solutions plus courtes existent déjà dans ce fil. Ce serait plus agréable si je pouvais utiliser autre chose que [a-zA-Z], mais étant donné que ed n'est pas un langage de programmation, il est en fait assez bon.

Tout d'abord, je voudrais dire que cela analyse uniquement la dernière ligne du fichier. Il serait possible d'analyser davantage, il suffit de taper, au début des deux premières lignes (cette plage "tout" spécifiée, par opposition à la plage de dernière ligne standard), mais cela augmenterait la taille du code à 37 caractères.

Maintenant pour des explications. La première ligne fait exactement ce que fait la solution Perl (sauf sans prise en charge des caractères Unicode). Je n'ai pas copié la solution Perl, j'ai juste inventé quelque chose de similaire par hasard.

La deuxième ligne imprime la dernière ligne, vous pouvez donc voir la sortie. La troisième ligne force à quitter - je dois le faire, sinon edj'imprimerais? pour vous rappeler que vous n'avez pas enregistré le fichier.

Maintenant, comment l'exécuter. Eh bien, c'est très simple. Exécutez simplement edle fichier contenant le cas de test, tout en canalisant mon programme, comme ça.

ed -s testcase < program

-sest silencieuse. Cela empêche edde sortir une taille de fichier laide au début. Après tout, je l'utilise comme script, pas comme éditeur, donc je n'ai pas besoin de métadonnées. Si je ne le faisais pas, ed montrerait la taille du fichier que je ne pourrais pas empêcher autrement.


J'ai installé ed juste pour essayer cela.
primo

6

Javascript, 49

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

Il utilise une expression régulière pour supprimer tous les caractères qui précèdent une lettre, ainsi que tous les caractères non-lettre. Ensuite, nous nous retrouvons avec la dernière lettre de chaque mot.

Merci à tomsmeding pour une belle amélioration.


3
Vous pouvez probablement améliorer cela en rendant le regex insensible à la casse, comme dans:alert(prompt().replace(/.(?=[a-z])|[^a-z]/gi,''))
tomsmeding

6

C, 78

Golfé:

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

Avec espace:

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

Sortie:

enter image description here


1
Vous pouvez économiser 4 octets en utilisant la déclaration K&R et la valeur par défaut 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

Essai

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

Exécutez sed:

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

Sortie:

flvmrp
ststbts
citwR

Explication

La première substitution remplace toutes les limites de mots, qui sont précédées par le groupe de correspondance souhaité, par une nouvelle ligne. Cela facilite la suppression de tous les caractères étrangers dans la deuxième substitution.

modifier

  • Utilisez un drapeau insensible à la casse (-2), merci manatwork .
  • Ne comptez pas les espaces (-1).

sedde » sla commande a idrapeau pour les cas correspondant insensible: s/[a-z]\b/&\n/gi.
manatwork

@manatwork: bon point, cela ne ferait que GNU sed, mais il semble que ce soit déjà le cas, merci.
Thor

\bconsidère _s comme des lettres, donc s'il y a des mots dans le test FIN avec _, la dernière lettre de ce mot n'est pas incluse dans la sortie
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

Si une nouvelle ligne finale est nécessaire, remplacez-la tr -d \\npar paste -sd ''.

modifier

  • Utilisez grep insensible à la casse (-2), merci manatwork .
  • Utilisez trau lieu de paste(-4), merci manatwork .
  • Ne comptez pas les espaces autour du tuyau (-2).

Assez créatif avec ça paste -sd '', mais tr -d \\nc'est plus court. En ce qui concerne grep, il a le -isens de l' interrupteur « ignorer la casse », ce qui peut le rendre plus court: grep -io '[a-z]\b'.
manatwork

@manatwork, trsupprimez également la nouvelle ligne finale. Le mode insensible à la casse est bien sûr plus court, merci.
Thor

il n'y a pas de règle exigeant une nouvelle ligne finale.
manatwork

@manatwork: Je suis d'accord avec ça, réponse mise à jour.
Thor

3

sed, 37 caractères

Longueur égale à la réponse de Thor , mais, je pense, plus simple.

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

La logique est assez banale - remplacez les séquences de lettres par leur dernière lettre, puis supprimez toutes les non-lettres.


3

Mathematica, 39

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

Tester:

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

Bon. LetterQdevrait être appelé LettersQ:) Je n'y ai pas pensé pour tester des chaînes entières.
Dr belisarius

@belisarius En fait, avec cette construction, elle est appliquée au niveau des caractères, ce pourrait donc être un "LetterQ" littéral et continuer à fonctionner.
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 (ou 43)

En supposant que la chaîne est déjà dans s:

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

Si vous devez lire à partir d'une invite et imprimer plutôt que d'utiliser la sortie REPL, convertissez sen readLineet encapsulez println()pour 59.


2

x86: 54 octets

Supposons une routine cdecl avec la signature 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
Soit dit en passant, je réalise que la question demande un programme et non une routine , mais je voulais faire quelque chose de différent. Contrairement à l'énoncé du problème, je suppose que je ne suis pas "une personne qui aime prendre les choses au pied de la lettre" après tout. : P
user1354557

2

Xi, 32

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

Xi est un langage encore dans sa phase bêta, mais il semble bien fonctionner avec le code golf alors j'ai pensé que je pourrais aussi bien montrer une autre solution courte et fonctionnelle (et annoncer un peu le langage :-)).


2

Mathematica 62 57 52

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

Essai

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}*)

J'ai par erreur modifié le vôtre, mais je l'ai ensuite annulé. Oups.
DavidC

2

Python3, 59 caractères

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

Traite correctement les majuscules et les soulignements. Le 2 est de passer re.suble re.IGNORECASEdrapeau sans avoir à utiliser re.I.


2

Python, 76 caractères

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


Vous pouvez supprimer l'espace après print.
flornquake

Raccourcissez en import re;print(*re.findall("([a-zA-Z])(?=$|[^a-zA-Z])",input()),sep='')
effectuant le

1

Python 3.x, 64 octets

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

2
Le dernier exemple ne fonctionne pas. En outre, une erreur se produit si la ligne commence ou se termine par un séparateur
AMK

Vous pouvez supprimer l'espace avant for.
Bakuriu

1

Lua, 42

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

Exemple d'utilisation: lua script.lua "asdf jkl;__zxcv~< vbnm,.qwer| |uiop"


1

Mathematica 71 47 45 61

Retour à la planche à dessin, après que @belisarius a trouvé une erreur dans le code.

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

Essai

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


\\wmatchs _, donc cela ne fonctionne pas pour (par exemple)"asdf jkl__zxcv~<vbnm,.qwer| |uiop"
Dr. belisarius

Attends Row@StringTake[ StringCases[#, LetterCharacter ..], -1] &@"asdf jkl__zxcv~<vbnm,.qwer| |uiop"me donne flvmrp, mais #~StringCases~RegularExpression@"\\w\\b" <> "" &@"asdf jkl__zxcv~<vbnm,.qwer| |uiop"revient fvmrpici. Obtenons-nous les mêmes résultats ??
Dr belisarius

@belisarius Vous aviez raison sur l'erreur dans ma version précédente. Je le testais avec la mauvaise chaîne!
DavidC

Hehe, +1 à nouveau
Dr belisarius

@belisarius les gars, veuillez voir la réponse que j'ai postée. Si c'est correct, c'est plus court.
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

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

Sortie: CodeGolf


Cette solution peut être raccourcie à 67 caractères si vous autorisez la sortie à inclure des caractères de retour arrière (code ASCII 8) au début. La sortie sera visuellement identique.

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

Même entrée, (visuellement) même sortie. <BS>est censé être le caractère de retour arrière.


1

C #

Méthode, 105 octets: (suppose des utilisations pour System, System.Text.RegularExpressions et System.Linq)

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

Programme, 211 octets:

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) caractères

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

Doit être exécuté avec le -pcommutateur:

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

Veuillez spécifier la rubyversion. 1.9.2 affiche «# <Enumerator: 0x9f65e10> # <Enumerator: 0x9f65d98> # <Enumerator: 0x9f65d34> # <Enumerator: 0x9f65cd0>».
manatwork

Tu as raison. J'avais complètement oublié que je l'avais installé, mais ma version actuelle de Ruby est 2.0 ( ruby 2.0.0p0 (2013-02-24 revision 39474). Lors de l'exécution du programme avec la version 1.8.7, il génère une valeur ASCII! Je ne savais pas qu'il y avait tant de différences entre les versions.
daniero

Merci, devra certainement mettre à jour mon Ruby. (. Les deux l'interprète et les connaissances) Le deuxième groupe de capture n'est pas nécessaire: gsub(/(\w+)\W*/){$1[-1]}.
manatwork

Oh, bien sûr que non. Merci, mis à jour :)
daniero

1

Rétine , 16 octets

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

Essayez-le en ligne!

Explication

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 octets

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

Port de la réponse Retina de @ mbomb007 .

Explication:

Essayez-le en ligne.

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

Explication supplémentaire pour l'expression régulière:

"(?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
C'est en fait (?i)pour le drapeau.
Jakob

0

Smalltalk , Squeak / Pharo flaveur
122 caractères avec une mise en forme traditionnelle pour cette méthode ajoutée à String:

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

62 caractères dans Pharo 1.4, avec regex et formatage bizarre

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

0

J: 60 caractères (ou 38 caractères pour une version moins correcte)

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

Si nous voulons laisser le programme s'arrêter chaque fois qu'il y a des mots se terminant par deux points ou un trait de soulignement, nous pouvons simplifier cela à 38 caractères.

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

Exemple d'exécution:

    (#~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 octets (pour une version correcte): (#~[:2&|64 90 96 122&I.@(u:inv)){:&>;:, ou 43 octets pour une version non explicite: (#~[:2&|64 90 96 122&I.@(u:inv))@:({:@>)@;:. Celui-ci utilise le verbe d'index d'intervalle I., qui interprète 64 90 96 122comme l'ensemble d'intervalles (__, 64] (64, 90], (90, 96], (96, 122], (122, _), et renvoie l'index de l'iterval auquel appartient son argument, le code ascii du caractère. Si cet index est impair, il n'est pas alphabétique.
Bolce Bussiere

@BolceBussiere ne fonctionne pas avec les traits de soulignement pour une raison quelconque (dernier cas de test).
FrownyFrog

@FrownyFrog ah, I see why, ;: interprets abc_ as one word since variable names can contain underscores. +10 bytes to add (#~~:&'_'), probably an inefficient fix
Bolce Bussiere

@BolceBussiere that’s just '_'-.~ or something similar.
FrownyFrog

0

It's in PHP. 197 bytes :( I'm beginner

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

EDITED Now it's 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;}}

1
For golf, you should as much as possible reduce your variable names to single characters at the very least.
Gaffi

1
edited it.Thanks for telling me.I'm new here.
Sasori

Sure. You may also want to look here for some additional PHP-specific help.
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;}} is 149, if it works.
Magic Octopus Urn

\W|_ excludes digits; so you should add \d to your regex or use /[^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"

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.