破解密码到密码锁


22

给定一个标准的密码锁,如图所示。解锁的方法是在组合行的代码中对齐4个数字。经过多年的忠诚服务,您已被锁厂解雇,并决定通过在下锁之前先放下锁来进行严格的报复,从而使每把锁都留在组合线上以在组合线上解锁。

密码锁

您还知道,通过查看其他行中数字的顺序,可以计算出组合线上必须有哪些数字(因此,将其解锁的​​组合就是)。

如果为锁上的每一行提供了一个编号,该编号从组合行(用于解锁锁的行)的第0行开始到第9行。例如,如果第4行上的数字为5336,则要解锁的组合为1992

不幸的是,这些锁已经打包,并且您对每个锁的查看都变得模糊了,因此您只能在锁的不同行上看到数字。

挑战

给定4对数字,其中整数的第一个数字表示行号,第二个数字表示在该行上出现的数字,请对锁进行组合。例如,如果您输入:

57 23 99 45

然后它应该输出:

2101

要么

25 78 63 15

3174

假设输入将始终是4个正整数,格式为`25 64 72 18。

这是,所以最短的程序以字节数为准。

这也是我的第一个问题,因此感谢您提供任何反馈意见。


我认为您需要澄清输入内容。您说“ 给定4对整数 ”,然后举一个例子57 23 99 45。那不是四对整数:而是四个整数。有些答案假设它们以字符串形式获取,而其他答案则假定它已准备好解析为4个整数。
彼得·泰勒

我不同意这一事实,它说四对整数使输入的格式清晰明了,57是整数对5和7,而不是整数57。我的第一个假设是该行是57,组合是23
Qwerty14 2014年

1
“数字对”怎么样?这样会更加清晰和精确(并且也可以与前导0s一起使用)。
蓬松的2014年

从技术上讲,正确的术语是置换锁。实际上,大多数“组合锁”都是置换锁,因为数字的顺序会有所不同。
nyuszika7h 2014年

从技术上讲是正确的,但我认为标题不那么吸引人。
罗里·麦克珀罗伊

Answers:


32

CJam,9个 8字节

ea9fbAf%

读取数字对作为命令行参数。要在线尝试代码,请更改ealS/从模拟的STDIN读取。

运行示例

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

怎么运行的

数字d的字符代码是48 + d。因此,考虑两位数的字符串xy为9的基数,得出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.                                                    ";

该死,你不能让别人赢,不?:P
Optimizer

我认为我们没有比这更好的CJam答案了
罗里·麦克珀罗伊

1
那里发生了什么事?
战争

1
@DigitalTrauma:当然可以。字符串"99"实际上是解释为阵列[57 57]通过b; "xy"9b被实现为9 * ord(x) + ord(y)。我应该将其添加到我的答案中。
丹尼斯

4
如果我们将可能的解决方案限制为可打印ASCII, 10,000几乎不能覆盖所有2个字符的程序。
丹尼斯

13

CJam,13 12 11个字符

多亏了user23013,它现在减少到11个字符:)

4{Ar:--A%}*

说明:

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

在线尝试

我知道它可以打更多。但这是我对CJam的第一次真正尝试,受经验的限制:)


另外,其他方法也可以用一个额外的字符来做同样的事情:

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

要么

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

要么

ea{i_A/-A%}/     // If input is passed through command line

我在等这个 好吧,下周...
Soham Chowdhury 2014年

前三个字符也可以是l~]。我觉得分析输入应该可以少于三个,但我从来没有使用CJam前:/
英戈·伯克

4{ri_A/-A%}*短一个字节。
IngoBürk2014年

1
啊,或者您从我先前的评论中得出了什么。好了,现在有两个12字节的解决方案!:)
IngoBürk2014年

3
或者4{Ar:--A%}*
jimmy23013 2014年

6

高尔夫球稿(14 13

在这里在线尝试

它与Optimizer的解决方案几乎相同,只是语言不同。很难用不同的方法来解决它,因为问题很简单,所以关系肯定归于Optimizer,无论如何,Optimizer的条目还早。

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

对于相同数量的字节,您可以执行

~]{.10/- 10%}/

在Golfscript中没有值为10的预定义变量?
Optimizer

@Optimizer不幸的是,没有。太糟糕了,因为与CJam相比,将栈中的输入早已成为优势。
IngoBürk2014年

是的,在CJam中可以是10个字符(在堆栈上输入),在Golfscript中可以是11个字符(具有预定义变量)
Optimizer

如果我不必在高尔夫球室留下空格的话,我也可以在Golfscript中拥有12个- 10
IngoBürk2014年

1
呵呵,即使是最短的语言也有不足之处:P
Optimizer

6

GNU dc,14个字节

借用@Dennis 聪明的9级技巧

9i[?A%nd]dxxxx

从STDIN读取的输入整数,每行一个。

说明:

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    

输出:

$ 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$ 
$ 

上一个答案,18个字节:

因为我以为这样可以更接近“高尔夫”语言(但没有):

[A?A~--A%n]dddxxxx

1
您可以保存一个字节:9i[?A%nd]dxxxx
丹尼斯

@丹尼斯-太棒了!现在,我与golfscript和APL并驾齐驱!
Digital Trauma 2014年

6

C 64 63 56或61

如果输入可以通过文件传递

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

如果输入应键入stdin

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

循环读取四个数字,然后通过从值中减去第一个数字并以10为模输出结果来处理每个数字。

由于以下各种注释以及使用putchar而不是printf而节省了费用


凉。您可以像这样放置在scanf外面,以节省逗号for()a,i;main(){for(;i++-4;printf("%d",(a-a/10)%10))scanf("%d",&a);}
Level River St

你也可以节省2个字节,通过使用a*.9替代a-a/10
REV

@steveverrill喜欢。所以专注于将所有内容都放在我错过的for循环中
Alchymist 2014年

1
@AcidShout抱歉-它不起作用。例如78 * .9 = 70.2,而78-78/10 =71。同样使用.9会将参数提升为双精度,所以我不能采用mod。
Alchymist 2014-09-16

您可以使用while循环并声明a以下参数作为参数来节省一些字节mainmain(a){while(scanf("%d",&a)>0)printf("%d",(a-a/10)%10);}
Dennis

5

Python 3、64

直截了当。

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

如果允许打印,它可以更短一些,例如[2, 1, 0, 1]46):

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

您可以通过str((i-i//10)%10)直接采取而不是使用第二来节省一些费用map()。我也是从发电机开始的,但是发现实际的for循环最终变得更短了。
DLosc 2014年

是的,谢谢你!
Soham Chowdhury 2014年

为什么要使用列表综合?使用genexps保存2个字符:print(''.join((i-i//10)%10for i in map(int,input().split())))。另外,如果输出中允许有空格,则可以避免join使用元组拆包:print(*((i-i//10)%10for i in map(int,input().split())))
Bakuriu 2014年

我想你是对的。
Soham Chowdhury 2014年

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));}

从命令行输入。从第二个参数中减去每个参数的第一个ASCII码,加10并取模10。

我认为这是我第一次printf用4 %而不是逗号写a (逗号在中 #define.


#define f scanf("%c%c ",&a,&b);putchar(48+(9*a+b)%10)随后a,b;main(){f;f;f;f;}将缩短18个字节。
丹尼斯

@Dennis是一个很大的改进,但基本上是一个完全不同的程序。我认为如果有人发布它,应该是您,而不是我。我不确定是否scanf需要scanf空格,因为应该将空格仅作为分隔符进行解析。Alchymist在C语言中有一个更好的主意。但是看来您已经用Cjam答案赢得了它。
水平河圣

是啊,我开始注意到,该空间后,a(n)可以省略,然后我注意到,把printf("%d%,...)周围宏将节省几个字节,最后我有点忘乎所以...... -需要空间,因为%c读入一个字符,任何字符,因此在第二次运行时它将在中存储32 a。-用C击败CJam应该很困难。printf()已经是我的答案了……
丹尼斯

4

Java-203字节

仅仅因为必须有一个Java条目,我看到了一个很好的机会让此代码成为可能(有史以来第一次提交)。

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);}}

如果还有改进的余地,我很乐意了解它们;-)


您可以搜索[技巧]并获得各种有关高尔夫的技巧,以帮助您入门:)
Optimizer

太好了,谢谢!查看一些技巧帮助我节省了13个字节:)
Sander 2014年

3

Lua-46个字符

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

一次读取三个字符(请给我一点点的怜悯,在末尾输入一个空格),尽管a和b是字符串y。打印时是否进行环绕检查。

我如何运行它:


1
您能否提供示例数据输入/输出,似乎无法使其在Ideone
Rory McPerlroy 2014年

@ Harry12345啊,对此感到抱歉。无政府状态高尔夫让我开始思考如何实现stdinput。我可能会编写更好的代码,但是lua太糟糕了。我发布了一个我运行程序的示例。
AndoDaan 2014年

3

JavaScript ES6 – 53 43字节

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

相当简单的函数,使用正则表达式获取数字。在尝试 http://jsfiddle.net/efc93986/1/上。如果不允许使用功能,请使用52字节的独立程序:

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

由于ES6当前仅在Firefox上运行,因此以下代码可在任何现代浏览器上运行,字节数为70:

alert(prompt().replace(/.. ?/g,function(a){return(1+a[1]-a[0])%10}))

我爱你1+
尼尔

1
问题是假设输入有效,因此您可以使用...?代替/\d+ ?。返回后的空格可以省略。另外,由于未指定特定的I / O,因此您应该可以使用功能。
丹尼斯2014年

1
a-a[0]而不是1+a[1]-a[0]应该工作。
丹尼斯

2

Python 2-33个字节

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

接受以逗号分隔的用户输入。例如输入:

29,26, 31, 88

输出:

7
4
8
0

如果要求输出与示例完全匹配,则它会更长。47个字节:

print"%d"*4%tuple((i-i/10)%10 for i in input())

input()在我的Python 2解释器中不起作用。
Soham Chowdhury 2014年

@SohamChowdhury您使用逗号了吗?
feersum

2
哦,不,我没有。现在可以使用了。附带一提,我认为您需要按照规范输入以空格分隔的输入。
Soham Chowdhury 2014年

3
我同意,输入应该是空间去限制
罗里McPerlroy

2

APL,14

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

说明
从屏幕输入。以空格分隔的值被解析为数组。
{...}¨对于每个数字,将其输入函数。
⍎¨⍕⍵接受参数,创建其数字数组。
--/计算单位减去十。
10|国防部10。


1
这可能是14个字符,但它是24 个字节
IngoBürk2014年

@IngoBürkcodegolf.stackexchange.com/ questions
TwiNight 2014年

但是对于代码高尔夫,我们使用UTF-8,而不是一些特殊的字符集。那只是一个漏洞,很容易被滥用。
IngoBürk2014年

1
@IngoBürk根据meta.codegolf.stackexchange.com/a/961/6972,答案可以用任何编码进行编码,除非OP另有说明。确实有一个用于APL字符的IBM代码页,它是一个单字节映射,这正是Dyalog在Unicode 3.0之前使用的代码。如果您坚持使用Unicode,那么如果我发明一种使用非Unicode字符的新语言怎么办?您将如何计算字节数?
TwiNight 2014年

我可以宣誓默认值为UTF-8。然后是14个字节。
IngoBürk2014年

2

20 15

非动词形式(作为语句而不是函数定义)短5个字符:

10|-~/|:10#.inv

动词形式是一个很好的火车

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

在示例输入中使用的动词:

   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

2

哈斯克尔60 58

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

单字符数字,这是Haskell打高尔夫球的真正克星。


2

佩尔:38 40

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

输出:

% perl code.pl
57 23 99 45
2101

25 78 63 15                                     
3174

1
1.下划线是markdown语法,因此您的代码有些混乱。为避免这种情况,请使用四个空格缩进代码。2. abs没必要;x - x/10不能为负。3.如果您使用标志-040pe(通常计数为5个字节)遍历以空格分隔的输入,则可以将代码缩短为$_=($_-int$_/10)%10。4.如果您希望避免使用命令行标志,仍然可以通过设置$/=$;和删除对的调用来节省一些字节split
丹尼斯2014年

1

Ruby,35个字节

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

说明

输入作为命令行参数。String#bytes返回一个整数数组(ASCII字符代码)。只有最后一个字符代码和第一个字符代码之间的差异才是重要的,而不是整数本身。


1

C#和LinqPad:104

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

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

1.不确定其他编译器,但GCC要求#include<iostream>std::之前cincout。2.如果省略,则不需要条件a=a%10。3.您不需要for循环周围的变量bc,换行符和括号(进行了一些修改)。
丹尼斯2014年

1
@SeanD:请不要批准修改代码的编辑。在这种情况下,编辑会使答案无效。它还删除了第一行,该行应出现在所有答案中。
丹尼斯

1
(CC @TeunPronk)
丹尼斯

@Dennis通常在此站点上的答案不包含预处理程序行。我省略了这些行,#include<iostream>并且using namespace std;
bacchusbeale 2014年

我知道通常不包括在字节数中,但是我认为它们应该出现在答案中。
丹尼斯

1

PHP-90个字符

以为我会尝试打高尔夫球,所以这是我的第一次尝试-可能会打更多的高尔夫球。

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

58个字符(由Ismael Miguel提供)

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

使用访问文件

file.php?n=57239945

尝试以下代码:<? for($i=0;$i<4;)echo abs($_GET[n][$i]%10);长度为44个字符。使用可以从浏览器访问file.php?n[]=xx&n[]=yy&n[]=xy&n[]=yx。(未经验证的代码)
Ismael Miguel 2014年

使用好主意,$_GET但它显示57%10,我需要(5-7)%10-
罗里·麦克珀罗伊

试试这个:<? for($i=0,$a=$_GET[n];$i<4;++$i)echo abs($a[$i][0]-$a[$i++][1]%10);。可悲的是,它的长度为65个字节。(忘记$i最后一个的增量),或者您可以尝试<? for($i=0;$i<8;)echo abs($_GET[n][$i++]-$_GET[n][$i++]%10);使用file.php?n[]=x&n[]=y&n[]=x&n[]=y&n[]=x&n[]=y&n[]=x&n[]=y,长度为61个字节,来访问浏览器。
Ismael Miguel 2014年

是的,第二个有效,需要做$_GET['n']。编辑了我的答案。
罗里·麦克珀罗伊

好吧,这不是必需的。它只是发出警告。这个网站很好。但是请尝试以下操作:<? for($i=0,$a=$_GET[n];$i<8;)echo abs($a[$i++]-$a[$i++]);。这个%10是没有用的,而这个看起来更好。另外,您可以使用访问它file.php?n[]=xyxyxyxy。该解决方案长58个字节。
Ismael Miguel 2014年

0

Python 3、60

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

输入和输出完全按照指定的方式进行,尽管它不会打印尾随的换行符。这里有两个有趣的技巧:1)用到的int()一个调用替换两个to的调用eval(),以及2)使用join()get a-b,然后b-a根据需要取反。幸运的是,即使第一个参数为负,Python的模运算符也会给出正值!


为什么这被否决?它工作得很好。(顺便说一句,eval('-'.join(x))技巧很出色。)
flornquake 2014年

@flornquake谢谢!
DLosc
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.