From b58db2d3c0971677a9eb1d80cb2b29e6bad31c67 Mon Sep 17 00:00:00 2001 From: Akshay Mankar Date: Sun, 3 Dec 2023 21:24:32 +0100 Subject: [PATCH] [haskell] Solve Day 3 --- answers.nix | 4 ++ default.nix | 0 haskell/aoc2023.cabal | 2 + haskell/app/Main.hs | 2 + haskell/default.nix | 4 +- haskell/src/Day3.hs | 85 +++++++++++++++++++++++++ input/day3 | 140 ++++++++++++++++++++++++++++++++++++++++++ input/day3-eg | 10 +++ 8 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 default.nix create mode 100644 haskell/src/Day3.hs create mode 100644 input/day3 create mode 100644 input/day3-eg diff --git a/answers.nix b/answers.nix index e25b34f..10c4370 100644 --- a/answers.nix +++ b/answers.nix @@ -7,4 +7,8 @@ part1 = "2406"; part2 = "78375"; }; + day3 = { + part1 = "531932"; + part2 = "73646890"; + }; } diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..e69de29 diff --git a/haskell/aoc2023.cabal b/haskell/aoc2023.cabal index 309a896..d377fae 100644 --- a/haskell/aoc2023.cabal +++ b/haskell/aoc2023.cabal @@ -19,8 +19,10 @@ library default-language: GHC2021 build-depends: base ^>=4.17.2.0 , containers + , fingertree exposed-modules: Day1 , Day2 + , Day3 executable aoc2023 import: warnings diff --git a/haskell/app/Main.hs b/haskell/app/Main.hs index 68c46cc..47332a7 100644 --- a/haskell/app/Main.hs +++ b/haskell/app/Main.hs @@ -5,10 +5,12 @@ module Main where import Day1 qualified import Day2 qualified import System.Environment (getArgs) +import qualified Day3 main :: IO () main = do getArgs >>= \case ["day1"] -> Day1.run ["day2"] -> Day2.run + ["day3"] -> Day3.run args -> error $ "Invlaid args: " <> show args diff --git a/haskell/default.nix b/haskell/default.nix index 214aac8..0cb6381 100644 --- a/haskell/default.nix +++ b/haskell/default.nix @@ -1,11 +1,11 @@ -{ mkDerivation, base, containers, lib }: +{ mkDerivation, base, containers, fingertree, lib }: mkDerivation { pname = "aoc2023"; version = "0.1.0.0"; src = ./.; isLibrary = true; isExecutable = true; - libraryHaskellDepends = [ base containers ]; + libraryHaskellDepends = [ base containers fingertree ]; executableHaskellDepends = [ base ]; homepage = "https://git.pub.solar/axeman/aoc2023"; description = "Advent of Code 2023"; diff --git a/haskell/src/Day3.hs b/haskell/src/Day3.hs new file mode 100644 index 0000000..2758862 --- /dev/null +++ b/haskell/src/Day3.hs @@ -0,0 +1,85 @@ +module Day3 where + +import Data.Char +import Data.Containers.ListUtils (nubOrd) +import Data.IntervalMap.FingerTree (Interval (..), IntervalMap) +import Data.IntervalMap.FingerTree qualified as IntervalMap +import Data.Map (Map) +import Data.Map.Lazy qualified as Map +import Data.Maybe (mapMaybe) +import Data.Set qualified as Set + +run :: IO () +run = do + (parts, numbers) <- readInput + putStrLn $ "Part 1 Answer: " <> show (part1 parts numbers) + putStrLn $ "Part 2 Answer: " <> show (part2 parts numbers) + +part1 :: PartsMap -> NumbersMap -> Int +part1 parts numbers = do + let partCoords = Map.keysSet parts + potentialPartNumberCoords = + Set.unions $ Set.map (Set.fromList . neighbours) partCoords + partNumberWithCoords = + Set.unions $ + Set.map + (\c -> Set.fromList $ IntervalMap.search c numbers) + potentialPartNumberCoords + partNumbers = map snd $ Set.toList partNumberWithCoords + sum partNumbers + +neighbours :: Coord -> [Coord] +neighbours (x, y) = + [ (x1, y1) + | x1 <- [x - 1 .. x + 1], + y1 <- [y - 1 .. y + 1] + ] + +part2 :: PartsMap -> NumbersMap -> Int +part2 parts numbers = + let starPartCoords = Map.keys $ Map.filter (== '*') parts + gearRatios = mapMaybe (gearRatio numbers) starPartCoords + in sum gearRatios + +gearRatio :: NumbersMap -> Coord -> Maybe Int +gearRatio numbers gearCoord = + let neighbourNums = nubOrd $ concatMap (\c -> nubOrd $ IntervalMap.search c numbers) (neighbours gearCoord) + in case neighbourNums of + [(_, n1), (_, n2)] -> Just (n1 * n2) + _ -> Nothing + +type Coord = (Int, Int) + +type PartsMap = Map Coord Char + +type NumbersMap = IntervalMap Coord Int + +readInput :: IO (PartsMap, NumbersMap) +readInput = do + ls <- lines <$> getContents + pure $ foldr parseLine (mempty, mempty) $ zip [0 ..] ls + +parseLine :: (Int, String) -> (PartsMap, NumbersMap) -> (PartsMap, NumbersMap) +parseLine (x, line) (accParts, accNumbers) = + (parsePartsLine x line accParts, parseNumbersLine x line accNumbers) + +parsePartsLine :: Int -> String -> PartsMap -> PartsMap +parsePartsLine x line acc = + let withIndices = zip [0 ..] line + parts = filter (\c -> snd c `notElem` "0123456789.\n") withIndices + partsWithX = map (\(y, c) -> ((x, y), c)) parts + in acc <> Map.fromList partsWithX + +parseNumbersLine :: Int -> String -> NumbersMap -> NumbersMap +parseNumbersLine x = go 0 Nothing + where + go :: Int -> Maybe (Int, Int) -> [Char] -> NumbersMap -> NumbersMap + go _ Nothing [] m = m + go curY Nothing (c : rest) m + | isDigit c = go (curY + 1) (Just (curY, digitToInt c)) rest m + | otherwise = go (curY + 1) Nothing rest m + go curY (Just (startY, curNum)) [] m = + IntervalMap.insert (Interval (x, startY) (x, curY - 1)) curNum m + go curY (Just (startY, curNum)) (c : rest) m + | isDigit c = go (curY + 1) (Just (startY, curNum * 10 + digitToInt c)) rest m + | otherwise = go (curY + 1) Nothing rest $ IntervalMap.insert (Interval (x, startY) (x, curY - 1)) curNum m diff --git a/input/day3 b/input/day3 new file mode 100644 index 0000000..9a6ea53 --- /dev/null +++ b/input/day3 @@ -0,0 +1,140 @@ +.......855.442......190..................................969..........520.......59.............................................172.......... +.......................-....@...21...........971........................*..............965.......577=..........316..465*169................. +........881.......881....635......*..........*.............%.577.....864.......873.........................742...*...............714..244... +.......*..../..................602......351...423....939.906...*.........899..-..........833..60..%....965...*....309......43......*.*...... +....737......294..........321*.......................$.......337....511.*.........58..............305.*.......153.............130.....638... +..............................821.544*282.........#......391............165...............836..........112.......................*.......... +..............$.....456.....................281....847...................................*....+.....................-448.@728....833........ +.......830...34.......%.......911..........$............553........702......21....279.........226....................................*...... +..........*......................+.....745......./...........&......../.....*......*...................192...247...40................504.... +...........304..938.........258..................679...702..742..$.........656..645..916.......*........*...+........-...263&............... +...841*168.....*.......169../...........@.................%.......633.-758..........*.......993......410.........920.............*195...492. +..............988.186....................689............&.........................554...........@...................*245......794.......@... +....+489..............@.....866..........................354...........567.............949.969...913.....&10....&........................... +350...........691...72..787*..........189.....639.............+...........*771............*....................736.........#..........639... +.................................561.*........&.....449......693.192...........344.....-...........847.....................496.192.39*...... +...912....792...................=.....925.............*..........-....175.232.....*.....887.156.........378.........183.................782. +.........*....217....955.644*...............609.....728.................*....*.....966.......*............*........*........427.494#........ +.....+...49......-.....*.....389........*......*812...................811...327............600..........233........320.&10...&.............. +...155...............259..........629.646..............*194...111...............%...................998.....292................872.......... +.......444.......648.....730.154....*.....657..$....816........*.....%.......618..123.....-...........*.......@........772.@....+.......*200 +..........*.........*.....&....*............*..208......168#..305....510...........*.....907.........901.........582.....$.238........50.... +........544.......935.........344..........106............................271.......849......-............890............................... +.....................................791.......=.................447*55.....*.............504.............*...........504............439.... +..675...........................#547.$...211.197.......814....22.............115.....................-...39..................307.499*....... +....*..........169.....%......%..........*..............*.....*...229................................887.....974....+875....*............... +..933......696.........909.682............624..594*.....622.367....*........-.....-218..........358*............&........319....748.978..... +......546.....*.....................817............636...........562.........716..........730.......195.....897.....-....................... +..18...*......206...890............/............*.......3...-..........286.....................................$...817...................... +.....404............*...334..........706...924..153.800..+.683......1.......685........*160.................................29..........579. +..................312.........498.......*....*.......@.............*....495....*....435............498..........83............*618..-....... +......./................*255............756..132.595...../......373..#.....#.286....................*......901..............*......526...... +.......283...351.....472..........990*..............*..42............815.........85..............996..........*......*418...486............. +426...........................=.......254..........305..........859..........#..-.......491.-.............204.355.780.............../....... +....976.........$.........582.500.............67...........937...$.........267......551.@...915..$........*.........................653..... +........801.....441...740*......................*....145..$.........................*............442...990..........494.................183. +..1........&...............$.................96..950...*......................429..592./....................922....@........................ +.......427...%.....%..680...798..63............*......163....580..........283*..........700...882............*..............=....423*....... +...........524..474......*........*....843.456...670...........*..96*986..........839.......=...&....952.330.726....@.......484........916.. +......500................632....27..*......=.......*..=.............................#..739.953.........&.*..........929.978...........*..... +..........157........................821........384..95............*531...489..478....&...................950......................295...... +......@.........=.........................................31....346...............*...................779........247.......761.............. +854.6..10.....174...........726%.965..........-852.......*...........642.=260...+.462....457...........*............-.......*.........-..... +...*...................32$..........................272*........89.....*......310.........#.......894...83...251.............408.721.303.... +.............................................771........406......*......................*........$..........*.....227$.............*........ +........*.260..758.......*360.....213.......#......425#........49....968........944*131.645..410......*240...354........611.....528......... +.....716.....*........412...........+...................470.............$.......................*..155......................256............. +..........867.........................348..........69......*852..................419...........798........605.........*787.=.......3*994.... +.....443......565.......*....793..744.*..............*270................529......+.................432...........323........+...*.......... +.................*...159.467.....#....612.....=.214............-....805./....911................49.....*.............+.878*..704.382.%900... +.490...542........46........................878...*..........512......*........#....336...445........898........212*........................ +....+.-......868...................................19................508.....$......@........*..............192.....143....636.............. +...............*.............592............176.......608-........*......%..290.-........#....620.....+........*..........*..............814 +............*...586.......60....*.......-.....@.545.@............99....536......815....820........./...598...373.....501....331.........$... +....985..776..........4...*......704.217.........+...531....709............308...................339............................746......... +....*...........359..+..869....................................*...........*..........262.................139...........164...........981... +.....951...........&..........408...315.564.................222..........781.................249.....995...+..........$.*....205.404.*...... +..............351@............*............*.......*../............289.......711......946...*....................102.34.7.......*....65..... +.................../102....550............137...254....772..599+....*...+..%................734.@.......+................................... +....715......591.................................................926...767..719..322............229..721...................../.......*563... +.......*889...$..@..........*.......188......401.......566......................%................................*873.....801.....%......... +.................690.....948...908.@....&....*.../622.....%..............%..........655...676...404.374.....=.747.............622..144...... +...*409.......=.................*.....379..340......................817.850..780.......+.*............*...510.....886..974.......*.......... +844.........622....241*313...475.............................170......*........*.........371..147.............532.........*325....778...802. +.......................................155.&.................@.....480...566..731..440.........*...........%...=..-373...................... +........931..................787....26*....178........372................@........=.........890............540............./........580.500. +.../.....-......988.......94.*.................494....*....*900..339..........652................177.4................%..762................ +..112.............*.606.......423................#.831..227............696..............814......*..................215.............428..... +......247*.....172..=...................955...................%...132......493............*.....43....276.........&.........&............... +..........10.............508..383..409...&..............285..860.%..........%.........916..406..............685....760....473.834........... +..620.395......................-....*......*.......+...%................................*.......496............................*............ +....$.%...760.......$......390.....361..991.285.522....................................437....&........332#.60................302.533....... +..........*.........828........648................................@....864..........*.......632....190............................*......... +220.209.626...802.................................198..961.......901....../.135..294..................*...843.......178............980.$.... +....#...........*.....................493...42.....#.........&.............................582......993..*..........*...908.............916. +..............207..............983......./.*.........269-.223..187.....104...206...827..73.*............542.901.583..78....*................ +.......................97.627...../.........856................*...716......$........#.%....357.............*.............238.........70.... +.........................*..../................................168...=.....................................186.....747-................*.... +....374....747-......*.....525.....92...449.....&..................#...........376...88.........580..447.........................342.814.... +191*..............156.868............*.*.....33.973...........910.176......433...*....*.........%.................*792............*......... +.......+......&...........246......767.133..*.....................................629..928.............233.....945......459....778...849.... +.....493....268..........-...................508...619.....%420....67$.....458....................=.......%./............*.................. +.............................110*....623*331......./.......................#.........263....610.297.........902.......100.....-.473...231... +.........................336.....482................................502................&....*....................-.........542...*...%...... +.924....................*.....................#....853......518......*...371.....905+.....412.................817.................97........ +....*671.770...891.%...374...589.....774...757.....*.................8......*............................................708..............79 +...............-...638..........*.....*.............431.....................104..........552.........346.........%.........*................ +.................................44...995.................................................*..........*..........369........177.....996...... +......949................-.....................351.........................557...........777..........454..538......625................120.. +.......*......242.....201.............953........*......$..957.163...636......-...............-.............*...777..*..............&....... +......169.....$............538...249.......840...900...256....*........*.229...........110.196..............699....*..502..........861.*.... +..........239................................*.......................465...*......&914...=.....*.......*412......147...................392.. +..........*........526......=..........670....613.............625.55...................*.....572....322..............235..........515....... +214....333........*......975.....358....*..&........205.......%...=......487........272.779......................107.%...........*.......... +............215........................556..549.............................*................492..........+......*......359.......944....... +..899..........#..846...........446.............797...98..795.991..........248.+15....457..................664.115........@................. +....+.+.........................*.................#...$......*.......27...................842*86.............................580.813.....481 +......683................288.582...159..................../...............457....................656.....464..99.....................753.... +937*.............752.361*............*..........759=.......635.*550................810@.200*44....*...../.....*...@........927..........*519 +...........*401.*...........41....568................$674...............*977.................................383.306..........*826.......... +........413......143.670....*............620....................%.................957..150.138.33.489..............................916...... +.............542......*.....322.....................808......585.....-.646.......-........*.......*..........#959....732...724*328...*..59.. +.......4......+.....520..%.................294..483*...............56...*........................514....13*.............*..........35....... +........*712....234.....241............712*...................92.........370.....*550.......798............365...........922.....+....550... +....145......&..................498.&....................434.......291.........51...........+.......*.........................902.....*..... +.....@........776...*..........*.....877.....87....*.997*..........*..................285........775.845.........962.....651........509..321 +82...................184.....418..........54*....35.........782%..201...........=734..*......$...................*........../...866.....*... +......416%........................749..................*816...........................830.204.................277......890.....&.........33. +....................961............*....*......319..861..................917..................976..$..............995....*.................. +..920......#828.84..............338..348.64....@........614..............$.....781@............*..29.....875..229*....234.....312........... +.......456......-...&......................................*.................9............280.235..........*..............280*.............. +......&.....277......841.....83.......554....442*769.......418.+603..15*882...%..........*...............920..759...............$.......876. +......................................*..............553..........................784.759......................@...533.......770..=......... +..........936...............*435....29...382.#.........*...603.......121....%..#...*....................&.........../............52......137 +..................340....121.............*....260.....339......11.....*...991..255.970...928.294.........17..457............................ +.......238.518....#..................569..163..............487..=.....578...................*.....*..........*.........86..362.......926.... +.......#....*........*...........467...+.........610.=......&..................@19.....892.....678......44.893..%..627*....*...359.......... +..........431.....450.146.................603...=....872.............745.................@...............@.....987............+............. +..........................$.........848..*..................%....745................443........591...957............................816*72.. +.....892*.....87..191....33....@...+........424........780..611...%..........184%......*...831*......&.....948...............726............ +............-...*...*..........301...904*.....*..........+........................527..494.......123..............................&......... +150.......183...530..872.................710...868.........436.824....727..577...*................*..............#498......&532.842......... +...............................-.....174......................*....&.....=...*.762...............340.312..705...........+................... +..........269....162...873*.....915.....*729.........995..321....102.*.....443........%....205........*....=......15...808......792......... +.333.......*...............425..........................$.*..........286...........556.......*......572...........*............%......348... +........520..766.=.....74*............692...813............81............152............%.....................@....91....................... +............+....670......720..169*......#........164..193......971...........+......991...%..559.288..720*....706........402..18........... +........383........................705.....763....*......*.........*.......6.270..........873....*.........109.............@....-....254*... +..........*....................226.........*...841....+...252...884.......*......48.....*..........................678=..................539 +......911..713...192.594..570...*...........33.....786...............851.807....*....472.890......563......................=.522..../....... +.894%..*............*.........25....&671.................*475....145.%.......137.............953..*...36..125..249*......774...*.549....696. +.......90..273........94.........=...........667......132.......#........120.....*.......697..*..910...*....*......567.......240.......*.... +.....@......*..........*.........294...@.......*..........595............*.....506.......*...655.....295.777......................%..896.... +477.448.179..370....829..356.611......474......76...........*.........972..............726.......................642....829....287.......... +.........................*.....*...........................384.............-................431....291.459#............*.................... +.........296.......715.794..759...............590.................410.......233.............*.....#.....................477..342....729*.... +.....989*...........................568..571.....*.488..98.......*........................123.577.............988...........*....$......285. +...............667.857*127............*....*..343..*............506...702..........295.................*......*.........600.....626.*....... +.......*563......*........................349.....945.................+......@........*....964%......33.642...431.......*............968.... +....229..........48....=....*.....447......................%....745$..........569...787.........*.....................887................... +.......................369...515..............100...........174..............................633.973........................................ \ No newline at end of file diff --git a/input/day3-eg b/input/day3-eg new file mode 100644 index 0000000..624ea4f --- /dev/null +++ b/input/day3-eg @@ -0,0 +1,10 @@ +467..114.. +...*...... +..35..633. +......#... +617*...... +.....+.58. +..592..... +......755. +...$.*.... +.664.598.. \ No newline at end of file