mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Correct formatting.
This commit is contained in:
@@ -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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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"),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ fn find_first(n: usize, len: usize) -> usize {
|
|||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Day14 {}
|
pub struct Day14 {}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user