RosettaCodeData/Task/Josephus-problem/Haskell/josephus-problem-1.hs

41 lines
1.3 KiB
Haskell

import Data.List ((\\))
import System.Environment (getArgs)
prisoners :: Int -> [Int]
prisoners n = [0 .. n - 1]
counter :: Int -> [Int]
counter k = cycle [k, k-1 .. 1]
killList :: [Int] -> [Int] -> ([Int], [Int], [Int])
killList xs cs = (killed, survivors, newCs)
where
(killed, newCs) = kill xs cs []
survivors = xs \\ killed
kill [] cs rs = (rs, cs)
kill (x:xs) (c:cs) rs
| c == 1 =
let ts = rs ++ [x]
in kill xs cs ts
| otherwise =
kill xs cs rs
killRecursive :: [Int] -> [Int] -> Int -> ([Int], [Int])
killRecursive xs cs m = killR ([], xs, cs)
where
killR (killed, remaining, counter)
| length remaining <= m = (killed, remaining)
| otherwise =
let (newKilled, newRemaining, newCounter) =
killList remaining counter
allKilled = killed ++ newKilled
in killR (allKilled, newRemaining, newCounter)
main :: IO ()
main = do
args <- getArgs
case args of
[n, k, m] -> print $ snd $ killRecursive (prisoners (read n))
(counter (read k)) (read m)
_ -> print $ snd $ killRecursive (prisoners 41) (counter 3) 1