Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/209.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 项目15-最后一次尝试_Haskell - Fatal编程技术网

Haskell 项目15-最后一次尝试

Haskell 项目15-最后一次尝试,haskell,Haskell,在过去的三天里,我一直在努力解决哈斯克尔的问题 以下是我目前的状态: import Data.Map as Map data Coord = Coord Int Int deriving (Show, Ord, Eq) corner :: Coord -> Bool corner (Coord x y) = (x == 0) && (y == 0) side :: Coord -> Bool side (Coord x y) = (x == 0) || (y

在过去的三天里,我一直在努力解决哈斯克尔的问题

以下是我目前的状态:

import Data.Map as Map

data Coord = Coord Int Int deriving (Show, Ord, Eq)

corner :: Coord -> Bool 
corner (Coord x y) = (x == 0) && (y == 0)

side :: Coord -> Bool
side (Coord x y) = (x == 0) || (y == 0)

move_right :: Coord -> Coord
move_right (Coord x y) = Coord (x - 1) y

move_down :: Coord -> Coord
move_down (Coord x y) = Coord x (y - 1)

calculation :: Coord -> Integer
calculation coord 
           | corner coord = 0
           | side coord = 1 
           | otherwise = (calculation (move_right coord)) + (calculation (move_down coord)) 

problem_15 :: Int -> Integer
problem_15 size =
           calculation (Coord size size)
它工作得很好,但如果“n”变大,则速度非常慢

据我所知,我可以使用动态编程和哈希表(例如Data.Map)来缓存计算值

我试过,但没有成功。我试过了,但下一个错误比上一个更可怕。所以我请求您的帮助:如何缓存已计算的值


我知道这个问题的数学解(Pascal三角形),但我对算法解感兴趣。

这个问题更适合二维数组缓存,因为输入值的范围是有界的

import Control.Applicative
import Data.Array

data Coord = Coord Int Int deriving (Show, Ord, Eq, Ix)

calculation :: Coord -> Integer
calculation coord@(Coord maxX maxY) = cache ! coord where
    cache = listArray bounds $ map calculate coords
    calculate coord
        | corner coord = 0
        | side coord   = 1
        | otherwise    = cache ! move_right coord + cache ! move_down coord

    zero  = Coord 0 0
    bounds = (zero, coord)
    coords = Coord <$> [0..maxX] <*> [0..maxY]
导入控件。应用程序
导入数据。数组
数据坐标=坐标积分推导(显示、Ord、Eq、Ix)
计算::坐标->整数
计算坐标@(坐标maxX maxY)=缓存!坐标在哪里
cache=listArray边界$map计算坐标
计算坐标
|角坐标=0
|侧坐标=1
|否则=缓存!向右移动坐标+缓存!向下移动坐标
零=坐标0
边界=(零,坐标)
coords=Coord[0..maxX][0..maxY]
我们将
派生Ix
添加到Coord中,以便直接将其用作数组索引,并且在计算中,我们使用
Coord 0 0
的下限和
Coord
的上限初始化二维数组
cache
。然后,我们只引用缓存中的值,而不是递归调用
calculation

现在,我们可以相对快速地计算出较大的值


*Main>问题15 1000
2048151626989489714335162502980825044396424887981397033820382637671748186202083755828932994182610206201464766319998023692415481798004524792018047549769261578563012896634320647148511523952516512277685886115395462561479073786684641544445336176137700738556738145896300713065104559595144798887462063687185145518285511731662762536637730846829322553890497438594814317550307837964443708100851637248274627914170166198837648408435414308177859470377465651884755146807496946749238030331018187232980096685674585602525499101181135253534658887941966653674904511306110096311906270342502293155911108976733963991149120

既然您已经知道正确(高效)的解决方案,我不会为您破坏任何东西:

您可以使用数组(这里非常合适,因为域是一个矩形)

然后用它来运行

evalState (calculation target) Map.empty

或者你可以用一个关于黑客的回忆录软件包,我记得这是我脑海中的一个,但是还有更多的,可能还有更好的。(当然还有更多可能的方法。)

使用动态规划和简单数组。那样的话,复杂性就是二次的。谢谢。这个语法是什么意思:coord@(coord maxX maxY)@demas它是一个“as模式”,将整个值绑定到
coord
,并将部分(这里的坐标)绑定到括号中模式的适当部分。@shang:所需的结果不会在
缓存中!零
?不是
缓存!协调
始终
0
?@gspr:不,相反<代码>缓存!零==计算(坐标0)==0@shang:哦,对了,我的错!我的(心理)索引与你的相反。这种数组解决方案存在深度递归问题,导致非常大的参数数出现堆栈溢出(当然不适用于原始的
20
)。我曾经尝试过一个
seq
s序列,其步长取决于实现。也许还有别的办法吗?
import qualified Data.Map as Map
import Control.Monad.State.Strict

type Path = State (Map Coord Integer)

calculation :: Coord -> Path Integer
calculation coord = do
    mb_count <- gets (Map.lookup coord)
    case mb_count of
      Just count -> return count
      Nothing
          | corner coord -> modify (Map.insert coord 0) >> return 0 -- should be 1, IMO
          | side coord -> modify (Map.insert coord 1) >> return 1
          | otherwise -> do
              above <- calculation (move_down coord)
              left <- calculation (move_right coord)
              let count = above + left
              modify (Map.insert coord count)
              return count
evalState (calculation target) Map.empty