Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 在这个动态编程示例中,如何使fromList变懒?_Haskell_Dynamic Programming_Lazy Evaluation_Memoization_Continuations - Fatal编程技术网

Haskell 在这个动态编程示例中,如何使fromList变懒?

Haskell 在这个动态编程示例中,如何使fromList变懒?,haskell,dynamic-programming,lazy-evaluation,memoization,continuations,Haskell,Dynamic Programming,Lazy Evaluation,Memoization,Continuations,上述情况并不完全正确。必须记住,所有的fs都是独立的 go x f y = (x + y) : f x go x f y = (x + y) : f x go x f y = (x + y) : f x 此外,为了清晰起见,将lambda分开也应该是有指导意义的 go x f'' y = (x + y) : f'' x go x f' y = (x + y) : f' x go x f y = (x + y) : f x 现在折叠从顶部开始。最顶端的语句的计算结果为 go x f'' = \

上述情况并不完全正确。必须记住,所有的
f
s都是独立的

go x f y = (x + y) : f x
go x f y = (x + y) : f x
go x f y = (x + y) : f x
此外,为了清晰起见,将lambda分开也应该是有指导意义的

go x f'' y = (x + y) : f'' x
go x f' y = (x + y) : f' x
go x f y = (x + y) : f x
现在折叠从顶部开始。最顶端的语句的计算结果为

go x f'' = \y -> (x + y) : f'' x
go x f' = \y -> (x + y) : f' x
go x f = \y -> (x + y) : f x
这减少到:

go 3 (\_ -> []) = \y -> (3 + y) : (\_ -> []) 3
go 2 (\y -> (3 + y) : []) = \y -> (2 + y) : (\y -> (3 + y) : []) 2
go 1 (\y -> (2 + y) : 5 : []) = \y -> (1 + y) : (\y -> (2 + y) : 5 : []) 1
结果是上面未完成的lambda。现在,fold计算第二个语句

go 3 (\_ -> []) = (\y -> (3 + y) : [])
go 2 (\y -> (3 + y) : []) = (\y -> (2 + y) : 5 : [])
go x f'' = \y -> (x + y) : f'' (2*y+1)
go x f' = \y -> (x + y) : f' (2*y+1)
go x f = \y -> (x + y) : f (2*y+1)
这减少到:

go 3 (\_ -> []) = \y -> (3 + y) : (\_ -> []) 3
go 2 (\y -> (3 + y) : []) = \y -> (2 + y) : (\y -> (3 + y) : []) 2
go 1 (\y -> (2 + y) : 5 : []) = \y -> (1 + y) : (\y -> (2 + y) : 5 : []) 1
折叠到最后一句话

go 3 (\_ -> []) = (\y -> (3 + y) : [])
go 2 (\y -> (3 + y) : []) = (\y -> (2 + y) : 5 : [])
go x f'' = \y -> (x + y) : f'' (2*y+1)
go x f' = \y -> (x + y) : f' (2*y+1)
go x f = \y -> (x + y) : f (2*y+1)
这减少到:

go 3 (\_ -> []) = \y -> (3 + y) : (\_ -> []) 3
go 2 (\y -> (3 + y) : []) = \y -> (2 + y) : (\y -> (3 + y) : []) 2
go 1 (\y -> (2 + y) : 5 : []) = \y -> (1 + y) : (\y -> (2 + y) : 5 : []) 1
将应用折叠外的0,并将最终lambda减小为

go 1 (\y -> (2 + y) : 5 : []) = \y -> (1 + y) : 3 : 5 : []
这只是开始。当
fx
替换为
fy
时,情况变得更加有趣

这里有一个与前一个类似的程序

1 : 3 : 5 : []
最重要的声明

go 3 (\_ -> []) = (\y -> (3 + y) : [])
go 2 (\y -> (3 + y) : []) = (\y -> (2 + y) : 5 : [])
go x f'' = \y -> (x + y) : f'' (2*y+1)
go x f' = \y -> (x + y) : f' (2*y+1)
go x f = \y -> (x + y) : f (2*y+1)
中间声明:

go 3 (\_ -> []) = \y -> (3 + y) : (\_ -> []) (2*y+1)
go 2 (\y -> (3 + y) : (\_ -> []) (2*y+1)) = \y -> (2 + y) : (\y -> (3 + y) : (\_ -> []) (2*y+1)) (2*y+1)
最后一句话:

go 3 (\_ -> []) = \y -> (3 + y) : (\_ -> []) (2*y+1)
go 2 (\y -> (3 + y) : (\_ -> []) (2*y+1)) = \y -> (2 + y) : (\y -> (3 + y) : (\_ -> []) (2*y+1)) (2*y+1)
注意表达式是如何建立的,因为不能应用
y
s。只有在插入0之后,才能计算整个表达式

go 1 (\y -> (2 + y) : (\y -> (3 + y) : (\_ -> []) (2*y+1)) (2*y+1)) = \y -> (1 + y) : (\y -> (2 + y) : (\y -> (3 + y) : (\_ -> []) (2*y+1)) (2*y+1)) 2*y+1
由于评估的顺序,有一个累积

编辑:所以

(\y -> (1 + y) : (\y -> (2 + y) : (\y -> (3 + y) : (\_ -> []) (2*y+1)) (2*y+1)) 2*y+1) 1

2 : (\y -> (2 + y) : (\y -> (3 + y) : (\_ -> []) (2*y+1)) (2*y+1)) 3

2 : 5 : (\y -> (3 + y) : (\_ -> []) (2*y+1)) 7

2 : 5 : 10 : (\_ -> []) 15

2 : 5 : 10 : []
go(candy,score)fcs=(candy',score):fccandy'score
其中candy'=最大candy$如果s<分数,则c+1,否则1
事实上,在每次迭代中,上面的代码在列表中传递了3次

首先,foldr必须在列表的后面,然后才能开始。然后,由于
candi'
依赖于
s
c
变量,这些变量不能立即应用,因此需要建立延续性,如最后一个示例中所示

然后,当两个
0
0
在折叠结束时输入时,整个过程才得到评估

go 1 (\y -> (2 + y) : (\y -> (3 + y) : (\_ -> []) (2*y+1)) (2*y+1)) = \y -> (1 + y) : (\y -> (2 + y) : (\y -> (3 + y) : (\_ -> []) (2*y+1)) (2*y+1)) 2*y+1

这有点难以解释。

您所链接的问题有一个干净的Haskell解决方案,使用右折叠。换句话说,通过使用更实用的样式,您可以跳过对lazy fromList、Memonization和所有这些的担忧

这样做的目的是维护一个
(candy,score)
对的列表,其中
candy
最初对所有人都是零(
在下面的代码中重复0
)。然后从左向右移动一次,如果此项得分超过之前的值,则增加
candy
值:

go (candy, score) f c s = (candy', score): f candy' score
    where candy' = max candy $ if s < score then c + 1 else 1
--s是分数,c是之前那个家伙的糖果
--如果s
再朝另一个方向做同样的事情:

-- s is the score and c is the candy of the guy before
-- if s < score then this guy should get at least c + 1 candies
candy' = max candy $ if s < score then c + 1 else 1
import Control.Monad(复制项)
导入控件。应用程序(())
求解::[Int]->Int
求解=求和。地图fst。环颠倒环拉链(重复0)
哪里
循环cs=foldr go(\\\\\>[])cs 0
去(糖果,得分)f c s=(糖果,得分):f糖果,得分
其中candy'=最大candy$如果s<分数,则c+1,否则1
main=do
n>=打印

这将线性执行,并通过HackerRank上的所有测试。

您所链接的问题有一个干净的Haskell解决方案,使用右折叠。换句话说,通过使用更实用的样式,您可以跳过对lazy fromList、Memonization和所有这些的担忧

这样做的目的是维护一个
(candy,score)
对的列表,其中
candy
最初对所有人都是零(
在下面的代码中重复0
)。然后从左向右移动一次,如果此项得分超过之前的值,则增加
candy
值:

go (candy, score) f c s = (candy', score): f candy' score
    where candy' = max candy $ if s < score then c + 1 else 1
--s是分数,c是之前那个家伙的糖果
--如果s
再朝另一个方向做同样的事情:

-- s is the score and c is the candy of the guy before
-- if s < score then this guy should get at least c + 1 candies
candy' = max candy $ if s < score then c + 1 else 1
import Control.Monad(复制项)
导入控件。应用程序(())
求解::[Int]->Int
求解=求和。地图fst。环颠倒环拉链(重复0)
哪里
循环cs=foldr go(\\\\\>[])cs 0
去(糖果,得分)f c s=(糖果,得分):f糖果,得分
其中candy'=最大candy$如果s<分数,则c+1,否则1
main=do
n>=打印

它的性能是线性的,并且通过了HackerRank上的所有测试。

好吧,关于我自己在顶部的问题,可能让事情变得懒惰的方法是只使用一个列表(列表列表列表或列表向量)。上面不可能让事情变得懒惰的原因是,映射类型在值上是懒惰的,在键上是严格的

更重要的是,我的分析,褶皱基本上是做两次通过是完全正确的。这些构建的延续在反向执行时的方式一开始完全让我感到困惑,但我已经修改了@behzad.nouri代码,使其只处理一个循环

import Control.Monad (replicateM)
import Control.Applicative ((<$>))

solve :: [Int] -> Int
solve = sum . map fst . loop . reverse . loop . zip  (repeat 0)
    where
    loop cs = foldr go (\_ _ -> []) cs 0 0
    go (candy, score) f c s = (candy', score): f candy' score
        where candy' = max candy $ if s < score then c + 1 else 1

main = do
    n <- read <$> getLine
    solve . fmap read <$> replicateM n getLine >>= print
modulemain其中
导入控制.Monad(复制项)
导入控件。应用程序(())
导入调试跟踪
求解::[Int]->Int
求解=求和。环
哪里
循环::[Int]->[Int]
循环=(\(\,x)->x0)。foldr go(0,0,\\\\\\>[]))
围棋:Int->(Int,Int,Int->Int->[Int])->(Int,Int,Int->Int->[Int])
围棋得分(坎迪普、得分、f)=
允许
candyP'=如果得分p
允许
candy'=最大candyP'$如果scoreN=打印

以上内容通过了所有测试,没有问题,这是上述分析正确性的有力证明。

好吧,关于我自己在顶部的问题,可能让事情变得懒惰的方法就是只使用一个列表(列表列表列表或列表向量)上面不可能使其变为惰性的原因是,映射类型在值中是惰性的,在键中是严格的

更重要的是,我的分析,褶皱基本上是做两次通过是完全正确的。那些建立起来的延续方式正在被改变