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!


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


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!


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!


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


8
J'attends que le downvoter explique ses raisons.
M. Xcoder


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.


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)

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


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!


É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.




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).


É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



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.

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

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

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

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.


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



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.


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):

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.