--- /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)
+    )
+}