【问题标题】:Age comparsion for Zebra Riddle斑马之谜的年龄比较
【发布时间】:2021-06-18 02:14:46
【问题描述】:

我正在尝试通过 CLP 使用 ECLiPSe Prolog 解决类似于爱因斯坦谜题的逻辑谜题:

一个乐队有 6 位爵士乐手,没有一位年龄小于 70 岁。每个艺术家都写过不同的歌曲。

使用的乐器是:位置 1 的钢琴(乐队的左侧外侧),位置 2 的长笛(位置 1 的右侧),位置 3 的鼓(位置 2 的右侧) )、低音提琴在位置 4(在位置 3 的右侧)、萨克斯在位置 5(在位置 4 的右侧)和小号在位置 6(在乐队的右侧)。

艺术家的名字是:Andi、Cornelius、Fritz、Markus、Pete、Walter。
艺术家的姓氏是:Bramkamp、Franke、Karolewicz、Lueg、Schlüter、Weidemann。
艺术家年龄分别为:76、77、78、79、80、82。
歌曲的标题是:Im Bermudadreieck、Jupps-Eck-Blues、Krösken-Tanz、Legende vom Bergmann、Sally's Dog、Wanne-Eickel-Blues。

线索 1:弹钢琴的人至少比使用低音提琴的人大两岁。
线索 2:Lueg 的右边更远的一个位置是 WalterWalter 也是比 Sally's Dog 作曲家更靠左的位置。
线索 3:位置 5 的人比 Pete 小一岁,比 Im Bermudadreieck 的作曲家大一岁。
线索 4:比 77 岁 艺术家更靠右的一位是 Wanne-Eickel-Blues 的作曲家。
线索 5:比 Fritz 更靠右的一个位置是 Franke弗兰克至少比 Legende von Bergmann 的作曲家大 3 岁。这位作曲家比 Schlüter 年长。
线索 6:比 Cornelius 更靠右的一个位置是 80 岁的 WeidemannWeidemann 也比 Karolewicz 更靠左一个位置。他们都不是Krösken-Tanz的作曲家。
线索 7:SchlüterJupps-Eck-Blues 的作曲家,比 Markus 更靠右一位。 SchlüterAndi 更靠左一个位置。

我对 Prolog 完全陌生,感谢 http://www.hakank.org/bprolog/http://www.hakank.org/bprolog/a_round_of_golf.pl 我能够完成大部分代码。目前我坚持线索4,我不知道如何将77岁艺术家的位置(1..6)与年龄列表(76..80:82)结合起来。

go :-
        
    N = 6,
    
    Piano = 1,
    Flute = 2,
    Drums = 3,
    DoubleBass = 4,
    Saxophon = 5,
    Trumpet = 6,
    Instrument = [Piano, Flute, Drums, DoubleBass, Saxophon, Trumpet],
    InstrumentS = ['Piano', 'Flute', 'Drums', 'DoubleBass', 'Saxophon', 'Trumpet'],
    
    FirstName = [Andi, Cornelius, Fritz, Markus, Pete, Walter], 
    FirstNameS = ['Andi', 'Cornelius', 'Fritz', 'Markus', 'Pete', 'Walter'],
    FirstName :: 1..N,
    
    LastName = [Bramkamp, Franke, Karolewicz, Lueg, Schlueter, Weidemann],
    LastNameS = ['Bramkamp', 'Franke', 'Karolewicz', 'Lueg', 'Schlüter', 'Weidemann'],
    LastName :: 1..N,
    
    Song = [Bermudadreieck, Jupps, Kroesken, Legende, Sally, Wanne],
    SongS = ['Im Bermudadreieck', 'Jupps-Eck-Blues', 'Krösken-Tanz', 
    'Legende vom Bergmann', 'Sally`s Dog', 'Wanne-Eickel-Blues'],
    Song :: 1..N,
    
    length(Age ,N),
    Age :: [76, 77, 78, 79, 80, 82],
    Age = [Age_Piano, Age_Flute, Age_Drums, Age_DoubleBass, Age_Saxophon, Age_Trumpet],

    alldifferent(FirstName), 
    alldifferent(LastName),
    alldifferent(Age),
    alldifferent(Song),

    % Clue 1 ---
    % The man at the piano ist at least two years older than the double bass user.
    Age_Piano #>= Age_DoubleBass + 2, 
    
    % Clue 2 ---
    % One position further to Lueg's right is Walter. 
    % Walter is also one position further to the left than Sally's Dog composer.
    Walter #= Lueg + 1, 
    Walter #= Sally - 1, 
    
    % Clue 3 ---
    % The man on position 5 is one year younger than Pete 
    % and one year older than the composer of Im Bermudadreieck.

    element(Pete, Age, Age_Pete),
    element(Bermudadreieck, Age, Age_Bermudadreieck),
    
    Pete #\= 5, 
    Bermudadreieck #\= 5,
    Age_Saxophon #= Age_Pete - 1,
    Age_Saxophon #= Age_Bermudadreieck + 1,
    
    % Clue 4 ---
    % One position further to the right than the 77 year old artist is the composer of Wanne-Eickel-Blues.
    element(Wanne, Age, Age_Wanne),
    
    Age_Wanne #\= 77, 
    
    % Clue 5 ---
    % One position further to right than Fritz is Franke. 
    % Franke is at least 3 years older than the composer of Legende von Bergmann. 
    % This composer is older than Schlüter.
    
    element(Franke, Age, Age_Franke),
    element(Legende, Age, Age_Legende),
    element(Schlueter, Age, Age_Schlueter),
    
    Franke #= Fritz + 1,
    Franke #\= Legende,
    Franke #\= Schlueter,
    Age_Franke #>= Age_Legende + 3,
    Age_Legende #> Age_Schlueter,
    
    % Clue 6 ---
    % One position further to the right than Cornelius is the 80 years old Weidemann. 
    % Weidemann is also one position further to the left than Karolewicz. 
    % None of them is the composer of Krösken-Tanz.
    
    element(Weidemann, Age, Age_Weidemann),
    
    Age_Weidemann #= 80,
    Weidemann #= Cornelius + 1,
    Weidemann #= Karolewicz - 1,
    Weidemann #\= Kroesken,
    Cornelius #\= Kroesken,
    Karolewicz #\= Kroesken,
    
    % Clue 7 ---
    % Schlüter, composer of Jupps-Eck-Blues, is one position further to the right than Markus. 
    % Schlüter is one position further to the left than Andi.
    Schlueter #= Jupps,
    Schlueter #= Markus + 1,
    Schlueter #= Andi - 1,

    term_variables([FirstName, LastName, Age, Song], Vars),

    labeling(Vars).

【问题讨论】:

    标签: prolog zebra-puzzle eclipse-clp


    【解决方案1】:

    感谢http://www.hakank.org/eclipse/,实现了可行的解决方案并很好地展示了结果。诀窍是创建另一个列表AgePos,其中包含所有年龄和给定的位置范围[1..N]

    [...]
    AgePos = [AP76, AP77, AP78, AP79, AP80, AP82],
    AgePos :: 1..N,
    [...]
    

    然后我将这个列表链接到Age

    [...]
    nth1(AP76, Age, Age_AP76),
    Age_AP76 #= 76,
    [...]
    

    完整的代码,有一些调整

    :- lib(ic).
    :- lib(listut).
    
    go :-
        
    N = 6,
    Range = 1..N,
    
    Piano = 1,
    Flute = 2,
    Drums = 3,
    DoubleBass = 4,
    Saxophon = 5,
    Trumpet = 6,
    Instrument = [Piano, Flute, Drums, DoubleBass, Saxophon, Trumpet],
    InstrumentS = ['piano', 'flute', 'drums', 'double bass', 'saxophon', 'trumpet'],
    
    FirstName = [Andi, Cornelius, Fritz, Markus, Pete, Walter], 
    FirstNameS = ['Andi', 'Cornelius', 'Fritz', 'Markus', 'Pete', 'Walter'],
    FirstName :: Range,
    
    LastName = [Bramkamp, Franke, Karolewicz, Lueg, Schlueter, Weidemann],
    LastNameS = ['Bramkamp', 'Franke', 'Karolewicz', 'Lueg', 'Schlüter', 'Weidemann'],
    LastName :: Range,
    
    Song = [Bermudadreieck, Jupps, Kroesken, Legende, Sally, Wanne],
    SongS = ['Im Bermudadreieck', 'Jupps-Eck-Blues', 'Krösken-Tanz', 
    'Legende vom Bergmann', 'Sally`s Dog', 'Wanne-Eickel-Blues'],
    Song :: Range,
    
    AgePos = [AP76, AP77, AP78, AP79, AP80, AP82],
    AgePos :: Range,
    
    dim(Age, [N]),
    Age :: [76, 77, 78, 79, 80, 82],
    collection_to_list(Age, AgeList),
    
    alldifferent(FirstName), 
    alldifferent(LastName),
    alldifferent(Age),
    alldifferent(AgePos),
    alldifferent(Song),
    
    % Age Setting
    
    nth1(AP76, AgeList, Age_AP76),
    nth1(AP77, AgeList, Age_AP77),
    nth1(AP78, AgeList, Age_AP78),
    nth1(AP79, AgeList, Age_AP79),
    nth1(AP80, AgeList, Age_AP80),
    nth1(AP82, AgeList, Age_AP82),
    
    Age_AP76 #= 76,
    Age_AP77 #= 77,
    Age_AP78 #= 78,
    Age_AP79 #= 79,
    Age_AP80 #= 80,
    Age_AP82 #= 82,
    
    % Clue 1 ---
    % The man at the piano ist at least two years older than the double bass user.
    
    nth1(Piano, AgeList, Age_Piano),
    nth1(DoubleBass, AgeList, Age_DoubleBass),
    
    Age_Piano #>= Age_DoubleBass + 2, 
    
    % Clue 2 ---
    % One position further to Lueg's right is Walter. 
    % Walter is also one position further to the left than Sally's Dog composer.
    
    Walter #= Lueg + 1, 
    Walter #= Sally - 1, 
    
    % Clue 3 ---
    % The man on position 5 is one year younger than Pete 
    % and one year older than the composer of Im Bermudadreieck.
    
    nth1(Pete, AgeList, Age_Pete),
    nth1(Bermudadreieck, AgeList, Age_Bermudadreieck),
    
    Age_Saxophon #= Age_Pete - 1,
    Age_Saxophon #= Age_Bermudadreieck + 1,
    
    % Clue 4 ---
    % One position further to the right than the 77 year old artist is 
    % the composer of Wanne-Eickel-Blues.
    
    Wanne #= AP77 + 1,
    
    % Clue 5 ---
    % One position further to right than Fritz is Franke. 
    % Franke is at least 3 years older than the composer of Legende von Bergmann. 
    % This composer is older than Schlüter.
    
    nth1(Franke, AgeList, Age_Franke),
    nth1(Legende, AgeList, Age_Legende),
    nth1(Schlueter, AgeList, Age_Schlueter),
    
    Franke #= Fritz + 1,
    Franke #\= Legende,
    Franke #\= Schlueter,
    Age_Franke #>= Age_Legende + 3,
    Age_Legende #> Age_Schlueter,
    
    % Clue 6 ---
    % One position further to the right than Cornelius is the 80 years old Weidemann. 
    % Weidemann is also one position further to the left than Karolewicz. 
    % None of them is the composer of Krösken-Tanz.
    
    nth1(Weidemann, AgeList, Age_Weidemann),
    
    Age_Weidemann #= 80,
    Weidemann #= Cornelius + 1,
    Weidemann #= Karolewicz - 1,
    Weidemann #\= Kroesken,
    Cornelius #\= Kroesken,
    Karolewicz #\= Kroesken,
    
    % Clue 7 ---
    % Schlüter, composer of Jupps-Eck-Blues, is one position further to the right than Markus. 
    % Schlüter is one position further to the left than Andi.
    
    Schlueter #= Jupps,
    Schlueter #= Markus + 1,
    Schlueter #= Andi - 1,
    
    term_variables([FirstName, LastName, Age, Song], Vars),
    
    labeling(Vars),
    
    write('\nPosition\t\tFirst Name\t\tLast Name\t\tAge\t\tSong\n'),
    write('---------\t\t---------\t\t---------\t\t---------\t\t---------\n'),
    
    ( foreach(I, Instrument),
        foreach(IS, InstrumentS),
        param(FirstName, FirstNameS, LastName, LastNameS, AgeList, Song, SongS)
        do 
        
        printf('%w', [IS]),
        
        ( foreach(F, FirstName),
                foreach(FS, FirstNameS),
                param(I) do
                
                F == I ->
                printf('\t\t%w', [FS])
        ;
                true
        ),
        ( foreach(L, LastName),
                foreach(LS, LastNameS),
                param(I) do
                
                L == I ->
                printf('\t\t%w', [LS])
        ;
                true
        ),
        
        nth1(I, AgeList, A),
        printf('\t\t%w', [A]), 
        
        ( foreach(S, Song),
                foreach(SS, SongS),
                param(I) do
                
                S == I ->
                printf('\t\t%w\n', [SS])
        ;
                true
        )
    ).
    

    【讨论】:

    • 如果将所有出现的nth1 替换为element,您将看到显着的加速。原因是nth1 是不确定的,而element 使用约束传播。 nth1 的多次调用导致了相当大的搜索树。
    • @jschimpf 感谢您的建议,我会检查一下
    猜你喜欢
    • 2017-10-20
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    相关资源
    最近更新 更多