Une serrure à combinaison ordinaire à N chiffres se compose de N disques rotatifs. Chaque disque a les chiffres 0-9 inscrits dans l'ordre, et vous devez les transformer en mot de passe correct pour l'ouvrir. Évidemment, si vous ne connaissez pas le mot de passe, vous devrez essayer au plus 10 N fois avant de le déverrouiller. Ce n'est pas intéressant.
Considérons donc une variante du verrou à combinaison, nommez-le verrou révélateur de distance.
À chaque tentative infructueuse d'ouvrir un verrou révélateur de distance, il répondra au nombre minimum de mouvements à déverrouiller.
Un mouvement est défini comme une rotation d'une position, par exemple, il faut 1 mouvement de 890
à 899
et 9 mouvements de 137
à 952
.
Le défi
Étant donné un verrou révélateur de distance avec son mot de passe inconnu, essayez d'ouvrir le verrou avec un nombre minimal de tentatives (pas de mouvements), tout en empêchant le programme de devenir trop long.
Règles et scores
- Vous devez écrire un programme complet qui entre depuis stdin et sort vers stdout. Le programme doit faire des entrées / sorties comme suit:
Start
Input an integer N (number of digits) from stdin
Do
Output a line containing decimal string of length N (your attempt) to stdout
Input an integer K (response of the lock) from stdin
While K not equal 0
End
Votre programme doit gérer jusqu'à N = 200 et doit s'exécuter moins de 5 secondes sur n'importe quelle entrée.
Les zéros non significatifs en sortie ne doivent pas être omis.
Il y a 5 données de test pour chaque longueur, donc le nombre total de données de test est de 1000. Les données de test sont générées de manière aléatoire.
Le score final sera (nombre total de suppositions dans toutes les données de test) * ln (longueur de code en octets + 50). Le score le plus bas l'emporte. (ln est logarithme naturel)
Je vais marquer le programme pour vous. Si vous voulez savoir comment je vais marquer votre programme, ou si vous voulez le noter par vous-même, jetez un œil aux éditions précédentes de ce post .
Ce défi se terminera le 07/12/2017 à 14h00 UTC. Je posterai alors ma solution.
Exemple d'exécution
Les lignes commençant par >
représentent l'entrée et les autres représentent la sortie du programme.
Vous pouvez avoir un mot de passe en tête et interagir avec votre programme pour le tester.
> 3 # 3-digit lock. The hidden password is 746
000 # 1st guess (by program)
> 11 # response to the 1st guess
555 # 2nd guess
> 4 # ...
755
> 2
735
> 2
744
> 2
746 # finally the correct answer! The program attempts 6 times.
> 0 # this is not necessary
Exemple de programme
EDIT: Peut-être que le format d'entrée / sortie ci-dessus n'était pas clair. Voici un exemple de programme en Python.
Python, 369 octets, nombre total de tentatives = 1005973, score = 6073935
import sys
N = int(input()) # get the lock size
ans = ''
for i in range(N): # for each digit
lst = []
for j in range(10): # try all numbers
print('0' * i + str(j) + '0' * (N - i - 1)) # make a guess
result = int(input()) # receive the response
lst.append(result)
ans += str(lst.index(min(lst)))
print(ans) # output the final answer
Merci à Jonah d' avoir simplifié le défi.
la source
162751*ln(388+50)=989887
.C # (.NET Core) , 617 octets, tentatives totales = 182255, score = 1185166
Espérons que C # dans ce format fonctionne pour vous. C'est sous la forme d'un programme complet, donc il devrait y avoir un moyen de compiler en un exécutable. Faites-moi savoir si je peux faire quelque chose pour vous faciliter la tâche. Les octets font partie de la notation même si la balise Code Golf est supprimée, ma soumission officielle supprime donc tous les espaces inutiles et les noms utiles. Mon explication ci-dessous utilisera des fragments du code non golfé:
Explication
Ce programme utilise une seule méthode d'assistance:
Ceci écrit la supposition sur stdout, puis lit la distance depuis stdin. Il termine également immédiatement le programme si une supposition est la combinaison exacte. Je l'appelle beaucoup. Ensuite la configuration initiale:
Cela obtient la longueur de la combinaison, puis commence à deviner avec tous les 0. Ensuite, il parcourt chaque chiffre d'une
for
boucle.Pour chaque chiffre, il devine 5, puis décide de l'étape suivante en fonction de la façon dont la distance a changé depuis la supposition précédente (où ce chiffre était 0).
Si la distance a augmenté de 5, alors 0 était correct pour cette distance. Ajustez ce chiffre à 0. La modification manuelle de la distance enregistrée empêche une estimation supplémentaire.
Si la distance a diminué de 5, alors 5 est le chiffre correct et nous passons immédiatement au chiffre suivant.
Après cela, les choses sont délicates. L'utilisation de
5
et0
pour mes suppositions initiales signifie que les possibilités de différence restantes sont3, 1, -1, -3
avec 2 possibilités pour chacune, qui nécessitent 1 supposition supplémentaire pour les distinguer. Chacun de ces cas prend une forme similaireCertains des nombres changent, mais nous essayons essentiellement l'une des deux possibilités et vérifions si le changement était le bon pour ce chiffre. Si ce n'était pas le cas, l'autre chiffre est correct, nous avons donc réglé ce chiffre puis ajusté la différence manuellement.
Cette méthode signifie que nous devons exiger, au plus, 1 supposition pour les 0 initiaux, 2 suppositions par chiffre, puis 1 supposition finale pour garantir que le dernier chiffre ne passe pas.
Cela pourrait être bogué, cela fonctionne pour autant que je l'ai vérifié manuellement, mais ce n'est pas une garantie.Bug trouvé et écrasé grâce à Colera Sula source
37
. La sortie est:00, 50, 30, 75, 75
(oui, deux 75s).<
avec>
dans tousif
enswitch
semble corriger le bug. Si c'est ce que vous voulez, votre score est182255*ln(617+50)=1185166
.Python 2 et 3: 175 octets, tentatives totales = 1005972, score = 5448445
Ce programme prend ceil (log (n)) * 10 tentatives par combinaison ou chaque chiffre prend 10 tentatives (donc
333
30 tentatives).Un grand merci à Colera Su pour m'avoir aidé avec la fonctionnalité d'entrée / sortie.
Version Python de Challenge ( modifiée par OP ).
J'ai écrit une version du code de verrouillage à l'intérieur de Python. Vous pouvez continuer et l'utiliser si vous essayez de résoudre ce problème en Python (comme moi). Les travaux suivants en Python 2 et 3. Il était beaucoup plus logique d'implémenter lock en tant que classe avec laquelle vous pouvez tester et j'ai décidé de créer une fonction de générateur pour deviner les entrées.
la source
LockIO
mal écrit le cours. J'ai envoyé une demande de modification. Deuxièmement, je pense que vous avez mal lu le critère de notation. Le score est calculé par les données de test générées par le générateur, pas par exemple (j'ai exécuté votre programme et le nombre total est 1005972). Le journal naturel est également manquant. Troisièmement, j'ai spécifié que vous devez fournir un programme complet, vous devez donc également inclure laLockIO
partie dans votre nombre d'octets. De plus, vous devez produire le résultat final, qui est également pris en compte dans le score.Lock
etmasterLock
est juste pour la commodité des tests.LockIO
est ce que vous devez réellement soumettre, car il utilise le format d'E / S requis.R ,
277 octets (score = 1175356)258 octets, tentatives totales = 202999, score = 1163205Essayez-le en ligne!
Version Stdin-stdout, comme demandé par l'OP, pas de passe-partout. Merci à Colera Su d'avoir corrigé un bug initial. Il s'agit d'une version légèrement plus courte que celle des commentaires.
Ci-dessous la soumission TIO pour exécuter un lot de tests dans TIO
R , 189 octets
Essayez-le en ligne!
Considérons un vecteur de zéros comme estimation initiale. Appelons V la distance entre la supposition actuelle et la solution. Pour chaque position, il suffit de vérifier les changements de V lorsque vous remplacez 0 par 5 et par 4. En fait, les différences entre changer 0 par 5 sont répertoriées dans mon vecteur s1. Les différences entre changer 0 par 4 sont répertoriées dans mon vecteur s2. Comme vous le voyez, ces deux vecteurs cartographient de manière unique les chiffres de la solution.
Le nombre total de tests est donc de
3 * L2 * L + 1, où L est la longueur du code: un contrôle initial contre tous les zéros, puis deux contrôles pour chaque chiffre, un contre 5 et un contre 4.L'amélioration d'un facteur 3 à un facteur 2 a été inspirée par la soumission de Kamil Drakari.
Le reste de la soumission TIO est passe-partout pour R. La soumission TIO présente le temps d'exécution et le nombre total d'opérations pour 1000 exécutions avec L = 1 ... 200, 5 répétitions pour chaque valeur de L.
la source
Error in scan(n = 1) : scan() expected 'a real', got 'S=rep(0,L)'
lors de l'exécution.scan(file=file("stdin"),n=1)
marche. Ce programme (identique au vôtre, juste corrigé les E / S) obtient un score de202999*ln(277+50)=1175356
.202999*ln(258+50) != 202999*ln(277+50)