在Prolog嘲笑一个知更鸟花园

时间:2014-03-05 21:24:00

标签: prolog

所以我试图解决着名着作“To Mock A Mockingbird”中的第一个问题。 它被称为“花园”,定义为:

  

在某个花园中,每朵花都是红色,黄色或蓝色,并且所有三种颜色都有代表。一位统计学家曾经访问过这个花园,并观察到你挑选的三朵花,其中至少有一朵必然是红色的。第二位统计学家参观了花园,并观察到无论你选择了哪三朵花,至少有一朵花一定是黄色的。两个逻辑学生听说了这个并且引起了争论。第一个学生说:“因此,无论你挑选哪三朵花,至少有一朵必然是蓝色的,不是吗?”第二个学生说:“当然不是!”

     

哪个学生是对的,为什么?

因此,如果您考虑解决方案,解决方案非常简单,但解决方案需要什么?

(你可以在书中找到P.19的解决方案:http://www.scribd.com/doc/194863914/Raymond-M-Smullyan-To-Mock-a-Mockingbird-and-Other-Logic-Puzzles-Including-an-Amazing-Adventure-in-Combinatory-Logic-Knopf-1985

我认为Prolog可能是正确的语言选择,因为它与逻辑编程有关...... 虽然我已经设置了一些推论,但这应该给我解决方案,但我有点卡住了,因为程序没有正确完成。

到目前为止,我有什么建议,你有什么建议我错过了什么/做错了吗?

#!/usr/bin/env swipl -q -g main -s

subsets_contain_item(_, []).
subsets_contain_item(Item, [H|T]) :-
    member(Item, H), subsets_contain_item(Item, T).

subsets_length([], _).
subsets_length([H|T], Len) :-
    length(H, Len), subsets_length(T, Len).

all_are_members_and_only(Items, L) :-
    all_are_members(Items, L),
    only_members(Items, L).

all_are_members([], _).
all_are_members([M|T], L) :-
    member(M, L), all_are_members(T, L).

only_members(_, []).
only_members(Items, [H|T]) :-
    member(H, Items), only_members(Items, T).

main(_) :-
    all_are_members_and_only([red, yellow, blue], Solution),
    subsets_contain_item(red, L),
    subsets_contain_item(yellow, L),
    findall(X0, only_members(Solution, X0), L),
    length(X0, 3),
    write(Solution).

1 个答案:

答案 0 :(得分:1)

完全不同的方法 - 使用ECLiPSe CLP Prolog http://www.eclipseclp.org/进行约束逻辑编程(可以翻译成其他Prolog)。

:- lib(ic).
:- lib(ic_global).

model(N, Flowers) :-
    dim(Flowers, [N]),
    Flowers :: 1..3, % 1 - Red, 2 - Yellow, 3 - Blue

    %  all three colours were represented
    atleast(1, Flowers, 1), atleast(1, Flowers, 2), atleast(1, Flowers, 3), 

    ( multifor([I, J, K], 1, N), param(Flowers) do
        ( (I =:= J ; I =:= K; J =:= K) ->
            % skip for non-different flowers
            true
        ;
            % at least one of them was bound to be red
            Flowers[I] #= 1 or Flowers[J] #= 1 or Flowers[K] #= 1,
            %  at least one was bound to be yellow
            Flowers[I] #= 2 or Flowers[J] #= 2 or Flowers[K] #= 2
        )
    ).

在我们拥有我们的模型之后,我们可以要求我们为3花园提供所有可能的配置:

[eclipse]: findall(Flowers, (model(3, Flowers), labeling(Flowers)), Sols).

Flowers = Flowers
Sols = [[](1, 2, 3), [](1, 3, 2), [](2, 1, 3), [](2, 3, 1), [](3, 1, 2), [](3, 2, 1)]

所有找到的配置只是1,2,3的排列 - 一个红色,一个黄色和一个蓝色花。 (我们可以在我们的模型中添加所谓的对称破坏约束,只有[](1,2,3)没有排列。)

现在让我们尝试更大的花园尺寸:

[eclipse]: findall(Flowers, (model(4, Flowers), labeling(Flowers)), Sols).
Flowers = Flowers
Sols = []

[eclipse]: findall(Flowers, (model(5, Flowers), labeling(Flowers)), Sols).
Flowers = Flowers
Sols = []

对于尺寸4和5没有解决方案。我们可以尝试更大的数字 - 没有解决方案,所以我们可以高度自信地推测(尽管我们还没有证明)唯一的解决方案是大小的花园3有一朵红色,一朵黄色和一朵蓝​​色花朵。第一个学生是对的。