Compare commits
No commits in common. "b2bd814c8aef63adf2a57756a0cc46f60032db8c" and "9380266a2a4c3821eb4a6591f999f15b2faf4565" have entirely different histories.
b2bd814c8a
...
9380266a2a
3 changed files with 422 additions and 55 deletions
35
example.txt
35
example.txt
|
@ -1,2 +1,33 @@
|
||||||
Time: 7 15 30
|
seeds: 79 14 55 13
|
||||||
Distance: 9 40 200
|
|
||||||
|
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
|
||||||
|
|
174
input.txt
174
input.txt
|
@ -1,2 +1,172 @@
|
||||||
Time: 44 82 69 81
|
seeds: 5844012 110899473 1132285750 58870036 986162929 109080640 3089574276 100113624 2693179996 275745330 2090752257 201704169 502075018 396653347 1540050181 277513792 1921754120 26668991 3836386950 66795009
|
||||||
Distance: 202 1076 1138 1458
|
|
||||||
|
seed-to-soil map:
|
||||||
|
3547471595 1239929038 174680800
|
||||||
|
3052451552 758183681 481745357
|
||||||
|
0 1427884524 1775655006
|
||||||
|
2844087171 549819300 208364381
|
||||||
|
3767989253 4004864866 5194940
|
||||||
|
3534196909 1414609838 13274686
|
||||||
|
1775655006 114264781 435554519
|
||||||
|
4148908402 4010059806 146058894
|
||||||
|
2729822390 0 114264781
|
||||||
|
3773184193 4156118700 138848596
|
||||||
|
2211209525 3203539530 518612865
|
||||||
|
3912032789 3767989253 236875613
|
||||||
|
|
||||||
|
soil-to-fertilizer map:
|
||||||
|
912405184 1056091028 152837752
|
||||||
|
194471272 1208928780 200072008
|
||||||
|
136115250 240819204 58356022
|
||||||
|
3502815281 3536983174 299994001
|
||||||
|
2321814552 2458149869 18748048
|
||||||
|
3173949445 2623931701 9591555
|
||||||
|
394543280 888648379 167442649
|
||||||
|
1990258415 3891640206 212931291
|
||||||
|
1068754270 54862533 153774684
|
||||||
|
1222528954 660792432 186471834
|
||||||
|
3340878967 3405750148 131233026
|
||||||
|
3472111993 3836977175 30703288
|
||||||
|
561985929 299175226 225501956
|
||||||
|
2942828492 4104571497 88527954
|
||||||
|
874532405 850775600 37872779
|
||||||
|
3031356446 3867680463 23959743
|
||||||
|
842350418 208637217 32181987
|
||||||
|
0 524677182 136115250
|
||||||
|
1065242936 847264266 3511334
|
||||||
|
2203189706 2339525023 118624846
|
||||||
|
1929736108 2563409394 60522307
|
||||||
|
3802809282 1847367009 492158014
|
||||||
|
1847367009 2790861223 82369099
|
||||||
|
2442430445 2873230322 500398047
|
||||||
|
3183541000 2633523256 157337967
|
||||||
|
3141827666 3373628369 32121779
|
||||||
|
787487885 0 54862533
|
||||||
|
3055316189 2476897917 86511477
|
||||||
|
2340562600 4193099451 101867845
|
||||||
|
|
||||||
|
fertilizer-to-water map:
|
||||||
|
798315344 439687669 1930292
|
||||||
|
1174979421 2966258900 475289790
|
||||||
|
439687669 778614573 55925503
|
||||||
|
3743699694 3453541232 155280637
|
||||||
|
2989334775 1659556189 96021468
|
||||||
|
1650269211 3441548690 11992542
|
||||||
|
3898980331 3608821869 395986965
|
||||||
|
1705125292 2123762646 842496254
|
||||||
|
3375514705 1755577657 368184989
|
||||||
|
646363825 441617961 94777173
|
||||||
|
1662261753 1616692650 42863539
|
||||||
|
495613172 627863920 150750653
|
||||||
|
2777061135 1174979421 212273640
|
||||||
|
741140998 834540076 57174346
|
||||||
|
800245636 536395134 91468786
|
||||||
|
2547621546 1387253061 229439589
|
||||||
|
3085356243 4004808834 290158462
|
||||||
|
|
||||||
|
water-to-light map:
|
||||||
|
541719462 212840988 165903288
|
||||||
|
3437755571 1615831015 672632835
|
||||||
|
1051033542 2678450187 510773217
|
||||||
|
243353905 378744276 104057369
|
||||||
|
1561806759 3801474127 134575711
|
||||||
|
707622750 677109833 258560892
|
||||||
|
2580483557 1051033542 195631857
|
||||||
|
0 935670725 30512917
|
||||||
|
347411274 482801645 194308188
|
||||||
|
30512917 0 127836567
|
||||||
|
2190497220 2288463850 389986337
|
||||||
|
3068589955 1246665399 369165616
|
||||||
|
1754579039 3936049838 66442917
|
||||||
|
4110388406 3616895237 184578890
|
||||||
|
158349484 127836567 85004421
|
||||||
|
2776115414 4002492755 292474541
|
||||||
|
1821021956 3247419973 369475264
|
||||||
|
1696382470 3189223404 58196569
|
||||||
|
|
||||||
|
light-to-temperature map:
|
||||||
|
338228166 2812162941 77503977
|
||||||
|
3123877206 693964345 40932068
|
||||||
|
3939438903 614787731 633466
|
||||||
|
3301169239 2299402886 215156012
|
||||||
|
3516325251 499164007 115623724
|
||||||
|
3852145506 3365439095 87293397
|
||||||
|
875755064 3565078024 729889272
|
||||||
|
2849390436 734896413 11914872
|
||||||
|
2861305308 215265512 77518872
|
||||||
|
4220385528 2056242491 68417151
|
||||||
|
2221674563 3167682469 34693717
|
||||||
|
2765973467 292784384 83416969
|
||||||
|
3198884011 1699097031 22283517
|
||||||
|
3164809274 2889666918 34074737
|
||||||
|
809366712 746811285 52314986
|
||||||
|
4096970661 1633036395 58945085
|
||||||
|
3221167528 2699611924 80001711
|
||||||
|
697021180 3452732492 112345532
|
||||||
|
2059345064 799126271 162329499
|
||||||
|
4155915746 629494563 64469782
|
||||||
|
2431111524 1721380548 334861943
|
||||||
|
684283267 2779613635 12737913
|
||||||
|
440342453 2923741655 243940814
|
||||||
|
3634265609 961455770 217879897
|
||||||
|
4288802679 3202376186 6164617
|
||||||
|
415732143 1691981480 4798917
|
||||||
|
1605644336 1179335667 453700728
|
||||||
|
420531060 2792351548 19811393
|
||||||
|
3631948975 1696780397 2316634
|
||||||
|
2938824180 2514558898 185053026
|
||||||
|
215265512 376201353 122962654
|
||||||
|
2256368280 2124659642 174743244
|
||||||
|
3940072369 3208540803 156898292
|
||||||
|
861681698 615421197 14073366
|
||||||
|
|
||||||
|
temperature-to-humidity map:
|
||||||
|
841576398 2731200418 60836938
|
||||||
|
1860695540 395011682 292982985
|
||||||
|
1518037021 3432774193 53954373
|
||||||
|
1786573987 2461900019 55353430
|
||||||
|
2940303448 1995108352 6974538
|
||||||
|
3014069287 1664464874 53916789
|
||||||
|
753139746 2190061656 88436652
|
||||||
|
2351822957 2925825589 209990361
|
||||||
|
3079884326 3498626816 37609115
|
||||||
|
4067060121 4186346579 108620717
|
||||||
|
4175680838 4102322798 3778367
|
||||||
|
1571991394 2415899186 46000833
|
||||||
|
2841627583 1157034722 22534242
|
||||||
|
1841927417 2517253449 18768123
|
||||||
|
2153678525 47765849 108568164
|
||||||
|
3251281674 1179568964 226737882
|
||||||
|
3067986076 3486728566 11898250
|
||||||
|
1308101633 1785172964 209935388
|
||||||
|
2262246689 1406306846 89576268
|
||||||
|
902413336 2278498308 137400878
|
||||||
|
1039814214 3765380846 268287419
|
||||||
|
45422022 156334013 238677669
|
||||||
|
3617672799 2612163195 119037223
|
||||||
|
2947277986 1718381663 66791301
|
||||||
|
1617992227 1495883114 168581760
|
||||||
|
284099691 687994667 469040055
|
||||||
|
4214721882 4106101165 80245414
|
||||||
|
2839283756 45422022 2343827
|
||||||
|
3117493441 2792037356 133788233
|
||||||
|
2864161825 2536021572 76141623
|
||||||
|
4179459205 4067060121 35262677
|
||||||
|
3736710022 3135815950 296958243
|
||||||
|
3478019556 2002082890 139653243
|
||||||
|
2610138841 3536235931 229144915
|
||||||
|
2561813318 2141736133 48325523
|
||||||
|
|
||||||
|
humidity-to-location map:
|
||||||
|
608325534 0 231346900
|
||||||
|
222429954 453776854 385895580
|
||||||
|
3710263359 3540956206 563631409
|
||||||
|
1193511298 1116937854 38719102
|
||||||
|
1702450793 1176729484 153572024
|
||||||
|
1694669826 1109156887 7780967
|
||||||
|
0 231346900 222429954
|
||||||
|
1856022817 1686715664 1854240542
|
||||||
|
1588644556 4104587615 106025270
|
||||||
|
1109156887 4210612885 84354411
|
||||||
|
4273894768 1155656956 21072528
|
||||||
|
1232230400 1330301508 356414156
|
||||||
|
|
266
src/main.rs
266
src/main.rs
|
@ -1,76 +1,242 @@
|
||||||
use std::io::stdin;
|
use std::cmp::{max, min};
|
||||||
|
use std::{collections::HashMap, io::stdin};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::Result;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
/// solve ax² + bx + c = 0
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
fn solve_quadratic(a: f64, b: f64, c: f64) -> (f64, f64) {
|
struct Range {
|
||||||
let r1 = (-b + f64::sqrt(b * b - 4.0 * a * c)) / 2.0 * a;
|
start: i64,
|
||||||
let r2 = (-b - f64::sqrt(b * b - 4.0 * a * c)) / 2.0 * a;
|
len: i64,
|
||||||
(r1, r2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_input() -> Result<(Vec<i64>, Vec<i64>)> {
|
impl Range {
|
||||||
|
fn intersection(&self, other: &Range) -> Option<Range> {
|
||||||
|
let i1 = max(self.start, other.start);
|
||||||
|
let i2 = min(self.start + self.len, other.start + other.len);
|
||||||
|
|
||||||
|
if i1 >= i2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Range {
|
||||||
|
start: i1,
|
||||||
|
len: i2 - i1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct RangeMap {
|
||||||
|
from: i64,
|
||||||
|
to: i64,
|
||||||
|
len: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct SeedsMap {
|
||||||
|
range_maps: Vec<RangeMap>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SeedsMap {
|
||||||
|
fn new() -> SeedsMap {
|
||||||
|
SeedsMap { range_maps: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_range(&mut self, range: (i64, i64, i64)) {
|
||||||
|
self.range_maps.push(RangeMap {
|
||||||
|
from: range.1,
|
||||||
|
to: range.0,
|
||||||
|
len: range.2,
|
||||||
|
});
|
||||||
|
self.range_maps.sort_by_key(|r| r.from);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map(&self, ranges: &[Range]) -> Vec<Range> {
|
||||||
|
let mut result = vec![];
|
||||||
|
for r in ranges {
|
||||||
|
result.extend(self.map_single_range(r));
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_single_range(&self, range: &Range) -> Vec<Range> {
|
||||||
|
if self.range_maps.is_empty() {
|
||||||
|
return vec![*range];
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result = vec![];
|
||||||
|
let first = self.range_maps.first().unwrap();
|
||||||
|
let last = self.range_maps.last().unwrap();
|
||||||
|
let left = min(range.start, first.from);
|
||||||
|
let right = max(range.start + range.len, last.from + last.len);
|
||||||
|
|
||||||
|
let mut last = left;
|
||||||
|
for rm in &self.range_maps {
|
||||||
|
// first, a range from last to rm.start, with no mapping
|
||||||
|
let r = Range {
|
||||||
|
start: last,
|
||||||
|
len: rm.from - last,
|
||||||
|
};
|
||||||
|
if let Some(i) = r.intersection(range) {
|
||||||
|
result.push(i);
|
||||||
|
}
|
||||||
|
// second, a range from rm.start, with mapping
|
||||||
|
let r = Range {
|
||||||
|
start: rm.from,
|
||||||
|
len: rm.len,
|
||||||
|
};
|
||||||
|
if let Some(i) = r.intersection(range) {
|
||||||
|
result.push(Range {
|
||||||
|
start: rm.to + i.start - rm.from,
|
||||||
|
len: i.len,
|
||||||
|
});
|
||||||
|
last = i.start + i.len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = Range {
|
||||||
|
start: last,
|
||||||
|
len: right - last,
|
||||||
|
};
|
||||||
|
if let Some(i) = r.intersection(range) {
|
||||||
|
result.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(seed_ranges: &mut Vec<Range>, maps: &mut HashMap<String, SeedsMap>) -> Result<()> {
|
||||||
let numbers = Regex::new(r"(\d+)")?;
|
let numbers = Regex::new(r"(\d+)")?;
|
||||||
let mut times = vec![];
|
let pairs = Regex::new(r"(\d+) (\d+)")?;
|
||||||
let mut distances = vec![];
|
let mut current_map = String::new();
|
||||||
for line in stdin().lines().map_while(Result::ok) {
|
for line in stdin().lines().map_while(Result::ok) {
|
||||||
if line.starts_with("Time:") {
|
if line.starts_with("seeds:") {
|
||||||
times = numbers
|
*seed_ranges = pairs
|
||||||
.captures_iter(&line.replace(' ', ""))
|
.captures_iter(&line)
|
||||||
.map(|c| c.get(1).unwrap().as_str().parse())
|
.map(|c| -> Result<Range> {
|
||||||
.map_while(Result::ok)
|
Ok(Range {
|
||||||
.collect();
|
start: c.get(1).unwrap().as_str().parse()?,
|
||||||
} else if line.starts_with("Distance:") {
|
len: c.get(2).unwrap().as_str().parse()?,
|
||||||
distances = numbers
|
})
|
||||||
.captures_iter(&line.replace(' ', ""))
|
})
|
||||||
.map(|c| c.get(1).unwrap().as_str().parse())
|
|
||||||
.map_while(Result::ok)
|
.map_while(Result::ok)
|
||||||
.collect();
|
.collect();
|
||||||
|
} else if line.ends_with(" map:") {
|
||||||
|
current_map = line
|
||||||
|
.split_whitespace()
|
||||||
|
.next()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.to_owned();
|
||||||
} else {
|
} else {
|
||||||
bail!("unexpected line: {}", line);
|
let nums: Vec<i64> = numbers
|
||||||
|
.captures_iter(&line)
|
||||||
|
.map(|c| c.get(1).unwrap().as_str().parse())
|
||||||
|
.map_while(Result::ok)
|
||||||
|
.collect();
|
||||||
|
if nums.len() == 3 {
|
||||||
|
let map = maps
|
||||||
|
.entry(current_map.clone())
|
||||||
|
.or_insert_with(SeedsMap::new);
|
||||||
|
map.add_range((nums[0], nums[1], nums[2]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((times, distances))
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let (times, distances) = parse_input()?;
|
let mut maps: HashMap<String, SeedsMap> = HashMap::new();
|
||||||
|
let mut seed_ranges: Vec<Range> = vec![];
|
||||||
|
|
||||||
if times.len() != distances.len() {
|
parse_input(&mut seed_ranges, &mut maps)?;
|
||||||
bail!(
|
|
||||||
"times has {} elements, but distances has {} elements",
|
let map_names = [
|
||||||
times.len(),
|
"seed-to-soil",
|
||||||
distances.len()
|
"soil-to-fertilizer",
|
||||||
);
|
"fertilizer-to-water",
|
||||||
|
"water-to-light",
|
||||||
|
"light-to-temperature",
|
||||||
|
"temperature-to-humidity",
|
||||||
|
"humidity-to-location",
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut locations = vec![];
|
||||||
|
for range in seed_ranges {
|
||||||
|
let mut mapped_ranges = vec![range];
|
||||||
|
for map_name in map_names {
|
||||||
|
let mapped = maps.get(map_name).unwrap().map(&mapped_ranges);
|
||||||
|
mapped_ranges = mapped;
|
||||||
}
|
}
|
||||||
|
locations.extend(mapped_ranges.iter().map(|r| r.start));
|
||||||
let mut prod = 1;
|
|
||||||
for i in 0..times.len() {
|
|
||||||
let t = times[i];
|
|
||||||
let d = distances[i];
|
|
||||||
|
|
||||||
// the equation to solve is x * (t - x) - d = 0
|
|
||||||
// = t*x - x*x - d = 0
|
|
||||||
// = -1x² + tx - d = 0
|
|
||||||
let (r1, r2) = solve_quadratic(-1.0, t as f64, -d as f64);
|
|
||||||
let r1 = (r1 + 1.0).floor() as i64;
|
|
||||||
let r2 = (r2 - 1.0).ceil() as i64;
|
|
||||||
|
|
||||||
let ways = (r2 - r1) + 1;
|
|
||||||
|
|
||||||
println!("{t} {d}");
|
|
||||||
println!("ways: {ways}");
|
|
||||||
prod *= ways;
|
|
||||||
}
|
}
|
||||||
|
println!("{}", locations.iter().min().unwrap());
|
||||||
println!("{prod}");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {}
|
fn test_intersections() {
|
||||||
|
let l = |r1: &Range, r2: &Range| r1.intersection(r2);
|
||||||
|
assert_eq!(
|
||||||
|
l(&Range { start: 1, len: 3 }, &Range { start: 1, len: 3 }),
|
||||||
|
Some(Range { start: 1, len: 3 })
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
l(&Range { start: 1, len: 2 }, &Range { start: 1, len: 3 }),
|
||||||
|
Some(Range { start: 1, len: 2 })
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
l(&Range { start: 2, len: 4 }, &Range { start: 0, len: 3 }),
|
||||||
|
Some(Range { start: 2, len: 1 })
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
l(&Range { start: 0, len: 3 }, &Range { start: 2, len: 4 }),
|
||||||
|
Some(Range { start: 2, len: 1 })
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
l(&Range { start: 3, len: 4 }, &Range { start: 0, len: 3 }),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
l(&Range { start: 0, len: 10 }, &Range { start: 4, len: 4 }),
|
||||||
|
Some(Range { start: 4, len: 4 })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_range_map() {
|
||||||
|
let mut m = SeedsMap::new();
|
||||||
|
m.add_range((52, 50, 48));
|
||||||
|
m.add_range((50, 98, 2));
|
||||||
|
let r = m.map_single_range(&Range { start: 79, len: 14 });
|
||||||
|
assert_eq!(r, [Range { start: 81, len: 14 }]);
|
||||||
|
|
||||||
|
let mut m = SeedsMap::new();
|
||||||
|
m.add_range((39, 0, 15));
|
||||||
|
m.add_range((0, 15, 37));
|
||||||
|
m.add_range((37, 52, 2));
|
||||||
|
let r = m.map_single_range(&Range { start: 81, len: 14 });
|
||||||
|
assert_eq!(r, [Range { start: 81, len: 14 }]);
|
||||||
|
|
||||||
|
let mut m = SeedsMap::new();
|
||||||
|
m.add_range((88, 18, 7));
|
||||||
|
m.add_range((18, 25, 70));
|
||||||
|
let r = m.map_single_range(&Range { start: 81, len: 14 });
|
||||||
|
assert_eq!(r, [Range { start: 74, len: 14 }]);
|
||||||
|
|
||||||
|
let mut m = SeedsMap::new();
|
||||||
|
m.add_range((81, 45, 19));
|
||||||
|
m.add_range((68, 64, 13));
|
||||||
|
m.add_range((45, 77, 23));
|
||||||
|
let r = m.map_single_range(&Range { start: 74, len: 14 });
|
||||||
|
assert_eq!(
|
||||||
|
r,
|
||||||
|
[Range { start: 78, len: 3 }, Range { start: 45, len: 11 }]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue