Partition an integer x into n primes: Difference between revisions

Content added Content deleted
(Added Prolog Solution)
m (→‎{{header|Haskell}}: Used Data.Numbers.Primes, tidied.)
Line 608: Line 608:


=={{header|Haskell}}==
=={{header|Haskell}}==
<lang haskell>{-# LANGUAGE TupleSections #-}
<lang haskell>import Data.Bool (bool)
import Data.Numbers.Primes

import Data.List (delete, intercalate)
import Data.List (delete, intercalate)


-- PRIME PARTITIONS ----------------------------------------------------------
-------------------- PRIME PARTITIONS ---------------------
partition :: Int -> Int -> [Int]
partition :: Int -> Int -> [Int]
partition x n
partition x n
| n <= 1 =
| n <= 1 =
[ x
[ x
| last ps == x ]
| x == last ps ]
| otherwise = partition_ ps x n
| otherwise = go ps x n
where
where
ps = takeWhile (<= x) primes
ps = takeWhile (<= x) primes
partition_ ps_ x 1 =
go ps_ x 1 =
[ x
[ x
| x `elem` ps_ ]
| x `elem` ps_ ]
partition_ ps_ x n =
go ps_ x n =
let found = foldMap partitionsFound ps_
let found = foldMap partitionsFound ps_
in nullOr found [] (head found)
in bool (head found) [] (null found)
where
where
partitionsFound p =
partitionsFound p =
let r = x - p
let r = x - p
rs = partition_ (delete p (takeWhile (<= r) ps_)) r (n - 1)
rs = go (delete p (takeWhile (<= r) ps_)) r (n - 1)
in nullOr rs [] [p : rs]
in bool [p : rs] [] (null rs)


-- TEST ----------------------------------------------------------------------
-------------------------- TEST ---------------------------
main :: IO ()
main :: IO ()
main =
main =
mapM_ putStrLn $
mapM_ putStrLn $
(\(x, n) ->
(\(x, n) ->
(intercalate
intercalate
" -> "
" -> "
[ justifyLeft 9 ' ' (show (x, n))
[ justifyLeft 9 ' ' (show (x, n))
, let xs = partition x n
, let xs = partition x n
in nullOr xs "(no solution)" (intercalate "+" (show <$> xs))
in bool (intercalate "+" (show <$> xs)) "(no solution)" (null xs)
])) <$>
]) <$>
concat
concat
[ [(99809, 1), (18, 2), (19, 3), (20, 4), (2017, 24)]
[ [(99809, 1), (18, 2), (19, 3), (20, 4), (2017, 24)]
, (22699, ) <$> [1 .. 4]
, (,) 22699 <$> [1 .. 4]
, [(40355, 3)]
, [(40355, 3)]
]
]


-- GENERIC --------------------------------------------------------------------
------------------------- GENERIC -------------------------
justifyLeft :: Int -> Char -> String -> String
justifyLeft :: Int -> Char -> String -> String
justifyLeft n c s = take n (s ++ replicate n c)
justifyLeft n c s = take n (s ++ replicate n c)</lang>

nullOr
:: Foldable t1
=> t1 a -> t -> t -> t
nullOr expression nullValue orValue =
if null expression
then nullValue
else orValue

primes :: [Int]
primes =
2 :
pruned
[3 ..]
(listUnion
[ (p *) <$> [p ..]
| p <- primes ])
where
pruned :: [Int] -> [Int] -> [Int]
pruned (x:xs) (y:ys)
| x < y = x : pruned xs (y : ys)
| x == y = pruned xs ys
| x > y = pruned (x : xs) ys
listUnion :: [[Int]] -> [Int]
listUnion = foldr union []
where
union (x:xs) ys = x : union_ xs ys
union_ (x:xs) (y:ys)
| x < y = x : union_ xs (y : ys)
| x == y = x : union_ xs ys
| x > y = y : union_ (x : xs) ys</lang>
{{Out}}
{{Out}}
<pre>(99809,1) -> 99809
<pre>(99809,1) -> 99809