-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path24b.hs
127 lines (105 loc) · 3.07 KB
/
24b.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}
import AOC
import qualified Prelude as P
import Data.Either
import Data.Functor
import Control.Lens hiding ((.>))
import Data.SBV
import qualified Data.Map as M
import Debug.Trace
type Data = SWord64
data Register = X | Y | Z | W deriving (Eq, Show)
data B = Var Register | Number Int deriving (Eq, Show)
data Instruction =
Input Register
| Instruction Op Register B
deriving (Eq, Show)
data Op =
Add
| Mul
| Div
| Mod
| Eql
deriving (Eq, Show)
data RegState = RegState {_x::Data, _y::Data, _z::Data, _w::Data}
makeLenses ''RegState
initialState :: RegState
initialState = RegState 0 0 0 0
toNum :: [Data] -> Data
toNum = foldl1 (\acc e -> acc * 10 + e)
readVal :: B -> State RegState Data
readVal (Number i) = pure $ fromIntegral i
readVal (Var reg) = readReg reg
readReg :: Register -> State RegState Data
readReg X = _x <$> get
readReg Y = _y <$> get
readReg Z = _z <$> get
readReg W = _w <$> get
writeReg :: Register -> Data -> State RegState ()
writeReg X v = x .= v
writeReg Y v = y .= v
writeReg Z v = z .= v
writeReg W v = w .= v
evalOp :: Op -> Register -> B -> State RegState ()
evalOp op reg b = do
a <- readReg reg
v <- readVal b
writeReg reg (op' a v)
where op' = opFunc op
opFunc :: Op -> Data -> Data -> Data
opFunc Add = (+)
opFunc Mul = (*)
opFunc Div = sDiv
opFunc Mod = sMod
opFunc Eql = \a b -> ite (a .== b) 1 0
interpret :: [Data] -> [Instruction] -> RegState
interpret d i = execState (interpret' d i) initialState
interpret' :: [Data] -> [Instruction] -> State RegState ()
interpret' [] [] = pure ()
interpret' (inp:rest) ((Input reg): ins) = writeReg reg inp >> interpret' rest ins
interpret' inp ((Instruction op a b): inss) = evalOp op a b >> interpret' inp inss
interpret' _ _ = error "someting went wrong"
run :: [Instruction] -> IO OptimizeResult
run inp = optimize Lexicographic $ do
x <- mkExistVars 14
constrain $ isValid x
minimize "value" $ toNum x
where
isValid :: [Data] -> SBool
isValid i =
sAll (\n -> n .>= 1 .&& n .<= 9) i
.&&
interpret i inp ^. z .== 0
main :: IO ()
main = do
content <- lines <$> getContents
x <- run $ ins content
print x
where
ins content = parseList p content
p :: Parser Instruction
p = do
inp <|> instruction
where
inp = try $ string "inp " >> Input <$> reg
instruction = do
o <- op
r <- reg
Instruction o r <$> be
op = add <|> mul <|> div <|> mod <|> eql
add = try $ string "add " $> Add
mul = try $ string "mul " $> Mul
div = try $ string "div " $> Div
mod = try $ string "mod " $> Mod
eql = try $ string "eql " $> Eql
be:: Parser B
be = space *> ((Var <$> reg) <|> (Number <$> signedInteger ))
reg :: Parser Register
reg = char 'x' $> X <|> char 'y' $> Y <|> char 'z' $> Z <|> char 'w' $> W