niels 2 年 前
コミット
328e574017
6 ファイル変更243 行追加0 行削除
  1. 76 0
      src/bin/day3.rs
  2. 67 0
      src/bin/day4.rs
  3. 76 0
      src/bin/day5.rs
  4. 7 0
      test_inputs/day3.txt
  5. 7 0
      test_inputs/day4.txt
  6. 10 0
      test_inputs/day5.txt

+ 76 - 0
src/bin/day3.rs

@@ -0,0 +1,76 @@
+use aoc2022_niels_overkamp::common::{self, AOCResult};
+
+const DAY: &str = "day3";
+
+const OFFSET_LOWER_BYTE: u8 = b'a'; // 0x61
+const OFFSET_UPPER_BYTE: u8 = b'A'; // 0x41
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+    common::run(DAY, &run)
+}
+
+pub fn run(input: &Vec<String>) -> AOCResult {
+    let mut running_sum = 0;
+    let mut running_group_sum = 0;
+    let mut group_i = 0;
+    let mut group_union = !0;
+    for line in input {
+        let line = line.as_bytes();
+        let mut left = 0u64;
+        for b in &line[..line.len()/2] {
+            let prio = if *b > OFFSET_LOWER_BYTE {
+               *b - OFFSET_LOWER_BYTE
+            } else {
+                *b - OFFSET_UPPER_BYTE + 26
+            };
+            left |= 1 << (prio as u64);
+        }
+        let mut right = 0u64;
+        for b in &line[line.len()/2..] {
+            let prio = if *b > OFFSET_LOWER_BYTE {
+               *b - OFFSET_LOWER_BYTE
+            } else {
+                *b - OFFSET_UPPER_BYTE + 26
+            };
+            right |= 1 << (prio as u64);
+        }
+
+        let duplicate = left & right;
+        let mut check = 1;
+        let mut prio = None;
+        for i in 1..53 {
+            if duplicate == check {
+                prio = Some(i);
+                break;
+            }
+            check <<= 1;
+        }
+        let prio = prio.unwrap();
+        running_sum += prio;
+
+        let union = left | right;
+        group_union &= union;
+        println!("{}, {}", union, group_union);
+        let mut check = 1;
+        if group_i == 2 {
+            group_i = 0;
+            for i in 1..53 {
+                if group_union == check {
+                    running_group_sum += i;
+                    break;
+                }
+                check <<= 1;
+            }
+            group_union = !0;
+        } else {
+            group_i += 1;
+        }
+
+    }
+    Ok([Some(running_sum.to_string()), Some(running_group_sum.to_string())])
+}
+
+#[test]
+pub fn test_day3() {
+    assert!(common::run_test(DAY, &run))
+}

+ 67 - 0
src/bin/day4.rs

@@ -0,0 +1,67 @@
+use std::{ops::Range, num::ParseIntError, str::FromStr};
+
+use aoc2022_niels_overkamp::common::{self, AOCResult};
+
+const DAY: &str = "day4";
+
+struct RangePair {
+    range1: Range<u64>,
+    range2: Range<u64>
+}
+
+impl RangePair {
+    fn self_contains(&self) -> bool {
+        (self.range1.start >= self.range2.start && self.range1.end <= self.range2.end) ||
+            (self.range2.start >= self.range1.start && self.range2.end <= self.range1.end)
+    }
+
+    fn self_overlaps(&self) -> bool {
+        self.self_contains() || self.range2.contains(&self.range1.start) || self.range2.contains(&(self.range1.end - 1))
+    }
+
+}
+
+impl FromStr for RangePair {
+    type Err = ParseIntError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let ((r1_start, r1_end), (r2_start, r2_end)) = s.split_once(",")
+                                                        .and_then(|(r1, r2)| r1.split_once("-").zip(r2.split_once("-")))
+                                                        .unwrap();
+        let r1_start = r1_start.parse::<u64>()?;
+        let r1_end = r1_end.parse::<u64>()?;
+        let r2_start = r2_start.parse::<u64>()?;
+        let r2_end = r2_end.parse::<u64>()?;
+
+        Ok(RangePair {
+            range1: Range { start: r1_start, end: r1_end + 1 },
+            range2: Range { start: r2_start, end: r2_end + 1 }
+        })
+    }
+}
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+    common::run(DAY, &run)
+}
+
+pub fn run(input: &Vec<String>) -> AOCResult {
+    let input = input.iter()
+                     .map(String::as_str)
+                     .map(str::parse::<RangePair>)
+                     .map(Result::unwrap);
+    let self_contains_count = input
+        .clone()
+        .map(|rp| rp.self_contains())
+        .filter(|b| *b)
+        .count();
+    let self_overlaps_count = input
+        .map(|rp| rp.self_overlaps())
+        .filter(|b| *b)
+        .count();
+    Ok([Some(self_contains_count.to_string()), Some(self_overlaps_count.to_string())])
+}
+
+#[test]
+pub fn test_day4() {
+    assert!(common::run_test(DAY, &run))
+}

+ 76 - 0
src/bin/day5.rs

@@ -0,0 +1,76 @@
+use aoc2022_niels_overkamp::common::{self, AOCResult};
+
+const DAY: &str = "day5";
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+    common::run(DAY, &run)
+}
+
+pub fn run(input: &Vec<String>) -> AOCResult {
+    let mut stacks: Vec<Vec<u8>> = vec![];
+    let mut input_iter = input.into_iter();
+    let mut operations: Vec<(usize, usize, usize)> = vec![];
+    'line: loop {
+        let line = input_iter.next();
+        if line.is_none() {
+            break
+        }
+        let line = line.unwrap();
+        for (container, i) in line.as_bytes().chunks(4).zip(0..) {
+            if i >= stacks.len() {
+                stacks.push(vec![]);
+            }
+            match container {
+                &[b' ', b' ', b' ', b' '] => (),
+                &[b'[', c,    b']'] | &[b'[', c,    b']', b' '] => stacks[i].insert(0, c),
+                &[_, b'1', _, _]          => break 'line,
+                _ => eprintln!("Unknown container {:?}", container)
+            }
+        }
+    }
+
+    input_iter.next();
+
+    for line in input_iter {
+        let (amount, from, to) = line.strip_prefix("move ")
+            .and_then(|s| s.split_once(" from "))
+            .and_then(|(amount, s)| s.split_once(" to ")
+                      .map(|(from, to)| (amount, from, to)))
+            .ok_or_else(|| format!("Could not parse line {}", line))?;
+
+        let (amount, from, to) = (amount.parse::<usize>()?, from.parse::<usize>()? - 1, to.parse::<usize>()? - 1);
+        operations.push((amount, from, to))
+    }
+
+    let mut stacks1 = stacks.clone();
+
+    for (amount, from, to) in operations.iter() {
+        let from_stack = stacks1.get_mut(*from).ok_or_else(|| format!("From stack does not exist in operation {:?}", (amount, from, to)))?;
+
+        let picked_up: Vec<_> = from_stack.drain((from_stack.len() - amount)..).collect();
+
+        let to_stack = stacks1.get_mut(*to).ok_or_else(|| format!("To stack does not exist in operation {:?}", (amount, from, to)))?;
+        to_stack.extend(picked_up.iter().rev());
+    }
+    let message1: String = stacks1.into_iter().map(|mut s| s.pop().unwrap() as char).collect();
+
+    let mut stacks2 = stacks;
+
+    for (amount, from, to) in operations.iter() {
+        let from_stack = stacks2.get_mut(*from).ok_or_else(|| format!("From stack does not exist in operation {:?}", (amount, from, to)))?;
+
+        let picked_up: Vec<_> = from_stack.drain((from_stack.len() - amount)..).collect();
+
+        let to_stack = stacks2.get_mut(*to).ok_or_else(|| format!("To stack does not exist in operation {:?}", (amount, from, to)))?;
+        to_stack.extend(picked_up);
+    }
+
+    let message2: String = stacks2.into_iter().map(|mut s| s.pop().unwrap() as char).collect();
+
+    Ok([Some(message1), Some(message2)])
+}
+
+#[test]
+pub fn test_day5() {
+    assert!(common::run_test(DAY, &run))
+}

+ 7 - 0
test_inputs/day3.txt

@@ -0,0 +1,7 @@
+vJrwpWtwJgWrhcsFMMfFFhFp
+jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
+PmmdzqPrVvPwwTWBwg
+wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
+ttgJtRGJQctTZtZT
+CrZsJsPPZsGzwwsLwLmpwMDw
+157$70

+ 7 - 0
test_inputs/day4.txt

@@ -0,0 +1,7 @@
+2-4,6-8
+2-3,4-5
+5-7,7-9
+2-8,3-7
+6-6,4-6
+2-6,4-8
+2$4

+ 10 - 0
test_inputs/day5.txt

@@ -0,0 +1,10 @@
+    [D]
+[N] [C]
+[Z] [M] [P]
+ 1   2   3
+
+move 1 from 2 to 1
+move 3 from 1 to 3
+move 2 from 2 to 1
+move 1 from 1 to 2
+CMZ$MCD