feat(day5): day5 solution and bytes optimizations

main
flavien 2023-12-06 18:06:15 +01:00
parent 46530a0693
commit 6c8fdeeeb6
No known key found for this signature in database
10 changed files with 582 additions and 120 deletions

27
Cargo.lock generated
View File

@ -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",
]

View File

@ -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"

View File

@ -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);
}

View File

@ -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?");

View File

@ -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?");

View File

@ -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?");

33
src/day5/example.txt Normal file
View File

@ -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

134
src/day5/main.rs Normal file
View File

@ -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);
}

256
src/day5/puzzle5.txt Normal file
View File

@ -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

View File

@ -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);
}
}
}