blob: 34a87ef96aff86e11a3c362f27a2f1e8c309acde (
plain) (
blame)
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
76
77
78
|
{-
Copyright (C) 2017 Yuchen Pei.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public
License along with this program. If not, see
<https://www.gnu.org/licenses/>.
-}
import Data.List.Split (splitOn)
import Data.Map (Map)
import qualified Data.Map as Map
data State = Active | Inactive | Terminated deriving Eq
exec :: [[Char]] -> Int -> Map Char Int -> Int
exec rom addr regs
| op == "snd" = exec rom (addr + 1) (Map.insert '_' dval regs)
| op == "set" = exec rom (addr + 1) (Map.insert dest val regs)
| op == "add" = exec rom (addr + 1) (Map.insert dest (dval + val) regs)
| op == "mul" = exec rom (addr + 1) (Map.insert dest (dval * val) regs)
| op == "mod" = exec rom (addr + 1) (Map.insert dest (dval `mod` val) regs)
| op == "jgz" = exec rom (if dval > 0 then addr + val else addr + 1) regs
| op == "rcv" = if dval /= 0 then regs Map.! '_' else exec rom (addr + 1) regs
where ins = rom !! addr
op:[dest]:xs = splitOn " " ins
dval = regs Map.! dest
x = head xs
val = if head x `elem` alphabet then regs Map.! (head x) else read x
alphabet = ['a'..'z']
initRegs :: Map Char Int
initRegs = Map.fromList $ zipWith (,) ['a'..'z'] (cycle [0])
initRegs' :: Map Char Int
initRegs' = Map.insert 'p' 1 initRegs
solve1 :: [Char] -> Int
solve1 xs = exec (splitOn "\n" xs) 0 initRegs
exec' me n myAddr myRegs myQueue myState theirAddr theirRegs theirQueue theirState
| myState == Terminated = n
| myAddr < 0 || myAddr >= length rom = exec' (1 - me) n theirAddr theirRegs theirQueue theirState myAddr myRegs myQueue Terminated
| op == "set" = exec' me n (myAddr + 1) (Map.insert dest val myRegs) myQueue myState theirAddr theirRegs theirQueue theirState
| op == "add" = exec' me n (myAddr + 1) (Map.insert dest (dval + val) myRegs) myQueue myState theirAddr theirRegs theirQueue theirState
| op == "mul" = exec' me n (myAddr + 1) (Map.insert dest (dval * val) myRegs) myQueue myState theirAddr theirRegs theirQueue theirState
| op == "mod" = exec' me n (myAddr + 1) (Map.insert dest (dval `mod` val) myRegs) myQueue myState theirAddr theirRegs theirQueue theirState
| op == "jgz" = exec' me n (if dval > 0 then myAddr + val else myAddr + 1) myRegs myQueue myState theirAddr theirRegs theirQueue theirState
| op == "snd" = exec' me (n + me) (myAddr + 1) myRegs myQueue myState theirAddr theirRegs (theirQueue ++ [dval]) theirState
| op == "rcv" && null myQueue && null theirQueue && theirState /= Active = n
| op == "rcv" && null myQueue = exec' (1 - me) n theirAddr theirRegs theirQueue theirState myAddr myRegs myQueue Inactive
| op == "rcv" = exec' me n (myAddr + 1) (Map.insert dest y myRegs) ys myState theirAddr theirRegs theirQueue theirState
where ins = rom !! myAddr
op:dest':xs = splitOn " " ins
dval = if head dest' `elem` alphabet then myRegs Map.! (head dest') else read dest'
dest = head dest'
x = head xs
val = if head x `elem` alphabet then myRegs Map.! (head x) else read x
y:ys = myQueue
solve2 = exec' 0 0 0 initRegs [] Active 0 initRegs' [] Active
rom = splitOn "\n" input
input0 = "set a 1\nadd a 2\nmul a a\nmod a 5\nsnd a\nset a 0\nrcv a\njgz a -1\nset a 1\njgz a -2"
input1 = "snd 1\nsnd 2\nsnd p\nrcv a\nrcv b\nrcv c\nrcv d"
input = "set i 31\nset a 1\nmul p 17\njgz p p\nmul a 2\nadd i -1\njgz i -2\nadd a -1\nset i 127\nset p 464\nmul p 8505\nmod p a\nmul p 129749\nadd p 12345\nmod p a\nset b p\nmod b 10000\nsnd b\nadd i -1\njgz i -9\njgz a 3\nrcv b\njgz b -1\nset f 0\nset i 126\nrcv a\nrcv b\nset p a\nmul p -1\nadd p b\njgz p 4\nsnd a\nset a b\njgz 1 3\nsnd b\nset f 1\nadd i -1\njgz i -11\nsnd a\njgz f -16\njgz a -19"
|