-
Notifications
You must be signed in to change notification settings - Fork 1
/
Day2.hs
75 lines (60 loc) · 1.89 KB
/
Day2.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
module Day2 where
import Data.List.Split
import Data.Maybe
import Data.Map as M
import Control.Applicative
readInt :: String -> Int
readInt s = read s
-- This may be an overkill
-- but we worship type safety
newtype Addr = A Int
deriving (Eq, Ord)
-- We could have derived Num
-- but this is safer
addP :: Addr -> Int -> Addr
addP (A p) off = A $ p + off
-- Store the program as a map
-- for quick random access
type Prog = M.Map Addr Int
get :: Addr -> Prog -> Int
get p prog = fromJust $ M.lookup p prog
getP :: Addr -> Int -> Prog -> Addr
getP p off prog = A $ fromJust $ M.lookup (addP p off) prog
put :: Addr -> Int -> Prog -> Prog
put p v prog = M.insert p v prog
mkProgram :: [Int] -> Prog
mkProgram listing = M.fromList (zip addressSpace listing)
where addressSpace = fmap A [0..]
run :: Prog -> (Int, Int) -> Int
run prog (noun, verb) = runProg (A 0) prog2
where prog1 = put (A 1) noun prog
prog2 = put (A 2) verb prog1
runProg :: Addr -> Prog -> Int
runProg ip prog =
let opCode = get ip prog
in if opCode == 99
then get (A 0) prog -- we're done!
else
runProg (addP ip 4) (exec opCode p1 p2 pr prog)
where p1 = getP ip 1 prog
p2 = getP ip 2 prog
pr = getP ip 3 prog
exec :: Int -> Addr -> Addr -> Addr -> Prog -> Prog
exec op p1 p2 pr prog = put pr val prog
where val = if op == 1
then m + n
else m * n
m = get p1 prog
n = get p2 prog
makeOutput :: Int -> Prog -> Int
makeOutput out prog = 100 * noun + verb
where pairs = (,) <$> [0..99] <*> [0..99]
outputs = zip (fmap (run prog) pairs) pairs
(noun, verb) = fromJust $ Prelude.lookup out outputs
main = do
text <- readFile "Data2.txt"
let listing = fmap readInt $ splitOn "," text
let prog = mkProgram listing
print $ run prog (12, 2)
print $ makeOutput 19690720 prog
test = [1,9,10,3,2,3,11,0,99,30,40,50]