Skip to content

Instantly share code, notes, and snippets.

@corpsmoderne
Created December 3, 2022 21:51
Show Gist options
  • Save corpsmoderne/86a46caf72df0c9c801486d17684625c to your computer and use it in GitHub Desktop.
Save corpsmoderne/86a46caf72df0c9c801486d17684625c to your computer and use it in GitHub Desktop.
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