Marche alphabétique optimale


30

Étant donné une chaîne d'entrée composée uniquement de lettres, renvoyez la taille de pas qui entraîne le nombre minimum de pas nécessaires pour visiter toutes les lettres dans l'ordre sur un alphabet d'habillage, en commençant par n'importe quelle lettre.

Par exemple, prendre la parole, dog. Si nous utilisons une taille de pas de 1, nous nous retrouvons avec:

defghijklmnopqrstuvwxyzabcdefg   Alphabet
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
defghijklmnopqrstuvwxyzabcdefg   Visited letters
d          o                 g   Needed letters

Pour un total de 30 étapes.

Cependant, si nous utilisons une taille de pas de 11, nous obtenons:

defghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg
^          ^          ^          ^          ^          ^
d          o          z          k          v          g   Visited letters
d          o                                           g   Needed letters

Pour un total de 6 étapes. Il s'agit du nombre minimum d'étapes, donc le résultat de retour pour dogest la taille de l'étape; 11.

Cas de test:

"dog"      -> 11
"age"      -> 6
"apple"    -> 19
"alphabet" -> 9
"aaaaaaa"  -> 0 for 0 indexed, 26 for 1 indexed
"abcdefga" -> 1 or 9
"aba"      -> Any odd number except for 13
"ppcg"     -> 15
"codegolf" -> 15
"testcase" -> 9
"z"        -> Any number
"joking"   -> 19

Règles

  • L'entrée sera une chaîne non vide ou un tableau de caractères composé uniquement des lettres aà z(vous pouvez choisir entre majuscules ou minuscules)
  • La sortie peut être 0 indexée (c'est-à-dire la plage 0-25) ou 1 indexée ( 1-26)
  • S'il y a une égalité, vous pouvez sortir n'importe quelle taille de pas ou tous
  • Il s'agit de , donc le plus petit nombre d'octets pour chaque langue gagne!

Avons-nous besoin de gérer une entrée vide?
pizzapants184

1
@ pizzapants184 Non. J'ai mis à jour la question pour spécifier que l'entrée ne sera pas vide
Jo King

Pouvons-nous prendre l'entrée comme un tableau de caractères?
Shaggy

@Shaggy Bien sûr que vous pouvez
Jo King

Y a-t-il une raison pour laquelle cela utilise des lettres au lieu de chiffres?
Wheat Wizard

Réponses:


6

Fusain , 41 octets

≔EEβEθ∧μ⌕⭆β§β⁺⌕β§θ⊖μ×κξλ⎇⊕⌊ιΣι⌊ιθI⌕θ⌊Φθ⊕ι

Essayez-le en ligne! Le lien est vers la version détaillée du code. 0 indexé. Explication:

Eβ

Faites une boucle sur les 26 tailles de pas. (En fait, je boucle sur l'alphabet en minuscules ici et j'utilise la variable d'index.)

Eθ∧μ

Faites une boucle sur chaque caractère de l'entrée après le premier.

⭆β§β⁺⌕β§θ⊖μ×κξ

Bouclez 26 fois et générez la chaîne de caractères résultante en effectuant 26 pas à la taille de pas donnée commençant (indexé 0) avec le caractère précédent de l'entrée.

⌕...λ

Recherchez la position du caractère actuel de l'entrée dans cette chaîne, ou -1 s'il n'est pas trouvé.

E...⎇⊕⌊ιΣι⌊ι

Prenez la somme de toutes les positions, sauf si aucune n'a été trouvée, auquel cas utilisez -1.

≔...θ

Économisez les sommes.

⌊Φθ⊕ι

Trouvez la somme minimale non négative.

I⌕θ...

Trouvez la première taille de pas avec cette somme et sortez-la.


5

JavaScript, 143 octets

w=>(a=[...Array(26).keys(m=1/0)]).map(s=>~[...w].map(c=>(t+=a.find(v=>!p|(u(c,36)+~v*s-u(p,36))%26==0),p=c),p=t=0,u=parseInt)+t<m&&(m=t,n=s))|n

Essayez-le en ligne!

Grâce à Shaggy, l'utilisation [...Array(26).keys()]économise 9 octets.



4

Gelée , 28 26 23 octets

S;þḅ26ŒpṢƑƇIŻ€S:g/ƊÞḢg/

La sortie est indexée 0. L'entrée est un bytestring et peut être dans tous les cas, mais les majuscules sont beaucoup plus rapides.

L'entrée d'une seule lettre doit être placée dans un boîtier spécial et coûte 2 octets. ._.

Essayez-le en ligne!

Notez qu'il s'agit d'une approche par force brute; les entrées de quatre lettres ou plus expireront sur TIO. La suite de tests préfère _39 «l'efficacité».

Comment ça marche

S;þḅ26ŒpṢƑƇIŻ€S:g/ƊÞḢg/  Main link. Argument: b (bytestring)

S                        Take the sum (s) of the code points in b.
 ;þ                      Concatenate table; for each k in [1, ..., s] and each c in
                         b, yield [k, c], grouping by c.
   ḅ26                   Unbase 26; map [k, c] to (26k + c).
      Œp                 Take the Cartesian product.
        ṢƑƇ              Comb by fixed sort; keep only increasing lists.
           I             Increments; take the forward differences of each list.
            Ż€           Prepend a 0 to each list.
                         I returns empty lists for single-letter input, so this is
                         required to keep g/ (reduce by GCD) from crashing.
                   Þ     Sort the lists by the link to the left.
              S:g/Ɗ      Divide the sum by the GCD.
                    Ḣ    Head; extract the first, smallest element.
                     g/  Compute the GCD.

4

Gelée , 17 octets

ƓI%
26×þ%iþÇo!SỤḢ

L'entrée est un bytestring sur STDIN, la sortie est indexée 1.

Essayez-le en ligne!

Comment ça marche

ƓI%            Helper link. Argument: m (26 when called)

Ɠ              Read a line from STDIN and eval it as Python code.
 I             Increments; take all forward differences.
  %            Take the differences modulo m.


26×þ%iþÇoSSỤḢ  Main link. No arguments.

26             Set the argument and the return value to 26.
  ×þ           Create the multiplication table of [1, ..., 26] by [1, ..., 26].
    %          Take all products modulo 26.
       Ç       Call the helper link with argument 26.
     iþ        Find the index of each integer to the right in each list to the left,
               grouping by the lists.
        o!     Replace zero indices (element not found) with 26!.
               This works for strings up to 25! = 15511210043330985984000000 chars,
               which exceeds Python's 9223372036854775807 character limit on x64.
          S    Take the sum of each column.
           Ụ   Sort the indices by their corresponding values.
            Ḣ  Head; extract the first index, which corresponds to the minimal value.

4

JavaScript (Node.js) ,  123 121 116  114 114 octets

s=>(i=26,F=m=>i--?F((g=x=>s[p]?s[k++>>5]?j=1+g(x+i,p+=b[p]==x%26+97):m:0)(b[p=k=0]+7)>m?m:(r=i,j)):r)(b=Buffer(s))

Essayez-le en ligne!

Commenté

i2526s[k++ >> 5]g32×LL

s => (                        // main function taking the string s
  i = 26,                     // i = current step, initialized to 26
  F = m =>                    // F = recursive function taking the current minimum m
    i-- ?                     // decrement i; if i was not equal to 0:
      F(                      //   do a recursive call to F:
        (g = x =>             //     g = recursive function taking a character ID x
          s[p] ?              //       if there's still at least one letter to match:
            s[k++ >> 5] ?     //         if we've done less than 32 * s.length iterations:
              j = 1 + g(      //           add 1 to the final result and add the result of
                x + i,        //             a recursive call to g with x = x + i
                p += b[p] ==  //             increment p if
                  x % 26 + 97 //             the current letter is matching
              )               //           end of recursive call to g
            :                 //         else (we've done too many iterations):
              m               //           stop recursion and yield the current minimum
          :                   //       else (all letters have been matched):
            0                 //         stop recursion and yield 0
        )(                    //     initial call to g with p = k = 0
          b[p = k = 0] + 7    //     and x = ID of 1st letter
        ) > m ?               //     if the result is not better than the current minimum:
          m                   //       leave m unchanged
        :                     //     else:
          (r = i, j)          //       update m to j and r to i
      )                       //   end of recursive call to F
    :                         // else (i = 0):
      r                       //   stop recursion and return the final result r
)(b = Buffer(s))              // initial call to F with m = b = list of ASCII codes of s

4

Ruby , 121 114 112 108 102 89 bytes

->s{(r=0..25).min_by{|l|p,=s;s.sum{|c|t=r.find{|i|(p.ord-c.ord+i*l)%26<1}||1/0.0;p=c;t}}}

Essayez-le en ligne!

0 indexé. Prend l'entrée comme un tableau de caractères.

Merci à ASCII uniquement pour les idées de golf d'une valeur de 12 octets.


:( close (basé sur une solution python)
uniquement à ASCII

100 , peut probablement être joué un peu plus
uniquement à ASCII


Excellente idée, -1 octet supplémentaire par p,=*sastuce, mais je ne suis pas sûr de la robustesse théorique d'une solution avec un score de pénalité codé en dur ... Donc, j'ai changé la constante à l'infini (bien que votre valeur autorise encore 2 octets de moins) ).
Kirill L.

Seulement 2 octets, pas mal
ASCII uniquement le

3

Python 2 , 230 222 222 216 194 169 octets

def t(s,l,S=0):
 a=ord(s[0])
 for c in s[1:]:
	while a-ord(c)and S<len(s)*26:S+=1;a=(a-65+l)%26+65
 return S
def f(s):T=[t(s,l)for l in range(26)];return T.index(min(T))

Essayez-le en ligne!

-22 octets de tsh

-39 octets de Jo King

Version plus ancienne avec explication:

A=map(chr,range(65,91)).index
def t(s,l,S=0):
 a=A(s[0]) 
 for c in s[1:]:
	while a!=A(c)and S<len(s)*26:
	 S+=1;a+=l;a%=26
 return S
def f(s):T=[t(s,l)for l in range(26)];return T.index(min(T))

Essayez-le en ligne!

Ce serait plus court dans une langue avec un nombre premier de lettres (ne nécessiterait pas la float('inf')gestion de boucles infinies). En fait, cette soumission aurait toujours besoin de cela pour gérer des chaînes comme "aaa". Cette soumission utilise maintenant 26*len(s)comme limite supérieure, ce qui arrête les boucles infinies.

Cette soumission est indexée sur 0 (renvoie des valeurs de 0 à 25 inclus).

f prend une chaîne (n majuscule) et renvoie le pas d'alphabet optimal

test une fonction d'aide qui prend la chaîne et un pas d'alphabet et renvoie le nombre de sauts nécessaires pour terminer la chaîne (ou 26*len(s)si cela est impossible).


2
Utilisez while a!=A(c)and S<len(s)*26:et vous pouvez supprimer if a==i:return float('inf'), car len(s)*26est la limite supérieure de toute réponse.
tsh





2

Rouge , 197 octets

func[s][a: collect[repeat n 26[keep #"`"+ n]]m: p: 99 a: append/dup a a m
u: find a s/1 repeat n 26[v: extract u n
d: 0 foreach c s[until[(v/(d: d + 1) = c)or(d > length? v)]]if d < m[m: d p: n]]p]

Essayez-le en ligne!


2

05AB1E (hérité) , 33 27 26 octets

Ç¥ε₂%U₂L<©ε®*₂%Xk'-žm:]øOWk

Utilise la version héritée car il semble y avoir un bogue lorsque vous souhaitez modifier / utiliser le résultat après une carte imbriquée dans la nouvelle version 05AB1E.

Sortie indexée 0.

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

Ç                        # ASCII values of the (implicit) input
 ¥                       # Deltas (differences between each pair)
  ε                      # Map each delta to:
   ₂%                    #  Take modulo-26 of the delta
     U                   #  Pop and store it in variable `X`
      L<                #  Push a list in the range [0,25]
         ©               #  Store it in the register (without popping)
          ε              #  Map each `y` to:
           ®*            #   Multiply each `y` by the list [0,25] of the register
             ₂%          #   And take modulo-26
                         #   (We now have a list of size 26 in steps of `y` modulo-26)
               Xk        #   Get the index of `X` in this inner list (-1 if not found)
                 '-₄:   '#   Replace the minus sign with "1000"
                         #   (so -1 becomes 10001; others remain unchanged) 
]                        # Close both maps
 ø                       # Zip; swapping rows/columns
  O                      # Sum each
   W                     # Get the smallest one (without popping the list)
    k                    # Get the index of this smallest value in the list
                         # (and output the result implicitly)

2

Python 3 , 191 178 162 octets

Merci à tous pour tous vos conseils! cela ressemble beaucoup plus à un golf.

*w,=map(ord,input())
a=[]
for i in range(26):
 n=1;p=w[0]
 for c in w:
  while n<len(w)*26and p!=c:
   n+=1;p+=i;
   if p>122:p-=26
 a+=[n]
print(a.index(min(a)))

Essayez-le en ligne!

Et mon code d'origine si quelqu'un est intéressé.

Transforme le mot en une liste de valeurs ASCII, puis parcourt les étapes de 0 à 25, vérifiant le nombre d'étapes nécessaires pour épuiser la liste (il existe un plafond pour arrêter les boucles infinies).

Le nombre d'étapes est ajouté à la liste a .

Après la grande boucle for, l'index de la plus petite valeur dans a est imprimé. Ceci est égal à la valeur de i (la taille du pas) pour cette itération de la boucle, QED.


1
Salut et bienvenue à PPCG! Pour commencer, votre nombre d'octets publié ne correspond pas à celui de TIO :) Maintenant, pour quelques conseils rapides: range(26)suffit - vous n'avez pas besoin de spécifier le début, car 0 est la valeur par défaut; a.append(n)pourrait être a+=[n]; la première ligne serait plus courte que map w=list(map(ord,input())), (en fait avec votre algorithme actuel, dans Py2, vous pouvez également supprimer le list(...)wrapping); éviter les ruptures espacement / ligne supplémentaires autant que possible (par exemple, pas besoin de nouvelles lignes dans Citations: if p>122:p-=26)
Kirill L.

1
Aussi, cela n>99semble suspect, est-ce une constante arbitraire pour sortir de la boucle inifinite? Ensuite, cela devrait probablement être quelque chose comme 26 * len (w), comme vous ne le savez jamais, quelle sera la taille de l'entrée.
Kirill L.

1
BTW, vous pouvez toujours vous en débarrasser list(...)dans Py3 et aussi d'un extra if: 165 octets . Jetez également un œil à cette rubrique de conseils , je suis sûr que vous améliorerez considérablement vos compétences en utilisant des conseils à partir de là!
Kirill L.

1
Je ne suis pas un expert en python, mais je pense que vous pouvez le faire while p!=c and n>len(w)*26:et vous débarrasser de cette dernière instruction if pour -8 octets.
Spitemaster

2
Bien que cela semble terrible et va à l'encontre de tout ce qui est Python, vous pouvez changer n+=1et p+=isur des lignes séparées n+=1;p+=ien un seul.
nedla2004
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.