Haskell实现:基于两点获取所有(Int, Int)型直线点的函数
生成两点间直线上的所有整数点的Haskell函数
嘿,我明白你被这个问题困扰很久了,咱们来一步步解决它。要获取两个(Int, Int)点连线上的所有整数坐标点,核心思路是利用**最大公约数(gcd)**来确定最小步长,这样就能遍历所有不遗漏的整数点。
实现代码
linePoints :: (Int, Int) -> (Int, Int) -> [(Int, Int)] linePoints p1@(x1, y1) p2@(x2, y2) | p1 == p2 = [p1] -- 两点相同的特殊情况 | otherwise = take (g + 1) $ iterate step p1 where dx = x2 - x1 -- x方向总位移 dy = y2 - y1 -- y方向总位移 g = gcd (abs dx) (abs dy) -- 位移的最大公约数 step (x, y) = (x + dx `div` g, y + dy `div` g) -- 每一步的移动量
代码解释
- 特殊情况处理:如果传入的两个点完全相同,直接返回只包含该点的列表,避免无效计算。
- 计算位移与步长:
dx和dy分别是两点在x、y方向的总距离,正负号代表移动方向。g是dx和dy绝对值的最大公约数,它决定了直线上整数点的总数(g + 1个,包含起点和终点)。step函数定义了每次移动的最小单位:把总位移除以g,保证每一步移动后都落在整数坐标上,且不会跳过任何直线上的整数点。
- 生成点序列:用
iterate生成从起点开始的无限点序列,再用take (g + 1)截取到终点为止的所有点,刚好覆盖整条直线上的所有整数点。
示例用法
-- 斜线方向的直线点 linePoints (0,0) (3,6) -- 输出: [(0,0),(1,2),(2,4),(3,6)] -- 垂直直线的情况 linePoints (5,5) (5,10) -- 输出: [(5,5),(5,6),(5,7),(5,8),(5,9),(5,10)] -- 反向输入两点的情况 linePoints (2,3) (0,0) -- 输出: [(2,3),(0,0)]
这个函数能完美覆盖所有整数点的情况,不管是水平、垂直还是任意斜线方向的直线都适用。
内容的提问来源于stack exchange,提问作者John merc
相关产品推荐
相关产品推荐

