Please don’t rely on this Gitea instance being around forever. If any of your build scripts use my (kageru’s) projects hosted here, check my Github or IEW on Github for encoding projects. If you can’t find what you’re looking for there, tell me to migrate it.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
6.6 KiB

import Data.List.Split
import Data.Char as Char
import Data.List as List
import Data.Either as Either
main = do
software <- getList <$> getContents
let combs = getComb [5,6,7,8,9]
--mapM putStrLn(map show combs)
putStrLn(show $ List.maximum ( map (\x-> part2 ( prepareAmps x software) 0 ) combs ))
-- let output = calcthruster software [4,3,2,1,0]
data Amplifier = Amplifier{ state :: [Int]
,index :: Int
,input :: [Int]
,output :: [Int] } deriving Show
getList :: String -> [Int]
getList = map read . splitOn ","
getComb :: [Int] -> [[Int]]
getComb array = filter ((5==).length.(List.nub)) $ mapM (const array) [1..5]
prepareAmps :: [Int] -> [Int] -> [Amplifier]
prepareAmps (p1:p2:p3:p4:p5:_) software = do
let a = step (Amplifier software 0 [] []) [p1]
let b = step (Amplifier software 0 [] []) [p2]
let c = step (Amplifier software 0 [] []) [p3]
let d = step (Amplifier software 0 [] []) [p4]
let e = step (Amplifier software 0 [] [0]) [p5]
let e2 = Amplifier (state e) (index e) (input e) [0]
[a,b,c,d,e2]
part2 :: [Amplifier] -> Int -> Int
part2 amps lastOuput = do
let ampA = link (amps!!4) (amps!!0)
let ampB = link (ampA) (amps!!1)
let ampC = link (ampB) (amps!!2)
let ampD = link (ampC) (amps!!3)
let ampE = link (ampD) (amps!!4)
if index ampE == -1
then lastOuput
else part2 ([ampA,ampB,ampC,ampD,ampE]) (head(output ampE))
link :: Amplifier -> Amplifier -> Amplifier
link left calc
| null (output left) = Amplifier (state calc) (-1) (input calc) (output calc)
| index left == -1 = Amplifier (state calc) (-1) (input calc) (output calc)
| otherwise = step calc ([last $ output left])
step :: Amplifier -> [Int] -> Amplifier
step amp input = operation (drop (index amp) (state amp)) (state amp) (index amp) input []
calcthrusters :: [Int] -> [Int] -> Int -> Int
calcthrusters software (p1:p2:p3:p4:p5:_) start = do
let outputA = operation software software 0 [p1, start] []
let outputB = operation software software 0 [p2, last $ output outputA] []
let outputC = operation software software 0 [p3, last $ output outputB] []
let outputD = operation software software 0 [p4, last $ output outputC] []
let outputE = operation software software 0 [p5, last $ output outputD] []
last $ output outputE
operation :: [Int] -> [Int] -> Int -> [Int] -> [Int] -> Amplifier
operation (99:_) state i input output =
Amplifier state i input output
operation (op:xs) state i input output
| last (digits op) == 1 = do
let newindex = i + 4
let newstate = add (fillup (revertdigs op) 5) (xs!!0) (xs!!1) (xs!!2) state
operation ((drop newindex newstate)) (newstate) newindex input output
| last (digits op) == 2 = do
let newindex = i + 4
let newstate = mult (fillup (revertdigs op) 5) (xs!!0) (xs!!1) (xs!!2) state
operation ((drop newindex newstate)) (newstate) newindex input output
| last (digits op) == 3 = do
if (length input) == 0
then (Amplifier state i input output)
else do
let newindex = i + 2
let newstate = put (fillup (revertdigs op) 3) (xs!!0) (head input) state
let newinput = drop 1 input
operation (drop newindex newstate) (newstate) newindex newinput output
| last (digits op) == 4 = do
let newindex = i + 2
let newoutput = out (fillup (revertdigs op) 3) output (xs!!0) state
let newinput = drop 1 input
operation ((drop newindex state)) (state) newindex input (newoutput)
| (last (digits op) == 5 ) = do
let newindex = jumpif (fillup (revertdigs op) 4) (xs!!0) (xs!!1) i state
operation ((drop newindex state)) (state) newindex input output
| (last (digits op) == 6 ) = do
let newindex = jumpifnot (fillup (revertdigs op) 4) (xs!!0) (xs!!1) i state
operation ((drop newindex state)) (state) newindex input output
| (last (digits op) == 7 ) = do
let newindex = i + 4
let newstate = lessthan (fillup (revertdigs op) 5) (xs!!0) (xs!!1) (xs!!2) state
operation ((drop newindex newstate)) (newstate) newindex input output
| (last (digits op) == 8 ) = do
let newindex = i + 4
let newstate = equal (fillup (revertdigs op) 5) (xs!!0) (xs!!1) (xs!!2) state
operation ((drop newindex newstate)) (newstate) newindex input output
add :: [Int] -> Int -> Int -> Int -> [Int] -> [Int]
add (op1:op2:m1:m2:m3:_) p1 p2 p3 state =
Main.insert state sum p3
where
sum = (getValue m1 p1 state) + (getValue m2 p2 state)
mult :: [Int] -> Int -> Int -> Int -> [Int] -> [Int]
mult (op1:op2:m1:m2:m3:_) p1 p2 p3 state =
Main.insert state sum p3
where
sum = (getValue m1 p1 state) * (getValue m2 p2 state)
put :: [Int] -> Int -> Int -> [Int] -> [Int]
put(op1:op2:m1:_) p1 input state =
Main.insert state input p1
out :: [Int] -> [Int] -> Int -> [Int] -> [Int]
out (op1:op2:m1:_) output p1 state =
output ++ [(getValue m1 p1 state)]
jumpif :: [Int] -> Int -> Int -> Int -> [Int] -> Int
jumpif (op1:op2:m1:m2:_) p1 p2 index state
| (getValue m1 p1 state) /= 0 = getValue m2 p2 state
| otherwise = index + 3
jumpifnot :: [Int] -> Int -> Int -> Int -> [Int] -> Int
jumpifnot (op1:op2:m1:m2:_) p1 p2 index state
| (getValue m1 p1 state) == 0 = getValue m2 p2 state
| otherwise = index + 3
lessthan :: [Int] -> Int -> Int -> Int -> [Int] -> [Int]
lessthan (op1:op2:m1:m2:m3:_) p1 p2 p3 state
| (getValue m1 p1 state) < (getValue m2 p2 state) = Main.insert state 1 p3
| otherwise = Main.insert state 0 p3
equal :: [Int] -> Int -> Int -> Int -> [Int] -> [Int]
equal (op1:op2:m1:m2:m3:_) p1 p2 p3 state
| (getValue m1 p1 state) == (getValue m2 p2 state) = Main.insert state 1 p3
| otherwise = Main.insert state 0 p3
insert :: [Int] -> Int -> Int -> [Int]
insert xs value index = do
let split = splitAt index xs
(fst split)++ [value] ++ (drop 1 (snd split))
digits :: Int -> [Int]
digits = map Char.digitToInt . show
revertdigs :: Int -> [Int]
revertdigs 0 = []
revertdigs x = x `mod` 10 : revertdigs (x `div` 10)
fillup :: [Int] -> Int -> [Int]
fillup array x = array ++ (replicate (x - (length array)) 0)
getValue :: Int -> Int -> [Int] -> Int
getValue 0 index array = array !! index
getValue 1 index array = index