Haskell 从指定坐标和方向的二维数组中获取n个元素
我有x,y坐标和char元素的数组。我需要一个函数来获取指定坐标方向上n个字符的列表。我用循环的方式写的:Haskell 从指定坐标和方向的二维数组中获取n个元素,haskell,Haskell,我有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 | --
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
它可以工作,但太慢了,我想知道如何优化它
阵列
速度很慢,因此您的第一步应该是移植到。使用unbox变量,因为默认的“boxed”表示为每个值分配堆存储并存储指向它的指针。没有二维向量这样的东西,所以您必须编写代码将坐标对转换为一维向量中的位置。如果仍然不够快,则使用unsafeIndex
函数及其相关函数进行访问,这些函数不进行边界检查(但不调用您所调用的函数)
另请参见。您可以使用如下原语重新设计:
f arr n s(dx,dy)=take n。地图(啊!)。迭代(\(!y,!x)->(y+dy,x+dx))。交换$s
。你能在代码运行太慢的情况下编写一个真正简单的例子吗?我得到了非法的bang模式(使用bang模式):!我不能提供简单的例子,但是考虑GOOKU-AI中成千上万个数组中的搜索模式。如果您修复了函数,我将提供两个函数之间的时间差。使用扩展名BangPatterns
以避免编译错误。获得最佳移动需要17秒,使用您的函数需要18秒。我正在寻找优化函数的方法,但如果将数组更改为unbox vector help,我将接受您的答案。给我一些时间,我看不出你的函数本质上有什么慢的地方,除了它使用数组,因此有很多未绑定的值。另一点是,通过使用一维实现,所有移动(N、NE、E等)都可以用一个偏移量表示,因此每一步只需进行一次加法。目前在数组中,我使用自己的类型,如data Square=Cross | Nought | Empty
,因此我不能只使用vector,因为它需要Unbox
实例。你认为创建/派生它会更好,还是我应该更改所有函数来处理chars?我使用vector-th-Unbox
和port-program-to-vector.Unbox成功地派生了Unbox实例,但它运行速度慢了两倍:不看代码很难说更多。您是否在进行优化编译?