提取列表中两个值之间的项目列表 - prolog
Extracting list of items between two values in a list - prolog
假设我有一个长度为 9 的唯一列表,其中包含 1 到 9 之间的值,随机顺序(想想数独),我想提取出现在值 1 之间的项目的子列表和 9(不包括)。即: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)
以保持整洁 here/seperation 关注):
between1and9(List,Between) :-
flatten([_,[1],Between,[9],_], List);
flatten([_,[9],Between,[1],_], List).
当 1 或 9 位于 List
中的第一个或最后一个位置时,或者如果它们在 List
中相邻时,此版本将失败。 between1and9([_,1,9,_,_,_,_,_,_],[])
是 true,但 between1and9([_,1,9,_,_,_,_,_,_],_)
是 false(当我尝试将其用作约束来解决更大的问题时失败。)
这似乎是导致两次失败的相同问题,flatten
似乎不喜欢将未知数视为空列表,除非它们在某处明确表示。
我明白为什么会这样,如果 flatten
可以 "invent" 第一个参数中的空列表,这将意味着第一个参数中的任何内容都有无限的解决方案。虽然我的完整程序有其他限制来防止这种情况,但我可以理解为什么 flatten
可能不想容纳它。
我可以通过将每个排列与析取相匹配来解释边缘情况(双关语)(即:flatten([_,1,B,9,_],L);flatten([_,9,B,1,_],L);flatten([_,1,B,9]);flatten...
,并将 Between 解释为一个空列表:\*above permutations on flatten*\; ( Between = [], (\*permutations for either edge and 1/9*\) )
但这似乎使一个已经冗长的解决方案(总共 10 个扁平排列)变得更糟(18)所以我有两个(密切相关的)问题:
如果我能做到以下几点:
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
的每个匹配排列。不幸的是,这个和它的一些变体都单方面失败了。我在这里遗漏了一些明显的东西吗? (我怀疑运算符优先,但我尝试了几个不同的版本。)
还是我这样做完全错了? flatten/2
文档表明,在大多数情况下它是一种反模式,是否有更前卫的*方式来解决这个问题?鉴于我在经历这个过程中意识到的所有陷阱,我几乎可以肯定存在。
(抱歉,我很痛苦地意识到我用来描述这里事物的很多术语可能是非常错误的,我只是有点熟悉 predicate/formal 逻辑等等用于描述控制流类型的编程。尽管我在实践中相当了解逻辑编程,但我仍在努力寻找一种语言来稳健地谈论它,我会用我得到的任何更正来修改这个问题。)
一些背景:我是 prolog 的新手,通过尝试扩展众多数独解算器之一来解决我在多年前打印出的一些谜题中发现的奇怪数独来测试我的理解显示了在任何给定行或列中出现在 1 和 9 之间的所有数字的总和作为额外提示,它有点像数独和绘图方块的混合。现在的求解器正在快速运行:SumSudoku(swish)。虽然到时候可能会乱七八糟
*推论问题:"pythonic?"
这个词有序言版本吗
您可以为此使用旧的 append/3
。有没有可能你一直想要 append/3
但不知何故认为它叫做 flatten
?
对于“1 在 9 之前”的情况,您可以这样写:
between_1_and_9(List, Sublist) :-
append(_, [1|Rest], List),
append(Sublist, [9|_], Rest).
对于“9 先于 1”的情况,您需要交换 1 和 9。
这也留下了 "spurious choice point"(感谢@PauloMoura 的评论)。确保以某种方式摆脱它。
至于"Pythonic"(这来自一个正在恢复的Pythonista),我只能说,放心:
There is always more than one obvious way to do it in Prolog.
你甚至不必是荷兰人。
假设我有一个长度为 9 的唯一列表,其中包含 1 到 9 之间的值,随机顺序(想想数独),我想提取出现在值 1 之间的项目的子列表和 9(不包括)。即: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)
以保持整洁 here/seperation 关注):
between1and9(List,Between) :-
flatten([_,[1],Between,[9],_], List);
flatten([_,[9],Between,[1],_], List).
当 1 或 9 位于 List
中的第一个或最后一个位置时,或者如果它们在 List
中相邻时,此版本将失败。 between1and9([_,1,9,_,_,_,_,_,_],[])
是 true,但 between1and9([_,1,9,_,_,_,_,_,_],_)
是 false(当我尝试将其用作约束来解决更大的问题时失败。)
这似乎是导致两次失败的相同问题,flatten
似乎不喜欢将未知数视为空列表,除非它们在某处明确表示。
我明白为什么会这样,如果 flatten
可以 "invent" 第一个参数中的空列表,这将意味着第一个参数中的任何内容都有无限的解决方案。虽然我的完整程序有其他限制来防止这种情况,但我可以理解为什么 flatten
可能不想容纳它。
我可以通过将每个排列与析取相匹配来解释边缘情况(双关语)(即:flatten([_,1,B,9,_],L);flatten([_,9,B,1,_],L);flatten([_,1,B,9]);flatten...
,并将 Between 解释为一个空列表:\*above permutations on flatten*\; ( Between = [], (\*permutations for either edge and 1/9*\) )
但这似乎使一个已经冗长的解决方案(总共 10 个扁平排列)变得更糟(18)所以我有两个(密切相关的)问题:
如果我能做到以下几点:
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
的每个匹配排列。不幸的是,这个和它的一些变体都单方面失败了。我在这里遗漏了一些明显的东西吗? (我怀疑运算符优先,但我尝试了几个不同的版本。)还是我这样做完全错了?
flatten/2
文档表明,在大多数情况下它是一种反模式,是否有更前卫的*方式来解决这个问题?鉴于我在经历这个过程中意识到的所有陷阱,我几乎可以肯定存在。
(抱歉,我很痛苦地意识到我用来描述这里事物的很多术语可能是非常错误的,我只是有点熟悉 predicate/formal 逻辑等等用于描述控制流类型的编程。尽管我在实践中相当了解逻辑编程,但我仍在努力寻找一种语言来稳健地谈论它,我会用我得到的任何更正来修改这个问题。)
一些背景:我是 prolog 的新手,通过尝试扩展众多数独解算器之一来解决我在多年前打印出的一些谜题中发现的奇怪数独来测试我的理解显示了在任何给定行或列中出现在 1 和 9 之间的所有数字的总和作为额外提示,它有点像数独和绘图方块的混合。现在的求解器正在快速运行:SumSudoku(swish)。虽然到时候可能会乱七八糟
*推论问题:"pythonic?"
这个词有序言版本吗您可以为此使用旧的 append/3
。有没有可能你一直想要 append/3
但不知何故认为它叫做 flatten
?
对于“1 在 9 之前”的情况,您可以这样写:
between_1_and_9(List, Sublist) :-
append(_, [1|Rest], List),
append(Sublist, [9|_], Rest).
对于“9 先于 1”的情况,您需要交换 1 和 9。
这也留下了 "spurious choice point"(感谢@PauloMoura 的评论)。确保以某种方式摆脱它。
至于"Pythonic"(这来自一个正在恢复的Pythonista),我只能说,放心:
There is always more than one obvious way to do it in Prolog.
你甚至不必是荷兰人。