密码锁


46

场景

经过一整天的辛苦工作,在办公室里浏览并浏览了stackexchange.com之后,我终于在16:58走出家门,已经疲倦了。因为我仍然只是一名实习生,所以我目前的交通方式是骑自行车。我前往值得信赖的Peugeot Reynolds 501,但是在我不能驶向它之前,我需要将其解锁。该锁是通过框架和前轮的标准四位数密码锁(0-9)。当我尝试保持清醒时,我将手向上拉以进入组合。 密码锁

挑战

因为我的手指很疲劳,所以我想用最少的动作将锁调到正确的位置。一移动定义为旋转一个位置(36度),例如,从5737到移动一5738。但是,我能够同时抓取最多三个连续的环,并将它们旋转为一个,这仅算作一个动作。例如,从到到仅有一个移动。从到移动不是一个动作,因为数字1,2和4向同一方向移动,但独立于数字3。57376837562657376838

因此,对于给定的组合,我可以在自行车锁上看到(任何4位整数),使锁解锁的最低移动量是多少,是的,我可以随时朝任一方向旋转。我的意思是,我可以在一个方向上转动一些数字,而在另一个方向上转动其他数字:对于每次解锁,并非我的所有动作都是顺时针或顺时针方向。

因为我很懒,所以我的解锁码是0000。

这是我无法打扰的代码编写工作,因此以字节数为单位的最短程序获胜。

输入来自stdin,您的代码应输出每次移动后每一步都能看到的组合,包括末尾的0000。每个组合输出都应以空格/换行符/逗号/句号/&符号分隔。

例子

Input: 1210
0100
0000

Input: 9871
9870
0980
0090
0000

Input: 5555
4445&3335&2225&1115&0005&0006&0007&0008&0009&0000

Input: 1234
0124 0013 0002 0001 0000

我尝试将其发布在http://bicycles.stackexchange.com上,但他们不喜欢它...

免责声明:第一次打高尔夫球,所以任何损坏的信息/遗失信息都请通知我!我也手动完成了所有示例,因此可能会有涉及较少动作的解决方案!

编辑:对于具有多个具有相等移动量(实际上是全部)的解决方案路径的答案,没有首选的解决方案。


18
欢迎来到PPCG;非常好的第一个挑战!
Doorknob

4
在我看来,这很可靠!欢迎来到PPCG!
Mego

1
很好的挑战。请问7478和3737的输出是什么?
noisyass2

1
@ noisyass2谢谢;弄乱者的答案如下:7478 8588 9698 0708 0808 0908 0008 0009 0000和3737 2627 1517 0407 0307 0207 0107 0007 0008 0009 0000仅查看3737,这是有道理的:仅查看前3位数字:如果我将所有前三个同时执行,数字1和3需要3个动​​作,然后数字2需要另外4个动作,因此总共需要7个动作。而如果我每个人单独移动,则每个动作需要3个动​​作,因此需要9个动作。
2013年

1
我想知道标题“密码锁”(或“自行车锁”)是否会吸引更多观众。
DavidC

Answers:


10

Matlab,412 327字节

打高尔夫球(感谢@AndrasDeak打高尔夫球s!):

s=dec2bin('iecbmgdoh'.'-97)-48;s=[s;-s];T=1e4;D=Inf(1,T);P=D;I=NaN(T,4);for i=1:T;I(i,:)=sprintf('%04d',i-1)-'0';end;G=input('');D(G+1)=0;for k=0:12;for n=find(D==k);for i=1:18;m=1+mod(I(n,:)+s(i,:),10)*10.^(3:-1:0)';if D(m)==Inf;D(m)=k+1;P(m)=n-1;end;end;end;end;n=0;X='0000';while n-G;n=P(n+1);X=[I(n+1,:)+48;X];end;disp(X)

该代码使用一些动态编程来查找从给定数字到0000仅使用可能的步骤的最短“路径” 。挑战基本上是最短的路径难题(或者,您可以将这些步骤视为可交换的组。),但是要解决有效的困难。基本结构是两个10000个元素的数组,一个数组用于存储获取该索引的步骤数,另一个数组用于存储指向图形中上一个“节点”的指针。它同时计算所有其他可能数字的“路径”。

例子:

9871
0981
0091
0001
0000

1210
0100
0000

Examples by @noisyass:

7478
8578
9678
0788
0899
0900
0000

3737
2627
1517
0407
0307
0207
0107
0007
0008
0009
0000

Own Example (longest sequence, shared with 6284)

4826
3826
2826
1826
0826
0926
0026
0015
0004
0003
0002
0001
0000    

完整代码(包括一些注释):

%steps
s=[eye(4);1,1,0,0;0,1,1,0;0,0,1,1;1,1,1,0;0,1,1,1];
s=[s;-s];


D=NaN(1,10000);%D(n+1) = number of steps to get to n
P=NaN(1,10000);%P(n+1) was last one before n

I=NaN(10000,4);%integer representation as array
for i=0:9999; 
    I(i+1,:)=sprintf('%04d',i)-'0';
end

G=9871; % define the current number (for the golfed version replaced with input('');
D(G+1)=0;
B=10.^(3:-1:0); %base for each digit

for k=0:100; %upper bound on number of steps;
    L=find(D==k)-1;
    for n=L; %iterate all new steps
        for i=1:18; %search all new steps
            m=sum(mod(I(n+1,:)+s(i,:),10) .* [1000,100,10,1]);
            if isnan(D(m+1))
                D(m+1) = k+1;
                P(m+1)=n;
            end
        end
    end
end
n=0;%we start here
X=[];
while n~=G
    X=[I(n+1,:)+'0';X];
    n=P(n+1);
end
disp([I(G+1,:)+'0';X,''])

真好!我自己是Matlab的主要用户,我想知道它的性能如何。
2013年

1
作为输入,6444您的代码给出了6444 7554 8664 9774 0884 0994 0004 0003 0002 0001 0000,而我发现答案是6444 6333 6222 6111 6000 7000 8000 90000000。我的答案是8个步骤,您的答案是10。问题,而且高尔夫版和非高尔夫版都存在。这已在您的最新编辑中修复。
2016年

1
我只是更正了代码中的一个小错误。在s最后一行[0,1,1,1]。然后,您也会得到一个8步解决方案!我给您带来不便=)对不起
flawr

1
@Lui这里有一个matlab / octave聊天室,它是Matlab衍生的languange MATL打高尔夫球的基础。
瑕疵的

1
对于4826,我发现了11个移动解决方案:4826 3716 2606 1506 0406 0306 0206 0106 0007 0008 0009 0000
noisyass2 2016年

4

批处理-288字节

即使您说它们必须是连续的(圆环),但我还是根据逻辑假设(按照示例)假定我可以跳过中间的圆环,例如从1234to 0224

设置/像素=
设置a =%x:〜0,1%&设置b =%x:〜1,1%&设置c =%x:〜2,1%&设置d =%x:〜3,1%
:l
@echo%x%&if%a%== 0(如果%d%NEQ 0置位/ ad = d-1),否则置位/ aa = a-1
@if%b%NEQ 0置位/ ab = b-1
@if%c%NEQ 0 set / ac = c-1
@if%x%NEQ 0000 set x =%a %% b %% c %% d%&goto l

这是我的批处理解决方案:236个字节。


编辑:更正的解决方案

设置/像素=
设置a =%x:〜0,1%&设置b =%x:〜1,1%&设置c =%x:〜2,1%&设置d =%x:〜3,1%
:l
@echo%x%&set k = 1&if%a%== 0(如果%d%NEQ 0 set / ad = d-1&set k = 0),否则set / aa = a-1&set k = 1
@if%b%NEQ如果%k%== 1 set / ab = b-1&set k = 0
@if%c%NEQ 0如果%k%== 0 set / ac = c-1
@if%x%NEQ 0000 set x =%a %% b %% c %% d%&goto l

新的解决方案(根据基础注释修复)重288个字节。


我没有深入研究您的答案,但是我在第一段中努力遵循您的逻辑。您具体指的是哪个示例?而你从去例子12340224不是一个运动。这个想法是,只用两个手指,我一次握住最多可以握住三个连续的戒指。
Lui

我的意思是,如果您可以连续移动3个环,可以合理地认为您也可以移动第一个和第三个环,而不必移动第二个。还是应该更改代码?
2016年

你的假设是错误的;您应该更改代码。您是否看到上述评论中解释的逻辑?
2013年

代码固定。我检查了几种不同类型的组合,在我看来,它总是用更短的方法。
NOIZE

这似乎只向下计数,因此与大数的组合(例如18动作代表9999)所花费的时间比必要的时间更长
faubi

2

Haskell-310字节

import Data.Char
import Data.List
r=replicate
h=head
a x=map(:x)[map(`mod`10)$zipWith(+)(h x)((r n 0)++(r(4-j)q)++(r(j-n)0))|j<-[1..3],n<-[0..j],q<-[1,-1]]
x!y=h x==h y
x#[]=(nubBy(!)$x>>=a)#(filter(![(r 4 0)])x)
x#y=unlines.tail.reverse.map(intToDigit<$>)$h y
main=do x<-getLine;putStrLn$[[digitToInt<$>x]]#[]

通过对已经达到的每个组合应用每个可能的转弯,直到其中一个是正确的组合,来反复构建新的组合列表,以实现此目的。每次迭代都会从列表中删除重复项,以防止内存使用量成倍增长。

作为强力解决方案,这是非常低效的,可能需要几分钟才能运行。

我在Haskell方面经验不足,因此可能会做得更好。


似乎为您的方法奠定了坚实的基础。我没有Haskell的经验,也没有(我知道)任何编译/运行它的方法。一个快速的谷歌也没有给我我可以尝试的任何地方。您能提供一个链接让我尝试吗?谢谢。
2013年

@Lui可以使用Glasgow Haskell编译器进行编译,但是除了下载和使用之外,我不知道有什么方法可以运行它。
faubi
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.