Correct formatting.

This commit is contained in:
2019-02-18 15:13:48 +01:00
parent 171d9fa2e9
commit c16ef40d73
28 changed files with 316 additions and 195 deletions

View File

@@ -37,18 +37,17 @@ fn test_part2(day: u32, bench: &mut Bencher) {
} }
macro_rules! day_bench { macro_rules! day_bench {
( $name:ident, $day:expr ) => { ( $name:ident, $day:expr ) => {
pub mod $name { pub mod $name {
use super::*; use super::*;
pub fn part1(bench: & mut Bencher) { pub fn part1(bench: &mut Bencher) {
test_part1( $day, bench); test_part1($day, bench);
}
pub fn part2(bench: & mut Bencher) {
test_part2( $day, bench);
}
} }
benchmark_group!( $name, $name::part1, $name::part2); pub fn part2(bench: &mut Bencher) {
test_part2($day, bench);
}
}
benchmark_group!($name, $name::part1, $name::part2);
}; };
} }

View File

@@ -20,7 +20,8 @@ pub trait Point {
} }
impl<T> Point for (T, T) impl<T> Point for (T, T)
where T: Add<Output=T> + Sub<Output=T> + Copy + Ord where
T: Add<Output = T> + Sub<Output = T> + Copy + Ord,
{ {
type CoordType = T; type CoordType = T;
@@ -32,7 +33,8 @@ impl<T> Point for (T, T)
} }
impl<T> Point for (T, T, T) impl<T> Point for (T, T, T)
where T: Add<Output=T> + Sub<Output=T> + Copy + Ord where
T: Add<Output = T> + Sub<Output = T> + Copy + Ord,
{ {
type CoordType = T; type CoordType = T;
@@ -44,7 +46,8 @@ impl<T> Point for (T, T, T)
} }
impl<T> Point for [T; 4] impl<T> Point for [T; 4]
where T: Default + Add<Output=T> + Sub<Output=T> + Copy + Ord where
T: Default + Add<Output = T> + Sub<Output = T> + Copy + Ord,
{ {
type CoordType = T; type CoordType = T;
@@ -58,7 +61,6 @@ where T: Default + Add<Output=T> + Sub<Output=T> + Copy + Ord
} }
} }
/// Apply Erathostenes's sieve to the supplied array /// Apply Erathostenes's sieve to the supplied array
/// ///
/// # Arguments /// # Arguments
@@ -111,8 +113,9 @@ pub fn trim_back(input: &mut Vec<u8>) {
/// ///
/// This function loads the input into a string and then attempts to parse it. /// This function loads the input into a string and then attempts to parse it.
pub fn read_single_input<T>(input: &mut Read) -> T pub fn read_single_input<T>(input: &mut Read) -> T
where T: FromStr, where
<T as FromStr>::Err: Debug T: FromStr,
<T as FromStr>::Err: Debug,
{ {
let mut buf = String::new(); let mut buf = String::new();
input.read_to_string(&mut buf).unwrap(); input.read_to_string(&mut buf).unwrap();
@@ -132,12 +135,13 @@ pub trait GroupingCount {
} }
impl<T> GroupingCount for T impl<T> GroupingCount for T
where T: Iterator, where
T::Item: Eq + Hash { T: Iterator,
T::Item: Eq + Hash,
{
type Type = T::Item; type Type = T::Item;
fn grouping_count(&mut self) -> HashMap<Self::Type, usize> fn grouping_count(&mut self) -> HashMap<Self::Type, usize> {
{
let mut counts = HashMap::new(); let mut counts = HashMap::new();
for element in self { for element in self {
@@ -170,11 +174,7 @@ mod tests {
prime_sieve(&mut input); prime_sieve(&mut input);
let output = [ let output = [
false, false, false, false, true, true, false, true, false, true, false, false,
true, true,
false, true,
false, true,
false, false
]; ];
assert_eq!(output, input); assert_eq!(output, input);

View File

@@ -52,7 +52,7 @@ impl OpCode {
/// Iterator over all possible OpCode values. /// Iterator over all possible OpCode values.
/// ///
/// This iterator is backed internally by a static array of all op codes. /// This iterator is backed internally by a static array of all op codes.
pub fn values() -> impl Iterator<Item=Self> { pub fn values() -> impl Iterator<Item = Self> {
OP_LIST.iter().cloned() OP_LIST.iter().cloned()
} }
} }

View File

@@ -17,7 +17,8 @@ impl common::Solution for Day01 {
fn part1(&mut self, input: &mut io::Read) -> String { fn part1(&mut self, input: &mut io::Read) -> String {
let reader = io::BufReader::new(input); let reader = io::BufReader::new(input);
let sum: i32 = reader.lines() let sum: i32 = reader
.lines()
.map(|x| x.unwrap().parse::<i32>().unwrap()) .map(|x| x.unwrap().parse::<i32>().unwrap())
.sum(); .sum();
@@ -30,7 +31,8 @@ impl common::Solution for Day01 {
freqs.insert(0); freqs.insert(0);
let mut sum = 0; let mut sum = 0;
let nums: Vec<i32> = reader.lines() let nums: Vec<i32> = reader
.lines()
.map(|x| x.unwrap().parse().unwrap()) .map(|x| x.unwrap().parse().unwrap())
.collect(); .collect();
loop { loop {

View File

@@ -56,7 +56,8 @@ impl common::Solution for Day02 {
fn part2(&mut self, input: &mut io::Read) -> String { fn part2(&mut self, input: &mut io::Read) -> String {
let mut ids: Vec<String> = io::BufReader::new(input) let mut ids: Vec<String> = io::BufReader::new(input)
.lines() .lines()
.map(|x| x.unwrap()).collect(); .map(|x| x.unwrap())
.collect();
ids.sort_unstable(); ids.sort_unstable();
for id1 in &ids { for id1 in &ids {

View File

@@ -25,17 +25,16 @@ impl Claim {
self.y..(self.y + self.height) self.y..(self.y + self.height)
} }
pub fn range(&self) -> impl Iterator<Item=(usize, usize)> { pub fn range(&self) -> impl Iterator<Item = (usize, usize)> {
iproduct!(self.xrange(), self.yrange()) iproduct!(self.xrange(), self.yrange())
} }
} }
#[derive(Default)] #[derive(Default)]
pub struct Day03 { pub struct Day03 {
claims: Vec<Claim> claims: Vec<Claim>,
} }
impl Day03 { impl Day03 {
pub fn new() -> Day03 { pub fn new() -> Day03 {
Default::default() Default::default()
@@ -62,21 +61,16 @@ impl Day03 {
} }
fn get_claims(&self) -> HashMap<(usize, usize), usize> { fn get_claims(&self) -> HashMap<(usize, usize), usize> {
self.claims.iter() self.claims.iter().flat_map(|x| x.range()).grouping_count()
.flat_map(|x| x.range())
.grouping_count()
} }
} }
impl common::Solution for Day03 { impl common::Solution for Day03 {
fn part1(&mut self, input: &mut io::Read) -> String { fn part1(&mut self, input: &mut io::Read) -> String {
self.read_claims(input); self.read_claims(input);
let claim_map = self.get_claims(); let claim_map = self.get_claims();
let multi_claim = claim_map.values() let multi_claim = claim_map.values().filter(|&&x| x > 1).count();
.filter(|&&x| x > 1)
.count();
multi_claim.to_string() multi_claim.to_string()
} }
@@ -85,7 +79,9 @@ impl common::Solution for Day03 {
self.read_claims(input); self.read_claims(input);
let claims = self.get_claims(); let claims = self.get_claims();
let uncontested = self.claims.iter() let uncontested = self
.claims
.iter()
.position(|x| x.range().all(|x| claims[&x] == 1)) .position(|x| x.range().all(|x| claims[&x] == 1))
.unwrap(); .unwrap();

View File

@@ -2,9 +2,9 @@ use std::collections::HashMap;
use std::io; use std::io;
use std::io::BufRead; use std::io::BufRead;
use chrono::DateTime;
use chrono::offset::TimeZone; use chrono::offset::TimeZone;
use chrono::offset::Utc; use chrono::offset::Utc;
use chrono::DateTime;
use chrono::Timelike; use chrono::Timelike;
use regex::Regex; use regex::Regex;
@@ -42,7 +42,9 @@ impl Day04 {
for line in reader.lines() { for line in reader.lines() {
let line = line.unwrap(); let line = line.unwrap();
let captures = scanner.captures(&line).unwrap(); let captures = scanner.captures(&line).unwrap();
let timestamp = Utc.datetime_from_str(&captures[1], "%Y-%m-%d %H:%M").unwrap(); let timestamp = Utc
.datetime_from_str(&captures[1], "%Y-%m-%d %H:%M")
.unwrap();
let event = match &captures[2] { let event = match &captures[2] {
"falls asleep" => EventType::SLEEP, "falls asleep" => EventType::SLEEP,
@@ -64,7 +66,6 @@ impl Day04 {
let mut guard: Option<usize> = None; let mut guard: Option<usize> = None;
let mut sleep_start: Option<DateTime<Utc>> = None; let mut sleep_start: Option<DateTime<Utc>> = None;
for event in &self.events { for event in &self.events {
match &event.event { match &event.event {
EventType::SHIFT(val) => { EventType::SHIFT(val) => {
@@ -86,11 +87,18 @@ impl Day04 {
sleeps sleeps
} }
fn format_results(sleepers: &HashMap<usize, [u32; 60]>, scores: &HashMap<usize, u32>) -> String { fn format_results(
sleepers: &HashMap<usize, [u32; 60]>,
scores: &HashMap<usize, u32>,
) -> String {
let (best_sleeper, _) = scores.iter().max_by(|&(_, a), &(_, b)| a.cmp(b)).unwrap(); let (best_sleeper, _) = scores.iter().max_by(|&(_, a), &(_, b)| a.cmp(b)).unwrap();
let best_minute = sleepers[best_sleeper].iter().enumerate() let best_minute = sleepers[best_sleeper]
.max_by(|&(_, a), &(_, b)| a.cmp(b)).unwrap().0; .iter()
.enumerate()
.max_by(|&(_, a), &(_, b)| a.cmp(b))
.unwrap()
.0;
(best_sleeper * (best_minute as usize)).to_string() (best_sleeper * (best_minute as usize)).to_string()
} }
@@ -100,7 +108,8 @@ impl common::Solution for Day04 {
fn part1(&mut self, input: &mut io::Read) -> String { fn part1(&mut self, input: &mut io::Read) -> String {
self.read_events(input); self.read_events(input);
let sleepers = self.get_sleeps(); let sleepers = self.get_sleeps();
let scores: HashMap<usize, u32> = sleepers.iter().map(|(k, v)| (*k, v.iter().sum())).collect(); let scores: HashMap<usize, u32> =
sleepers.iter().map(|(k, v)| (*k, v.iter().sum())).collect();
Day04::format_results(&sleepers, &scores) Day04::format_results(&sleepers, &scores)
} }
@@ -108,7 +117,10 @@ impl common::Solution for Day04 {
fn part2(&mut self, input: &mut io::Read) -> String { fn part2(&mut self, input: &mut io::Read) -> String {
self.read_events(input); self.read_events(input);
let sleepers = self.get_sleeps(); let sleepers = self.get_sleeps();
let scores: HashMap<usize, u32> = sleepers.iter().map(|(k, v)| (*k, *v.iter().max().unwrap())).collect(); let scores: HashMap<usize, u32> = sleepers
.iter()
.map(|(k, v)| (*k, *v.iter().max().unwrap()))
.collect();
Day04::format_results(&sleepers, &scores) Day04::format_results(&sleepers, &scores)
} }

View File

@@ -42,9 +42,16 @@ impl common::Solution for Day05 {
input.read_to_end(&mut data).expect("Can't read input!"); input.read_to_end(&mut data).expect("Can't read input!");
common::trim_back(&mut data); common::trim_back(&mut data);
let min_len = (b'a'..=b'z').map(|option| data.iter().filter(|&x| !x.eq_ignore_ascii_case(&option)).cloned().collect()) let min_len = (b'a'..=b'z')
.map(|option| {
data.iter()
.filter(|&x| !x.eq_ignore_ascii_case(&option))
.cloned()
.collect()
})
.map(Day05::reduce) .map(Day05::reduce)
.min().unwrap(); .min()
.unwrap();
min_len.to_string() min_len.to_string()
} }

View File

@@ -49,7 +49,7 @@ impl Day06 {
self.ymax = my; self.ymax = my;
} }
fn range(&self) -> impl Iterator<Item=Coordinate> { fn range(&self) -> impl Iterator<Item = Coordinate> {
iproduct!(0..=self.xmax, 0..=self.ymax) iproduct!(0..=self.xmax, 0..=self.ymax)
} }
@@ -103,13 +103,20 @@ impl Solution for Day06 {
infinite.extend(grid.first().unwrap().iter().filter_map(claim_filter)); infinite.extend(grid.first().unwrap().iter().filter_map(claim_filter));
infinite.extend(grid.last().unwrap().iter().filter_map(claim_filter)); infinite.extend(grid.last().unwrap().iter().filter_map(claim_filter));
for row in grid.iter().take(self.ymax) { for row in grid.iter().take(self.ymax) {
infinite.extend([row.first().unwrap(), row.last().unwrap()].iter() infinite.extend(
.cloned().filter_map(claim_filter)); [row.first().unwrap(), row.last().unwrap()]
.iter()
.cloned()
.filter_map(claim_filter),
);
} }
let counts = grid.iter().flat_map(|x| x.iter()) let counts = grid
.iter()
.flat_map(|x| x.iter())
.filter_map(claim_filter) .filter_map(claim_filter)
.filter(|x| !infinite.contains(x)).grouping_count(); .filter(|x| !infinite.contains(x))
.grouping_count();
counts.values().max().unwrap().to_string() counts.values().max().unwrap().to_string()
} }

View File

@@ -18,8 +18,7 @@ struct Worker {
impl Ord for Worker { impl Ord for Worker {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
other.time.cmp(&self.time) other.time.cmp(&self.time).then(other.work.cmp(&self.work))
.then(other.work.cmp(&self.work))
} }
} }
@@ -55,11 +54,19 @@ impl Day07 {
} }
} }
fn part2_parametrized(&mut self, input: &mut Read, base_time: usize, max_workers: usize) -> usize { fn part2_parametrized(
&mut self,
input: &mut Read,
base_time: usize,
max_workers: usize,
) -> usize {
self.read_edges(input); self.read_edges(input);
let mut starting_points: BinaryHeap<Reverse<char>> = self.forward.keys() let mut starting_points: BinaryHeap<Reverse<char>> = self
.forward
.keys()
.filter(|&x| !self.dep_count.contains_key(x)) .filter(|&x| !self.dep_count.contains_key(x))
.map(|&x| Reverse(x)).collect(); .map(|&x| Reverse(x))
.collect();
let mut workers: BinaryHeap<Worker> = BinaryHeap::new(); let mut workers: BinaryHeap<Worker> = BinaryHeap::new();
let mut time = 0; let mut time = 0;
@@ -106,8 +113,12 @@ impl Solution for Day07 {
let mut result = String::new(); let mut result = String::new();
let mut starting_points: BinaryHeap<_> = self.forward.keys().filter(|&x| !self.dep_count.contains_key(x)) let mut starting_points: BinaryHeap<_> = self
.map(|&x| Reverse(x)).collect(); .forward
.keys()
.filter(|&x| !self.dep_count.contains_key(x))
.map(|&x| Reverse(x))
.collect();
while let Some(Reverse(c)) = starting_points.pop() { while let Some(Reverse(c)) = starting_points.pop() {
result.push(c); result.push(c);

View File

@@ -1,12 +1,11 @@
use std::io::Read; use std::io::Read;
use common::Solution;
use common::read_single_input; use common::read_single_input;
use common::Solution;
#[derive(Default)] #[derive(Default)]
pub struct Day08 {} pub struct Day08 {}
fn total1(items: &[usize]) -> (usize, usize) { fn total1(items: &[usize]) -> (usize, usize) {
let children = items[0]; let children = items[0];
let meta_entries = items[1]; let meta_entries = items[1];
@@ -42,7 +41,8 @@ fn total2(items: &[usize]) -> (usize, usize) {
values.push(ct); values.push(ct);
} }
let total = items[start..(start + meta_entries)].iter() let total = items[start..(start + meta_entries)]
.iter()
.filter_map(|&x| values.get(x - 1)) .filter_map(|&x| values.get(x - 1))
.sum(); .sum();
@@ -50,7 +50,6 @@ fn total2(items: &[usize]) -> (usize, usize) {
} }
} }
impl Day08 { impl Day08 {
pub fn new() -> Self { pub fn new() -> Self {
Default::default() Default::default()

View File

@@ -1,5 +1,5 @@
use std::i32;
use std::collections::HashSet; use std::collections::HashSet;
use std::i32;
use std::io::BufRead; use std::io::BufRead;
use std::io::BufReader; use std::io::BufReader;
use std::io::Read; use std::io::Read;
@@ -23,7 +23,9 @@ impl Day10 {
fn read_inputs(&mut self, input: &mut Read) { fn read_inputs(&mut self, input: &mut Read) {
let reader = BufReader::new(input); let reader = BufReader::new(input);
let matcher = Regex::new(r"position=<\s*(-?\d+),\s*(-?\d+)> velocity=<\s*(-?\d+),\s*(-?\d+)>").unwrap(); let matcher =
Regex::new(r"position=<\s*(-?\d+),\s*(-?\d+)> velocity=<\s*(-?\d+),\s*(-?\d+)>")
.unwrap();
for line in reader.lines() { for line in reader.lines() {
let line = line.unwrap(); let line = line.unwrap();
@@ -69,13 +71,20 @@ impl Day10 {
fn height(&self) -> i32 { fn height(&self) -> i32 {
match self.points.iter().skip(1).step_by(2).minmax() { match self.points.iter().skip(1).step_by(2).minmax() {
MinMaxResult::MinMax(x, y) => { y - x + 1 } MinMaxResult::MinMax(x, y) => y - x + 1,
_ => panic!("Input does not make sense."), _ => panic!("Input does not make sense."),
} }
} }
fn underestimate_time(&self) -> i32 { fn underestimate_time(&self) -> i32 {
let (lower, upper) = match self.points.iter().enumerate().skip(1).step_by(2).minmax_by_key(|&(_, y)| y) { let (lower, upper) = match self
.points
.iter()
.enumerate()
.skip(1)
.step_by(2)
.minmax_by_key(|&(_, y)| y)
{
MinMaxResult::MinMax((x, _), (y, _)) => (x, y), MinMaxResult::MinMax((x, _), (y, _)) => (x, y),
_ => panic!("Input does not make sense"), _ => panic!("Input does not make sense"),
}; };

View File

@@ -1,8 +1,8 @@
use std::i32; use std::i32;
use std::io::Read; use std::io::Read;
use common::Solution;
use common::read_single_input; use common::read_single_input;
use common::Solution;
fn power_at(serial: i32, (x, y): (i32, i32)) -> i32 { fn power_at(serial: i32, (x, y): (i32, i32)) -> i32 {
let rack_id = x + 10; let rack_id = x + 10;

View File

@@ -16,16 +16,21 @@ fn char_bool(c: char) -> bool {
match c { match c {
'#' => true, '#' => true,
'.' => false, '.' => false,
_ => panic!("Invalid input {}", c) _ => panic!("Invalid input {}", c),
} }
} }
fn print_state(state: &[(i64, bool)]) -> String { fn print_state(state: &[(i64, bool)]) -> String {
state.iter().map(|(_, x)| if *x { '#' } else { '.' }).collect() state
.iter()
.map(|(_, x)| if *x { '#' } else { '.' })
.collect()
} }
fn state_from_string(representation: &str, offset: i64) -> State { fn state_from_string(representation: &str, offset: i64) -> State {
representation.chars().enumerate() representation
.chars()
.enumerate()
.map(|(i, c)| (i as i64 + offset, char_bool(c))) .map(|(i, c)| (i as i64 + offset, char_bool(c)))
.collect() .collect()
} }
@@ -72,8 +77,7 @@ impl Day12 {
} }
} }
let new_len = new_state.len() - new_state.iter().rev() let new_len = new_state.len() - new_state.iter().rev().take_while(|&&(_, x)| !x).count();
.take_while(|&&(_, x)| !x).count();
new_state.truncate(new_len); new_state.truncate(new_len);
new_state new_state
@@ -98,10 +102,7 @@ impl Day12 {
} }
fn sum(&self, state: &[(i64, bool)]) -> i64 { fn sum(&self, state: &[(i64, bool)]) -> i64 {
state.iter() state.iter().filter(|&&(_, x)| x).map(|&(i, _)| i).sum()
.filter(|&&(_, x)| x)
.map(|&(i, _)| i)
.sum()
} }
} }

View File

@@ -83,7 +83,6 @@ impl PartialOrd for Cart {
} }
} }
#[derive(Default)] #[derive(Default)]
pub struct Day13 { pub struct Day13 {
grid: Vec<Vec<char>>, grid: Vec<Vec<char>>,
@@ -230,7 +229,6 @@ mod tests {
assert_eq!("7,3", instance.part1(&mut SAMPLE1_INPUT)) assert_eq!("7,3", instance.part1(&mut SAMPLE1_INPUT))
} }
#[test] #[test]
fn sample_part2() { fn sample_part2() {
let mut instance = Day13::new(); let mut instance = Day13::new();

View File

@@ -66,7 +66,6 @@ fn find_first(n: usize, len: usize) -> usize {
unreachable!(); unreachable!();
} }
#[derive(Default)] #[derive(Default)]
pub struct Day14 {} pub struct Day14 {}

View File

@@ -57,7 +57,9 @@ impl Day15 {
for (x, c) in line.chars().enumerate() { for (x, c) in line.chars().enumerate() {
match c { match c {
'#' => { current[x] = true; } '#' => {
current[x] = true;
}
'E' | 'G' => { 'E' | 'G' => {
self.units.push(Unit { self.units.push(Unit {
pos: (y, x), pos: (y, x),
@@ -78,13 +80,19 @@ impl Day15 {
let initial = self.units[unit].pos; let initial = self.units[unit].pos;
let faction = self.units[unit].faction; let faction = self.units[unit].faction;
let enemy_positions: HashSet<Coordinate> = self.units.iter() let enemy_positions: HashSet<Coordinate> = self
.units
.iter()
.filter(|x| x.faction != faction && x.is_alive()) .filter(|x| x.faction != faction && x.is_alive())
.map(|x| x.pos).collect(); .map(|x| x.pos)
.collect();
let all_positions: HashSet<Coordinate> = self.units.iter() let all_positions: HashSet<Coordinate> = self
.units
.iter()
.filter(|x| x.is_alive()) .filter(|x| x.is_alive())
.map(|x| x.pos).collect(); .map(|x| x.pos)
.collect();
let mut todo = BinaryHeap::new(); let mut todo = BinaryHeap::new();
let mut prev: HashMap<Coordinate, Coordinate> = HashMap::new(); let mut prev: HashMap<Coordinate, Coordinate> = HashMap::new();
@@ -92,19 +100,13 @@ impl Day15 {
todo.push(Reverse((0, initial))); todo.push(Reverse((0, initial)));
while let Some(Reverse((d, (y, x)))) = todo.pop() { while let Some(Reverse((d, (y, x)))) = todo.pop() {
let next = [ let next = [(y - 1, x), (y, x - 1), (y, x + 1), (y + 1, x)];
(y - 1, x),
(y, x - 1),
(y, x + 1),
(y + 1, x),
];
for pos in &next { for pos in &next {
if !prev.contains_key(pos) && !self.walls[pos.0][pos.1] { if !prev.contains_key(pos) && !self.walls[pos.0][pos.1] {
if enemy_positions.contains(pos) { if enemy_positions.contains(pos) {
return prev.remove(&(y, x)); return prev.remove(&(y, x));
} else if !all_positions.contains(pos) { } else if !all_positions.contains(pos) {
;
let prev_step = *prev.get(&(y, x)).unwrap_or(pos); let prev_step = *prev.get(&(y, x)).unwrap_or(pos);
prev.insert(*pos, prev_step); prev.insert(*pos, prev_step);
todo.push(Reverse((d + 1, *pos))); todo.push(Reverse((d + 1, *pos)));
@@ -119,7 +121,9 @@ impl Day15 {
let initial = self.units[unit].pos; let initial = self.units[unit].pos;
let faction = self.units[unit].faction; let faction = self.units[unit].faction;
let to_attack = self.units.iter() let to_attack = self
.units
.iter()
.enumerate() .enumerate()
.filter(|(_, x)| x.faction != faction && x.is_alive()) .filter(|(_, x)| x.faction != faction && x.is_alive())
.filter(|(_, x)| x.pos.manhattan(initial) == 1) .filter(|(_, x)| x.pos.manhattan(initial) == 1)
@@ -154,8 +158,8 @@ impl Day15 {
if target.hp == 0 { if target.hp == 0 {
match target.faction { match target.faction {
'E' => { self.alive[0] -= 1 } 'E' => self.alive[0] -= 1,
'G' => { self.alive[1] -= 1 } 'G' => self.alive[1] -= 1,
_ => panic!(), _ => panic!(),
}; };
} }
@@ -167,7 +171,9 @@ impl Day15 {
#[allow(dead_code)] #[allow(dead_code)]
fn print(&self) { fn print(&self) {
let positions: HashMap<_, _> = self.units.iter() let positions: HashMap<_, _> = self
.units
.iter()
.filter(|x| x.is_alive()) .filter(|x| x.is_alive())
.map(|x| (x.pos, x)) .map(|x| (x.pos, x))
.collect(); .collect();
@@ -192,8 +198,7 @@ impl Day15 {
} }
fn return_score(&self, rounds: usize) -> String { fn return_score(&self, rounds: usize) -> String {
let result: usize = rounds * self.units.iter().map(|x| x.hp as usize) let result: usize = rounds * self.units.iter().map(|x| x.hp as usize).sum::<usize>();
.sum::<usize>();
result.to_string() result.to_string()
} }
@@ -247,7 +252,6 @@ impl Solution for Day15 {
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use common::Solution; use common::Solution;
@@ -262,14 +266,7 @@ mod tests {
include_bytes!("samples/15.6.txt"), include_bytes!("samples/15.6.txt"),
]; ];
const SAMPLE1_OUTPUT: [&str; 6] = [ const SAMPLE1_OUTPUT: [&str; 6] = ["27730", "36334", "39514", "27755", "28944", "18740"];
"27730",
"36334",
"39514",
"27755",
"28944",
"18740",
];
#[test] #[test]
fn sample_part1() { fn sample_part1() {
@@ -282,13 +279,7 @@ mod tests {
#[test] #[test]
fn sample_part2() { fn sample_part2() {
let indices = [0, 2, 3, 4, 5]; let indices = [0, 2, 3, 4, 5];
let outputs = [ let outputs = ["4988", "31284", "3478", "6474", "1140"];
"4988",
"31284",
"3478",
"6474",
"1140",
];
for (&input, output) in indices.iter().zip(outputs.iter()) { for (&input, output) in indices.iter().zip(outputs.iter()) {
let mut instance = Day15::new(); let mut instance = Day15::new();

View File

@@ -6,8 +6,8 @@ use std::io::Read;
use regex::Regex; use regex::Regex;
use common::Solution; use common::Solution;
use cpu::CPU;
use cpu::OpCode; use cpu::OpCode;
use cpu::CPU;
pub struct Day16 { pub struct Day16 {
matcher: Regex, matcher: Regex,
@@ -38,12 +38,27 @@ impl Day16 {
found found
} }
fn determine_options(&mut self, mut reader: &mut BufReader<&mut Read>) -> [HashSet<OpCode>; 16] { fn determine_options(
&mut self,
mut reader: &mut BufReader<&mut Read>,
) -> [HashSet<OpCode>; 16] {
let mut mappings: [HashSet<OpCode>; 16] = [ let mut mappings: [HashSet<OpCode>; 16] = [
HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(),
HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(),
HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(),
HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(),
HashSet::new(),
HashSet::new(),
HashSet::new(),
HashSet::new(),
HashSet::new(),
HashSet::new(),
HashSet::new(),
HashSet::new(),
HashSet::new(),
HashSet::new(),
HashSet::new(),
HashSet::new(),
]; ];
let mut before = [0; 6]; let mut before = [0; 6];
let mut op = [0; 4]; let mut op = [0; 4];
@@ -54,11 +69,10 @@ impl Day16 {
reader.read_line(&mut self.buf).unwrap_or(0); reader.read_line(&mut self.buf).unwrap_or(0);
if mappings[op[0] as usize].is_empty() { if mappings[op[0] as usize].is_empty() {
mappings[op[0] as usize].extend(OpCode::values() mappings[op[0] as usize]
.filter(|x| x.is_valid(&op, &before, &after))); .extend(OpCode::values().filter(|x| x.is_valid(&op, &before, &after)));
} else { } else {
for option in OpCode::values() for option in OpCode::values().filter(|x| !x.is_valid(&op, &before, &after)) {
.filter(|x| !x.is_valid(&op, &before, &after)) {
mappings[op[0] as usize].remove(&option); mappings[op[0] as usize].remove(&option);
} }
continue; continue;
@@ -149,7 +163,6 @@ impl Solution for Day16 {
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use common::Solution; use common::Solution;

View File

@@ -62,7 +62,8 @@ impl Day17 {
} }
fn support_end<T>(&mut self, center: usize, range: T, y: usize) -> (usize, bool) fn support_end<T>(&mut self, center: usize, range: T, y: usize) -> (usize, bool)
where T: Iterator<Item=usize> where
T: Iterator<Item = usize>,
{ {
let mut prev = center; let mut prev = center;
for x in range { for x in range {
@@ -88,7 +89,11 @@ impl Day17 {
fn descend(&mut self, pos: Coordinate) { fn descend(&mut self, pos: Coordinate) {
let (x, y) = pos; let (x, y) = pos;
if y > self.ymax || self.clays.contains(&pos) || self.flowing.contains(&pos) || self.contained.contains(&pos) { if y > self.ymax
|| self.clays.contains(&pos)
|| self.flowing.contains(&pos)
|| self.contained.contains(&pos)
{
return; return;
} }
@@ -119,8 +124,7 @@ impl Solution for Day17 {
self.descend((500, 0)); self.descend((500, 0));
let result = self.contained.len() let result = self.contained.len() + self.flowing.len() - self.ymin;
+ self.flowing.len() - self.ymin;
result.to_string() result.to_string()
} }

View File

@@ -50,7 +50,7 @@ impl From<char> for Tile {
'|' => Tile::Tree, '|' => Tile::Tree,
'#' => Tile::Lumber, '#' => Tile::Lumber,
'.' => Tile::Open, '.' => Tile::Open,
_ => Tile::Invalid _ => Tile::Invalid,
} }
} }
} }
@@ -129,9 +129,12 @@ impl Day18 {
} }
fn score(&self) -> String { fn score(&self) -> String {
let result = self.grid.iter() let result = self
.grid
.iter()
.flat_map(|x| x.iter()) .flat_map(|x| x.iter())
.cloned().grouping_count(); .cloned()
.grouping_count();
(result[&Tile::Tree] * result[&Tile::Lumber]).to_string() (result[&Tile::Tree] * result[&Tile::Lumber]).to_string()
} }

View File

@@ -3,8 +3,8 @@ use std::io::BufReader;
use std::io::Read; use std::io::Read;
use common::Solution; use common::Solution;
use cpu::CPU;
use cpu::OpCode; use cpu::OpCode;
use cpu::CPU;
#[derive(Default)] #[derive(Default)]
pub struct Day19 { pub struct Day19 {

View File

@@ -62,7 +62,11 @@ impl Day20 {
Default::default() Default::default()
} }
fn follow_directions(&mut self, initial: &[Coordinate], data: &[u8]) -> (Vec<Coordinate>, usize) { fn follow_directions(
&mut self,
initial: &[Coordinate],
data: &[u8],
) -> (Vec<Coordinate>, usize) {
let mut pos = Vec::from(initial); let mut pos = Vec::from(initial);
let mut positions = Vec::new(); let mut positions = Vec::new();
@@ -96,7 +100,7 @@ impl Day20 {
*p = dir.walk(*p); *p = dir.walk(*p);
} }
} }
val => panic!("Invalid input character: {}", val) val => panic!("Invalid input character: {}", val),
} }
index += 1; index += 1;
} }
@@ -111,12 +115,13 @@ impl Day20 {
while let Some((dist, pos)) = todo.pop_front() { while let Some((dist, pos)) = todo.pop_front() {
if let Some(dirs) = self.paths.get(&pos) { if let Some(dirs) = self.paths.get(&pos) {
let dirs = dirs.iter().enumerate() let dirs = dirs.iter().enumerate().filter_map(|(idx, state)| {
.filter_map(|(idx, state)| if *state { if *state {
Some(Direction::from(idx)) Some(Direction::from(idx))
} else { } else {
None None
}); }
});
for dir in dirs { for dir in dirs {
let new_pos = dir.walk(pos); let new_pos = dir.walk(pos);
if !visited.contains_key(&new_pos) { if !visited.contains_key(&new_pos) {
@@ -147,7 +152,11 @@ impl Solution for Day20 {
let pos = (0, 0); let pos = (0, 0);
self.follow_directions(&[pos], &data[1..]); self.follow_directions(&[pos], &data[1..]);
self.distances().values().filter(|&&x| x >= 1000).count().to_string() self.distances()
.values()
.filter(|&&x| x >= 1000)
.count()
.to_string()
} }
} }

View File

@@ -4,18 +4,15 @@ use std::io::Read;
use common::Solution; use common::Solution;
#[derive(Default)] #[derive(Default)]
pub struct Day21 { pub struct Day21 {}
}
struct ValidInputs { struct ValidInputs {
f: i64 f: i64,
} }
impl ValidInputs { impl ValidInputs {
pub fn new(start: i64) -> Self { pub fn new(start: i64) -> Self {
ValidInputs { ValidInputs { f: start }
f: start
}
} }
} }

View File

@@ -93,8 +93,7 @@ impl Solution for Day22 {
let mut table = compute_table(target, depth); let mut table = compute_table(target, depth);
table[target.1][target.0] = 0; table[target.1][target.0] = 0;
let result: usize = table.iter().flat_map(|x| x.iter()) let result: usize = table.iter().flat_map(|x| x.iter()).sum();
.sum();
result.to_string() result.to_string()
} }
@@ -105,9 +104,21 @@ impl Solution for Day22 {
let mut todo = BinaryHeap::new(); let mut todo = BinaryHeap::new();
let mut visited: HashSet<State> = HashSet::new(); let mut visited: HashSet<State> = HashSet::new();
let target_state = State { pos: target, climbing: false, torch: true }; let target_state = State {
pos: target,
climbing: false,
torch: true,
};
todo.push((Reverse((0, 0).manhattan(target)), Reverse(0), State { pos: (0, 0), climbing: false, torch: true })); todo.push((
Reverse((0, 0).manhattan(target)),
Reverse(0),
State {
pos: (0, 0),
climbing: false,
torch: true,
},
));
while let Some((Reverse(approx), Reverse(dist), state)) = todo.pop() { while let Some((Reverse(approx), Reverse(dist), state)) = todo.pop() {
if visited.contains(&state) { if visited.contains(&state) {
@@ -122,9 +133,21 @@ impl Solution for Day22 {
// Handle equipment changes // Handle equipment changes
let changes = [ let changes = [
State { pos: state.pos, climbing: state.climbing, torch: !state.torch }, State {
State { pos: state.pos, climbing: !state.climbing, torch: state.torch }, pos: state.pos,
State { pos: state.pos, climbing: !state.climbing, torch: !state.torch }, climbing: state.climbing,
torch: !state.torch,
},
State {
pos: state.pos,
climbing: !state.climbing,
torch: state.torch,
},
State {
pos: state.pos,
climbing: !state.climbing,
torch: !state.torch,
},
]; ];
for state in changes.iter().cloned() { for state in changes.iter().cloned() {
@@ -146,8 +169,15 @@ impl Solution for Day22 {
climbing: state.climbing, climbing: state.climbing,
}; };
if !visited.contains(&new_state) && new_state.is_valid(table[yn][xn]) && (x == xn || y == yn) { if !visited.contains(&new_state)
todo.push((Reverse(dist + 1 + target.manhattan(new_state.pos)), Reverse(dist + 1), new_state)); && new_state.is_valid(table[yn][xn])
&& (x == xn || y == yn)
{
todo.push((
Reverse(dist + 1 + target.manhattan(new_state.pos)),
Reverse(dist + 1),
new_state,
));
} }
} }
} }
@@ -164,7 +194,6 @@ mod tests {
const SAMPLE_INPUT: &[u8] = include_bytes!("samples/22.txt"); const SAMPLE_INPUT: &[u8] = include_bytes!("samples/22.txt");
#[test] #[test]
fn sample_part1() { fn sample_part1() {
let mut instance = Day22::new(); let mut instance = Day22::new();

View File

@@ -9,7 +9,7 @@ use common::Point;
use common::Solution; use common::Solution;
type Coordinate = (i64, i64, i64); type Coordinate = (i64, i64, i64);
type Graph<'a> = &'a[HashSet<usize>]; type Graph<'a> = &'a [HashSet<usize>];
type NodeSet = HashSet<usize>; type NodeSet = HashSet<usize>;
fn bron_kerbosch(graph: Graph) -> Vec<NodeSet> { fn bron_kerbosch(graph: Graph) -> Vec<NodeSet> {
@@ -24,7 +24,13 @@ fn bron_kerbosch(graph: Graph) -> Vec<NodeSet> {
cliques cliques
} }
fn bron_kerbosch1(graph: Graph, cliques: &mut Vec<NodeSet>, r: &mut NodeSet, p: NodeSet, mut x: NodeSet) { fn bron_kerbosch1(
graph: Graph,
cliques: &mut Vec<NodeSet>,
r: &mut NodeSet,
p: NodeSet,
mut x: NodeSet,
) {
if p.is_empty() && x.is_empty() { if p.is_empty() && x.is_empty() {
if cliques.is_empty() { if cliques.is_empty() {
cliques.push(r.clone()); cliques.push(r.clone());
@@ -56,10 +62,9 @@ fn bron_kerbosch1(graph: Graph, cliques: &mut Vec<NodeSet>, r: &mut NodeSet, p:
} }
} }
#[derive(Default)] #[derive(Default)]
pub struct Day23 { pub struct Day23 {
bots: Vec<(i64, Coordinate)> bots: Vec<(i64, Coordinate)>,
} }
impl Day23 { impl Day23 {
@@ -74,7 +79,7 @@ impl Day23 {
for line in reader.lines() { for line in reader.lines() {
let line = line.unwrap(); let line = line.unwrap();
let mut ints = [0i64;4]; let mut ints = [0i64; 4];
for (c, i) in matcher.find_iter(&line).zip(ints.iter_mut()) { for (c, i) in matcher.find_iter(&line).zip(ints.iter_mut()) {
*i = c.as_str().parse().unwrap(); *i = c.as_str().parse().unwrap();
} }
@@ -92,7 +97,10 @@ impl Solution for Day23 {
self.bots.sort_unstable(); self.bots.sort_unstable();
let (best_range, best_pos) = *self.bots.last().unwrap(); let (best_range, best_pos) = *self.bots.last().unwrap();
let result = self.bots.iter().filter(|(_, pos)| pos.manhattan(best_pos) <= best_range) let result = self
.bots
.iter()
.filter(|(_, pos)| pos.manhattan(best_pos) <= best_range)
.count(); .count();
result.to_string() result.to_string()
@@ -118,8 +126,11 @@ impl Solution for Day23 {
let mut best = None; let mut best = None;
for clique in cliques { for clique in cliques {
let dist = clique.iter().map(|&x| (0, 0, 0).manhattan(self.bots[x].1) - self.bots[x].0) let dist = clique
.max().unwrap(); .iter()
.map(|&x| (0, 0, 0).manhattan(self.bots[x].1) - self.bots[x].0)
.max()
.unwrap();
if best.is_none() { if best.is_none() {
best = Some(dist); best = Some(dist);
} else { } else {

View File

@@ -61,9 +61,9 @@ impl Day24 {
for line in reader.lines() { for line in reader.lines() {
let line = line.unwrap(); let line = line.unwrap();
match line.as_str() { match line.as_str() {
"Immune System:" => { fac = 'D' } "Immune System:" => fac = 'D',
"" => {} "" => {}
"Infection:" => { fac = 'I' } "Infection:" => fac = 'I',
line => { line => {
let caps = matcher.captures(line).unwrap_or_else(|| { let caps = matcher.captures(line).unwrap_or_else(|| {
panic!("{}", line); panic!("{}", line);
@@ -100,7 +100,9 @@ impl Day24 {
fn simulate(&mut self) -> bool { fn simulate(&mut self) -> bool {
let mut order: Vec<usize> = (0..self.units.len()).collect(); let mut order: Vec<usize> = (0..self.units.len()).collect();
order.sort_unstable_by_key(|&x| Reverse((self.units[x].effective_power(), self.units[x].initiative))); order.sort_unstable_by_key(|&x| {
Reverse((self.units[x].effective_power(), self.units[x].initiative))
});
// select targets // select targets
let mut targets: Vec<Option<usize>> = vec![None; self.units.len()]; let mut targets: Vec<Option<usize>> = vec![None; self.units.len()];
@@ -114,8 +116,19 @@ impl Day24 {
} }
let damage = self.units.iter().map(|x| unit.damage_to(x)).collect_vec(); let damage = self.units.iter().map(|x| unit.damage_to(x)).collect_vec();
let target = (0..self.units.len()) let target = (0..self.units.len())
.filter(|&x| !is_targeted[x] && self.units[x].faction != unit.faction && self.units[x].is_alive() && damage[x] > 0) .filter(|&x| {
.max_by_key(|&x| (damage[x], self.units[x].effective_power(), self.units[x].initiative)); !is_targeted[x]
&& self.units[x].faction != unit.faction
&& self.units[x].is_alive()
&& damage[x] > 0
})
.max_by_key(|&x| {
(
damage[x],
self.units[x].effective_power(),
self.units[x].initiative,
)
});
if let Some(target) = target { if let Some(target) = target {
targets[i] = Some(target); targets[i] = Some(target);
@@ -172,7 +185,9 @@ impl Day24 {
if self.both_alive() { if self.both_alive() {
false false
} else { } else {
self.units.iter().filter(|x| x.is_alive()) self.units
.iter()
.filter(|x| x.is_alive())
.all(|x| x.faction == faction) .all(|x| x.faction == faction)
} }
} }

View File

@@ -2,10 +2,10 @@ use std::io::Read;
use regex::Regex; use regex::Regex;
use common::Solution;
use std::io::BufReader;
use std::io::BufRead;
use common::Point; use common::Point;
use common::Solution;
use std::io::BufRead;
use std::io::BufReader;
#[derive(Default)] #[derive(Default)]
pub struct Day25 { pub struct Day25 {

View File

@@ -13,30 +13,38 @@ use aoc_2018::get_impl;
fn main() { fn main() {
let matches = app_from_crate!() let matches = app_from_crate!()
.arg(Arg::with_name("day") .arg(
.value_name("DAY") Arg::with_name("day")
.help("Number of the day to execute") .value_name("DAY")
.required(true) .help("Number of the day to execute")
.takes_value(true)) .required(true)
.arg(Arg::with_name("part2") .takes_value(true),
.short("2") )
.help("Run part 2 instead of part 1") .arg(
.long("part2")) Arg::with_name("part2")
.arg(Arg::with_name("input") .short("2")
.short("i") .help("Run part 2 instead of part 1")
.long("input") .long("part2"),
.help("Optional input file, stdin otherwise") )
.takes_value(true)) .arg(
.arg(Arg::with_name("time") Arg::with_name("input")
.short("t") .short("i")
.long("time") .long("input")
.help("Print the time for the result")) .help("Optional input file, stdin otherwise")
.takes_value(true),
)
.arg(
Arg::with_name("time")
.short("t")
.long("time")
.help("Print the time for the result"),
)
.get_matches(); .get_matches();
let mut implementation = get_impl(value_t_or_exit!(matches, "day", u32)); let mut implementation = get_impl(value_t_or_exit!(matches, "day", u32));
let mut data: Box<io::Read> = match matches.value_of("input") { let mut data: Box<io::Read> = match matches.value_of("input") {
Some(filename) => { Box::new(fs::File::open(filename).unwrap()) } Some(filename) => Box::new(fs::File::open(filename).unwrap()),
None => { Box::new(io::stdin()) } None => Box::new(io::stdin()),
}; };
let begin = Instant::now(); let begin = Instant::now();