--- /dev/null
+use std::io::BufRead;
+
+use regex::Regex;
+
+pub fn read_program<R>(mut reader: R) -> String
+where
+ R: BufRead,
+{
+ let mut output = String::new();
+ reader.read_to_string(&mut output).unwrap();
+ output
+}
+
+pub fn execute_corrupted_program(prog: &str) -> i32 {
+ let mul_re = Regex::new(r#"mul\((\d{1,3}),(\d{1,3})\)"#).unwrap();
+
+ let mut val = 0;
+ for cap in mul_re.captures_iter(prog) {
+ let n1 = cap[1].parse::<i32>().unwrap();
+ let n2 = cap[2].parse::<i32>().unwrap();
+ val += n1 * n2
+ }
+
+ val
+}
+
+pub fn execute_corrupted_program_dodont(prog: &str) -> i32 {
+ let mul_re = Regex::new(r#"mul\((\d{1,3}),(\d{1,3})\)|don't\(\)|do\(\)"#).unwrap();
+
+ let mut val = 0;
+ let mut enable = true;
+ for cap in mul_re.captures_iter(prog) {
+ match &cap[0] {
+ "don't()" => enable = false,
+ "do()" => enable = true,
+ _ if enable => {
+ let n1 = cap[1].parse::<i32>().unwrap();
+ let n2 = cap[2].parse::<i32>().unwrap();
+ val += n1 * n2
+ }
+ _ => (), // Skip 'mul' instruction.
+ }
+ }
+ val
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ static CORRUPTED_PROGRAM_PART1: &str =
+ r#"xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"#;
+
+ #[test]
+ fn test_part1() {
+ let v = execute_corrupted_program(CORRUPTED_PROGRAM_PART1);
+ assert_eq!(v, 161);
+ }
+
+ static CORRUPTED_PROGRAM_PART2: &str =
+ r#"xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"#;
+
+ #[test]
+ fn test_part2() {
+ let v = execute_corrupted_program_dodont(CORRUPTED_PROGRAM_PART2);
+ assert_eq!(v, 48);
+ }
+}
day02::nb_of_safe_reports_with_tolerance(&reports)
)
}
+
+pub fn day03() -> String {
+ let f = fs::File::open("data/day03.input").unwrap();
+ let program = day03::read_program(BufReader::new(f));
+ format!(
+ "part1: {}, part2: {}",
+ day03::execute_corrupted_program(&program),
+ day03::execute_corrupted_program_dodont(&program)
+ )
+}