diff --git a/README.md b/README.md index c7847ad..c749057 100644 --- a/README.md +++ b/README.md @@ -88,3 +88,4 @@ This should start the server at `localhost:8080`. ❄️ [Day 01](aoc-solver/src/y2024/day01.rs) ❄️ [Day 02](aoc-solver/src/y2024/day02.rs) +❄️ [Day 03](aoc-solver/src/y2024/day03.rs) diff --git a/aoc-solver/src/y2024/day03.rs b/aoc-solver/src/y2024/day03.rs new file mode 100644 index 0000000..67e36fd --- /dev/null +++ b/aoc-solver/src/y2024/day03.rs @@ -0,0 +1,139 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{anychar, char, digit1}, + combinator::{map, map_res}, + multi::many0, + sequence::{delimited, preceded, separated_pair}, + IResult, +}; + +use crate::solution::{AocError, Solution}; + +#[derive(PartialEq, Debug)] +enum Instruction { + Mul(u32, u32), + Enable, + Disable, +} + +fn parse_mul(input: &str) -> IResult<&str, (u32, u32)> { + preceded( + tag("mul"), + delimited( + char('('), + separated_pair( + map_res(digit1, |i: &str| i.parse::()), + char(','), + map_res(digit1, |i: &str| i.parse::()), + ), + char(')'), + ), + )(input) +} + +fn parse_other(input: &str) -> IResult<&str, ()> { + let (unhandled, _ignored) = anychar(input)?; + Ok((unhandled, ())) +} + +fn parse_instruction(input: &str) -> IResult<&str, Option> { + alt(( + map(tag("do()"), |_| Some(Instruction::Enable)), + map(tag("don't()"), |_| Some(Instruction::Disable)), + map(parse_mul, |(a, b)| Some(Instruction::Mul(a, b))), + map(parse_other, |_| None), + ))(input) +} + +fn parse(input: &str) -> Result, AocError> { + let (_unhandled, parsed) = + many0(parse_instruction)(input).map_err(|err| AocError::parse(input, err))?; + + let instructions = parsed.into_iter().flatten().collect(); + + Ok(instructions) +} + +pub struct Day03; +impl Solution for Day03 { + type A = u32; + type B = u32; + + fn default_input(&self) -> &'static str { + include_str!("../../../inputs/2024/day03.txt") + } + + fn part_1(&self, input: &str) -> Result { + let sum = parse(input)? + .iter() + .map(|instruction| match instruction { + Instruction::Mul(a, b) => a * b, + _ => 0, + }) + .sum(); + + Ok(sum) + } + + fn part_2(&self, input: &str) -> Result { + let mut enabled = true; + let sum = parse(input)? + .iter() + .map(|instruction| match instruction { + Instruction::Mul(a, b) if enabled => a * b, + Instruction::Enable => { + enabled = true; + 0 + } + Instruction::Disable => { + enabled = false; + 0 + } + _ => 0, + }) + .sum(); + + Ok(sum) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_solves_part1_example() { + assert_eq!( + Day03.part_1( + "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))" + ), + Ok(161) + ); + } + + #[test] + fn it_solves_part2_example() { + assert_eq!( + Day03.part_2( + "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))" + ), + Ok(48) + ); + } + + #[test] + fn it_parses_input() { + assert_eq!( + parse("xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"), + Ok(vec![ + Instruction::Mul(2, 4), + Instruction::Disable, + Instruction::Mul(5, 5), + Instruction::Mul(11, 8), + Instruction::Enable, + Instruction::Mul(8, 5), + ]) + ); + } +} diff --git a/aoc-solver/src/y2024/mod.rs b/aoc-solver/src/y2024/mod.rs index 91257ee..25857b3 100644 --- a/aoc-solver/src/y2024/mod.rs +++ b/aoc-solver/src/y2024/mod.rs @@ -2,7 +2,7 @@ use crate::solution::{Solution, Solver}; pub mod day01; pub mod day02; -// pub mod day03; +pub mod day03; // pub mod day04; // pub mod day05; // pub mod day06; @@ -26,7 +26,7 @@ pub mod day02; // pub mod day24; // pub mod day25; -pub const MAX_DAYS: u8 = 2; +pub const MAX_DAYS: u8 = 3; pub struct Y2024; @@ -35,7 +35,7 @@ impl Solver for Y2024 { match day { 1 => day01::Day01.run(input, 1, 2024), 2 => day02::Day02.run(input, 2, 2024), - // 3 => day03::Day03.run(input, 3, 2024), + 3 => day03::Day03.run(input, 3, 2024), // 4 => day04::Day04.run(input, 4, 2024), // 5 => day05::Day05.run(input, 5, 2024), // 6 => day06::Day06.run(input, 6, 2024), @@ -77,7 +77,7 @@ impl Solver for Y2024 { match day { 1 => include_str!("./day01.rs"), 2 => include_str!("./day02.rs"), - // 3 => include_str!("./day03.rs"), + 3 => include_str!("./day03.rs"), // 4 => include_str!("./day04.rs"), // 5 => include_str!("./day05.rs"), // 6 => include_str!("./day06.rs"), diff --git a/aoc-web/src/header.rs b/aoc-web/src/header.rs index dfa0d52..3570d18 100644 --- a/aoc-web/src/header.rs +++ b/aoc-web/src/header.rs @@ -21,6 +21,7 @@ pub fn header(props: &HeaderProps) -> Html { <> + } }, diff --git a/inputs/2024/day03.txt b/inputs/2024/day03.txt new file mode 100644 index 0000000..9bbf58c --- /dev/null +++ b/inputs/2024/day03.txt @@ -0,0 +1,6 @@ +'*when(932,461)!:who()(*mul(662,950)mul(878,53){#+{&%}mul(675,225)^how(648,963)&)#how(924,189)[mul(14,114)!mul(528,270)]#from()mul(866,868) what())mul(253,100); )when()@{mul(827,104))% -,'mul(955,284)/'-(([!from(177,673)*mul(343,826)@}where()mul(211,118)select()why()%who()()do()'where()'+[!--<:mul(734,544)@when()who(239,383)+!,^~mul(362,147))mul(448,470)}where(916,77);select()/mul(885,970)what()(mul(926,912)when(),,-;?'from()@mul(166,868):from()mul(481,818)[how()who()~!,when()why();mul(2,227)do()![-[ where() ;mul(352,331)-[:mul(724,613)&-~@mul(133,235);when(849,671))where()?~where()@%mul(504,704)why()]<&mul(150,546)^:why();where(793,121)~!')[mul(345,200))[%select()why()^:%where()mul(112,504)'(from(194,838) when()]'why(231,15))$mul(480,487)where(335,714)$(;@{mul(542,838)-(mul(111,392))select()>when()mul(416,295)select()why(){from()<:mul(190,460)$(?how()when()mul(597,500)mul(714,782);?%>!mul(303,578)from(481,153)*&;,mul(373,860)~who()how(){mul(871,673)#@why():/[who():}don't()$<+#-(how()%-do()!when()!when()from(342,582)@mul(877,442)from()mul(874,842);[?how()when()who()from()?(mul(415,601)#+/]:mul(132,522)#where(222,639)]from()&[how()~mul(278,563)?,~-?,(why()>mul(740,126)]select()';>]*,where(),mul(853,590)where()'~+mul(284,920)from()/+};-+[?^mul(656,345)]why()mul(185,132)-mul(770,693)~[what()<@-from()mul(200,187)mul(624,299)}mul(811,930)}+$]${&#?mul(805,62){;?when()/,:what()('mul(602,308)#}&^select()<@@how()why()mul(572,706)mul(327,202){'^*who()@mul(965,541)why()?/{[&when()mul(298,736):@}} mul(667,224)why()(- $#mul(641,534)'^mul(981,964)?;}don't()from(208,511)]})from(823,301)why()select()mul(462,251)select(){from()why()$how()'}}mul(83,963)how()$}+~:!,)mul(317,238)*'{ do()mul(408,63)-,*where()who()*@mul(761,933)who()who()&]^mul(757,153) mul(761,877):@#*^where(790,345)$why()mul(464,363)mul(546,662)from()do()-when())'^mul(133,153) +$when()*+:@{[who()do():#when(755,316)select()<){+@mul(228,645)$/who()[+$>from()mul(379,971)what()( )where()-mul(333,963)/(@$why()#when()why()!select()do()[!when()^why()#mul(254,172)!!mul(150-/:!%:who()select()what()?mul(511,672)]?'do();/how()when()&select()select()mul(602,681){where() }mul(52,967)mul(373,270)'&^from(767,468)#@who();-mul(965,683)how()#]#$(@mul(205,224)&*^*!why():&$mul(464,992)who()(&don't()&^mul(41,520)]mul(639,416)select(),who()$mul(322,578)&%%where()(how(580,932)what()&mul(529,241)[??#mul(758,621)*mul(771,275)>select()(why()]mul(87,225)how()how()~@what()how()where()mul(335,347),mul(585,232)$select()/&}^;( mul(594,43)who()~@mul(380,624)mul(678,429);what()what() -/mul(660-select()/mul(305,408);select()~mul(815,711)mul(757,285){how()/why()select()@@){^mul(902,868)from()/'when(){@;mul(295,421)-from()!}<:mul(308,315),when()%/>^$mul(542,950)do()@&^#?~!'how(525,85)mul(191,12)?%]+mul(787,915)-#{#[where(532,178):mul@-mul(941,234){where()?$how()^;%*[$[@[mul(92,115)don't()how()mul(493,708)>:;)~when()&mul(710,155)('<^$+$mul(166,985)]{+mul(171,503)%{select(6,86)-'select()mul(825,487)when()/[:?<>mul(459,298)>]select()!don't()'{:;mul(96,934)}-*,%,don't(){+who()$who()!who()mul(517,278)~}@mul(574,84)^&%:what(),mul(723,445)?$mul(952,833))? @select()~who();*]mul(866,509)}who(174,511)]mul(369,695)-what()select(){~>{mul(191,238)&:!:>'what(),mul(381,727^*:where(670,586))-:mul(922,333)how()?how()&?,;when()]@mul(432,354)}^mul(263,98);}]:,mul(661,118)%! [from())mul(276,921)^]]]^when();select()mul(895,325)why()+where()!from(294,522)^^^~)mul(153,481)mul(861,802)[]how()(*&mul(219,815)-:&%what()what()@mul(377,33)mul(156&<}how()^mul(654,99)/?>-~select()@)mul(20,758)mul(378,510)(^)*who()?#<+mul(652,169)%when():*+how()mul(860,302+don't()'!who()/) mul(376,810)<: !why()>{mul(431,544)+mul(860,291)when()from(),-why()#mul(367who() <]>){from() @,mul(194,2))$why()how()*when()mul(965,720)@]#){where()[,*+mul(461,205)^how();;(^)>mul(10,206)^,< who()%$%~mul(716,424)[mul(76,949)mul(605,201)-mul(84,478)%when()@+~what()~mul(562,278)mul(746,153)who(987,176)mul(70,785)mul(583,929)-why()/why()%! +mul(512,816)'who()mul(869,983)?mul(735;*why(521,585)$do()from()(how()select()mul(594,821++@!mul(602,847)mul(561,601)mul(351,649)~!why()+][?&mul(884,49)}!when()&#where()when()))+mul(853,585)~$$@mul(462,772):-)what()mul(871,925)$>*^mul(488,569)do()what():when()/(+<+<^mul(556,667)select()where()mul(308,658)@/when()]where()({do()%mul(281,279))'$]do()$#from()]::;*;mul(831,254)who(33,9)mul(593,778)/)$!{how() mul(716,94)where()#+where()~+~[select()?do()+<,mul(119,848)how()(what();'[,mul(205,435)mul(462,597)#(<:mul+mul(821,403)&**mul(309,390) +from()*/)where()*@>mul(425,149)[/:,(,;:{#mul(442,406)>(;<$,&%*mul(954{why(467,228)select();{>)%how(604,161)what()from()mul(359,89),from()*];~when()]mul(403,60)?[];*+#,mul(528,565#>;*- mul(894,804) don't()-mul(736,961)mul(169,583)where()#%~@mul(943,85)$,mul(820,12)]mul(86,786)~mul(453,237how()]what()^when()!-mul(826,572)from()?*select())]from())mul(3,29)how()who()@/+when();%mul(285,796)when())mul(193 ^@,from()#what()>'$(mul(313,971)<#mul(871,501)@how();from()from()mul(648,120)$^}{how()&)(mul(170,653)^who()mul(284,948)*mul(338,643how()~who()!}@(>mul(822,278)when(990,725)+do(),what() mul(7,493)][when()why(530,953)mul(241,105)mul(280,649)when()'??~mul(995,913)&how()select()$~mul(461,746)[:;{]//-mul(419,572)mul(347,770)how()mul(566,424)mul(180,109);select()when()where(827,268)/<,+mul(629,648);'(~mul(46,371)+*$what()mul(203,987)mul(686,836)(when()from()what()}];]mul(716,962)where()mul(821,591):>^mul(902,217)$;>where()?~}select()mul(702,261)when(){~!!mul(181,296)?#mul(698,522)@mul(461,392)~who()(]<%!from()don't()>}),%where()mul(562,168)#;from() where()mul(237,53) mul(268,711)when()~]+{'~mul(36,808)#;[:)select()[when()(who()mul(763,177)from()select()why(){/(mul(701,861)>how()!,*what(753,574)@mul(238,46)mul(663,748)&mul(742,855)##/)-mul(818,603)>what()-,mul(835,282)select()>;#*mul(897,85)/where(){!mul(852,153)mul(633,603)-what():where()[[mul(776,51{&from()>%>^mul(64,533)mul(992,697)'when(),mul(331%#%$]*;who()mul(799,100))@[;%<%how()when():mul(781,214)}%!what()from()how()from()mul(609,497)-how()&who()mul>[when()#,[select()mul(848,464)mul(998,874)$]mul(933,654)#*>what()select():[;#when()mul(288,108)select() mul(856,529))#&from()[do()where():who()*[%]?mul(236,606)$*)when());^}mul(458,967)from()who()from(){mul(379,719)<*mul&#!/usr/bin/perl>!who()#mul(357,342)?how():/[from();mul(419,654) +![/mul(665,722)mul(44,793)from() $when()[/from():?mul(910,529)!how()!@>where()mul(85,692)]-%/mul(884,81)who(521,804)what()what(){what()when()mul(990,766)mul(793,200)select()mul(755,282),[(where()+;(#mul(394,96)mul(351,116)-^(mul(641,709)$,mul(982,628!,,[when()^~(how(184,286)what() mul(750,635)}%{%<> ?&mul(931,9)$[mul(698,488)~how():why()^*mul(564,153)}-where()why() what()mul(714,569)from()?[?mul(80,973):#'+don't()}{how()}mul(437,592)(where()?,when()how()%:#mul(295,199) +)}from()>what()}mul(877,282)'where() &~?what(){*mul(222,408)mul(827,819)why() # do();;,why();,[mul(321,402)}who()'mul(755,90)select()what())mul(977,344)#why()who()?+-mul(383,635)($;when()#mul(900,601)+do();mul(206,834)mul(383,432){what(360,811)mul(827,802),)?$where()who()?{do()when()?$why();{{mul(544,551):mul(380,98)where()mul(231,896)mul(248,602)select()(who()mul(338,121),why()):>mul(95,711)?'{mul(638 -)@!mul(681,304)what()~^%(mul(116,692)}&select()why(664,706)why();}&mul(103,869), mul(205,12)}-[mul(979,353)when(){mul(303,476)-/<$!%%]mul(358,341)select()&}who()why(163,835);>+mul(34,734)mul(330,527)mul(428,357)who()[mul(680,857)>-/;when() what()/ select()mul(218,336)&-who()when()where()who()-from()+mul(84,105)when()&?select(477,434)($#'mul(128,545){+'why()+),?'$mul(745,121),what())mul(133,419)@$/$+;who(115,246)^/(mul(135,230)~:^mul(675,10)$(what()%do()+what()-why()mul(838,662)how()%mul(683,258+*mul(492,582))mul(246,947){(mul(548,714)from()*~+[-why()select()mul(118,285)where(){<}/%mul(221,266)#mul(79,261)%why()mul(349,642)what(){<(mul(811,491)mul(852,262)what()where(752,95)<^)mul(133,969{select()mul(252,913)why(765,304);?what()mul(661,7):#%?!'mul(744,62)%)mul(532]select()}when()when()]'[%^mul(565,470)^why()mul(9,544),@ what()mul+&!where()*+mul(659,140)mul(982,671))*@% *''mul(508,215))from()-!]> ~mul(413,418)>[(^,,mul(512,738)!-@what(){!<&mul(545,683)mul(461,493)~'mul(255,513+}{~from()what()mul(10,277)*who()&why();!&+-mul(281,940)how()>/$mul(246,406)@{~how()/<>!don't()-:~(mul(741,150)}mul(271,458))when():!&?mul(645,221) why()))mul(943,83)(select()@'@mul(557,649)(select(93,936)when()~?what() mul(196,320);where()?>who()mul(208,759)+what()&%@why()$do()mul(931,359)#?who()# [*##mul(754,721)@]#from()>;,mul(924,810)~]mul(504,18)&when()+!'>(mul(420,227)<[{{why()do()$who(){','#what()mul(11,549)mul(275,839)+**&what()mul(960,111)~mul(863,559)mul(997,395)?(}>where(),mul(553,109)[^ 'mul(337,751)<>@++;when()what(278,714)mul(50,770) +when()@select()where() ([mul(747,2)~ do()]'[why()(>why()mul(20,45)* ,^&!'~mul(769how()from()-/;mul(101,318)from()what():from()who()%mul(114,822)*why()[>select()where(832,207)from(214,70)from()mul(93,917),*$}:> ~what()mul(650,282){how()mul(556,140)where()what()mul(876,167)+&mul#who()~#}@mul(902,167)^!^%mul(137,823)>mul(550,698)how()'$mul(843,697){)'#-@ )/-mul(617,639)from()select()mul(838,59)why():from()when()mul(512,68) when()from()from(); don't()mul(292,873)){+don't(){]mul(663,183)+select();/- how()+ *mul(638,19)]<}:!&where()%mul(321${mul(145,779)what()[~/>:don't()*##why()*+'mul(268(]$*+how()-'when()mul(845,280)what()^}@mul(989,77)'select()*$?$mul(368,599)@@:'@where())mul(348,748) }$;%+select()?%mul(70,929),,^[]^select()#mul(830,51,?&!mul(858,374),select()when()}why()%what()]select()?mul(180,625)!mul(73,99)mul(445,334)/,!@@mul(464,542)!,from()$?[mul(516,277)]mul(617,538)mul(292,731)-*$*what(289,332):why()>mul(994!select(),>$)mul(289,272){why()/:^/mul(983,85)when()mul(18,611)}mul(466,826)who()--mul(470,873)!+*&mul(101,733)'where()mul(983,778)mul(974,217)/-+/]@from(),>mul(483,292)'?$<},*what()mul(599,699)}/from()[*where(){mul(466,649)#'*:!where()mul(434,181)-/what()$/select()}mul(135,403)+'mul(988,367)mul(699,753)^,':+}})do()mul(876,320)why(){~/mul(550,960)$(*:-?$what()mul(259,261)mul(140,435)mul(981,455)#&}+'mul(434,245))!{mul(905,337)@select(716,497)(#}how(880,682)*from()mul(408,109)!}%don't()%<)how()%/mul(485,635)&from(), :;%/mul(421,957)#mul(138,916)mul(779,979)who();mul(694,921)/[/$!&@select()mul(599,341),}/}#'where()what()who()>mul(990;@ !-why()don't(){*:!what(): ^mul(734,796)-:/where() mul(940,41)what(609,666)'how()what(522,700)mul(602,249)^where()(!~)mul(880,415)select())>(%}mulwhen()why()?<+?mul(744,997)from()#when()+{~where()mul(37,232)#mul(996,205)mul(993,863)why()mul(144,204),,what()mul(169,251) +%who()^why() mul(410,625)from();what(){[+who(67,306)]$mul{how()mul(456,501);&from()]%<&don't()(!where()}@>}!,mul(566,94)> )when()<-mul(725who(77,893),@>who()-!when()mul(197,527)what()+?+, mul(170,190)@*when(){@why()don't():when()^how()>{}]mul(660,36)when()],]how()@~who(14,397)]mul(260,88)who()~select()when()<{,-do():>why() mul(276,661)?)~how()/'&why()mul(199,824)&,$*'(#) mul(919,245)&who()/mul(469,339)[[>why() do()mul(388,947)who()#~mul(145,154>,~{ mul(752,410){,!~why()why()#mul(498,700))!; mul(290,290):@from(176,870)[%@mul(340,622)(when(821,843)+when()%why()+mul(663,681)@^/(? '{select()%don't()where(51,291)&]:mul(253,129)why(){where()select(),^mul(795,485);!why():@mul(799,33)//mul(97,531)from();?@%%mul(833,760)!&!/^#&mul(867,677))@mul(483,613))how()@;)^%;?mul(518,57)!$)-why()what()}how(){*mul(919when()$-),mul(206,121)}+']){mul(46,767)-mul(32,66)where()mul(986,477)why()}:;select()@ {{mul(93,728)%;(%where()select()mul(955,534)($~;mul(743,671)[+<%,+$$$mul(154,834)'who()*select()}#when()!mul(129,508)why()who()++when()mul(343,945)^what()^) >do():mul(586,351):%##who()>#?mul(498,937)],mul(326,512)from()!%#>}from()mul(610,769)how()/mul(955,551)#%,]mul(376,333)<-;when(435,299)#why(){>*%mul(609,536)!>{> :+%&mul(304,490)<[mul(690,195) //where()#&;~mul(499,478)! what()why()why()^mul(923,423)&when()mul(96,306)^why()who()%from()]/how()]mul(731,186)///mul(516,127)$-{ why()!]'mul(280,921)::@(]{how() what()mul(198,835)[-!from()*%mul(149,825) where()where()mul(660,669)(]&@mul(803,556)how(677,591)mul(609,507))?/>@'mul(176,185)[when()from()$}when()where()mul(496,706)why()^<&~?{/%)mul(349,473)how()>?{]!mul(242,815)@%-?;[{~mul(56,909) mul(638,125)#>^select()>^-?-'mul(517,633)why()]%mul(480,954)?'-'>}mul(5,623)what()}from(904,521)](who()