同样的事情在一瞬间冻结或工作

时间:2015-02-22 15:49:01

标签: haskell

下面的代码解决了这个challenge

  

找出给定整数X可以表示为唯一自然数的N次幂之和的方式的数量。

import Control.Monad (guard)
import qualified Data.Map.Strict as Map
import Data.Map ((!),fromList,Map(..),member)

-- depth first search higher order function
depthFirstSearch :: (node -> [node]) -> -- successor node generator
                   (node -> Bool) -> -- is goal checker
                   [node] -> -- starting root nodes
                   [node] -- goal nodes
depthFirstSearch succ goal roots = search' roots
  where search' [] = []
        search' (x:xs) | goal x = x : search' xs
                       | otherwise = search' (succ x ++ xs)


type Degree = Int
type CurrentSum = Int
type CurrentNumber = Int
type Node = (CurrentNumber,CurrentSum)
type Goal = Int

-- generates valid successor nodes
succN :: Goal -> Map Int Int -> Node -> [Node]
succN goal _map (i,sum) = do
  i' <- [(i+1)..goal]
  guard (member i' _map)
  let sum' = sum + _map!i'
  guard (sum' <= goal)
  return (i',sum')
-- checks if the node is the goal
goalN :: Goal -> Node -> Bool
goalN goal (_,sum) = goal == sum

-- counts solutions
solCount :: Degree -> Goal -> Int
solCount d goal =
  let roots = [(i,i^d) | i <- [1..goal], i^d <= goal]
      _map = Map.fromList roots
      nodes = depthFirstSearch (succN goal _map) (goalN goal) roots
      c = length nodes
  in c

奇怪的事情正在发生。它冻结在solCount 10 1000上。如果我在solCount中手动运行ghci,则会按预期冻结

let roots = [(i,i^10) | i <- [1..1000], i^10 <= 1000] -- [(1,1)]
let _map = Map.fromList roots 
let nodes = depthFirstSearch (succN 1000 _map) (goalN 1000) roots
nodes

但是当它被替换为像这样的“相同”的东西时

let nodes = depthFirstSearch (succN 1000 $ Map.fromList [(1,1)]) (goalN 1000) [(1,1)]
nodes

立即打印结果。我不知道为什么它会冻结而不会冻结。

1 个答案:

答案 0 :(得分:3)

假设:

let roots = [(i,i^10) | i <- [1..1000], i^10 <= 1000] -- [(1,1)]
由于溢出,Ints不正确。您可以通过使用整数和转换执行比较来解决此问题:

let roots = [(b,b^10) | a <- [(1::Integer)..1000], a^1000 <= 1000, let b = fromInteger a ]

您可能没有发现此问题,因为ghci默认为REPL中的整数,但代码roots中的类型为[Int]