Khóa xe đạp kết hợp


46

Kịch bản

Sau một ngày dài làm việc trong văn phòng và duyệt stackexchange.com , cuối cùng tôi cũng bước ra khỏi cửa lúc 16:58, đã mệt mỏi với ngày. Bởi vì tôi vẫn chỉ là một thực tập sinh, phương thức vận chuyển hiện tại của tôi là trên xe đạp. Tôi đi đến Peugeot Reynold 501 đáng tin cậy của tôi , nhưng trước khi tôi có thể lái nó, tôi cần phải mở khóa nó. Khóa là khóa kết hợp bốn chữ số tiêu chuẩn (0-9), thông qua khung và bánh trước. Khi tôi cố gắng tỉnh táo, tôi kéo tay lên để vào trong sự kết hợp. Khóa xe đạp kết hợp

Các thách thức

Bởi vì ngón tay của tôi rất mệt mỏi, tôi muốn biến khóa thành sự kết hợp chính xác với ít cử động nhất. Một chuyển động được định nghĩa là xoay theo một vị trí (36 độ), ví dụ có một chuyển động từ 5737đến 5738. Tuy nhiên, tôi có thể nắm bắt tới ba vòng liên tiếp cùng một lúc và xoay chúng thành một vòng , chỉ được tính là một chuyển động duy nhất. Ví dụ, cũng chỉ có một chuyển động từ 5737đến 6837hoặc đến 5626. Di chuyển từ 5737đến 6838không phải là một chuyển động, vì các chữ số số 1,2 và 4 đã di chuyển theo cùng một hướng, nhưng độc lập với chữ số 3.

Do đó, đối với một kết hợp nhất định tôi có thể thấy trên khóa xe đạp (bất kỳ số nguyên 4 chữ số nào), số lượng chuyển động thấp nhất tôi có thể thực hiện để mở khóa là gì, và vâng, tôi có thể xoay theo bất kỳ lúc nào. Điều này có nghĩa là tôi có thể biến một số chữ số theo một hướng và các chữ số khác theo hướng khác: không phải tất cả các chuyển động của tôi sẽ theo chiều kim đồng hồ hoặc theo chiều kim đồng hồ cho mỗi lần mở khóa.

Bởi vì tôi lười biếng, mã mở khóa của tôi là 0000.

Đây là mã golf Tôi không thể bận tâm viết nhiều mã, vì vậy chương trình ngắn nhất về số byte sẽ thắng.

Đầu vào là từ stdin và mã của bạn sẽ xuất ra các kết hợp tôi có thể thấy ở mỗi bước sau mỗi chuyển động, bao gồm 0000 ở cuối. Mỗi đầu ra kết hợp phải được phân tách bằng dấu cách / dòng mới / dấu phẩy / dấu chấm / ký hiệu.

Ví dụ

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

Tôi đã thử đăng bài này trên http: // bicenses.stackexchange.com , nhưng họ không thích nó ...

Tuyên bố từ chối trách nhiệm: Đầu tiên chơi golf, vì vậy bất cứ điều gì bị hỏng / bất kỳ thông tin bị thiếu nào hãy cho tôi biết! Ngoài ra tôi đã làm tất cả các ví dụ bằng tay, vì vậy có thể có các giải pháp liên quan đến các chuyển động ít hơn!

EDIT: Đối với các câu trả lời có nhiều đường dẫn giải pháp với số lượng chuyển động bằng nhau (thực tế là tất cả chúng), không có giải pháp ưa thích nào.


18
Chào mừng đến với PPCG; thử thách đầu tiên rất tốt đẹp!
Doorknob

4
Điều này có vẻ vững chắc với tôi! Chào mừng đến với PPCG!
Mego

1
Thử thách đẹp. Tôi có thể hỏi những gì nên là đầu ra cho các trường hợp: 7478 và 3737?
ồn ào2

1
@ noisyass2 Cảm ơn; Câu trả lời của flawr đưa ra như sau: 7478 8588 9698 0708 0808 0908 0008 0009 0000 và 3737 2627 1517 0407 0307 0207 0107 0007 0008 0009 0000 Chỉ cần nhìn vào 3737, điều này có nghĩa: Chỉ nhìn vào 3 chữ số đầu tiên: ba chuyển động đầu tiên cùng một lúc, phải mất 3 chuyển động cho các chữ số 1 và 3, và sau đó 4 chuyển động khác cho chữ số 2, do đó tổng cộng là bảy chuyển động. Trong khi đó, nếu tôi di chuyển từng cá nhân, thì mỗi lần di chuyển 3 lần, như vậy là 9 lần di chuyển.
Lui

1
Tôi đang tự hỏi liệu tiêu đề "Khóa kết hợp" (hay "Khóa xe đạp") có thể thu hút nhiều người xem hơn không.
DavidC

Câu trả lời:


10

Matlab, 412 327 byte

Đã chơi gôn (Cảm ơn @AndrasDeak vì chơi golf 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)

Mã này sử dụng một số chương trình động để tìm "đường dẫn" ngắn nhất từ ​​số đã cho đến 0000chỉ sử dụng các bước có thể. Thách thức về cơ bản là một con đường ngắn nhất (thay vào đó bạn có thể coi các bước là một nhóm giao hoán.) Nhưng khó khăn đã đến với việc thực hiện hiệu quả . Các cấu trúc cơ bản là hai mảng 10000 phần tử, một mảng để lưu trữ số bước để đến chỉ mục đó, một cấu trúc khác để lưu trữ một con trỏ tới 'nút' trước đó trong biểu đồ của chúng tôi. Nó đồng thời tính toán 'đường dẫn' cho tất cả các số có thể khác.

Ví dụ:

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    

Mã đầy đủ (bao gồm một số ý kiến):

%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,''])

Đẹp! Bản thân tôi là một người dùng Matlab, tôi đã tự hỏi về việc giá vé sẽ tốt như thế nào.
Lui

1
Đối với đầu vào, 6444mã của bạn cung cấp 6444 7554 8664 9774 0884 0994 0004 0003 0002 0001 0000, trong khi tôi tìm thấy câu trả lời là 6444 6333 6222 6111 6000 7000 8000 9000 0000. Câu trả lời của tôi là 8 bước, của bạn là 10. Tôi không thể thấy vấn đề, và nó dường như ở đó trong cả phiên bản golf và không có người lái. Điều này được cố định trong chỉnh sửa mới nhất của bạn.
Lui

1
Tôi chỉ sửa một lỗi nhỏ trong mã. Trong shàng cuối cùng nên được [0,1,1,1]. Sau đó, bạn nhận được một giải pháp 8 bước quá! Tôi xin lỗi vì sự bất tiện này =)
flawr

1
@Lui Có một phòng chat matlab / octave , trong số những thứ khác, nó là một loại Cơ sở cho MATL languange có nguồn gốc từ Matlab.
flawr

1
cho 4826, tôi tìm thấy một giải pháp di chuyển 11: 4826 3716 2606 1506 0406 0306 0206 0106 0007 0008 0009 0000
ồn ào2

4

Mẻ - 288 byte

Ngay cả khi bạn nói rằng chúng phải liên tiếp (các vòng), tôi giả sử bằng logic (theo ví dụ) rằng tôi có thể bỏ qua vòng giữa, như từ 1234đến 0224.

đặt / px =
đặt a =% x: ~ 0,1% và đặt b =% x: ~ 1,1% và đặt c =% x: ~ 2,1% và đặt d =% x: ~ 3,1%
: tôi
@echo% x% & if% a% == 0 (nếu% d% NEQ 0 set / ad = d-1) khác set / aa = a-1
@if% b% NEQ 0 bộ / ab = b-1
@if% c% NEQ 0 bộ / ac = c-1
@if% x% NEQ 0000 đặt x =% a %% b %% c %% d% & goto l

Đây là giải pháp Batch của tôi: 236 byte.


Chỉnh sửa: giải pháp sửa chữa

đặt / px =
đặt a =% x: ~ 0,1% và đặt b =% x: ~ 1,1% và đặt c =% x: ~ 2,1% và đặt d =% x: ~ 3,1%
: tôi
@echo% x% & đặt k = 1 & if% a% == 0 (nếu% d% NEQ 0 đặt / ad = d-1 & đặt k = 0) khác đặt / aa = a-1 & đặt k = 1
@if% b% NEQ 0 nếu% k% == 1 bộ / ab = b-1 & đặt k = 0
@if% c% NEQ 0 nếu% k% == 0 bộ / ac = c-1
@if% x% NEQ 0000 đặt x =% a %% b %% c %% d% & goto l

Giải pháp mới (cố định theo các ý kiến ​​cơ bản) nặng 288 byte.


Tôi đã không nhìn vào câu trả lời của bạn rất sâu sắc, nhưng tôi đang đấu tranh để làm theo logic của bạn trong đoạn đầu tiên. Ví dụ cụ thể mà bạn đang đề cập đến? Và ví dụ của bạn về việc đi từ 1234đến không phải0224 là một phong trào. Ý tưởng là chỉ với hai ngón tay, tôi có thể nắm được tới ba vòng liên tiếp chỉ bằng một nắm.
Lui

Ý tôi là, nếu bạn có thể di chuyển 3 vòng liên tiếp, thật hợp lý khi nghĩ rằng bạn cũng có thể di chuyển vòng thứ nhất và thứ ba, tránh vòng thứ hai. Hay tôi nên thay đổi mã của mình?
noize

Giả định của bạn là sai; bạn nên thay đổi mã của bạn. Bạn có thấy logic như được giải thích trong nhận xét trên không?
Lui

Mã cố định. Tôi đã kiểm tra với một số loại kết hợp khác nhau và có vẻ như tôi luôn luôn đi theo con đường ngắn hơn.
noize

Điều này dường như chỉ đếm ngược xuống, do đó, mất nhiều thời gian hơn mức cần thiết cho các kết hợp có số cao (ví dụ: 18 di chuyển cho 9999)
faubi

2

Haskell - 310 byte

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]]#[]

Điều này hoạt động bằng cách liên tục xây dựng một danh sách kết hợp mới bằng cách áp dụng từng lượt có thể cho từng kết hợp đã đạt được cho đến khi một trong số chúng là kết hợp đúng. Các bản sao được xóa khỏi danh sách trên mỗi lần lặp để giữ cho mức sử dụng bộ nhớ tăng theo cấp số nhân.

Là một giải pháp vũ phu, điều này rất không hiệu quả và có thể mất vài phút để chạy.

Tôi không có nhiều kinh nghiệm với Haskell, vì vậy một số điều có lẽ có thể được thực hiện tốt hơn.


Có vẻ như một cơ sở vững chắc cho cách tiếp cận của bạn. Tôi chưa có kinh nghiệm với Haskell, cũng không (mà tôi biết) bất kỳ phương tiện biên dịch / chạy nó. Google nhanh chóng không cung cấp cho tôi bất cứ nơi nào tôi có thể thử nó. Bạn có thể cung cấp một liên kết cho phép tôi thử nó? Cảm ơn.
Lui

@Lui Nó có thể được biên dịch với Trình biên dịch Haskell của Glasgow , nhưng ngoài việc tải xuống và sử dụng mà tôi không biết cách nào để chạy nó.
faubi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.