フィジカルの練習問題(難)

「Tokyo美人物語」にエビちゃんが出ていない合間を縫ってきしださんからの問題の続きを.

というかkoichikさん向け(^^

小船の問題。
  • 父・母・息子×2・娘×2・メイド・犬がいる
  • 2人乗りの船ひとつで全員向こう岸に渡りたい(犬も一人と数える)
  • 父は母がいないとき娘を食べる
  • 母は父がいないとき息子を食べる
  • 犬はメイドがいないとき家族全員を食べる
  • 船をこげるのは父・母・メイドだけ
  • みんなが渡れる手順を求めるプログラムを作成せよ。


まずは落ち穂拾いから.
金曜日の日記で妥当な状態を表す述語を作成したのですが,その最後の述語

invalid_state(S) :-
	member(dog, S),
	not(member(made, S)).

これだけだと犬が単独の状態が不正に扱われてしまいます.というか,不正にされてしまって困ったことになったのですが.
そんなわけで (どんなわけで?),

invalid_state([dog]) :-
	!, fail.
invalid_state(S) :-
	member(dog, S),
	not(member(made, S)).

とすることで犬だけの場合は妥当扱いにしました.心より恥じる.


さて,次は船での移動を表す述語を用意します.
こっちからあっちへ移動できるリスト (集合) を go/1 で,あっちからこっちへ移動できるリスト (集合) を back/1 で表します.
ちょっと悩んだのですが,パターンも少ないことだし単純に定義.

go([f, m]).
go([f, s1]).
go([f, s2]).
go([f, made]).
go([m, d1]).
go([m, d2]).
go([m, made]).
go([made, s1]).
go([made, s2]).
go([made, d1]).
go([made, d2]).
go([made, dog]).

back([f]).
back([m]).
back([made]).
back(L) :-
	go(L).

ちなみに f は父, m は母,s1・s2 は息子1・2,d1・d2は娘1・2,made はメイド,dog は犬.


これで残りは安全に移動可能な組み合わせの探索.
こっちからあっちへ移動可能な組み合わせを示す述語は forward,あっちからこっちへ移動可能な組み合わせを示す述語は backward とします.
で,いろいろ試行錯誤した結果はこうなりました.

forward(H, T, _, _, _, _, R) :-
	go(B),
	difference(H, B, H2),
	H2 = [],
	union(T, B, T2),
	equal_sets(T2, [f, m, s1, s2, d1, d2, made, dog]),
	R = [[H, '>>', B, '>>', T2]], !.
forward(H, T, FHA, FTA, BHA, BTA, R) :-
	go(B),
	subset(B, H),
	difference(H, B, H2),
	element_set(H2, FHA),
	remove_set(FHA, H2, FHA2),
	union(T, B, T2),
	element_set(T2, FTA),
	remove_set(FTA, T2, FTA2),
	backward(H2, T2, FHA2, FTA2, BHA, BTA, R2),
	append([H, '>>', B, '>>', T2], R2, R).

backward(H, T, FHA, FTA, BHA, BTA, R) :-
	back(B),
	subset(B, T),
	difference(T, B, T2),
	element_set(T2, BTA),
	remove_set(BTA, T2, BTA2),
	union(H, B, H2),
	element_set(H2, BHA),
	remove_set(BHA, H2, BHA2),
	forward(H2, T2, FHA, FTA, BHA2, BTA2, R2),
	append([H, '<<', B, '<<', T], R2, R).

引数の H はこっち側の状態を表すリスト,T はあっち側の状態を表すリスト,FHA はこっちからあっちへ移動した後に選択可能なこっち側の状態のリスト,FTA はこっちからあっちへ移動した後に選択可能なあっち側のリスト,BHA はあっちからこっちへ移動した後に選択可能なこっち側のリスト,BTA はあっちからこっちへ移動した後に選択可能なあっち側のリスト,R は移動した結果のリスト.
基本的な考え方は前回示したとおり.

H0 = S T0 = {}
H1 = H0 - B1 T1 = T0 + B1
H2 = H1 + B2 T2 = T1 - B2
H3 = H2 - B3 T3 = T2 + B3
・・・ ・・・
Hn = Hn-1 - Bn = {} Tn = Tn-1 + Bn = S

考え方は Prolog っぽいとはまでは言えなくても,まぁまぁいい感じだと思うのだけど,結果のコードが激しく手続き的なのはいかがなものか?


そして最初の一撃を加えるための述語.

start(R) :-
	valid_state_set(S),
	I = [f, m, s1, s2, d1, d2, made, dog],
	remove_set(S, I, S1),
	forward(I, [], S, S, S1, S, R).

こいつが H0 および T0 を与えます.


forward/7backward/7 で使っている element_set はある集合が集合の集合の要素 (であるところの集合) かテストする述語,remove_set/3 はある集合を集合の集合から削除する述語です.

element_set(X, [Y|_]) :-
	equal_sets(X, Y).
element_set(X, [_|Set]) :-
	element_set(X, Set).

remove_set([X|Set1], Set, Set1) :-
	equal_sets(X, Set), !.
remove_set([X|Set1], Set, [X|Set2]) :-
	remove_set(Set1, Set, Set2).

Java なら要素が Object だろうが Set だろうが同じ Set のオペレーションが使えるわけですが... なんか不便だなぁ.ちゃんとうまい手があるのだろうか?


その他,写経本から持ってきたもの.

element(X, [X|_]).
element(X, [_|Set]) :-
	element(X, Set).

difference([], _, []).
difference([X|Set1], Set2, Diff) :-
	element(X, Set2), !,
	difference(Set1, Set2, Diff).
difference([X|Set1], Set2, [X|Diff]) :-
	difference(Set1, Set2, Diff).

equal_sets(Set1, Set2) :-
	difference(Set1, Set2, []),
	difference(Set2, Set1, []).

intersect([], _, []).
intersect([X|Set1], Set2, [X|Int]) :-
	element(X, Set2), !,
	intersect(Set1, Set2, Int).
intersect([_|Set1], Set2, Int) :-
	intersect(Set1, Set2, Int).

union([], Set, Set).
union([X|Set1], Set2, Union) :-
	element(X, Set2), !,
	union(Set1, Set2, Union).
union([X|Set1], Set2, [X|Union]) :-
	union(Set1, Set2, Union).


こいつを実行した結果 (ちょっと整形してます).

5 ?- start(R).

R = [
	[[f, m, s1, s2, d1, d2, made, dog], >>, [made, dog], >>, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], <<, [made], <<, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], >>, [made, s1], >>, [dog, made, s1]], 
	[[f, m, s2, d1, d2, made, dog], <<, [made, dog], <<, [dog, made, s1]], 
	[[f, m, s2, d1, d2, made, dog], >>, [f, s2], >>, [s1, f, s2]], 
	[[m, d1, d2, made, dog, f], <<, [f], <<, [s1, f, s2]], 
	[[m, d1, d2, made, dog, f], >>, [f, m], >>, [s1, s2, f, m]], 
	[[d1, d2, made, dog, m], <<, [m], <<, [s1, s2, f, m]], 
	[[d1, d2, made, dog, m], >>, [made, dog], >>, [s1, s2, f, made, dog]], 
	[[d1, d2, m, f], <<, [f], <<, [s1, s2, f, made, dog]], 
	[[d1, d2, m, f], >>, [f, m], >>, [s1, s2, made, dog, f, m]], 
	[[d1, d2, m], <<, [m], <<, [s1, s2, made, dog, f, m]], 
	[[d1, d2, m], >>, [m, d1], >>, [s1, s2, made, dog, f, m, d1]], 
	[[d2, made, dog], <<, [made, dog], <<, [s1, s2, made, dog, f, m, d1]], 
	[[d2, made, dog], >>, [made, d2], >>, [s1, s2, f, m, d1, made, d2]], 
	[[dog, made], <<, [made], <<, [s1, s2, f, m, d1, made, d2]], 
	[[dog, made], >>, [made, dog], >>, [s1, s2, f, m, d1, d2, made, dog]]
] ;

R = [
	[[f, m, s1, s2, d1, d2, made, dog], >>, [made, dog], >>, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], <<, [made], <<, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], >>, [made, s1], >>, [dog, made, s1]], 
	[[f, m, s2, d1, d2, made, dog], <<, [made, dog], <<, [dog, made, s1]], 
	[[f, m, s2, d1, d2, made, dog], >>, [f, s2], >>, [s1, f, s2]], 
	[[m, d1, d2, made, dog, f], <<, [f], <<, [s1, f, s2]], 
	[[m, d1, d2, made, dog, f], >>, [f, m], >>, [s1, s2, f, m]], 
	[[d1, d2, made, dog, m], <<, [m], <<, [s1, s2, f, m]], 
	[[d1, d2, made, dog, m], >>, [made, dog], >>, [s1, s2, f, made, dog]], 
	[[d1, d2, m, f], <<, [f], <<, [s1, s2, f, made, dog]], 
	[[d1, d2, m, f], >>, [f, m], >>, [s1, s2, made, dog, f, m]], 
	[[d1, d2, m], <<, [m], <<, [s1, s2, made, dog, f, m]], 
	[[d1, d2, m], >>, [m, d2], >>, [s1, s2, made, dog, f, m, d2]], 
	[[d1, made, dog], <<, [made, dog], <<, [s1, s2, made, dog, f, m, d2]], 
	[[d1, made, dog], >>, [made, d1], >>, [s1, s2, f, m, d2, made, d1]], 
	[[dog, made], <<, [made], <<, [s1, s2, f, m, d2, made, d1]], 
	[[dog, made], >>, [made, dog], >>, [s1, s2, f, m, d2, d1, made, dog]]
] ;

R = [
	[[f, m, s1, s2, d1, d2, made, dog], >>, [made, dog], >>, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], <<, [made], <<, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], >>, [made, s2], >>, [dog, made, s2]], 
	[[f, m, s1, d1, d2, made, dog], <<, [made, dog], <<, [dog, made, s2]], 
	[[f, m, s1, d1, d2, made, dog], >>, [f, s1], >>, [s2, f, s1]], 
	[[m, d1, d2, made, dog, f], <<, [f], <<, [s2, f, s1]], 
	[[m, d1, d2, made, dog, f], >>, [f, m], >>, [s2, s1, f, m]], 
	[[d1, d2, made, dog, m], <<, [m], <<, [s2, s1, f, m]], 
	[[d1, d2, made, dog, m], >>, [made, dog], >>, [s2, s1, f, made, dog]], 
	[[d1, d2, m, f], <<, [f], <<, [s2, s1, f, made, dog]], 
	[[d1, d2, m, f], >>, [f, m], >>, [s2, s1, made, dog, f, m]], 
	[[d1, d2, m], <<, [m], <<, [s2, s1, made, dog, f, m]], 
	[[d1, d2, m], >>, [m, d1], >>, [s2, s1, made, dog, f, m, d1]], 
	[[d2, made, dog], <<, [made, dog], <<, [s2, s1, made, dog, f, m, d1]], 
	[[d2, made, dog], >>, [made, d2], >>, [s2, s1, f, m, d1, made, d2]], 
	[[dog, made], <<, [made], <<, [s2, s1, f, m, d1, made, d2]], 
	[[dog, made], >>, [made, dog], >>, [s2, s1, f, m, d1, d2, made, dog]]
] ;

R = [
	[[f, m, s1, s2, d1, d2, made, dog], >>, [made, dog], >>, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], <<, [made], <<, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], >>, [made, s2], >>, [dog, made, s2]], 
	[[f, m, s1, d1, d2, made, dog], <<, [made, dog], <<, [dog, made, s2]], 
	[[f, m, s1, d1, d2, made, dog], >>, [f, s1], >>, [s2, f, s1]], 
	[[m, d1, d2, made, dog, f], <<, [f], <<, [s2, f, s1]], 
	[[m, d1, d2, made, dog, f], >>, [f, m], >>, [s2, s1, f, m]], 
	[[d1, d2, made, dog, m], <<, [m], <<, [s2, s1, f, m]], 
	[[d1, d2, made, dog, m], >>, [made, dog], >>, [s2, s1, f, made, dog]], 
	[[d1, d2, m, f], <<, [f], <<, [s2, s1, f, made, dog]], 
	[[d1, d2, m, f], >>, [f, m], >>, [s2, s1, made, dog, f, m]], 
	[[d1, d2, m], <<, [m], <<, [s2, s1, made, dog, f, m]], 
	[[d1, d2, m], >>, [m, d2], >>, [s2, s1, made, dog, f, m, d2]], 
	[[d1, made, dog], <<, [made, dog], <<, [s2, s1, made, dog, f, m, d2]], 
	[[d1, made, dog], >>, [made, d1], >>, [s2, s1, f, m, d2, made, d1]], 
	[[dog, made], <<, [made], <<, [s2, s1, f, m, d2, made, d1]], 
	[[dog, made], >>, [made, dog], >>, [s2, s1, f, m, d2, d1, made, dog]]
] ;

R = [
	[[f, m, s1, s2, d1, d2, made, dog], >>, [made, dog], >>, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], <<, [made], <<, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], >>, [made, d1], >>, [dog, made, d1]], 
	[[f, m, s1, s2, d2, made, dog], <<, [made, dog], <<, [dog, made, d1]], 
	[[f, m, s1, s2, d2, made, dog], >>, [m, d2], >>, [d1, m, d2]], 
	[[f, s1, s2, made, dog, m], <<, [m], <<, [d1, m, d2]], 
	[[f, s1, s2, made, dog, m], >>, [f, m], >>, [d1, d2, f, m]], 
	[[s1, s2, made, dog, f], <<, [f], <<, [d1, d2, f, m]], 
	[[s1, s2, made, dog, f], >>, [made, dog], >>, [d1, d2, m, made, dog]], 
	[[s1, s2, f, m], <<, [m], <<, [d1, d2, m, made, dog]], 
	[[s1, s2, f, m], >>, [f, m], >>, [d1, d2, made, dog, f, m]], 
	[[s1, s2, f], <<, [f], <<, [d1, d2, made, dog, f, m]], 
	[[s1, s2, f], >>, [f, s1], >>, [d1, d2, made, dog, m, f, s1]], 
	[[s2, made, dog], <<, [made, dog], <<, [d1, d2, made, dog, m, f, s1]], 
	[[s2, made, dog], >>, [made, s2], >>, [d1, d2, m, f, s1, made, s2]], 
	[[dog, made], <<, [made], <<, [d1, d2, m, f, s1, made, s2]], 
	[[dog, made], >>, [made, dog], >>, [d1, d2, m, f, s1, s2, made, dog]]
] ;

R = [
	[[f, m, s1, s2, d1, d2, made, dog], >>, [made, dog], >>, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], <<, [made], <<, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], >>, [made, d1], >>, [dog, made, d1]], 
	[[f, m, s1, s2, d2, made, dog], <<, [made, dog], <<, [dog, made, d1]], 
	[[f, m, s1, s2, d2, made, dog], >>, [m, d2], >>, [d1, m, d2]], 
	[[f, s1, s2, made, dog, m], <<, [m], <<, [d1, m, d2]], 
	[[f, s1, s2, made, dog, m], >>, [f, m], >>, [d1, d2, f, m]], 
	[[s1, s2, made, dog, f], <<, [f], <<, [d1, d2, f, m]], 
	[[s1, s2, made, dog, f], >>, [made, dog], >>, [d1, d2, m, made, dog]], 
	[[s1, s2, f, m], <<, [m], <<, [d1, d2, m, made, dog]], 
	[[s1, s2, f, m], >>, [f, m], >>, [d1, d2, made, dog, f, m]], 
	[[s1, s2, f], <<, [f], <<, [d1, d2, made, dog, f, m]], 
	[[s1, s2, f], >>, [f, s2], >>, [d1, d2, made, dog, m, f, s2]], 
	[[s1, made, dog], <<, [made, dog], <<, [d1, d2, made, dog, m, f, s2]], 
	[[s1, made, dog], >>, [made, s1], >>, [d1, d2, m, f, s2, made, s1]], 
	[[dog, made], <<, [made], <<, [d1, d2, m, f, s2, made, s1]], 
	[[dog, made], >>, [made, dog], >>, [d1, d2, m, f, s2, s1, made, dog]]
] ;

R = [
	[[f, m, s1, s2, d1, d2, made, dog], >>, [made, dog], >>, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], <<, [made], <<, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], >>, [made, d2], >>, [dog, made, d2]], 
	[[f, m, s1, s2, d1, made, dog], <<, [made, dog], <<, [dog, made, d2]], 
	[[f, m, s1, s2, d1, made, dog], >>, [m, d1], >>, [d2, m, d1]], 
	[[f, s1, s2, made, dog, m], <<, [m], <<, [d2, m, d1]], 
	[[f, s1, s2, made, dog, m], >>, [f, m], >>, [d2, d1, f, m]], 
	[[s1, s2, made, dog, f], <<, [f], <<, [d2, d1, f, m]], 
	[[s1, s2, made, dog, f], >>, [made, dog], >>, [d2, d1, m, made, dog]], 
	[[s1, s2, f, m], <<, [m], <<, [d2, d1, m, made, dog]], 
	[[s1, s2, f, m], >>, [f, m], >>, [d2, d1, made, dog, f, m]], 
	[[s1, s2, f], <<, [f], <<, [d2, d1, made, dog, f, m]], 
	[[s1, s2, f], >>, [f, s1], >>, [d2, d1, made, dog, m, f, s1]], 
	[[s2, made, dog], <<, [made, dog], <<, [d2, d1, made, dog, m, f, s1]], 
	[[s2, made, dog], >>, [made, s2], >>, [d2, d1, m, f, s1, made, s2]], 
	[[dog, made], <<, [made], <<, [d2, d1, m, f, s1, made, s2]], 
	[[dog, made], >>, [made, dog], >>, [d2, d1, m, f, s1, s2, made, dog]]
] ;

R = [
	[[f, m, s1, s2, d1, d2, made, dog], >>, [made, dog], >>, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], <<, [made], <<, [made, dog]], 
	[[f, m, s1, s2, d1, d2, made], >>, [made, d2], >>, [dog, made, d2]], 
	[[f, m, s1, s2, d1, made, dog], <<, [made, dog], <<, [dog, made, d2]], 
	[[f, m, s1, s2, d1, made, dog], >>, [m, d1], >>, [d2, m, d1]], 
	[[f, s1, s2, made, dog, m], <<, [m], <<, [d2, m, d1]], 
	[[f, s1, s2, made, dog, m], >>, [f, m], >>, [d2, d1, f, m]], 
	[[s1, s2, made, dog, f], <<, [f], <<, [d2, d1, f, m]], 
	[[s1, s2, made, dog, f], >>, [made, dog], >>, [d2, d1, m, made, dog]], 
	[[s1, s2, f, m], <<, [m], <<, [d2, d1, m, made, dog]], 
	[[s1, s2, f, m], >>, [f, m], >>, [d2, d1, made, dog, f, m]], 
	[[s1, s2, f], <<, [f], <<, [d2, d1, made, dog, f, m]], 
	[[s1, s2, f], >>, [f, s2], >>, [d2, d1, made, dog, m, f, s2]], 
	[[s1, made, dog], <<, [made, dog], <<, [d2, d1, made, dog, m, f, s2]], 
	[[s1, made, dog], >>, [made, s1], >>, [d2, d1, m, f, s2, made, s1]], 
	[[dog, made], <<, [made], <<, [d2, d1, m, f, s2, made, s1]], 
	[[dog, made], >>, [made, dog], >>, [d2, d1, m, f, s2, s1, made, dog]]
] ;

No

8 パターン見つけてくれました.
どれも 17 手.もっと手数の多いパターンは見つからなかったよ.なんか間違ってるかなぁ?


これはこれで楽しかったのですが,写経と両立するのはちょっと大変なので,明日からはまた写経に戻ろうと思います.