fork download
  1. #!/usr/bin/env stack
  2. -- stack --resolver=lts-9.12 --install-ghc runghc
  3. {-
  4. Cannibal numbers
  5. =======================
  6.  
  7. - https://r...content-available-to-author-only...d.it/76qk58
  8.  
  9. Sorts the input and makes the largest numbers eat the smallest, one at a time.
  10.  
  11. Maintains a list of "cannibalised" numbers (and their cannibals)
  12. in case a switch needs to be made
  13. (i.e. for a 3 to eat a 2 instead of a 1, such to make room for another 2 to eat a 1).
  14.  
  15. Unfortunately it's quite inefficient due to the recurring `sortBy s` of that list,
  16. which could have been improved by using some kind of cursor.
  17. -}
  18. module Main
  19. ( main
  20. , cannibalise
  21. ) where
  22.  
  23. import Data.List
  24. import Data.Ord
  25.  
  26. cannibalise :: ([Int], [Int]) -> [Int]
  27. cannibalise (ns, qs) = map (recurse sns 0 []) qs
  28. where
  29. sns = sortBy (comparing Down) ns
  30.  
  31. recurse :: [Int] -> Int -> [(Int, Int)] -> Int -> Int
  32. recurse ns c us q =
  33. case ns of
  34. (f:l)
  35. | f >= q -> recurse l (c + 1) us q
  36. | ll < 1 -> c
  37. | f > last l -> recurse ((f + 1) : init l) c ((f, last l) : us) q
  38. | otherwise ->
  39. case sortBy s us of
  40. ((fus, sus):tus)
  41. | f < fus && f > sus ->
  42. recurse ((f + 1) : init l) c ((fus, f) : (f, sus) : tus) q
  43. | otherwise -> c
  44. _ -> c
  45. where ll = length l
  46. s (fx, sx) (fy, sy)
  47. | sx == sy = compare fy fx
  48. | otherwise = compare sx sy
  49. _ -> c
  50.  
  51. main = interact io
  52. where
  53. io i =
  54. case lines i of
  55. (_:ns:qs:_) ->
  56. show $ cannibalise (map read (words ns), map read (words qs))
Success #stdin #stdout 0s 8388607KB
stdin
9 1
2 2 2 2 2 2 1 1 1
4
stdout
[3]