summary refs log tree commit diff homepage
path: root/src
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2016-12-04 01:58:18 -0500
committerJune McEnroe <june@causal.agency>2020-11-22 00:13:50 -0500
commitae746649a32c4d5d7e80695a435f20f99bdea19a (patch)
tree77ac415e35e435d3db9c596654a4064f3c9fa34e /src
parentDay 3 part 2 (diff)
downloadaoc-ae746649a32c4d5d7e80695a435f20f99bdea19a.tar.gz
aoc-ae746649a32c4d5d7e80695a435f20f99bdea19a.zip
Day 4
Diffstat (limited to 'src')
-rw-r--r--src/bin/day04.rs78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/bin/day04.rs b/src/bin/day04.rs
new file mode 100644
index 0000000..9f7d0ab
--- /dev/null
+++ b/src/bin/day04.rs
@@ -0,0 +1,78 @@
+use std::io::{self, Read};
+use std::str::FromStr;
+
+struct Room {
+    name: String,
+    sector_id: u32,
+    checksum: String,
+}
+
+impl FromStr for Room {
+    type Err = ();
+    fn from_str(s: &str) -> Result<Self, ()> {
+        let mut iter = s.trim_right_matches(']')
+            .rsplitn(3, |c| c == '-' || c == '[');
+
+        let checksum = iter.next().ok_or(())?;
+        let sector_id = iter.next().ok_or(())?;
+        let name = iter.next().ok_or(())?;
+
+        Ok(Room {
+            name: name.into(),
+            sector_id: sector_id.parse().map_err(|_| ())?,
+            checksum: checksum.into(),
+        })
+    }
+}
+
+impl Room {
+    fn real(&self) -> bool {
+        let mut letters = [
+            (0, 'a'), (0, 'b'), (0, 'c'), (0, 'd'), (0, 'e'), (0, 'f'), (0, 'g'), (0, 'h'),
+            (0, 'i'), (0, 'j'), (0, 'k'), (0, 'l'), (0, 'm'), (0, 'n'), (0, 'o'), (0, 'p'),
+            (0, 'q'), (0, 'r'), (0, 's'), (0, 't'), (0, 'u'), (0, 'v'), (0, 'w'), (0, 'x'),
+            (0, 'y'), (0, 'z'),
+        ];
+
+        for letter in self.name.chars().filter(|c| c.is_alphabetic()) {
+            let index = letter as u8 - b'a';
+            letters[index as usize].0 -= 1;
+        }
+
+        letters.sort();
+
+        let expected: String = letters.into_iter()
+            .map(|l| l.1)
+            .take(5)
+            .collect();
+
+        expected == self.checksum
+    }
+}
+
+fn solve(input: &str) -> u32 {
+    input.lines()
+        .map(str::parse)
+        .map(Result::unwrap)
+        .filter(Room::real)
+        .map(|room| room.sector_id)
+        .sum()
+}
+
+fn main() {
+    let mut input = String::new();
+    io::stdin().read_to_string(&mut input).unwrap();
+
+    println!("Part 1: {}", solve(&input));
+}
+
+#[test]
+fn part1() {
+    let input = "
+aaaaa-bbb-z-y-x-123[abxyz]
+a-b-c-d-e-f-g-h-987[abcde]
+not-a-real-room-404[oarel]
+totally-real-room-200[decoy]
+";
+    assert_eq!(1514, solve(&input[1..]));
+}