下面的代码解决了这个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
立即打印结果。我不知道为什么它会冻结而不会冻结。
答案 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]
。