Questa è la risposta più precisa che possiamo darti, ma prima studiala attentamente e vedi se è adatta al tuo lavoro.
Soluzione:
C# (.NET Core), 617 byte, tentativi totali = 182255, punteggio = 1185166
using System;namespace p{class C{static void Main(){var l=Console.ReadLine();int L=int.Parse(l);var g=new int[L];var p=n(g);for(int i=0;i0){g[i]=9;d-=2;}break;case 1:g[i]=2;d=n(g);f=d-p;if(f>0){g[i]=8;d-=4;}break;case-1:g[i]=3;d=n(g);f=d-p;if(f>0){g[i]=7;d-=4;}break;case-3:g[i]=4;d=n(g);f=d-p;if(f>-3){g[i]=6;d-=2;}break;}p=d;}n(g);}static int n(int[] g){foreach(var i in g){Console.Write(i);}Console.WriteLine();var s=Console.ReadLine();var d=int.Parse(s);if(d<1) Environment.Exit(0);return d;}}}
Speriamo che C# in questo formato funzioni per voi. È sotto forma di programma completo, quindi dovrebbe esserci un modo per compilare un eseguibile. Fatemi sapere se c'è qualcosa che posso fare per renderlo più semplice. I byte fanno parte del punteggio anche se il tag Code Golf è stato rimosso, quindi il mio invio ufficiale rimuove tutti gli spazi bianchi non necessari e i nomi utili. La mia spiegazione qui di seguito utilizzerà frammenti di codice non golfato:
Spiegazione
Questo programma utilizza un solo metodo helper:
static int newGuess(IEnumerable guess)
{
foreach (var item in guess)
{
Console.Write(item);
}
Console.WriteLine();
var distanceString = Console.ReadLine();
var distance = int.Parse(distanceString);
if (distance < 1) System.Environment.Exit(0);
return distance;
}
Scrive l'ipotesi su stdout, quindi legge la distanza da stdin. Inoltre termina immediatamente il programma se un'ipotesi è la combinazione esatta. Lo chiamo spesso. Poi la configurazione iniziale:
var lengthString = Console.ReadLine();
int length = int.Parse(l);
var guess = new int[length];
var prevDistance = newGuess(guess);
Ottiene la lunghezza della combinazione, quindi inizia a indovinare con tutti 0. Successivamente, esegue un'iterazione di tutte le cifre in una sequenza di for
ciclo.
guess[i] = 5;
var distance = newGuess(guess);
var difference = distance - prevDistance;
var switchVar = difference;
switch (switchVar)
Per ogni cifra, indovina 5, poi decide il passo successivo in base a come è cambiata la distanza dalla precedente ipotesi (in cui quella cifra era 0).
case 5:
guess[i] = 0;
distance -= 5;
break;
Se la distanza è aumentata di 5, allora 0 era corretto per quella distanza. Regolare la cifra su 0. Modificando manualmente la distanza registrata si evita un'ulteriore ipotesi.
case -5:
break;
Se la distanza è diminuita di 5, allora 5 è la cifra corretta e si passa immediatamente alla cifra successiva.
Dopo di che le cose si complicano. Utilizzando 5
e 0
per le mie ipotesi iniziali significa che le possibilità di differenza rimanenti sono 3, 1, -1, -3
con 2 possibilità per ciascuna, che necessitano di un'ulteriore ipotesi per essere distinte. Ognuno di questi casi assume una forma simile
case 3:
guess[i] = 1;
distance = newGuess(guess);
difference = distance - prevDistance;
if (difference > 0)
{
guess[i] = 9;
distance -= 2;
}
Alcuni numeri cambiano, ma essenzialmente proviamo una delle due possibilità e verifichiamo se il cambiamento era quello corretto per quella cifra. Se non lo era, allora l'altra cifra è corretta, quindi impostiamo quella cifra e regoliamo la differenza manualmente.
Questo metodo significa che dovrebbe essere necessaria al massimo un'ipotesi per gli 0 iniziali, due ipotesi per ogni cifra e un'ultima ipotesi per garantire che l'ultima cifra non cada.
Potrebbe essere difettoso, ma per quanto ho controllato manualmente funziona, ma non è una garanzia.
Bug trovato e risolto grazie a Colera Su
C, 388374 368 byte, tentativi totali = 162751, punteggio = 982280
char s[999];i;G;H;t;n;h;e;R(x){scanf("%d",x);}W(i,x,a){printf((i-n?0:4)+"%0*d%0*dn",i,x,n-i,0);R(a);}S(k,i){if(!(t=e=k>4?s[i]=48:k<1?s[i]=53:!G?H=k,G=i:0)){for(;t++h?53+H:53-H,s[i]=t>h^e?53+k:53-k;G=0;}}main(){R(&n);for(W(n,0,&h);i++>1,i))W(i,5,&t);s[G]=53+H,puts(s+1),s[G]=53-H,puts(s+1);}
Python 2 e 3: 175 byte, tentativi totali = 1005972, punteggio = 5448445
Questo programma richiede ceil(log(n))*10 tentativi per combinazione o ogni singola cifra richiede 10 tentativi (quindi, 333
richiede 30 tentativi).
N=int(input());o=0
def c(a):
print("0"*(N-len(str(a)))+str(a))
return int(input())
for j in range(N):m={c(i):i for i in reversed(range(0,10**(j+1),10**j))};o+=m[min(m)]
c(o)
Un enorme ringraziamento a Colera Su per avermi aiutato con la funzionalità di input/output.
Versione Python della sfida (modificata da OP).
Ho scritto una versione del codice del lucchetto in Python. Potete usarla se state cercando di risolvere il problema in Python (come me). Il seguente funziona in Python 2 e 3. Era molto più sensato implementare lock come classe da testare e ho deciso di creare una funzione generatrice per indovinare gli ingressi.
import sys
class Lock:
def __init__(self, number):
self.lock = str(number)
def l(self): #lengthOfNumber
return len(self.lock)
def c(self, guess): #check a guess
guess = str(guess)
guess = "0" * (len(self.lock) - len(guess)) + guess
difference = 0
for i in range(len(self.lock)):
d1 = abs(int(self.lock[i]) - int(guess[i]))
d2 = 10 - d1
difference += d1 if d1 < d2 else d2
return difference
def masterLock():
testdata = ["000","555","755","735","744","746"]
for answer in testdata:
yield Lock(answer)
class LockIO:
def __init__(self):
self.lock = int(input())
def l(self):
return self.lock
def c(self, guess):
guess = str(guess)
guess = "0" * (self.lock - len(guess)) + guess
print(guess)
sys.stdout.flush()
return int(input())
for l in masterLock():
# Write your code here that tries to guess it
# When you're done testing you can unindent your code,
# replace "for l in masterLock():" with "l = LockIO()"
# and submit the code.
#
# Examples:
# l.l() # returns the length of the lock
# l.c("952") # returns the distance to the lock
# l.c(952) # number also works
pass