Browse Source

Moved Intcode to a module

master
Micah Halter 1 month ago
parent
commit
4a0ee0b65c
15 changed files with 115 additions and 315 deletions
  1. +55
    -0
      00-utils/Intcode.hs
  2. +15
    -36
      02-1202-program-alarm/answer.hs
  3. +1
    -1
      02-1202-program-alarm/run.sh
  4. +5
    -38
      05-sunny-with-a-chance-of-asteroids/answer.hs
  5. +1
    -1
      05-sunny-with-a-chance-of-asteroids/run.sh
  6. +17
    -44
      07-amplification-circuit/answer.hs
  7. +1
    -1
      07-amplification-circuit/run.sh
  8. +5
    -62
      09-sensor-boost/answer.hs
  9. +1
    -1
      09-sensor-boost/run.sh
  10. +7
    -44
      11-space-police/answer.hs
  11. +1
    -1
      11-space-police/run.sh
  12. +2
    -42
      13-care-package/answer.hs
  13. +1
    -1
      13-care-package/run.sh
  14. +2
    -42
      15-oxygen-system/answer.hs
  15. +1
    -1
      15-oxygen-system/run.sh

+ 55
- 0
00-utils/Intcode.hs View File

@@ -0,0 +1,55 @@
module Intcode
( parseProg
, compute
, computeTilHalt
, startingState
) where

import Data.List as List
import Data.Maybe
import Data.Ord
import Data.List.Split
import qualified Data.Map.Strict as Map

parseProg :: String -> Map.Map Int Int
parseProg str = Map.fromList $ List.zip [0..] $ map (read :: String -> Int) $ splitOn "," str

compute :: (Map.Map Int Int, Int, Int) -> ([Int], [Int]) -> ((Map.Map Int Int, Int, Int), ([Int], [Int]))
compute (x, y, z) (input_orig, output) =
if op == 99
then ((x, -1, z), (input_orig, output))
else if op == 1 || op == 2
then compute ((Map.insert dest ((if op == 1 then (+) else (*)) left right) x), (y+4), z) (input_orig, output)
else if op == 3
then compute ((Map.insert dest input x), (y+2), z) (inputs, output)
else if op == 4
then ((x, y+2, z), (input_orig, (left:output)))
else if op == 5 || op == 6
then compute (x, (if (if op == 5 then (/=) else (==)) left 0 then right else (y+3)), z) (input_orig, output)
else if op == 7 || op == 8
then compute ((Map.insert dest (if (if op == 7 then (<) else (==)) left right then 1 else 0) x), (y+4), z) (input_orig, output)
else if op == 9
then compute (x, y+2, z+left) (input_orig, output)
else
((Map.empty, -1, z), (input_orig, output))
where
(input:inputs) = if Prelude.length input_orig > 0 then input_orig else (0:input_orig)
indexOfIndex y = Map.findWithDefault 0 (x Map.! y) x
digits = Prelude.reverse $ Prelude.map (read . return) $ show $ x Map.! y
op = (if Prelude.length digits > 1 then 10 * digits!!1 else 0) + digits!!0
left = if Prelude.length digits > 2 && digits!!2 == 1 then x Map.! (y+1)
else if Prelude.length digits > 2 && digits!!2 == 2 then x Map.! (z+(x Map.! (y+1)))
else indexOfIndex (y+1)
right = if Prelude.length digits > 3 && digits!!3 == 1 then x Map.! (y+2)
else if Prelude.length digits > 3 && digits!!3 == 2 then x Map.! (z+(x Map.! (y+2)))
else indexOfIndex (y+2)
dest = if op == 3 then (if Prelude.length digits > 2 && digits!!2 == 2 then z+(x Map.! (y+1)) else x Map.! (y+1))
else (if Prelude.length digits > 4 && digits!!4 == 2 then z else 0)+(x Map.! (y+3))

computeTilHalt :: ((Map.Map Int Int, Int, Int), ([Int], [Int])) -> [Int]
computeTilHalt ((prog, y, z), (inputs, outputs)) =
if y == -1 then outputs
else computeTilHalt $ compute (prog, y, z) (inputs, outputs)

startingState :: Map.Map Int Int -> [Int] -> ((Map.Map Int Int, Int, Int), ([Int], [Int]))
startingState prog input = ((prog, 0, 0), (input, []))

+ 15
- 36
02-1202-program-alarm/answer.hs View File

@@ -1,47 +1,24 @@
import System.Environment
import Data.List.Split
import Data.Sequence
import qualified Data.Map.Strict as Map

parse :: String -> Seq Int
parse = fromList . map (read :: String -> Int) . splitOn ","
import Intcode

compute :: Seq Int -> Int -> Seq Int
compute x y = do
let op = x `index` y
let indexOfIndex y = index x $ index x y
let left = indexOfIndex (y+1)
let right = indexOfIndex (y+2)
if op == 99
then x
else if op /= 1 && op /= 2
then fromList []
else
compute (update (x `index` (y+3)) ((if op == 1 then (+) else (*)) left right) x) (y+4)
computeTilHalt2 :: ((Map.Map Int Int, Int, Int), ([Int], [Int])) -> Int
computeTilHalt2 ((prog, y, z), io) =
if y == -1 then prog Map.! 0
else computeTilHalt2 $ compute (prog, y, z) io

findParamsBrute :: Seq Int -> Int -> [Int] -> Int
findParamsBrute x y [p1,p2] = do
let computed = compute (update 1 p1 $ update 2 p2 x) 0
let ans = computed `index` 0
if y == ans
then 100*p1 + p2
else if ans > y
then -1
else if y `mod` 1000 > ans `mod` 1000
then findParamsBrute x y [p1, p2 + 1]
else
findParamsBrute x y [p1+1, p2]

findParams :: Int -> Int
findParams goal = do
let first = (goal-493708) `div` 243000
let second = goal - 493708 - 243000*first
100*first + second

findParams goal = 100*first + second
where
first = (goal-493708) `div` 243000
second = goal - 493708 - 243000*first

main = do
input <- getArgs
let x = parse $ input!!0
print $ (x `compute` 0) `index` 0
let parsed = parseProg $ input!!0

let map = Map.insert 1 12 parsed
let newMap = Map.insert 2 2 map
print $ computeTilHalt2 $ startingState newMap []
print $ findParams 19690720

+ 1
- 1
02-1202-program-alarm/run.sh View File

@@ -1,3 +1,3 @@
#!/bin/sh

runhaskell answer.hs `< input`
runhaskell -i$(dirname $(pwd))/00-utils answer.hs `< input`

+ 5
- 38
05-sunny-with-a-chance-of-asteroids/answer.hs View File

@@ -1,43 +1,10 @@
import Data.Sequence
import System.Environment
import Data.List.Split

parse :: String -> Seq Int
parse = fromList . map (read :: String -> Int) . splitOn ","

revDigits :: Int -> [Int]
revDigits = Prelude.reverse . Prelude.map (read . return) . show

compute :: Seq Int -> Int -> IO (Seq Int)
compute x y = do
let indexOfIndex y = index x $ index x y
let digits = revDigits $ x `index` y
let op = (if Prelude.length digits > 1 then 10 * digits!!1 else 0) + digits!!0
let left = if Prelude.length digits > 2 && digits!!2 == 1 then x `index` (y+1) else indexOfIndex (y+1)
let right = if Prelude.length digits > 3 && digits!!3 == 1 then x `index` (y+2) else indexOfIndex (y+2)
let dest = if op == 3 then x `index` (y+1) else x `index` (y+3)
if op == 99
then return (x)
else if op == 1 || op == 2
then compute (update dest ((if op == 1 then (+) else (*)) left right) x) (y+4)
else if op == 3
then do
print "Input:"
input <- getLine
compute (update dest (read input::Int) x) (y+2)
else if op == 4
then do
print "Output:"
print left
compute x (y+2)
else if op == 5 || op == 6
then compute x (if (if op == 5 then (/=) else (==)) left 0 then right else (y+3))
else if op == 7 || op == 8
then compute (update dest (if (if op == 7 then (<) else (==))left right then 1 else 0) x) (y+4)
else
return (fromList [])
import Intcode

main = do
input <- getArgs
let x = parse $ input!!0
x `compute` 0 >>= print
let parsed = parseProg $ input!!0

print $ flip (!!) 0 $ computeTilHalt $ startingState parsed [1]
print $ flip (!!) 0 $ computeTilHalt $ startingState parsed [5]

+ 1
- 1
05-sunny-with-a-chance-of-asteroids/run.sh View File

@@ -1,3 +1,3 @@
#!/bin/sh

runhaskell answer.hs `< input`
runhaskell -i$(dirname $(pwd))/00-utils answer.hs `< input`

+ 17
- 44
07-amplification-circuit/answer.hs View File

@@ -3,60 +3,33 @@ import Data.Sequence
import Data.List
import Data.List.Split
import Data.Ord
import qualified Data.Map.Strict as Map

parse :: String -> Seq Int
parse = fromList . map (read :: String -> Int) . splitOn ","
import Intcode

revDigits :: Int -> [Int]
revDigits = Prelude.reverse . Prelude.map (read . return) . show
startingStates :: Map.Map Int Int -> [Int] -> Seq ((Map.Map Int Int, Int, Int), ([Int], [Int]))
startingStates prog comps = update 0 (state, (input ++ [0], output)) out
where
out = fromList $ map (\i -> startingState prog [i]) comps
(state, (input, output)) = out `index` 0

compute :: (Seq Int, Int) -> ([Int], [Int]) -> ((Seq Int, Int), ([Int], [Int]))
compute (x, y) (input_orig, output) = do
let (input:inputs) = if Prelude.length input_orig > 0 then input_orig else (0:input_orig)
let indexOfIndex y = index x $ index x y
let digits = revDigits $ x `index` y
let op = (if Prelude.length digits > 1 then 10 * digits!!1 else 0) + digits!!0
let left = if Prelude.length digits > 2 && digits!!2 == 1 then x `index` (y+1) else indexOfIndex (y+1)
let right = if Prelude.length digits > 3 && digits!!3 == 1 then x `index` (y+2) else indexOfIndex (y+2)
let dest = if op == 3 then x `index` (y+1) else x `index` (y+3)
if op == 99
then ((x, -1), (input_orig, output))
else if op == 1 || op == 2
then compute ((update dest ((if op == 1 then (+) else (*)) left right) x), (y+4)) (input_orig, output)
else if op == 3
then compute ((update dest input x), (y+2)) (inputs, output)
else if op == 4
then ((x, y+2), (input_orig, (left:output)))
else if op == 5 || op == 6
then compute (x, (if (if op == 5 then (/=) else (==)) left 0 then right else (y+3))) (input_orig, output)
else if op == 7 || op == 8
then compute ((update dest (if (if op == 7 then (<) else (==))left right then 1 else 0) x), (y+4)) (input_orig, output)
else
((fromList [], -1), (input_orig, output))

startingState :: Seq Int -> [Int] -> Seq ((Seq Int, Int), ([Int], [Int]))
startingState prog comps = do
let out = fromList $ map (\i -> ((prog, 0), ([i], []))) comps
let (prog, (input, output)) = out `index` 0
update 0 (prog, (input ++ [0], output)) out

runSeries :: Seq ((Seq Int, Int), ([Int], [Int])) -> [Int] -> Int -> Int
runSeries :: Seq ((Map.Map Int Int, Int, Int), ([Int], [Int])) -> [Int] -> Int -> Int
runSeries states comps idx = do
let (prog, (newInput, newOutput:outputs)) = uncurry compute $ index states idx
let newStates = update idx (prog, (newInput, newOutput:outputs)) states
let (state, (newInput, newOutput:outputs)) = uncurry compute $ index states idx
let newStates = update idx (state, (newInput, newOutput:outputs)) states
let newIdx = if idx+1 == Data.List.length comps then 0 else idx+1
let ((nextProg, nextY), (nextInput, nextOutput)) = index newStates newIdx
let ((nextProg, nextY, nextZ), (nextInput, nextOutput)) = index newStates newIdx
if nextY == -1
then newOutput
else
runSeries (update newIdx ((nextProg, nextY), (nextInput ++ [newOutput], nextOutput)) newStates) comps newIdx
runSeries (update newIdx ((nextProg, nextY, nextZ), (nextInput ++ [newOutput], nextOutput)) newStates) comps newIdx

findMax :: Seq Int -> [[Int]] -> ([Int], Int)
findMax prog comps = maximumBy (comparing snd) $ map (\i -> (i, runSeries (startingState prog i) i 0)) comps
findMax :: Map.Map Int Int -> [[Int]] -> Int
findMax prog comps = snd $ maximumBy (comparing snd) $ map (\i -> (i, runSeries (startingStates prog i) i 0)) comps

main = do
input <- getArgs
let x = parse $ input!!0
let parsed = parseProg $ input!!0

print $ findMax x $ permutations [0..4]
print $ findMax x $ permutations [5..9]
print $ findMax parsed $ permutations [0..4]
print $ findMax parsed $ permutations [5..9]

+ 1
- 1
07-amplification-circuit/run.sh View File

@@ -1,3 +1,3 @@
#!/bin/sh

runhaskell answer.hs `< input`
runhaskell -i$(dirname $(pwd))/00-utils answer.hs `< input`

+ 5
- 62
09-sensor-boost/answer.hs View File

@@ -1,71 +1,14 @@
import System.Environment
import Data.Sequence
import Data.List
import Data.List.Split
import Data.Ord
import qualified Data.Map.Strict as Map

parse :: String -> Seq Int
parse = fromList . map (read :: String -> Int) . splitOn ","

revDigits :: Int -> [Int]
revDigits = Prelude.reverse . Prelude.map (read . return) . show

extendSeq :: Int -> Seq Int -> Seq Int
extendSeq x input = input >< (fromList $ Prelude.take x (repeat 0))

compute :: (Seq Int, Int, Int) -> ([Int], [Int]) -> ((Seq Int, Int, Int), ([Int], [Int]))
compute (x, y, z) (input_orig, output) = do
let (input:inputs) = if Prelude.length input_orig > 0 then input_orig else (0:input_orig)
let indexOfIndex y = index x $ index x y
let digits = revDigits $ x `index` y
let op = (if Prelude.length digits > 1 then 10 * digits!!1 else 0) + digits!!0
let left = if Prelude.length digits > 2 && digits!!2 == 1 then x `index` (y+1) else if Prelude.length digits > 2 && digits!!2 == 2 then x `index` (z+(x `index` (y+1))) else indexOfIndex (y+1)
let right = if Prelude.length digits > 3 && digits!!3 == 1 then x `index` (y+2) else if Prelude.length digits > 3 && digits!!3 == 2 then x `index` (z+(x `index` (y+2))) else indexOfIndex (y+2)
let dest = if op == 3 then (if digits!!2 == 2 then z+(x `index` (y+1)) else x `index` (y+1)) else (if Prelude.length digits > 4 && digits!!4 == 2 then z else 0)+(x `index` (y+3))
let newX = if dest+1 > Data.Sequence.length x then extendSeq ((dest+1)-(Data.Sequence.length x)) x else x
if op == 99
then ((newX, -1, z), (input_orig, output))
else if op == 1 || op == 2
then compute ((update dest ((if op == 1 then (+) else (*)) left right) newX), (y+4), z) (input_orig, output)
else if op == 3
then compute ((update dest input newX), (y+2), z) (inputs, output)
else if op == 4
then ((newX, y+2, z), (input_orig, (left:output)))
else if op == 5 || op == 6
then compute (newX, (if (if op == 5 then (/=) else (==)) left 0 then right else (y+3)), z) (input_orig, output)
else if op == 7 || op == 8
then compute ((update dest (if (if op == 7 then (<) else (==))left right then 1 else 0) newX), (y+4), z) (input_orig, output)
else if op == 9
then compute (newX, y+2, z+left) (input_orig, output)
else
((fromList [], -1, z), (input_orig, output))

startingState :: Seq Int -> [Int] -> [Int] -> Seq ((Seq Int, Int, Int), ([Int], [Int]))
startingState prog comps inps = do
let out = fromList $ map (\i -> ((prog, 0, 0), ([i], []))) comps
let (prog, (input, output)) = out `index` 0
update 0 (prog, (input ++ inps, output)) out

runSeries :: Seq ((Seq Int, Int, Int), ([Int], [Int])) -> [Int] -> Int -> [Int]
runSeries states comps idx = do
let (prog, (newInput, newOutput:outputs)) = uncurry compute $ index states idx
let newStates = update idx (prog, (newInput, newOutput:outputs)) states
let newIdx = if idx+1 == Data.List.length comps then 0 else idx+1
let ((nextProg, nextY, nextZ), (nextInput, nextOutput)) = index newStates newIdx
if nextY == -1
then (newOutput:outputs)
else
runSeries (update newIdx ((nextProg, nextY, nextZ), (nextInput ++ [newOutput], nextOutput)) newStates) comps newIdx

runSingle :: Seq Int -> [Int] -> [Int]
runSingle prog inputs = runSeries (startingState prog inputs []) [0] 0

findMax :: Seq Int -> [[Int]] -> ([Int], Int)
findMax prog comps = maximumBy (comparing snd) $ map (\i -> (i, (runSeries (startingState prog i [0]) i 0)!!0)) comps
import Intcode

main = do
input <- getArgs
let x = parse $ input!!0
let parsed = parseProg $ input!!0

print $ runSingle x [1]
print $ runSingle x [2]
print $ flip (!!) 0 $ computeTilHalt $ startingState parsed [1]
print $ flip (!!) 0 $ computeTilHalt $ startingState parsed [2]

+ 1
- 1
09-sensor-boost/run.sh View File

@@ -1,3 +1,3 @@
#!/bin/sh

runhaskell answer.hs `< input`
runhaskell -i$(dirname $(pwd))/00-utils answer.hs `< input`

+ 7
- 44
11-space-police/answer.hs View File

@@ -4,56 +4,19 @@ import Data.List
import Data.List.Split
import Data.Ord
import Data.Foldable
import Data.Maybe
import qualified Data.Map.Strict as Map
import Debug.Trace

parse :: String -> Map.Map Int Int
parse str = Map.fromList $ Data.List.zip [0..] $ map (read :: String -> Int) $ splitOn "," str

revDigits :: Int -> [Int]
revDigits = Prelude.reverse . Prelude.map (read . return) . show

compute :: (Map.Map Int Int, Int, Int) -> ([Int], [Int]) -> ((Map.Map Int Int, Int, Int), ([Int], [Int]))
compute (x, y, z) (input_orig, output) =
if op == 99
then ((x, -1, z), (input_orig, output))
else if op == 1 || op == 2
then compute ((Map.insert dest ((if op == 1 then (+) else (*)) left right) x), (y+4), z) (input_orig, output)
else if op == 3
then compute ((Map.insert dest input x), (y+2), z) (inputs, output)
else if op == 4
then ((x, y+2, z), (input_orig, (left:output)))
else if op == 5 || op == 6
then compute (x, (if (if op == 5 then (/=) else (==)) left 0 then right else (y+3)), z) (input_orig, output)
else if op == 7 || op == 8
then compute ((Map.insert dest (if (if op == 7 then (<) else (==)) left right then 1 else 0) x), (y+4), z) (input_orig, output)
else if op == 9
then compute (x, y+2, z+left) (input_orig, output)
else
((Map.empty, -1, z), (input_orig, output))
where
(input:inputs) = if Prelude.length input_orig > 0 then input_orig else (0:input_orig)
indexOfIndex y = Map.findWithDefault 0 (x Map.! y) x
digits = revDigits $ x Map.! y
op = (if Prelude.length digits > 1 then 10 * digits!!1 else 0) + digits!!0
left = if Prelude.length digits > 2 && digits!!2 == 1 then x Map.! (y+1)
else if Prelude.length digits > 2 && digits!!2 == 2 then x Map.! (z+(x Map.! (y+1)))
else indexOfIndex (y+1)
right = if Prelude.length digits > 3 && digits!!3 == 1 then x Map.! (y+2)
else if Prelude.length digits > 3 && digits!!3 == 2 then x Map.! (z+(x Map.! (y+2)))
else indexOfIndex (y+2)
dest = if op == 3 then (if Prelude.length digits > 2 && digits!!2 == 2 then z+(x Map.! (y+1)) else x Map.! (y+1))
else (if Prelude.length digits > 4 && digits!!4 == 2 then z else 0)+(x Map.! (y+3))
import Intcode

getPoints :: ((Map.Map Int Int, Int, Int), ([Int], [Int])) -> Map.Map (Int, Int) Int -> Int -> (Int, Int) -> Map.Map (Int, Int) Int
getPoints (prog, (inputs, outputs)) map dir (x, y) = if nextY2 == -1 then newMap else getPoints ((nextProg2, nextY2, nextZ2), (newInput2, (newDir:newOutputs2))) newMap newDir2 (newX, newY)
getPoints (prog, (inputs, outputs)) map dir (x, y) = if nextY2 == -1 then newMap
else getPoints ((nextProg2, nextY2, nextZ2), (newInput2, (newDir:newOutputs2))) newMap newDir2 (newX, newY)
where
currColor = Map.findWithDefault 0 (x, y) map
((nextProg1, nextY1, nextZ1), (newInput1, (newColor:newOutputs1))) = compute prog ((currColor:inputs), outputs)
newMap = if nextY1 == -1 || newColor == currColor then map else Map.insert (x, y) newColor map
((nextProg2, nextY2, nextZ2), (newInput2, (newDir:newOutputs2))) = if nextY1 == -1 then ((nextProg1, nextY1, nextZ1), (newInput1, (newColor:newOutputs1)))
else compute (nextProg1, nextY1, nextZ1) (newInput1, (newColor:newOutputs1))
else compute (nextProg1, nextY1, nextZ1) (newInput1, (newColor:newOutputs1))
newDir2 = mod (dir+(if newDir == 0 then -1 else 1)) 4
newX = if newDir2 == 1 then x+1 else if newDir2 == 3 then x-1 else x
newY = if newDir2 == 0 then y+1 else if newDir2 == 2 then y-1 else y
@@ -72,7 +35,7 @@ paint map = foldl (\i j->i ++ (j ++ ['\n'])) [] $ Data.List.Split.chunksOf width

main = do
input <- getArgs
let parsed = parse $ input!!0
let parsed = parseProg $ input!!0

print $ Map.size $ getPoints ((parsed, 0, 0), ([], [])) (Map.empty) 0 (0, 0)
putStr $ paint $ getPoints ((parsed, 0, 0), ([], [])) (Map.singleton (0,0) 1) 0 (0, 0)
print $ Map.size $ getPoints (startingState parsed []) (Map.empty) 0 (0, 0)
putStr $ paint $ getPoints (startingState parsed []) (Map.singleton (0,0) 1) 0 (0, 0)

+ 1
- 1
11-space-police/run.sh View File

@@ -1,3 +1,3 @@
#!/bin/sh

runhaskell answer.hs `< input`
runhaskell -i$(dirname $(pwd))/00-utils answer.hs `< input`

+ 2
- 42
13-care-package/answer.hs View File

@@ -3,46 +3,7 @@ import Data.List
import Data.List.Split
import qualified Data.Map.Strict as Map

parse :: String -> Map.Map Int Int
parse str = Map.fromList $ Data.List.zip [0..] $ map (read :: String -> Int) $ splitOn "," str

revDigits :: Int -> [Int]
revDigits = Prelude.reverse . Prelude.map (read . return) . show

compute :: (Map.Map Int Int, Int, Int) -> ([Int], [Int]) -> ((Map.Map Int Int, Int, Int), ([Int], [Int]))
compute (x, y, z) (input_orig, output) =
if op == 99
then ((x, -1, z), (input_orig, output))
else if op == 1 || op == 2
then compute ((Map.insert dest ((if op == 1 then (+) else (*)) left right) x), (y+4), z) (input_orig, output)
else if op == 3
then compute ((Map.insert dest input x), (y+2), z) (inputs, output)
else if op == 4
then ((x, y+2, z), (input_orig, (left:output)))
else if op == 5 || op == 6
then compute (x, (if (if op == 5 then (/=) else (==)) left 0 then right else (y+3)), z) (input_orig, output)
else if op == 7 || op == 8
then compute ((Map.insert dest (if (if op == 7 then (<) else (==)) left right then 1 else 0) x), (y+4), z) (input_orig, output)
else if op == 9
then compute (x, y+2, z+left) (input_orig, output)
else
((Map.empty, -1, z), (input_orig, output))
where
(input:inputs) = if Prelude.length input_orig > 0 then input_orig else (0:input_orig)
indexOfIndex y = Map.findWithDefault 0 (x Map.! y) x
digits = revDigits $ x Map.! y
op = (if Prelude.length digits > 1 then 10 * digits!!1 else 0) + digits!!0
left = if Prelude.length digits > 2 && digits!!2 == 1 then x Map.! (y+1)
else if Prelude.length digits > 2 && digits!!2 == 2 then x Map.! (z+(x Map.! (y+1)))
else indexOfIndex (y+1)
right = if Prelude.length digits > 3 && digits!!3 == 1 then x Map.! (y+2)
else if Prelude.length digits > 3 && digits!!3 == 2 then x Map.! (z+(x Map.! (y+2)))
else indexOfIndex (y+2)
dest = if op == 3 then (if Prelude.length digits > 2 && digits!!2 == 2 then z+(x Map.! (y+1)) else x Map.! (y+1))
else (if Prelude.length digits > 4 && digits!!4 == 2 then z else 0)+(x Map.! (y+3))

startingState :: Map.Map Int Int -> [Int] -> ((Map.Map Int Int, Int, Int), ([Int], [Int]))
startingState prog input = ((prog, 0, 0), (input, []))
import Intcode

getElements :: ((Map.Map Int Int, Int, Int), ([Int], [Int])) -> [((Int, Int), Int)]
getElements ((prog, y, z), (inputs, outputs)) = if y == -1 then map (\[x, y, i] -> ((x, y), i)) $ Data.List.Split.chunksOf 3 $ Data.List.reverse outputs else getElements $ compute (prog, y, z) (inputs, outputs)
@@ -53,10 +14,9 @@ solveA = Prelude.length . Data.List.filter (\(pos, i) -> i == 2)
solveB :: [((Int, Int), Int)] -> Int
solveB = snd . last


main = do
input <- getArgs
let parsed = parse $ input!!0
let parsed = parseProg $ input!!0

let output = getElements $ startingState parsed []
print $ solveA output

+ 1
- 1
13-care-package/run.sh View File

@@ -1,3 +1,3 @@
#!/bin/sh

runhaskell answer.hs `< input`
runhaskell -i$(dirname $(pwd))/00-utils answer.hs `< input`

+ 2
- 42
15-oxygen-system/answer.hs View File

@@ -2,49 +2,9 @@ import System.Environment
import Data.List as List
import Data.Maybe
import Data.Ord
import Data.List.Split
import qualified Data.Map.Strict as Map

parse :: String -> Map.Map Int Int
parse str = Map.fromList $ List.zip [0..] $ map (read :: String -> Int) $ splitOn "," str

revDigits :: Int -> [Int]
revDigits = Prelude.reverse . Prelude.map (read . return) . show

compute :: (Map.Map Int Int, Int, Int) -> ([Int], [Int]) -> ((Map.Map Int Int, Int, Int), ([Int], [Int]))
compute (x, y, z) (input_orig, output) =
if op == 99
then ((x, -1, z), (input_orig, output))
else if op == 1 || op == 2
then compute ((Map.insert dest ((if op == 1 then (+) else (*)) left right) x), (y+4), z) (input_orig, output)
else if op == 3
then compute ((Map.insert dest input x), (y+2), z) (inputs, output)
else if op == 4
then ((x, y+2, z), (input_orig, (left:output)))
else if op == 5 || op == 6
then compute (x, (if (if op == 5 then (/=) else (==)) left 0 then right else (y+3)), z) (input_orig, output)
else if op == 7 || op == 8
then compute ((Map.insert dest (if (if op == 7 then (<) else (==)) left right then 1 else 0) x), (y+4), z) (input_orig, output)
else if op == 9
then compute (x, y+2, z+left) (input_orig, output)
else
((Map.empty, -1, z), (input_orig, output))
where
(input:inputs) = if Prelude.length input_orig > 0 then input_orig else (0:input_orig)
indexOfIndex y = Map.findWithDefault 0 (x Map.! y) x
digits = revDigits $ x Map.! y
op = (if Prelude.length digits > 1 then 10 * digits!!1 else 0) + digits!!0
left = if Prelude.length digits > 2 && digits!!2 == 1 then x Map.! (y+1)
else if Prelude.length digits > 2 && digits!!2 == 2 then x Map.! (z+(x Map.! (y+1)))
else indexOfIndex (y+1)
right = if Prelude.length digits > 3 && digits!!3 == 1 then x Map.! (y+2)
else if Prelude.length digits > 3 && digits!!3 == 2 then x Map.! (z+(x Map.! (y+2)))
else indexOfIndex (y+2)
dest = if op == 3 then (if Prelude.length digits > 2 && digits!!2 == 2 then z+(x Map.! (y+1)) else x Map.! (y+1))
else (if Prelude.length digits > 4 && digits!!4 == 2 then z else 0)+(x Map.! (y+3))

startingState :: Map.Map Int Int -> [Int] -> ((Map.Map Int Int, Int, Int), ([Int], [Int]))
startingState prog input = ((prog, 0, 0), (input, []))
import Intcode

getPoints :: ((Map.Map Int Int, Int, Int), ([Int], [Int])) -> Map.Map (Int, Int) Int -> (Int, Int) -> Map.Map (Int, Int) Int
getPoints ((prog, y, z), (inputs, outputs)) map pos = if y == -1 then map else if lastObj == 0 then map else List.foldl Map.union Map.empty $ List.map (\(i, p) -> calcNext ((prog, y, z), (inputs, outputs)) map i p) (unmappedNeighbors map pos)
@@ -67,7 +27,7 @@ getMaxDis map pos item = snd $ maximumBy (comparing snd) $ Map.elems $ Map.filte

main = do
input <- getArgs
let parsed = parse $ input!!0
let parsed = parseProg $ input!!0

let map = getPoints (startingState parsed []) (Map.singleton (0, 0) 1) (0, 0)
print $ getMaxDis map (0, 0) 2

+ 1
- 1
15-oxygen-system/run.sh View File

@@ -1,3 +1,3 @@
#!/bin/sh

runhaskell answer.hs `< input`
runhaskell -i$(dirname $(pwd))/00-utils answer.hs `< input`

Loading…
Cancel
Save