This commit is contained in:
2020-12-16 16:52:43 -08:00
parent 8c537e610f
commit 20e7d9c512
5 changed files with 408 additions and 14 deletions

View File

@@ -23,18 +23,11 @@ fn solve_d13_p1(input: &str) -> usize {
},
|min, bus_id| {
let offset = t % bus_id;
let wait_time = if offset == 0 {
0
} else {
bus_id - offset
};
let wait_time = if offset == 0 { 0 } else { bus_id - offset };
if min.wait_time < wait_time {
min
} else {
WaitTime{
bus_id,
wait_time,
}
WaitTime { bus_id, wait_time }
}
},
);

View File

@@ -92,7 +92,7 @@ impl Mask2 {
let mut or_mask = 0;
for (idx, b) in mask.iter().enumerate() {
match b {
b'0' => {},
b'0' => {}
b'1' => {
or_mask |= 1 << 35 - idx;
}
@@ -107,7 +107,7 @@ impl Mask2 {
fn set_memory(&self, mem: &mut HashMap<u64, u64>, address: u64, value: u64) {
let offset = address | self.or_mask;
for mut floating_value in 0 .. 2 << self.floating.count_ones() {
for mut floating_value in 0..2 << self.floating.count_ones() {
let mut addr = offset;
for bit in BitIndexes::new(self.floating) {
addr = set_bit(addr, bit, (floating_value & 1) == 1);
@@ -126,13 +126,16 @@ fn set_bit(value: u64, bit_idx: u64, enabled: bool) -> u64 {
}
}
struct BitIndexes{
struct BitIndexes {
value: u64,
current_idx: u64,
}
impl BitIndexes {
fn new(value: u64) -> Self {
BitIndexes{value, current_idx: 0}
BitIndexes {
value,
current_idx: 0,
}
}
}
@@ -168,4 +171,4 @@ fn solve_d14_p2(input: &str) -> u64 {
}
}
memory.values().sum()
}
}

129
src/day16.rs Normal file
View File

@@ -0,0 +1,129 @@
use aoc_runner_derive::aoc;
use std::ops::RangeInclusive;
fn split_once<'a>(input: &'a str, delimeter: &str) -> Option<(&'a str, &'a str)> {
let idx = input.find(delimeter)?;
Some((&input[..idx], &input[idx + delimeter.len()..]))
}
struct Rule<'a> {
name: &'a str,
a: RangeInclusive<usize>,
b: RangeInclusive<usize>,
}
impl<'a> Rule<'a> {
fn parse(input: &'a str) -> Option<Self> {
let (name, rem) = split_once(input, ": ")?;
let (a, b) = split_once(rem, " or ")?;
let a = {
let (start, end) = split_once(a, "-")?;
RangeInclusive::<usize>::new(start.parse().ok()?, end.parse().ok()?)
};
let b = {
let (start, end) = split_once(b, "-")?;
RangeInclusive::<usize>::new(start.parse().ok()?, end.parse().ok()?)
};
Some(Rule { name, a, b })
}
fn matches(&self, value: usize) -> bool {
self.a.contains(&value) || self.b.contains(&value)
}
}
#[aoc(day16, part1)]
fn solve_d16_p1(input: &str) -> usize {
let (rules, rem) = split_once(input, "\n\nyour ticket:\n").unwrap();
let (_your_ticket, nearby_tickets) = split_once(rem, "\n\nnearby tickets:\n").unwrap();
let rules: Vec<_> = rules.split('\n').map(|x| Rule::parse(x).unwrap()).collect();
nearby_tickets
.split('\n')
.flat_map(|line| line.split(','))
.filter_map(|x| {
let value: usize = x.parse().unwrap();
if rules.iter().any(|rule| rule.matches(value)) {
None
} else {
Some(value)
}
})
.sum()
}
#[aoc(day16, part2)]
fn solve_d16_p2(input: &str) -> usize {
let (rules, rem) = split_once(input, "\n\nyour ticket:\n").unwrap();
let (my_ticket, nearby_tickets) = split_once(rem, "\n\nnearby tickets:\n").unwrap();
let rules: Vec<_> = rules.split('\n').map(|x| Rule::parse(x).unwrap()).collect();
assert!(rules.len() < 63);
let mut candidates = vec![(1u64 << rules.len()) - 1; rules.len()];
let mut scratch = Vec::with_capacity(rules.len());
for line in nearby_tickets.split('\n') {
scratch.clear();
scratch.extend(line.split(',').map(|field| {
let value = field.parse().unwrap();
// Initialize a bitmap of which rules the field is valid for. `1`
// indicates the value is valid for that field. `0` is invalid.
let mut bitmap = 0u64;
for (rule_idx, rule) in rules.iter().enumerate() {
if rule.matches(value) {
bitmap |= 1 << rule_idx;
}
}
bitmap
}));
if scratch.iter().copied().any(|x| x == 0) {
continue;
}
candidates
.iter_mut()
.zip(scratch.iter())
.for_each(|(candidate, valid_bitmask)| {
*candidate &= valid_bitmask;
});
}
while candidates.iter().copied().any(|x| x.count_ones() > 1) {
for idx in 0..candidates.len() {
let candidate = candidates[idx];
if candidate.count_ones() == 1 {
let mask = !candidate;
for before in &mut candidates[..idx] {
*before &= mask;
}
for after in &mut candidates[idx + 1..] {
*after &= mask;
}
}
}
}
my_ticket
.split(',')
.map(|x| x.parse::<usize>().unwrap())
.zip(candidates.into_iter().map(|x| x.trailing_zeros() as usize))
.filter_map(|(field, rule_idx)| {
if rules[rule_idx].name.starts_with("departure") {
Some(field)
} else {
None
}
})
.product()
}
#[test]
fn test_foo() {
const INPUT: &str = "class: 0-1 or 4-19
row: 0-5 or 8-19
seat: 0-13 or 16-19
your ticket:
11,12,13
nearby tickets:
3,9,18
15,1,5
5,14,9";
solve_d16_p2(INPUT);
}

View File

@@ -5,6 +5,7 @@ pub mod day12;
pub mod day13;
pub mod day14;
pub mod day15;
pub mod day16;
pub mod day2;
pub mod day3;
pub mod day4;