【问题标题】:Chain of dominos多米诺骨牌链
【发布时间】:2022-08-14 22:38:35
【问题描述】:

我正在学习 prolog 并在 exercism.io 上解决一些练习。我被困住了。我不想在互联网上搜索解决方案,因此我只会在练习部分提供一点帮助,因为我不明白我的错误在哪里,也不知道如何调试它。

练习是创建一个合法的chain of dominos。为此,我想编写一个简单的检查器。 [(1,2), (2,3), (3,4), (4,1)] 以及 [(1,1)][] 是合法的。 [(1,2)][(1,2), (3,1)][(1,2),(2,3)] 是非法的。我可以用我的is_chain 检查它:

is_loop([]).
is_loop([(X,X)]).
is_loop([(L,_)|Xs]) :-
    last(Xs, (_, L)).

is_chain_no_loop([]).
is_chain_no_loop([(_, _)]).
is_chain_no_loop([(_,L), (L,Y)|Xs]) :-
    is_chain_no_loop([(L,Y)|Xs]).

is_chain(X) :-
    is_loop(X), is_chain_no_loop(X).

我把它分成两部分。 is_loop 检查第一个和最后一个元素是否兼容,is_chain_no_loop 检查内链。

这是我的困惑开始的地方。

我可以问序言,什么样的列表是有效的: is_chain(R).

我得到以下信息:

R = []
R = [(_1370,_1370)]
R = [(_1370,_1372), (_1372,_1370)]
R = [(_1370,_1372), (_1372,_1384), (_1384,_1370)]
R = [(_1370,_1372), (_1372,_1384), (_1384,_1396), (_1396,_1370)]
R = [(_1370,_1372), (_1372,_1384), (_1384,_1396), (_1396,_1408), (_1408,_1370)]
R = [(_1370,_1372), (_1372,_1384), (_1384,_1396), (_1396,_1408), (_1408,_1420), (_552,_502)]

除了最后一个,我都明白了。我正在使用在线 SWI-Prolog SWISH。 为什么R的最后一张骨牌错了? _1420_552 不匹配,_502 与第一个 _1370 不匹配。

最重要的是,(因为我假设is_chain 工作正常,但显然不是)我开始实现chain,得到了Pile 的多米诺骨牌,我可以得到正确的Chain (如果有的话)。

chain([], Chain) :- is_chain(Chain).
chain([P, Pile], []) :- chain(Pile, [P]).

现在,这还不完整,但我也不明白这里的东西。 给定一个Chain,它是一个有效的链,如果它是is_chain。简单的。 如果我没有Chain,那么我只需从 Pile 中选择一个P 并从它开始。 除了chain([(1,1)], R)false。但是is_chain([(1,1)])true

考虑到一切,似乎有一些深刻的东西,我不了解序言或其执行(或它的搜索)。很抱歉,我无法将其分解为更简单的示例。

编辑:

经过更多思考,我意识到is_chain 可以通过“吃掉”多米诺骨牌的递归更简单地实现:

is_chain([]).
is_chain([(X,X)]).
is_chain([(X,Y), (Y, Z)|Ls]) :-
    is_chain([(X,Z)|Ls]).

但是,这会导致相同的解决方案...

  • 我也担心我的问题不值得 StackOverflow。这可能更适合 Reddit 或某些 IRC ......我仍然希望有人能将我推向正确的方向。
  • 我怀疑它正在工作,并且您的代码中没有错误。尝试is_chain(Dominos), Dominos = [First-_|_Rest] 并看到它在链变长时将First 保持在开始和结束位置。我不知道发生了什么;我的怀疑是来自is_loop 的开始变量和来自is_chain_no_loop([(_, _)]) 的结束变量使它们不同的变量只要它们统一,而在链内部,它们都来自is_chain([(X,Y), (Y, Z)|Ls]) :-,其中Y同一个变量在两个地方。不过,这主要是猜测,并不是一个可靠的答案。
  • 了解如何调试 Prolog,以便您可以看到正在发生的事情,而不是感到困惑和卡住 - swi-prolog.org/pldoc/man?section=debugoverview 及其子页面。
  • 避免使用“逗号列表”,它们很容易混淆 - swi-prolog.discourse.group/t/… - 可以使用例如d(X, Y) 是一个正常的术语。
  • 啊;在我的评论中,我的意思是is_chain(Dominos), Dominos = [(First,_)|_Rest],我在玩多米诺骨牌时已将代码更改为使用X-Y 而不是(X,Y),但忘记将我的示例改回来。

标签: prolog


【解决方案1】:

问题是我不明白序言:D

@TessellatingHeckler 指出,我可以用is_chain(Dominos), Dominos = [(First,_)|_Rest] 测试is_chain

这证实了代码工作得很好。

chain 显然是错误的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-04
    相关资源
    最近更新 更多