【问题标题】:Get n elements from 2D Array at specified coordinates and direction从二维数组中获取指定坐标和方向的 n 个元素
【发布时间】:2017-06-16 14:30:43
【问题描述】:

我有 x,y 坐标和 char 元素的数组。我需要函数来获取指定坐标方向上的 n 个字符列表。我用循环的方式写的:

import Data.Array

exampleArray = array ((1,1),(2,2)) [((1,1),'a'), ((1,2),'b'), ((2,1),'c'), ((2,2),'d')]
--       1   2  
--     +---+---+
--   1 | a | b |
--     +---+---+
--   2 | c | d |
--     +---+---+

f :: Array (Int, Int) Char -> Int -> (Int, Int) -> (Int, Int) -> [Char]
f _ 0 _ _ = []
f arr n (x,y) (dirX, dirY) = (arr ! (y,x)) : f arr (n-1) (x+dirX,y+dirY) (dirX, dirY)

-- ac
list = f exampleArray 2 (1,1) (0,1) -- get 2 chars from array at 1,1 toward E

-- cb
list2 = f exampleArray 2 (1,2) (1,(-1)) -- get 2 chars from array at 1,2 toward NE

它可以工作,但它太慢了,我想知道如何优化它?

【问题讨论】:

  • 您可以使用如下原语重新设计:f arr n s (dx, dy) = take n . map (arr!) . iterate (\(!y, !x) -> (y + dy, x + dx)) . swap $ s。你能写出你的代码运行速度太慢的真正简单的例子吗?
  • 我收到Illegal bang-pattern (use BangPatterns): ! y
  • 我无法提供简单的示例,但请考虑在 gomoku AI 中搜索数千个数组中的模式。如果您修复功能,我将提供两个功能之间的时间差。
  • 使用扩展名BangPatterns避免编译错误。
  • 获得最佳移动需要 17 秒,而使用您的函数则需要 18 秒。

标签: haskell


【解决方案1】:

Array 很慢,所以第一步应该是移植到vector package。使用未装箱变体,因为默认的“装箱”表示为每个值分配堆存储并存储指向它的指针。没有二维向量之类的东西,因此您必须编写代码将坐标对转换为一维向量中的位置。如果这仍然不够快,则使用 unsafeIndex 函数及其相关函数进行访问,它们不会进行边界检查(但不要调用 cannot put down 的函数)。

另见this question

【讨论】:

  • 我一直在寻找优化函数的方法,但是如果将数组更改为未装箱矢量帮助,我会接受您的回答。给我一些时间去做。
  • 我看不到你的函数本质上慢的地方,除了它使用数组,因此有很多未装箱的值。还有一点是,通过一维实现,您的所有移动(N、NE、E 等)都可以用单个偏移量表示,因此您只需每步进行一次加法。
  • 目前在数组中我使用自己的类型,如data Square = Cross | Nought | Empty,所以我不能只使用向量,因为它需要Unbox 实例。您认为创建/派生它会更好还是我应该更改所有函数以处理字符?
  • 我设法用vector-th-unbox 派生了 Unbox 实例并将程序移植到 Vector.Unboxed,但它的运行速度要慢两倍:pastebin.com/7CEWNfFP
  • 不看代码很难说更多。你在编译优化吗?
猜你喜欢
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
  • 2021-08-19
  • 2019-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多