【发布时间】:2023-03-19 15:15:01
【问题描述】:
我对 Haskell 比较陌生,但我正在尝试通过阅读和尝试解决 Project Euler 中的问题来学习。我目前正在尝试实现一个函数,该函数采用无限的整数列表并返回所述列表中元素的成对和的有序列表。我真的在寻找针对我所面临的具体问题的解决方案,而不是关于不同策略或方法的建议,但这些也是受欢迎的,因为作为编码人员并不意味着知道如何实施策略,而是选择最好的可用的策略。
我的方法依赖于遍历无限生成器的无限列表并按顺序检索元素,其中有几个数学属性对实现我的解决方案很有用。
如果我试图获得自然数的成对和的序列,例如,这将是我的代码:
myList :: [Integer]
myList = [1..]
myGens :: [[Integer]]
myGens = gens myList
where
gens = \xs -> map (\x -> [x+y|y<-(dropWhile (<x) xs)]) xs
无论使用的数字集如何,只要它是排序的,以下条件都成立:
- ∀ i ≥ 0,
head (gens xs !! i) == 2*(myList !! i) - ∀ i,j,k ≥ 0, l > 0,
(((gens xs) !! i) !! j) < (((gens xs) !! i+k) !! j+l)
第二种情况的特殊情况是:
- ∀ i,j ≥ 0,
(((gens xs) !! i) !! j) < (((gens xs) !! i+1) !! j) - ∀ i,j ≥ 0, k > 0,
(((gens xs) !! i) !! j) < (((gens xs) !! i+k) !! j)
这是我要修改的特定代码:
stride :: [Integer] -> [Int] -> [[Integer]] -> [Integer]
stride xs cs xss = x : stride xs counts streams
where
(x,i) = step xs cs xss
counts = inc i cs
streams = chop i xss
step :: [Integer] -> [Int] -> [[Integer]] -> (Integer,Int)
step xs cs xss = pace xs (defer cs xss)
pace :: [Integer] -> [(Integer,Int)] -> (Integer,Int)
pace hs xs@((x,i):xt) = minim (x,i) hs xt
where
minim :: (Integer,Int) -> [Integer] -> [(Integer,Int)] -> (Integer,Int)
minim m _ [] = m
minim m@(g,i) hs (y@(h,n):ynt) | g > h && 2*(hs !! n) > h = y
| g > h = minim y hs ynt
| 2*(hs !! n) > g = m
| otherwise = minim m hs ynt
defer :: [Int] -> [[a]] -> [(a,Int)]
defer cs xss = (infer (zip cs (zip (map head xss) [0..])))
infer :: [(Int,(a,Int))] -> [(a,Int)]
infer [] = []
infer ((c,xi):xis) | c == 0 = xi:[]
| otherwise = xi:(infer (dropWhile (\(p,(q,r)) -> p>=c) xis))
我正在使用的有问题的集合具有多个不同对产生相同总和的属性。我想要一种有效的方法来一次处理所有重复元素,以避免增加计算所有成对总和的成本,因为如果 M 是重复的数量,它需要 M 更多的测试。
有人有什么建议吗?
编辑:
我对代码进行了一些更改,独立于建议的内容,希望对我的原始代码、修改后的代码和迄今为止的提案的相对效率提供反馈。
stride :: [Integer] -> [Int] -> [[Integer]] -> [Integer]
stride xs cs xss = x : stride xs counts streams
where
(x,is) = step xs cs xss
counts = foldr (\i -> inc i) cs is
streams = foldr (\i -> chop i) xss is
step :: [Integer] -> [Int] -> [[Integer]] -> (Integer,[Int])
step xs cs xss = pace xs (defer cs xss)
pace :: [Integer] -> [(Integer,Int)] -> (Integer,[Int])
pace hs xs@((x,i):xt) = minim (x,(i:[])) hs xt
where
minim :: (Integer,[Int]) -> [Integer] -> [(Integer,Int)] -> (Integer,[Int])
minim m _ [] = m
minim m@(g,is@(i:_)) hs (y@(h,n):ynt) | g > h && 2*(hs !! n) > h = (h,[n])
| g > h = minim (h,[n]) hs ynt
| g == h && 2*(hs !! n) > h = (g,n:is)
| g == h = minim (g,n:is) hs ynt
| g < h && 2*(hs !! n) > g = m
| g < h = minim m hs ynt
另外,我省略了inc 和chop 的代码:
alter :: (a->a) -> Int -> [a] -> [a]
alter = \f -> \n -> \xs -> (take (n) xs) ++ [f (xs !! n)] ++ (drop (n+1) xs)
inc :: Int -> [Int] -> [Int]
inc = alter (1+)
chop :: Int -> [[a]] -> [[a]]
chop = alter (tail)
【问题讨论】:
标签: algorithm list haskell duplicates generator