Encuentre la forma más corta de avanzar un contador a un número determinado


10

Tengo un mostrador Es un dispositivo pequeño que se ve así:

mostrador

La pantalla va de 0000a 9999. Tiene un pequeño botón en la parte superior que aumenta el recuento en 1, y una pequeña perilla a la derecha cuyo propósito es restablecer el contador a 0.

Ahora, lo que pasa con la pequeña perilla es que si la gira hacia atrás, puede hacer que aumente cualquier dígito que desee una vez que la vuelva a girar hacia adelante. Entonces, si presiono el botón del contador 10 veces para que se muestre el contador 0010, puedo girar la perilla hacia atrás hasta que escuche un pequeño clic, luego girarla hacia adelante nuevamente y hacer que vaya directamente a 0090.

Pero, la perilla siempre aumentará todas las ocurrencias del mismo dígito en 1 cada vez que empuje los números hacia adelante. Entonces, si el contador se muestra 6060, solo puede hacer que aumente a 7070, no a 6070o 7060. Además, el mando rodará 9s a 0sin necesidad de llevar, por lo que 0990avanzará al 0000lugar de 1000o 1100.


Quiero saber la forma más eficiente de configurar el contador en un número determinado. Su tarea es escribir un programa o función que determine la secuencia más corta de presionar un botón y avanzar la perilla para hacerlo.

Su programa tomará como entrada un número de 4 dígitos a partir 0000de 9999, y devolver una serie de pasos en el siguiente formato:

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

Donde Csignifica "presione el botón del contador" y cualquier dígito Ddel 0 al 9 significa "use la perilla para avanzar todas las apariciones de D1".

Su programa debe producir una secuencia válida de pasos para todas las combinaciones posibles de cuatro dígitos, y se puntuará por el número total de pasos necesarios para los 10,000 casos. En el caso de un empate (muy probablemente cuando se encuentre el algoritmo óptimo), el código más corto ganará.


¿Qué sucede si gira la perilla hacia adelante? ¿Se convertirá 0010en 0020en ese caso? ¿O solo puedes girar la perilla hacia atrás? Y también, ¿cada "D" cuenta como el número "D" de avances de la perilla (por ejemplo, 1234567significa girar la perilla 1 vez, luego 2 veces, luego 3 veces, etc.)? ¿O solo significa cada giro de la perilla por separado (por ejemplo, 1234567solo significa girar la perilla 7 veces)?
R. Kap

Parece que lo anterior y lo siguiente no están relacionados.
Leaky Nun

La perilla puede incluso elegir dígitos en el siguiente.
Leaky Nun

Si gira la perilla hacia adelante, avanzará 0010 a 0020 o 1111, dependiendo de la posición en la que ya se encuentre la perilla. Gire la perilla hacia atrás para establecer su posición y luego hacia adelante para avanzar los dígitos.
Joe Z.

1
¡En serio, este tipo necesita su contador al valor correcto! ¡¡¡AHORA!!!
CalculatorFeline

Respuestas:


5

Lua, 327763 pasos (óptimo, 276 bytes)

Versión de golf:

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[(...)])

Versión mejorada de los ejemplos en cuestión (solo 1000se ha mejorado):

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

Versión sin golf:

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, puntaje 512710

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

Corrige un error con StringRepeat(se comporta incorrectamente para StringRepeat[x_String,0])


¿Es necesario que haya un espacio en StringRepeat[x_String, 0]:=""?
gato

No, pero era demasiado vago para eliminarlo. ¿Es eso un problema?
CalculatorFeline

No, en absoluto: P Era curioso para mí que el resto del código sea de golf excepto por un espacio en blanco.
gato el

... eso es golf, ¿verdad? ¿O es Mathematica el nuevo ruido de línea?
gato el

@cat Esto no es code-golf
pppery

1

Pyth, 327763 pasos (óptimo, 130 bytes)

Desde el compilador en línea es inepto en el manejo de dicha tarea enorme, me he dado menos trabajo, por lo que sólo se genera 0, 1y 1111. Sin embargo, teóricamente puede resolver el problema, ya que utiliza el mismo algoritmo que el Lua en la parte superior.

Pruébalo en línea!

=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

Cómo funciona:

=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: el lua uno está debajo. : P Pero esto es increíble, buen trabajo.
Rɪᴋᴇʀ

Todavía está arriba para mí: o
Leaky Nun

Ordeno por activo, tal vez tienes votos. Pero en realidad no importa.
Rɪᴋᴇʀ

Oh, está abajo para mí ahora lol
Leaky Nun

1

JavaScript (ES6), 327763 pasos (óptimo, 184 bytes)

A Breadth First Search, no tan inteligente ni tan rápido.

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

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

Prueba

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>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.