hello! Sorry did not post yesterday as was visiting my mum in hospital, but completed day 7 this morning, which I have to say was a bit messy!
Day 8 on the other hand seems a lot of fun and I'm remembering more Haskel (and cateory theory) each new day. It's been a while :-) Anywhy, below is today's soloution(s). I did give into using Parser combinators as it just seemed simplier, but other than that it is all fairly standard.
-- anamorphism for lists, used to generate our program traces and modificationsunfoldr::(b->Maybe(a,b))->(b->[a])unfoldrfb=casefbofJust(a,b')->a:unfoldrfb'Nothing->[]-- our 3 known opcodesdataOp=NOpInt|AccInt|JmpIntderiving(Show,Eq)typeProgram=[Op]typePC=Int-- Simple parserlexer=Token.makeTokenParser(TP.emptyDef{Token.reservedNames=["nop","acc","jmp"]})reserved=Token.reservedlexer-- op codeinteger=Token.integerlexer-- integerwhiteSpace=Token.whiteSpacelexer-- whitespace-- parse individual opcodepOpcode::TP.Parser(Int->Op)pOpcode=(reserved"nop">>returnNOp)<|>(reserved"acc">>returnAcc)<|>(reserved"jmp">>returnJmp)-- parse an individual instructionpInstruction::TP.ParserOppInstruction=doop<-pOpcodewhiteSpaceop.fromIntegral<$>integer-- parse all opsparseOps::String->[Op]parseOps=either(error.show)id.TP.parse(TP.many1(whiteSpace>>pInstruction))""-- given a PC and a set of visited PC, have we been there before?halt::PC->DS.SetInt->Boolhalt=DS.member-- execute a single op, returning a new acc and a function to compute next PCexecuteOp::Op->Int->(Int,PC->PC)executeOp(NOp_)acc=(acc,(+1))executeOp(Accinc)acc=(acc+inc,(+1))executeOp(Jmpi)acc=(acc,(+i))-- step a single op for a given program, at PC, seen PCs, and current Accstep::(Program,PC,DS.SetInt,Int)->Maybe((Bool,Int),(Program,PC,DS.SetInt,Int))step(ps,pc,seen,acc)|pc>=lengthps=Nothing|otherwise=let(acc',next)=executeOp(ps!!pc)accpc'=nextpcinJust((haltpc'seen,acc'),(ps,pc',DS.insertpc'seen,acc'))-- modify an op (NOP => JMP and JMP => NOP), if possiblemodOp::Op->MaybeOpmodOp(NOpi)=Just(Jmpi)modOp(Accinc)=NothingmodOp(Jmpi)=Just(NOpi)-- generate a modified program, if possible, given a Program and PCmods::(Program,PC)->Maybe(MaybeProgram,(Program,PC))mods(ps,pc)=ifpc<lengthpsthenJust(maybe(Nothing,(ps,pc+1))aux(modOp(ps!!pc)))elseNothingwhereauxop=(Just(takepcps++[op]++drop(pc+1)ps),(ps,pc+1))-- produce all traces of a programs executionexecute::Program->[(Bool,Int)]executeps=unfoldrstep(ps,0,DS.empty,0)-- find acc at the point when a single op is executed twicepart1=snd.head.dropWhile(not.fst).execute-- find a acc for a modified program that terminatespart2=fromMaybe0.head.dropWhile(==Nothing).map(p.execute).foldr(\ab->maybeb(:b)a)[].unfoldrmods.(\ps->(ps,0))wherep[(False,v)]=Justvp((True,_):_)=Nothingp(_:xs)=pxs-- run task 1 and task 2 for AOC ay 8main=doops<-readFile"day8_input"<&>parseOpsprint(part1ops)print(part2ops)
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
hello! Sorry did not post yesterday as was visiting my mum in hospital, but completed day 7 this morning, which I have to say was a bit messy!
Day 8 on the other hand seems a lot of fun and I'm remembering more Haskel (and cateory theory) each new day. It's been a while :-) Anywhy, below is today's soloution(s). I did give into using Parser combinators as it just seemed simplier, but other than that it is all fairly standard.