Created
December 3, 2022 21:51
-
-
Save corpsmoderne/86a46caf72df0c9c801486d17684625c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use itertools::Itertools; | |
use std::convert::From; | |
use std::fs::File; | |
use std::io::{self, BufRead}; | |
use std::ops::BitAnd; | |
fn main() { | |
let backpacks = get_data("./input"); | |
println!("Part1: {}", part1(&backpacks)); | |
println!("Part2: {}", part2(&backpacks)); | |
} | |
fn part1(backpacks: &[Vec<u8>]) -> u32 { | |
backpacks | |
.iter() | |
.map(|group| { | |
let half = group.len() / 2; | |
let first = &group[0..half]; | |
let second = &group[half..]; | |
let double = (Set::from(first) & Set::from(second)) | |
.iter() | |
.next() | |
.expect("no double found"); | |
get_val(double) | |
}) | |
.sum() | |
} | |
fn part2(backpacks: &[Vec<u8>]) -> u32 { | |
backpacks | |
.iter() | |
.tuples() | |
.map(|(g1, g2, g3)| { | |
let badge = (Set::from(g1) & Set::from(g2) & Set::from(g3)) | |
.iter() | |
.next() | |
.expect("no badge found"); | |
get_val(badge) | |
}) | |
.sum() | |
} | |
fn get_data(filename: &str) -> Vec<Vec<u8>> { | |
let file = File::open(filename).unwrap(); | |
io::BufReader::new(file) | |
.lines() | |
.map(|l| l.unwrap().bytes().collect()) | |
.collect() | |
} | |
fn get_val(b: u8) -> u32 { | |
if (b'a'..=b'z').contains(&b) { | |
(b - b'a' + 1) as u32 | |
} else if (b'A'..=b'Z').contains(&b) { | |
(b - b'A' + 27) as u32 | |
} else { | |
panic!("bad input"); | |
} | |
} | |
// My custom Set | |
#[derive(Debug, Clone, Copy)] | |
struct Set { | |
tbl: [bool; 256], | |
} | |
impl Set { | |
fn iter(&self) -> impl Iterator<Item = u8> + '_ { | |
SetIter { set: self, idx: 0 } | |
} | |
} | |
impl From<&[u8]> for Set { | |
fn from(v: &[u8]) -> Self { | |
let mut tbl = [false; 256]; | |
for b in v { | |
tbl[*b as usize] = true; | |
} | |
Self { tbl } | |
} | |
} | |
impl From<&Vec<u8>> for Set { | |
fn from(v: &Vec<u8>) -> Self { | |
Self::from(v.as_slice()) | |
} | |
} | |
impl BitAnd for Set { | |
type Output = Self; | |
fn bitand(self, rhs: Self) -> Self { | |
let mut set = Set { tbl: self.tbl }; | |
for (i, &b) in rhs.tbl.iter().enumerate() { | |
set.tbl[i] &= b; | |
} | |
set | |
} | |
} | |
struct SetIter<'a> { | |
set: &'a Set, | |
idx: usize, | |
} | |
impl<'a> Iterator for SetIter<'a> { | |
type Item = u8; | |
fn next(&mut self) -> Option<Self::Item> { | |
while self.idx < self.set.tbl.len() { | |
if self.set.tbl[self.idx] { | |
return Some(self.idx as u8); | |
} | |
self.idx += 1; | |
} | |
None | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment