feat(day5): day5 solution and bytes optimizations
parent
46530a0693
commit
6c8fdeeeb6
|
@ -5,3 +5,30 @@ version = 3
|
|||
[[package]]
|
||||
name = "adventofcode2023"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atoi"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
atoi = "2.0"
|
||||
|
||||
[[bin]]
|
||||
name = "day1"
|
||||
|
@ -21,4 +22,8 @@ path = "src/day3/main.rs"
|
|||
|
||||
[[bin]]
|
||||
name = "day4"
|
||||
path = "src/day4/main.rs"
|
||||
path = "src/day4/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "day5"
|
||||
path = "src/day5/main.rs"
|
|
@ -15,19 +15,15 @@ fn convert_spelled_numbers(line: &str) -> String {
|
|||
.replace("nine", "9")
|
||||
}
|
||||
|
||||
fn compute_calibration_values_sum(puzzle: &str) -> u32 {
|
||||
fn compute_calibration_values_sum(puzzle: &[u8]) -> u32 {
|
||||
puzzle
|
||||
.lines()
|
||||
.split(|&c| c == b'\n')
|
||||
.map(|line| {
|
||||
(
|
||||
line.chars().find_map(|c| c.to_digit(10)).unwrap(),
|
||||
line.chars().rev().find_map(|c| c.to_digit(10)).unwrap(),
|
||||
)
|
||||
})
|
||||
.fold(0, |acc, (first_nb, last_nb)| {
|
||||
let calibration_value = first_nb * 10 + last_nb;
|
||||
acc + calibration_value
|
||||
((line.iter().find(|c| c.is_ascii_digit()).unwrap() - b'0') * 10
|
||||
+ (line.iter().rev().find(|c| c.is_ascii_digit()).unwrap() - b'0'))
|
||||
as u32
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -35,11 +31,14 @@ fn main() {
|
|||
let start_time = std::time::Instant::now();
|
||||
println!("--- Day 1: Trebuchet?! ---");
|
||||
println!("What is the sum of all of the calibration values?");
|
||||
println!("{}", compute_calibration_values_sum(&puzzle));
|
||||
println!("{}", compute_calibration_values_sum(puzzle.as_bytes()));
|
||||
println!("--- Part Two ---");
|
||||
println!("What is the sum of all of the calibration values?");
|
||||
let converted_puzzle = convert_spelled_numbers(&puzzle);
|
||||
println!("{}", compute_calibration_values_sum(&converted_puzzle));
|
||||
println!(
|
||||
"{}",
|
||||
compute_calibration_values_sum(converted_puzzle.as_bytes())
|
||||
);
|
||||
let elapsed_time = start_time.elapsed();
|
||||
println!("compute time: {:?}", elapsed_time);
|
||||
}
|
||||
|
|
|
@ -1,48 +1,53 @@
|
|||
use adventofcode2023::utils::get_puzzle;
|
||||
use adventofcode2023::utils::get_puzzle_bytes;
|
||||
use std::str;
|
||||
|
||||
type CubeSet = (u32, u32, u32);
|
||||
type Game = (u32, Vec<CubeSet>);
|
||||
|
||||
fn parse_game_id(game_id_str: &str) -> u32 {
|
||||
game_id_str
|
||||
.rsplit_once(' ')
|
||||
.unwrap()
|
||||
.1
|
||||
.parse::<u32>()
|
||||
.unwrap()
|
||||
fn parse_number(line: &[u8]) -> u32 {
|
||||
line.iter()
|
||||
.filter(|b| b.is_ascii_digit())
|
||||
.fold(0, |acc, &b| acc * 10 + (b - b'0') as u32)
|
||||
}
|
||||
|
||||
fn parse_cube_set(set_str: &str) -> CubeSet {
|
||||
let cubes_list = set_str.split(", ");
|
||||
fn parse_cube_set(set_str: &[u8]) -> CubeSet {
|
||||
let cubes_list = set_str.split(|&b| b == b',');
|
||||
cubes_list.fold(
|
||||
(0, 0, 0),
|
||||
|(red_cubes, green_cubes, blue_cubes), cube_str| {
|
||||
let (cube_count_str, cube_color) = cube_str.rsplit_once(' ').unwrap();
|
||||
let cube_count = cube_count_str.parse::<u32>().unwrap();
|
||||
let pos = cube_str
|
||||
.iter()
|
||||
.position(|&b| b.is_ascii_alphabetic())
|
||||
.unwrap();
|
||||
let (cube_count_str, cube_color) = cube_str.split_at(pos);
|
||||
let cube_count = parse_number(cube_count_str);
|
||||
match cube_color {
|
||||
"red" => (red_cubes + cube_count, green_cubes, blue_cubes),
|
||||
"green" => (red_cubes, green_cubes + cube_count, blue_cubes),
|
||||
"blue" => (red_cubes, green_cubes, blue_cubes + cube_count),
|
||||
_ => panic!("unknown color: {}", cube_color),
|
||||
b"red" => (red_cubes + cube_count, green_cubes, blue_cubes),
|
||||
b"green" => (red_cubes, green_cubes + cube_count, blue_cubes),
|
||||
b"blue" => (red_cubes, green_cubes, blue_cubes + cube_count),
|
||||
_ => panic!("unknown color: {}", str::from_utf8(cube_color).unwrap()),
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_game_sets(game_str: &str) -> Vec<CubeSet> {
|
||||
fn parse_game_sets(game_str: &[u8]) -> Vec<CubeSet> {
|
||||
game_str
|
||||
.split("; ")
|
||||
.split(|&c| c == b';')
|
||||
.map(parse_cube_set)
|
||||
.collect::<Vec<CubeSet>>()
|
||||
}
|
||||
|
||||
fn parse_puzzle(puzzle: &str) -> Vec<Game> {
|
||||
fn parse_puzzle(puzzle: &[u8]) -> Vec<Game> {
|
||||
puzzle
|
||||
.lines()
|
||||
.map(|line| line.rsplit_once(": ").unwrap())
|
||||
.split(|&c| c == b'\n')
|
||||
.map(|line| {
|
||||
let sep = line.iter().position(|&c| c == b':').unwrap();
|
||||
line.split_at(sep)
|
||||
})
|
||||
.map(|(game_id_str, game_str)| {
|
||||
let game_id = parse_game_id(game_id_str);
|
||||
let sets_of_cubes = parse_game_sets(game_str);
|
||||
let game_id = parse_number(game_id_str);
|
||||
let sets_of_cubes = parse_game_sets(&game_str[1..]);
|
||||
(game_id, sets_of_cubes)
|
||||
})
|
||||
.collect::<Vec<Game>>()
|
||||
|
@ -63,7 +68,7 @@ fn check_max_cubes(sets_of_cubes: &[CubeSet]) -> bool {
|
|||
true
|
||||
}
|
||||
|
||||
fn compute_impossible_games_sum(puzzle: &str) -> u32 {
|
||||
fn compute_impossible_games_sum(puzzle: &[u8]) -> u32 {
|
||||
parse_puzzle(puzzle).iter().fold(0, {
|
||||
|acc, (game_id, sets_of_cubes)| {
|
||||
if check_max_cubes(sets_of_cubes) {
|
||||
|
@ -99,7 +104,7 @@ fn count_minimal_cubes(sets_of_cubes: &[CubeSet]) -> (u32, u32, u32) {
|
|||
})
|
||||
}
|
||||
|
||||
fn compute_sum_of_power(puzzle: &str) -> u32 {
|
||||
fn compute_sum_of_power(puzzle: &[u8]) -> u32 {
|
||||
parse_puzzle(puzzle).iter().fold(0, {
|
||||
|acc, (_, sets_of_cubes)| {
|
||||
let (red_min, green_min, blue_min) = count_minimal_cubes(sets_of_cubes);
|
||||
|
@ -109,7 +114,7 @@ fn compute_sum_of_power(puzzle: &str) -> u32 {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let puzzle = get_puzzle();
|
||||
let puzzle = get_puzzle_bytes();
|
||||
let start_time = std::time::Instant::now();
|
||||
println!("--- Day 2: Cube Conundrum ---");
|
||||
println!("What is the sum of the IDs of those games?");
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::cmp::min;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use adventofcode2023::utils::get_puzzle;
|
||||
use adventofcode2023::utils::get_puzzle_bytes;
|
||||
use atoi::atoi;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PartNumber {
|
||||
|
@ -16,29 +17,29 @@ trait SymbolCheckable {
|
|||
fn is_symbol(&self) -> bool;
|
||||
}
|
||||
|
||||
impl SymbolCheckable for char {
|
||||
impl SymbolCheckable for u8 {
|
||||
fn is_symbol(&self) -> bool {
|
||||
*self != '.' && !self.is_alphanumeric()
|
||||
*self != b'.' && !self.is_ascii_punctuation()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_number(line: &str) -> (u32, usize) {
|
||||
let number_str = line
|
||||
.chars()
|
||||
.take_while(|c| c.is_ascii_digit())
|
||||
.collect::<String>();
|
||||
let number = number_str.parse::<u32>().unwrap();
|
||||
(number, number_str.len())
|
||||
fn parse_number(line: &[u8]) -> (u32, usize) {
|
||||
let number_len = line
|
||||
.iter()
|
||||
.position(|&c| !c.is_ascii_digit())
|
||||
.unwrap_or(line.len());
|
||||
let number = atoi::<u32>(&line[..number_len]).unwrap();
|
||||
(number, number_len)
|
||||
}
|
||||
|
||||
fn parse_parts(puzzle: &str) -> Vec<PartsLine> {
|
||||
fn parse_parts(puzzle: &[u8]) -> Vec<PartsLine> {
|
||||
puzzle
|
||||
.lines()
|
||||
.split(|&c| c == b'\n')
|
||||
.map(|line| {
|
||||
let mut part_numbers = Vec::new();
|
||||
let mut i = 0;
|
||||
while i < line.len() {
|
||||
let c = line.chars().nth(i).unwrap();
|
||||
let c = line.get(i).unwrap();
|
||||
if c.is_ascii_digit() {
|
||||
let (number, number_len) = parse_number(&line[i..]);
|
||||
let part_number = PartNumber {
|
||||
|
@ -57,11 +58,11 @@ fn parse_parts(puzzle: &str) -> Vec<PartsLine> {
|
|||
.collect::<Vec<PartsLine>>()
|
||||
}
|
||||
|
||||
fn compute_part_numbers_sum(puzzle: &str) -> u32 {
|
||||
fn compute_part_numbers_sum(puzzle: &[u8]) -> u32 {
|
||||
let mut part_lines = parse_parts(puzzle);
|
||||
let line_range_max = part_lines.len() - 1;
|
||||
for (line_index, line) in puzzle.lines().enumerate() {
|
||||
for (i, c) in line.chars().enumerate() {
|
||||
for (line_index, line) in puzzle.split(|&c| c == b'\n').enumerate() {
|
||||
for (i, c) in line.iter().enumerate() {
|
||||
if c.is_symbol() {
|
||||
let line_range = line_index.saturating_sub(1)..=min(line_index + 1, line_range_max);
|
||||
part_lines[line_range]
|
||||
|
@ -79,13 +80,13 @@ fn compute_part_numbers_sum(puzzle: &str) -> u32 {
|
|||
.fold(0, |acc, part_number| acc + part_number.number)
|
||||
}
|
||||
|
||||
fn compute_gear_ratios_sum(puzzle: &str) -> u32 {
|
||||
fn compute_gear_ratios_sum(puzzle: &[u8]) -> u32 {
|
||||
let part_lines = parse_parts(puzzle);
|
||||
let line_range_max = part_lines.len() - 1;
|
||||
let mut gear_ratios_sum = 0;
|
||||
for (line_index, line) in puzzle.lines().enumerate() {
|
||||
for (i, c) in line.chars().enumerate() {
|
||||
if c == '*' {
|
||||
for (line_index, line) in puzzle.split(|&c| c == b'\n').enumerate() {
|
||||
for (i, c) in line.iter().enumerate() {
|
||||
if *c == b'*' {
|
||||
let line_range = line_index.saturating_sub(1)..=min(line_index + 1, line_range_max);
|
||||
let gear_parts = part_lines[line_range]
|
||||
.iter()
|
||||
|
@ -105,7 +106,7 @@ fn compute_gear_ratios_sum(puzzle: &str) -> u32 {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let puzzle = get_puzzle();
|
||||
let puzzle = get_puzzle_bytes();
|
||||
let start_time = std::time::Instant::now();
|
||||
println!("--- Day 3: Gear Ratios ---");
|
||||
println!("What is the sum of all of the part numbers in the engine schematic?");
|
||||
|
|
104
src/day4/main.rs
104
src/day4/main.rs
|
@ -1,43 +1,29 @@
|
|||
use adventofcode2023::utils::get_puzzle;
|
||||
use adventofcode2023::utils::get_puzzle_bytes;
|
||||
|
||||
fn parse_numbers(line: &str) -> Vec<u32> {
|
||||
line.split_whitespace()
|
||||
.map(|number_str| number_str.parse::<u32>().unwrap())
|
||||
.collect::<Vec<u32>>()
|
||||
fn compute_points(winning_numbers: &[u8], my_numbers: &[u8]) -> u32 {
|
||||
let win_count = my_numbers
|
||||
.chunks_exact(3)
|
||||
.map(|n| &n[1..])
|
||||
.filter(|n| {
|
||||
winning_numbers
|
||||
.chunks_exact(3)
|
||||
.map(|n| &n[1..])
|
||||
.any(|c| &c == n)
|
||||
})
|
||||
.count() as u32;
|
||||
2u32.pow(win_count) >> 1
|
||||
}
|
||||
|
||||
fn compute_points(winning_numbers: &[u32], my_numbers: &[u32]) -> u32 {
|
||||
let count = winning_numbers
|
||||
.iter()
|
||||
.filter(|&x| my_numbers.contains(x))
|
||||
.count();
|
||||
if count == 0 {
|
||||
0
|
||||
} else {
|
||||
2_u32.pow(count as u32 - 1)
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_total_points(puzzle: &str) -> u32 {
|
||||
fn compute_total_points(puzzle: &[u8]) -> u32 {
|
||||
let col = puzzle.iter().position(|&b| b == b':').unwrap();
|
||||
let sep = puzzle.iter().position(|&b| b == b'|').unwrap();
|
||||
puzzle
|
||||
.lines()
|
||||
.map(|lines| {
|
||||
lines
|
||||
.rsplit_once(": ")
|
||||
.unwrap()
|
||||
.1
|
||||
.rsplit_once(" | ")
|
||||
.unwrap()
|
||||
})
|
||||
.map(|(winning_numbers_str, my_numbers_str)| {
|
||||
(
|
||||
parse_numbers(winning_numbers_str),
|
||||
parse_numbers(my_numbers_str),
|
||||
)
|
||||
})
|
||||
.fold(0, |acc, (winning_numbers, my_numbers)| {
|
||||
acc + compute_points(&winning_numbers, &my_numbers)
|
||||
.split(|&c| c == b'\n')
|
||||
.map(|line| (&line[col + 1..sep], &line[sep + 1..]))
|
||||
.map(|(winning_numbers_bytes, my_numbers_bytes)| {
|
||||
compute_points(winning_numbers_bytes, my_numbers_bytes)
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
struct Scratchcard {
|
||||
|
@ -45,48 +31,46 @@ struct Scratchcard {
|
|||
copies: u32,
|
||||
}
|
||||
|
||||
fn parse_scratchcards(puzzle: &str) -> Vec<Scratchcard> {
|
||||
fn parse_scratchcards(puzzle: &[u8]) -> Vec<Scratchcard> {
|
||||
let col = puzzle.iter().position(|&b| b == b':').unwrap();
|
||||
let sep = puzzle.iter().position(|&b| b == b'|').unwrap();
|
||||
puzzle
|
||||
.lines()
|
||||
.map(|lines| {
|
||||
lines
|
||||
.rsplit_once(": ")
|
||||
.unwrap()
|
||||
.1
|
||||
.rsplit_once(" | ")
|
||||
.unwrap()
|
||||
})
|
||||
.map(|(winning_numbers_str, my_numbers_str)| {
|
||||
(
|
||||
parse_numbers(winning_numbers_str),
|
||||
parse_numbers(my_numbers_str),
|
||||
)
|
||||
})
|
||||
.split(|&c| c == b'\n')
|
||||
.map(|line| (&line[col + 1..sep], &line[sep + 1..]))
|
||||
.map(|(winning_numbers, my_numbers)| Scratchcard {
|
||||
score: winning_numbers
|
||||
.iter()
|
||||
.filter(|&x| my_numbers.contains(x))
|
||||
score: my_numbers
|
||||
.chunks_exact(3)
|
||||
.map(|n| &n[1..])
|
||||
.filter(|n| {
|
||||
winning_numbers
|
||||
.chunks_exact(3)
|
||||
.map(|n| &n[1..])
|
||||
.any(|c| &c == n)
|
||||
})
|
||||
.count() as u32,
|
||||
copies: 1,
|
||||
})
|
||||
.collect::<Vec<Scratchcard>>()
|
||||
}
|
||||
|
||||
fn compute_total_scratchcards(puzzle: &str) -> u32 {
|
||||
fn compute_total_scratchcards(puzzle: &[u8]) -> u32 {
|
||||
let mut scratchcards = parse_scratchcards(puzzle);
|
||||
for current_i in 0..scratchcards.len() {
|
||||
let to_copy_end = current_i + 1 + scratchcards[current_i].score as usize;
|
||||
for _ in 0..scratchcards[current_i].copies {
|
||||
for next_i in current_i + 1..to_copy_end {
|
||||
scratchcards[next_i].copies += 1;
|
||||
}
|
||||
let current_copies = scratchcards[current_i].copies;
|
||||
for next_scratchcard in scratchcards
|
||||
.iter_mut()
|
||||
.take(to_copy_end)
|
||||
.skip(current_i + 1)
|
||||
{
|
||||
next_scratchcard.copies += current_copies;
|
||||
}
|
||||
}
|
||||
scratchcards.iter().map(|card| card.copies).sum()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let puzzle = get_puzzle();
|
||||
let puzzle = get_puzzle_bytes();
|
||||
let start_time = std::time::Instant::now();
|
||||
println!("--- Day 4: Scratchcards ---");
|
||||
println!("How many points are they worth in total?");
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
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
|
|
@ -0,0 +1,134 @@
|
|||
use adventofcode2023::utils::get_puzzle_bytes;
|
||||
use atoi::atoi;
|
||||
use std::array;
|
||||
use std::cmp;
|
||||
use std::iter;
|
||||
use std::ops::Range;
|
||||
|
||||
const SECTIONS: usize = 7;
|
||||
|
||||
type Map = Vec<(Range<u64>, u64)>;
|
||||
|
||||
fn parse_maps(puzzle: &[u8]) -> Vec<Map> {
|
||||
let mut lines = puzzle.split(|&c| c == b'\n').skip(2);
|
||||
(0..SECTIONS)
|
||||
.map(|_| {
|
||||
let mut map = (&mut lines)
|
||||
.skip(1)
|
||||
.take_while(|line| !line.is_empty())
|
||||
.map(|line| {
|
||||
let mut iter = line.splitn(3, |b| b == &b' ').map(|b| atoi(b).unwrap());
|
||||
let values: [_; 3] = array::from_fn(|_| iter.next().unwrap());
|
||||
(values[1]..values[1] + values[2], values[0])
|
||||
})
|
||||
.collect::<Map>();
|
||||
map.sort_by_key(|(range, _)| range.start);
|
||||
map
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn parse_seeds(puzzle: &[u8]) -> Vec<u64> {
|
||||
puzzle[0..puzzle.iter().position(|b| b == &b'\n').unwrap()]
|
||||
.split(|b| b == &b' ')
|
||||
.skip(1)
|
||||
.map(|b| atoi(b).unwrap())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn compute_lowest_location_number(puzzle: &[u8]) -> u64 {
|
||||
let maps = parse_maps(puzzle);
|
||||
let seeds = parse_seeds(puzzle);
|
||||
seeds
|
||||
.iter()
|
||||
.map(|&seed| {
|
||||
maps.iter().fold(seed, |seed, map| {
|
||||
map.iter()
|
||||
.find_map(|(range, to)| match range.contains(&seed) {
|
||||
true => Some(seed + to - range.start),
|
||||
false => None,
|
||||
})
|
||||
.unwrap_or(seed)
|
||||
})
|
||||
})
|
||||
.min()
|
||||
.unwrap() as u64
|
||||
}
|
||||
|
||||
fn parse_seed_ranges(puzzle: &[u8]) -> Vec<Range<u64>> {
|
||||
let mut range_iter = puzzle[0..puzzle.iter().position(|b| b == &b'\n').unwrap()]
|
||||
.split(|b| b == &b' ')
|
||||
.skip(1)
|
||||
.map(|b| atoi::<u64>(b).unwrap());
|
||||
iter::from_fn(|| range_iter.next().zip(range_iter.next()))
|
||||
.map(|(start, len)| start..start + len)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn overlap<T: Ord>(a: Range<T>, b: Range<T>) -> Option<Range<T>> {
|
||||
let start = cmp::max(a.start, b.start);
|
||||
let end = cmp::min(a.end, b.end);
|
||||
if start < end {
|
||||
Some(start..end)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn map_range_to_destination(range: &Range<u64>, map: &Map) -> Vec<Range<u64>> {
|
||||
let mut mapped_ranges = Vec::new();
|
||||
let remainder_range = map.iter().fold(range.clone(), |range, (map_range, to)| {
|
||||
match overlap(range.clone(), map_range.clone()) {
|
||||
Some(overlap_range) => {
|
||||
if overlap_range.start > range.start {
|
||||
mapped_ranges.push(range.start..overlap_range.start);
|
||||
}
|
||||
mapped_ranges.push(
|
||||
overlap_range.start + to - map_range.start
|
||||
..overlap_range.end + to - map_range.start,
|
||||
);
|
||||
overlap_range.end..range.end
|
||||
}
|
||||
None => range,
|
||||
}
|
||||
});
|
||||
if !remainder_range.is_empty() {
|
||||
mapped_ranges.push(remainder_range);
|
||||
}
|
||||
mapped_ranges
|
||||
}
|
||||
|
||||
fn compute_lowest_location_from_ranges(puzzle: &[u8]) -> u64 {
|
||||
let maps = parse_maps(puzzle);
|
||||
let seed_ranges = parse_seed_ranges(puzzle);
|
||||
seed_ranges
|
||||
.iter()
|
||||
.flat_map(|seed_range| {
|
||||
maps.iter().fold(vec![seed_range.clone()], |ranges, map| {
|
||||
ranges
|
||||
.iter()
|
||||
.flat_map(|range| map_range_to_destination(range, map))
|
||||
.collect()
|
||||
})
|
||||
})
|
||||
.map(|range| range.start)
|
||||
.min()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let puzzle = get_puzzle_bytes();
|
||||
let start_time = std::time::Instant::now();
|
||||
println!("--- Day 5: If You Give A Seed A Fertilizer ---");
|
||||
println!(
|
||||
"What is the lowest location number that corresponds to any of the initial seed numbers?"
|
||||
);
|
||||
println!("{}", compute_lowest_location_number(&puzzle));
|
||||
println!("--- Part Two ---");
|
||||
println!(
|
||||
"What is the lowest location number that corresponds to any of the initial seed numbers?"
|
||||
);
|
||||
println!("{}", compute_lowest_location_from_ranges(&puzzle));
|
||||
let elapsed_time = start_time.elapsed();
|
||||
println!("compute time: {:?}", elapsed_time);
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
seeds: 280775197 7535297 3229061264 27275209 77896732 178275214 2748861189 424413807 3663093536 130341162 613340959 352550713 1532286286 1115055792 1075412586 241030710 3430371306 138606714 412141395 146351614
|
||||
|
||||
seed-to-soil map:
|
||||
2328878418 2173757269 55676388
|
||||
1604614185 284259424 18300254
|
||||
871339571 2660737044 103656521
|
||||
0 2281891142 53219493
|
||||
3600371492 4267529956 27437340
|
||||
1755732868 600174302 280911746
|
||||
225053611 2335110635 5908609
|
||||
3686191373 3693094019 157260119
|
||||
2301308430 2341019244 27569988
|
||||
2249924082 2817678844 51384348
|
||||
3843451492 3390401982 116711122
|
||||
866920588 2368589232 4418983
|
||||
319632173 0 10243502
|
||||
2384554806 302559678 74545000
|
||||
2036644614 2373008215 45489224
|
||||
480632565 1433058022 386288023
|
||||
3448897781 4166650940 100879016
|
||||
2082133838 377104678 167790244
|
||||
2644445775 2418497439 242239605
|
||||
1305360177 881086048 292964881
|
||||
3960162614 3638948449 54145570
|
||||
385155055 1819346045 95477510
|
||||
4021970860 3919567265 19798429
|
||||
3085107497 3850354138 69213127
|
||||
230962220 195589471 88669953
|
||||
1261037103 2129434195 44323074
|
||||
3627808832 3085107497 52096478
|
||||
329875675 544894922 55279380
|
||||
1622914439 2229433657 52457485
|
||||
1675371924 1352697078 80360944
|
||||
974996092 1914823555 107394862
|
||||
3549776797 3574405015 50594695
|
||||
3679905310 3632662386 6286063
|
||||
1082390954 1174050929 178646149
|
||||
2459099806 10243502 185345969
|
||||
160435271 2764393565 53285279
|
||||
3154320624 3939365694 227285246
|
||||
53219493 2022218417 107215778
|
||||
3381605870 3507113104 67291911
|
||||
4041769289 3137203975 253198007
|
||||
4014308184 3624999710 7662676
|
||||
213720550 2875352319 11333061
|
||||
1598325058 2869063192 6289127
|
||||
|
||||
soil-to-fertilizer map:
|
||||
3389090999 2596751746 608341779
|
||||
105086589 871525822 220821758
|
||||
3187814092 3748571797 34038948
|
||||
1063982526 822144230 49381592
|
||||
4071580733 3394766608 36570558
|
||||
1969786851 1283647913 135669504
|
||||
2338688657 3782610745 100105665
|
||||
2105456355 1092347580 1733094
|
||||
1113364118 0 435632229
|
||||
325908347 1524404006 161994939
|
||||
2438794322 4084049871 210917425
|
||||
4108151291 3471527086 26197923
|
||||
3997432778 2273224151 74147955
|
||||
3161148447 2395583294 26665645
|
||||
621898776 435632229 386512001
|
||||
4134349214 3882716410 46400134
|
||||
2649711747 3205093525 86087105
|
||||
4256353957 2384855243 10728051
|
||||
487903286 1149652423 133995490
|
||||
0 1419317417 105086589
|
||||
4218232485 3356645136 38121472
|
||||
4180749348 2347372106 37483137
|
||||
2910301659 3497725009 250846788
|
||||
2735798852 2422248939 23521261
|
||||
2273224151 3291180630 65464506
|
||||
3262042960 3957001832 127048039
|
||||
1548996347 1686398945 420790504
|
||||
4267082008 3929116544 27885288
|
||||
2759320113 2445770200 150981546
|
||||
1008410777 1094080674 55571749
|
||||
3221853040 3431337166 40189920
|
||||
|
||||
fertilizer-to-water map:
|
||||
2007324874 2683611319 23475372
|
||||
1313988767 1367341468 459297221
|
||||
1773285988 1938578086 234038886
|
||||
257353189 1257656713 109684755
|
||||
221312488 2981571133 36040701
|
||||
3464645820 3633779898 112824320
|
||||
1132250794 2637724313 45887006
|
||||
1178137800 0 135850967
|
||||
810899989 2295076898 321350805
|
||||
3706800774 4118877604 99172458
|
||||
3805973232 4218050062 17186653
|
||||
3823159885 3746604218 37073582
|
||||
2305284688 135850967 719035066
|
||||
3146779680 1826638689 111939397
|
||||
3024319754 2172616972 122459926
|
||||
3959767492 3783677800 335199804
|
||||
3934534290 4235236715 25233202
|
||||
408129309 854886033 402770680
|
||||
3258719077 2616427703 21296610
|
||||
3577470140 3504449264 129330634
|
||||
367037944 3238924322 41091365
|
||||
3860233467 4260469917 34497379
|
||||
3894730846 3464645820 39803444
|
||||
0 3017611834 221312488
|
||||
2030800246 2707086691 274484442
|
||||
|
||||
water-to-light map:
|
||||
3878354467 2554575322 61538919
|
||||
280412900 1377596407 93760042
|
||||
684284359 195116588 99127467
|
||||
4078572373 3977755696 216394923
|
||||
2619535971 3527291682 385503365
|
||||
1493593206 1581399685 135608385
|
||||
3693719871 2668857297 184634596
|
||||
2554575322 3912795047 64960649
|
||||
3236793954 2853491893 456925917
|
||||
817630982 1044576172 333020235
|
||||
1205196262 294244055 132442996
|
||||
1739244827 1012243273 32332899
|
||||
1771577726 0 101384292
|
||||
0 101384292 4968095
|
||||
101989723 448809000 178423177
|
||||
4019116409 4194150619 21593654
|
||||
4040710063 3489429372 37862310
|
||||
4968095 627232177 97021628
|
||||
374172942 724253805 287989468
|
||||
783411826 106352387 34219156
|
||||
3005039336 2616114241 52743056
|
||||
3939893386 4215744273 79223023
|
||||
1629201591 1471356449 110043236
|
||||
3057782392 3310417810 179011562
|
||||
1337639258 1717008070 155953948
|
||||
1150651217 140571543 54545045
|
||||
662162410 426687051 22121949
|
||||
|
||||
light-to-temperature map:
|
||||
2762906378 2204259687 134492279
|
||||
106349111 681820034 721307054
|
||||
997408643 115890239 153244527
|
||||
1512335036 1822350940 381908747
|
||||
3858505517 4045949291 249018005
|
||||
1894243783 3569882248 437693111
|
||||
3820131585 4007575359 38373932
|
||||
1505707247 3508506612 6627789
|
||||
2693538653 3439138887 69367725
|
||||
3029056394 2470409703 186112104
|
||||
54501260 269134766 51847851
|
||||
1452421821 3193053968 53285426
|
||||
850537566 0 115890239
|
||||
4107523522 3246339394 159303690
|
||||
4266827212 3164913884 28140084
|
||||
0 447698702 54501260
|
||||
3450202466 1452421821 369929119
|
||||
2897398657 2338751966 131657737
|
||||
966427805 650839196 30980838
|
||||
2331936894 3515134401 54747847
|
||||
2420180544 2656521807 273358109
|
||||
1206941949 502199962 83686237
|
||||
1150653170 320982617 56288779
|
||||
1361055492 585886199 42071596
|
||||
1290628186 377271396 70427306
|
||||
2386684741 3405643084 33495803
|
||||
827656165 627957795 22881401
|
||||
3215168498 2929879916 235033968
|
||||
|
||||
temperature-to-humidity map:
|
||||
3512511508 3713321076 246696808
|
||||
1575177202 3115625465 474937809
|
||||
4090629460 2000274085 135040194
|
||||
1141835951 1250511056 29255284
|
||||
151257068 40127528 247347323
|
||||
796868343 1046685126 203825930
|
||||
32926673 475089348 115925678
|
||||
3091489330 2135314279 421022178
|
||||
4225669654 1871071039 45515305
|
||||
4018596644 1533302854 72032816
|
||||
2105871498 1332898874 176621643
|
||||
398604391 732156704 170521927
|
||||
2475375726 4289723131 5244165
|
||||
4271184959 1509520517 23782337
|
||||
2480619891 2698929267 337643768
|
||||
3911645962 1605335670 55526138
|
||||
3759208316 3590563274 122757802
|
||||
3058110291 3082246426 33379039
|
||||
1404278872 1916586344 83687741
|
||||
15821415 1279766340 17105258
|
||||
0 902678631 15821415
|
||||
148852351 943795712 2404717
|
||||
2966942025 2607761001 91168266
|
||||
1308993408 3036573035 45673391
|
||||
1000694273 591015026 141141678
|
||||
756740815 0 40127528
|
||||
3881966118 1308993408 23905466
|
||||
1171091235 918500046 25295666
|
||||
1539650216 3960017884 35526986
|
||||
1354666799 4047228473 49612073
|
||||
3905871584 1865296661 5774378
|
||||
3967172100 2556336457 51424544
|
||||
2050115011 1809540174 55756487
|
||||
1487966613 3995544870 51683603
|
||||
2818263659 1660861808 148678366
|
||||
569126318 287474851 187614497
|
||||
2282493141 4096840546 192882585
|
||||
1196386901 946200429 100484697
|
||||
|
||||
humidity-to-location map:
|
||||
1176010827 433228953 11431675
|
||||
3343304446 3212529205 243926878
|
||||
3019400776 2809960450 121184456
|
||||
598353273 717816068 6343029
|
||||
2345678711 3761800910 44017519
|
||||
2389696230 4104193148 30873153
|
||||
334421220 1167819222 181559786
|
||||
2083857214 2364759797 169609191
|
||||
169788889 1665299576 164632331
|
||||
1547379326 837819247 83916771
|
||||
636928438 1349379008 3985237
|
||||
1997878235 4242793968 52173328
|
||||
4036700740 3456456083 70103553
|
||||
1701551461 724159097 55714896
|
||||
2050051563 4072991568 31201580
|
||||
1495464492 0 51914834
|
||||
1771229473 779873993 57945254
|
||||
1757266357 444660628 13963116
|
||||
640913675 1829931907 79566117
|
||||
604696302 1135587086 32232136
|
||||
2790976533 2058196402 571198
|
||||
0 183116767 169788889
|
||||
581107897 458623744 17245376
|
||||
1032415123 921736018 143595704
|
||||
2880695042 3109061793 3719369
|
||||
3596511671 3547168702 214632208
|
||||
1989658157 4064771490 8220078
|
||||
2791547731 1989658157 68538245
|
||||
1631296097 1065331722 70255364
|
||||
2253466405 2606294055 92212306
|
||||
2591363195 3865158152 199613338
|
||||
2532023472 3805818429 59339723
|
||||
1253517544 475869120 241946948
|
||||
3811143879 2058767600 225556861
|
||||
3334473574 2931144906 8830872
|
||||
720479792 1353364245 311935331
|
||||
2420569383 2698506361 111454089
|
||||
2081253143 2603689984 2604071
|
||||
3140585232 2939975778 159805668
|
||||
2860085976 3526559636 20609066
|
||||
1829174727 352905656 80323297
|
||||
515981006 117989876 65126891
|
||||
3587231324 3099781446 9280347
|
||||
1187442502 51914834 66075042
|
||||
2953735407 3112781162 65665369
|
||||
4187239629 4135066301 107727667
|
||||
3300390900 3178446531 34082674
|
||||
2884414411 2534368988 69320996
|
||||
4106804293 2284324461 80435336
|
18
src/utils.rs
18
src/utils.rs
|
@ -17,3 +17,21 @@ pub fn get_puzzle() -> String {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_puzzle_bytes() -> Vec<u8> {
|
||||
let mut args_iter = env::args();
|
||||
let cmd_name = args_iter.next().unwrap();
|
||||
let path = match args_iter.next() {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
eprintln!("USAGE: {} puzzle_path", cmd_name);
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
match fs::read(&path) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
panic!("error opening {}: {}", path, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue