Day 5
This commit is contained in:
parent
f23334c962
commit
7bbd5ff22c
3 changed files with 255 additions and 9 deletions
|
@ -6,14 +6,14 @@ use crate::utils::Day;
|
|||
pub struct Day4 {
|
||||
pub input: String,
|
||||
pub acc: usize,
|
||||
pub cards: HashMap::<usize /* Card # */, Vec<usize> /* (won card indexes) */>
|
||||
pub cards: HashMap<usize /* Card # */, Vec<usize> /* (won card indexes) */>,
|
||||
}
|
||||
|
||||
impl Day4 {
|
||||
fn recurse(&mut self, cards: &Vec<usize>) {
|
||||
for card in cards {
|
||||
self.acc += 1;
|
||||
|
||||
|
||||
if let Some(won_cards) = self.cards.get(card) {
|
||||
self.recurse(&won_cards.clone())
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ impl Day4 {
|
|||
impl Day for Day4 {
|
||||
fn part1(&mut self) -> String {
|
||||
let mut sum = 0usize;
|
||||
|
||||
|
||||
for line in self.input.lines() {
|
||||
let (winning, numbers) = line.split_once(": ").unwrap().1.split_once(" | ").unwrap();
|
||||
let winning = winning.split_whitespace().collect::<Vec<_>>();
|
||||
|
@ -37,7 +37,10 @@ impl Day for Day4 {
|
|||
}
|
||||
|
||||
if winning_numbers.len() != 0 {
|
||||
sum += winning_numbers.iter().skip(1).fold(1usize, |acc, _| acc * 2);
|
||||
sum += winning_numbers
|
||||
.iter()
|
||||
.skip(1)
|
||||
.fold(1usize, |acc, _| acc * 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +60,14 @@ impl Day for Day4 {
|
|||
}
|
||||
}
|
||||
|
||||
self.cards.insert(i + 1, winning_numbers.into_iter().enumerate().map(|(j, _)| (i + 1) + (j + 1)).collect());
|
||||
self.cards.insert(
|
||||
i + 1,
|
||||
winning_numbers
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(j, _)| (i + 1) + (j + 1))
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
self.recurse(&self.cards.keys().map(|e| *e).collect::<Vec<_>>());
|
||||
|
@ -98,9 +108,9 @@ Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
|
|||
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
|
||||
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"#
|
||||
.to_string(),
|
||||
acc: 0usize,
|
||||
cards: HashMap::new()
|
||||
acc: 0usize,
|
||||
cards: HashMap::new()
|
||||
}
|
||||
.solve(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
233
src/day5/mod.rs
Normal file
233
src/day5/mod.rs
Normal file
|
@ -0,0 +1,233 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::utils::Day;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Day5 {
|
||||
pub input: String,
|
||||
}
|
||||
|
||||
impl Day for Day5 {
|
||||
fn part1(&mut self) -> String {
|
||||
let groups = self.input.split("\n\n").skip(1).map(|g| {
|
||||
let mut lines = g.lines();
|
||||
(lines.next().unwrap(), lines.collect::<Vec<_>>())
|
||||
});
|
||||
|
||||
let seeds = self
|
||||
.input
|
||||
.lines()
|
||||
.next()
|
||||
.unwrap()
|
||||
.split_once(": ")
|
||||
.unwrap()
|
||||
.1
|
||||
.split_whitespace()
|
||||
.map(|s| s.parse::<usize>().unwrap());
|
||||
let groups = groups
|
||||
.map(|(name, list)| {
|
||||
(
|
||||
name.split_once(' ').unwrap().0.split_once("-to-").unwrap(),
|
||||
list.into_iter().map(|line| {
|
||||
let nums = line.split_whitespace()
|
||||
.map(|n| n.parse::<usize>().unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
(nums[0], nums[1], nums[2])
|
||||
}).collect::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
.map(|((from, to), mappings)| (
|
||||
from,
|
||||
(
|
||||
to,
|
||||
mappings
|
||||
)
|
||||
))
|
||||
.collect::<HashMap<&str, (&str, Vec<(usize, usize, usize)>)>>();
|
||||
|
||||
let mut locations = Vec::<usize>::new();
|
||||
|
||||
for seed in seeds {
|
||||
let (mut category, mut value) = ("seed", seed);
|
||||
while category != "location" {
|
||||
let (new_category, mappings) = groups.get(category).unwrap();
|
||||
category = new_category;
|
||||
|
||||
for (destination_start, source_start, length) in mappings {
|
||||
if (source_start..&(source_start + length)).contains(&&value) {
|
||||
let delta = *source_start as isize - *destination_start as isize;
|
||||
value = (value as isize - delta) as usize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locations.push(value)
|
||||
}
|
||||
|
||||
locations.into_iter().min().unwrap().to_string()
|
||||
}
|
||||
|
||||
/// Yes my solution was to brute force it
|
||||
/// Yes it worked
|
||||
/// Yes it only took 13m and 31s to solve
|
||||
/// No I will not elaborate on why I felt the need to do it this way
|
||||
/// Yes I should probably solve it correctly at some point
|
||||
fn part2(&mut self) -> String {
|
||||
let groups = self.input.split("\n\n").skip(1).map(|g| {
|
||||
let mut lines = g.lines();
|
||||
(lines.next().unwrap(), lines.collect::<Vec<_>>())
|
||||
});
|
||||
|
||||
let seeds = self
|
||||
.input
|
||||
.lines()
|
||||
.next()
|
||||
.unwrap()
|
||||
.split_once(": ")
|
||||
.unwrap()
|
||||
.1
|
||||
.split_whitespace()
|
||||
.map(|s| s.parse::<usize>().unwrap())
|
||||
.collect::<Vec<usize>>();
|
||||
let seeds = seeds
|
||||
.as_slice()
|
||||
.chunks(2);
|
||||
|
||||
let groups = groups
|
||||
.map(|(name, list)| {
|
||||
(
|
||||
name.split_once(' ').unwrap().0.split_once("-to-").unwrap(),
|
||||
list.into_iter().map(|line| {
|
||||
let nums = line.split_whitespace()
|
||||
.map(|n| n.parse::<usize>().unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
(nums[0], nums[1], nums[2])
|
||||
}).collect::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
.map(|((from, to), mappings)| (
|
||||
from,
|
||||
(
|
||||
to,
|
||||
mappings
|
||||
)
|
||||
))
|
||||
.collect::<HashMap<&str, (&str, Vec<(usize, usize, usize)>)>>();
|
||||
|
||||
let mut location = 100000000usize;
|
||||
let seedslen = seeds.len();
|
||||
|
||||
for (i, chunk) in seeds.enumerate() {
|
||||
let (initial, range) = (chunk[0], chunk[1]);
|
||||
for (j, seed) in (initial..(initial + range)).enumerate() {
|
||||
if j % 1000 == 0 {
|
||||
println!("Chunk {}/{}, Seed {}/{} ({:.2}%)", i, seedslen, j, range, j as f64 / range as f64 * 100.0);
|
||||
}
|
||||
let (mut category, mut value) = ("seed", seed);
|
||||
while category != "location" {
|
||||
let (new_category, mappings) = groups.get(category).unwrap();
|
||||
category = new_category;
|
||||
|
||||
for (destination_start, source_start, length) in mappings {
|
||||
if (source_start..&(source_start + length)).contains(&&value) {
|
||||
let delta = *source_start as isize - *destination_start as isize;
|
||||
value = (value as isize - delta) as usize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if location > value { location = value }
|
||||
}
|
||||
}
|
||||
|
||||
location.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{day5::Day5, utils::Day};
|
||||
|
||||
#[test]
|
||||
fn passes_example_1() {
|
||||
dbg!(Day5 {
|
||||
input: r#"seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 15 37
|
||||
37 52 2
|
||||
39 0 15
|
||||
|
||||
fertilizer-to-water map:
|
||||
49 53 8
|
||||
0 11 42
|
||||
42 0 7
|
||||
57 7 4
|
||||
|
||||
water-to-light map:
|
||||
88 18 7
|
||||
18 25 70
|
||||
|
||||
light-to-temperature map:
|
||||
45 77 23
|
||||
81 45 19
|
||||
68 64 13
|
||||
|
||||
temperature-to-humidity map:
|
||||
0 69 1
|
||||
1 0 69
|
||||
|
||||
humidity-to-location map:
|
||||
60 56 37
|
||||
56 93 4"#.to_string(),
|
||||
}
|
||||
.solve(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn passes_example_2() {
|
||||
dbg!(Day5 {
|
||||
input: r#"seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 15 37
|
||||
37 52 2
|
||||
39 0 15
|
||||
|
||||
fertilizer-to-water map:
|
||||
49 53 8
|
||||
0 11 42
|
||||
42 0 7
|
||||
57 7 4
|
||||
|
||||
water-to-light map:
|
||||
88 18 7
|
||||
18 25 70
|
||||
|
||||
light-to-temperature map:
|
||||
45 77 23
|
||||
81 45 19
|
||||
68 64 13
|
||||
|
||||
temperature-to-humidity map:
|
||||
0 69 1
|
||||
1 0 69
|
||||
|
||||
humidity-to-location map:
|
||||
60 56 37
|
||||
56 93 4"#.to_string(),
|
||||
}
|
||||
.solve(2));
|
||||
}
|
||||
}
|
|
@ -6,12 +6,13 @@ use std::{
|
|||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
use crate::{day1::Day1, day2::Day2, day3::Day3, day4::Day4, utils::Day};
|
||||
use crate::{day1::Day1, day2::Day2, day3::Day3, day4::Day4, day5::Day5, utils::Day};
|
||||
|
||||
pub mod day1;
|
||||
pub mod day2;
|
||||
pub mod day3;
|
||||
pub mod day4;
|
||||
pub mod day5;
|
||||
pub mod fetcher;
|
||||
pub mod utils;
|
||||
|
||||
|
@ -91,6 +92,7 @@ async fn main() {
|
|||
acc: 0usize,
|
||||
cards: HashMap::new(),
|
||||
}),
|
||||
5 => Box::new(Day5 { input: response }),
|
||||
_ => panic!("Invalid day #"),
|
||||
};
|
||||
let start = std::time::Instant::now();
|
||||
|
@ -140,6 +142,7 @@ async fn main() {
|
|||
acc: 0usize,
|
||||
cards: HashMap::new(),
|
||||
}),
|
||||
5 => Box::new(Day5 { input: response }),
|
||||
_ => panic!("Invalid day #"),
|
||||
};
|
||||
let mut timings = Vec::<Duration>::new();
|
||||
|
|
Loading…
Reference in a new issue