From 669e2cfb2c1e72705e0dd84e8b4f3c3dfdfb993a Mon Sep 17 00:00:00 2001 From: xuu Date: Tue, 3 Dec 2024 14:51:54 -0700 Subject: [PATCH 1/4] feat: add day 3 2024 (iter crashes on solution 2) --- aoc2024/day03/example.txt | 1 + aoc2024/day03/example2.txt | 1 + aoc2024/day03/input.txt | 6 + aoc2024/day03/main.go | 247 +++++++++++++++++++++++++++++++++++++ aoc2024/day03/main_test.go | 45 +++++++ runner.go | 13 +- 6 files changed, 309 insertions(+), 4 deletions(-) create mode 100644 aoc2024/day03/example.txt create mode 100644 aoc2024/day03/example2.txt create mode 100644 aoc2024/day03/input.txt create mode 100644 aoc2024/day03/main.go create mode 100644 aoc2024/day03/main_test.go diff --git a/aoc2024/day03/example.txt b/aoc2024/day03/example.txt new file mode 100644 index 0000000..2e1a90a --- /dev/null +++ b/aoc2024/day03/example.txt @@ -0,0 +1 @@ +xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5)) \ No newline at end of file diff --git a/aoc2024/day03/example2.txt b/aoc2024/day03/example2.txt new file mode 100644 index 0000000..b774ec9 --- /dev/null +++ b/aoc2024/day03/example2.txt @@ -0,0 +1 @@ +xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5)) \ No newline at end of file diff --git a/aoc2024/day03/input.txt b/aoc2024/day03/input.txt new file mode 100644 index 0000000..2dabcba --- /dev/null +++ b/aoc2024/day03/input.txt @@ -0,0 +1,6 @@ +)+when())~why(),),mul(712,171)@}-?}mul(506,85)who()%mul(613,601)/;#from()#mul(977,581)~what()?/$^-+(*mul(142,89)[who();*):*mul(64,644)}when()select()mul(652,872)mul(594,202)?%$when(196,699)mul(311,646)<>/how()where()(+:mul(867,971)}&where()'/&[&$mul(192,659)select();<#}mul(367,411)mul(841,862)when()(%!mul(922,272)^;}mul(593,223)mul(918,232)mul(760,145)]^?why()>mul(558,476)where()who()&do()^]($,~&-{where()mul(855,134),(--{mul(691,389)+mul(352,712)why()<(]'/}-mul(138,405)$where()mul(176,679) from()'!why(){:mul(516,55)%*>mul(97,636)mul(30,945)**~what()$,mul(486,399)# ,~~!]mul(277,667);~$[from()how()&mul(412,36)([@@,what()% mul(478,68)&mul(293,979)mul(218,379)~)'?-&from()@mul(887,161)(mul(156,481)who();&[:mul(308,96)mul(718,985),] when())/~>^$mul(84,469)*where()mul(500,291)who()])]*don't()who()select()^;,@mul(837,399)$(,(-who()}'mul(835,602)~:]mul(99,872)how()what()%{who(794,618)>mul(227,398)why()where()-why()what()^/:; mul(753,183)[{ ]#^#%%~mul(196,63)}%don't()who()$ :how(),select()~@mul(214,483),:select()%)}who()mul(198,36)*do()what()mul(330,804)what():+>mul(10,447)*/!mul(580,733):&where()'mul(247,9)$)[:#-select()?do()mul(157,768)why()/ who()$from()where()don't()mul(527,694){how(206,792)mul(314,331)/from()/what()#mul(49,792)',-(why()#/]mul(645,190)from()$?mul(775,2)!+select()+^]from(104,329)!mul(287,711)}select():){mul(770,682)!don't()! *^+ when()]%-mul(291,143)mul(956,213)[[>{%'#*{~mul(569,514)[}how()@;mul(291,643)what()%&-where()#@when()mul(678,494)>%mul(303?<%where()what()mul(601,775)mul(91,748)&why()mul(648,173)~*mul(101,949)*:}>'from()-what()^}mul(890,865)what()mul(398,428),select(261,665)where()when()+mul(315,619what()mul(301,311)^~ where(297,851)#{!+&:mul(548,329)mul(239,714)who()@why()(#+!select()why()do()when()mul(249,859)}>@mul(174,437)how(131,486)mul(294,93)mul(605,381)@#}what():~mul(873,431)#)who()^how()select()from()#mul(411,803)-(>why(){{mul(400,846)mul(705(~+%mul(235,314)how(),where()++<{mul(795,270)how()#? $'*select()mul(301,531)mul(109,954)/mul(451,416)%%!select()mul(834,747)%select()[ mul(457,765)do()when()@mul(779,58)('who()mul(275,708) +])$&mul(546,476)&]mul<}~mul(490,931) why()>~)from()@mul(302,82)mul(625,374)-;>%where()mul(864,633):!-,how()when()mul(748,5)what()!how(447,20)]what()/where()<'}don't()from()}why()mul(837,78)what()&:%where()?mul(402,690)mul(689,472)(:{+&}*+mul(915,883)}?)#from(62,762)-mul(512,958)+who()$#^{*mul(798,476{:@who()#mul(89,309),how()!what()what()where()mul(613,761)^[~~:&do()>mul(375,874))?{why()'@mul(75,714)!<%why():!don't()select()?when()@:?<[~mul(43,740)mul(389,134{'(~- >who()mul(755,490)when() what()mul(391,722);what()mul(107,927)~mul(901,762)+;when()+$^select()mul(609,510)#how():select()@)mul(937,386)) +&){mul(757,236)?how()/[who()'*how(937,357)&when()mul(521,787)where(954,730)#what()^mul(158,498)+mul']do() select()}$mul(60,389):~/;;#where()^mul(958,451)*!{{ %/#:mul(855,921)]mul(558,622))-mul(269,240)+how(626,93)+,$(!mul(735,376)%%[where()mul(868,976)~& @;]mul(597,168)from()what()select()@what()mul(40,231):who()({&who()~don't()+~who()-mul(693,922)/why()mul(597,656)mul(826,321)when()mul(793,429)select()~:~}how()how()@mul(837,77)when()mul(389,114)@mul(362,967)+mul(342,929)#where()~mul(218,879)--+[%]who(933,163)mul(314,457)'&/&,)(mul(362,966)- ^how()>mul(890,685)[;$;#where()how()+mul(239,920):(@;%when()+mul(88,839)&^)@why()what()how()where()[mul(572,398)what()$mul(752,549)what()when()'>[mul(732,854)(+@ {(who(621,788) mul(86,481)how()@*'mul(954,533):how()'from()}-when()mul(826$]}how()mul(482,558){%what()^/&)}^[mul(45,414)}how(){;&how()~#mul(300,115)*)?select()<]%mul(374,474){#select()#mul(215,47)who(){^++?%{&mul(332,567)$mul(357,321)/from()#( why(496,793)mul(501where()@}who()select()}mul(62,985),!select()}#+{{]mul(211,725)?]< :how()select()mul(958,722)#'where()!what()@$mul(157,358)mul(998,511)mul(97,681)*;mul(206,463))*mul(790,146select()when(199,114)&[%!';select(){who()do()mul(960,474^}+why(960,681),~>[why(701,791)mul(865,506)?-;select()/~@do()+{'what()~select()%+mul(638,544)) >$^*mul(583,859){[mulhow()>who()/?^~%mul(19,182)~select()select()select()**+mul(77,374)&@??when()>[mul(630,751)mul(740,291)){@*{what()what()@&who()mul(760,727)where()<^ >][mul(996,13)}{%*when()+*mul(865,56)*]mul(995,58)how()}what()@!!)';(mul(323,37)~mul(348,89);{when()~)'mul)'>what()<$%who()%don't()from(533,539)?'~-'where()-+?mul(917,600);from(672,658)mul(966,120)/'@/'^mul(895,427)mul(842,971)',@mul>who(){mul(670,166)where();)^don't()~$+#:when()?!mul(871,536)who(67,974)do()##select()>+(#mul(502,269)!$[^where()where():where()mul(652,742) +from()#%;why()(why()?mul(43,859){(who()]-:{mul(162,15):>how()@%$:mul(322,158)what()$&*{how()mul(949,468)where()?what()+mul(890,635)@;mul(937,114&+:where()#mul(516,431)who()mul(516,755),}who()'!mul(484,114)*}who()who()]mul(623,440)!%{{why()how()}mul(774,302)&)[{select(873,278)-@mul(91,958)<}?-,>+/from()}mul(910,920)']:~how(996,958))why()@mul(134,589)<''when()mul(853,477*$!mul(204,437) where()#how()>~who()*mul(697,199)[-~}select()mul(928,999)!what()when()!>mul(721,616) }why()%)mul(166,276),^$$[when())-why()mul(921,345)&when()'how()-mul(858,22):when()mul(812,54)how()%@%^&mul(11,654)where()^!)%mul(398,677)what()what()[/$:who(279,228)#mul(649,529)mul(78,877):mul(265'&}!why()how()mul(826,788){*:{?,who():mul(463,163)select()mul(342,950)mul(339,663)from()where(){,who()<:?why()when()mul(568,433)$,select()?mul(182,776)^/*,<%*select()%mul(705,962)what();}mul(717,100)from()mul(664,69 % *mul(423,876);from() who(),mul(630,98)[:?how()from(718,704)mul(356,570)#why()select()')from()@:mul(193,467)when() !!)select(625,819)/(!when()mul(171,718)do()<:,what();select(){$}?mul)+mul(20,284)$/,~from()],^mul(984,419);; mul(503,701)+[(;select()?/mul(634-how()mul(424,769))~ -where()* }who(484,481)how()mul(707,101)*do()where())select()(from()]#who(335,623)when()who()mul(911,436)what()}mul(777,219)what()['}when():select()mul(948,616)%/mul(476+&!&who()'>@]'mul(540,542)select()%when() mul(21,652)^#why():?,![where(),+#{+mul(957,516)select()@who()!mul(949,720)$ >from()[>when()@mul(302,42)*when()};mul(62,497>~~)@how()why()*(mul(664,358),mul(739,738)?/)from()//mul(377,419)}{-what()~why()^[]mul(40,477]#+?]don't() when()]mul(870,3)why();%?-how(721,560)$);[mul(568,692)+~how()mul(638,590)~% ?]mul(901,665)+:;?mul(518{&(+~/#when(87,181)@what())mul(675,719)}why() do() ;^mul(596,35) )mul(427,664){when()what(){select()+%}mul(737,893) mul(709,889)!-@,when();where()mul(129,840)when()mul(920,817)#]?^?why())@@mul(269,369) mul(828,795)@*;where()mul(682,546)from(){/mul(243,207)mul(503,124)[from()where()&what()&}(mul(750,321)how()>'&)mul(970,615)why()~mul(876,7)&:%select(836,319)$who()&mulwhere())/]{mul(312,66) ~'%why()from()mul?{select()] ;?*?select()mul(453,529)why(117,235)^do()@'-+from(370,703)mul(644,160)<[,mul(227,457)~}%%select()^>select(360,884)]mul(925,534)-select()'mul(739,218) &/&how()~^mul(332,459) (&{!select(856,366)-don't()()when()-from(487,696)%?what(768,731)mul(745,482)[,select()mul(880,43)^why()mul*@[[+where()what()how()mul(546,582)from()[/&why()mul(308,97)mul(343,420)}when()~mul(824,505)why()?!who(),mul(261,37)what(580,629)^-mul(554,10)$} %)?^*+mul(519,543)!{&#*mul(71#+select()&'why()*mul(67,843)~>where()]mulwhat()where()/[what() who()(/@/#!/usr/bin/perl&>mul(708,675) +@from()[$from()why(548,875)mul(121,80)}:$-mul(4,306)mul(763,819)how()~)}'what()do()mul(185,413)*don't()how())>:-]mul(988,832)from()#? what():how()~what()?mul(186,334)select()mul(302,939)*&{#+:)+do()[~+'mul(981,447)do())(how()where()&what()?][&mul(31,754)$?*^+-%(>)mul(851,878))>what()^#$do()]?,)mul(470,861)/!what()mul(861,914)@}when()when(535,739)/where()mul(404,36)why()where()do():}mul(192,10){,from()]!'!when();mul(439,983)when()?*where()who()mul(264,570)/where())mul(118,609>~])&<;+what()}mul(740,187)-!why(),{- <&mul(515,176)why()(#&?$who())^mul(861,78)mul(425,831)^*}don't()&);how()]mul(983,533)/mul(871,157)why() why()mul(822,445)*?>/{}what())mul(466,451)what():+?mul(362,799)select()@{~^^mul(808,226),mul(847,636)how()'select()+?mul(965,149)##?~mul(898,404)$select()! mul(704,590)~mul(453,171)!:why()#^< mul(667,115)>select()from()who()how()?/mul(689,875)why()what()})&!&mul(51,975)^]what();:when()don't()[;$ where()why()mul(71,129)who()%mul(841<@mul(61,222)$;[#~~mul(433,310)>from()how(932,844){?-%mul(172,290)select()''how()*-where()%when()mul(868,592),(select():*:/mul(313,54)}from()how()^*]-where()+do()(--select()what(),/ mul(867,197)mul(203,803)+when()%;-where()%<-don't()]]@where()why()!#why()!mul(949,149)]?mul(960,580)how()mul(12,600));mul(210,348)*mul(565,871)'%where()mul(577,267)!#)mul(474,282)<#>%when(255,810)(mul'why()+*when()how()~->]mul(76,674)what()}}%where()where(552,574)mul(172,533)why()mul(166,405)(from()#/how()how() ^^(mul(580@( ^how()from()mul(168,469)}]@how()~mul(319,476)^]from()(what()'>/,^mul(953,57)# how()select()mul(534,477):select(791,428)~$,when()mul(504,444'mul(534,163)where()# %why()!mul;,why()from()}'mul(819,924):mul(914,787) #?select():!+%];mul(743,314)[?#{mul(127,154)how()+[@!]mul(402,199)!)why(774,912)?~,( where()&mul(747,407)don't()>what()where()'why()why()why(844,133)mul(649,89)mul*when()mul(878,257)!>%#>;select()mul(371,837)-;from()where()~-mul(314,883){}mul(952,191)(-#-mul(400,750)what())what()mul(83,753) +who()!select()$}mul(79,756)where()^?',-mul(273,582) why()do()&~) what()what()mul(92,844)where()!what()/>> {%mul(678,890)mul(784,836)mul(184,623) +who()mul(590,239)%%mul(67,657)when()({]mul(556,689)when()/+: :(who()$,~])mul(810,145)$from()^/)?(/>mul(468,772)(~(who()mul(663,347)where() #how(572,145)!<&;mul(704,336)%$++!mul(170,815)from();why()mul(944,939)]select()!mul(584,361)what()~why()[why()>,~mul(794,457)from()~,how(898,290)don't()mul(889,959)where(594,614):who()*/-mul(786,550)!how()mul(481,863)*!select()who():@mul(980,469)when()-&*#~[*~mul(972,650);&from()$!/:$mul(140,685)]/~[{where(409,316)mul(232,721)>why()who(902,515)who()$!where()/>mul(247,605)'what()select()mul(936,163)mul(591,955)how()mul(931,542)how();what()'*;where()&<(,mul(55,798) ,[+what(){^mul(441,281)?mul(570,318)mul(973,304)}what()]mul(45,721)#?@?where()(>!#mul(701,624)select()[-mul*{mul(67,259)(({%+ -+mul(986,986)&from()who()-'mul(726,819):mul(490,252) what()+how()select()-why(423,93)mul(694,82)-how(328,923)>'how()&(%what()*mul(372,723)'?!!}mul(231,968)-!%mul(415,363){mul(723,230why(141,301)^when()mul(123,44)how()#-who(){&!{mul(513,206)mul(651,372)/#'who()%when()when()^how()mul(894,333)*>mul(789,454)mul(527,63)]}!][#-:mul(696,451)-mul(725,992)/({mul(951,218)/*,who()(];}$mul(999!how()+why()~what()$#)(what()mul(866,336)&when()@!]mul(277#+why()when()where()]mul(625,228)don't()how()*from() mul(728,218)[<&mul(685,966)when()]([':>mul(88,454):,mul(980,618)[:mul(983,851)from() (where()mul(136,951)mul(923,850)select()^what()when()where();{-mul(574,853)'!%select()[how()~)!~don't()>+*mul(999,45)%how()$*^mul(663,51)what() mul(72,914)when()where()^*>';from()mul(717,449)from(116,874)!#}^~$()why()mul(253,711)!-?[where()where()$-@do()%#+&&why()&?who()mul(575,697)*{mul(124,326) )};}why()/')mul(524,584)from())who()?~mul(245,768)!how()@)mul(704,867)^from()]%$(?when()mul(90,724)-;]why()?mul(434,982)%[$from()/-mul(947,645)%what()from()~*;why();-mul(637,644)mul(728,998how(363,38)]#[mul(968,268)mul(118!}how()who()&+$mul(512,161)/~+mul-who()mul(627,181);when()&do()}#;select(139,567)what()*from()-why()mul(914,709)mul(372,426)select()/select()(:mul(573,160]select():mul(439,918)mul(8,169)&why()^'mul(417,187))([who()/when()who()>mul(715,150)-how(609,180),mul(208,512)'why()':&mul(998,345) +[:~from(109,28)mul(762,958)-mul(962,739)%mul(808,716)'{(]},<;mul(937,746)where()select(731,533)select()[,how()}select()who()mul(191,854)where()mul(479,494>*why()mul(453,745)/%/mul(857,414):>who() ?mul(724,307))(<&select()mul(514,942)why()<,where(857,995)why()who()(mul(499,812)how()why()select()@,{@,^$mul(870,75){where()%when()}mul(715,952)mul(679,508)]-*#~mul(976,825)@what(311,818);}>+don't()from()!(mul(831,784)select(401,869)>##what()}$}mul(485,631)%when()don't(){%[%where()mul^!'@select()$when(194,342)mul(955,305)when(714,487)!~[mul(132,571)&<<[?}select(424,232)what()mul(728,300)select()where()@>{*mul(695,119)mul(350,526)~/what()when(),?'mul(166,855)%!,who()}why()from()}what()#mul(197,953)from()}from()?mul(608,965)$*]/,(when()what(),mul(393,927)@ what()how(),/mul(157,25)}%:who()-how(727,121)who()[mul(335,527)[%^,>/&where(){select(415,462)mul(450,651)@-where()when()%&('mul(741,677)#what()-:? ;+when()?mul(783,55(!' <{who()when()#(mul(905,243),mul(822,319)>select()- )#why()'^+mul(837,766)^who(69,740);{,{}^?mul(495,650when()select()when()(%why()mul(298,908)?from()-where()mul(781,697)%)$[mul(661,538)<{-&%%&$-how(),,what()mul(634,148)[mul(13,464)*'?what()'$%mul(311,661)]?how()don't()[>^]%when()# where()what()mul(5,587)+!-what() +mul(618,897)#where()where())how(){mul(944,841)@'?,(~~mul(970,389)*,')mul(285,941)^#mul(554,821),&}]/when()mul(906,954)who()why(),!!()why()mul(89,545)~;) why()*)mul(507,709)@mul(977,650)+]how()-, mul(204,198){/$'~}<{]}do())? +;/why()select()%*mul(226,790)< >how())from()$ ;#mul(901,307)?when()+when()when())mul(19,239)>where()(when() mul(964,735)from()mul(484,646)select() ,;@how()$');do()^#what()mul(297,515))#*{;%&~select()mul(404,614))~)[mul(182,657),{from()mul(450,272)(mul(228,343):what()[what()%(mul(970,721) #%> why()mul(879,558) %+?do()-)select()]mul(723,300); *why()mul(384,706)?)do()mul(799,503)~select(327,603)when()<>mul(216,403)select()<{(,mul(721,553)from())?when()mul(319,645)don't()*';how()where()(how(151,143)mul(675,236) 0 { + for i, r := range string(buf) { + println(i, r) + if !yield(r) { + return + } + } + s, _ := in.Read(buf) + buf = buf[:s] + } + + for !yield(-1) { + } + } + next, stop := iter.Pull(seq) + lex := lexer{iter: next, stop: stop} + lex.readRune() + lex.readRune() + return &lex +} + +type lexer struct { + rune rune + next rune + + iter func() (rune, bool) + stop func() + + buf []rune + token string + literal []rune +} + +func (l *lexer) Stop() { l.stop() } + +func (l *lexer) readRune() { + if l.rune == -1 { + return + } + if r, ok := l.iter(); ok { + l.rune, l.next = l.next, r + } else { + l.rune, l.next = l.next, -1 + } +} + +func (l *lexer) loadRune(tok string) { + l.token = tok + l.literal = append(l.literal, l.rune) + l.readRune() +} + +func (l *lexer) loadNumber() { + l.token = "TokNUMBER" + for strings.ContainsRune("0123456789", l.rune) { + l.literal = append(l.literal, l.rune) + l.readRune() + } +} + +func (l *lexer) loadString(accept string) { + l.token = "TokSTRING" + for !(!strings.ContainsRune(accept, l.rune) || l.rune == 0 || l.rune == -1) { + l.literal = append(l.literal, l.rune) + l.readRune() + } +} + +func (l *lexer) NextTok() bool { + l.literal = l.literal[:0] + + switch l.rune { + case 'm': + l.loadString("mul") + l.token = "TokMUL" + if string(l.literal) != "mul" { + l.token = "TokILLEGAL" + return false + } + return true + case 'd': + l.loadString("don't") + switch string(l.literal) { + case "don't": + l.token = "TokDONT" + case "do": + l.token = "TokDO" + default: + l.token = "TokILLEGAL" + return false + } + return true + + case '(': + l.loadRune("TokLPAREN") + return true + case ')': + l.loadRune("TokRPAREN") + return true + case ',': + l.loadRune("TokCOMMA") + return true + + case -1: + l.loadRune("TokEOF") + return false + default: + if '0' <= l.rune && l.rune <= '9' { + l.loadNumber() + return true + } + } + + l.loadRune("TokILLEGAL") + return true +} + +func (l *lexer) Iter() iter.Seq2[string, string] { + return func(yield func(string, string) bool) { + for l.NextTok() { + if !yield(l.token, string(l.literal)) { + return + } + } + } +} + +func readMul(lex *lexer) int { + if lex.token != "TokMUL" || string(lex.literal) != "mul" { + return 0 + } + + var a, b = -1, -1 + if !lex.NextTok() || lex.token != "TokLPAREN" { + return 0 + } + + if !lex.NextTok() || lex.token != "TokNUMBER" { + return 0 + } + a = aoc.Atoi(string(lex.literal)) + + if !lex.NextTok() || lex.token != "TokCOMMA" { + return 0 + } + + if !lex.NextTok() || lex.token != "TokNUMBER" { + return 0 + } + b = aoc.Atoi(string(lex.literal)) + + if !lex.NextTok() || lex.token != "TokRPAREN" { + return 0 + } + fmt.Println(a, "*", b) + return a * b +} + +func readDont(lex *lexer) bool { + if lex.token != "TokDONT" || string(lex.literal) != "don't" { + return false + } + if !lex.NextTok() || lex.token != "TokLPAREN" { + return false + } + if !lex.NextTok() || lex.token != "TokRPAREN" { + return false + } + return true +} + +func readDo(lex *lexer) bool { + if lex.token != "TokDO" || string(lex.literal) != "do" { + return false + } + if !lex.NextTok() || lex.token != "TokLPAREN" { + return false + } + if !lex.NextTok() || lex.token != "TokRPAREN" { + return false + } + return true +} diff --git a/aoc2024/day03/main_test.go b/aoc2024/day03/main_test.go new file mode 100644 index 0000000..0c751f5 --- /dev/null +++ b/aoc2024/day03/main_test.go @@ -0,0 +1,45 @@ +package main + +import ( + "bytes" + "testing" + + _ "embed" + + "github.com/matryer/is" +) + +//go:embed example.txt +var example []byte +//go:embed example2.txt +var example2 []byte + +//go:embed input.txt +var input []byte + +func TestExample(t *testing.T) { + is := is.New(t) + + result, err := run(bytes.NewReader(example)) + is.NoErr(err) + + t.Log(result) + is.Equal(result.valuePT1, 161) + + result, err = run(bytes.NewReader(example2)) + is.NoErr(err) + + is.Equal(result.valuePT2, 48) +} + +func TestSolution(t *testing.T) { + is := is.New(t) + + result, err := run(bytes.NewReader(input)) + is.NoErr(err) + + t.Log(result) + is.True(result.valuePT1 < 186942148) // first attempt too high + is.Equal(result.valuePT1, 184122457) + is.Equal(result.valuePT2, 0) +} diff --git a/runner.go b/runner.go index 4cb1a7f..bce53ff 100644 --- a/runner.go +++ b/runner.go @@ -4,6 +4,7 @@ import ( "bufio" "flag" "fmt" + "io" "log" "os" "path/filepath" @@ -16,7 +17,7 @@ import ( var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`") var memprofile = flag.String("memprofile", "", "write memory profile to `file`") -func Runner[R any, F func(*bufio.Scanner) (R, error)](run F) (R, error) { +func runnerFile[R any, F func(*os.File) (R, error)]() *os.File { if len(os.Args) < 2 { Log("Usage:", filepath.Base(os.Args[0]), "FILE") os.Exit(22) @@ -57,16 +58,20 @@ func Runner[R any, F func(*bufio.Scanner) (R, error)](run F) (R, error) { }() } - input, err := os.Open(inputFilename) if err != nil { Log(err) os.Exit(1) } - scan := bufio.NewScanner(input) + return input +} - return run(scan) +func Runner[R any, F func(*bufio.Scanner) (R, error)](run F) (R, error) { + return run(bufio.NewScanner(runnerFile[R]())) +} +func RunnerReader[R any, F func(io.Reader) (R, error)](run F) (R, error) { + return run(runnerFile[R]()) } func MustResult[T any](result T, err error) { -- 2.45.1 From 7b9a71f84cfe8a534ace39ba9bd7254c8c5f3d8a Mon Sep 17 00:00:00 2001 From: xuu Date: Tue, 3 Dec 2024 15:11:33 -0700 Subject: [PATCH 2/4] chore: state before changes that were working --- aoc2024/day03/main.go | 82 +++++--------------------------------- aoc2024/day03/main_test.go | 9 ++--- 2 files changed, 14 insertions(+), 77 deletions(-) diff --git a/aoc2024/day03/main.go b/aoc2024/day03/main.go index 13bfcd4..54327bc 100644 --- a/aoc2024/day03/main.go +++ b/aoc2024/day03/main.go @@ -24,36 +24,18 @@ func (r result) String() string { return fmt.Sprintf("%#v", r) } func run(read io.Reader) (*result, error) { sum := 0 - sum2 := 0 lexer := Lexer(read) - active := true + for typ, token := range lexer.Iter() { - for typ, _ := range lexer.Iter() { - // fmt.Println(typ, string(token)) - switch { - case typ == "TokMUL": - if m := readMul(lexer); m != 0 { - sum += m - if active { - sum2 += m - } - } - case typ == "TokDONT": - if readDont(lexer) { - println("don't()", active) - active = false - } - - case typ == "TokDO": - if readDo(lexer) { - println("do()", active) - active = true - } + if m := readMul(lexer); m != 0 { + fmt.Println(typ, string(token)) + sum += m } } - return &result{sum, sum2}, nil + + return &result{sum, -1}, nil } func Lexer(in io.Reader) *lexer { @@ -63,8 +45,7 @@ func Lexer(in io.Reader) *lexer { buf = buf[:s] for len(buf) > 0 { - for i, r := range string(buf) { - println(i, r) + for _, r := range string(buf) { if !yield(r) { return } @@ -90,8 +71,8 @@ type lexer struct { iter func() (rune, bool) stop func() - buf []rune - token string + buf []rune + token string literal []rune } @@ -137,24 +118,7 @@ func (l *lexer) NextTok() bool { case 'm': l.loadString("mul") l.token = "TokMUL" - if string(l.literal) != "mul" { - l.token = "TokILLEGAL" - return false - } return true - case 'd': - l.loadString("don't") - switch string(l.literal) { - case "don't": - l.token = "TokDONT" - case "do": - l.token = "TokDO" - default: - l.token = "TokILLEGAL" - return false - } - return true - case '(': l.loadRune("TokLPAREN") return true @@ -198,7 +162,7 @@ func readMul(lex *lexer) int { if !lex.NextTok() || lex.token != "TokLPAREN" { return 0 } - + if !lex.NextTok() || lex.token != "TokNUMBER" { return 0 } @@ -219,29 +183,3 @@ func readMul(lex *lexer) int { fmt.Println(a, "*", b) return a * b } - -func readDont(lex *lexer) bool { - if lex.token != "TokDONT" || string(lex.literal) != "don't" { - return false - } - if !lex.NextTok() || lex.token != "TokLPAREN" { - return false - } - if !lex.NextTok() || lex.token != "TokRPAREN" { - return false - } - return true -} - -func readDo(lex *lexer) bool { - if lex.token != "TokDO" || string(lex.literal) != "do" { - return false - } - if !lex.NextTok() || lex.token != "TokLPAREN" { - return false - } - if !lex.NextTok() || lex.token != "TokRPAREN" { - return false - } - return true -} diff --git a/aoc2024/day03/main_test.go b/aoc2024/day03/main_test.go index 0c751f5..08fbc75 100644 --- a/aoc2024/day03/main_test.go +++ b/aoc2024/day03/main_test.go @@ -26,10 +26,9 @@ func TestExample(t *testing.T) { t.Log(result) is.Equal(result.valuePT1, 161) - result, err = run(bytes.NewReader(example2)) - is.NoErr(err) - - is.Equal(result.valuePT2, 48) + // result, err = run(bytes.NewReader(example2)) + // is.NoErr(err) + // is.Equal(result.valuePT2, 48) } func TestSolution(t *testing.T) { @@ -41,5 +40,5 @@ func TestSolution(t *testing.T) { t.Log(result) is.True(result.valuePT1 < 186942148) // first attempt too high is.Equal(result.valuePT1, 184122457) - is.Equal(result.valuePT2, 0) + //is.Equal(result.valuePT2, 0) } -- 2.45.1 From 127257c494b043447dd863bbf17de62a2e1fcb54 Mon Sep 17 00:00:00 2001 From: xuu Date: Tue, 3 Dec 2024 15:12:39 -0700 Subject: [PATCH 3/4] chore: state after where broken --- aoc2024/day03/main.go | 98 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 11 deletions(-) diff --git a/aoc2024/day03/main.go b/aoc2024/day03/main.go index 54327bc..a609288 100644 --- a/aoc2024/day03/main.go +++ b/aoc2024/day03/main.go @@ -22,33 +22,66 @@ type result struct { func (r result) String() string { return fmt.Sprintf("%#v", r) } func run(read io.Reader) (*result, error) { - sum := 0 + sum2 := 0 lexer := Lexer(read) - for typ, token := range lexer.Iter() { + active := true - if m := readMul(lexer); m != 0 { - fmt.Println(typ, string(token)) - sum += m + for typ, _ := range lexer.Iter() { + // fmt.Println(typ, string(token)) + switch { + case typ == "TokMUL": + if m := readMul(lexer); m != 0 { + sum += m + if active { + sum2 += m + } + } + case typ == "TokDONT": + if readDont(lexer) { + println("don't()", active) + active = false + } + + case typ == "TokDO": + if readDo(lexer) { + println("do()", active) + active = true + } } } - - return &result{sum, -1}, nil + return &result{sum, sum2}, nil } func Lexer(in io.Reader) *lexer { seq := func(yield func(rune) bool) { + defer func() { + if err := recover(); err != nil { + fmt.Println("ERR", err) + return + } + fmt.Println("NO DEFER AND NO PANIC??") + }() + buf := make([]byte, 256) s, _ := in.Read(buf) buf = buf[:s] for len(buf) > 0 { - for _, r := range string(buf) { + for i, r := range string(buf) { + println(i, r) + if i >= 72 { + fmt.Println("START") + } if !yield(r) { return } + if i >= 72 { + fmt.Println("STOP") + } + } s, _ := in.Read(buf) buf = buf[:s] @@ -71,8 +104,8 @@ type lexer struct { iter func() (rune, bool) stop func() - buf []rune - token string + buf []rune + token string literal []rune } @@ -118,7 +151,24 @@ func (l *lexer) NextTok() bool { case 'm': l.loadString("mul") l.token = "TokMUL" + if string(l.literal) != "mul" { + l.token = "TokILLEGAL" + return false + } return true + case 'd': + l.loadString("don't") + switch string(l.literal) { + case "don't": + l.token = "TokDONT" + case "do": + l.token = "TokDO" + default: + l.token = "TokILLEGAL" + return false + } + return true + case '(': l.loadRune("TokLPAREN") return true @@ -162,7 +212,7 @@ func readMul(lex *lexer) int { if !lex.NextTok() || lex.token != "TokLPAREN" { return 0 } - + if !lex.NextTok() || lex.token != "TokNUMBER" { return 0 } @@ -183,3 +233,29 @@ func readMul(lex *lexer) int { fmt.Println(a, "*", b) return a * b } + +func readDont(lex *lexer) bool { + if lex.token != "TokDONT" || string(lex.literal) != "don't" { + return false + } + if !lex.NextTok() || lex.token != "TokLPAREN" { + return false + } + if !lex.NextTok() || lex.token != "TokRPAREN" { + return false + } + return true +} + +func readDo(lex *lexer) bool { + if lex.token != "TokDO" || string(lex.literal) != "do" { + return false + } + if !lex.NextTok() || lex.token != "TokLPAREN" { + return false + } + if !lex.NextTok() || lex.token != "TokRPAREN" { + return false + } + return true +} -- 2.45.1 From 6a1766910744eec3ecedfd0fdaf10ad144a749d0 Mon Sep 17 00:00:00 2001 From: xuu Date: Tue, 3 Dec 2024 16:15:53 -0700 Subject: [PATCH 4/4] feat(aoc2024): complete day 3 part 2 --- aoc2024/day03/main.go | 34 ++++++---------------------------- aoc2024/day03/main_test.go | 9 +++++---- 2 files changed, 11 insertions(+), 32 deletions(-) diff --git a/aoc2024/day03/main.go b/aoc2024/day03/main.go index a609288..31d6474 100644 --- a/aoc2024/day03/main.go +++ b/aoc2024/day03/main.go @@ -28,25 +28,22 @@ func run(read io.Reader) (*result, error) { lexer := Lexer(read) active := true - for typ, _ := range lexer.Iter() { - // fmt.Println(typ, string(token)) - switch { - case typ == "TokMUL": + for lexer.NextTok() { + switch lexer.token { + case "TokMUL": if m := readMul(lexer); m != 0 { sum += m if active { sum2 += m } } - case typ == "TokDONT": + case "TokDONT": if readDont(lexer) { - println("don't()", active) active = false } - case typ == "TokDO": + case "TokDO": if readDo(lexer) { - println("do()", active) active = true } } @@ -57,31 +54,15 @@ func run(read io.Reader) (*result, error) { func Lexer(in io.Reader) *lexer { seq := func(yield func(rune) bool) { - defer func() { - if err := recover(); err != nil { - fmt.Println("ERR", err) - return - } - fmt.Println("NO DEFER AND NO PANIC??") - }() - buf := make([]byte, 256) s, _ := in.Read(buf) buf = buf[:s] for len(buf) > 0 { - for i, r := range string(buf) { - println(i, r) - if i >= 72 { - fmt.Println("START") - } + for _, r := range string(buf) { if !yield(r) { return } - if i >= 72 { - fmt.Println("STOP") - } - } s, _ := in.Read(buf) buf = buf[:s] @@ -153,7 +134,6 @@ func (l *lexer) NextTok() bool { l.token = "TokMUL" if string(l.literal) != "mul" { l.token = "TokILLEGAL" - return false } return true case 'd': @@ -165,7 +145,6 @@ func (l *lexer) NextTok() bool { l.token = "TokDO" default: l.token = "TokILLEGAL" - return false } return true @@ -230,7 +209,6 @@ func readMul(lex *lexer) int { if !lex.NextTok() || lex.token != "TokRPAREN" { return 0 } - fmt.Println(a, "*", b) return a * b } diff --git a/aoc2024/day03/main_test.go b/aoc2024/day03/main_test.go index 08fbc75..259c765 100644 --- a/aoc2024/day03/main_test.go +++ b/aoc2024/day03/main_test.go @@ -26,9 +26,10 @@ func TestExample(t *testing.T) { t.Log(result) is.Equal(result.valuePT1, 161) - // result, err = run(bytes.NewReader(example2)) - // is.NoErr(err) - // is.Equal(result.valuePT2, 48) + result, err = run(bytes.NewReader(example2)) + is.NoErr(err) + is.Equal(result.valuePT1, 161) + is.Equal(result.valuePT2, 48) } func TestSolution(t *testing.T) { @@ -40,5 +41,5 @@ func TestSolution(t *testing.T) { t.Log(result) is.True(result.valuePT1 < 186942148) // first attempt too high is.Equal(result.valuePT1, 184122457) - //is.Equal(result.valuePT2, 0) + is.Equal(result.valuePT2, 107862689) } -- 2.45.1