조합 자전거 자물쇠


46

시나리오

사무실에서 하루 종일 업무를 수행하고 stackexchange.com을 탐색 한 후 마침내 16:58에 문을 나섰습니다. 나는 여전히 인턴이기 때문에 현재 교통 수단은 자전거입니다. 나는 믿을 수있는 푸조 레이놀즈 501로 향 하지만, 항해를 시작하기 전에 잠금을 해제해야합니다. 잠금 장치는 프레임과 앞 바퀴를 통한 표준 4 자리 콤비네이션 잠금 장치 (0-9)입니다. 깨어 있으려고 노력할 때 손을 위로 들어 올려 조합에 들어갑니다. 조합 자전거 자물쇠

도전

손가락이 너무 피곤하기 때문에 자물쇠를 최소한의 움직임으로 올바른 조합으로 돌리고 싶습니다. 하나 개의 이동은 한 위치 (도 36)에 의한 회전으로 정의되며, 예를 들어 하나 개가 이동 5737하려면 5738. 그러나, 나는 동시에 세 개의 연속 된 링 을 잡고 하나의 회전으로 돌릴 수 있는데, 이것은 단일 움직임으로 만 간주됩니다. 예를 들어도있다 하나의 운동 에서 57376837나에가 5626. 에서 이동하는 5737것은 6838자리 번호 1, 2 및 4는 독립적 자리 숫자 (3)의 동일한 방향으로 이동하지만 것처럼, 하나 개의 이동 아니다.

따라서 주어진 조합에 대해 자전거 잠금 장치 (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 감사합니다; flawr의 답변은 다음을 제공합니다. 처음 세 개는 동시에 숫자 1과 3에 대해 3 개의 움직임을 취한 다음 숫자 2에 대해 또 다른 4 개의 움직임을 취하므로 총 7입니다. 각각을 개별적으로 움직이면 각각 3 번씩 움직이므로 9 번씩 움직입니다.
Lui

1
제목 "Combination Lock"(또는 "Bike Lock")이 더 많은 시청자를 끌어들일 지 궁금합니다.
DavidC

답변:


10

MATLAB, 412 327 바이트

Golfed (@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 사용자 자신이기 때문에 나는 그것이 얼마나 잘 지낼 지 궁금했습니다.
Lui

1
입력을 6444위해 코드에 6444 7554 8664 9774 0884 0994 0004 0003 0002 0001 0000을 제공하는 반면, 정답은 6444 6333 6222 6111 6000 7000 8000 9000 0000입니다. 내 대답은 8 단계이며 10 단계입니다. 문제가 있으며 골프 및 언 골프 버전 모두에있는 것으로 보입니다. 이것은 최신 편집에서 수정되었습니다.
Lui

1
방금 코드에서 작은 오류를 수정했습니다. 에서 s마지막 행되어야한다 [0,1,1,1]. 그러면 8 단계 솔루션도 얻게됩니다! 불편을 드려 죄송합니다 =)
flawr

1
@Lui matlab / octave 대화방이 있으며, 그 중에서도 Matlab에서 파생 된 골프 언어 랭귀지 MATL의 일종입니다.
flawr

1
4826의 경우 11 이동 솔루션을 찾았습니다. 4826 3716 2606 1506 0406 0306 0206 0106 0007 0008 0009 0000
noisyass2

4

배치-288 바이트

비록 그들이 연속적이어야한다고 말하더라도 (예 : 다음) 논리에서 (예 : 다음) 중간에서 건너 뛸 수 있다고 가정 1234합니다 0224.

set / px =
세트 a = % x : ~ 0,1 % & set b = % x : ~ 1,1 % & set c = % x : ~ 2,1 % & set d = % x : ~ 3,1 %
:엘
@echo % x % & if % a % == 0 (% d % NEQ 0 설정 / ad = d-1 인 경우) else set / aa = a-1
@if % b % NEQ 0 세트 / ab = b-1
@if % c % NEQ 0 set / ac = c-1
@if % x % NEQ 0000 세트 x = % a %% b %% c %% d % & goto l

이것은 내 배치 솔루션입니다 : 236 바이트.


편집 : 수정 된 솔루션

set / px =
세트 a = % x : ~ 0,1 % & set b = % x : ~ 1,1 % & set c = % x : ~ 2,1 % & set d = % x : ~ 3,1 %
:엘
@echo % x % & set k = 1 & if % a % == 0 (% d % NEQ 0 설정 / ad = d-1 & set k = 0 인 경우) else set / aa = a-1 & set k = 1
@if % b % NEQ % k % == 1 세트 / ab = b-1 & set k = 0 인 경우 0
@if % c % NEQ % k % == 0 set / ac = c-1 인 경우 0
@if % x % NEQ 0000 세트 x = % a %% b %% c %% d % & goto l

새로운 솔루션 (기본 주석에 따라 수정 됨)은 288 바이트입니다.


나는 당신의 대답을 깊이있게 보지 않았지만 첫 번째 단락에서 당신의 논리를 따르기 위해 고심하고 있습니다. 어떤 예를 구체적으로 언급하고 있습니까? 그리고에서가는 당신의 예 1234에는 0224것입니다 하지 한 운동. 아이디어는 두 손가락 만 사용하여 단일 그립으로 최대 3 개의 연속 링을 잡을 수 있다는 것입니다.
Lui

3 개의 연속 된 링을 움직일 수 있다면, 첫 번째와 세 번째 링도 이동할 수 있고 두 번째 링을 피할 수 있다고 생각하는 것이 합리적입니다. 아니면 코드를 변경해야합니까?
noize

당신의 가정이 잘못되었습니다. 코드를 변경해야합니다. 위의 의견에서 설명한 논리가 보입니까?
Lui

코드가 수정되었습니다. 몇 가지 다른 유형의 조합으로 확인했으며 항상 더 짧은 방법이 필요한 것처럼 보입니다.
noize

이 수치는 아래쪽으로 만 계산되므로 숫자가 많은 조합 (예 : 9999의 18 이동)에 필요한 것보다 시간이 오래 걸립니다
faubi

2

하스켈-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에 대해 경험하지 않았으며 그것을 컴파일 / 실행하는 수단도 없었습니다. 빠른 Google은 내가 시도 할 수있는 곳을 제공하지 않습니다. 당신이 그것을 시도 할 수있는 링크를 줄 수 있습니까? 감사.
Lui

@Lui Glasgow Haskell Compiler 로 컴파일 할 수 있지만 다운로드 및 사용과는 별도로 실행 방법을 모르겠습니다.
faubi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.