Crackez le code de la serrure à combinaison

22

Étant donné une serrure à combinaison standard comme celle de l'image. Le moyen de le déverrouiller consiste à aligner les 4 chiffres du code sur la ligne de combinaison. Après des années de bons et loyaux services, vous avez été licencié de la fabrique de serrures et vous avez décidé de vous venger en ne mélangeant pas les serrures avant de les envoyer, laissant ainsi chaque serrure avec la combinaison pour la déverrouiller sur la ligne de combinaison.

Serrure à combinaison

Vous savez également qu'en regardant l'ordre des numéros dans les autres lignes, il est possible de déterminer quels numéros doivent être sur la ligne de combinaison (et donc la combinaison pour la déverrouiller).

Si chaque ligne de la serrure reçoit un numéro à partir de la ligne 0 pour la ligne de combinaison (la ligne qui déverrouille la serrure) à la ligne 9. Par exemple, si les numéros de la ligne 4 le sont 5336, alors la combinaison pour la déverrouiller serait 1992.

Malheureusement, les serrures ont déjà été emballées et votre vue de chaque serrure est obscurcie, vous ne pouvez donc voir que les numéros sur différentes lignes de la serrure.

Le défi

Étant donné 4 paires de chiffres, où le premier chiffre de l'entier représente le numéro de ligne et le deuxième chiffre représente le numéro qui apparaît sur cette ligne, déterminez la combinaison du verrou. Par exemple, si vous saisissez:

57 23 99 45

Ensuite, il devrait sortir:

2101

Ou

25 78 63 15

et

3174

Supposons que l'entrée sera toujours 4 entiers positifs sous la forme `25 64 72 18.

Il s'agit de , donc les programmes les plus courts en nombre d'octets gagnent.

C'est aussi ma première question, donc tout commentaire est apprécié.

Rory McPerlroy
la source
Je pense que vous devez clarifier l'entrée. Vous dites " Étant donné 4 paires d'entiers " et donnez ensuite un exemple 57 23 99 45. Ce n'est pas quatre paires d'entiers: c'est quatre entiers. Et certaines réponses supposent qu'elles obtiennent cela sous forme de chaîne, tandis que d'autres supposent qu'elle est prête à être analysée en 4 pouces.
Peter Taylor
Je ne suis pas d'accord, le fait qu'il indique quatre paires d'entiers rend le format de l'entrée clair, 57 est la paire d'entiers 5 et 7, pas l'entier 57. Ma première hypothèse était que la ligne était 57 et la combinaison était 23.
Qwerty01
1
Que diriez-vous des "paires de chiffres?" Ce serait beaucoup plus clair et précis (et fonctionne également avec les 0s principaux ).
moelleux
Techniquement, le terme correct serait verrou de permutation . La plupart des "verrous à combinaison" sont en fait des verrous à permutation, car l'ordre des chiffres fait une différence.
nyuszika7h
Techniquement oui, c'est correct, mais je ne pense pas que cela donne un titre accrocheur.
Rory McPerlroy

Réponses:

32

CJam, 9 8 octets

ea9fbAf%

Lit les paires de chiffres comme arguments de ligne de commande. Pour essayer le code en ligne , passez eaà lS/pour lire à partir de STDIN simulé.

Exemple d'exécution

$ cjam <(echo ea9fbAf%) 57 23 99 45; echo
2101
$ cjam <(echo ea9fbAf%) 25 78 63 15; echo
3174

Comment ça marche

Le code de caractère du chiffre d est 48 + d . Ainsi, en considérant la chaîne à deux chiffres xy, un nombre de base 9 donne 9 * (48 + x) + (48 + y) = 10 * (48 + x) + y - x ≡ y - x (mod 10) .

ea       " Push the array of command-line arguments.                                      ";
  9fb    " Mapped base 9 conversion; replace each string 'xy' with (9 * ord(x) + ord(y)). ";
     Af% " Take the results modulo 10.                                                    ";
Dennis
la source
Bon sang, tu ne peux pas laisser quelqu'un d'autre gagner, non? : P
Optimizer
Je ne pense pas que nous aurons une meilleure réponse CJam que celle-ci
Rory McPerlroy
1
Qu'est-ce qui vient de se passer là-bas?
Guerre du
1
@DigitalTrauma: Bien sûr, allez-y. La chaîne "99"est en fait interprétée comme le tableau [57 57]par b; "xy"9best implémenté en tant que 9 * ord(x) + ord(y). Je devrais ajouter cela à ma réponse.
Dennis
4
10000 couvre à peine tous les programmes à 2 caractères si nous limitons les solutions possibles à l'ASCII imprimable.
Dennis
13

CJam, 13 12 11 caractères

Grâce à user23013, il est maintenant réduit à 11 caractères :)

4{Ar:--A%}*

Explications:

4{       }*     "Run the code block 4 times";
   r            "Read the next input token (whitespace separated)";
    :-          "Subtract 2nd number from the first treating r as a 2 numbered string";
  A   -         "Subtract the result of above from 10";
       A%       "Take modulus of 10 and store it on stack";

Essayez-le en ligne

Je sais qu'on peut jouer au golf plus. Mais c'est ma première vraie tentative sur CJam et je suis limité par l'expérience :)


Alternativement, les autres méthodes pour faire la même chose avec 1 caractère supplémentaire:

l~]{_A/-A%}/     // My previous solution

ou

4{ri_A/-A%}*     // As pointed out by Ingo

ou

ea{i_A/-A%}/     // If input is passed through command line
Optimiseur
la source
J'étais en train d'attendre pour cela. Eh bien, la semaine prochaine ...
Soham Chowdhury
Les trois premiers caractères pourraient également être l~]. J'ai l'impression que l'analyse de l'entrée devrait être possible avec moins de trois, mais je n'ai jamais utilisé CJam auparavant: /
Ingo Bürk
4{ri_A/-A%}*est un octet plus court.
Ingo Bürk
1
Ah, ou ce que vous avez fait de mon commentaire précédent. Eh bien maintenant, il y a deux solutions de 12 octets! :)
Ingo Bürk
3
Ou 4{Ar:--A%}*.
jimmy23013
6

Golfscript (14 13 )

Essayez-le en ligne ici

C'est à peu près la même chose que la solution d'Optimizer , mais dans une langue différente. Il est difficile de l'aborder différemment car le problème est assez simple , donc la cravate va certainement à l'Optimizer, dont l'entrée était plus tôt de toute façon.

~]{.10:^/-^%}/

Pour le même nombre d'octets que vous pouvez faire

~]{.10/- 10%}/
Ingo Bürk
la source
Aucune variable prédéfinie avec une valeur 10 dans Golfscript?
Optimizer
@Optimizer Malheureusement, non. Dommage, car avoir déjà l'entrée sur la pile serait l'avantage sur CJam.
Ingo Bürk
Oui, il peut être de 10 caractères dans CJam (avec entrée sur la pile) ou 11 dans Golfscript (avec variable prédéfinie)
Optimizer
Je pourrais aussi avoir 12 dans Golfscript si seulement je n'avais pas à laisser de place - 10.
Ingo Bürk
1
heh, même la plus courte des langues ont leurs courtes allées: P
Optimizer
6

GNU dc , 14 octets

Emprunter le truc astucieux de base 9 de Dennis :

9i[?A%nd]dxxxx

Entiers d'entrée lus depuis STDIN, un par ligne.

Explication:

9i                # Set input radix to 9
  [     ]         # push a macro, defined thus:
   ?              #   read number from STDIN and push
    A             #   push literal 10
     %            #   calculate number mod 10
      n           #   print, with no newline
       d          #   duplicate macro
         d        # duplicate macro
          xxxx    # execute the macro 4 times    

Sortie:

$ for i in 57 23 99 45; do echo $i; done | dc ./combolock.dc
2101$ 
$ for i in 25 78 63 15; do echo $i; done | dc ./combolock.dc
3174$ 
$ 

Réponse précédente, 18 octets:

Parce que je pensais que je pourrais me rapprocher des langues "golf" avec ça (mais je ne l'ai pas fait):

[A?A~--A%n]dddxxxx
Traumatisme numérique
la source
1
Vous pouvez enregistrer un octet:9i[?A%nd]dxxxx
Dennis
@Dennis - Fantastique! Maintenant, je suis au coude à coude avec golfscript et APL!
Digital Trauma
6

C 64 63 56 ou 61

Si l'entrée peut être envoyée depuis un fichier

main(a){while(scanf("%d",&a)>0)putchar(48+(a-a/10)%10);}

Si l'entrée doit être tapée en stdin

i;main(a){for(;i++-4;putchar(48+(a-a/10)%10))scanf("%d",&a);}

Lit les quatre nombres dans une boucle puis traite chacun en soustrayant le premier chiffre de la valeur et en imprimant le résultat modulo 10.

Économies grâce aux divers commentaires ci-dessous et en utilisant également putchar au lieu de printf

Alchymiste
la source
Cool. Vous pouvez enregistrer une virgule en mettant l' scanfextérieur for()comme cecia,i;main(){for(;i++-4;printf("%d",(a-a/10)%10))scanf("%d",&a);}
Level River St
Vous pouvez également enregistrer 2 octets en utilisant a*.9au lieu dea-a/10
rev
@steveverrill J'aime ça. Alors concentré sur tout mettre dans la boucle que j'ai raté
Alchymist
1
@AcidShout Désolé - cela ne fonctionne pas. Par exemple 78 * .9 = 70.2, tandis que 78 - 78/10 = 71. L'utilisation de .9 favorise également l'argument à un double, donc je ne peux pas prendre le mod.
Alchymist
Vous pouvez économiser quelques octets en utilisant une whileboucle et en déclarant acomme argument main:main(a){while(scanf("%d",&a)>0)printf("%d",(a-a/10)%10);}
Dennis
5

Python 3, 64

Simple.

print(''.join([(i-i//10)%10 for i in map(int,input().split())]))

Il peut être plus court si je suis autorisé à imprimer, disons à la [2, 1, 0, 1]place ( 46 ):

print([i%10-i//10 for i in map(int,input().split())])
Soham Chowdhury
la source
Vous pouvez en sauvegarder en prenant str((i-i//10)%10)directement au lieu d'en utiliser une seconde map(). J'ai aussi commencé avec des générateurs pour le mien, mais j'ai constaté qu'une forboucle réelle était finalement plus courte.
DLosc
Oui, merci pour ça!
Soham Chowdhury du
Pourquoi utilisez-vous des listes de compréhension? Utilisez genexps pour sauver 2 caractères: print(''.join((i-i//10)%10for i in map(int,input().split()))). De plus , si les espaces sont dans la sortie provoque bien vous pouvez éviter joinet déballage tuple utilisation: print(*((i-i//10)%10for i in map(int,input().split()))).
Bakuriu du
Je suppose que vous avez raison.
Soham Chowdhury
4

C, 92

#define a(n) ,(10+v[n][1]-*v[n])%10
main(int c,char**v){printf("%d%d%d%d"a(1)a(2)a(3)a(4));}

Entrée depuis la ligne de commande. Soustrait le premier code ASCII de chaque argument du second, ajoute 10 et prend modulo 10.

Je pense que c'est la première fois que j'écris un printfavec quatre %s et sans virgule (la virgule est dans le #define.)

Level River St
la source
#define f scanf("%c%c ",&a,&b);putchar(48+(9*a+b)%10)suivi a,b;main(){f;f;f;f;}serait de 18 octets plus court.
Dennis
@Dennis c'est une grande amélioration, mais c'est fondamentalement un programme complètement différent. Je pense que si quelqu'un l'affiche, ce devrait être vous, pas moi. Je ne sais pas si l'espace dedans scanfest nécessaire, étant donné qu'il scanfest censé analyser les espaces blancs uniquement comme séparateur. Alchymist a une idée encore meilleure en C. Mais il semble que vous l'ayez déjà gagnée avec votre réponse Cjam.
Level River St
Ouais, j'ai commencé par remarquer que l'espace après a(n)pouvait être omis, puis j'ai remarqué que mettre printf("%d%,...)autour de votre macro économiserait quelques octets et finalement je me suis un peu emporté ... - L'espace est nécessaire car %clit un caractère, n'importe quel caractère, donc lors de la deuxième exécution, il stockerait 32 pouces a. - Battre CJam avec C devrait s'avérer difficile. printf()est déjà aussi longue que ma réponse ...
Dennis
4

Java - 203 octets

Juste parce qu'il doit y avoir une entrée Java, j'ai vu une belle opportunité de donner une chance au golf (première soumission jamais).

class M{public static void main(String[] a){String r="";for(int i=0;i<4;i++){int l=Byte.valueOf(a[i].substring(1));int f=Byte.valueOf(a[i].substring(0,1));r+=(l-f<0)?l-f+10:l-f;}System.out.print(r);}}

S'il y a de la place pour quelques améliorations, je serais heureux de les connaître ;-)

Sander
la source
Vous pouvez rechercher [conseils] et obtenir divers conseils sur le golf pour vous aider à démarrer :)
Optimizer
Cool merci! Vérifier quelques conseils m'a aidé à raser 13 octets :)
Sander
3

Lua - 46 personnages

while''do a,b=io.read(1,1,1)print((b-a)%10)end

Lit trois caractères à la fois (accordez-moi la petite pitié de saisir un espace à la fin), et même si a et b sont string-y ... ba MAGICALEMENT leur permet de concevoir un bébé entier sain. Est-ce que le retour à la ligne est vérifié lors de l'impression.

Comment je le gère:

AndoDaan
la source
1
Pourriez-vous fournir un exemple d'entrée / sortie de données, ne semble pas pouvoir le faire fonctionner sur Ideone
Rory McPerlroy
@ Harry12345 Ah, désolé pour ça. Anarchy Golf est en train de décider comment implémenter stdinput. Je pourrais probablement mieux le coder, mais meh, lua est terrible. J'ai posté un exemple de moi exécutant le programme.
AndoDaan
3

JavaScript ES6 - 53 43 octets

f=n=>n.replace(/.. ?/g,a=>(1+a[1]-a[0])%10)

Fonction assez simple, utilise l'expression régulière pour obtenir les chiffres. Essayez-le sur http://jsfiddle.net/efc93986/1/ . Si les fonctions ne sont pas autorisées, un programme autonome à 52 octets:

alert(prompt().replace(/.. ?/g,a=>(1+a[1]-a[0])%10))

Comme ES6 ne fonctionne actuellement que sur Firefox, le code suivant fonctionne sur n'importe quel navigateur moderne, à 70 octets:

alert(prompt().replace(/.. ?/g,function(a){return(1+a[1]-a[0])%10}))
NinjaBearMonkey
la source
Je t'aime 1+.
Neil
1
La question dit de supposer une entrée valide, vous pouvez donc utiliser à la ...?place de /\d+ ?. L'espace après le retour peut être omis. De plus, étant donné qu'aucune E / S spécifique n'a été spécifiée, vous devriez pouvoir utiliser une fonction.
Dennis
1
a-a[0]au lieu de 1+a[1]-a[0]devrait également fonctionner.
Dennis
2

Python 2 - 33 octets

for i in input():print(i-i/10)%10

Accepte les entrées utilisateur séparées par des virgules. Par exemple, entrée:

29,26, 31, 88

Sortie:

7
4
8
0

Si la sortie doit correspondre exactement à l'exemple, elle est beaucoup plus longue. 47 octets:

print"%d"*4%tuple((i-i/10)%10 for i in input())
feersum
la source
input()ne fonctionne pas dans mon interpréteur Python 2.
Soham Chowdhury le
@SohamChowdhury avez-vous utilisé des virgules?
feersum
2
Oh, non, je ne l'ai pas fait. Ça fonctionne maintenant. Sur une note latérale, je pense que vous devez prendre une entrée délimitée par l'espace selon la spécification.
Soham Chowdhury le
3
Je suis d'accord, l'entrée doit être limitée en espace
Rory McPerlroy
2

APL, 14

10|{--/⍎¨⍕⍵}¨⎕

L'explication
prend l'entrée de l'écran. Les valeurs séparées par des espaces sont analysées sous forme de tableau.
{...}¨pour chaque numéro, introduisez-le dans la fonction.
⍎¨⍕⍵prend l'argument, créez un tableau de ses chiffres.
--/calcule les unités moins les dizaines.
10|mod 10.

TwiNight
la source
1
Il peut s'agir de 14 caractères, mais de 24 octets .
Ingo Bürk
mais pour le golf de code, nous comptons en UTF-8, pas un jeu de caractères spécial. Ce serait juste une faille et pourrait être abusé très facilement.
Ingo Bürk
1
@ IngoBürk Selon meta.codegolf.stackexchange.com/a/961/6972, les réponses peuvent être encodées dans n'importe quel encodage, sauf indication contraire de l'OP. Il existe en effet une page de codes IBM pour les caractères APL qui est un mappage à un octet, ce qui est exactement ce que Dyalog utilisait avant Unicode 3.0. Si vous insistez sur Unicode, que se passe-t-il si j'invente une nouvelle langue qui utilise des caractères non Unicode? Comment comptez-vous les octets pour cela?
TwiNight
J'aurais juré que la valeur par défaut était UTF-8. C'est donc 14 octets.
Ingo Bürk du
2

J - 20 15

La forme non verbale (comme instruction au lieu de la définition de la fonction) est 5 caractères plus courte:

10|-~/|:10#.inv

La forme verbale qui est un joli train :

10|[:-~/[:|:10#.inv]

Ce verbe utilisé sur les exemples d'entrées:

   10|-~/|:10#.inv 57 23 99 45
2 1 0 1
   10|-~/|:10#.inv 25 78 63 15
3 1 7 4

rotd =: 10|[:-~/[:|:10#.inv] NB. verb form

   rotd 25 78 63 15
3 1 7 4
   rotd 57 23 99 45
2 1 0 1
jpjacobs
la source
2

Haskell 60 58

main=interact$show.map((\x->mod(x-x`div`10)10).read).words

Chiffres à un seul caractère, un véritable ennemi du golf à Haskell.

Zeta
la source
2

Perl: 38 40

print abs($_-int$_/10)%10for split" ",<>

Sortie:

% perl code.pl
57 23 99 45
2101

25 78 63 15                                     
3174
Riymus
la source
1
1. Les traits de soulignement sont une syntaxe de démarque, donc votre code a été un peu foiré. Pour éviter cela, indenter le code avec quatre espaces. 2. absn'est pas nécessaire; x - x/10ne peut pas être négatif. 3. Si vous utilisez les indicateurs -040pe(généralement comptés comme 5 octets) pour parcourir les entrées délimitées par un espace, vous pouvez raccourcir votre code en $_=($_-int$_/10)%10. 4. Si vous préférez éviter les indicateurs de ligne de commande, vous pouvez toujours enregistrer quelques octets en définissant $/=$;et en supprimant l'appel à split.
Dennis
1

Rubis, 35 octets

$*.map{|n|a,b=n.bytes;$><<(b-a)%10}

Explication

L'entrée est prise comme argument de ligne de commande. String#bytesrenvoie un tableau d'entiers (codes de caractères ASCII). Seule la différence entre le dernier et le premier code de caractère est importante, pas les entiers eux-mêmes.

britishtea
la source
1

C # et LinqPad: 104

Util.ReadLine<string>("").Split(' ').Select(s =>(s[1]-s[0])).Aggregate("",(r,a)=>r+(a<0?10+a:a)).Dump();
EvilFonti
la source
1

C ++ 118

int main()
{
int a,b,c;
for(int i=0; i<4; i++)
{
cin>>a;
b=a/10;
a=a%10;
c=a-b;
if(c<0)c+=10;
cout<<c;
}
}
bacchusbeale
la source
1. Je ne suis pas sûr des autres compilateurs, mais GCC requiert #include<iostream>et std::avant cinet cout. 2. Vous n'avez pas besoin du conditionnel si vous omettez a=a%10. 3. Vous n'avez pas besoin des variables bet cdes sauts de ligne et (avec quelques modifications) des crochets autour de la boucle for.
Dennis
1
@SeanD: veuillez ne pas approuver les modifications qui modifient le code. Dans ce cas particulier, la modification a rendu la réponse invalide. Il a également supprimé la première ligne, qui devrait être présente dans toutes les réponses.
Dennis
1
(CC @TeunPronk)
Dennis
@Dennis répond généralement sur ce site ne comprend pas de lignes de préprocesseur. J'ai omis les lignes #include<iostream>etusing namespace std;
bacchusbeale
Je sais qu'il n'est généralement pas inclus dans le nombre d'octets, mais je pense qu'ils devraient être présents dans la réponse.
Dennis
1

PHP - 90 caractères

Je pensais que j'essaierais le golf de code alors voici, ma première tentative - peut probablement être joué plus.

<?php $a=array(57,23,99,45);foreach($a as$b){echo abs(substr($b,0,1)-substr($b,1,1)%10);}

58 personnages (gracieuseté d'Ismael Miguel)

for($i=0,$a=$_GET[n];$i<8;)echo abs($a[$i++]-$a[$i++]);

Accéder au fichier à l'aide

file.php?n=57239945
Rory McPerlroy
la source
Essayez ce code: <? for($i=0;$i<4;)echo abs($_GET[n][$i]%10);qui fait 44 caractères. Accès à partir d'un navigateur à l'aide de file.php?n[]=xx&n[]=yy&n[]=xy&n[]=yx. (code non testé)
Ismael Miguel
Bonne idée d'utiliser $_GETmais il affiche 57% 10 et j'ai besoin de (5-7)% 10
Rory McPerlroy
Essayez celui - ci: <? for($i=0,$a=$_GET[n];$i<4;++$i)echo abs($a[$i][0]-$a[$i++][1]%10);. Malheureusement, il fait 65 octets de long. (oublié l' $iincrémentation sur le dernier) Ou vous pouvez essayer d' <? for($i=0;$i<8;)echo abs($_GET[n][$i++]-$_GET[n][$i++]%10);accéder au navigateur en utilisant file.php?n[]=x&n[]=y&n[]=x&n[]=y&n[]=x&n[]=y&n[]=x&n[]=y61 octets de long.
Ismael Miguel
Oui, le second fonctionne, il faut le faire $_GET['n']. J'ai édité ma réponse.
Rory McPerlroy
Eh bien, ce n'est pas obligatoire. Il émet simplement un avertissement. C'est très bien pour ce site Web. Mais essayez celui - ci: <? for($i=0,$a=$_GET[n];$i<8;)echo abs($a[$i++]-$a[$i++]);. Le %10est inutile et celui-ci est tout simplement meilleur. Vous pouvez également y accéder à l'aide de file.php?n[]=xyxyxyxy. Cette solution fait 58 octets.
Ismael Miguel,
0

Python 3, 60

for x in input().split():print(-eval('-'.join(x))%10,end='')

Entrer et sortir exactement comme spécifié, bien qu'il n'imprime pas de nouvelle ligne de fin. Deux astuces intéressantes ici: 1) remplacer deux appels à int()un appel à eval(), et 2) utiliser join()pour obtenir a-b, puis l'annuler b-asi nécessaire. Heureusement, l'opérateur modulo de Python donne des valeurs positives même si le premier argument est négatif!

DLosc
la source
Pourquoi cela a-t-il été rejeté? Cela fonctionne parfaitement bien. (Btw, l' eval('-'.join(x))astuce est géniale.)
flornquake
@flornquake Merci!
DLosc