提取列表中两个值之间的项目列表-Prolog

时间:2019-03-29 07:30:08

标签: list prolog logic

说我有一个长度为9的值(长度介于9和1之间)的唯一列表,包括一个随机顺序(想算数独),我想提取一个值介于1和9之间的项的子列表。 (独家)。 IE:between1and9([1,3,5,4,2,9,7,8,6],[3,5,4,2])应该为真。

目前,我正在尝试使用flatten/2,但运气不佳。这是我目前的策略(假设我在其他地方强制执行List ins 1..9, maplist(all_distinct, List), length(List, 9),以使其在这里保持整洁/关注点分离):

between1and9(List,Between) :-
  flatten([_,[1],Between,[9],_], List);
  flatten([_,[9],Between,[1],_], List).

尽管当1或9位于List中的第一个或最后一个位置时,或者如果它们在List中相邻时,此版本失败。 between1and9([_,1,9,_,_,_,_,_,_],[])是正确的,但是between1and9([_,1,9,_,_,_,_,_,_],_)是错误的(当我尝试将其作为约束来解决更大的问题时会失败。)

导致这两个失败的原因似乎都是相同的问题,flatten似乎不喜欢将未知数视为空列表,除非在某个地方将其明确表示。

我明白了为什么会这样,如果flatten可以“发明”第一个参数中的空列表,那意味着第一个参数中的任何事物都有无限的解决方案。尽管我的整个程序还有其他限制来防止这种情况,但我可以理解为什么flatten可能不希望这样做。

我可以通过将每个置换与析取项相匹配来说明边缘情况(双关语意味)(即:flatten([_,1,B,9,_],L);flatten([_,9,B,1,_],L);flatten([_,1,B,9]);flatten...,并使用\*above permutations on flatten*\; ( Between = [], (\*permutations for either edge and 1/9*\) )

将“之间”解释为空列表)

但是,这似乎使本来就很漫长的解决方案(总共10个扁平化排列)更加糟糕(18个),所以我有两个(密切相关)问题:

  1. 如果我可以执行以下操作:

    between1and9(L,B) :-
      ( ( X = 1, Y = 9 ); ( X = 9, Y = 1 ) ),
      ( ( Z1 = _; Z1 = [] ), ( Z2 = _ ; Z2 = [] ) ),
      ( B = _; B = [] ),
      flatten([Z1,X,B,Y,Z2],L).
    

    我不必手动键入flatten的每个匹配匹配项。不幸的是,这和它的一些变化都单方面失败了。我在这里缺少明显的东西吗? (我怀疑是操作者优先,但我尝试了几种不同的版本。)

  2. 还是我这样做完全错误? flatten/2文档表明,在大多数情况下,这是一种反模式,是否有更多解决问题的前言式方法?考虑到我正在经历的所有陷阱,我几乎可以肯定确实存在。

(对不起,我很痛苦地意识到,我用来描述这种事情的很多术语可能是非常错误的,我只是对谓词/形式逻辑很熟悉,并且更习惯于描述控制流类型编程。尽管我在实践中相当了解逻辑编程,但我仍在努力寻找一种健壮的语言来讨论它,但我将对这个问题进行任何修正,以修正它。)

某些背景:我是新手,它是通过尝试扩展众多数独解决方案中的一种来解决我数年前在打印出来的一些难题中发现的数独的怪异问题时来证明我的理解的,作为额外提示,出现在任何给定行或列中1到9之间的所有数字的总和,有点像数独和picross的混合。现在的求解器不停运行:SumSudoku(swish)。尽管可能一团糟。

*推论问题:“ pythonic”一词的序言版本吗?

1 个答案:

答案 0 :(得分:2)

您可以为此使用旧的append/3。您是否可能一直想要append/3,但又以某种方式认为它叫做flatten

对于“ 1比9优先”的情况,您应该这样写:

between_1_and_9(List, Sublist) :-
    append(_, [1|Rest], List),
    append(Sublist, [9|_], Rest).

您需要将1和9交换为“ 9比1优先”的情况。

这还会留下一个“虚假的选择点”(谢谢@PauloMoura的评论)。确保以某种方式摆脱它。

对于“ Pythonic”(这是来自恢复中的Pythonista),我只能放心地说:

  

在Prolog中,总有不止一种显而易见的方法。

您甚至不必是荷兰人。