Prolog列表问题咨询及同行坐标列表提取实现求助
提取Prolog中同一行的坐标列表
看起来你已经在搭建棋盘相关的Prolog逻辑(比如胜利条件判断),现在想要实现提取同一行的坐标列表对吧?我来帮你梳理几种可行的实现方式,结合你现有的代码逻辑来适配。
核心思路:利用你的line/2谓词筛选坐标
你已经定义了line/2来判断两个坐标是否在同一行,我们可以基于这个谓词,结合Prolog的内置高阶谓词或者递归,快速实现坐标筛选。
方式1:用include/3快速筛选指定行的坐标
include/3是Prolog内置的高阶谓词,专门用来从列表中筛选出所有满足指定条件的元素,非常适合你的需求:
% 提取指定行号的所有坐标 same_row_coords(TargetRow, OriginalCoords, SameRowCoords) :- include(line((TargetRow, _)), OriginalCoords, SameRowCoords).
解释:
line((TargetRow, _), Coord)会调用你已有的line/2谓词,判断Coord是否和(TargetRow, _)在同一行(也就是Coord的第一个元素等于TargetRow)。include/3会遍历OriginalCoords,把所有满足这个条件的坐标收集到SameRowCoords中。
方式2:递归实现(如果你不想用内置高阶谓词)
如果你更倾向于手动递归实现,也可以写一个递归谓词来遍历列表筛选:
% 递归版本:提取指定行的坐标 same_row_coords_rec(_, [], []). same_row_coords_rec(TargetRow, [(Row, Col)|Rest], [(Row, Col)|FilteredRest]) :- Row = TargetRow, % 当前坐标在目标行,保留 same_row_coords_rec(TargetRow, Rest, FilteredRest). same_row_coords_rec(TargetRow, [(Row, Col)|Rest], FilteredRest) :- Row \= TargetRow, % 当前坐标不在目标行,跳过 same_row_coords_rec(TargetRow, Rest, FilteredRest).
方式3:按行分组所有坐标
如果你的需求是把整个坐标列表按行号分组(比如把所有行1的坐标放一组,行2的放另一组),可以用group_pairs_by_key/2来实现:
% 按行分组坐标列表,返回形如 [(行号, [该行列坐标列表]), ...] 的结构 group_coords_by_row(OriginalCoords, GroupedByRow) :- % 先把每个坐标转换成 (行号, 坐标) 的键值对 maplist(coord_to_row_pair, OriginalCoords, RowKeyValuePairs), % 按行号分组 group_pairs_by_key(RowKeyValuePairs, GroupedByRow). % 辅助谓词:将坐标 (Row, Col) 转换为 (Row, (Row, Col)) 的键值对 coord_to_row_pair((Row, Col), (Row, (Row, Col))).
测试示例
假设你有一个坐标列表:
test_coords([(1,1), (1,2), (1,3), (2,1), (2,2), (3,1)]).
查询提取行1的坐标:
?- test_coords(Coords), same_row_coords(1, Coords, Result). Result = [(1,1), (1,2), (1,3)].查询按行分组的结果:
?- test_coords(Coords), group_coords_by_row(Coords, Grouped). Grouped = [(1, [(1,1), (1,2), (1,3)]), (2, [(2,1), (2,2)]), (3, [(3,1)])].
关于你尝试的select/3
select/3的作用是从列表中选出单个元素并返回剩余列表,适合单次选择场景。如果要提取所有符合条件的元素,include/3或者递归遍历会更高效简洁,不需要多次调用select/3。
内容的提问来源于stack exchange,提问作者Adnane Mounassib
相关产品推荐
相关产品推荐

