如何确定矩阵的所有给定坐标都是相连的?

2024-03-18

给定一个网格,我如何确定网格的元素是否都在单个区域中。在下面的情况下是正确的,因为矩阵中的每个元素都有一个邻居。

示例1:

gridneighbours([[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[4,1],[4,2]]).
true.

然而在我的第二个例子中,Example2:

gridneighbours([[1,1],[1,2],[1,3],[1,4],[1,5],[1,6],[3,1],[4,1],[4,2]]).
false.

这是错误的,因为 [3,1]、[4,1]、[4,2] 与前面的元素不相交。 最初,我尝试使用 Prolog 中的子集通过简单地从 X 或 Y 中添加或减去来检查另一个相邻的现有元素,但这不起作用,因为分割区域的元素将彼此相邻。另外,对角线不算是彼此相邻。

更新,添加代码: 这是我得到的:

%Check right
neighbourcheck([X,Y|_],S) :- X1 is X + 1, subset([[X1,Y]],S).
%Check left
neighbourcheck([X,Y|_],S) :- X1 is X - 1, subset([[X1,Y]],S).
%Check Up
neighbourcheck([X,Y|_],S) :- Y1 is Y + 1, subset([[X,Y1]],S).
%Check Down
neighbourcheck([X,Y|_],S) :- Y1 is Y - 1, subset([[X,Y1]],S).
% Iterate through all sublists and check for neighbours
gridneighbour(S) :- forall(member(X,S), neighbourcheck(X,S)).

这不起作用的原因是因为子集不关心我们是否与另一个不相交的元素匹配。即 [3,1] 与 [4,1] 匹配。 运行此代码并使用上面的示例给出:

  • 示例1:正确
  • 示例 2:正确(显然这应该是错误的,因为 [3,1]、[4,1] 和 [4,2] 是分开的)。

一种有效的简单方法可以概述如下:

  • 从两组点(列表?)开始:您知道属于某个区域的点,Region其余的,Rest。一开始,你可以选择任意一个点属于Region,剩下的就在Rest.
  • Look in Rest for a point that is a neighbor to any point in Region.
    • 如果你找到邻居,请将其从Rest to Region并重复
    • 如果你找不到邻居,就停下来
  • 如果有点在Rest最后,那么这就是not一个地区。

这是一个更简单的定义方法neighbors/2:

neighbors([X1,Y1], [X2,Y2]) :-
    abs(X1-X2) + abs(Y1-Y2) =:= 1.

您可以通过简单地尝试每种可能的组合来查找一个列表中与另一个列表中的点相邻的点:

% add_to_region(+Region0, +Rest0, -Region, -Rest)
%% Look in Rest0 for a neighbor to Region0;
%% Region is Region0 with the neighbor,
%% Rest is Rest0 without it
add_to_region(Region, Rest0, [B|Region], Rest) :-
    member(A, Region),
    select(B, Rest0, Rest),
    neighbors(A, B).

对member/2 的调用通过回溯来选取Region 中的每个点到A。对 select/3 的调用选择 Rest0 到 B 中的每个点,其余点在 Rest 中。如果两个点是邻居,则将 B 添加到 Region 前面。

如果当前区域没有更多邻居,则此操作将会失败Rest,并且如果有的话至少成功一次。你可能想用once(add_to_region(Region0, Rest0, Region, Rest))这样你就没有不必要的选择点。使用你的例子:

?- once(
      add_to_region(
         [[1,1],[1,2],[1,3],[2,1]],
         [[2,2],[2,3],[3,1],[4,1],[4,2]],
         Region, Rest)).
Region = [[2, 2], [1, 1], [1, 2], [1, 3], [2, 1]],
Rest = [[2, 3], [3, 1], [4, 1], [4, 2]].

See how [2,2]被挑选自Rest并添加到Region.

?- add_to_region(
   [[1,1],[1,2],[1,3],[1,4],[1,5],[1,6]],
   [[3,1],[4,1],[4,2]],
   Region, Rest).
false.

这失败了,因为没有任何点Rest是任意点的邻居Region.

Edit

如上所述,这绝对是可行的,但只需稍加修改,我们就可以拥有一个更容易在 Prolog 中实现的算法。事情是这样的:

set_region_rest(+Set, -Region, -Rest)

  • 按照标准术语顺序对点集进行排序;现在你有一个ordset.
  • 将此集合拆分为一个 Region 和一个不属于它的 Rest

为了进行拆分,我们将维护一个额外的列表。我们将其称为开放节点列表:我们尚未探索的节点。一开始,输入列表的第一个元素是唯一的开放节点。 其余元素按原样传递。 最后两个参数 Region 和 Rest 是输出参数。

open_set_closed_rest(Open, Set, Closed, Rest)

  • 如果开放集为空,则封闭集的其余部分(现在的区域)也为空;剩下的 Set 就是 Rest。
  • Otherwise:
    • 从Open列表中取出第一对坐标;立即将其放在 Closed 坐标的前面。
    • 尝试在坐标集中找到第一对的任何邻居;如果找到任何,请将其附加到公开组的前面;删除邻居后剩下的 Set 是新的 Set。
    • 用新的公开组、剩余的封闭组、剩余的组和休息组再试一次。

为了在 Prolog 中做到这一点,我将首先清理坐标表示。 有点烦人的是,它们出现在两个列表中:如果我们使用一对来代替,那么书写就会少得多:[X,Y] ---> X-Y。为此,我添加此谓词:

xy(XY) :-
        coordinates(C),
        maplist([[X,Y], X-Y]>>true, C, XY).
xy([1-1,1-3,1-2]).
xy([1-2,2-1,2-2]).
xy([1-1, 1-2, 1-3, 1-4, 1-5,
    2-1,                2-5,
    3-1,                3-5,
    4-1,                4-5,
    5-1, 5-2, 5-3, 5-4, 5-5]).
xy([1-1, 1-2, 1-3, 1-4, 1-5,
    2-1,                2-5,
    3-1,      3-3,      3-5,
    4-1,                4-5,
    5-1, 5-2, 5-3, 5-4, 5-5]).

coordinates([[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[4,1],[4,2]]).
coordinates([[1,1],[1,2],[1,3],[1,4],[1,5],[1,6],[3,1],[4,1],[4,2]]).

(我还添加了 4 个额外的测试集!)

有了这个,我得到:

?- xy(XY).
XY = [1-1, 1-2, 1-3, 2-1, 2-2, 2-3, 3-1, 4-1, ... - ...] [write] % press 'w' here
XY = [1-1, 1-2, 1-3, 2-1, 2-2, 2-3, 3-1, 4-1, 4-2] ;
XY = [1-1, 1-2, 1-3, 1-4, 1-5, 1-6, 3-1, 4-1, 4-2] ;
XY = [1-1, 1-3, 1-2] ;
XY = [1-2, 2-1, 2-2] ;
XY = [1-1, 1-2, 1-3, 1-4, 1-5, 2-1, 2-5, 3-1, 3-5, 4-1, 4-5, 5-1, 5-2, 5-3, 5-4, 5-5] ;
XY = [1-1, 1-2, 1-3, 1-4, 1-5, 2-1, 2-5, 3-1, 3-3, 3-5, 4-1, 4-5, 5-1, 5-2, 5-3, 5-4, 5-5].

以下是尝试用代码编写上述算法的方法:

set_region_rest([A|As], Region, Rest) :-
        sort([A|As], [B|Bs]),
        open_set_closed_rest([B], Bs, Region, Rest).

这只是对输入 Set 进行排序并从中分离出第一个元素。 第一个元素是 Open 集中的第一个坐标对,其余的是 Set,然后是输出参数。

现在,为了将集合分成区域和休息,只要我们在开放集中有坐标对,我们就需要继续增长区域。如果Open集是空的,这意味着我们的Region是完整的,剩下的Set就是Rest:

:- use_module(library(clpfd)).

open_set_closed_rest([], Rest, [], Rest).

为了找出集合中坐标的哪些邻居,我们使用ord_intersection/4 http://eu.swi-prolog.org/pldoc/doc_for?object=ord_intersection/4,它同时为我们提供了 Set 中的邻居以及 Set 的其余部分。

NB:4个邻居坐标已排序!

open_set_closed_rest([X-Y|As], Set, [X-Y|Closed0], Rest) :-
        X0 #= X-1, X1 #= X + 1,
        Y0 #= Y-1, Y1 #= Y + 1,
        ord_intersection([X0-Y,X-Y0,X-Y1,X1-Y], Set, New, Set0),
        append(New, As, Open),
        open_set_closed_rest(Open, Set0, Closed0, Rest).

就是这个。有了这个,我得到了以下6种解决方案:

?- xy(XY), set_region_rest(XY, Region, Rest).
XY = [1-1, 1-2, 1-3, 2-1, 2-2, 2-3, 3-1, 4-1, 4-2],
Region = [1-1, 1-2, 1-3, 2-3, 2-2, 2-1, 3-1, 4-1, 4-2],
Rest = [] ;
XY = [1-1, 1-2, 1-3, 1-4, 1-5, 1-6, 3-1, 4-1, 4-2],
Region = [1-1, 1-2, 1-3, 1-4, 1-5, 1-6],
Rest = [3-1, 4-1, 4-2] ;
XY = [1-1, 1-3, 1-2],
Region = [1-1, 1-2, 1-3],
Rest = [] ;
XY = [1-2, 2-1, 2-2],
Region = [1-2, 2-2, 2-1],
Rest = [] ;
XY = [1-1, 1-2, 1-3, 1-4, 1-5, 2-1, 2-5, 3-1, 3-5, 4-1, 4-5, 5-1, 5-2, 5-3, 5-4, 5-5],
Region = [1-1, 1-2, 1-3, 1-4, 1-5, 2-5, 3-5, 4-5, 5-5, 5-4, 5-3, 5-2, 5-1, 4-1, 3-1, 2-1],
Rest = [] ;
XY = [1-1, 1-2, 1-3, 1-4, 1-5, 2-1, 2-5, 3-1, 3-3, 3-5, 4-1, 4-5, 5-1, 5-2, 5-3, 5-4, 5-5],
Region = [1-1, 1-2, 1-3, 1-4, 1-5, 2-5, 3-5, 4-5, 5-5, 5-4, 5-3, 5-2, 5-1, 4-1, 3-1, 2-1],
Rest = [3-3].

顺便说一下,使用set_region_rest/3作为构建块,我们可以轻松地将一组坐标分割为区域:

set_regions([], []).
set_regions([X|Xs], [R|Rs]) :-
        set_region_rest([X|Xs], R, Rest),
        set_regions(Rest, Rs).

So now:

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

如何确定矩阵的所有给定坐标都是相连的? 的相关文章

  • 多个事实的聚合解决方案

    尝试创建一个谓词 timePeriod 2 计算特定事实的两个日期之间的时间段 我已经设法自己做到这一点 但当 其他答案 存在于同一列表中时会遇到问题 即更容易用示例解释 我有以下知识基础事实 popStar Jackson 1987 19
  • Smullyan 数值机的解决方案

    在这里我建议找到 Smullyan 数值机的解决方案 此处定义 http heras gilsanz com manuel smullyan machines html 问题陈述 它们是接受数字列表作为输入 并根据输入模式遵循一些规则将其转
  • 如何确定矩阵的所有给定坐标都是相连的?

    给定一个网格 我如何确定网格的元素是否都在单个区域中 在下面的情况下是正确的 因为矩阵中的每个元素都有一个邻居 示例1 gridneighbours 1 1 1 2 1 3 2 1 2 2 2 3 3 1 4 1 4 2 true 然而在我
  • Prolog 中的失败谓词有什么用?

    我想不出我需要它的情况 优雅的系统提供false 0作为命令式的声明式同义词fail 0 它有用的一个例子是当您想要手动强制回溯副作用时 例如 between 1 3 N format line w n N false line 1 lin
  • 在 dll 中嵌入 prolog 引擎

    我最近一直在开发一个嵌入 prolog 推理引擎的 C 应用程序 正如标题中所述 我现在尝试生成一个 DLL 而不是可执行文件 以便我可以在另一个项目中使用它 由于我是 DLL 开发的新手 我想我可以从一个小例子开始 我有3个文件 like
  • 展平列表

    尝试解决练习 07http www ic unicamp br meidanis courses mc336 2009s2 prolog problemas http www ic unicamp br meidanis courses m
  • 如何使用 Prolog 查找二叉树的深度

    我正在学习 Prolog 并试图找到一个深度二叉树使用 Prolog 我代表一棵树是这样的 nil is a tree tree 1 nil nil this is a leaf tree 1 tree 1 nil nil nil this
  • 获取 Prolog 中的解决方案列表

    我正在学习 Prolog 并且正在阅读一本名为 人工智能 Prolog 编程 的书 作为练习 我想学习如何扩展本书中的示例之一 有人可以帮忙吗 假设您有以下事实 parent pam bob pam is a parent of bob p
  • 二叉树的 Herbrand 宇宙、Herbrand 基础和 Herbrand 模型(序言)

    什么是二叉树的 Herbrand 宇宙 Herbrand Base 和 Herbrand Model binary tree empty binary tree tree Left Element Right binary tree Lef
  • 关于构建列表直至满足条件

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

    为了计算两个相同长度列表之间的汉明距离 我使用foldl hamm A B 0 R 有了这个定义hamm 4 hamm A A V V hamm A B V0 V1 A B V1 is V0 1 第一条规则的删减可以防止不必要的回溯 然而
  • 寻找最大最小值集合

    我正在尝试编写一个 天真的或半天真的 程序 给定一组元素和许多玩家将其划分为这个数量的玩家 并且对于每个这样的划分取最小值 按总和 子集 然后 我想计算所有这些最小除法的最大值 这被称为https en wikipedia org wiki
  • 如何在Prolog中编写cmp_list/3函数?

    Write a predicate cmp list 3 the first 2 arguments are 2 lists and the last one is Comparison which means ge lt le or gt
  • Prolog 中的迷你数独求解器中途停止

    我正在学习 七周七种语言 我只是想从书中找到一个例子 它解决迷你数独网格 4x4 作者使用的是 gprolog 但我使用的是 swi prolog 无论出于何种原因 我都无法让 gprolog 在我的虚拟机上工作 但 swi prolog
  • 在列表列表中查找形状

    节目说明 该计划的目的 我的程序旨在计算 20X15 大小的平面中形状的位置 我有一个形状列表 其中包含形状类型 其 ID 半径或高度以及其在平面上的预期 X Y 位置 我有一个不同的二元运算列表 仅包含形状类型 其 id 及其与另一个形状
  • SWI Prolog 使用的检查优化会发生什么情况?

    去引用SICStus Prolog 手册 https sicstus sics se sicstus docs 3 12 9 html sicstus Occur html 逻辑编程背后的通常数学理论禁止 创建循环项 规定发生检查应该是 每
  • 如何为有效号码指定 DCG?

    我正在尝试为有效数字指定 DCG 如下所示 value Number gt valid number Number 基本上检查指定的值是否是数字 它也可能是变量 因此有必要检查 我不知道如何构建这个valid number不过 DCG 谓词
  • F# 和模糊逻辑

    我知道这可能听起来很奇怪 但我想知道 Microsoft Visual F 正在进入的这个新世界中的一件事 这种语言有很多应用 我要学习 关于解析 函数式编程 结构化编程 但是人工智能呢 模糊逻辑有什么应用吗 F 是一种适合模糊逻辑应用程序
  • 根据一个值找到列表内列表的最小值

    我在序言中有这个列表 dublin london 1000 dublin moscow london 5000 我想计算列表的最小值 这样答案应该是 dublin london 1000 这个问题有一些类似的问题序言中列表列表中的最小值 h
  • Prolog 展平列表

    flatten A B R islist A gt flatten A R1 R R1 write A append A R1 R flatten B R1 flatten X X islist 这是我写的代码 但我有奇怪的问题 I get

随机推荐

  • 为什么我的 UILabel 不显示 NSInteger

    我有一个 ViewController 和 GameController 类 它是 NSObject 的子类 视图控制器有一个链接到它的按钮 并触发一个初始化 GameController 类的 IBAction 在 GameControl
  • 剪切背景以露出下面的图层

    有没有办法剪切 div 背景以暴露下面的图层 就像这样 to this 欢迎任何前沿的 CSS 规则 UPDATE 好的 我做了一个示例代码 http jsfiddle net coma 9ae7g 1 http jsfiddle net
  • 创建新文件时,vscode 让我选择一个编辑器

    When creating a new file vscode let me select an editor It hasn t do so and I don t want to choose one because I only us
  • 我应该如何处理 Perl 中不再使用的对象?

    我正在编写一个链接到外部资源的类 其中一种方法是破坏外部资源的删除方法 不应对该对象进行进一步的方法调用 我正在考虑设置一个标志 如果设置了标志 那么就会在所有方法中死亡 但是有没有更好 更简单的方法呢 也许涉及破坏 到目前为止 我真的很喜
  • Android Studio:“libpng 警告:iCCP:无法识别已编辑的已知 sRGB 配置文件”

    我花了几个小时试图解决这个问题 app mergeDebugResources AAPT err 927129865 C Users Will AndroidStudioProjects Splitter2 app build interm
  • 从两个绝对路径获取相对路径

    我有两个绝对文件系统路径 A 和 B 并且我想生成第三个文件系统路径来表示 A 相对于 B 使用案例 管理播放列表的媒体播放器 用户将文件添加到播放列表 新文件路径已添加到播放列表相对于播放列表路径 将来 整个音乐目录 包括播放列表 都会转
  • ANGULAR 2 - 组件共享数据服务

    这真的让我很头疼 我有一个不错的小应用程序 使用 Firebase 和 Angular 2 设置社交登录 一切都应该是实时的 基本上 当用户通过 Facebook 登录时 我希望将他们的个人信息传递到服务并存储为 Observable 并立
  • 如何在Python中的一个图形上绘制多个kdeplot

    我有以下数据 name val G Kittle 4 0 G Kittle 10 0 D Hopkins 3 0 L Fitzgerald 6 0 C Kupp 18 0 R Woods 21 0 N Harry 7 0 S Michel
  • Angular:创建 Angular 项目时出现新错误

    我使用时遇到此错误ng 新项目名称 发现无效的配置文件 angular json 请在运行命令之前删除该文件 我收到此错误 我不知道如何获得解决方案 我卸载了 angular cli 并再次安装 npm clean 缓存也不起作用 我不知道
  • 持续监听TCP端口

    我编写了一个能够通过 TCP 协议从端口接收数据的代码 我每 15 分钟从 ESP8266 接收一次数据 然后 ESP 进入深度睡眠模式 如何改变它才能使其持续工作 我想在 while 循环中创建一个新连接 但它不起作用 My code i
  • 如何在调用任何 url 时提供 ntlm 身份验证?

    我有一个使用 ntlm Windows 集成身份验证 进行身份验证的托管 URL 我在 windows 上使用 java 1 8 URL url new URL someUrl HttpURLConnection con HttpURLCo
  • 如果小程序在浏览器的 JRE 中运行,为什么机器上还需要 JRE?

    Applet 在浏览器的 JRE 中运行 这是否意味着您不必在计算机上安装 JRE 即可运行小程序 浏览器的 JVM is您计算机上安装的 JRE 浏览器通常不会附带自己的浏览器 它们只是使用您系统上已安装的任何浏览器 也许您混淆了 Jav
  • Angular 9 SSR 404 未找到带有状态代码的页面

    我正在使用 Angular 9 和 SSR 现在正在尝试获取 404 页面 它与客户端成功合作 但状态始终为 200 Ok 当我尝试使用 Angular ssr 时 它也显示 200 是状态代码 我的 Angular 路由器已成功传递到 4
  • 如何在Pycharm中暂停程序执行(暂停按钮不起作用)?

    在 Pycharm 5 0 4 中调试我的 Python 3 5 程序时 我试图按下暂停按钮来查找程序挂起的原因 位置 可以在 Visual Studio 中完成 但是 什么也没有发生 暂停按钮不会变成灰色 恢复按钮保持灰色 并且在调试器工
  • 来自 Kafka Producer 的控制台消息过多

    如何控制 Kafka 生产者或消费者的控制台日志记录级别 我在 Scala 中使用 Kafka 0 9 API 每次send on the KafkaProducer被调用时 控制台给出如下输出 这是否表明我没有KafkaProducer设
  • 未报告的异常 java.lang.Exception [重复]

    这个问题在这里已经有答案了 未报告的异常 java lang Exception 必须捕获或声明为抛出 为什么会出现这个问题呢 有什么简单的方法可以帮助解决这个问题吗 我在我的java中应用这个代码 public byte encrypt
  • 类的友元声明中定义的函数名称是否具有链接?

    class A friend void fun 1 根据 dcl meaning general p2 如果声明是友元声明 声明者不bind a name basic link 指出仅names可以有一个链接 当一个名称可以表示与另一个作
  • 确定输入流的大小

    我目前的情况是 我必须读取一个文件并将内容放入InputStream 之后我需要将内容InputStream到一个字节数组中 它需要 据我所知 的大小InputStream 有任何想法吗 根据要求 我将显示我从上传的文件创建的输入流 Inp
  • 我无法将父目录添加到 Git 中的 *safe.directory*

    将 Git 更新为v2 35 2 windows 1我收到以下错误 致命 不安全的存储库 F GitHub my project 由其他人拥有 要为此目录添加例外 请调用 git config global add safe directo
  • 如何确定矩阵的所有给定坐标都是相连的?

    给定一个网格 我如何确定网格的元素是否都在单个区域中 在下面的情况下是正确的 因为矩阵中的每个元素都有一个邻居 示例1 gridneighbours 1 1 1 2 1 3 2 1 2 2 2 3 3 1 4 1 4 2 true 然而在我