This commit is contained in:
Shadowfacts 2023-12-05 12:00:52 -05:00
parent 89f0756557
commit d7a1b5d9c0
3 changed files with 533 additions and 1 deletions

261
input/day5.txt Normal file
View File

@ -0,0 +1,261 @@
seeds: 2906422699 6916147 3075226163 146720986 689152391 244427042 279234546 382175449 1105311711 2036236 3650753915 127044950 3994686181 93904335 1450749684 123906789 2044765513 620379445 1609835129 60050954
seed-to-soil map:
2642418175 2192252668 3835256
2646253431 2276158914 101631202
2640809144 3719389865 1609031
2439110058 2377790116 121628096
439727986 2712085714 392957193
993018128 1316992003 327657967
832685179 1875058987 50438969
2796039666 0 1107546829
182253984 3569317158 150072707
2747884633 1826903954 48155033
2268424297 3406848659 162468499
0 1644649970 182253984
1794130013 2499418212 105266207
2560738154 2196087924 80070990
1512587867 1925497956 72096972
2094053960 3729216158 174370337
1320676095 3105042907 191911772
1899396220 1997594928 194657740
2430892796 3720998896 8217262
1584684839 1107546829 209445174
332326691 2604684419 107401295
883124148 3296954679 109893980
soil-to-fertilizer map:
1486714106 1238503832 507721065
637816737 149749818 437782225
1182620803 2675299784 39248251
3597657865 3775149764 175910008
3773567873 3962939269 152626038
3000531163 3487988055 287161709
1221869054 1043346723 160011771
1417026163 2117544922 69687943
3584687325 3000531163 12970540
3938073408 3484898614 3089441
4154999630 4115565307 65971879
3941162849 3087497490 97611489
427771233 2337712270 210045504
2132339212 587532043 265793132
4220971509 3013501703 73995787
3926193911 3951059772 11879497
3287692872 3271363394 97309928
3385002800 3185108979 86254415
277291828 2187232865 150479405
1075598962 1746224897 107021841
1994435171 2714548035 137904041
2398132344 1853246738 264298184
4038774338 3368673322 116225292
0 2547757774 127542010
127542010 0 149749818
2662430528 853325175 190021548
3471257215 4181537186 113430110
1381880825 1203358494 35145338
fertilizer-to-water map:
1335715777 3551297863 15572557
3058091197 394986221 12806050
3214739636 1272556544 43474947
2194583281 3796992984 5908188
1795111705 3569682225 74131978
2761913827 2554114847 40731321
163407858 97246509 38153094
201560952 135399603 99530224
2940391010 2113359463 79167148
1379193735 3838257748 62489021
605586814 1626110823 487248640
1210765693 2673739436 122138279
2657443462 2449644482 104470365
1332903972 3566870420 2811805
1092835454 1468044840 52984152
3612861396 610695664 247630343
4056909324 407792271 18897075
1351288334 3900746769 27905401
2200491469 2958550754 43716751
3070897247 426689346 143842389
2563990948 2356191968 93452514
3860491739 2192526611 17573017
430342797 3077819515 14543393
1441682756 3140553634 112714328
1554397084 1521028992 105081831
1659478915 858326007 135632790
1195705829 4279907432 15059864
4075806399 3372259011 179038852
2490006393 570531735 40163929
2244208220 2795877715 126807124
3272482070 3939528106 340379326
444886190 3092362908 48190726
1145819606 3027933292 49886223
2371015344 3253267962 118991049
3878064756 3002267505 25665787
1869243683 993958797 278597747
3258214583 1316031491 14267487
2802645148 1330298978 137745862
2563752764 2673501252 238184
3903730543 3643814203 153178781
97246509 234929827 66161349
2158717366 2922684839 35865915
2147841430 3928652170 10875936
3019558158 2594846168 38533039
493076916 2210099628 112509898
2530170322 2322609526 33582442
394986221 3802901172 35356576
4254845251 2633379207 40122045
water-to-light map:
52352735 734025495 196243881
3196736017 3686620279 539418860
4260073591 2346541810 34893705
3824140629 2381435515 128703321
460535344 312464861 85993982
963896761 930269376 1539501
2058204537 3345283958 241067289
1428799796 3586351247 100269032
3077002514 1717378211 119733503
2792038862 1432414559 284963652
0 683119049 18725350
2738205765 2731593698 53833097
248596616 6913757 211938728
953587656 0 6913757
3736154877 2818563473 87985752
1988337486 2311649339 34892471
668927450 398458843 284660206
2023229957 3310309378 34974580
18725350 951959788 13476474
2631325954 2191463345 25160101
1295231825 2967131323 133567971
2491590802 2510138836 139735152
546529326 701844399 32181096
3952843950 2906549225 60582098
1882790692 3100699294 48444656
2354408068 1295231825 137182734
4153221679 4226039139 68928157
2299901593 3288939581 21369797
2321271390 2785426795 33136678
578710422 222247833 90217028
4013426048 3149143950 139795631
1529068828 1837741481 353721864
1931235348 2216623446 57102138
32201824 931808877 20150911
2299271826 1837111714 629767
960501413 218852485 3395348
4222149836 2273725584 37923755
2656486055 2649873988 81719710
light-to-temperature map:
2002559950 382000741 90685628
285136495 3669200023 235300945
1697895437 3029658057 91190914
2333974289 2655904102 65571245
283606237 1729595262 1530258
3395579298 2846931786 182726271
3908077331 4156397993 58163239
1641412094 1383382121 13076534
3171401086 1731125520 55619959
2399545534 283606237 11466807
2411012341 694053237 46713076
555564215 2831795288 15136498
570700713 1473120509 221347978
520437440 1694468487 35126775
1640428391 3411773949 983703
2936877085 306865692 75135049
3578305569 2167033125 54004942
1076200859 2221038067 81247286
3884751672 1148097778 23325659
3632310511 746654088 139828329
4189239539 3506297541 50289650
1909020061 3412757652 93539889
2709622442 740766313 5887775
792048691 1911214447 163922279
3999452535 4264264797 30702499
3159608438 295073044 11792648
1064487544 2588752680 11713315
1172524157 902820295 245277483
1789086351 1263448411 119933710
2715510217 472686369 221366868
2093245578 3147917902 240728711
1417801640 2366125929 222626751
3303682899 2075136726 91896399
955970970 4214561232 49703565
1157448145 2302285353 15076012
3012012134 3388646613 23127336
3966240570 1230236446 33211965
4030155034 2317361365 48764564
3227021045 1396458655 76661854
3035139470 1786745479 124468968
2457725417 3904500968 251897025
1005674535 1171423437 58813009
4078919598 2721475347 110319941
1654488628 886482417 16337878
3772138840 3556587191 112612832
1670826506 3120848971 27068931
4239529189 2600465995 55438107
temperature-to-humidity map:
2776202835 2235980179 978805
79456303 770215397 125672111
350944915 144658185 147068664
239335677 1555124158 884128
3153890512 3800437685 109571794
240219805 0 95968287
2078890110 4167578198 41164706
3637428670 2781740910 54319513
3511657938 2772352153 5987732
2771529423 3277605929 4673412
498013579 291726849 399032245
3691748183 3910009479 257568719
3548876568 3282279341 16553363
3135162288 2217251955 18728224
2161038070 2836060423 259888366
3565429931 4208742904 71998739
3952717927 3799896230 541455
2777181640 2500118625 179031937
3953259382 3395098982 156601616
4109860998 3298832704 70018024
2580082919 1819987413 191446504
1398347285 895887508 382372949
205128414 1556008286 34207263
2956213577 2011433917 178948711
3517645670 2679150562 4361571
336188092 129901362 14756823
1364414210 95968287 33933075
1173909525 1590215549 190504685
3263462306 3551700598 248195632
2420926436 2495861681 4256944
1819987413 2236958984 258902697
2120054816 3095948789 26757601
4179879022 2683512133 88840020
3522007241 2190382628 26869327
2146812417 4280741643 14225653
0 690759094 79456303
897045824 1278260457 276863701
4268719042 3368850728 26248254
2425183380 3122706390 154899539
3949316902 2778339885 3401025
humidity-to-location map:
1568324830 3576584364 32633066
300199016 474209742 262529847
3559913667 3345416335 231168029
1042084677 290085772 184123970
0 27095618 110260307
562728863 0 7921916
1860347496 3086490828 96440514
1956788010 3609217430 226060373
262990154 1080572947 37208862
2182848383 3062438579 9763931
589824481 1443076400 49986334
639810815 1329220256 113856144
1600957896 1568324830 245101282
2310901200 1813426112 1249012467
3791081696 3835277803 341400607
1846059178 3072202510 14288318
4132482303 3182931342 162484993
2192612314 4176678410 118288886
965105406 736739589 76979271
753666959 1117781809 211438447
110260307 137355925 152729847
1226208647 813718860 266854087
570650779 7921916 19173702

270
src/day05.rs Normal file
View File

@ -0,0 +1,270 @@
use std::{collections::HashMap, ops::Range};
use regex::Regex;
pub fn run() {
let input = include_str!("../input/day5.txt");
// let 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"#;
let almanac = Almanac::parse_seed_list(input);
let part1 = almanac.convert_seeds_to_locations();
dbg!(part1.iter().min().unwrap());
let almanac2 = Almanac::parse_seed_range(input);
let part2 = almanac2.convert_seeds_to_locations();
dbg!(part2.iter().min().unwrap());
}
#[derive(Debug, Clone)]
struct Almanac<S: IntoIterator<Item = i64> + Clone> {
seeds: S,
maps: HashMap<(String, String), Map>,
}
fn parse_maps<'a>(parts: impl Iterator<Item = &'a str>) -> HashMap<(String, String), Map> {
let mut maps = HashMap::new();
let map_name_re = Regex::new(r#"(\w+)-to-(\w+) map:"#).unwrap();
for map_s in parts {
let (name, rest) = map_s.split_once("\n").unwrap();
let map_captures = map_name_re.captures(name).unwrap();
let map = Map::parse(rest);
maps.insert(
(map_captures[1].to_owned(), map_captures[2].to_owned()),
map,
);
}
maps
}
impl Almanac<Vec<i64>> {
fn parse_seed_list(s: &str) -> Self {
let mut parts = s.split("\n\n");
let seeds_s = parts.next().unwrap();
assert!(seeds_s.starts_with("seeds: "));
let seeds_s = seeds_s.split_at("seeds: ".len()).1;
let seeds = seeds_s
.split(" ")
.map(|s| s.parse::<i64>().unwrap())
.collect::<Vec<_>>();
Self {
seeds,
maps: parse_maps(parts),
}
}
}
#[derive(Debug, Clone, PartialEq)]
struct Seeds {
ranges: Vec<Range<i64>>,
cur: Option<Range<i64>>,
}
impl Iterator for Seeds {
type Item = i64;
fn next(&mut self) -> Option<Self::Item> {
if self.cur.is_none() || self.cur.as_ref().unwrap().is_empty() {
if self.ranges.is_empty() {
self.cur = None;
return None;
} else {
self.cur = Some(self.ranges.remove(0));
return self.next();
}
} else {
let cur = self.cur.as_ref().unwrap();
let ret = cur.start;
self.cur = Some((cur.start + 1)..cur.end);
return Some(ret);
}
}
}
impl Almanac<Seeds> {
fn parse_seed_range(s: &str) -> Self {
let mut parts = s.split("\n\n");
let seeds_s = parts.next().unwrap();
assert!(seeds_s.starts_with("seeds: "));
let seeds_s = seeds_s.split_at("seeds: ".len()).1;
let numbers = seeds_s
.split(" ")
.map(|s| s.parse::<i64>().unwrap())
.collect::<Vec<_>>();
assert!(numbers.len() % 2 == 0);
let ranges = numbers
.chunks(2)
.map(|chunk| chunk[0]..(chunk[0] + chunk[1]))
.collect::<Vec<_>>();
Self {
seeds: Seeds { ranges, cur: None },
maps: parse_maps(parts),
}
}
}
impl<S: IntoIterator<Item = i64> + Clone> Almanac<S> {
fn convert(&self, xs: &mut Vec<i64>, from: &str, to: &str) {
let map = self
.maps
.get(&(from.to_owned(), to.to_owned()))
.expect(&format!("conversion from {} to {}", from, to));
for i in 0..xs.len() {
xs[i] = map.convert(xs[i]);
}
}
fn convert_seeds_to_locations(&self) -> Vec<i64> {
let path = &[
"soil",
"fertilizer",
"water",
"light",
"temperature",
"humidity",
"location",
];
let mut cur_type = "seed";
let mut cur = self.seeds.clone().into_iter().collect::<Vec<_>>();
for next in path {
self.convert(&mut cur, cur_type, next);
cur_type = next;
}
cur
}
}
#[derive(Debug, Clone, PartialEq)]
struct Map {
// range of source and offset to dest
ranges: Vec<(Range<i64>, i64)>,
}
impl Map {
fn parse(s: &str) -> Self {
let ranges = s
.lines()
.map(|l| {
let mut parts = l.trim().split(" ");
let dest_start: i64 = parts.next().unwrap().parse().unwrap();
let source_start: i64 = parts.next().unwrap().parse().unwrap();
let len: i64 = parts.next().unwrap().parse().unwrap();
assert_eq!(parts.next(), None);
(
source_start..(source_start + len),
dest_start - source_start,
)
})
.collect::<Vec<_>>();
Self { ranges }
}
fn convert(&self, source: i64) -> i64 {
for (range, offset) in self.ranges.iter() {
if range.contains(&source) {
return source + offset;
}
}
source
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_map() {
assert_eq!(
Map::parse("50 98 2\n52 50 48"),
Map {
ranges: vec![(98..100, -48), (50..98, 2),],
}
)
}
#[test]
fn test_map_convert() {
let m = Map {
ranges: vec![(98..100, -48), (50..98, 2)],
};
assert_eq!(m.convert(98), 50);
assert_eq!(m.convert(53), 55);
assert_eq!(m.convert(10), 10);
}
#[test]
fn test_parse_almanac() {
let a = Almanac::parse_seed_list(
r#"seeds: 79 14 55 13
seed-to-soil map:
50 98 2
52 50 48"#,
);
assert_eq!(a.seeds, vec![79, 14, 55, 13]);
let k = ("seed".to_owned(), "soil".to_owned());
assert_eq!(a.maps.keys().collect::<Vec<_>>(), vec![&k]);
assert_eq!(
a.maps[&k],
Map {
ranges: vec![(98..100, -48), (50..98, 2)],
}
);
}
#[test]
fn test_parse_almanac_seed_ranges() {
let a = Almanac::parse_seed_range("seeds: 1 2 3 4");
assert_eq!(
a.seeds,
Seeds {
ranges: vec![1..3, 3..7],
cur: None,
}
);
}
#[test]
fn test_seeds_iter() {
assert_eq!(
Seeds {
ranges: vec![1..3, 3..7],
cur: None,
}
.collect::<Vec<_>>(),
vec![1, 2, 3, 4, 5, 6]
);
}
}

View File

@ -5,7 +5,8 @@ mod day01;
mod day02;
mod day03;
mod day04;
mod day05;
fn main() {
day04::run();
day05::run();
}