プロローグのパズル「オオカミ、ヤギ、キャベツ」の日本語版

このパズルは、 この出版物のHabrahabrですでによく知られています。

パズルの本質は次のとおりです( 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 )。

notsafeXY ):- notsafe_XY ); notsafe_YX )。

safeXY ):- \ + notsafeXY )。

safebridge ([ XY ]) :-( 大人X ); 大人Y ))、 安全なXY、!
safebridge ([ X ]):- 大人X )。

すべて ([
son1、son2、father、
娘1、娘2、母、
犯罪者、警察
])。

allsafeL ):-
forallメンバーHL )、
大人H
; 息子H )、
メンバー (母親、 L
-> メンバー (父、 L
; 本当

; H )、
メンバー (父、 L
-> メンバー (mother、 L
; 本当

; H =犯罪者、 メンバー (警察、 L
)) 、!
allsafe ([_])。
allsafe ([])。

allPairs ([ H | T ]、[ HP2 ]):-
メンバーP2T )。

allPairs ([_ | T ]、 P ):-
allPairsTP )。

step_stateLeft1 、left)、 stateLeft2 、right)):-
allPairsLeft1OnBridge
; メンバーALeft1 )、
OnBridge = [ A ]
)、

safebridgeOnBridge )、

減算Left1OnBridgeLeft2 )、
allsafeLeft2 )、

すべてすべて )、
減算AllLeft2Right )、
allsafe )。

ステップstateLeft1 、left)、 stateLeft2 、right)):-
step_stateLeft1 、left)、 stateLeft2 、right))。

ステップstateLeft1 、right)、 stateLeft2 、left)):-
allAll )、
減算AllLeft1Right1 )、
step_stateRight1 、left)、 stateRight2 、right))、
減算AllRight2Left2 )。

notequal状態L1P1 )、 状態L2P2 )):-
\ +
P1 = P2
ソートL1L )、
ソートL2L

解決InpOutpPrevSteps 、[ ステップ | ステップ ]):-
ステップ = ステップInpS1 )、
ステップforallメンバーステップState1 、_)、 PrevSteps )、 notequalState1S1 ))、 %ループ防止

S1 = Outp
-> ステップ = []
; solveS1Outp 、[ Step | PrevSteps ]、 Steps


解決する :-
allAll )、
findallステップ解決状態すべて 、左)、 状態 ([]、_)、[]、 ステップ )、 ソリューション )、
長さSolutionsSolLength )、
format' Found〜w solutions: 〜n ' 、[ SolLength ])、
forallメンバーSolutionSolutions )、
形式'〜nSolution:〜n' )、
forallメンバーステップソリューション )、
printStepステップ

))。

printStepstepstateL1Pos1 )、 stateL2 、_))):-
Pos1 =
-> 減算L1L2Moved )、
形式'〜w->左:〜w〜n' 、[ 移動L2 ])
; Pos1 =
-> 減算L2L1Moved )、
形式'〜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について説明しています。 この問題の解決策(記事よりも少し複雑)をここのプロローグに置きました

Source: https://habr.com/ru/post/J51997/


All Articles