0

我试图在序言中解决爱因斯坦难题 - 五朋友版 - 但我卡住了。我似乎无法在我的代码中找到错误,或者如何解决它。目标是编写一个 Prolog 程序,正确识别他们每个人做了什么样的谜题、谜题的主题以及他们完成它需要多长时间 - 解决方案(人、种类、时间、主题)

我也收到此错误: uncaught exception: error(existence_error(procedure,members/3),clue1/0)

我觉得跟会员有关系?

知识库:

  1. 五个朋友分别是 Krystal、Angie,一个是做外太空拼图的,一个是用 30 分钟完成拼图的,一个是做单词搜索的。

  2. Ethan 要么在 90 分钟内完成字母拼图,要么在 20 分钟内完成冬季主题拼图。

  3. 德里克和那个做逻辑谜题的人,一个花了 45 分钟,而另一个人做了一个电影主题的谜题。男孩用最短和最长的时间完成他们的谜题。

  4. 尼克花了不到 40 分钟的时间来解决他的谜题,这不是视觉数独。安吉花了 40 多分钟来完成她的猫拼图。

  5. 那个花了 60 分钟做运动拼图的女孩没有做拼图。拼图是由一个男孩做的,比做逻辑拼图的男孩用时短,但比做单词搜索的男孩用时多。

  6. 视觉数独要么需要一个小时才能完成,要么是以外太空为主题的。德雷克没有做冬季主题的谜题(不是单词搜索。)

这是我的代码:

woman(krystal).
woman(angie).
man(dereck).
man(ethan).
man(nick).

kind(word).
kind(sudoku).
kind(letter).
kind(jigsaw).
kind(logic).

time(30).
time(90).
time(20).
time(45).
time(60).

theme(outerspace).
theme(winter).
theme(movies).
theme(sports).
theme(cat).

members([],_).
members([M|Ms],Xs) :- select(M,Xs,Ys),members(Ms,Ys).


clue1(Game) :- members([[krystal,_,_,_,_], [angie,_,_,_], [P,_,30,_], [P,word,_,_], [P,_,_,outerspace]], Game, man(P)).
clue2(Game) :- members([[krystal,_,_,_,_], [angie,_,_,_],[P,_,_,outerspace], [P,_,_,outerspace], [P,_,_,outerspace]], Game, man(P)).
clue3(Game) :- members([[krystal,_,_,_,_], [angie,_,_,_],[P,_,30,_], [P,_,30,_], [P,_,30,_]], Game, man(P)).
clue4(Game) :- members([[krystal,_,_,_,_], [angie,_,_,_],[P,_,_,word], [P,_,_,word], [P,_,_,word]], Game, man(P)).
clue5(Game) :- member([ethan, letter, 90,_], Game).
clue5(Game) :- member([ethan, _, 20, winter], Game).
clue6(Game) :- member([P, _, 20, _], Game, man(P)).
clue6(Game) :- member([P, _, 90, _], Game), man(P).
clue7(Game) :- member([dereck, _, 45, _], Game).
clue7(Game) :- member([dereck, _, _, movies], Game).
clue8(Game) :- member([_, logic, 45, _], Game).
clue8(Game) :- member([_, logic, _, sport], Game).
clue9(Game) :- member([nick, _, 30, _], Game).
clue9(Game) :- member([nick, _, 20, _], Game).
clue10(Game) :- member([P, sudoku, _, _], Game, \+nick(P)).
clue11(Game) :- member([angie, _, 45, cat], Game).
clue11(Game) :- member([angie, _, 60, cat], Game).
clue11(Game) :- member([angie, _, 90, cat], Game).
clue12(Game) :- member([P, Q, 60, sport], Game, girl(P), \+sport(Q)).

clue13(Game) :- member([P, jigsaw, Q, _], Game, man(P), \+time(20)).
clue13(Game) :- member([P, jigsaw, Q, _], Game, man(P), \+time(90)).
clue13(Game) :- member([P, jigsaw, 30, _], Game, man(P)), member([_, word, 20, _], Game), (member([_, logic, 40, _], Game); member([_, logic, 60, _], Game); member([_, logic, 90, _], Game)).
clue13(Game) :- member([P, jigsaw, 45, _], Game, man(P)), (member([_, word, 20, _], Game); member([_, word, 30, _], Game)), (member([_, logic, 60, _], Game); member([_, logic, 90, _], Game)).
clue13(Game) :- member([P, jigsaw, 60, _], Game, man(P)), (member([_, word, 20, _], Game); member([_, word, 30, _], Game); member([_, word, 46, _], Game)), member([_, logic, 90, _], Game).

clue14(Game) :- member([_, sudoku, 60, _], Game).
clue14(Game) :- member([_, sudoku, _, outerspace], Game).
clue15(Game) :- member([P, _, _, winter], Game, \+dereck(P)).
clue16(Game) :- member([_,word,_,P], Game, \+winter(P)).

clue17(Game, A,B,C,D) :- member([A,B,C,D], Game).

solution(A,B,C,D) :-
    Game = [A,B,C,D],
    clue1(Game),
    clue2(Game),
    clue3(Game),
    clue4(Game),
    clue5(Game),
    clue6(Game),
    clue7(Game),
    clue8(Game),
    clue9(Game),
    clue10(Game),
    clue11(Game),
    clue12(Game),
    clue13(Game),
    clue14(Game),
    clue15(Game),
    clue16(Game),
    clue17(Game, A,B,C,D),
    members([[_,sudoku,_,_], [_,logic,_,_],[_,letter,_,_],[_,jigsaw,_,_],[_,word,_,_]],Game),
    members([[krystal,_,_,_],[angie,_,_,_],[ethan,_,_,_],[dereck,_,_,_],[nick,_,_,_]],Game),
    members([[_,_,60,_],[_,_,45,_],[_,_,90,_],[_,_,30,_],[_,_,20,_]],Game),
    members([[_,_,_,sports],[_,_,_,cat],[_,_,_,outerspace],[_,_,_,movies],[_,_,_,winter]],Game),
    write(Game),
    true.

/*
1) One is named Krytal who didnt do the Outerspace puzzle, the Word search and didnt use 30 min 
    and One is named Angie who didnt do the Outerspace puzzle, the Word search and didnt use 30 min
2) One boy did the Outerspace puzzle
3) One boy used 30 min
4) One boy did the Word Search  
5) Ethan either finished the letter tiles in 90 minutes or did the winter themed puzzle in 20 minutes.
6) Boys took the shortest and longest times to finish their puzzles.
7) Dereck either took 45 minutes or did a movies themed puzzle.
8) The one who did the logic puzzle either took 45 minutes or did a movies themed puzzle.
9) Nick spent less than 40 minutes working on his puzzle
10) Nick did not the Visual Sudoku. 
11) Angie spent more than 40 minutes working on her Cat puzzle.
12) The girl who spent 60 minutes working on a sports puzzle did NOT do the Jigsaw. 
13) the jigsaw was done by a boy in less time than the one who did the Logic Puzzle but more time than the one who did the Word Search.
14) The Visual Sudoku either took an hour to complete or was Outerspace themed. 
15) Dereck did not do the winter themed puzzle 
16) The Word Search is not winter themed
*/
4

1 回答 1

4

这只是对最直接问题的回答,它不会为您提供完整的工作解决方案。不过,你的道路很好,请不要气馁!

此外,首先:将您的程序加载到 SWI-Prolog 会给出两个警告:

Warning: /home/isabelle/einstein.pl:49:
    Singleton variables: [Q]
Warning: /home/isabelle/einstein.pl:50:
    Singleton variables: [Q]

这意味着在这些位置的子句中,您有“单例”变量:在子句中只出现一次的变量。单例变量可能表示非常严重的逻辑错误,因此您不应忽略此类警告。Q也许前两个子句中的变量clue13应该以某种方式与时间2090

至于你的报错信息,我们来解包:

  • existence_error(procedure, ...)意味着您试图调用一个不存在的“过程”(更常见的是我们称它们为“谓词”)
  • members/3是不存在的程序
  • clue1/0是坏呼叫的位置。

作为参考,我的本地版本的 SWI-Prolog 报告了类似这样的相同错误,这对用户更友好一点:

?- solution(A, B, C, D).
ERROR: Undefined procedure: members/3
ERROR:   However, there are definitions for:
ERROR:         members/2
ERROR: 
ERROR: In:
ERROR:   [10] members([[krystal|...],...|...],[_3044,_3050|...],man(_3056))
ERROR:    [9] clue1([_3084,_3090|...]) at /home/isabelle/einstein.pl:29
ERROR:    [8] solution(_3116,_3118,_3120,_3122) at /home/isabelle/einstein.pl:64
ERROR:    [7] <user>

无论哪种方式,您都试图调用 from一个带有三个参数clue1的谓词,但不存在这样的定义。members让我们看看你的定义:

clue1(Game) :- members([[krystal,_,_,_,_], [angie,_,_,_], [P,_,30,_], [P,word,_,_], [P,_,_,outerspace]], Game, man(P)).

这个问题很难被发现,因为你学会了非常糟糕的代码格式化习惯。这不是你的错:太多的经典 Prolog 书籍坚持将太多的代码放在一行中,所以太多的 Prolog 程序员以这种方式编写代码。

你的意思更像是这样的:

clue1(Game) :-
    members([[krystal,_,_,_,_], [angie,_,_,_], [P,_,30,_],
             [P,word,_,_], [P,_,_,outerspace]],
            Game,
    man(P)).

你现在能看到吗?该members调用应在 之后关闭Game,并且man(P)不应作为此调用的参数。所以这应该是:

clue1(Game) :-
    members([[krystal,_,_,_,_], [angie,_,_,_], [P,_,30,_],
             [P,word,_,_], [P,_,_,outerspace]],
            Game),
    man(P).

我非常非常强烈地建议您不要在每行中编写多个目标,并且在目标内也不要打破长行。您将需要以类似的方式修复更多谓词。

在此之后,您的程序将不再存在存在错误,但会在members调用内部快速失败。您正在尝试调用members(<five-element list>, <four-element list>),但这不会成功。您在内部设置Game变量的方式solution看起来不对。尝试为您正在谈论的对象使用比Ato更具描述性的名称。D

于 2020-09-14T14:37:32.407 回答