Compare commits

..

2 commits

Author SHA1 Message Date
b2bd814c8a day 6 part 2 2023-12-07 11:54:11 -05:00
228c5fb6d5 day 6 part 1 2023-12-07 11:53:43 -05:00
3 changed files with 55 additions and 422 deletions

View file

@ -1,33 +1,2 @@
seeds: 79 14 55 13 Time: 7 15 30
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
View file

@ -1,172 +1,2 @@
seeds: 5844012 110899473 1132285750 58870036 986162929 109080640 3089574276 100113624 2693179996 275745330 2090752257 201704169 502075018 396653347 1540050181 277513792 1921754120 26668991 3836386950 66795009 Time: 44 82 69 81
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

View file

@ -1,242 +1,76 @@
use std::cmp::{max, min}; use std::io::stdin;
use std::{collections::HashMap, io::stdin};
use anyhow::Result; use anyhow::{bail, Result};
use regex::Regex; use regex::Regex;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] /// solve ax² + bx + c = 0
struct Range { fn solve_quadratic(a: f64, b: f64, c: f64) -> (f64, f64) {
start: i64, let r1 = (-b + f64::sqrt(b * b - 4.0 * a * c)) / 2.0 * a;
len: i64, let r2 = (-b - f64::sqrt(b * b - 4.0 * a * c)) / 2.0 * a;
(r1, r2)
} }
impl Range { fn parse_input() -> Result<(Vec<i64>, Vec<i64>)> {
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 pairs = Regex::new(r"(\d+) (\d+)")?; let mut times = vec![];
let mut current_map = String::new(); let mut distances = vec![];
for line in stdin().lines().map_while(Result::ok) { for line in stdin().lines().map_while(Result::ok) {
if line.starts_with("seeds:") { if line.starts_with("Time:") {
*seed_ranges = pairs times = numbers
.captures_iter(&line) .captures_iter(&line.replace(' ', ""))
.map(|c| -> Result<Range> {
Ok(Range {
start: c.get(1).unwrap().as_str().parse()?,
len: c.get(2).unwrap().as_str().parse()?,
})
})
.map_while(Result::ok)
.collect();
} else if line.ends_with(" map:") {
current_map = line
.split_whitespace()
.next()
.unwrap_or_default()
.to_owned();
} else {
let nums: Vec<i64> = numbers
.captures_iter(&line)
.map(|c| c.get(1).unwrap().as_str().parse()) .map(|c| c.get(1).unwrap().as_str().parse())
.map_while(Result::ok) .map_while(Result::ok)
.collect(); .collect();
if nums.len() == 3 { } else if line.starts_with("Distance:") {
let map = maps distances = numbers
.entry(current_map.clone()) .captures_iter(&line.replace(' ', ""))
.or_insert_with(SeedsMap::new); .map(|c| c.get(1).unwrap().as_str().parse())
map.add_range((nums[0], nums[1], nums[2])); .map_while(Result::ok)
.collect();
} else {
bail!("unexpected line: {}", line);
} }
} }
} Ok((times, distances))
Ok(())
} }
fn main() -> Result<()> { fn main() -> Result<()> {
let mut maps: HashMap<String, SeedsMap> = HashMap::new(); let (times, distances) = parse_input()?;
let mut seed_ranges: Vec<Range> = vec![];
parse_input(&mut seed_ranges, &mut maps)?; if times.len() != distances.len() {
bail!(
let map_names = [ "times has {} elements, but distances has {} elements",
"seed-to-soil", times.len(),
"soil-to-fertilizer", distances.len()
"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_intersections() { fn test() {}
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 }]
);
}
} }