Problem 78 (two solutions ― 78 uses recursion and takes too long, 78_alt uses a recursive function for the partition function that relies on generalized pentagonal numbers); Problem 79 done by hand.
This commit is contained in:
parent
29716fee83
commit
546d8f5ffe
|
@ -0,0 +1,30 @@
|
||||||
|
import qualified Data.IntMap.Strict as M
|
||||||
|
|
||||||
|
filterSum :: Int -> M.IntMap Int -> Int
|
||||||
|
filterSum n subMap =
|
||||||
|
let filterMap = M.filterWithKey (\k _ -> k <= n) subMap
|
||||||
|
in M.foldr (+) 0 filterMap
|
||||||
|
|
||||||
|
getSubmap :: Int -> M.IntMap (M.IntMap Int) -> M.IntMap Int
|
||||||
|
getSubmap k numMap = M.findWithDefault undefined k numMap
|
||||||
|
|
||||||
|
insertSubmap :: Int -> M.IntMap (M.IntMap Int) -> M.IntMap (M.IntMap Int)
|
||||||
|
insertSubmap n numMap=
|
||||||
|
let getFilterSumInsert k subMap = M.insert k (filterSum k (getSubmap (n-k) numMap)) subMap
|
||||||
|
subMap = foldr getFilterSumInsert M.empty [n, n-1..1]
|
||||||
|
in M.insert n subMap numMap
|
||||||
|
|
||||||
|
addToList :: (M.IntMap (M.IntMap Int), (Int, Int)) -> Int -> (M.IntMap (M.IntMap Int), (Int, Int))
|
||||||
|
addToList (currMap, _) n =
|
||||||
|
let nextMap = insertSubmap n currMap
|
||||||
|
nextVal = filterSum n $ getSubmap n $ nextMap
|
||||||
|
in (nextMap, (n, nextVal))
|
||||||
|
|
||||||
|
createNummap :: [(M.IntMap (M.IntMap Int), (Int, Int))]
|
||||||
|
createNummap =
|
||||||
|
let initialMap = M.fromList [(0, M.fromList [(0, 1)])]
|
||||||
|
in scanl addToList (initialMap, (1, 1)) [1..]
|
||||||
|
|
||||||
|
main = print $
|
||||||
|
let (_, finalVal) = last $ takeWhile (\(_, (_, val)) -> val `mod` 1000000 /= 0) $ createNummap
|
||||||
|
in finalVal
|
|
@ -0,0 +1,25 @@
|
||||||
|
import qualified Data.IntMap.Strict as M
|
||||||
|
|
||||||
|
type Map = M.IntMap Integer
|
||||||
|
type Sign = Integer
|
||||||
|
|
||||||
|
getOrFail :: Int -> Map -> Integer
|
||||||
|
getOrFail n m = M.findWithDefault undefined n m
|
||||||
|
|
||||||
|
pentNumsSign :: [(Int, Sign)]
|
||||||
|
pentNumsSign = map (\n -> ((3 * n * n - n) `div` 2, if (even ((abs n) - 1)) then 1 else -1)) $ concat $ map (\n -> [n, -n]) [1..]
|
||||||
|
|
||||||
|
partition :: Int -> Map -> Map
|
||||||
|
partition n m =
|
||||||
|
let part = sum $ map (\(p, sgn) -> sgn * (getOrFail (n-p) m)) $ takeWhile (\(p, sgn) -> p <= n) pentNumsSign
|
||||||
|
in M.insert n part m
|
||||||
|
|
||||||
|
findPartition :: Int -> Map -> Int
|
||||||
|
findPartition n m =
|
||||||
|
let newM = partition n m
|
||||||
|
val = getOrFail n newM
|
||||||
|
in if val `mod` 1000000 == 0
|
||||||
|
then n
|
||||||
|
else findPartition (n+1) newM
|
||||||
|
|
||||||
|
main = print $ findPartition 1 $ M.fromList [(0, 1)]
|
|
@ -0,0 +1,9 @@
|
||||||
|
Did this one by hand: 73162890
|
||||||
|
|
||||||
|
Algorithm:
|
||||||
|
For each three-digit sequence jkl,
|
||||||
|
If there's no path from j to k or k to l,
|
||||||
|
Draw such a directed edge from j to k or k to l
|
||||||
|
If there's more than one path from any m to n
|
||||||
|
Remove all paths except for the longest
|
||||||
|
The result should be a linear acyclic chain
|
Loading…
Reference in New Issue