(Rubik) Cep Küpünü çözün


16

Senin görevin

.. Görünüşe göre Brian Fantana'nın yapamadığı şeyi yapmak ve 2x2x2 Rubik Küpünü çözmek.

cep küp - çapa

Tasarım

- -   A B   - -   - -
- -   C D   - -   - -

E F   G H   I J   K L
M N   O P   Q R   S T

- -   U V   - -   - -
- -   W X   - -   - -

Ve stdin veya komut satırı (seçiminiz - lütfen cevabınızda belirtin) yoluyla size verilecektir:

ABCDEFGHIJKLMNOPQRSTUVWX

AD'nin U-yüzünü (yukarı), EFMN'nin L-yüzünü (solda), GHOP'un F-yüzünü (ön), IJQR'nin R-yüzünü (sağda), KLST'nin B-yüzü (arka) ve UX, D-yüzünü (aşağı) oluşturur.

Her bir rengi temsil eden altı benzersiz karakter olacaktır, ancak bunlar değişebilir, bu nedenle her renk için kullanılacak 6 ascii karakterinin herhangi bir kombinasyonuna hazırlanın.

Özellikler

  • Kodunuz yalnızca Sağ (R), Üst (U) ve Ön (F) yüzleri kullanarak bir çözüm çıkarmalı ve standart gösterimi kullanmalıdır: R, R ', R2, U, U', U2, F, F ', F2. Daha fazla bilgiyi burada bulabilirsiniz . RUF alt kümesine yönelik kısıtlama 2x2 küp için standarttır (İpucu: sol alt arka köşeyi çalışmak için sabit bir taban olarak kabul edin).
  • Kodunuz cep küpünün tüm olası permütasyonlarını çözebilmelidir.
  • Her çözümün tamamlanması 30 saniyeden az sürmelidir.
  • Her çözelti 30 hareketten az olmalıdır.
  • Her zaman 20 hamleden daha az cevap veren çözümler için% -20 bonus verilecektir (bunun için kapsamlı bir kontrol yapabilmem için lütfen cevabınıza ekleyin)
  • Her zaman en uygun çözümü sunan kod için -50% bonus verilecektir. - Yine, lütfen cevabınızda reklam verin
  • Çözümler aynı yüzde iki ardışık hareket içermemelidir, çünkü bunlar tek bir hareketle kolayca birleştirilebilir.
  • Çözümler isteğe bağlı olarak her hareket arasında tek bir boşluk ve yalnızca tek bir boşluk içerebilir .
  • Gerekirse bütün çözelti sekansı, bir çift parantez, tırnak işareti, kaşlı ayraç, köşeli ayraç veya şaryo içinde bulunabilir, ancak başka herhangi bir harici çıkışa izin verilmez.
  • Lütfen kodunuzun kısaca yorumlanmış bir sürümünü veya kodunuzun ayrıntılı bir açıklamasını sağlayın.
  • Harici dosyalar kullanılmaz. Buna internet, veri tabloları ve bu tür bir sorun için yapılmış kütüphaneler / paketler dahildir.
  • En kısa kod bayt sayısı kazanır.
  • Kazanan, 30 Temmuz 2014 Çarşamba günü seçildi.

20
2x2, 3x3 ve 4x4'ümüz var , ancak hala parlama şansım için 1x1 meydan okumasını bekliyorum. Mükemmel bir algoritmam var!
Kapı tokmağı

İşte K'de ~ en uygun (= en kısa) çözümü bile üreten ~ 500 karakterlik bir çözücü: speedsolving.com/forum/…
Jakube

Dijkstra kullanarak kaba kuvvet uygulamak için 30 saniye yeterli olmalıdır: sadece 3674160 pozisyonları vardır.
Peter Taylor

2
1. Çıktıda boşluk üzerinde herhangi bir kısıtlama olmadığını varsayalım 2. Nesnel olabilmek için, "isteğe bağlı" olarak bırakmak yerine 20 hareketin altındaki çözümler için bonus tanımlamanız gerekir.
Level River St

@steveverrill Düzeltti. Ayrıca boşluk belirtimi eklendi. Teşekkürler!
Kyle McCormick

Yanıtlar:


11

Python 2.7: 544 bayt -50% = 272 bayt **

import sys;o=''.join;r=range;a=sys.argv[1];a=o([(' ',x)[x in a[12]+a[19]+a[22]] for x in a]);v={a:''};w={' '*4+(a[12]*2+' '*4+a[19]*2)*2+a[22]*4:''}
m=lambda a,k:o([a[([0x55a5498531bb9ac58d10a98a4788e0,0xbdab49ca307b9ac2916a4a0e608c02,0xbd9109ca233beac5a92233a842b420][k]>>5*i)%32] for i in r(24)])
def z(d,h):
 t={}
 for s in d[0]:
  if s in d[1]:print d[h][s]+d[1-h][s];exit()
  n=[d[0][s],'']
  for k in r(3):
   for j in r(3):s=m(s,k);t[s]=n[h]+'RUF'[k]+" 2'"[(j,2-j)[h]]+n[1-h]
   s=m(s,k)
 d[0]=t;return d
while 1:v,w=z([v,w],0);w,v=z([w,v],1)

Stackexchange, sekmeleri birden çok boşlukla değiştirir. Çok teknik bu sürüm 549 bayt var. 6-10. Satırlardaki ilk iki boşluğu bir tablo ile değiştirin.

Programımın arkasındaki fikir: İlk fikrim ilk nefes aramasıydı. Ama bu çok uzun sürdü. Sert (11 hareket optimum) karıştırma için yaklaşık 2 dakika. Bu yüzden soruna her iki taraftan da yaklaşmaya karar verdim. İki set kullanıyorum. 1,2,3, ... mesafeli tüm durumları karıştırmaya ve set1'e kaydederim ve aynı zamanda 1,2,3, ... mesafeli tüm durumları çözülmüş haline getirir ve kaydederim set2. Bir durum her iki sette de ilk kez olduğunda çözümü bulduk.

Bunun için bilinmeyen çözülmüş küpün renklerine ihtiyacım var. 13, 20 ve 23 karakterleri sol, arka ve aşağı renkleri tanımlar. Ancak bu 3 renk küpü temsil etmek için yeterlidir. Diğer 3 rengi beyaz boşluklarla değiştiriyorum ve çözdüğüm durumu '____ll____bbll____dddd' olarak temsil edebilirim.

Oh, ve permütasyonları kısaltmak için /codegolf//a/34651/29577 adresinden bir fikir kullandım.

Ungolfed sürümü:

import sys

#define permutations for R,U,F
permutation = [[0,7,2,15,4,5,6,21,16,8,3,11,12,13,14,23,17,9,1,19,20,18,22,10],
            [2,0,3,1,6,7,8,9,10,11,4,5,12,13,14,15,16,17,18,19,20,21,22,23],
            [0,1,13,5,4,20,14,6,2,9,10,11,12,21,15,7,3,17,18,19,16,8,22,23]]

def applyMove(state, move):
    return ''.join([state[i] for i in permutation[move]])

scramble = sys.argv[1]
#remove up,front,rigth colors
scramble = ''.join([(' ', x)[x in scramble[12]+scramble[19]+scramble[22]] for x in scramble])
solved = ' '*4+scramble[12]*2+' '*4+scramble[19]*2+scramble[12]*2+' '*4+scramble[19]*2+scramble[22]*4

dict1 = {scramble: ''} #stores states with dist 0,1,2,... from the scramble
dict2 = {solved: ''} #stores states with dist 0,1,2,... from the solved state

moveName = 'RUF'
turnName = " 2'"

for i in range(6):
    tmp = {}
    for state in dict1:
        if state in dict2:
            #solution found
            print dict1[state] + dict2[state]
            exit()
        moveString = dict1[state]
        #do all 9 moves
        for move in range(3):
            for turn in range(3):
                state = applyMove(state, move)
                tmp[state] = moveString + moveName[move] + turnName[turn]
            state = applyMove(state, move)
    dict1 = tmp
    tmp = {}
    for state in dict2:
        if state in dict1:
            #solution found
            print dict1[state] + dict2[state]
            exit()
        moveString = dict2[state]
        #do all 9 moves
        for move in range(3):
            for turn in range(3):
                state = applyMove(state, move)
                tmp[state] = moveName[move] + turnName[2 - turn] + moveString
            state = applyMove(state, move)
    dict2 = tmp

Sonuçtan oldukça memnunum, çünkü Python için oldukça yeniyim. Bu benim ilk python programlarımızdan biri.

düzenleme: yarım yıl sonra: 427 -% 50 = 213.5

Python ve golf alanında biraz daha deneyimim var. Bu yüzden orijinal kodumu gözden geçirdim ve 100'den fazla karakter kaydedebilirim.

import sys;o=''.join;a=sys.argv[1];d=[{o((' ',x)[x in a[12]+a[19]+a[22]]for x in a):[]},{' '*4+(a[12]*2+' '*4+a[19]*2)*2+a[22]*4:[]}]
for h in[0,1]*6:
 for s,x in d[h].items():
  for y in range(12):
   d[h][s]=x+[y-[1,-1,1,3][h*y%4]];
   if s in d[1-h]:print o('RUF'[x/4]+" 2'"[x%4]for x in d[0][s]+d[1][s][::-1]);exit()
   s=o(s[ord(c)-97]for c in'acahabcdnpbfegefhugiovjgqkciljdeklflmmmnnvoopxphrqdjrrbsstttuuqsviwwwkxx'[y/4::3])

Temel olarak aynı yaklaşımı kullanıyorum. En büyük değişiklik, artık bir fonksiyon tanımlamam. Onun yerine

def z(d,h):
 for s in d[0]:
  if s in d[1]:...
while 1:v,w=z([v,w],0);w,v=z([w,v],1)

Yapabilirim

for h in[0,1]*6:
 for s in d[h]:
  if s in d[1-h]:...

Ayrıca hareket lamdasını biraz değiştirdim. İşlev çağrısı yalnızca bir kez göründüğünden, önce kısaltın ve sonra kodu doğrudan entegre edin.

Her durum için, hareketleri içeren bir dize yerine, hareketleri temsil etmek için 0 ile 11 arasında bir sayı listesi tutarım. Sayılar en sonunda dönüştürülür.

Ayrıca ı-döngüler iki Birleştirilen 'for k in r(3):for j in r(3):birine for y in r(12). Bu nedenle hareketleri de yapmak zorundayım U4, R4, F4. Tabii ki böyle bir hareket en kısa çözümde görünmüyor, bu yüzden " 2'"[x%4]çalışıyor. (Eğer x % 4 == 3aralık dışında istisna bir dizin olurdu)

Daha önce ikinci setteki girişi aradığım için biraz daha hızlı. 11 hareketli bir çözelti için yaklaşık 0.5 saniye.


2
En sevdiğim arama algoritmam (IDA * yanında) çift yönlü bfs kullanmak için seçildi. Zaman izin verirse, birkaç saat içinde iyimserlik için test edeceğim. Ayrıca, bulmacayı çözmek için gerçekten U / R / F renklerine ihtiyacınız olmadığını fark etmedim. Güzel yapılmış!
Kyle McCormick

Doğruluk ve iyimserlik için 20 test durumum için geçti.
Kyle McCormick

çok güzel .. 24 daha hızlı uygulamak için bana yardımcı oldu! js tek yönlü bfs
RE60K

aslında '____ll____bbll____dddd' '____ll____bbll____bbdddd' olmalıdır
RE60K

7

C, 366-50% optimum bonus = 183

char c[99],t[3][26]={"ZGONFZCPTEZBHUMZ","ZIQPHZRUGAZJWOCZ","ZACB@ZJHFDZKIGEZ"};r=20;f(int m,int n){int e,i,j;for(i=4;i--;){for(j=15;j--;)c[t[n][j+1]]=c[t[n][j]];c[m]="FRU"[n],c[m+1]="4'2 "[i],c[m+2]=0;for(e=0,j=68;j<76;j++) e+= (c[j]!=c[j+8]) + (c[j]!=c[j^1]);i&&e&&e<45-m*2&m<r?f(m+2,(n+1)%3),f(m+2,(n+2)%3):e||(puts(c),r=m);}}main(){scanf("%s",c+64);f(0,2),f(0,1),f(0,0);}

Özyineleme kullanarak, program 11 adede kadar derin bir ağaç ( http://en.wikipedia.org/wiki/Pocket_Cube ve aşağıda belirtilen sayfaya göre optimum çözümün maksimum uzunluğu ) ve bir çözüm bulduğunda yazdırır (en fazla 22 karakter uzunluğunda, işlev bağımsız değişkeni tarafından izlenir m.) Kullanılan sıra, U, U2, U 'ile başlayan tüm yolların R veya F ile başlayan herhangi bir yol aranmadan önce arandığı bir tür sözlük sırasıdır. Bu nedenle, öncelikle en uygun çözümü bulmak zorunda değildir.

Bir çözüm basıldığında, daha sonra yalnızca eşit veya daha kısa çözümlerin yazdırılmasını sağlayan reşit yapılır m. r=m-2Ekstra 2 karakter koymak, ancak bulunan her uzunluktan (en uygun olana kadar) yalnızca bir çözümün yazdırılmasını sağlar. SADECE en uygun çözümü göstermesini istiyorsanız, şimdiye kadar bulunan en iyi çözüm bir değişkene depolanmalı ve programın sonunda yazdırılan en uygun çözüm (bu yaklaşık 15 karaktere mal olacaktır).

giriş diziye c[]64'ten itibaren diziye okunur . Bu, taşınabilir tabloda alfabe karakterlerini kullanmak için gereklidir. Semboller @aracılığıyla Wçözümleri iş için testi yapmak için bir çift sayıya üzerinde başlatmak için gerekli olduğundan söz başına X yoluyla yerine A'nın kullanılmaktadır. c['Z']geçici depolama için de kullanılır, çünkü 4 kat rotasyon gerçekleştirmek için toplam 5 atamaya ihtiyaç vardır. İlk bölümü c[]kullanılmadığından, (tüm C dizeleri gibi sıfır bayt ile sonlandırılmış) çözümü saklamak mümkündür.

for(i..)tarafından belirtilen yüzün 4 çeyrek turluk bir dizisinden geçer n.

Birincisi for(j..), tabloya göre gerçek değiştirmeyi gerçekleştirir t[].

Küpün çözülüp çözülmediğini test etmek için sadece dört yan yüzü kontrol etmek gerekir. URF ve DFR parçaları U ve D etiketleri çıkarıldığında bile ayırt edilebilir, çünkü bir parça XRF'yi saat yönünde okurken diğer XFR'yi okur. İki parça birbiriyle değiştirilirse, U aşağı yüzünde ve tam tersi, F rengi sağ yüzde ve tam tersi olarak görünecektir.

İkincisi for(j..), dört yan yüzdeki uyumsuzlukların sayısını sayar. Örneğin ön yüz için G & O, H & P ve G & H'yi (iki kez) karşılaştırır. e== 0 ise, küp çözülür. Eğer e<9 veya e<13, gelecek bir hareket veya sırasıyla 2 hamlede küpü çözmek mümkün olabilir. Aksi takdirde, bu sayıda hamlede küpü çözmek kesinlikle mümkün değildir. Zaman kazanmak için, bu sezgisel tarama ağacını budamak ve 10 veya 11 derinlikteki dalların çoğunda zamanın boşa gitmesini önlemek için kullanılır . Formül olarak ifade edilir, bu olur e<45-m*2.

Açık Kod

char c[99],t[3][26]={"ZGONFZCPTEZBHUMZ","ZIQPHZRUGAZJWOCZ","ZACB@ZJHFDZKIGEZ"};
r=20;                                                       //All moves are output as 2 characters. The index of the last move of the longest solution (11 moves) shall be 20.

f(int m,int n){                                             //perform a cycle through four 1/4 turns of the face specified in n. The index of the move reported in the solution is m.
  int e,i,j;                                                //e is for counting mismatches. i loops through the four 1/4 turns. j performs other functions.
  for(i=4;i--;){

    for(j=15;j--;)c[t[n][j+1]]=c[t[n][j]];                  //A 1/4 turn is performed as three 4-sticker rotations of the type z=a;a=b;b=c;c=d;d=z using the data in the movetable t[][]

    c[m]="FRU"[n],c[m+1]="4'2 "[i],c[m+2]=0;                //Write to the output in c[] the face to be turned and the number of 1/4 turns. Terminate with a zero byte to overwrite any longer solution that may have been found before. 

    for(e=0,j=68;j<76;j++)e+=(c[j]!=c[j+8])+(c[j]!=c[j^1]); //Compare each sticker of the top row of the side faces (64+4 through 64+11) with the stickers below and beside it. Count the number of mismatches.

    i && e && e<45-m*2 & m<r?                               //if the number of 1/4turns is not 4 AND the cube is not solved AND the heuristic (as described in the text) is good AND a shorter solution has not already been found,
      f(m+2,(n+1)%3), f(m+2,(n+2)%3):                       //deepen the search to another faceturn of the other two faces. 
      e||(puts(c),r=m);                                     //otherwise, if a solution has been found, print the solution and reduce the value of r to the new max solution length.
  } 
}

main(){
  scanf("%s",c+64);                                         //scan in the current cube state to c[] at index 64.
  f(0,2),f(0,1),f(0,0);                                     //call f() three times to search for solutions beginning with U R and F.
}

Verim

Program http://www.jaapsch.net/puzzles/cube2.htm adresinde 1-13 arası desenlerle test edilmiştir.

Aşağıdaki sonuçlar, TÜM optimal çözümleri bulmak için makinemdeki zamanlamayı verir (meraklı olanlar için). Ayrıca, daha karmaşık pozisyonlar için, yukarıda belirtilen 2 baytlık modifikasyon için zamanlama verilir, bu da sadece tek bir optimum çözüm bulur. Bu zamanlamalar için hem ilk çözümü bulması hem de programın sonlandırılması için verilir. Verilen çözümler (genellikle bağlantılı sayfadaki jeneratörleri ters çevirerek elde edilen çözümlerden farklıdır) bir çevrimiçi küp simülatörü ile doğrulanmıştır.

U 4 (1 move) horizontal flags (not mirror symmetric)
1 solution 1 sec

U2 (1 move) 4 horizontal flags (mirror symmetric)
1 solution 1 sec

F2 R2 F2 (3 moves) 4 vertical flags  
UUUULRBFRLFBLRBFRLFBDDDD 2 solutions 1 sec

U2 F2 R2 U2 (4 moves) Supertwist; 6 flags
DDUURRBFRRFBLLBFLLFBUUDD 3 solutions 1 sec

U F2 U2 R2 U (5 moves) 4 vertical flags, 2 checkerboards
UDDULBRFRFLBLBRFRFLBUDDU 2 solutions 1 sec

R2 F2 R2 U2 (4 moves) 4 checkerboards
UUUURLFBLRBFLRBFRLFBDDDD 4 solutions 1 sec

R U2 R' F2 R U' R2 U F2 U' (10 moves) Cube in cube
FFFUDDRFRULLLDRRUULBBBDB 18 solutions 26 sec; 1 solution U F2U'R2U R'F2R U2R' 1,13 sec 

R F U' R2 U F' R U F2 R2 (10 moves) Cube in cube 2
DDDUFFLFRBRRLFLLBBRBUUDU 8 solutions 28 sec; 1 solution R F U'R2U F'R U F2R2 12,21 sec 

U R F2 U R F2 R U F' R (10 moves)3-Cycle
UFFULDRFRULBLLFRURBBDBDD 45 solutions 26 sec; 1 solution U R'F U'F'R'F2U R F2 8,14 sec 

U R U' R2 U' R' F' U F2 R F' (11 moves) Column turn
UUUDLLFRFRBBLLFRFRBBDUDD many solutions 29 sec; 1 solution U R U'F U2R F'R'F'U2F' 3,27 sec 

F' U R' F2 U' R F U R2 U R' (11 moves)Corner swap
UUUURLFBLRBFLLFFRRBBDDDD 29 sec 24 solutions; 1 solution R U'F R U'R2U'F'R'U F2 12,28 sec

U F2 U' (3 moves) Zig-zag 
UDUDLLFRFFLBLBRRFRBBUUDD 1 solution 1 sec 

U' F2 U2 R2 U' F2 U2 R2 U' (9 moves) 2 Checkerboards, 4 L
DUUDLLFBRRBFLRFFRLBBUDDU 8 solutions 13 sec; 1 solution U F2U2R2U R2U2F2U' 1,5 sec

Kulağa iyi geliyor. Burada yakın bir rekabet görmek isterim.
Kyle McCormick

@KyleMcCormick Programım sonunda bitti ve iyi çalışıyor ancak beklemekten bıktınız ve diğer yanıtı kabul ettiğiniz görüyorum. 2 gün önce benim hatamdan çok daha iyi bir hata vardı (yüzler yanlış yöne dönüyor.) Ayrıca, sezgisel olarak 2 seviyeye uygulamak hızı geliştirdi. Yine de birkaç çözüm üretir, ancak son çözümün en iyi olacağı garanti edilir (metindeki olası çıktı değişiklikleri hakkında daha fazla.) Diğer gönderimlerden çok daha kısa. Çıktı formatında herhangi bir sorun yaşarsanız bana bildirin.
Level River St

Temel golflerle 358 bayt .
MD XF
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.