aboutsummaryrefslogtreecommitdiff
path: root/2023/17-Clumsy_Crucible
diff options
context:
space:
mode:
Diffstat (limited to '2023/17-Clumsy_Crucible')
-rw-r--r--2023/17-Clumsy_Crucible/example13
-rw-r--r--2023/17-Clumsy_Crucible/first.hs108
-rw-r--r--2023/17-Clumsy_Crucible/input141
3 files changed, 262 insertions, 0 deletions
diff --git a/2023/17-Clumsy_Crucible/example b/2023/17-Clumsy_Crucible/example
new file mode 100644
index 0000000..f400d6e
--- /dev/null
+++ b/2023/17-Clumsy_Crucible/example
@@ -0,0 +1,13 @@
+2413432311323
+3215453535623
+3255245654254
+3446585845452
+4546657867536
+1438598798454
+4457876987766
+3637877979653
+4654967986887
+4564679986453
+1224686865563
+2546548887735
+4322674655533
diff --git a/2023/17-Clumsy_Crucible/first.hs b/2023/17-Clumsy_Crucible/first.hs
new file mode 100644
index 0000000..aa5c6d9
--- /dev/null
+++ b/2023/17-Clumsy_Crucible/first.hs
@@ -0,0 +1,108 @@
+-- requires cabal install --lib megaparsec parser-combinators heap vector
+module Main (main) where
+
+import Control.Applicative.Permutations
+import Control.Monad (void, when)
+import qualified Data.Char as C
+import Data.Either
+import Data.Functor
+import qualified Data.Heap as H
+import qualified Data.List as L
+import qualified Data.Map as M
+import Data.Maybe
+import qualified Data.Set as S
+import qualified Data.Vector as V
+import qualified Data.Vector.Unboxed as VU
+import Data.Void (Void)
+import Text.Megaparsec
+import Text.Megaparsec.Char
+
+import Debug.Trace
+
+exampleExpectedOutput = 102
+
+type Line = VU.Vector Int
+type Input = V.Vector Line
+
+type Parser = Parsec Void String
+
+parseLine :: Parser Line
+parseLine = do
+ line <- some (C.digitToInt <$> digitChar) <* eol
+ return $ VU.generate (length line) (line !!)
+
+parseInput' :: Parser Input
+parseInput' = do
+ line <- some parseLine <* eof
+ return $ V.generate (length line) (line !!)
+
+parseInput :: String -> IO Input
+parseInput filename = do
+ input <- readFile filename
+ case runParser parseInput' filename input of
+ Left bundle -> error $ errorBundlePretty bundle
+ Right input' -> return input'
+
+data Heading = NS | EW deriving (Eq, Show)
+data Position = Position Int Int Int Heading deriving (Show) -- cost x y heading
+instance Ord Position where
+ compare (Position c1 _ _ _) (Position c2 _ _ _) = c1 `compare` c2
+instance Eq Position where
+ (Position c1 _ _ _) == (Position c2 _ _ _) = c1 == c2
+type Candidates = H.MinHeap Position
+type CostsState = M.Map (Int,Int) (Int, Int) -- (x, y) (NSCost, EWCost)
+
+step :: Input -> CostsState -> Position -> [Position]
+step input costs (Position cost x y h) = L.concat [next 1 1 0, next (-1) (-1) 0]
+ where
+ next :: Int -> Int -> Int -> [Position] -- diff increment costchange
+ next 4 _ _ = []
+ next (-4) _ _ = []
+ next d i costChange = case heatLoss of
+ Just hl -> if improvement hl then (Position (cost + costChange + hl) x' y' h') : next (d+i) i (costChange + hl)
+ else next (d+i) i (costChange + hl)
+ Nothing -> []
+ where
+ h' | h == NS = EW
+ | otherwise = NS
+ x' | h' == NS = x
+ | otherwise = x + d
+ y' | h' == NS = y + d
+ | otherwise = y
+ improvement :: Int -> Bool
+ improvement hl = case M.lookup (x', y') costs of
+ Just (h1, h2) -> case h' of
+ NS -> cost + hl < h1
+ EW -> cost + hl < h2
+ Nothing -> undefined -- should not happen, we catch out of bound when looking for heatLoss
+ heatLoss :: Maybe Int
+ heatLoss = case input V.!? y' of
+ Just line -> line VU.!? x'
+ Nothing -> Nothing
+
+compute :: Input -> Int
+compute input = compute' startingCosts startingCandidates
+ where
+ compute' :: CostsState -> Candidates -> Int
+ compute' costs candidates | x == size - 1 && y == size - 1 = cost
+ | improvement = compute' costs' (H.union candidates' (H.fromList $ step input costs position))
+ | otherwise = compute' costs candidates'
+ where
+ candidates' = H.drop 1 candidates
+ costs' = M.insert (x, y) (if h == NS then (cost, snd state) else (fst state, cost)) costs
+ improvement | h == NS = cost < fst state
+ | otherwise = cost < snd state
+ position@(Position cost x y h) = head $ H.take 1 candidates
+ state = costs M.! (x, y)
+ infinity = maxBound :: Int
+ startingCandidates = H.fromList [Position 0 0 0 h|h <- [NS, EW]] :: Candidates
+ startingCosts = M.fromList [((x, y), (infinity, infinity))|x<-[0..size], y<-[0..size]]
+ size = V.length input
+
+main :: IO ()
+main = do
+ example <- parseInput "example"
+ let exampleOutput = compute example
+ when (exampleOutput /= exampleExpectedOutput) (error $ "example failed: got " ++ show exampleOutput ++ " instead of " ++ show exampleExpectedOutput)
+ input <- parseInput "input"
+ print $ compute input
diff --git a/2023/17-Clumsy_Crucible/input b/2023/17-Clumsy_Crucible/input
new file mode 100644
index 0000000..ec67fbd
--- /dev/null
+++ b/2023/17-Clumsy_Crucible/input
@@ -0,0 +1,141 @@
+333213136361262336321612214531777457112145343436646554277834586842636477377358665483232322865545123271135255712112742775561145666154365233356
+625436214642112116663631316165754345156613447614784645884723775385422237785533457846422687888517441575665644164125345724771731422533345336535
+135464262413363523172353673663343124614327663325483447348582478365458326464522365884857228745883344645545337271265517463212456153534241544452
+463341164253235233654257664712176156221273446338438725387868466637872246443458373458772474446735864427171225417624722447465614145334226531133
+612123231364647651775663426212224226114337776577776736788424832776656343782563357835523563646643373362516426762263641757743221457544513132115
+554121446241214313746711736452662635625733462823288665545675563668763743787742653833765545345747825838821335355445434347415641445636564324243
+224451135242133732146576324716743753368865727642288276285674826268356773857358774272262757346428753268886423252537566456457145362241413235356
+312115633663242411233636615741633726487283228864835444425576777233878745223464452866553565685646725656653473162633463643521135773411433452466
+542364224173757771326524416535552277757354762743288837354468764353627364676267546484532727724264832675772357663444464333544311464653635434155
+644453415415675332722151756256718248247685882878285324462473375646475283722538546752748236463677656374757244824312452134314757122175246666133
+553335516731473766365715331215568572352758878273527332573426865584372534367686638785426548725847452264452655432363227522743746771746731616324
+133445474224722676227554462116647666753275526734788533873228633423522662378822462553685245662683348523576827224635133441463776656147576542321
+262263545476415133716375434754684868667682745356337755425335477366862483227738582326352468542752785886234837282845863613725264761734336443244
+114557561615633115446342258245858844385456266756554434328822765476533686573637497788623453646223225852468238675466763313713633227154741356245
+611315162633241542646131578684535533767564585652735786467776834489896877967363837453335767245825426445885342673428236331451157547442775237312
+362261614652576557153353266488324456657568285858237439538887578466544663574533349347999664436466843472663827648852522875316714732344324217372
+154236775775512321522263368636678482445745255477872966786867669355994753645973978496654594795457367226453428858886655252654623377164654233436
+462622424671674313226637785458826766472883676833993634453836356375787779937773696649358983467446647337585265887587723374463642735172144752645
+256461325176535257663462355464575334764872223438763949469848778946443559566434444799354636443886736785674266463345527548557615613664272723332
+624227517633531434243827827654636862345763525366656758486948446474677985365493464466378853868458497378656656647884675348243277163765174172612
+642426252112436471458742474775766555755482666556764666989755347483839876866543593833948554547649543695673778734785343556567234476436622452236
+472761551511731356577488843522288387648575847749585654676577859987674545338478446453935695888655834749368252388424646347784477427672675234731
+747257136413274266658434523648663224583865945533979664865739647394863547663534658684836947849398659354975525423267856334772333414472751271125
+574343547662773544664738635233783383586446637996489896655677988659366366569546668595949965836367778345574626644234463758638787822267745754521
+367475241771674622685256576755377256694657754777544899383684634438534485979934747656784795398385666575337783432384738285554737675522715746365
+256367447543715652882652564564844549667487979647384545688783886347534748746799385454464568597377867697868876544676868477782387732724561552121
+261235663177628353884845384445766258763957538398695337944456734653958794684775489984866453396736953989445799737336434633265843536845722326147
+431276435456537534853737352526378373785887936397348334479754963636988696675746463374338676858375353484947593688636237753457284385777117617624
+421367347552372223365324757658483977886994994547997755837953398686686495795587856558739768889585363493453579446427556683583574426622272442257
+653441321737655477657783556762464689667939878673459467647756948694579899586649949485693964996883964648379558954548747354857488783362127442566
+515161447757685543432764636463458639776554884767986333854576485676459546765778469857646486376565785857443977735796532864253257624473821333334
+336171521157845857727533754249765675378444363369739966487567564657564788675786859867955577864736596843659475696378544727675554642784241753632
+623372113877373226883677764958453497559443687766594489754655444467966644745947494698459586785645959777965677437493446724843825534677422225442
+236731618585276273353786287559939845985699963868795668657679996977589756994768598496447448576699786446978776785836952358253352634682675575162
+765546725582536686487447374798889846794833537458484957646996958598746684878684958848884578574656384796834539634597853385236344482474876472666
+235141347247436634846668336949436933994444973649584458877948958567497986597747594579955455786945889674656448794468553656367688688576238422422
+671623678362665454588528544384845379775883686557595448549476796988894494486867784996978797854689456778495488399676989768386537635625688831242
+514567273474547255558849794485665888753549445498649654858986448467857554544489744945685865544486656543767539535947995573778388352332288357236
+421323835776877754277637737948643468887899675798595548644885557689854854755598964995897678954896674945488794549443555993763265444882527744633
+354668742484843385355475877734984796958775599649956999999868487764495968495996998799544585565676488647789369959545359597757558327676228242324
+223675455323285573553448797956956995447989558679767596794986699975765799696477454587975754758775874888765498885699494634477672743525548872573
+476176284827585535382536674788367479838589886659789789675958497767575745594699578578798877588865566954496744386339878768748227448658776552362
+675625837477642733439383847993547559885769745955958866975847899547878879759976747796969499588689558956864465635487346833935452386378264867816
+472576623464266256473345754344444687595755546988945978967684649897557995775998977845644887549855889776779634755544666998999672672342225572236
+723338425874676478785895383956556476546955695985859465659544888989996856667888856697795988445756499858565899394779558798674387882836464633723
+753728823447466882883747584457899843886998789895745784456685775586887577578765568686646979944897697865577785359537559569439878872222674682675
+274684763532572374694739777585794889467744468465856969675999788859799587656669956766879888694794447678648759598739793358559772824233728356645
+115256466578823832558738735747633445985469799749547867559586775788896687689676778758799785564977797499978848453988848336553978432627386327573
+548252468286265749598354987757696464686857494949578959857786799756957966686965775569557987846877876965964586958467884766384759555228862634247
+775472876326246686637894874745853649677794865574684765688797569775786779676665589897676756784645888896665785543377644867338379482443888857873
+644246825637683644835877767347453454568867554444775599777767668577979986777676558668678688677679776689769699579869596396588947647254276727432
+675667637753876445999597848375487698587994465886656589877797669767788999875799765675659757957578557549945978889843335993675545354636824673588
+453657476346684869637675496555556899746757988568488977766655889967896758557996798965985989857698968976595894997539483568475599986552355853787
+632248555553887766398487683844487988644864579699765575897969566597999875796789796868695775556589856859985497684784986459989377837883752727386
+266885253575644787699874544547358568447586577656878599657789988877699865956869569876989796775779644456759775589884987483797956747657856577762
+723737537288886965937656574853968596447486789966589956855986786958985788878986767699969598779956745799646979669779964733354855388722376852482
+443568274582252776976439948936677979955468588859687866879589988898686988555665587768558588765557864897448688757653998979337985377854464534445
+447864347254476796783339876544897778998589886776989758966555866986869698869987597675579987966765886976856455866796939445755784944224278247282
+286764482526429646636893847639887457964499865677657686675598857859797898986769757875786568567875884684897845464566539854353669377286744552562
+884623287654836563345579989899869797774668448589998785767869696687897686898796989867595959779585698588455599575769555743843637455423642847562
+473473534468357576875845833637898889894456886876658898586788889999978988998996766667995685987759868969954665459945743358543335675522322378342
+558656456533693883798863894469449475765876655569858666587798989687787787989969897758776576759555957456874769876788793436438855695738227383863
+775323532357798584683386967869946765585998787866977987768899897967977677787668867979997875686697856578774577566474536533944646986828353322626
+636525836872783447833786838746487985757947559969566995787998789678697887868999886776987796867865978774949956548865588585333454467763683243723
+223783768826293857378738893588985777747665455658759689799898778786898798968769968866675997995587875974646549667698977489885365856652626534534
+655668564837447467734565736667964785484656976967858568999686677669768867778699977967988896858859975554449795969546794984867597638648248862288
+225343788236467744769383578758544899859678585565557767667976969786769668786977967696677777767879769879599956585486565669653579739367484637542
+835548267463785585868885946675784945686995679868879868987996776666887886779978868697689999897889796585884675744998754566869986454554226637285
+524428887552843774745688555798844499576574787766799978865898668987896987898688678969787697657777676868954858888788978685799658846625432887244
+763757348466458486656985748946874858799455676675987865666678777698899997898866986677866879785687579874469459574889673643598465975777433358366
+558623257663757383557737659894456765449758668885695585688999896679878866779769888776767959786989978696448594745469878439358857637358376632635
+528622755875457489733889333676448449454678675689757776677677989696976997989988998776976656885665797787967855898746764557993438689586832535665
+262728464482859769395553766495674944869965999668566886969668676777777997768868787977768658859995696654799457798859898374396568466488756437887
+487364277357887467848976636677547566648654786665587569798866998968969679896669978778669565988899885979674848554559648349968485933658775276677
+256557832538447785573836549555759676868974976586768988799986797966866968688667679787685978567778888955456854966856893685889888958764585648486
+855327664424565667757758383684697655957747577978978775569899977977699667776898969778876576599586557597548664594777895375789973774584645288543
+732845238734368499538864859548756666479886668687697768598879889678988699668687669688977859865889687898469679897598943336499683959942888535428
+458542434722763964465544385478485684455675996566988868659799887966987786679967897869965595997757965798487494979485589377554593895588267246482
+685847653777387636587598637367844947984698996755976878779587879698766699987897976799568875579798897684584584986654768893364665848656732765345
+762585858463375454454757776765559455786986498756689585998968787967679696669978887887688575658778696897888854989458553333897338689655835452286
+667873648672677658987454838677545846469568967886596768986598796689987767768689666768986658987869955676568588688768453475384649894476834537652
+842528743554868476638843667989678696874765796896959858759975698996797697976896867888777589667795556658457584544444987934878388869422286538442
+665343556563653997694469347978779548957944896859765588765596979887999677667789969589887866968899686678674894597485654658977459957726383878528
+328824677886664984396688493979448944877675767875999859577958979976669668997796865999595779786956688644899745994747993439474788339373534756228
+355756624245748345976656569348866554494757766868566879567996775777969987877698797776568579757957884846984866766974746746679776886436337862352
+355757567353465353488558943489856995554566447865897697675796898598867787679676599676998886658795658757497445698747499484766988999524476665632
+846657543354688449334738753488965977658866855499795568898766969857755689976595969566968775778979897599779888747778646949389737938563864722776
+222542436248338757373365596953577857876777785799965997596579779865977868956968975778576689656575877994977994789888957578689985758278542255648
+826824626578323678956737348575645548667794498456877779558696685766765996577578587987677557956655865887766685575597559586696339864465556545445
+672427854774774447537349755387458787447985567486958868665967999968578888699789679579765855665666979559547795958783794639459777774442844848878
+452738222778884766739495654588679795558448477676597569955979565868955588879678799665558655888789467848675579858647645878346849574448882222864
+758576763255686269387767336544539998768579756648557995595656978897967599569788776975596788679985698969567697489998968793955383784544678786632
+678436753644435345347447966785579845484646744646487695989759998868659588985955685776856855858876655597799764746838845569653937223437636586333
+153356642488363235694785688879876855588546969589468567687885587869879886789976696579686967894679667978785876977786753437476588524434273755854
+317882332358268727633385869964735386459785875794857867997665676899967595976585567676855598555645898564749684567698568497736368755887663276756
+553352323553345584655944375958334686544568859455468796685877879698899655875768559585886794875996949678754578849953483443664676458224858845353
+226242868452584232838385446446584795649549968885595968669559887868595888787986597867775869477996957548958997745474643897437962535233473847335
+763437726764765464384839593494346588548966488976888467686695997587595769966888579976969574885694897878495979536355474365933684556223554783653
+334278427343676884873643567798477894397499659898464896868445778678559678867597585695856677759484646474967738743563443894378377283723754866354
+364424658235542285759346854636443367549844976595677469978794477788586986958755885599989755694446697474644964964983966865983577367685328757466
+455622346675434466627968485848334339354654996796977484977857577887756998698686754756945458949654447788745764956687878957977434537343783638652
+414184424528876752586855777635698734866576769557959785596469664746649494559498845858666498789995498898658847578497464938567723887863346627657
+222772455675785688574998639973555974944766976784479574958877596999849664659945847467647789846894574575635438985969979554995728363778854553125
+677628437436684347656498938477378693894696449576775986548874779449786764447597479766688898875689864965776667499493345574866436336567337437624
+727144464542867245566869335935377934486434974797786595457564598959848687776647496647465959978878559954334348436574447499645564648783242651735
+674465558434274722483688736769576358375786454868584589888544764896746786474855594477756874777796878944535948989854563367676767484465444776326
+726533354666455265533323549584966633794448865544599665579849559497987549997649674549948764954685654349464854738689883675423622887538654821713
+535573223637762777632285839887974778679897479369667476556956869879497768758647674887896647544666687975893857695458543723255688642672675862221
+255535736242852283868554325347575397384336774436484858866587586755899486587655454967555665966975663696979486933568746833678573262445584616646
+214572456854867737354845558369476949957347579668976958674554696576744766648687859866476774777643597768347583663398885752627665835224846512477
+371732321862355823583888685844948884786873347664969678964485466654478449789884489776849689977577875398656486579666646252236884842427525351222
+755452776637557847683266785359855837945944434565975844659787695696599787667855996799896894795583563369965993837535988483426388337385551317346
+624247422144477474527542264625377545399353835655777686676558457988798589686775496667468777664876676594688543354784668676457344367483543224435
+726747757662436335676345653676447795979833784595875464445795867894945684668894664784796997383764953754343447734898852834456338785274333454615
+656524125146784236674758852648558449357375838974493447769796646554486847575545464888994338434735849538353478789986482347532782254363661472563
+741673514746232538637764537446675846398449657483463375339458595884669445554943846844543788465649464966859863755825887888234583773257611734354
+115447175112756867445654567638362867738959786833688557394833846766836963768548698489347967855973377359398374424534763322552454276872625532313
+646447735554116277864467783735634526644379536385485867549646689936365936747569865533745486769389548684434696386454368652483866265564264175517
+156357554736777347244836373377643868656397864867543567474734466399984876557668389778368878535399696963467657336387568483474722445664715556671
+676531166544312447583457363455235228663973454388438947673946746397554543958554839695589977738346656754557864443875267837373884832321325454352
+375454737124536248825826374335662725588486787449847987633835885576444673594585963544539687578738858696895377838727858622246743261771513171412
+663221374752176732356433254854467623222337544745757575986873573348797879683544358747747883345378444998345746855624868354582726326427315146522
+372672327573647444768323574353783836558756863845757974999357964793355369499865757489588866744979345496744543385375627278633243325452754777727
+274411174533334575377634754324275384762783855996735464353753454977454863488377875438734385846633365787658277884763677557882653763245234776223
+146347645243261273336652374224464433425686378576955887786883747389484868679879937578846538888495848456473877527237835533565641525351147615326
+141327513341666141456432262572624453542782332474487533834446535778573599686333378976786438944868387632546466422733238663662467436527227326373
+452334645227737122357346433753223664266624686726288755858638875989736854855937375897383455453552262745532864542645456757322527154263366545246
+564567126412756234244374586823572827374582865645538367879397839863933576769579345934496455586668763835224477367878667425336151337125473517231
+522573127256225475151321676282788662828282654287378334654664485457379835977568695853846443237655738445627723762862432252247713467242214222715
+115232137775553663237162765368267344427487347824665373483627845573784686839985736626727684228876547543784372385582862455642317132377274374326
+614413156371526427352242352155873282328737854473556666586484765738353332376774777335743758274258857326568365427873811553131613135216564354355
+253143425547637746352146673345427633575267732435583484844824334674266868882434835445546486887675482737678485652343545677362731672733355235426
+135416521244316712675247627473738882768645567522443286388764423448534575553633387378644626683283266657388887325266535244771737424147617432243
+224264636446232647421555321542226827527468366836655546266327524662542748584562245765823264636467576284785684627137242762421431155713541156551
+125223515312471412437476611237727888843547672522485265335266476756823553686844257655425377577535653447587823487447715644722565471412322644515
+466226253356466742613422245771772648283625753376568357583424862627265425238836236538423663853668245256256886743613661555715336473155535446153
+156113463546647546677356722765372325222684267767736523785588826535245724585442626474425786735443647537842265534261737657677635756761552664461
+413165222554534642614256513354313511531447235383325856686642346288744536764733824582786672755644735786636555447622131315536651514411612546144
+122656344636144672343462327767372421575444642365688282487355348223472385562684363233663426485262384645652447136253111261762331217515423142461
+625544236663123525632771524343756333375737354285885448862737335573726334374686245844372776387666268514551657774225657652271651412245212411451
+423126354124653331672162233413635177574771624528322686824883233468774665567775866376682464873886553453552265645627675251266551441231365256263