パズルの本質は次のとおりです( bor1sを引用):
6人家族と盗賊の警官をいかだで川の反対側に運ぶ必要があります。 しかし、同時に、2人だけがいかだに乗せられます(説明:そのうちの1人は成人でなければなりません)。母親は、父親がいないまま、男の子、父親、女の子を打ちます。 盗賊(説明:警官がいない場合)は、単に全員を濡らします。
http://freeweb.siol.net/danej/riverIQGame.swfでオンラインでパズルを完成できます。
プロローグは通常、このような問題を解決するのに良い仕事をします。
息子 (son1)。
息子 (son2)。
娘 (daughter1)。
娘 (daughter2)。
大人 (父)。
大人 (母)。
大人 (警察)。
notsafe_ (犯罪者、 X ):- X \ = police 。
notsafe_ (mother、 Y ):- 息子 ( Y )。
notsafe_ (父、 Y ):- 娘 ( Y )。
notsafe ( X 、 Y ):- notsafe_ ( X 、 Y ); notsafe_ ( Y 、 X )。
safe ( X 、 Y ):- \ + notsafe ( X 、 Y )。
safebridge ([ X 、 Y ]) :-( 大人 ( X ); 大人 ( Y ))、 安全な ( X 、 Y ) 、! 。
safebridge ([ X ]):- 大人 ( X )。
すべて ([
son1、son2、father、
娘1、娘2、母、
犯罪者、警察
])。
allsafe ( L ):-
forall ( メンバー ( H 、 L )、
( 大人 ( H )
; 息子 ( H )、
( メンバー (母親、 L )
-> メンバー (父、 L )
; 本当
)
; 娘 ( H )、
( メンバー (父、 L )
-> メンバー (mother、 L )
; 本当
)
; H =犯罪者、 メンバー (警察、 L )
)) 、! 。
allsafe ([_])。
allsafe ([])。
allPairs ([ H | T ]、[ H 、 P2 ]):-
メンバー ( P2 、 T )。
allPairs ([_ | T ]、 P ):-
allPairs ( T 、 P )。
step_ ( state ( Left1 、left)、 state ( Left2 、right)):-
( allPairs ( Left1 、 OnBridge )
; メンバー ( A 、 Left1 )、
OnBridge = [ A ]
)、
safebridge ( OnBridge )、
減算 ( Left1 、 OnBridge 、 Left2 )、
allsafe ( Left2 )、
すべて ( すべて )、
減算 ( All 、 Left2 、 Right )、
allsafe ( 右 )。
ステップ ( state ( Left1 、left)、 state ( Left2 、right)):-
step_ ( state ( Left1 、left)、 state ( Left2 、right))。
ステップ ( state ( Left1 、right)、 state ( Left2 、left)):-
all ( All )、
減算 ( All 、 Left1 、 Right1 )、
step_ ( state ( Right1 、left)、 state ( Right2 、right))、
減算 ( All 、 Right2 、 Left2 )。
notequal ( 状態 ( L1 、 P1 )、 状態 ( L2 、 P2 )):-
\ + (
P1 = P2 、
ソート ( L1 、 L )、
ソート ( L2 、 L )
)
解決 ( Inp 、 Outp 、 PrevSteps 、[ ステップ | ステップ ]):-
ステップ = ステップ ( Inp 、 S1 )、
ステップ 、 forall ( メンバー ( ステップ ( State1 、_)、 PrevSteps )、 notequal ( State1 、 S1 ))、 %ループ防止
( S1 = Outp
-> ステップ = []
; solve ( S1 、 Outp 、[ Step | PrevSteps ]、 Steps )
)
解決する :-
all ( All )、
findall ( ステップ 、 解決 ( 状態 ( すべて 、左)、 状態 ([]、_)、[]、 ステップ )、 ソリューション )、
長さ ( Solutions 、 SolLength )、
format ( ' Found〜w solutions: 〜n ' 、[ SolLength ])、
forall ( メンバー ( Solution 、 Solutions )、
( 形式 ( '〜nSolution:〜n' )、
forall ( メンバー ( ステップ 、 ソリューション )、
printStep ( ステップ )
)
))。
printStep ( step ( state ( L1 、 Pos1 )、 state ( L2 、_))):-
( Pos1 =左
-> 減算 ( L1 、 L2 、 Moved )、
形式 ( '〜w->左:〜w〜n' 、[ 移動 、 L2 ])
; Pos1 =右
-> 減算 ( L2 、 L1 、 Moved )、
形式 ( '〜w <-左:〜w〜n' 、[ 移動 、 L2 ])
)
プログラムは、川を渡るための8つのオプションをすばやく見つけて表示します。
プログラムの動作を噛むことは大したことではありませんが、アルゴリズムは次のように簡単に説明できます。 システムの状態をフォーム状態(L、Pos)に設定します。ここで、Lは橋の左側の人のリスト、Posはtheの位置(左、右)です。
このプログラムは、システムの状態の可能な変更を記述する述語ステップ(S1、S2)を記述します。 問題を解決するために、述語解決があります。
solve(S1, S2) :-
step(S1, S), %
( S = S2 % ,
; solve(S, S2) % ,
).
プロローグの列挙された性質を使用して、この述部は、最終状態([]、_)状態(誰も残っていない)に達するまで(プログラムの冒頭に記載された制限で)ステップを可能にします。 ただし、すでに合格した状態になっていないことを述語にチェックする必要がありました。そうしないと、プログラムは明らかにサイクルをたどります。
Haskell、J、RubyのRSDNフォーラムのパズルソリューションをご覧ください 。 また、興味があれば、お気に入りのYPでソリューションを作成することをお勧めします。
追加。 川を越えるための別の問題(Zurgからの脱出)の解決については、 こちらをご覧ください 。 この記事では、Haskellが検索の問題を解決するのにも非常に便利であるという事実と、この分野の従来のPrologについて説明しています。 この問題の解決策(記事よりも少し複雑)をここのプロローグに置きました 。