Trouvez le moyen le plus court de faire avancer un compteur jusqu'à un certain nombre


10

J'ai un comptoir. C'est un petit appareil qui ressemble à ceci:

compteur

L'affichage va de 0000à 9999. Il a un petit bouton poussoir en haut qui augmente le décompte de 1, et un petit bouton à droite dont le but est de remettre le compteur à 0.

Maintenant, la chose à propos du petit bouton est que si vous le tournez vers l'arrière, vous pouvez lui faire augmenter le chiffre que vous voulez une fois que vous le tournez à nouveau vers l'avant. Donc, si j'appuie 10 fois sur le bouton du compteur pour que le compteur s'affiche 0010, je peux ensuite tourner le bouton vers l'arrière jusqu'à ce que j'entende un petit clic, puis le tourner à nouveau vers l'avant et le faire avancer directement 0090.

Mais, le bouton augmentera toujours toutes les occurrences du même chiffre de 1 à chaque fois qu'il poussera des nombres vers l'avant. Donc, si le compteur s'affiche 6060, vous ne pouvez que le faire passer à 7070, pas à 6070ou 7060. De plus, le bouton roulera 9sur 0sans porter, donc 0990avancera à la 0000place de 1000ou 1100.


Je veux connaître le moyen le plus efficace de régler le compteur sur un certain nombre. Votre tâche consiste à écrire un programme ou une fonction qui déterminera la séquence la plus courte d'appuis sur les boutons et les avancements des boutons nécessaires pour le faire.

Votre programme prendra en entrée un nombre à 4 chiffres de 0000à 9999et renverra une série d'étapes au format suivant:

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

Csignifie «appuyez sur le bouton du compteur» et n'importe quel chiffre Dde 0 à 9 signifie «utilisez le bouton pour avancer toutes les occurrences de D1».

Votre programme doit produire une séquence d'étapes valide pour toutes les combinaisons possibles à quatre chiffres et sera notée par le nombre total d'étapes requises pour les 10 000 cas. En cas d'égalité (très probablement lorsque l'algorithme optimal est trouvé), le code le plus court l'emportera.


Que se passe-t-il si vous tournez le bouton vers l'avant? Est-ce que tourner 0010dans 0020dans ce cas? Ou pouvez-vous seulement tourner le bouton vers l'arrière? Et aussi, chaque "D" compte-t-il comme un nombre "D" d'avancées du bouton (par exemple, cela 1234567signifie- t -il tourner le bouton 1 fois, puis 2 fois, puis 3 fois, etc.)? Ou cela signifie-t-il simplement chaque tour de bouton séparé (par exemple, cela 1234567signifie- t-il simplement tourner le bouton 7 fois)?
R. Kap

On dirait que ce qui précède et ce qui suit ne sont pas liés.
Leaky Nun

Le bouton peut même choisir des chiffres ci-dessous.
Leaky Nun

Tourner le bouton vers l'avant fera avancer 0010 à 0020 ou 1111, selon la position dans laquelle le bouton est déjà. Vous tournez le bouton vers l'arrière pour définir sa position, puis vers l'avant pour avancer les chiffres.
Joe Z.

1
Sérieusement, ce mec a besoin de son compteur à la bonne valeur !!!! MAINTENANT!!!
CalculatorFeline

Réponses:


5

Lua, 327763 pas (optimal, 276 octets)

Version golfée:

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

Version améliorée des exemples en question (seule 1000est améliorée):

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

Version non golfée:

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, score 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 bug avec StringRepeat(se comporte incorrectement pour StringRepeat[x_String,0])


Doit-il y avoir un espace dedans StringRepeat[x_String, 0]:=""?
chat

Non, mais j'étais trop paresseux pour l'enlever. Est-ce un problème?
CalculatorFeline

Pas du tout: P C'était juste curieux pour moi que le reste du code soit joué au golf à l'exception d' un espace blanc.
chat

... qui est golfed, non? Ou Mathematica est-il le nouveau bruit de ligne?
chat

@cat Ce n'est pas du code-golf
pppery

1

Pyth, 327763 pas (optimal, 130 octets)

Étant donné que le compilateur en ligne est inepte à faire face à cette tâche énorme, je l' ai donné moins de travail, de sorte qu'il ne génère que 0, 1et 1111. Cependant, il peut théoriquement résoudre le problème, car il utilise le même algorithme que le Lua en haut.

Essayez-le en ligne!

=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

Comment ça fonctionne:

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

À noter: le lua est en dessous. : P Mais c'est incroyable, bon travail.
Rɪᴋᴇʀ

Est toujours au-dessus pour moi: o
Leaky Nun

Je trie par actif, vous avez peut-être des votes. Mais ça n'a pas vraiment d'importance.
Rɪᴋᴇʀ

Oh c'est en dessous pour moi maintenant lol
Leaky Nun

1

JavaScript (ES6), 327763 étapes (optimal, 184 octets)

Une recherche en largeur, pas si intelligente et pas si rapide.

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

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

Tester

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>

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.