]> aoc.elinar.fr Git - aoc_2024/commitdiff
Day17 - part 1
authoralex <>
Tue, 17 Dec 2024 08:22:18 +0000 (09:22 +0100)
committeralex <>
Tue, 17 Dec 2024 08:22:18 +0000 (09:22 +0100)
src/day17.rs [new file with mode: 0644]
src/main.rs

diff --git a/src/day17.rs b/src/day17.rs
new file mode 100644 (file)
index 0000000..9208ae0
--- /dev/null
@@ -0,0 +1,169 @@
+use std::error::Error;
+use std::path::Path;
+
+struct Computer {
+    regA: u64,
+    regB: u64,
+    regC: u64,
+    prgm: Vec<u8>,
+    ptr: usize,
+    out: Vec<u8>,
+}
+
+impl Computer {
+    pub fn new(input: &str) -> Self {
+        let (regs, mut prgm) = input.split_once("\n\n").unwrap();
+
+        let regs: Vec<u64> = regs.split("\n")
+            .map(|l| l[12..l.len()].parse::<u64>().unwrap())
+            .collect();
+        let regA = regs[0];
+        let regB = regs[1];
+        let regC = regs[2];
+
+        if prgm.ends_with("\n") {
+            prgm = &prgm[0..prgm.len()-1];
+        }
+
+        let prgm: Vec<u8> = prgm[9..prgm.len()].split(",")
+            .map(|v| v.parse::<u8>().unwrap())
+            .collect();
+        let ptr = 0;
+        let out = Vec::new();
+
+        Self { regA, regB, regC, prgm, ptr, out }
+    }
+
+    fn adv(&self, num: u64, operand: u8) -> u64 {
+        num /  2_u64.pow(self.combo(operand) as u32)
+    }
+
+    fn combo(&self, operand: u8) -> u64 {
+        match operand {
+            0 | 1 | 2 | 3 => operand as u64,
+            4 => self.regA,
+            5 => self.regB,
+            6 => self.regC,
+            _ => unreachable!(),
+        }
+    }
+
+    fn run(&mut self) {
+        while self.ptr < self.prgm.len() {
+            let opcode = self.prgm[self.ptr];
+            let operand = self.prgm[self.ptr + 1];
+            match opcode {
+                0 => self.regA = self.adv(self.regA, operand),
+                1 => self.regB ^= operand as u64,
+                2 => self.regB = self.combo(operand) % 8,
+                3 => {
+                    if self.regA != 0 {
+                        self.ptr = operand as usize;
+                        continue;
+                    }
+                },
+                4 => self.regB ^= self.regC,
+                5 => self.out.push((self.combo(operand) % 8) as u8),
+                6 => self.regB = self.adv(self.regA, operand),
+                7 => self.regC = self.adv(self.regA, operand),
+                _ => {}
+            }
+            self.ptr += 2;
+        }
+        //println!("regA={} regB={} regC={} {:?}", self.regA, self.regB, self.regC, self.out);
+    }
+
+    fn print(&self) -> String {
+        let s: Vec<String> = self.out.iter()
+            .map(|v| v.to_string())
+            .collect();
+        s.join(",")
+    }
+}
+
+fn run_part1(input: &str) -> Result<String, Box<dyn Error>> {
+    println!("Running {} - part 1", get_day());
+
+    let mut computer = Computer::new(input);
+    computer.run();
+    Ok(computer.print())
+}
+
+fn run_part2(input: &str) -> Result<String, Box<dyn Error>> {
+    println!("Running {} - part 2", get_day());
+
+    let res = "".to_string();
+    Ok(res)
+}
+
+pub fn run(input: &str) -> Result<(), Box<dyn Error>> {
+    let res = run_part1(input)?;
+    println!("{res}");
+
+    let res = run_part2(input)?;
+    println!("{res}");
+
+    Ok(())
+}
+
+fn get_day() -> String {
+    let filename = file!();
+    Path::new(filename).file_stem().unwrap().to_str().unwrap().to_string()
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    static TEXT_INPUT_0: &str = "\
+Register A: 0
+Register B: 0
+Register C: 9
+
+Program: 2,6";
+    static TEXT_INPUT_1: &str = "\
+Register A: 10
+Register B: 0
+Register C: 0
+
+Program: 5,0,5,1,5,4";
+    static TEXT_INPUT_2: &str = "\
+Register A: 2024
+Register B: 0
+Register C: 0
+
+Program: 0,1,5,4,3,0";
+    static TEXT_INPUT_3: &str = "\
+Register A: 0
+Register B: 29
+Register C: 0
+
+Program: 1,7";
+    static TEXT_INPUT_4: &str = "\
+Register A: 0
+Register B: 2024
+Register C: 43690
+
+Program: 4,0";
+    static TEXT_INPUT_5: &str = "\
+Register A: 729
+Register B: 0
+Register C: 0
+
+Program: 0,1,5,4,3,0";
+
+    #[test]
+    fn test_part1() {
+        assert_eq!("", run_part1(TEXT_INPUT_0).unwrap());
+        assert_eq!("0,1,2", run_part1(TEXT_INPUT_1).unwrap());
+        assert_eq!("4,2,5,6,7,7,7,7,3,1,0", run_part1(TEXT_INPUT_2).unwrap());
+        assert_eq!("", run_part1(TEXT_INPUT_3).unwrap());
+        assert_eq!("", run_part1(TEXT_INPUT_4).unwrap());
+        assert_eq!("4,6,3,5,6,3,5,2,1,0", run_part1(TEXT_INPUT_5).unwrap());
+    }
+
+    #[test]
+    fn test_part2() {
+        assert_eq!("", run_part2(TEXT_INPUT_5).unwrap());
+    }
+}
index 55d2ac4479e643ef2de939b078fd9a71189da524..f34e9c086989fd06620b07d212bbcafb2ccd3026 100644 (file)
@@ -20,6 +20,7 @@ pub mod day13;
 pub mod day14;
 pub mod day15;
 pub mod day16;
+pub mod day17;
 
 fn main() {
     let args: Vec<String> = env::args().collect();
@@ -58,6 +59,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box<dyn Error>> {
         "day14" => day14::run(&input)?,
         "day15" => day15::run(&input)?,
         "day16" => day16::run(&input)?,
+        "day17" => day17::run(&input)?,
         _ => return Err(format!("unknown or unimplemented day \"{day}\"").into()),
     }
     Ok(())