14ペグのパズルを解く


8

前書き

一般的なパズルには、下の画像に示すように、ティー/ペグ用の15個の穴がある三角形のボードが含まれます。

ペグボードのサンプル画像

一番上の穴を除いて、ボード内のすべてのペグから始めて、パズルのポイントは、チェッカーのようにペグを互いに飛び越えて、正確に1つのペグを残すことです。唯一有効な移動は、1つのペグを隣接するペグを越えて任意の方向に空の穴にジャンプすることです。ジャンプしたペグは、ボードから削除されます。有効な手が残っていない場合、プレイは終了します。

スペック

あなたの仕事は、ペグパズルの完全なソリューションを見つけることができるプログラムを書くことです。考えられる解決策は複数あるので、プログラムは1つだけ印刷する必要があります。

  • プログラムは入力を受け取りません。外部ソースからのデータの読み取りは許可されていません。
  • この形式を使用して、残りの1ペグの結果が得られる13のムーブのリストを印刷します。

    Peg 1 jumps Peg 3 to Hole 6.

  • 穴/ペグには上から下、左から右に番号が付けられているため、上部のペグ/穴は1で、右下が15になるまで番号が付けられます。
  • プログラム実行時にソリューション見つける必要があります。プログラムで解決する以外の方法でソリューションを直接印刷すると、自動的に失格になります。
  • ボーナス:複数のユニークなソリューションを出力できる場合は、10ボーナスポイントを受け取ります(空白行で区切って印刷できます)。
  • ボーナス:数値15がソースコードのどこにも表示されない場合、5ボーナスポイントを受け取ります。

得点

これはコードゴルフなので、正しい答えを出力する(バイト数による)最短のソリューションが勝者となります。総バイト数からボーナスポイントが差し引かれます。プログラムの実行のサンプル出力とideone、可能であればプログラムの実行を示すリンクまたは同様のサイトへのリンクを提供してください。


これにはコードゴルフタグがあるので、文字数であるとしか仮定できない客観的勝利基準とどのようにボーナスポイントを混ぜ合わせるのですか?
JB

「ボーナスポイントは合計バイトカウントから差し引かれます。」という説明を追加しました。それは理にかなっていますか?
mellamokb 2012

2番目のボーナスは簡単に入手できません。 15=0xff=(1<4)-1=~(-1<<4)=...
ラチェットフリーク

3
あなたの表現のいくつかは15それ自身よりも長い> = 5文字です;)
mellamokb

回答:


8

ルビー、スコア240 238 234 = 249-10-5

s=->t,r,c{c>0?(t+t.reverse).gsub(/[A-O]{2}[a-o]/){|j|s[t.tr(j,j.swapcase),r+"Peg #{j[0].ord-64} jumps Peg #{j[1].ord-64} to Hole #{j[2].ord-96}.\n",c-1]}:$><<r+"\n"}
s["aBD,BDG,DGK,CEH,EHL,FIM,aCF,CFJ,FJO,BEI,EIN,DHM,DEF,GHI,HIJ,KLM,LMN,MNO,","",13]

このパズルのすべての可能な解決策を出力する単純なルビの実装(私のコンピューターでは1分もかかりません)。出力の最初の行は次のとおりです。

Peg 6 jumps Peg 3 to Hole 1.
Peg 4 jumps Peg 5 to Hole 6.
Peg 1 jumps Peg 2 to Hole 4.
Peg 14 jumps Peg 9 to Hole 5.
Peg 7 jumps Peg 8 to Hole 9.
Peg 12 jumps Peg 13 to Hole 14.
Peg 10 jumps Peg 6 to Hole 3.
Peg 4 jumps Peg 5 to Hole 6.
Peg 3 jumps Peg 6 to Hole 10.
Peg 15 jumps Peg 10 to Hole 6.
Peg 6 jumps Peg 9 to Hole 13.
Peg 14 jumps Peg 13 to Hole 12.
Peg 11 jumps Peg 12 to Hole 13.

Peg 6 jumps Peg 3 to Hole 1.
Peg 4 jumps Peg 5 to Hole 6.
Peg 1 jumps Peg 2 to Hole 4.
Peg 14 jumps Peg 9 to Hole 5.
Peg 7 jumps Peg 8 to Hole 9.
...

そして、オンラインの例はここにあります


トータルソリューションがいくつあるのか知りたいです。
mellamokb 2012

@mellamokbそれは29760の解決策があると言います。
ハワード

4
29760ソリューション?私が最初にこのゲームを知ったとき、それは見つけるために、永遠に連れて行ってくれたものを
PhiNotPi 2012

2
それは奇妙です。2 ^ 14(16384)のボード状態があり、それらのすべてに到達できるとは限りません。州よりも少ない解決策があったに違いない。
kaoD

2
@kaoD:ソリューションは実際には13の動きのシーケンス(元のボード状態からの13の連続した状態)であり、技術的には(2 ^ 15)^ 13の固有の可能性があり、非常に大多数はルールに基づいて正しくありません。(ボードは穴から始まるので、握りは無関係であるから)のいずれかで充填または空にすることができた15の穴があるので、2 ^ 15(32768)の可能なボードの状態が実際にもある
mellamokb

3

Python、324文字、スコア= 319

f=0xf
x=0x12413624725935836a45647b48d58c59e69d6af78989abcdcdedef
Z=[(x>>12*i&f,x>>12*i+4&f,x>>12*i+8&f)for i in range(18)]
M=[[65532,'']]
for i in' '*13:
 Q=[]
 for p,m in M:
  for a,b,c in[x[::-1]for x in Z]+Z:
   if p>>a&p>>b&~p>>c&1:Q+=[[p^2**a^2**b^2**c,m+"Peg %d jumps Peg %d to Hole %d.\n"%(a,b,c)]]
 M=Q
print M[0][1]

ペグの状態はビットマスクとして保持されます。 Mペグ状態のリストとその状態に到達するための指示が含まれています。

すべてのソリューションを印刷することもできます(29760あります)が、10文字以上のコストがかかります。

実行に約90秒かかるため、ideoneに投稿することはできません。

出力:

Peg 6 jumps Peg 3 to Hole 1.
Peg 4 jumps Peg 5 to Hole 6.
Peg 1 jumps Peg 2 to Hole 4.
Peg 14 jumps Peg 9 to Hole 5.
Peg 12 jumps Peg 13 to Hole 14.
Peg 7 jumps Peg 8 to Hole 9.
Peg 10 jumps Peg 6 to Hole 3.
Peg 4 jumps Peg 5 to Hole 6.
Peg 3 jumps Peg 6 to Hole 10.
Peg 15 jumps Peg 10 to Hole 6.
Peg 6 jumps Peg 9 to Hole 13.
Peg 14 jumps Peg 13 to Hole 12.
Peg 11 jumps Peg 12 to Hole 13.

10ポイントのボーナスを受け取るには、最低2つのソリューションを印刷する必要があります。
mellamokb 2012

3

C、386文字、スコア= 371

int f[37],o[36],t[36],r[14],i[14],m=1,s=~3,j=18;main(){while(j--)o[j]=o[18+j]=(f[j]=t[18+j]="AABBCCDDDEEFFGHKLM"[j]-64)+(t[j]=f[18+j]="DFGIHJKMFLNMOIJMNO"[j]-64)>>1;while(m)if(!f[++j])s=r[--m],j=i[m];else if(s>>f[j]&s>>o[j]&~s>>t[j]&1)if(r[m]=s,s^=1<<f[j]|1<<o[j]|1<<t[i[m]=j],j=-1,++m>13)for(m=printf("\n");m<14;++m)printf("Peg %d jumps Peg %d to Hole %d.\n",f[i[m]],o[i[m]],t[i[m]]);}

1秒未満ですべての29760ソリューションを出力します。

このバージョンは、(とりわけ)コンパイラがprintf()の暗黙の宣言を許可することを前提としています。implicit-intを使用すると、さらに6文字を節約できますが、その機能は技術的にC99から削除されました。

また、2つの文字列の大文字を対応する制御文字に置き換えることで、さらに4バイトを節約できます。コンパイラーがそのような文字列を許可する必要がなく、すでに高密度のソースコードを完全に読みにくくするため、ここではそれをしませんでした。

わかりやすくするために、難読化されたサイズ最適化を行わない同じアルゴリズムを次に示します。

#include <stdio.h>
int f[37], o[36], t[36], r[14], i[14], m, j, s = ~3;
int main(void)
{
    for (j = 0 ; j < 18 ; ++j) {
        f[j] = t[18+j] = "AABBCCDDDEEFFGHKLM"[j] - 64;
        t[j] = f[18+j] = "DFGIHJKMFLNMOIJMNO"[j] - 64;
        o[j] = o[18+j] = (f[j] + t[j]) >> 1;
    }
    j = 0;
    for (m = 1 ; m ; ++j) {
        if (!f[j]) {
            --m;
            s = r[m];
            j = i[m];
        } else if ((s >> f[j]) & (s >> o[j]) & (~s >> t[j]) & 1) {
            r[m] = s;
            i[m] = j;
            s ^= (1 << f[j]) | (1 << o[j]) | (1 << t[j]);
            j = -1;
            ++m;
            if (m > 13) {
                printf("\n");
                for (m = 1 ; m < 14 ; ++m)
                    printf("Peg %d jumps Peg %d to Hole %d.\n",
                           f[i[m]], o[i[m]], t[i[m]]);
            }
        }
    }
    return 0;
}

f、o、およびtは、最初のループで初期化される正当なジャンプのリストです。rとiは、プログラムがすべての可能なゲームをバックトラックおよび探索するために使用する履歴を形成します。

これは改善できると確信しています!


交換初期化中一のchar省あります>>1では/2
Peter Taylor

>>の代わりに/を使用すると、追加の前後に括弧が必要になります。
ブレッドボックス、2012年

ああ、かっこをつけていないものとは違うので、括弧を読み違えます。
Peter Taylor
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.