go(a, d) など。ルートa、ルートb、ルートc、ルートdなどのルートも印刷したい
door(a, b).
door(b, c).
door(c, d).
door(b, e).
door(e, f).
door(e, g).
go(FromRoom, ToRoom):-
door(FromRoom,ToRoom).
go(FromRoom, ToRoom) :-
door(FromRoom, NextRoom),
go(NextRoom, ToRoom).
述語に IO とロジックを混在させないようにしてください。コードのテスト、デバッグ、推論が困難になり、バックトレースで非常に紛らわしい出力が生成されます。
ここでは、再帰中に道路をリストに保持できます。
例として、3 番目の引数を指定すると、次のようになります。
go(FromRoom, ToRoom, [FromRoom, ToRoom]) :-
door(FromRoom, ToRoom).
go(FromRoom, ToRoom, [FromRoom|Path]) :-
door(FromRoom, NextRoom),
go(NextRoom, ToRoom, Path).
クエリはパスを正しく返します。
?- go(a, g, Path).
Path = [a, b, e, g] ;
false.
必要に応じて、出力リストPath
を出力するときに出力リストをフォーマットできます。しかし、これは本当に簡単な問題です: 再帰中に出力する代わりにリストをフォーマットします。
良い方法は、単純に go/2 をルートも考慮した関係に変えることです。リストを記述する場合によくあることですが、DCG が適しています。
go(From, To) --> [From, To], { door(From, To) }.
go(From, To) --> [From],
{ door(From, Next) },
go(Next, To).
例:
?- phrase(go(a, d), Rooms).
Rooms = [a, b, c, d] ;
false.
そして write/1 に関して: トップレベルに応答の出力を処理させることが多いため、これが必要になることはめったにありません。format/2 は、多くの場合、必要に応じて出力をフォーマットするために write/1 よりも適しています。たとえば、次のようになります。
write('['), write(From), write(':'), write(To), write(']')
あなたは書ける:
format("[~w: ~w]", [From, To])
これには、次のように書き込み述語を使用する必要があります
go(FromRoom, ToRoom):-
door(FromRoom,ToRoom),
write('['), write(FromRoom), write(':'), write(ToRoom), write(']').
go(FromRoom, ToRoom) :-
door(FromRoom, NextRoom),
write('['), write(FromRoom), write(':'), write(NextRoom), write(']'),
go(NextRoom, ToRoom).
または、必要な形式のルートは
go(FromRoom, ToRoom):-
door(FromRoom,ToRoom),
write(FromRoom), write(' route '), write(ToRoom).
go(FromRoom, ToRoom) :-
door(FromRoom, NextRoom),
write(FromRoom), write(' route '),
go(NextRoom, ToRoom).