22
[aoc20.git] / 22 / one.icl
1 module one
2
3 import StdEnv, StdDebug
4 import Data.Either
5
6 input :: ([Int], [Int])
7 input =
8 ([45,10,43,46,25,36,16,38,30,15,26,34,9,2,44,1,4,40,5,24,49,3,41,19,13]
9 ,[28,50,37,20,6,42,32,47,39,22,14,7,21,17,27,8,48,11,23,12,18,35,29,33,31]
10 )
11
12 //input :: ([Int], [Int])
13 //input =
14 // ([ 9, 2, 6, 3, 1]
15 // ,[ 5, 8, 4, 7, 10]
16 // )
17
18 Start = (uncurry combat input, uncurry rcombat input [] [])
19
20 combat :: [Int] [Int] -> Either Int Int
21 combat [] b = Right (score b)
22 combat a [] = Left (score a)
23 combat [a:as] [b:bs]
24 | a > b = combat (as ++ [a,b]) bs
25 | a < b = combat as (bs ++ [b,a])
26 | otherwise = abort "draw"
27
28 score :: [Int] -> Int
29 score d = sum [i*d\\d<-reverse d & i<-[1..]]
30
31 rcombat :: [Int] [Int] [[Int]] [[Int]] -> Either Int Int
32 rcombat [] b _ _ = Right (score b)
33 rcombat a [] _ _ = Left (score a)
34 rcombat [a:as] [b:bs] ahist bhist
35 | isMember [a:as] ahist && isMember [b:bs] bhist = Left (score [a:as])
36 # (ahist, bhist) = ([[a:as]:ahist], [[b:bs]:bhist])
37 | a <= length as && b <= length bs
38 = case rcombat (take a as) (take b bs) [] [] of
39 Left s = rcombat (as ++ [a,b]) bs ahist bhist
40 Right s = rcombat as (bs ++ [b,a]) ahist bhist
41 | a > b = rcombat (as ++ [a,b]) bs ahist bhist
42 | a < b = rcombat as (bs ++ [b,a]) ahist bhist