Réduire la chaîne à un extrait de l'alphabet

25

Étant donné une chaîne non vide composée uniquement de caractères alphabétiques minuscules et majuscules et d'espaces ( [a-zA-Z ]), réduisez-la à un extrait de l'alphabet, en commençant par le premier caractère.

Pour réduire une chaîne, commencez par le premier caractère alphabétique, puis supprimez tous les caractères suivants qui ne sont pas la prochaine lettre de l'alphabet. Continuez ainsi jusqu'à ce que vous atteigniez la fin de la chaîne.

Par exemple codegolf:

Commencez par c, supprimez ocar ce n'est pas la prochaine lettre de l'alphabet.
Gardez dcomme il est la prochaine lettre de l'alphabet, et de garder ecomme il est la lettre suivante aussi.
Supprimez g, oet let conservez f.

Votre extrait final serait alors cdef

Règles

  • La capitalisation doit être maintenue, ce CodEgolFqui entraîneraitCdEF
  • L'espace n'est pas une lettre de l'alphabet et doit donc toujours être supprimé, même s'il s'agit du début de la chaîne
  • En raison de la nature de la réduction, le premier caractère alphabétique de l'entrée sera toujours le premier caractère de la sortie.
  • zZest la dernière lettre de l'alphabet. Il n'y a pas de lettres après, l'alphabet ne boucle pas.

Cas de test

codegolf -> cdef
CodEgolf -> CdEf
 codeolfg -> cdefg
ProgrammingPuzzles -> P
Stack Exchange -> St
The quick red fox jumped over the lazy brown dog -> Tuvw
Zebra -> Z
Abcdegfhijkl -> Abcdef

Notation

Il s'agit de , donc le moins d'octets dans chaque langue gagne!

Skidsdev
la source
D'après l'avant-dernier cas de test, je vois que si nous atteignons zNous nous arrêtons, non?
M. Xcoder
@ Mr.Xcoder Correct, voir le dernier point sous "Rules"
Skidsdev
2
Veuillez ajouter un cas de test avec un espace au début. Comme:<space>codegolf
M. Xcoder
Puis-je retourner un tableau des lettres de sortie?
TheLethalCoder
1
@ Mr.Xcoder oui vous pouvez
Skidsdev

Réponses:

12

JavaScript (ES6), 66 79 68 67 octets

f=([c,...s],p)=>c?(p?~parseInt(c+p,36)%37:c<'!')?f(s,p):c+f(s,c):''

Comment?

Test des lettres consécutives

Étant donné que la conversion de deux caractères en leurs codes ASCII serait une opération assez longue dans JS, nous utilisons plutôt la formule suivante:

~parseInt(b + a, 36) % 37

Pourvu que a et b soient dans [a-zA-Z ], l'expression ci-dessus est égale 0si et seulement si a et b sont des lettres consécutives (c'est-à-dire des chiffres consécutifs en base 36), peu importe le cas des caractères.

Par exemple:

~parseInt("Y" + "x", 36) = ~(36 * parseInt("Y", 36) + parseInt("x", 36))
                         = ~(36 * 34 + 33)
                         = -(36 * 34 + 33 + 1)
                         = -(37 * 34)

Formaté et commenté

f = ([c,                              // c = current character
         ...s],                       // s = array of remaining characters
                p) =>                 // p = previous matching letter
  c ? (                               // if there's still at least 1 character to process:
      p ?                             //   if p was already defined:
        ~parseInt(c + p, 36) % 37     //     test if p and c are NON-consecutive letters
      :                               //   else:
        c < '!'                       //     test if c is a space character
    ) ?                               //   if the above test passes:
      f(s, p)                         //     ignore c and keep the current value of p
    :                                 //   else:
      c + f(s, c)                     //     append c to the final result and update p to c
  :                                   // else:
    ''                                //   stop recursion

Cas de test

Arnauld
la source
7

Python 2 , 69 octets

lambda s:reduce(lambda x,y:x+y*((ord(y)-ord(x[~0]))%32==1),s.strip())

Essayez-le en ligne!

Une simple réduction de la chaîne. Nous concaténons simplement le caractère suivant si et seulement si (ord(y)-ord(x[~0]))%32==1. Contrôle très moche - je suis sûr qu'il peut être amélioré, mais je ne sais pas comment!

Sisyphe
la source
Solution intelligente! Dommage que ce soit uniquement Python 2: P
M. Xcoder
Vous pouvez le rendre compatible avec Python 3 avec from functools import*.
2017 totalement humain
1
@ThomasWard totalement humain disait aux autres comment le rendre compatible Python 3. Btw, import functools as fet f.est beaucoup plus long que from functools import*sûr, même utilisé une fois. Voir ce fil pour plus d'informations.
M. Xcoder
7

Python 3 , 75 85 84 91 81 77 75 octets

Je pense que c'est aussi court que possible en Python 3 . Il peut être raccourci de quelques octets en Python 2, comme indiqué dans la soumission de Sisyphe .

  • EDIT: +10 pour corriger un bug
  • EDIT: -1 en corrigeant un autre bug
  • EDIT: +7 pour corriger un autre bug
  • EDIT: -10 octets avec l'aide de @Ruud
  • EDIT: -4 octets car l'OP nous a permis de sortir les lettres séparées par une nouvelle ligne
  • EDIT: -2 octets grâce à @Ruud , retour au nombre d'octets d'origine!
s=input().strip();k=0
for i in s:
 if(ord(i)-ord(s[0]))%32==k:k+=1;print(i)

Essayez-le en ligne!

M. Xcoder
la source
J'ai des idées d'amélioration, je vais bientôt jouer au golf sur mobile.
M. Xcoder
2
81 octets . Les majuscules et les minuscules correspondent facilement lorsqu'elles sont modulées par 32
Arfie
@Ruud Ce sont exactement les choses dont je parlais dans mon commentaire, l'édition.
M. Xcoder
79 octets
Arfie
8
J'attends que le downvoter explique ses raisons.
M. Xcoder
6

05AB1E , 13 octets

áćsv¤yìuÇÆiy«

Essayez-le en ligne!

-1 merci à Adnan

Erik le Outgolfer
la source
Pouvez-vous remplacer ðKpar á?
Adnan
@Adnan Je pense que oui ...
Erik the Outgolfer
4

Brachylog , 15 octets

;ṢxS⊇.ḷ~sẠ∧Sh~h

Essayez-le en ligne!

Ce serait 10 octets ⊇.ḷ~sẠ&h~h:, sans la contrainte assez peu intéressante "les chaînes peuvent commencer par des espaces".

Explication

;ṢxS               S is the Input with all spaces removed
   S⊇.             The Output is an ordered subset of the Input
     .ḷ            The Output lowercased…
        ~sẠ          …is a substring of "abcdefghijklmnopqrstuvwxyz"
           ∧
            Sh     The first char of S…
              ~h   …is the first char of the Output

Comme c'est assez déclaratif, c'est aussi très lent.

Fatalize
la source
Eh bien, au moins, il bat Jelly! Et, du côté positif, je ne pense pas que vous puissiez vraiment surpasser cela ...
Erik the Outgolfer
3

MATL , 18 16 15 octets

Merci à Mr.Xcoder d' avoir signalé une erreur, maintenant corrigée

Xz1&)"t@hkd1=?@

Les lettres dans la sortie sont séparées par des retours à la ligne.

Essayez-le en ligne! Ou vérifiez tous les cas de test (le code de pied de page affiche toutes les lettres de sortie sur la même ligne pour plus de clarté).

Explication

Xz       % Implicitly input a string. Remove spaces
1&)      % Push first character and then the remaining substring
"        % For each
  t      %   Duplicate previous character
  @      %   Push current character
  h      %   Concatenate both characters
  k      %   Convert to lowercase
  d      %   Consecutive difference. Gives a number
  1=     %   Is it 1?
  ?      %   If so
    @    %     Push current char
         %   End (implicit)
         % End (implicit)
         % Display stack (implicit)
Luis Mendo
la source
Vous avez oublié de supprimer les espaces lorsqu'ils se trouvent au début de la chaîne: l' espace n'est pas une lettre de l'alphabet et doit donc toujours être supprimé, même s'il s'agit du début de la chaîne .
M. Xcoder
@ Mr.Xcoder Merci! Corrigé
Luis Mendo
3

Java (OpenJDK 8) , 102 101 74 octets

s->{char c=0;for(char x:s)if(c<1&x>32|~-x%32==c%32)System.out.print(c=x);}

Essayez-le en ligne!

-27 octets grâce à @Olivier Grégoire

Nevay
la source
1
75 octets: s->{char c=0;for(char x:s)if(c<33&x>33|~-x%32==c%32)System.out.print(c=x);}(avec char[]comme entrée).
Olivier Grégoire
2

C # (Mono) , 129 107 93 91 87 octets

s=>{var r=s.Trim()[0]+"";foreach(var c in s)if(r[r.Length-1]%32==~-c%32)r+=c;return r;}

Enregistré 2 octets grâce à @Mr. Xcoder.
4 octets enregistrés grâce à @jkelm.

Essayez-le en ligne!

TheLethalCoder
la source
Échoue sur les espaces de tête
Skidsdev
@Mayube Woops n'a pas vu cela, corrigé.
TheLethalCoder
2
91 octets . Dans les langages de type C et Python, (c-1)%32est~-c%32
M. Xcoder
1
87 octets Vous n'avez pas besoin de réaffecter la chaîne coupée à cause des vérifications dans la boucle for
jkelm
2

PHP, 64 + 1 octets

while($c=$argn[$i++])$c<A||$n&&($c&_)!=$n||(print$c)&$n=++$c&__;

Exécuter en tant que pipe avec -nRou l' essayer en ligne .


A part les trucs habituels: Lorsque $catteint Z, ++$centraîne AA,
et &__maintient que la longueur intacte; donc $nne correspondra plus $c.

Titus
la source
2

Haskell, 106 105 97 octets

import Data.Char
import Data.List
z=ord.toUpper
a%b|z a+1==z b=b|0<3=a
nub.scanl1(%).filter(>' ')

J'ai essayé d'utiliser l' fromEnumarithmétique + char au lieu d'importer Data.Char, mais cela a fini par être plus long ...

8 octets enregistrés grâce à H.PWiz!

Essayez-le en ligne.

Cristian Lupascu
la source
102 octets avecfilter
H.PWiz
Ou 100 octets avecData.List
H.PWiz
@ H.PWiz Super! Merci!
Cristian Lupascu
2

Pyth, 21 20 18 octets

ef&qhThQhxGrT0tyr6

Essayez-le ici.

Version 20 octets bien plus efficace:

.U+b?t-CrZ1Creb1kZr6

Essayez-le ici.

-1 merci à M. Xcoder (indirectement).

Erik le Outgolfer
la source
Équivalent: .U+b?tlrreb1rZ1kZrz6(je pense). Mais cette astuce m'a aidé.
M. Xcoder
@ Mr.Xcoder Si c'était un équivalent, j'aurais pu enregistrer un octet avec, .U+b?tlrreb1rZ1kZr6mais r <str> 6signifie malheureusement A.strip(), ne pas supprimer les espaces non précédés ou en fin de chaîne.
Erik the Outgolfer
Oh oui, je n'ai pas vu que votre solution repose sur la suppression de tous les espaces (pas le mien)
M. Xcoder
@ Mr.Xcoder Umm, vous devez supprimer tous les espaces.
Erik the Outgolfer
Non, je ne devrais pas, car l'espace a une valeur ASCII de 32, alors que toutes les lettres l'ont > 64, et n'affecte donc pas la fonctionnalité. Je pense que cela s'applique également à votre réponse.
M. Xcoder
1

Perl 6 , 51 octets

{S:i:g/\s|(\w){}<([<!before "{chr $0.ord+1}">.]+//}

Essaye-le

Étendu:

{  # bare block lambda with implicit parameter $_

  S                          # substitute implicitly on $_, not in-place
  :ignorecase
  :global
  /

    |  \s                    # match any space

    |  (\w)                  # match a word character
       {}                    # make sure $/ is updated (which $0 uses)

       <(                    # ignore everything before this

       [

           <!before "{       # make sure this won't match after this point
             chr $0.ord + 1  # the next ASCII character
           }">

           .                 # any character

       ]+                    # match it at least once

  //                         # remove what matched
}

Notez qu'il <!before …>s'agit d'une assertion de largeur nulle

Brad Gilbert b2gills
la source
1

Japt , 18 17 16 octets

1 octet enregistré grâce à @Shaggy

x
c
Çc %H¥V%H©V°

Testez-le en ligne!

Je pensais que ce serait un peu plus court, mais ... Telle est la vie ...

Explication

x    First line: set U to the result.
x    Trim all spaces off of the input. Only necessary to remove leading spaces.

c    Second line: set V to the result.
c    Take the charcode of the first character in U.

 Ç   c %H¥ V%H© V°
UoZ{Zc %H==V%H&&V++}   Final line: output the result.
UoZ{               }   Filter to only the chars in Z where
    Zc                   the charcode of Z
       %H                mod 32
         ==V%H           equals V mod 32.
              &&V++      If true, increment V for the next letter.
ETHproductions
la source
Plus court que ma parodie de 28 octets, au moins! : D Il semble que vous puissiez remplacer rSpar x.
Shaggy
1

C # (.NET Core) , 70 60 + 18 octets

-10 octets grâce à TheLethalCoder

a=>{var c=a.Trim()[0];return a.Where(x=>x%32==c%32&&++c>0);}

Le nombre d'octets comprend également:

using System.Linq;

Essayez-le en ligne!

1 octet de plus (actuellement) (pas plus) que TheLethalCoder afin de publier pour le plaisir. Approche différente, avec LINQ.

Cela tire parti de deux fonctionnalités de type C en C # - une charvariable de caractère se comporte implicitement de la même manière qu'un entier int, et l'opérateur booléen AND &&n'exécute pas l'opération de droite si left renvoie a false. Explication du code:

a =>                                  // Take string as input
{
    var c = a.Trim()[0];              // Delete leading spaces and take first letter
    return a.Where(                   // Filter out characters from the string, leaving those that:
               x => x % 32 == c % 32  // it's the next character in alphabet case-insensitive (thanks to modulo 32 - credits to previous answers)
               && ++c > 0             // If it is, go to the subsequent character in alphabet (and this always has to return true)
           );
}
Grzegorz Puławski
la source
Supprimez le .ToArray()en revenant en tant que IEnumerable<char>pour enregistrer les octets.
TheLethalCoder
@TheLethalCoder à droite, je viens de voir le commentaire sous le défi. Merci!
Grzegorz Puławski
1

q / kdb +, 47 45 octets

Solution:

{10h$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}

Exemples:

q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"CodEgolf"
"CdEf"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}" codeolfg"
"cdefg"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"ProgrammingPuzzles"
"P"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"The quick red fox jumped over the lazy brown dog"
"Tuvw"

Explication:

Tirer parti de l' mod 32astuce des solutions existantes avec la fonction de convergence . Itérer sur la chaîne, si la différence entre le dernier élément du résultat (par exemple commence par Tpour "Le renard roux rapide ...") et le caractère actuel est 1 (après avoir été mod'd avec 32), alors nous l'ajoutons à le résultat (d'où la raison pour laquelle nous le prenons last x), puis remettez tout en chaîne.

{10h$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x} / the solution
{                                           } / lambda function
                                      trim x  / trim whitespace (leading/trailing)
                                   7h$        / cast string to ASCII (a -> 97)
     ({                         }/)           / converge
                    y-last x                  / y is the next item in the list, x contains results so far
              1=mod[        ;32]              / is the result mod 32 equal to 1
       (x;x,y)                                / if false, return x, if true return x concatenated with y
 10h$                                         / cast back to characters
streetster
la source
1

Perl 5 , 30 + 1 (-n) = 31 octets

/$b/i&&(print,$b=++$_)for/\S/g

Essayez-le en ligne!

Comment?

/$b/i        # check if this letter equals the one in $b, ignore case
&&(print,    # output it if so
$b=++$_)     # store the next character to find
for/\S/g     # Looping over all non-whitespace characters
Xcali
la source
0

Rétine , 76 octets

 

^.
$&$&$&¶
{T`@@L@l`@l@l@`..¶
T`l`L`.¶
(.)(.)((¶).*?(\1|\2)|¶.*)
$5$5$5$4

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

 

Supprimer des espaces.

^.
$&$&$&¶

Tripliquez le premier caractère et insérez un séparateur.

{T`@@L@l`@l@l@`..¶
T`l`L`.¶

Convertissez les deuxième et troisième caractères en minuscules et incrémentez-les. Convertissez ce dernier en majuscules. Ce sont maintenant les caractères de recherche.

(.)(.)((¶).*?(\1|\2)|¶.*)
$5$5$5$4

Essayez de faire correspondre l'un des caractères de recherche. S'il est trouvé, tripliquez la correspondance, ce qui redémarre la boucle pour la prochaine recherche. Sinon, supprimez simplement les caractères de recherche et le reste de l'entrée.

Neil
la source
0

8ème , 114 octets

Code

: z dup n:1+ 32 bor >r "" swap s:+ . ; 
: f s:trim 0 s:@ z ( nip dup 32 bor r@ n:= if rdrop z then ) s:each rdrop ;

Explication

: z             \ n -- (r: x)
                \ print letter and save on r-stack OR-bitwised ASCII code of following letter
  dup           \ duplicate item on TOS
  n:1+          \ get ASCII code of the following letter
  32 bor        \ bitwise OR of ASCII code and 32 
  >r            \ save result on r-stack
  "" swap s:+ . \ print letter
;

: f        \ s -- 
  s:trim   \ remove trailing whitespace
  0 s:@    \ get 1st letter
  z        \ print 1st letter and save on r-stack OR-bitwised ASCII code of following letter
  ( nip    \ get rid of index
    dup    \ duplicate item on TOS
    32 bor \ bitwise OR of current ASCII code and 32 
    r@     \ get value stored on r-stack
    n:=    \ compare values to see if letter is printable or not
    if 
      rdrop \ clean r-stack
      z     \ print letter and save on r-stack OR-bitwised ASCII code of following letter
    then 
  ) 
  s:each    \ handle each character in string
  rdrop     \ clean r-stack
;

Exemple

ok> " The quick red fox jumped over the lazy brown dog" f
Tuvw
Manoir du Chaos
la source
0

Pyth, 15 octets

eo,}r0NG_xQhNty

Suite de tests

Contrairement à toutes les autres réponses, cela ne colle pas la sortie, il génère toutes les sous-séquences de l'entrée, puis leur ordonne de mettre la chaîne souhaitée à la fin, et la sort.

isaacg
la source
Je pense que vous devez vérifier si la première lettre de la sortie est également la première lettre de l'entrée. Et je pense que l'ordre initial est important.
Erik the Outgolfer
@EriktheOutgolfer Désolé, vous dites que la réponse est fausse? Je m'assure que la séquence dont le premier caractère est le plus ancien dans l'entrée parmi toutes les sous-séquences qui sont en ordre alphabétique est celle triée jusqu'à la fin. Voir le cas de test commençant par un espace.
isaacg
Pouvez-vous ajouter une explication s'il vous plaît? J'ai peut-être mal compris ou quelque chose ...
Erik the Outgolfer
0

J, solution partielle

Je publie ceci pour des commentaires et des idées d'amélioration plus que toute autre chose. Cela fonctionne, mais ne gère pas les cas de majuscules et de bord d'espace, et c'est déjà long pour J.

D'abord un verbe auxiliaire dyadique qui vous indique si les arguments gauche et droit sont alphabétiquement adjacents:

g=.(= <:)&(a.&i.)  NB. could save one char with u:

Ensuite un verbe qui supprime le premier élément qui ne fait pas partie d'une séquence alphabétique à partir du premier élément:

f=.({~<^:3@>:@i.&0@(0,~2&(g/\))) ::]

Notez que nous utilisons Adverse ::pour retourner l'intégralité de l'argument s'il n'y a pas d'élément non-séquence trouvé (c'est-à-dire si l'argument entier est une séquence alphabétique valide).

Enfin, la solution est donnée en appliquant fjusqu'à la convergence:

f^:_ 'codegolf'  NB. => 'cdef'

Essayez-le en ligne!


Et voici une version analysée de fpour une lecture plus facile:

           ┌─ ~ ─── {                         
           │                              ┌─ <
           │                       ┌─ ^: ─┴─ 3
           │                 ┌─ @ ─┴─ >:      
       ┌───┤           ┌─ @ ─┴─ i.            
       │   │     ┌─ & ─┴─ 0                   
       │   │     │                            
       │   └─ @ ─┤     ┌─ 0                   
── :: ─┤         │     ├─ ~ ─── ,             
       │         └─────┤                      
       │               │     ┌─ 2             
       │               └─ & ─┴─ \ ─── / ──── g
       └─ ]         

Question secondaire : pourquoi les caractères de la boîte ne s'alignent-ils pas parfaitement lorsqu'ils sont affichés sur SO (ils fonctionnent dans ma console):

Jonas
la source