41 lines
1.3 KiB
Haskell
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
|