关于构建列表直至满足条件

2024-04-07

我想解决《巨猫军团之谜》 https://youtu.be/YeMVoJKn1Tg由 Dan Finkel 使用 Prolog 编写。

基本上你从[0],然后使用以下三个操作之一构建此列表:添加5,添加7,或采取sqrt。当您成功建立一个列表后,您就成功完成了游戏2,10 and 14按该顺序出现在列表中,并且它们之间可以有其他数字。

规则还要求所有元素都是不同的,它们都是<=60和 都只是整数。 例如,从[0],你可以申请(add5, add7, add5),这会导致[0, 5, 12, 17],但由于它没有按顺序排列 2,10,14,因此不能满足游戏。

我想我已经成功地写出了所需的事实,但我不知道如何实际构建列表。我认为使用dcg是一个不错的选择,但我不知道如何。

这是我的代码:

:- use_module(library(lists)).
:- use_module(library(clpz)).
:- use_module(library(dcgs)).

% integer sqrt
isqrt(X, Y) :- Y #>= 0, X #= Y*Y.

% makes sure X occurs before Y and Y occurs before Z
before(X, Y, Z) --> ..., [X], ..., [Y], ..., [Z], ... .
... --> [].
... --> [_], ... .

% in reverse, since the operations are in reverse too.
order(Ls) :- phrase(before(14,10,2), Ls).

% rule for all the elements to be less than 60.
lt60_(X) :- X #=< 60.
lt60(Ls) :- maplist(lt60_, Ls).

% available operations
add5([L0|Rs], L) :- X #= L0+5, L = [X, L0|Rs].  
add7([L0|Rs], L) :- X #= L0+7, L = [X, L0|Rs].
root([L0|Rs], L) :- isqrt(L0, X), L = [X, L0|Rs].

% base case, the game stops when Ls satisfies all the conditions.
step(Ls) --> { all_different(Ls), order(Ls), lt60(Ls) }.

% building the list
step(Ls) --> [add5(Ls, L)], step(L).
step(Ls) --> [add7(Ls, L)], step(L).
step(Ls) --> [root(Ls, L)], step(L).

该代码发出以下错误,但我没有尝试跟踪它或任何其他内容,因为我确信我错误地使用了 DCG:

?- phrase(step(L), X).
caught: error(type_error(list,_65),sort/2)

我正在使用 Scryer-Prolog,但我认为所有模块都可以在swipl也喜欢clpfd代替clpz.


step(Ls) --> [add5(Ls, L)], step(L).

这不会做你想要的。它描述了表单的列表元素add5(Ls, L)。想必Ls当你到达这里时必然会产生一些价值,但是L没有绑定。L如果Ls是一个正确形式的非空列表,并且您executed目标add5(Ls, L)。但你并没有执行这个目标。您正在将一个术语存储在列表中。然后,与L完全未绑定,期望将其绑定到列表的代码的某些部分将抛出此错误。大概是这样sort/2电话在里面all_different/1.

Edit:这里发布了一些令人惊讶的复杂或低效的解决方案。我认为 DCG 和 CLP 在这里都太过分了。所以这是一个相对简单且快速的方法。为了执行正确的 2/10/14 顺序,它使用状态参数来跟踪我们以正确的顺序看到了哪些:

puzzle(Solution) :-
    run([0], seen_nothing, ReverseSolution),
    reverse(ReverseSolution, Solution).
    
run(FinalList, seen_14, FinalList).
run([Head | Tail], State, Solution) :-
    dif(State, seen_14),
    step(Head, Next),
    \+ member(Next, Tail),
    state_next(State, Next, NewState),
    run([Next, Head | Tail], NewState, Solution).
    
step(Number, Next) :-
    (   Next is Number + 5
    ;   Next is Number + 7
    ;   nth_integer_root_and_remainder(2, Number, Next, 0) ),
    Next =< 60,
    dif(Next, Number).  % not strictly necessary, added by request

    
state_next(State, Next, NewState) :-
    (   State = seen_nothing,
        Next = 2
    ->  NewState = seen_2
    ;   State = seen_2,
        Next = 10
    ->  NewState = seen_10
    ;   State = seen_10,
        Next = 14
    ->  NewState = seen_14
    ;   NewState = State ).

SWI-Prolog 上的计时:

?- time(puzzle(Solution)), writeln(Solution).
% 13,660,415 inferences, 0.628 CPU in 0.629 seconds (100% CPU, 21735435 Lips)
[0,5,12,17,22,29,36,6,11,16,4,2,9,3,10,15,20,25,30,35,42,49,7,14]
Solution = [0, 5, 12, 17, 22, 29, 36, 6, 11|...] .

重复的member确保不重复的调用占据了大部分执行时间。使用“已访问”表(未显示)可将时间缩短至约 0.25 秒。

Edit:进一步削减一点,速度提高 100 倍:

prev_next(X, Y) :-
    between(0, 60, X),
    (   Y is X + 5
    ;   Y is X + 7
    ;   X > 0,
        nth_integer_root_and_remainder(2, X, Y, 0) ),
    Y =< 60.

moves(Xs) :-
    moves([0], ReversedMoves),
    reverse(ReversedMoves, Xs).
    
moves([14 | Moves], [14 | Moves]) :-
    member(10, Moves).
moves([Prev | Moves], FinalMoves) :-
    Prev \= 14,
    prev_next(Prev, Next),
    (   Next = 10
    ->  member(2, Moves)
    ;   true ),
    \+ member(Next, Moves),
    moves([Next, Prev | Moves], FinalMoves).

?- time(moves(Solution)), writeln(Solution).
% 53,207 inferences, 0.006 CPU in 0.006 seconds (100% CPU, 8260575 Lips)
[0,5,12,17,22,29,36,6,11,16,4,2,9,3,10,15,20,25,30,35,42,49,7,14]
Solution = [0, 5, 12, 17, 22, 29, 36, 6, 11|...] .

移动表可以预先计算(枚举所有解决方案)prev_next/2,在动态谓词中断言它们,并调用它)以获得另外一两毫秒的时间。使用 CLP(FD) 而不是“直接”算术会使 SWI-Prolog 上的速度显着变慢。尤其,Y in 0..60, X #= Y * Y而不是nth_integer_root_and_remainder/4目标将此时间延长至约 0.027 秒。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于构建列表直至满足条件 的相关文章

  • LISP 非常简单的列表问题

    我正在学习 lisp 而且我对此还很陌生 所以我想知道 如果我这样做 defparameter list 1 list 1 2 defparameter list 2 list 2 3 defparameter list 3 append
  • 对自身内部列表的递归引用[重复]

    这个问题在这里已经有答案了 所以我在 python 中遇到了一些非常奇怪的东西 我尝试添加对列表本身的引用 该代码可能有助于比我能表达的更好地展示我所说的内容 我正在使用 IDLE 编辑器 交互模式 gt gt gt l 1 2 3 gt
  • 将 for 循环转换为列表理解

    我有一个for循环 将字符串列表中每个元素的子字符串与另一个字符串列表中的元素进行比较 mylist for x in list1 mat False for y in list2 if x 14 in y mat True if not
  • 如何使用append/3在prolog中递归构建列表?

    我需要了解一些事实的价值 这部分似乎正在发挥作用 fact1 A Val1 fact2 B Val2 A B 但是一旦我尝试附加这些值 Val1 Val2 通过使用append 3谓词到列表 OutList 我只得到一个可能的解决方案 而不
  • 将2个暗淡数组“列表列表”输出到python中的文本文件

    简单的问题 我正在创建一个两个暗淡的数组 ddist 0 d for in 0 d 在下面的代码中使用列表 它使用 gis 数据输出距离 我只是想要一种简单的方法来获取数组 列表的结果并将其输出到保持相同的 N N 结构的文本文件 我过去曾
  • 将人员分配到床位 - 自动化方法[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我每年都会帮助举办青年营 将与会者分配到卧室是一项艰巨的任务 有 92 个卧室 活动持续一周 与会者停留的时间长短不一 而且床需要重复
  • 如何定义 map::iterator 列表和 list::iterator 映射

    我需要 Map iterator 的列表和 List iterator 的映射 我怎样才能做到这一点 typedef std list
  • 如何在 Python 中使用 .format() 打印“for”循环中的列表?

    我是 Python 新手 我正在编写一段非常简单的代码 使用 for 循环打印列表的内容 format 我想要如下的输出 但我收到此错误 names David Peter Michael John Bob for i in names p
  • prolog跟踪如何使用

    跟踪prolog程序时如何进行第二步 例如 我想跟踪以下简单程序 length1 0 length1 X Xs N length1 Xs N1 N is N1 1 我跟踪程序 trace length 1 2 3 N Call 7 leng
  • 在 HTML 下拉列表中有一个滚动条

    我正在寻找一种在 HTML 的下拉列表中添加滚动条的方法 这样如果下拉列表包含的内容超过例如 5 项 将出现滚动条以查看其余项 这是因为我将被迫列出一些大清单 过去几个小时我一直在谷歌上搜索它 但没有运气 它需要适用于 IE8 FF 和 C
  • 将一个列表(n 元组或列表)与另一个列表(也可以是数组)缩放的惯用 F# 方法是什么?

    Given let weights 0 5 0 4 0 3 let X 2 3 4 7 3 2 5 3 6 我想要的是 wX 0 5 2 3 4 0 4 7 3 2 0 3 5 3 6 我想知道一种使用列表和数组来执行此操作的优雅方法 欢迎
  • 合并一个对(元组)列表?

    从链接对的列表中 我想将这些对组合成公共 ID 组 这样我就可以将 group ids 写回数据库 例如 UPDATE table SET group n WHERE id IN Example 1 2 3 4 1 5 6 3 7 8 be
  • 查找嵌套列表中元素的索引?

    我有一个类似的列表 mylist lt list a 1 b list A 1 B 2 c list C 1 D 3 是否有一种 无循环 方法来识别元素的位置 例如如果我想用 5 替换 C 的值 并且在哪里找到元素 C 并不重要 我可以这样
  • Prolog 检查数字列表是否按顺序排列

    我希望能够获取一个数字列表并获得按顺序排列的最大数字序列 例如 in order 1 2 3 4 5 N N 5 expected result in order 1 2 5 6 7 8 4 N N 4 expected result 到目
  • R从列表中提取数据框,列名中没有前缀

    我在列表中放置了一个数据框 然后 当尝试将其提取回来时 我得到了该数据帧的所有以列表键为前缀的列名称 有没有办法完全按照最初传递的方式提取数据帧 cols lt c column1 Column2 Column3 df1 lt data f
  • 如何将列表列表写入 CSV 文件 Python?

    我有一个列表 例如 a b c d e f 我想将其写入 CSV 文件 如下所示 a b c d e f 我怎么做 我尝试过使用 csv writerows 但输出文件的每个字符位于不同的单元格中 并且全部位于同一行中 从某种意义上说 第一
  • 查找数据帧列表中同一列中的所有重复值并将其转换为 NULL

    我有一个清单BELGIAN COAST list包含数百个数据帧 df1 df2 15 列 X 1000 行 每个数据帧的最后一列称为Chemicals并包含一些字符 例如Sulfate or Ammonia 但是这一列有很多行Chemic
  • 如何通过 python 中的函数运行列表?

    我试图通过我创建的函数运行我的列表 但不断收到错误 我不知道出了什么问题 温度 F temp f 19 21 21 21 23 功能 def fahrToCelsius tempFahrenheit return tempFahrenhei
  • R - 通过覆盖和递归合并列表

    假设我有两个带有名字的列表 a list a 1 b 2 c list d 1 e 2 d list a 1 b 2 b list a 2 c list e 1 f 2 d 3 e 2 我想递归地合并这些列表 如果第二个参数包含冲突的值 则
  • Prolog 否定和逻辑否定

    假设我们有以下程序 a tom v pat 和查询 返回 false a X v X 当追踪时 我可以看到X被实例化为tom 谓词a tom 成功 因此 a tom fails 我在一些教程中读到 不 在Prolog中只是一个测试 不会导致

随机推荐

  • 在swift ios中多线程并行执行多个任务

    我知道队列的创建并且能够执行单个任务 但如何并行执行多个任务 并发队列 gt let concurrentQueue DispatchQueue label com some concurrentQueue attributes concu
  • 配置 Microsoft Application Insights 以监视 Windows 服务

    是否可以配置微软的应用洞察 http msdn microsoft com en us library dn481095 aspx监控 Windows 服务 我有一个在 Azure 中运行的 VM 其中托管了 Web 服务 我需要安装哪个版
  • 在 fxml 文件之间切换

    我在 swing 组件内使用 jfxPanel 创建了一个应用程序 我面临的问题是我无法更改 fxml 文件 当单击 fxml 的按钮时 我想处理该 fxml 并在那里加载另一个 fxml 文件 这就是我到目前为止所做的 public cl
  • Objective-C 类前缀 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 您对命名 ObjC 类有何偏好 我有点不确定对此最合理的方法是什么 所以很高兴听到一些其他意见 Apple 建议为 cocoa 类添加前缀 因为
  • 在 jQuery 中,如何使用元素选中和取消选中所有复选框? [复制]

    这个问题在这里已经有答案了 我有以下代码 它使用通常位于复选框顶部的 LABEL 元素检查页面上的所有复选框 现在如何使用相同的 LABEL 元素取消选中所有框 jQuery document ready function var chec
  • Kibana4 监听端口 80 而不是端口 5601

    我在运行 RHEL7 的 Amazo EC2 实例上运行 elasticsearch 1 4 和 kibana4 Kibana4 作为独立进程运行 未部署在 nginx 等 Web 容器中 它正在侦听端口 5601 默认端口 我想让 kib
  • Android - 加载图像Url并在ImageView中显示

    我有这段代码来加载图像 服务器是安全的 我得到的答复是 200 这意味着可以 然后还要加载正确的网址 问题是当我运行我的应用程序时 图像不会被加载 try Bitmap bitmap null URL imageUrl new URL ur
  • C++ - 生成随机位集的有效方法,具有可配置的平均“1 与 0”比率

    我正在寻找一种高效的方法来生成随机数std bitset设定长度 我还希望能够影响1s 出现在结果中 因此如果概率值设置得足够低 则所有结果中只有一小部分会包含1 但仍然有可能 但不太可能 导致所有1s 它将用于计算量很大的应用程序 因此欢
  • 动态调用函数 - Python

    我有一个功能列表 例如 def filter bunnies pets def filter turtles pets def filter narwhals pets 有没有办法通过使用代表其名称的字符串来调用这些函数 e g filte
  • 如何更新 GridView / ListView 的每个元素上的 ProgressBar 状态?

    目前我有一个 GridView 每个元素都应该有一个单独的 ProgressBar 这些元素代表单独的下载 我想使用这些进度条显示下载的状态 但我应该如何更新它们呢 我的问题是 根据文档 以及我在 Google IO 视频中听到的内容 更新
  • 我应该实际使用哪个版本的 jQuery? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 所以几个月前 有一段时间我实际上并不需要 jQuery 来完成任何事情 并且几乎忘记了它 然后我醒了 所以 我前往http jquery
  • C++ 迭代模板 Map

    当我有一个包含模板映射和一个模板类const iterator声明如下代码typedef 如何迭代类外部映射的元素 例如 main 中以将它们打印在输出上 template
  • 删除小于X的数组元素

    我有数组 arr1 array 5 3 9 11 6 15 arr2 array 11 20 1 3 8 现在我需要循环遍历 arr1并找到小于的最大数X foreach arr1 as x need element that is MAX
  • 如何在 Laravel 中使用主密码登录用户?

    在 Laravel 中 我想使用主密码登录我的任何用户帐户 这是我在控制器中尝试过的 if Input get password master password email Input get email user User find em
  • 通过 YAML 发布管道运行 azure powershell 脚本

    我有正常且工作的发布管道 通过给定的某个部署组 该管道执行一些任务 复制脚本 执行该 powershell 脚本 在部署组中定义的目标计算机上 删除脚本 我知道 YAML 不支持部署组 但是 幸运的是我 到目前为止我的部署组只有一台机器 我
  • UI 测试 - isSelected 始终返回 false

    我们最近使用 Xcode 8 2 1 8C1002 将 Swift 2 3 项目更新为 Swift 3 现在大多数与 tableViews 和 isSelected 属性相关的 UI 测试都不起作用 即使选择了对象 它也始终返回 false
  • mysql 无法添加外键?

    我使用MySQL Workbench在表中添加外键 但发生了一些奇怪的错误 这是SQL语句 ALTER TABLE tansung Declaration ADD COLUMN goodsId INT 11 NOT NULL AFTER d
  • 如何获取 UIScrollView 中的当前缩放级别?

    为了尝试创建一种解决方法 使图像在 UIScrollView 中居中并使其表现得像 Apple 的照片应用程序一样 我需要获取当前的缩放级别并使用该数字来计算图像在每个缩放级别应插入的量 注意 我知道一些程序员通过将图像集中在与滚动视图大小
  • 当不应该使用整数和双精度数时会给出不同的答案

    我正在解决欧拉项目问题14 https projecteuler net problem 14使用java 我并不是寻求帮助解决问题 我已经解决了 但我遇到了一些我无法弄清楚的事情 问题是这样的 为正集合定义以下迭代序列 整数 n n 2
  • 关于构建列表直至满足条件

    我想解决 巨猫军团之谜 https youtu be YeMVoJKn1Tg由 Dan Finkel 使用 Prolog 编写 基本上你从 0 然后使用以下三个操作之一构建此列表 添加5 添加7 或采取sqrt 当您成功建立一个列表后 您就