Stepping alfabetico ottimale


30

Data una stringa di input composta da sole lettere, restituisce la dimensione del passo che si traduce nella quantità minima di passi necessari per visitare tutte le lettere in ordine sopra un alfabeto a capo, a partire da qualsiasi lettera.

Per esempio, prendiamo la parola, dog. Se utilizziamo un passo di 1, finiamo con:

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

Per un totale di 30 passaggi.

Tuttavia, se utilizziamo un passo di 11, otteniamo:

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

Per un totale di 6 passaggi. Questa è la quantità minima di passi, quindi il risultato di ritorno dogè la dimensione del passo; 11.

Casi 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

Regole

  • Ingresso sarà una stringa non vuota o array di caratteri costituiti unicamente da lettere aper z(si può scegliere tra maiuscolo o minuscolo)
  • L'output può essere 0 indicizzato (ovvero l'intervallo 0-25) o 1 indicizzato ( 1-26)
  • Se c'è un pareggio, è possibile produrre qualsiasi dimensione del passo o tutti
  • Questo è , quindi vince il minor numero di byte per ogni lingua!

Dobbiamo gestire input vuoti?
pizzapants184,

1
@ pizzapants184 No. Ho aggiornato la domanda per specificare che l'input sarà non vuoto
Jo King

Possiamo prendere l'input come una matrice di caratteri?
Shaggy,

@Shaggy Certo che puoi
Jo King il

C'è una ragione per cui utilizza lettere anziché numeri?
Wheat Wizard

Risposte:


6

Carbone , 41 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. 0-indicizzati. Spiegazione:

Eβ

Passa attraverso le 26 dimensioni del gradino. (In realtà cerco qui l'alfabeto minuscolo e utilizzo la variabile indice.)

Eθ∧μ

Passa sopra ogni carattere dell'input dopo il primo.

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

Ripeti 26 volte e genera la stringa di caratteri risultante eseguendo 26 passi alla dimensione del passo indicata iniziando (indicizzato 0) con il carattere precedente dell'input.

⌕...λ

Trova la posizione del carattere corrente dell'input in quella stringa, oppure -1 se non trovato.

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

Prendi la somma di tutte le posizioni, a meno che non ne sia stata trovata una, nel qual caso usa -1.

≔...θ

Salva le somme.

⌊Φθ⊕ι

Trova la somma minima non negativa.

I⌕θ...

Trova la dimensione del primo passo con quella somma e stampala.


5

JavaScript, 143 byte

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

Provalo online!

Grazie a Shaggy, usando [...Array(26).keys()]salva 9 byte.



4

Gelatina , 28 26 23 byte

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

L'output è indicizzato 0. L'input è un bytestring e può essere comunque, ma il maiuscolo è molto più veloce.

L'immissione di una sola lettera deve essere in maiuscolo e costa 2 byte. ._.

Provalo online!

Si noti che questo è un approccio a forza bruta; gli input con quattro o più lettere scadranno su TIO. La suite di test si prefigge _39 "efficienza".

Come funziona

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

Gelatina , 17 byte

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

L'input è un bytestring su STDIN, l'output è 1-indicizzato.

Provalo online!

Come funziona

Ɠ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 byte

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

Provalo online!

Commentate

io2526s[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

Rubino , 121 114 112 108 102 89 byte

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

Provalo online!

0-indicizzati. Accetta input come una matrice di caratteri.

Grazie al solo ASCII per idee golf da 12 byte.


:( close (basato sulla soluzione python)
ASCII il

100 , probabilmente si può giocare a golf un po 'di più
solo ASCII il


Ottima idea, -1 più byte per p,=*strucco, ma non sono così sicuro della solidità teorica di una soluzione con un punteggio di penalità codificato ... Quindi, ho cambiato la costante in infinito (anche se il tuo valore consentirebbe altri 2 byte di sconto ).
Kirill L.,

Solo 2 byte, non male
solo ASCII il

3

Python 2 , 230 222 216 194 169 byte

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

Provalo online!

-22 byte da tsh

-39 byte da Jo King

Versione precedente con spiegazione:

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

Provalo online!

Questo sarebbe più breve in una lingua con un numero primo di lettere (non avrebbe bisogno della float('inf')gestione di loop infiniti). In realtà, questa presentazione sarebbe ancora necessaria per gestire stringhe come "aaa". Questo invio ora utilizza 26*len(s)come limite superiore, che arresta loop infiniti.

Questo invio è indicizzato 0 (restituisce valori compresi tra 0 e 25 inclusi).

f prende una stringa (n maiuscola) e restituisce il passo alfabetico ottimale

tè una funzione di supporto che prende la stringa e un passo di alfabeto e restituisce il numero di hop necessari per terminare la stringa (o 26*len(s)se impossibile).


2
Usa while a!=A(c)and S<len(s)*26:e puoi rimuovere if a==i:return float('inf'), poiché len(s)*26è il limite superiore di qualsiasi risposta.
TSH





2

Rosso , 197 byte

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]

Provalo online!


2

05AB1E (legacy) , 33 27 26 byte

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

Utilizza la versione legacy perché sembra che ci sia un bug quando si desidera modificare / utilizzare il risultato dopo una mappa nidificata nella nuova versione 05AB1E.

Uscita indicizzata 0.

Provalo online o verifica tutti i casi di test .

Spiegazione:

Ç                        # 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 byte

Grazie a tutti per tutti i vostri consigli! questo sembra molto più simile al 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)))

Provalo online!

E il mio codice originale se qualcuno è interessato.

Trasforma la parola in un elenco di valori ASCII, quindi scorre tra le dimensioni dei gradini da 0 a 25, controllando il numero di passaggi necessari per esaurire l'elenco (è presente un limite massimo per interrompere loop infiniti).

Numero di passaggi aggiunti all'elenco a .

Dopo il ciclo for for, viene stampato l'indice del valore più piccolo in a . Questo è uguale al valore di i (la dimensione del passo) per quella iterazione del loop, QED.


1
Ciao e benvenuto in PPCG! Per cominciare, il conteggio dei byte postati non corrisponde a quello su TIO :) Ora, per un paio di suggerimenti rapidi: range(26)è sufficiente: non è necessario specificare l'inizio, poiché 0 è l'impostazione predefinita; a.append(n)potrebbe essere a+=[n]; la prima riga sarebbe più corta come mappa w=list(map(ord,input()))(in realtà con il tuo attuale algoritmo, in Py2 potresti anche eliminare il list(...)wrapping); evitare interruzioni di spaziatura / riga in eccesso il più possibile (per esempio, senza necessità di nuove righe in oneliners: if p>122:p-=26)
Kirill L.

1
Inoltre, questo n>99sembra sospetto, è una costante arbitraria per uscire dal circuito inifinito? Quindi probabilmente dovrebbe essere qualcosa come 26 * len (w), come non sai mai, quanto sarà grande l'input.
Kirill L.,

1
A proposito, puoi ancora sbarazzartene list(...)in Py3 e anche di un extra if: 165 byte . Inoltre, dai un'occhiata a questo argomento suggerimenti , sono sicuro che migliorerai notevolmente le tue abilità usando i consigli da lì!
Kirill L.,

1
Non sono un esperto di Python, ma penso che tu possa fare while p!=c and n>len(w)*26:e sbarazzarti di quest'ultima istruzione if per -8 byte.
Spitemaster,

2
Anche se sembra terribile e va contro qualsiasi cosa sia Python, puoi cambiare n+=1e p+=isu linee separate n+=1;p+=isu uno.
nedla2004,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.