mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 12:50:32 +01:00
Correct formatting.
This commit is contained in:
@@ -37,7 +37,6 @@ fn test_part2(day: u32, bench: &mut Bencher) {
|
||||
}
|
||||
|
||||
macro_rules! day_bench {
|
||||
|
||||
( $name:ident, $day:expr ) => {
|
||||
pub mod $name {
|
||||
use super::*;
|
||||
|
||||
@@ -20,7 +20,8 @@ pub trait Point {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -32,7 +33,8 @@ impl<T> Point for (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;
|
||||
|
||||
@@ -44,7 +46,8 @@ impl<T> Point for (T, T, T)
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -58,7 +61,6 @@ where T: Default + Add<Output=T> + Sub<Output=T> + Copy + Ord
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Apply Erathostenes's sieve to the supplied array
|
||||
///
|
||||
/// # 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.
|
||||
pub fn read_single_input<T>(input: &mut Read) -> T
|
||||
where T: FromStr,
|
||||
<T as FromStr>::Err: Debug
|
||||
where
|
||||
T: FromStr,
|
||||
<T as FromStr>::Err: Debug,
|
||||
{
|
||||
let mut buf = String::new();
|
||||
input.read_to_string(&mut buf).unwrap();
|
||||
@@ -132,12 +135,13 @@ pub trait GroupingCount {
|
||||
}
|
||||
|
||||
impl<T> GroupingCount for T
|
||||
where T: Iterator,
|
||||
T::Item: Eq + Hash {
|
||||
where
|
||||
T: Iterator,
|
||||
T::Item: Eq + Hash,
|
||||
{
|
||||
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();
|
||||
|
||||
for element in self {
|
||||
@@ -170,11 +174,7 @@ mod tests {
|
||||
prime_sieve(&mut input);
|
||||
|
||||
let output = [
|
||||
false, false,
|
||||
true, true,
|
||||
false, true,
|
||||
false, true,
|
||||
false, false
|
||||
false, false, true, true, false, true, false, true, false, false,
|
||||
];
|
||||
|
||||
assert_eq!(output, input);
|
||||
|
||||
@@ -17,7 +17,8 @@ impl common::Solution for Day01 {
|
||||
fn part1(&mut self, input: &mut io::Read) -> String {
|
||||
let reader = io::BufReader::new(input);
|
||||
|
||||
let sum: i32 = reader.lines()
|
||||
let sum: i32 = reader
|
||||
.lines()
|
||||
.map(|x| x.unwrap().parse::<i32>().unwrap())
|
||||
.sum();
|
||||
|
||||
@@ -30,7 +31,8 @@ impl common::Solution for Day01 {
|
||||
freqs.insert(0);
|
||||
|
||||
let mut sum = 0;
|
||||
let nums: Vec<i32> = reader.lines()
|
||||
let nums: Vec<i32> = reader
|
||||
.lines()
|
||||
.map(|x| x.unwrap().parse().unwrap())
|
||||
.collect();
|
||||
loop {
|
||||
|
||||
@@ -56,7 +56,8 @@ impl common::Solution for Day02 {
|
||||
fn part2(&mut self, input: &mut io::Read) -> String {
|
||||
let mut ids: Vec<String> = io::BufReader::new(input)
|
||||
.lines()
|
||||
.map(|x| x.unwrap()).collect();
|
||||
.map(|x| x.unwrap())
|
||||
.collect();
|
||||
ids.sort_unstable();
|
||||
|
||||
for id1 in &ids {
|
||||
|
||||
@@ -32,10 +32,9 @@ impl Claim {
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Day03 {
|
||||
claims: Vec<Claim>
|
||||
claims: Vec<Claim>,
|
||||
}
|
||||
|
||||
|
||||
impl Day03 {
|
||||
pub fn new() -> Day03 {
|
||||
Default::default()
|
||||
@@ -62,21 +61,16 @@ impl Day03 {
|
||||
}
|
||||
|
||||
fn get_claims(&self) -> HashMap<(usize, usize), usize> {
|
||||
self.claims.iter()
|
||||
.flat_map(|x| x.range())
|
||||
.grouping_count()
|
||||
self.claims.iter().flat_map(|x| x.range()).grouping_count()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl common::Solution for Day03 {
|
||||
fn part1(&mut self, input: &mut io::Read) -> String {
|
||||
self.read_claims(input);
|
||||
let claim_map = self.get_claims();
|
||||
|
||||
let multi_claim = claim_map.values()
|
||||
.filter(|&&x| x > 1)
|
||||
.count();
|
||||
let multi_claim = claim_map.values().filter(|&&x| x > 1).count();
|
||||
|
||||
multi_claim.to_string()
|
||||
}
|
||||
@@ -85,7 +79,9 @@ impl common::Solution for Day03 {
|
||||
self.read_claims(input);
|
||||
let claims = self.get_claims();
|
||||
|
||||
let uncontested = self.claims.iter()
|
||||
let uncontested = self
|
||||
.claims
|
||||
.iter()
|
||||
.position(|x| x.range().all(|x| claims[&x] == 1))
|
||||
.unwrap();
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
|
||||
use chrono::DateTime;
|
||||
use chrono::offset::TimeZone;
|
||||
use chrono::offset::Utc;
|
||||
use chrono::DateTime;
|
||||
use chrono::Timelike;
|
||||
use regex::Regex;
|
||||
|
||||
@@ -42,7 +42,9 @@ impl Day04 {
|
||||
for line in reader.lines() {
|
||||
let line = 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] {
|
||||
"falls asleep" => EventType::SLEEP,
|
||||
@@ -64,7 +66,6 @@ impl Day04 {
|
||||
let mut guard: Option<usize> = None;
|
||||
let mut sleep_start: Option<DateTime<Utc>> = None;
|
||||
|
||||
|
||||
for event in &self.events {
|
||||
match &event.event {
|
||||
EventType::SHIFT(val) => {
|
||||
@@ -86,11 +87,18 @@ impl Day04 {
|
||||
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_minute = sleepers[best_sleeper].iter().enumerate()
|
||||
.max_by(|&(_, a), &(_, b)| a.cmp(b)).unwrap().0;
|
||||
let best_minute = sleepers[best_sleeper]
|
||||
.iter()
|
||||
.enumerate()
|
||||
.max_by(|&(_, a), &(_, b)| a.cmp(b))
|
||||
.unwrap()
|
||||
.0;
|
||||
|
||||
(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 {
|
||||
self.read_events(input);
|
||||
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)
|
||||
}
|
||||
@@ -108,7 +117,10 @@ impl common::Solution for Day04 {
|
||||
fn part2(&mut self, input: &mut io::Read) -> String {
|
||||
self.read_events(input);
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -42,9 +42,16 @@ impl common::Solution for Day05 {
|
||||
input.read_to_end(&mut data).expect("Can't read input!");
|
||||
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)
|
||||
.min().unwrap();
|
||||
.min()
|
||||
.unwrap();
|
||||
|
||||
min_len.to_string()
|
||||
}
|
||||
|
||||
@@ -103,13 +103,20 @@ impl Solution for Day06 {
|
||||
infinite.extend(grid.first().unwrap().iter().filter_map(claim_filter));
|
||||
infinite.extend(grid.last().unwrap().iter().filter_map(claim_filter));
|
||||
for row in grid.iter().take(self.ymax) {
|
||||
infinite.extend([row.first().unwrap(), row.last().unwrap()].iter()
|
||||
.cloned().filter_map(claim_filter));
|
||||
infinite.extend(
|
||||
[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(|x| !infinite.contains(x)).grouping_count();
|
||||
.filter(|x| !infinite.contains(x))
|
||||
.grouping_count();
|
||||
|
||||
counts.values().max().unwrap().to_string()
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@ struct Worker {
|
||||
|
||||
impl Ord for Worker {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
other.time.cmp(&self.time)
|
||||
.then(other.work.cmp(&self.work))
|
||||
other.time.cmp(&self.time).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);
|
||||
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))
|
||||
.map(|&x| Reverse(x)).collect();
|
||||
.map(|&x| Reverse(x))
|
||||
.collect();
|
||||
|
||||
let mut workers: BinaryHeap<Worker> = BinaryHeap::new();
|
||||
let mut time = 0;
|
||||
@@ -106,8 +113,12 @@ impl Solution for Day07 {
|
||||
|
||||
let mut result = String::new();
|
||||
|
||||
let mut starting_points: BinaryHeap<_> = self.forward.keys().filter(|&x| !self.dep_count.contains_key(x))
|
||||
.map(|&x| Reverse(x)).collect();
|
||||
let mut starting_points: BinaryHeap<_> = self
|
||||
.forward
|
||||
.keys()
|
||||
.filter(|&x| !self.dep_count.contains_key(x))
|
||||
.map(|&x| Reverse(x))
|
||||
.collect();
|
||||
|
||||
while let Some(Reverse(c)) = starting_points.pop() {
|
||||
result.push(c);
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use std::io::Read;
|
||||
|
||||
use common::Solution;
|
||||
use common::read_single_input;
|
||||
use common::Solution;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Day08 {}
|
||||
|
||||
|
||||
fn total1(items: &[usize]) -> (usize, usize) {
|
||||
let children = items[0];
|
||||
let meta_entries = items[1];
|
||||
@@ -42,7 +41,8 @@ fn total2(items: &[usize]) -> (usize, usize) {
|
||||
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))
|
||||
.sum();
|
||||
|
||||
@@ -50,7 +50,6 @@ fn total2(items: &[usize]) -> (usize, usize) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Day08 {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::i32;
|
||||
use std::collections::HashSet;
|
||||
use std::i32;
|
||||
use std::io::BufRead;
|
||||
use std::io::BufReader;
|
||||
use std::io::Read;
|
||||
@@ -23,7 +23,9 @@ impl Day10 {
|
||||
|
||||
fn read_inputs(&mut self, input: &mut Read) {
|
||||
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() {
|
||||
let line = line.unwrap();
|
||||
@@ -69,13 +71,20 @@ impl Day10 {
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
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."),
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
_ => panic!("Input does not make sense"),
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::i32;
|
||||
use std::io::Read;
|
||||
|
||||
use common::Solution;
|
||||
use common::read_single_input;
|
||||
use common::Solution;
|
||||
|
||||
fn power_at(serial: i32, (x, y): (i32, i32)) -> i32 {
|
||||
let rack_id = x + 10;
|
||||
|
||||
@@ -16,16 +16,21 @@ fn char_bool(c: char) -> bool {
|
||||
match c {
|
||||
'#' => true,
|
||||
'.' => false,
|
||||
_ => panic!("Invalid input {}", c)
|
||||
_ => panic!("Invalid input {}", c),
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
representation.chars().enumerate()
|
||||
representation
|
||||
.chars()
|
||||
.enumerate()
|
||||
.map(|(i, c)| (i as i64 + offset, char_bool(c)))
|
||||
.collect()
|
||||
}
|
||||
@@ -72,8 +77,7 @@ impl Day12 {
|
||||
}
|
||||
}
|
||||
|
||||
let new_len = new_state.len() - new_state.iter().rev()
|
||||
.take_while(|&&(_, x)| !x).count();
|
||||
let new_len = new_state.len() - new_state.iter().rev().take_while(|&&(_, x)| !x).count();
|
||||
new_state.truncate(new_len);
|
||||
|
||||
new_state
|
||||
@@ -98,10 +102,7 @@ impl Day12 {
|
||||
}
|
||||
|
||||
fn sum(&self, state: &[(i64, bool)]) -> i64 {
|
||||
state.iter()
|
||||
.filter(|&&(_, x)| x)
|
||||
.map(|&(i, _)| i)
|
||||
.sum()
|
||||
state.iter().filter(|&&(_, x)| x).map(|&(i, _)| i).sum()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,6 @@ impl PartialOrd for Cart {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Day13 {
|
||||
grid: Vec<Vec<char>>,
|
||||
@@ -230,7 +229,6 @@ mod tests {
|
||||
assert_eq!("7,3", instance.part1(&mut SAMPLE1_INPUT))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn sample_part2() {
|
||||
let mut instance = Day13::new();
|
||||
|
||||
@@ -66,7 +66,6 @@ fn find_first(n: usize, len: usize) -> usize {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Day14 {}
|
||||
|
||||
|
||||
@@ -57,7 +57,9 @@ impl Day15 {
|
||||
|
||||
for (x, c) in line.chars().enumerate() {
|
||||
match c {
|
||||
'#' => { current[x] = true; }
|
||||
'#' => {
|
||||
current[x] = true;
|
||||
}
|
||||
'E' | 'G' => {
|
||||
self.units.push(Unit {
|
||||
pos: (y, x),
|
||||
@@ -78,13 +80,19 @@ impl Day15 {
|
||||
let initial = self.units[unit].pos;
|
||||
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())
|
||||
.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())
|
||||
.map(|x| x.pos).collect();
|
||||
.map(|x| x.pos)
|
||||
.collect();
|
||||
|
||||
let mut todo = BinaryHeap::new();
|
||||
let mut prev: HashMap<Coordinate, Coordinate> = HashMap::new();
|
||||
@@ -92,19 +100,13 @@ impl Day15 {
|
||||
todo.push(Reverse((0, initial)));
|
||||
|
||||
while let Some(Reverse((d, (y, x)))) = todo.pop() {
|
||||
let next = [
|
||||
(y - 1, x),
|
||||
(y, x - 1),
|
||||
(y, x + 1),
|
||||
(y + 1, x),
|
||||
];
|
||||
let next = [(y - 1, x), (y, x - 1), (y, x + 1), (y + 1, x)];
|
||||
|
||||
for pos in &next {
|
||||
if !prev.contains_key(pos) && !self.walls[pos.0][pos.1] {
|
||||
if enemy_positions.contains(pos) {
|
||||
return prev.remove(&(y, x));
|
||||
} else if !all_positions.contains(pos) {
|
||||
;
|
||||
let prev_step = *prev.get(&(y, x)).unwrap_or(pos);
|
||||
prev.insert(*pos, prev_step);
|
||||
todo.push(Reverse((d + 1, *pos)));
|
||||
@@ -119,7 +121,9 @@ impl Day15 {
|
||||
let initial = self.units[unit].pos;
|
||||
let faction = self.units[unit].faction;
|
||||
|
||||
let to_attack = self.units.iter()
|
||||
let to_attack = self
|
||||
.units
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, x)| x.faction != faction && x.is_alive())
|
||||
.filter(|(_, x)| x.pos.manhattan(initial) == 1)
|
||||
@@ -154,8 +158,8 @@ impl Day15 {
|
||||
|
||||
if target.hp == 0 {
|
||||
match target.faction {
|
||||
'E' => { self.alive[0] -= 1 }
|
||||
'G' => { self.alive[1] -= 1 }
|
||||
'E' => self.alive[0] -= 1,
|
||||
'G' => self.alive[1] -= 1,
|
||||
_ => panic!(),
|
||||
};
|
||||
}
|
||||
@@ -167,7 +171,9 @@ impl Day15 {
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn print(&self) {
|
||||
let positions: HashMap<_, _> = self.units.iter()
|
||||
let positions: HashMap<_, _> = self
|
||||
.units
|
||||
.iter()
|
||||
.filter(|x| x.is_alive())
|
||||
.map(|x| (x.pos, x))
|
||||
.collect();
|
||||
@@ -192,8 +198,7 @@ impl Day15 {
|
||||
}
|
||||
|
||||
fn return_score(&self, rounds: usize) -> String {
|
||||
let result: usize = rounds * self.units.iter().map(|x| x.hp as usize)
|
||||
.sum::<usize>();
|
||||
let result: usize = rounds * self.units.iter().map(|x| x.hp as usize).sum::<usize>();
|
||||
result.to_string()
|
||||
}
|
||||
|
||||
@@ -247,7 +252,6 @@ impl Solution for Day15 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use common::Solution;
|
||||
@@ -262,14 +266,7 @@ mod tests {
|
||||
include_bytes!("samples/15.6.txt"),
|
||||
];
|
||||
|
||||
const SAMPLE1_OUTPUT: [&str; 6] = [
|
||||
"27730",
|
||||
"36334",
|
||||
"39514",
|
||||
"27755",
|
||||
"28944",
|
||||
"18740",
|
||||
];
|
||||
const SAMPLE1_OUTPUT: [&str; 6] = ["27730", "36334", "39514", "27755", "28944", "18740"];
|
||||
|
||||
#[test]
|
||||
fn sample_part1() {
|
||||
@@ -282,13 +279,7 @@ mod tests {
|
||||
#[test]
|
||||
fn sample_part2() {
|
||||
let indices = [0, 2, 3, 4, 5];
|
||||
let outputs = [
|
||||
"4988",
|
||||
"31284",
|
||||
"3478",
|
||||
"6474",
|
||||
"1140",
|
||||
];
|
||||
let outputs = ["4988", "31284", "3478", "6474", "1140"];
|
||||
|
||||
for (&input, output) in indices.iter().zip(outputs.iter()) {
|
||||
let mut instance = Day15::new();
|
||||
|
||||
@@ -6,8 +6,8 @@ use std::io::Read;
|
||||
use regex::Regex;
|
||||
|
||||
use common::Solution;
|
||||
use cpu::CPU;
|
||||
use cpu::OpCode;
|
||||
use cpu::CPU;
|
||||
|
||||
pub struct Day16 {
|
||||
matcher: Regex,
|
||||
@@ -38,12 +38,27 @@ impl Day16 {
|
||||
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] = [
|
||||
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 op = [0; 4];
|
||||
@@ -54,11 +69,10 @@ impl Day16 {
|
||||
reader.read_line(&mut self.buf).unwrap_or(0);
|
||||
|
||||
if mappings[op[0] as usize].is_empty() {
|
||||
mappings[op[0] as usize].extend(OpCode::values()
|
||||
.filter(|x| x.is_valid(&op, &before, &after)));
|
||||
mappings[op[0] as usize]
|
||||
.extend(OpCode::values().filter(|x| x.is_valid(&op, &before, &after)));
|
||||
} else {
|
||||
for option in OpCode::values()
|
||||
.filter(|x| !x.is_valid(&op, &before, &after)) {
|
||||
for option in OpCode::values().filter(|x| !x.is_valid(&op, &before, &after)) {
|
||||
mappings[op[0] as usize].remove(&option);
|
||||
}
|
||||
continue;
|
||||
@@ -149,7 +163,6 @@ impl Solution for Day16 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use common::Solution;
|
||||
|
||||
@@ -62,7 +62,8 @@ impl Day17 {
|
||||
}
|
||||
|
||||
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;
|
||||
for x in range {
|
||||
@@ -88,7 +89,11 @@ impl Day17 {
|
||||
fn descend(&mut self, pos: Coordinate) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -119,8 +124,7 @@ impl Solution for Day17 {
|
||||
|
||||
self.descend((500, 0));
|
||||
|
||||
let result = self.contained.len()
|
||||
+ self.flowing.len() - self.ymin;
|
||||
let result = self.contained.len() + self.flowing.len() - self.ymin;
|
||||
result.to_string()
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ impl From<char> for Tile {
|
||||
'|' => Tile::Tree,
|
||||
'#' => Tile::Lumber,
|
||||
'.' => Tile::Open,
|
||||
_ => Tile::Invalid
|
||||
_ => Tile::Invalid,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,9 +129,12 @@ impl Day18 {
|
||||
}
|
||||
|
||||
fn score(&self) -> String {
|
||||
let result = self.grid.iter()
|
||||
let result = self
|
||||
.grid
|
||||
.iter()
|
||||
.flat_map(|x| x.iter())
|
||||
.cloned().grouping_count();
|
||||
.cloned()
|
||||
.grouping_count();
|
||||
|
||||
(result[&Tile::Tree] * result[&Tile::Lumber]).to_string()
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ use std::io::BufReader;
|
||||
use std::io::Read;
|
||||
|
||||
use common::Solution;
|
||||
use cpu::CPU;
|
||||
use cpu::OpCode;
|
||||
use cpu::CPU;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Day19 {
|
||||
|
||||
@@ -62,7 +62,11 @@ impl Day20 {
|
||||
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 positions = Vec::new();
|
||||
|
||||
@@ -96,7 +100,7 @@ impl Day20 {
|
||||
*p = dir.walk(*p);
|
||||
}
|
||||
}
|
||||
val => panic!("Invalid input character: {}", val)
|
||||
val => panic!("Invalid input character: {}", val),
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
@@ -111,11 +115,12 @@ impl Day20 {
|
||||
|
||||
while let Some((dist, pos)) = todo.pop_front() {
|
||||
if let Some(dirs) = self.paths.get(&pos) {
|
||||
let dirs = dirs.iter().enumerate()
|
||||
.filter_map(|(idx, state)| if *state {
|
||||
let dirs = dirs.iter().enumerate().filter_map(|(idx, state)| {
|
||||
if *state {
|
||||
Some(Direction::from(idx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
for dir in dirs {
|
||||
let new_pos = dir.walk(pos);
|
||||
@@ -147,7 +152,11 @@ impl Solution for Day20 {
|
||||
let pos = (0, 0);
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,18 +4,15 @@ use std::io::Read;
|
||||
use common::Solution;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Day21 {
|
||||
}
|
||||
pub struct Day21 {}
|
||||
|
||||
struct ValidInputs {
|
||||
f: i64
|
||||
f: i64,
|
||||
}
|
||||
|
||||
impl ValidInputs {
|
||||
pub fn new(start: i64) -> Self {
|
||||
ValidInputs {
|
||||
f: start
|
||||
}
|
||||
ValidInputs { f: start }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,8 +93,7 @@ impl Solution for Day22 {
|
||||
let mut table = compute_table(target, depth);
|
||||
table[target.1][target.0] = 0;
|
||||
|
||||
let result: usize = table.iter().flat_map(|x| x.iter())
|
||||
.sum();
|
||||
let result: usize = table.iter().flat_map(|x| x.iter()).sum();
|
||||
result.to_string()
|
||||
}
|
||||
|
||||
@@ -105,9 +104,21 @@ impl Solution for Day22 {
|
||||
|
||||
let mut todo = BinaryHeap::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() {
|
||||
if visited.contains(&state) {
|
||||
@@ -122,9 +133,21 @@ impl Solution for Day22 {
|
||||
|
||||
// Handle equipment changes
|
||||
let changes = [
|
||||
State { pos: state.pos, 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 },
|
||||
State {
|
||||
pos: state.pos,
|
||||
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() {
|
||||
@@ -146,8 +169,15 @@ impl Solution for Day22 {
|
||||
climbing: state.climbing,
|
||||
};
|
||||
|
||||
if !visited.contains(&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));
|
||||
if !visited.contains(&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");
|
||||
|
||||
|
||||
#[test]
|
||||
fn sample_part1() {
|
||||
let mut instance = Day22::new();
|
||||
|
||||
@@ -24,7 +24,13 @@ fn bron_kerbosch(graph: Graph) -> Vec<NodeSet> {
|
||||
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 cliques.is_empty() {
|
||||
cliques.push(r.clone());
|
||||
@@ -56,10 +62,9 @@ fn bron_kerbosch1(graph: Graph, cliques: &mut Vec<NodeSet>, r: &mut NodeSet, p:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Day23 {
|
||||
bots: Vec<(i64, Coordinate)>
|
||||
bots: Vec<(i64, Coordinate)>,
|
||||
}
|
||||
|
||||
impl Day23 {
|
||||
@@ -92,7 +97,10 @@ impl Solution for Day23 {
|
||||
self.bots.sort_unstable();
|
||||
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();
|
||||
|
||||
result.to_string()
|
||||
@@ -118,8 +126,11 @@ impl Solution for Day23 {
|
||||
|
||||
let mut best = None;
|
||||
for clique in cliques {
|
||||
let dist = clique.iter().map(|&x| (0, 0, 0).manhattan(self.bots[x].1) - self.bots[x].0)
|
||||
.max().unwrap();
|
||||
let dist = clique
|
||||
.iter()
|
||||
.map(|&x| (0, 0, 0).manhattan(self.bots[x].1) - self.bots[x].0)
|
||||
.max()
|
||||
.unwrap();
|
||||
if best.is_none() {
|
||||
best = Some(dist);
|
||||
} else {
|
||||
|
||||
@@ -61,9 +61,9 @@ impl Day24 {
|
||||
for line in reader.lines() {
|
||||
let line = line.unwrap();
|
||||
match line.as_str() {
|
||||
"Immune System:" => { fac = 'D' }
|
||||
"Immune System:" => fac = 'D',
|
||||
"" => {}
|
||||
"Infection:" => { fac = 'I' }
|
||||
"Infection:" => fac = 'I',
|
||||
line => {
|
||||
let caps = matcher.captures(line).unwrap_or_else(|| {
|
||||
panic!("{}", line);
|
||||
@@ -100,7 +100,9 @@ impl Day24 {
|
||||
|
||||
fn simulate(&mut self) -> bool {
|
||||
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
|
||||
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 target = (0..self.units.len())
|
||||
.filter(|&x| !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));
|
||||
.filter(|&x| {
|
||||
!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 {
|
||||
targets[i] = Some(target);
|
||||
@@ -172,7 +185,9 @@ impl Day24 {
|
||||
if self.both_alive() {
|
||||
false
|
||||
} else {
|
||||
self.units.iter().filter(|x| x.is_alive())
|
||||
self.units
|
||||
.iter()
|
||||
.filter(|x| x.is_alive())
|
||||
.all(|x| x.faction == faction)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ use std::io::Read;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use common::Solution;
|
||||
use std::io::BufReader;
|
||||
use std::io::BufRead;
|
||||
use common::Point;
|
||||
use common::Solution;
|
||||
use std::io::BufRead;
|
||||
use std::io::BufReader;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Day25 {
|
||||
|
||||
@@ -13,30 +13,38 @@ use aoc_2018::get_impl;
|
||||
|
||||
fn main() {
|
||||
let matches = app_from_crate!()
|
||||
.arg(Arg::with_name("day")
|
||||
.arg(
|
||||
Arg::with_name("day")
|
||||
.value_name("DAY")
|
||||
.help("Number of the day to execute")
|
||||
.required(true)
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("part2")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("part2")
|
||||
.short("2")
|
||||
.help("Run part 2 instead of part 1")
|
||||
.long("part2"))
|
||||
.arg(Arg::with_name("input")
|
||||
.long("part2"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("input")
|
||||
.short("i")
|
||||
.long("input")
|
||||
.help("Optional input file, stdin otherwise")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("time")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("time")
|
||||
.short("t")
|
||||
.long("time")
|
||||
.help("Print the time for the result"))
|
||||
.help("Print the time for the result"),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let mut implementation = get_impl(value_t_or_exit!(matches, "day", u32));
|
||||
let mut data: Box<io::Read> = match matches.value_of("input") {
|
||||
Some(filename) => { Box::new(fs::File::open(filename).unwrap()) }
|
||||
None => { Box::new(io::stdin()) }
|
||||
Some(filename) => Box::new(fs::File::open(filename).unwrap()),
|
||||
None => Box::new(io::stdin()),
|
||||
};
|
||||
|
||||
let begin = Instant::now();
|
||||
|
||||
Reference in New Issue
Block a user