Trova il modo più breve per far avanzare un contatore a un determinato numero


10

Ho un contatore. È un piccolo dispositivo che assomiglia a questo:

contatore

Il display passa da 0000a 9999. Ha un piccolo pulsante in alto che aumenta il conteggio di 1 e una piccola manopola a destra il cui scopo è di ripristinare il contatore a 0.

Ora, la cosa sulla piccola manopola è che se la giri all'indietro, puoi farla aumentare qualsiasi cifra desiderata una volta che la giri di nuovo in avanti. Quindi, se premo il pulsante del contatore 10 volte in modo che il contatore mostri 0010, posso quindi ruotare la manopola all'indietro fino a quando sento un piccolo clic, quindi ruotarlo di nuovo in avanti e farlo andare dritto 0090.

Tuttavia, la manopola aumenterà sempre tutte le occorrenze della stessa cifra di 1 ogni volta che spinge i numeri in avanti. Quindi, se il contatore mostra 6060, puoi solo farlo aumentare a 7070, non a 6070o 7060. Inoltre, la manopola ruoterà 9su 0senza trasportare, quindi 0990avanzerà al 0000posto di 1000o 1100.


Voglio sapere il modo più efficiente per impostare il contatore su un certo numero. Il tuo compito è scrivere un programma o una funzione che determinerà la sequenza più breve di pressioni di pulsanti e avanzamenti della manopola necessari per farlo.

Il programma prenderà come input un numero di 4 cifre da 0000a 9999e restituirà una serie di passaggi nel seguente formato:

> 0001
C
> 0093
C12345678C12345678CCC
> 1000
C12345678C12345678C12345678C12345678C12345678C12345678C12345678C
> 9999
012345678

Dove Csta per "premere il pulsante contatore" e qualsiasi cifra Dda 0 a 9 sta per "utilizzare la manopola per far avanzare tutte le occorrenze di D1".

Il programma deve produrre una sequenza valida di passaggi per tutte le possibili combinazioni di quattro cifre e verrà assegnato un punteggio in base al numero totale di passaggi richiesti per tutti i 10.000 casi. In caso di pareggio (molto probabilmente quando viene trovato l'algoritmo ottimale), vincerà il codice più breve.


Cosa succede se si gira la manopola in avanti? Si trasformerà 0010in 0020quel caso? Oppure puoi solo ruotare la manopola all'indietro? Inoltre, ogni "D" conta come "D" numero di avanzamenti della manopola (ad esempio, 1234567significa ruotare la manopola 1 volta, quindi 2 volte, quindi 3 volte, e così via)? Oppure significa solo ogni giro di manopola separato (per esempio, significa 1234567solo ruotare la manopola 7 volte)?
R. Kap

Sembra che il sopra e il sotto non siano correlati.
Leaky Nun

La manopola può anche scegliere cifre nel seguito.
Leaky Nun

Ruotando la manopola in avanti si avanzerà da 0010 a 0020 o 1111, a seconda della posizione in cui si trova già la manopola. Ruotare la manopola all'indietro per impostarne la posizione, quindi in avanti per far avanzare le cifre.
Joe Z.

1
Scherzi a parte, questo ragazzo ha bisogno del suo contatore al valore corretto !!!! ADESSO!!!
CalculatorFeline

Risposte:


5

Lua, 327763 passi (ottimale, 276 byte)

Versione golfizzata:

a={[0]=""}t=tonumber for i=0,52 do A={}for k,v in pairs(a)do A[k]=v L=("%04d"):format(k)for i=1,4 do c=L:sub(i,i)d=L:gsub(c,(t(c)+1)%10)e=a[t(d)]A[d]=(not e or #e>#v)and v..c or e end b=k+1 if k<9999then e=a[b]A[b]=(not e or #e>#v)and v.."C"or e end end a=A endprint(a[(...)])

Versione migliorata degli esempi in questione (solo 1000migliorata):

0001:C
0093:CCCCCCCCCC12345678CCC
1000:0CCCCCCCCCCC2345678C23456789
     (0000>1111>1122>1199>1200>1000)
9999:012345678

Versione non golfata:

a = {[0]=""}
for i=0,52 do
    A = {}
    for k,v in pairs(a) do
        A[k] = v
        L=("%04d"):format(k)
        for i=1,4 do
           c=L:sub(i,i)
           d=L:gsub(c,(tonumber(c)+1)%10)
           e=a[tonumber(d)]
           A[d] = (not e or #e > #v) and v..c or e
        end
        b=k+1
        if k < 9999 then
            e=a[b]
            A[b] = (not e or #e > #v) and v.."C" or e
        end
    end
    a=A
end
print(a[93],a[1000],a[9999])

1

Mathematica, punteggio 512710

Unprotect[StringRepeat]
StringRepeat[x_String, 0]:=""
Protect[StringRepeat]
#<>StringRepeat["C",#3-#2*1111]&[Array[ToString@#&,#,0],##]&[If[#<10^3,0,Quotient[#,1111]],#]&

Risolve un bug con StringRepeat(si comporta in modo errato per StringRepeat[x_String,0])


Deve esserci uno spazio dentro StringRepeat[x_String, 0]:=""?
gatto

No, ma ero troppo pigro per rimuoverlo. È un problema?
CalculatorFeline

Niente affatto: P Era solo curioso per me che il resto del codice fosse giocato a golf tranne uno spazio bianco.
gatto

... quello è golf, giusto? O è Mathematica il nuovo rumore di linea?
gatto

@cat Questo non è code-golf
pppery

1

Pyth, 327763 passi (ottimale, 130 byte)

Dal momento che il compilatore online è inetto a trattare con tale enorme compito, ho dato meno lavoro, in modo da generare solo 0, 1e 1111. Tuttavia, può teoricamente risolvere il problema, perché utilizza lo stesso algoritmo del Lua in alto.

Provalo online!

=Y.d((0k;V53=ZYFGY XZG=k@YG=N%"%04d"GV4=b@NH=di:Nb%"%d"ehibTT XZd.x?>l@Ydlk+kb@Yd+kb)=bhGI<G9999 XZb.x?>l@Yblk+k\C@Yb+k\C))=YZ;@YQ

Come funziona:

=Y.d((0k;V53=ZYFGY XZG=k@YG=N%"%04d"GV4=b@NH=di:Nb%"%d"ehibTT XZd.x?>l@Ydlk+kb@Yd+kb)=bhGI<G9999 XZb.x?>l@Yblk+k\C@Yb+k\C))=YZ)@YQ
                  assign_copy('Q',eval_input())
=Y.d((0k;         assign_copy('Y',dict(0=k))
V53               for N in range(0,53):
=ZY                   assign_copy('Z',Y)
FGY                   for G in num_to_range(Y):
 XZG=k@YG                 no_print(Z[G] = assign_copy('k',lookup(Y,G)))
=N%"%04d"G                assign_copy('N',format("%04d",G))
V4                        for H in range(0,4):
=b@NH                         assign_copy('b',lookup(N,H))
=di:Nb%"%d"ehibTT             assign_copy('d',base(replace(N,b,format("%d",mod10(increment(base(b,10))))),10))
 XZd.x?>l@Ydlk+kb@Yd+kb       no_print(Z[d]=try_and_catch(greater_than(Plen(lookup(Y,d)),Plen(k)) ? concat(k,b) : lookup(Y,d)), lambda:plus(k,b))
)                         <anti-indent>
=bhG                      assign_copy('b',head(G))
I<G9999                   if less_than(G,9999):
 XZb.x?>l@Yblk+k\C@Yb+k\C     no_print(Z[b]=try_and_catch(greater_than(Plen(lookup(Y,b)),Plen(k)) ? concat(k,"C") : lookup(Y,b)), lambda:plus(k,"C"))
)                         <anti-indent>
)                     <anti-indent>
=YZ                   assign('Y',Z)
)                 <anti-indent>
@YQ               print(lookup(Y,Q))

Solo notando: quello lua è sotto. : P Ma è fantastico, ottimo lavoro.
R

È ancora sopra per me: o
Leaky Nun

Ordino per attivo, forse hai voti. Ma non importa davvero.
R

Oh, è sotto per me ora lol
Leaky Nun

1

JavaScript (ES6), 327763 passi (ottimale, 184 byte)

Una prima ricerca ampia, non così intelligente e non così veloce.

t=>eval("for(k=[],s=[['0000',i='']];[u,p]=s[i++],u-t;k[v=(1+u-~0+'').slice(-4)]=k[v]||s.push([v,p+'C']))[...u].map(x=>k[v=[...u].map(y=>x-y?y:-~x%10).join``]=k[v]||s.push([v,p+x]));p")

Meno golf

t=>{
  k=[]; // mark values already found to reduce search
  for( i=0, s=[['0000','']]; 
       [u,p]=s[i++], // u: current code, p:current steps
       u != t; // exit if target found
     )
  {
     // try all digits present in current code
     [...u].map(x=> {
       v=[...u].map(y=>x-y?y:-~x%10).join`` // apply digit x to u
       if (!k[v]) // check if value v not found already
          k[v] = s.push([v,p+x]));
     })
     v=(1+u-~0+'').slice(-4); // try operator C
     if (!k[v]) // check if value v not found already
       k[v] = s.push([v,p+'C']))
  }
  return p
}

Test

f=t=>eval("for(k=[],s=[['0000',i='']];[u,p]=s[i++],u-t;k[v=(1+u-~0+'').slice(-4)]=k[v]||s.push([v,p+'C']))[...u].map(x=>k[v=[...u].map(y=>x-y?y:-~x%10).join``]=k[v]||s.push([v,p+x]));p")

function SingleTest()
{
  var i=S.value
  if (/^\d{4}$/.test(i)) X.value=f(i)
  else X.value='invalid input'
}  

SingleTest()

function LongTest()
{
  var i=0,v,r,t=0
  
  var step=_=>{ 
    v = ('000'+i).slice(-4);
    r = f(v);
    t+= r.length    
    V.value = v;
    R.value = r;
    T.value = t;
    ++i;
    if(i<10000) setTimeout(step, 0)
  }  
  
  step()
}
#V,#T,#S { width:5em }
#R,#X { width: 25em }
Single Test <input id=S value='0093'><button onclick="SingleTest()">-></button><input readonly id=X><hr>
Long test (0000 ... 9999) <button onclick="LongTest()">Go</button>(i mean <i>long</i>, runtime 1 hour)<br>
<input readonly id=V>
<input readonly id=R> 
Total steps:<input readonly id=T>

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.