diff --git a/2021/day05_hydrothermal_venture/Cargo.toml b/2021/day05_hydrothermal_venture/Cargo.toml new file mode 100644 index 0000000..69f86e1 --- /dev/null +++ b/2021/day05_hydrothermal_venture/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day05_hydrothermal_venture" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2021/day05_hydrothermal_venture/challenge.txt b/2021/day05_hydrothermal_venture/challenge.txt new file mode 100644 index 0000000..98f6b06 --- /dev/null +++ b/2021/day05_hydrothermal_venture/challenge.txt @@ -0,0 +1,86 @@ +You come across a field of [hydrothermal vents](https://en.wikipedia.org/wiki/Hydrothermal_vent) on the ocean floor! These vents constantly produce large, opaque clouds, so it would be best to avoid them if possible. + +They tend to form in *lines*; the submarine helpfully produces a list of nearby lines of vents (your puzzle input) for you to review. For example: + +``` +0,9 -> 5,9 +8,0 -> 0,8 +9,4 -> 3,4 +2,2 -> 2,1 +7,0 -> 7,4 +6,4 -> 2,0 +0,9 -> 2,9 +3,4 -> 1,4 +0,0 -> 8,8 +5,5 -> 8,2 + +``` + +Each line of vents is given as a line segment in the format `x1,y1 -> x2,y2` where `x1`,`y1` are the coordinates of one end the line segment and `x2`,`y2` are the coordinates of the other end. These line segments include the points at both ends. In other words: + +* An entry like `1,1 -> 1,3` covers points `1,1`, `1,2`, and `1,3`. +* An entry like `9,7 -> 7,7` covers points `9,7`, `8,7`, and `7,7`. + +For now, *only consider horizontal and vertical lines*: lines where either `x1 = x2` or `y1 = y2`. + +So, the horizontal and vertical lines from the above list would produce the following diagram: + +``` +.......1.. +..1....1.. +..1....1.. +.......1.. +.112111211 +.......... +.......... +.......... +.......... +222111.... + +``` + +In this diagram, the top left corner is `0,0` and the bottom right corner is `9,9`. Each position is shown as *the number of lines which cover that point* or `.` if no line covers that point. The top-left pair of `1`s, for example, comes from `2,2 -> 2,1`; the very bottom row is formed by the overlapping lines `0,9 -> 5,9` and `0,9 -> 2,9`. + +To avoid the most dangerous areas, you need to determine *the number of points where at least two lines overlap*. In the above example, this is anywhere in the diagram with a `2` or larger - a total of `*5*` points. + +Consider only horizontal and vertical lines. *At how many points do at least two lines overlap?* + +Your puzzle answer was `6007`. + +\--- Part Two --- +---------- + +Unfortunately, considering only horizontal and vertical lines doesn't give you the full picture; you need to also consider *diagonal lines*. + +Because of the limits of the hydrothermal vent mapping system, the lines in your list will only ever be horizontal, vertical, or a diagonal line at exactly 45 degrees. In other words: + +* An entry like `1,1 -> 3,3` covers points `1,1`, `2,2`, and `3,3`. +* An entry like `9,7 -> 7,9` covers points `9,7`, `8,8`, and `7,9`. + +Considering all lines from the above example would now produce the following diagram: + +``` +1.1....11. +.111...2.. +..2.1.111. +...1.2.2.. +.112313211 +...1.2.... +..1...1... +.1.....1.. +1.......1. +222111.... + +``` + +You still need to determine *the number of points where at least two lines overlap*. In the above example, this is still anywhere in the diagram with a `2` or larger - now a total of `*12*` points. + +Consider all of the lines. *At how many points do at least two lines overlap?* + +Your puzzle answer was `19349`. + +Both parts of this puzzle are complete! They provide two gold stars: \*\* + +At this point, you should [return to your Advent calendar](/2021) and try another puzzle. + +If you still want to see it, you can [get your puzzle input](5/input). \ No newline at end of file diff --git a/2021/day05_hydrothermal_venture/src/lib.rs b/2021/day05_hydrothermal_venture/src/lib.rs new file mode 100644 index 0000000..9a907c8 --- /dev/null +++ b/2021/day05_hydrothermal_venture/src/lib.rs @@ -0,0 +1,132 @@ +use core::fmt::Display; +use std::{num::ParseIntError, collections::{HashMap, HashSet}}; + +#[derive(Debug, PartialEq, Eq)] +pub enum ParseError { + ParseIntError(std::num::ParseIntError), + LineMalformed(String), +} + +impl From for ParseError { + fn from(value: ParseIntError) -> Self { + Self::ParseIntError(value) + } +} + +impl Display for ParseError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::ParseIntError(e) => write!(f, "Unable to parse into integer: {e}"), + Self::LineMalformed(v) => write!(f, "Line is malformed: {v}"), + } + } +} + +struct Line { + start: (usize, usize), + end: (usize, usize), +} + +impl TryFrom<&str> for Line { + type Error = ParseError; + + fn try_from(value: &str) -> Result { + let ends: Vec<_> = value.split_whitespace().collect(); + if ends.len() != 3 { + return Err(Self::Error::LineMalformed(value.to_string())); + } + + let start: Vec<_> = ends[0].split(',').collect(); + let end: Vec<_> = ends[2].split(',').collect(); + + if start.len() != 2 || end.len() != 2 { + return Err(Self::Error::LineMalformed(value.to_string())); + } + + Ok(Self { + start: (start[0].parse()?, start[1].parse()?), + end: (end[0].parse()?, end[1].parse()?), + }) + } +} + +impl Line { + fn get_horizontal_vertical_coordinates(&self) -> Vec<(usize, usize)> { + if self.start.0 == self.end.0 { + let x = self.start.0; + let min = self.start.1.min(self.end.1); + let max = self.start.1.max(self.end.1); + + (min..=max).map(|y| (x, y)).collect() + } else if self.start.1 == self.end.1 { + let y = self.start.1; + let min = self.start.0.min(self.end.0); + let max = self.start.0.max(self.end.0); + + (min..=max).map(|x| (x, y)).collect() + } else { + Vec::new() + } + } + + fn get_diagonal_coordingates(&self) -> Vec<(usize, usize)> { + if self.start.0 < self.end.0 && self.start.1 < self.end.1 { + (0..=self.end.0-self.start.0).map(|f| (self.start.0+f, self.start.1+f)).collect() + } else if self.start.0 < self.end.0 && self.start.1 > self.end.1 { + (0..=self.end.0-self.start.0).map(|f| (self.start.0+f, self.start.1-f)).collect() + } else if self.start.0 > self.end.0 && self.start.1 > self.end.1 { + (0..=self.start.0-self.end.0).map(|f| (self.start.0-f, self.start.1-f)).collect() + } else if self.start.0 > self.end.0 && self.start.1 < self.end.1 { + (0..=self.start.0-self.end.0).map(|f| (self.start.0-f, self.start.1+f)).collect() + } else { + Vec::new() + } + } +} + +pub fn run(input: &str) -> Result<(usize, usize), ParseError> { + let lines: Vec<_> = input.lines().map(Line::try_from).collect::, _>>()?; + let mut all_points = HashSet::new(); + let mut duplicates = HashSet::new(); + lines.iter().for_each(|line| { + line.get_horizontal_vertical_coordinates().iter().for_each(|coord| { + if all_points.contains(coord) { + duplicates.insert(*coord); + } + all_points.insert(*coord); + }); + }); + let first = duplicates.len(); + lines.iter().for_each(|line| { + line.get_diagonal_coordingates().iter().for_each(|coord| { + if all_points.contains(coord) { + duplicates.insert(*coord); + } + all_points.insert(*coord); + }); + }); + let second = duplicates.len(); + Ok((first, second)) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::fs::read_to_string; + + fn read_file(name: &str) -> String { + read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string() + } + + #[test] + fn test_sample() { + let sample_input = read_file("tests/sample_input"); + assert_eq!(run(&sample_input), Ok((5, 12))); + } + + #[test] + fn test_challenge() { + let challenge_input = read_file("tests/challenge_input"); + assert_eq!(run(&challenge_input), Ok((6007, 19349))); + } +} diff --git a/2021/day05_hydrothermal_venture/tests/challenge_input b/2021/day05_hydrothermal_venture/tests/challenge_input new file mode 100644 index 0000000..22e9364 --- /dev/null +++ b/2021/day05_hydrothermal_venture/tests/challenge_input @@ -0,0 +1,500 @@ +818,513 -> 818,849 +259,377 -> 259,599 +120,758 -> 977,758 +49,386 -> 170,386 +773,644 -> 773,745 +510,958 -> 797,671 +480,438 -> 14,904 +475,346 -> 648,173 +620,167 -> 477,310 +632,756 -> 275,756 +225,896 -> 432,896 +582,450 -> 93,450 +402,262 -> 254,410 +915,236 -> 709,236 +338,530 -> 338,375 +243,857 -> 370,984 +32,449 -> 32,26 +672,832 -> 203,363 +426,961 -> 426,402 +108,469 -> 550,27 +567,698 -> 495,770 +25,872 -> 861,36 +12,15 -> 960,963 +986,159 -> 986,765 +912,437 -> 714,437 +476,400 -> 476,873 +125,52 -> 951,878 +633,939 -> 633,641 +12,986 -> 987,11 +783,204 -> 467,520 +547,834 -> 413,700 +879,133 -> 879,890 +409,128 -> 365,128 +913,404 -> 913,598 +798,40 -> 841,40 +279,410 -> 279,758 +935,807 -> 959,783 +389,391 -> 389,38 +271,736 -> 271,865 +70,10 -> 814,10 +694,266 -> 694,92 +860,128 -> 860,966 +755,871 -> 608,871 +519,54 -> 519,833 +817,733 -> 156,72 +553,558 -> 726,558 +152,21 -> 830,699 +529,721 -> 608,721 +744,719 -> 744,221 +962,966 -> 10,14 +863,813 -> 863,984 +138,167 -> 801,830 +926,901 -> 926,769 +170,630 -> 623,177 +281,207 -> 510,207 +41,52 -> 945,956 +100,204 -> 100,43 +177,588 -> 469,588 +946,37 -> 201,782 +669,89 -> 669,868 +945,32 -> 46,931 +673,274 -> 412,274 +424,979 -> 169,979 +774,220 -> 774,571 +684,272 -> 229,272 +621,458 -> 621,884 +222,964 -> 222,608 +953,146 -> 145,954 +442,736 -> 442,230 +471,341 -> 471,124 +632,954 -> 968,954 +492,562 -> 911,981 +485,320 -> 485,349 +888,758 -> 888,23 +271,555 -> 732,555 +932,415 -> 792,275 +399,478 -> 399,472 +543,774 -> 543,261 +422,872 -> 422,715 +524,471 -> 445,471 +573,513 -> 573,762 +721,39 -> 482,39 +379,482 -> 379,479 +70,770 -> 336,770 +797,724 -> 797,364 +498,646 -> 498,410 +756,19 -> 756,83 +901,918 -> 11,918 +572,23 -> 362,23 +814,563 -> 750,627 +279,736 -> 249,706 +509,257 -> 509,897 +127,374 -> 399,102 +421,139 -> 607,139 +79,520 -> 166,607 +491,779 -> 284,986 +395,606 -> 395,164 +958,244 -> 442,760 +493,509 -> 673,509 +76,321 -> 482,727 +903,926 -> 103,126 +729,689 -> 63,23 +956,13 -> 198,771 +973,452 -> 193,452 +282,362 -> 896,976 +68,985 -> 985,68 +148,109 -> 310,109 +852,920 -> 371,439 +334,41 -> 864,571 +258,592 -> 72,778 +259,990 -> 259,308 +480,363 -> 480,751 +943,153 -> 801,153 +755,172 -> 123,804 +355,501 -> 437,501 +666,769 -> 340,769 +982,10 -> 23,969 +886,410 -> 886,669 +454,410 -> 454,218 +426,688 -> 227,688 +969,959 -> 207,959 +586,27 -> 591,22 +852,133 -> 166,819 +587,199 -> 781,199 +78,85 -> 78,394 +468,162 -> 727,162 +261,473 -> 573,473 +924,300 -> 924,873 +651,817 -> 651,600 +717,909 -> 717,187 +898,656 -> 454,656 +805,873 -> 507,873 +529,825 -> 529,217 +578,503 -> 783,503 +929,663 -> 920,663 +332,938 -> 332,381 +710,783 -> 272,783 +505,863 -> 240,863 +146,548 -> 146,849 +71,822 -> 820,73 +875,883 -> 451,883 +983,17 -> 30,970 +646,350 -> 646,330 +618,430 -> 881,430 +398,977 -> 643,732 +839,441 -> 406,874 +948,358 -> 178,358 +26,660 -> 26,612 +418,467 -> 418,115 +899,936 -> 899,611 +770,430 -> 770,648 +653,136 -> 95,694 +645,153 -> 818,153 +622,604 -> 77,59 +470,597 -> 592,719 +753,921 -> 743,921 +507,821 -> 507,275 +696,969 -> 433,969 +48,284 -> 552,284 +391,866 -> 187,866 +571,897 -> 107,433 +24,466 -> 24,186 +949,587 -> 582,587 +541,32 -> 541,583 +12,984 -> 986,10 +124,988 -> 124,904 +209,548 -> 209,12 +828,652 -> 34,652 +455,460 -> 905,910 +632,638 -> 343,638 +371,275 -> 145,275 +66,941 -> 945,62 +672,286 -> 672,301 +447,45 -> 82,410 +665,683 -> 487,683 +410,582 -> 670,842 +917,705 -> 917,323 +122,372 -> 403,653 +970,47 -> 40,977 +15,707 -> 732,707 +666,854 -> 666,256 +640,230 -> 188,230 +71,297 -> 71,472 +51,431 -> 339,431 +957,363 -> 82,363 +844,171 -> 274,171 +184,81 -> 184,786 +437,456 -> 138,456 +326,478 -> 814,966 +956,76 -> 226,806 +399,572 -> 399,877 +923,813 -> 923,898 +445,221 -> 947,723 +85,590 -> 415,590 +644,127 -> 644,140 +372,732 -> 372,522 +413,186 -> 244,186 +291,163 -> 197,69 +889,41 -> 208,722 +835,925 -> 835,616 +790,340 -> 426,340 +26,872 -> 805,93 +617,701 -> 828,701 +344,654 -> 530,654 +940,989 -> 41,90 +642,87 -> 206,523 +306,54 -> 306,761 +672,778 -> 672,868 +29,959 -> 974,14 +458,166 -> 86,166 +565,394 -> 352,181 +516,805 -> 457,805 +464,450 -> 756,450 +177,181 -> 661,181 +962,394 -> 630,62 +94,613 -> 12,613 +932,159 -> 818,273 +640,642 -> 976,642 +184,346 -> 184,22 +370,672 -> 458,672 +235,334 -> 770,869 +207,17 -> 811,17 +351,25 -> 896,25 +589,178 -> 921,510 +672,733 -> 937,733 +159,718 -> 787,90 +598,317 -> 598,455 +591,164 -> 591,374 +276,321 -> 515,321 +245,431 -> 245,350 +268,976 -> 939,305 +319,297 -> 823,297 +246,132 -> 229,132 +338,707 -> 338,59 +723,402 -> 723,739 +539,846 -> 94,846 +879,458 -> 783,458 +400,847 -> 770,477 +111,957 -> 858,210 +640,340 -> 878,578 +613,446 -> 115,446 +119,480 -> 119,425 +447,34 -> 986,34 +730,357 -> 532,555 +85,283 -> 26,283 +834,327 -> 263,898 +739,580 -> 640,481 +841,938 -> 841,123 +987,979 -> 23,15 +827,563 -> 632,563 +313,419 -> 466,572 +323,326 -> 455,326 +976,683 -> 976,314 +896,568 -> 338,568 +733,464 -> 819,464 +613,608 -> 493,608 +178,137 -> 178,663 +262,595 -> 262,308 +535,268 -> 851,268 +653,111 -> 653,723 +947,47 -> 23,971 +351,800 -> 351,806 +143,49 -> 850,756 +872,643 -> 872,265 +946,727 -> 427,727 +354,284 -> 938,868 +652,874 -> 652,447 +920,27 -> 387,27 +816,265 -> 816,366 +238,632 -> 336,534 +593,399 -> 593,425 +696,108 -> 138,666 +828,110 -> 240,698 +421,590 -> 847,590 +409,449 -> 622,449 +986,291 -> 45,291 +580,34 -> 663,34 +921,988 -> 35,102 +619,88 -> 249,88 +48,773 -> 503,773 +277,560 -> 377,460 +139,803 -> 123,787 +339,688 -> 907,120 +775,117 -> 775,203 +237,287 -> 507,557 +27,832 -> 429,430 +70,592 -> 672,592 +701,295 -> 69,295 +723,672 -> 714,672 +974,359 -> 292,359 +439,462 -> 439,973 +681,922 -> 357,922 +402,521 -> 25,521 +297,525 -> 297,227 +763,797 -> 763,153 +737,634 -> 869,634 +379,875 -> 810,875 +427,117 -> 705,117 +785,376 -> 265,896 +922,818 -> 141,37 +61,371 -> 61,432 +557,303 -> 411,303 +573,100 -> 295,100 +767,657 -> 231,657 +11,938 -> 875,74 +782,393 -> 782,502 +899,913 -> 519,533 +887,11 -> 244,654 +730,271 -> 426,271 +555,538 -> 379,538 +871,866 -> 871,461 +934,178 -> 934,845 +741,327 -> 325,327 +332,394 -> 518,580 +673,372 -> 809,236 +951,972 -> 77,98 +985,585 -> 985,55 +604,341 -> 269,676 +408,70 -> 455,23 +718,239 -> 718,522 +15,16 -> 984,985 +743,836 -> 852,836 +407,59 -> 246,220 +388,538 -> 388,587 +978,249 -> 810,249 +506,945 -> 506,644 +657,101 -> 657,522 +879,261 -> 935,261 +751,625 -> 926,800 +676,183 -> 573,286 +272,491 -> 765,984 +867,207 -> 570,207 +117,784 -> 750,784 +883,528 -> 883,845 +430,765 -> 581,614 +748,839 -> 748,775 +265,16 -> 188,93 +894,584 -> 525,215 +278,414 -> 19,673 +588,446 -> 588,656 +469,676 -> 469,354 +383,848 -> 669,848 +212,341 -> 367,341 +988,582 -> 988,825 +296,187 -> 785,187 +255,400 -> 255,286 +756,886 -> 524,654 +966,32 -> 966,940 +711,243 -> 81,873 +207,34 -> 359,186 +555,850 -> 45,850 +41,962 -> 947,56 +15,888 -> 15,795 +773,709 -> 579,515 +228,517 -> 228,334 +495,290 -> 965,290 +462,309 -> 462,421 +945,274 -> 945,735 +547,361 -> 547,140 +37,930 -> 836,930 +987,445 -> 45,445 +25,766 -> 757,34 +643,946 -> 318,621 +507,402 -> 507,981 +22,903 -> 488,437 +887,487 -> 957,487 +57,434 -> 21,398 +688,907 -> 917,678 +146,498 -> 146,965 +375,939 -> 888,426 +966,151 -> 684,433 +160,373 -> 722,373 +410,571 -> 410,683 +588,667 -> 588,337 +832,348 -> 376,804 +567,430 -> 453,430 +368,442 -> 97,442 +11,191 -> 584,764 +647,965 -> 647,331 +576,856 -> 976,456 +205,287 -> 205,495 +677,872 -> 677,246 +21,16 -> 973,968 +949,738 -> 126,738 +921,595 -> 921,370 +539,821 -> 660,821 +143,188 -> 143,793 +639,930 -> 639,454 +522,360 -> 917,755 +128,281 -> 647,800 +456,365 -> 456,34 +434,530 -> 431,530 +549,792 -> 549,892 +414,229 -> 41,602 +289,468 -> 592,771 +555,624 -> 727,452 +187,780 -> 187,838 +807,282 -> 807,968 +52,249 -> 52,332 +797,525 -> 462,190 +295,562 -> 654,921 +862,627 -> 252,627 +22,116 -> 866,960 +155,652 -> 155,979 +598,748 -> 51,748 +130,601 -> 231,601 +468,183 -> 468,414 +208,193 -> 927,912 +25,755 -> 770,755 +667,755 -> 916,506 +395,103 -> 395,468 +763,62 -> 763,153 +371,816 -> 371,109 +508,138 -> 37,609 +464,983 -> 707,983 +282,295 -> 282,536 +646,680 -> 646,775 +95,117 -> 95,62 +606,963 -> 203,963 +403,195 -> 97,195 +743,293 -> 743,815 +243,748 -> 431,748 +953,54 -> 22,985 +693,810 -> 656,810 +163,221 -> 728,786 +187,648 -> 187,337 +98,559 -> 98,165 +903,49 -> 46,906 +600,779 -> 432,779 +500,606 -> 500,878 +812,797 -> 31,16 +204,786 -> 517,786 +952,757 -> 952,923 +66,809 -> 66,831 +479,72 -> 17,72 +96,430 -> 96,932 +346,667 -> 796,667 +731,102 -> 162,102 +755,846 -> 755,135 +90,18 -> 404,18 +828,802 -> 134,108 +278,946 -> 278,765 +289,163 -> 869,743 +134,58 -> 887,58 +354,735 -> 904,185 +897,74 -> 897,716 +508,904 -> 508,719 +285,358 -> 795,868 +51,155 -> 51,643 +579,388 -> 431,240 +79,330 -> 869,330 +955,863 -> 140,48 +800,473 -> 689,473 +711,128 -> 918,128 +787,166 -> 787,36 +257,684 -> 873,68 +984,986 -> 10,12 +76,580 -> 660,580 +265,868 -> 955,868 +569,491 -> 466,594 +535,654 -> 37,654 +889,751 -> 411,273 +681,491 -> 600,491 +459,721 -> 459,109 +824,130 -> 689,265 +406,780 -> 406,965 +18,31 -> 904,917 +179,91 -> 232,38 +280,552 -> 428,700 +967,980 -> 19,32 +47,289 -> 738,980 +160,592 -> 120,592 +710,412 -> 28,412 +40,430 -> 747,430 +435,821 -> 747,509 +36,741 -> 36,363 +787,30 -> 847,30 +725,968 -> 725,940 +739,356 -> 27,356 +65,193 -> 419,193 +318,513 -> 404,513 +150,230 -> 150,968 +847,410 -> 847,505 +950,188 -> 950,278 +816,312 -> 587,541 +980,145 -> 154,145 +79,781 -> 616,781 +433,284 -> 433,309 +624,264 -> 569,264 +604,859 -> 570,825 +936,691 -> 350,105 +259,631 -> 648,242 +445,27 -> 445,872 +438,689 -> 977,150 +718,603 -> 718,327 +967,310 -> 98,310 +439,381 -> 439,35 +645,240 -> 282,240 +475,54 -> 475,658 +972,610 -> 759,823 diff --git a/2021/day05_hydrothermal_venture/tests/sample_input b/2021/day05_hydrothermal_venture/tests/sample_input new file mode 100644 index 0000000..b258f68 --- /dev/null +++ b/2021/day05_hydrothermal_venture/tests/sample_input @@ -0,0 +1,10 @@ +0,9 -> 5,9 +8,0 -> 0,8 +9,4 -> 3,4 +2,2 -> 2,1 +7,0 -> 7,4 +6,4 -> 2,0 +0,9 -> 2,9 +3,4 -> 1,4 +0,0 -> 8,8 +5,5 -> 8,2