Kombinasyon bisiklet kilidi


46

Senaryo

Ofis ve tarama içinde uzun bir günlük çalışma slogging sonra stackexchange.com , sonunda gün zaten yorgun, Saat 16:58 kapıdan çıkacak. Hala sadece stajyer olduğum için şu anki ulaşım tarzım bisikletle. Kendime güvendiğim Peugeot Reynolds 501’e gidiyorum, ama yelken açmadan önce kilidini açmam gerekiyor. Kilit, çerçeve ve ön tekerlek boyunca standart dört haneli şifreli bir kilittir (0-9). Uyanık kalmaya çalışırken, kombinasyona girmek için elimi yukarı çekiyorum. Kombinasyon bisiklet kilidi

Meydan okuma

Parmaklarım çok yorgun olduğundan, en az hareketle kilidi doğru kombinasyona çevirmek istiyorum. Bir hareket, bir konumla (36 derece) bir dönüş olarak tanımlanır, örneğin 5737ila arasında bir hareket vardır 5738. Bununla birlikte, aynı anda arka arkaya ç halkayı aynı anda kavrayabiliyorum ve onları tek bir hareket olarak sayılan bir olarak çevirebiliyorum. Örneğin , arasında veya arasında yalnızca bir hareket var . Taşıma için basamak sayısı 1,2 ve 4, bağımsız bir şekilde basamaklı sayı 3, aynı yönde hareket, ancak gibi, tek bir hareket değildir.57376837562657376838

Bu nedenle, belirli bir kombinasyon için, bisiklet kilidinde (4 basamaklı bir tamsayı) görebiliyorum, kilidi açmak için yapabileceğim en düşük hareket sayısı nedir ve evet, herhangi bir zamanda herhangi bir yönde dönebilirim. Bununla, bazı rakamları bir yönde, diğer rakamları da diğer yöne döndürebileceğimi kastediyorum: her hareket için tüm hareketlerim saat yönünde veya saat yönünde olmayacak.

Tembel olduğum için kilit açma kodum 0000.

Bu kod golf Çok fazla kod yazmaktan rahatsız olamam, bu yüzden bayt sayısındaki en kısa program kazanır.

Giriş, stdin'den gelir ve kodunuz, her hareketten sonra, 0000 de dahil olmak üzere, her adımda görebildiğim kombinasyonları çıkarmalıdır. Kombinasyon çıkışlarının her biri bir boşluk / newline / virgül / period / ve işaretiyle ayrılmalıdır.

Örnekler

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

Bunu http://bicycles.stackexchange.com adresinde göndermeyi denedim , ancak beğenmediler ...

Yasal Uyarı: İlk golf, bu yüzden herhangi bir kırık / herhangi bir eksik bilgi bana bildirin! Ayrıca tüm örnekleri el ile yaptım, bu yüzden daha az hareket içeren çözümler olabilir!

EDIT: Eşit sayıda harekete sahip (hemen hemen hepsi) çoklu çözüm yollarına sahip cevaplar için, tercih edilen bir çözüm yoktur.


18
PPCG'ye Hoşgeldiniz; çok güzel ilk meydan okuma!
Doorknob

4
Bu bana sağlam görünüyor! PPCG'ye Hoşgeldiniz!
Mego

1
Güzel meydan okuma. Davaların çıktısının ne olması gerektiğini sorabilir miyim: 7478 ve 3737?
noisyass2

1
@ noisyass2 Teşekkürler; flawr'ın cevabı aşağıdakileri verir: ilk üçü aynı anda, 1 ve 3 rakamları için 3 hareket, ardından 2 rakamı için 4 hareket, dolayısıyla toplam yedi hareket. Oysa eğer her birini ayrı ayrı hareket ettirirsem, her biri 3 hamle, yani 9 hamle alır.
Lui

1
"Şifreli Kilit" (veya "Bisiklet Kilidi") başlığının daha fazla izleyici çekip çekemeyeceğini merak ediyorum.
DavidC

Yanıtlar:


10

Matlab, 412 327 bayt

Golf (Golf için @AndrasDeak sayesinde 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)

Bu kodlar, verilen numaradan 0000sadece olası adımları kullanarak en kısa 'yolu' bulmak için bir miktar dinamik programlama kullanır . Zorluk, temelde en kısa yol prioblemidir (alternatif olarak, adımları komütatif bir grup olarak düşünebilirsiniz). Ancak zorluk, verimli bir uygulama ile ortaya çıkıyordu . Temel yapılar, biri bu dizine ulaşmak için atılacak adım sayısını depolamak için diğeri, grafiğimizdeki önceki 'düğüme' bir işaretçi koymak için kullanılan iki adet 10000 elemanlı dizidir. Eşzamanlı olarak, diğer tüm olası numaraların 'yollarını' hesaplar.

Örnekler:

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    

Tam Kod (bazı yorumlar dahil):

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

Güzel! Çoğunlukla Matlab kullanıcısı olmak ne kadar işe yarayacağını merak ediyordum.
Lui,

1
Giriş 6444kodunuz için 6444 7554 8664 9774 0884 0994 0004 0003 0002 0001 0000, oysa cevabı 6444 6333 6222 6111 6000 7000 8000 9000 0000 olarak buluyorum. Cevabım 8 adım, senin 10. sorun ve hem golf hem de unungolfed versiyonunda olduğu görülüyor. Bu, en son düzenlemenizde sabittir.
Lui

1
Koddaki küçük bir hatayı düzelttim. Gelen sson sırada olmalıdır [0,1,1,1]. O zaman siz de 8 adımlı bir çözüm elde edin!
Verdiğim

1
@Lui Bir matlab / oktav sohbet odası var, diğer şeylerin yanı sıra Matlab'dan türetilen golf sahası MATL için bir çeşit Taban.
kusur,

1
4826 için bir 11 hamle çözümü buldum: 4826 3716 2606 1506 0406 0306 0206 0106 0007 0008 0009 0000
noisyass2 13.01

4

Toplu İş - 288 bayt

Eğer onlar ardışık (yüzük) olmak zorunda Desen bile, ben itibaren, Ortadakini atlayabilirsiniz ki (örneğin aşağıdaki) mantığı ile farz 1234etmek 0224.

grubu / piksel =
a =% x: ~% 0,1 & set b =% x: ~ 1,1% & set c =% x: ~ 2,1% & set d =% x: ~% 3,1
: l
@ echo% x% & eğer% a% == 0 (eğer% d% NEQ 0 set / ad = d-1 ise) / aa = a-1 ayarladıysa
@% b% NEQ 0 kümesi / ab = b-1
@if% c% NEQ 0 kümesi / ac = c-1
@if% x% NEQ 0000, x =% a %% b %% c %% d% &% l

Bu benim Batch çözümüm: 236 bayt.


Düzenleme: düzeltilmiş çözüm

grubu / piksel =
a =% x: ~% 0,1 & set b =% x: ~ 1,1% & set c =% x: ~ 2,1% & set d =% x: ~% 3,1
: l
@ echo% x% & set k = 1 &% a% == 0 ise (% d% NEQ 0 ise set / ad = d-1 & set k = 0 ise) / aa = a-1 & set k = 1 ise
@if% b% NEQ 0 eğer% k% == 1 set / ab = b-1 & set k = 0
@if% c% NEQ 0 ise, eğer% k% == 0 set / ac = c-1
@if% x% NEQ 0000, x =% a %% b %% c %% d% &% l

Yeni çözüm (altta yatan yorumlara göre düzeltildi) 288 bayttır.


Cevabınıza derinlemesine bakmadım ama ilk paragrafta mantığınızı takip etmek için mücadele ediyorum. Özellikle hangi örneğe değiniyorsunuz? Ve giden senin örneği 1234için 0224ise değil bir hareketi. Buradaki fikir, yalnızca iki parmağınızı kullanarak, ardı ardına üç halkayı tek bir tutuşla kavrayabilmemdir.
Lui,

Yani, ardışık 3 halkayı hareket ettirebilirseniz, ikincisini de kaçınarak birinci ve üçüncü olanı da hareket ettirebileceğinizi düşünmek mantıklıdır. Yoksa kodumu değiştirmeli miyim?
saat

Senin varsayımın yanlış; kodunu değiştirmelisin. Yukarıdaki açıklamada açıklandığı gibi mantığı görüyor musunuz?
Lui,

Kod düzeltildi. Birkaç farklı kombinasyon türünü kontrol ettim ve bana göre her zaman daha kısa sürüyor gibi görünüyor.
1

Bu sadece aşağıya doğru sayılıyor gibi görünüyor, bu yüzden yüksek sayılar içeren kombinasyonlar için gerekenden daha uzun sürüyor (örneğin, 9999 için 18 hamle)
faubi

2

Haskell - 310 bayt

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

Bu, bir tanesi doğru kombinasyon olana kadar ulaşılan her kombinasyona olası her dönüşü uygulayarak art arda yeni bir kombinasyon listesi oluşturarak çalışır. Bellek kullanımını katlanarak büyümekten korumak için yinelemelerdeki listeden yinelenenler kaldırılıyor.

Bir kaba kuvvet çözümü olarak, bu çok verimsiz ve çalışması birkaç dakika sürebilir.

Haskell ile fazla bir tecrübem yok, bu yüzden bazı şeyler muhtemelen daha iyi yapılabilirdi.


Yaklaşımınız için sağlam bir temel gibi görünüyor. Haskell ile ya da (bildiğim kadarıyla) tecrübe edemiyorum. Hızlı bir google da deneyebileceğim bir yer vermiyor. Denememe izin veren bir link verebilir misin? Teşekkürler.
Lui,

@Lui Glasgow Haskell Derleyici ile derlenebilir , ancak indirme ve kullanma dışında çalıştırmanın herhangi bir yolunu bilmiyorum.
faubi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.