diff --git a/aoc2021/input/day13.txt b/aoc2021/input/day13.txt new file mode 100644 index 0000000..aef0a4a --- /dev/null +++ b/aoc2021/input/day13.txt @@ -0,0 +1,916 @@ +1213,736 +1158,890 +626,303 +98,10 +878,268 +1208,143 +112,400 +865,894 +1218,179 +1089,418 +535,886 +726,515 +1263,786 +589,270 +80,518 +288,322 +1101,483 +989,308 +1002,707 +467,18 +1036,364 +552,591 +445,280 +912,40 +1268,761 +984,47 +883,574 +815,784 +719,236 +865,166 +836,581 +656,735 +228,264 +23,466 +1099,515 +1284,665 +432,268 +195,493 +1001,308 +430,222 +1294,537 +427,646 +574,381 +1116,829 +1143,808 +950,578 +293,579 +28,751 +169,341 +326,159 +257,721 +773,670 +1231,556 +306,436 +454,520 +1267,522 +85,309 +1273,358 +1019,208 +870,504 +647,175 +408,544 +1310,386 +912,854 +512,10 +674,770 +273,742 +626,584 +112,10 +736,420 +1198,884 +214,620 +139,751 +448,782 +771,646 +709,796 +755,460 +179,838 +360,578 +274,364 +656,401 +810,61 +194,310 +584,515 +773,238 +184,241 +932,661 +105,333 +1096,838 +959,838 +252,341 +1237,338 +112,884 +746,812 +735,556 +45,75 +815,838 +654,719 +1225,309 +1226,892 +453,465 +783,520 +987,446 +348,458 +976,175 +487,392 +1307,558 +1279,882 +145,509 +909,444 +1310,389 +626,527 +356,527 +363,774 +142,130 +246,581 +1064,581 +925,837 +166,842 +529,877 +124,341 +709,546 +651,490 +372,16 +537,614 +1004,213 +1198,661 +1240,40 +701,504 +1103,120 +638,462 +857,351 +269,794 +1099,122 +624,360 +1284,217 +902,26 +102,672 +691,208 +850,287 +1083,698 +636,770 +475,539 +1280,735 +495,712 +1273,655 +217,854 +1109,687 +345,565 +939,43 +902,203 +803,241 +35,838 +169,624 +206,236 +413,718 +617,599 +729,786 +372,430 +467,242 +771,324 +924,268 +574,854 +167,502 +141,738 +166,52 +659,336 +1240,123 +672,462 +902,581 +883,320 +37,655 +209,0 +897,875 +823,630 +1074,264 +385,794 +1131,838 +1151,504 +1294,357 +1260,396 +1228,768 +209,57 +1225,360 +1111,710 +333,586 +996,371 +954,140 +790,367 +843,348 +1058,877 +252,509 +181,385 +1218,267 +1123,428 +191,98 +1039,372 +214,504 +274,260 +359,751 +1109,753 +659,359 +10,674 +835,56 +730,490 +378,1 +0,539 +35,182 +276,661 +469,626 +1061,533 +783,432 +656,847 +281,707 +187,428 +1275,568 +716,143 +938,878 +663,117 +738,254 +954,86 +467,796 +966,761 +405,311 +209,651 +38,98 +1233,824 +430,837 +1290,841 +865,280 +1123,18 +985,170 +182,859 +1164,245 +656,607 +979,784 +634,10 +460,829 +768,172 +1126,317 +1000,805 +1198,830 +629,536 +208,542 +1193,747 +328,60 +1123,751 +1004,10 +1056,571 +254,571 +1086,57 +192,815 +1287,204 +1012,754 +838,411 +1225,361 +380,310 +616,117 +621,243 +1165,509 +706,781 +564,530 +905,311 +162,763 +354,889 +975,103 +10,226 +326,847 +184,317 +1261,143 +1310,65 +310,462 +1208,672 +402,17 +85,361 +129,847 +1020,486 +16,462 +618,856 +440,102 +686,381 +925,794 +453,65 +1287,639 +180,656 +507,91 +460,65 +893,271 +344,581 +609,208 +246,432 +781,246 +185,268 +311,696 +736,488 +346,707 +875,708 +38,565 +420,267 +433,18 +1101,651 +159,222 +420,627 +1245,446 +905,361 +954,527 +909,450 +495,392 +755,434 +179,429 +1230,868 +1129,621 +932,681 +211,122 +344,313 +52,530 +602,288 +947,326 +433,113 +634,557 +529,17 +647,117 +1253,324 +331,502 +580,205 +1111,184 +359,143 +52,36 +32,409 +1280,584 +112,661 +1143,392 +1228,126 +32,485 +28,310 +768,436 +1000,761 +281,502 +753,214 +443,646 +1213,680 +97,515 +939,820 +112,172 +1068,674 +371,43 +1089,642 +1064,82 +1131,429 +947,840 +684,751 +420,264 +1082,660 +965,553 +52,82 +795,751 +351,98 +1143,726 +815,224 +80,656 +900,605 +897,360 +706,333 +880,57 +676,841 +119,877 +938,16 +393,176 +1001,586 +507,388 +31,194 +405,182 +35,470 +185,716 +1310,57 +733,70 +391,658 +815,182 +31,65 +868,866 +356,140 +628,229 +841,492 +691,712 +1195,696 +634,287 +523,65 +345,138 +310,49 +663,623 +474,581 +520,639 +224,57 +1287,428 +328,579 +323,392 +351,504 +1287,255 +815,360 +194,136 +207,269 +542,436 +432,178 +110,634 +878,716 +201,829 +897,718 +52,726 +328,159 +1258,502 +1307,87 +1129,733 +979,315 +323,427 +1002,187 +351,639 +938,430 +527,520 +870,176 +1069,639 +1307,467 +36,856 +23,31 +413,534 +402,341 +687,65 +619,120 +634,884 +1258,858 +18,203 +542,885 +604,781 +1282,758 +5,553 +1294,385 +378,437 +1096,56 +835,838 +23,876 +1111,278 +1011,33 +308,707 +117,798 +331,763 +470,241 +830,732 +1265,691 +982,287 +950,709 +755,196 +691,694 +776,12 +1290,765 +619,40 +738,640 +1121,88 +938,464 +951,143 +537,208 +736,518 +405,126 +453,543 +365,694 +157,329 +385,57 +37,358 +482,341 +442,28 +870,457 +984,336 +693,239 +917,176 +45,158 +892,264 +1258,812 +1113,534 +303,7 +1004,661 +569,869 +281,158 +378,681 +569,534 +16,509 +435,708 +373,840 +1192,542 +721,606 +1041,794 +1151,392 +343,646 +684,143 +1064,740 +552,751 +1151,182 +1143,616 +698,313 +1064,812 +446,800 +564,812 +1191,717 +452,105 +85,360 +947,504 +380,82 +937,483 +319,551 +922,815 +1213,515 +984,607 +73,556 +309,852 +50,661 +1181,847 +1300,535 +448,560 +291,854 +447,8 +0,91 +1191,625 +932,233 +371,689 +361,131 +865,798 +1169,738 +446,94 +966,581 +110,309 +74,404 +1000,49 +1,842 +798,354 +20,884 +1233,406 +1230,243 +492,267 +867,248 +346,187 +1245,472 +736,406 +656,287 +962,590 +572,640 +544,260 +927,522 +841,786 +1029,392 +169,278 +378,445 +420,630 +488,52 +626,751 +927,372 +691,854 +803,355 +3,87 +1230,26 +154,341 +612,313 +823,560 +802,245 +216,137 +987,427 +207,120 +775,877 +897,176 +1266,654 +541,191 +159,110 +1275,182 +678,268 +1153,565 +1274,856 +991,656 +15,696 +172,341 +691,504 +310,705 +1275,470 +574,243 +448,637 +1111,262 +951,751 +619,390 +539,324 +626,143 +733,809 +656,281 +0,837 +529,429 +862,180 +1279,194 +947,568 +227,574 +378,400 +418,364 +556,182 +969,481 +500,61 +947,774 +761,333 +1012,136 +1258,530 +574,518 +666,311 +326,558 +512,130 +870,718 +689,682 +1104,658 +1101,614 +187,876 +1237,556 +313,861 +222,716 +676,884 +201,375 +336,28 +1058,509 +469,492 +1081,232 +361,763 +42,761 +1183,462 +1148,110 +1273,239 +905,712 +863,438 +905,518 +736,474 +1034,445 +1088,716 +1022,677 +117,224 +1265,686 +1171,751 +862,112 +0,165 +1123,546 +1310,508 +49,143 +880,837 +976,719 +684,361 +1233,70 +28,478 +82,126 +1053,721 +131,625 +900,289 +1193,278 +373,65 +1272,796 +490,617 +1016,633 +413,176 +82,96 +1116,584 +469,786 +867,646 +843,652 +1118,815 +775,886 +624,829 +166,500 +555,574 +385,837 +455,278 +487,840 +65,446 +1139,819 +1211,460 +1169,114 +1101,894 +624,381 +227,250 +119,269 +1029,56 +616,98 +905,126 +937,449 +1096,504 +1141,624 +1099,772 +201,687 +1116,65 +217,40 +708,136 +787,65 +1273,648 +1155,338 +659,87 +201,207 +402,161 +1091,708 +440,722 +447,269 +1022,572 +939,205 +497,329 +1058,553 +542,661 +863,886 +155,338 +622,857 +92,715 +612,133 +962,458 +634,159 +28,30 +288,677 +1028,878 +1183,520 +169,176 +23,428 +1292,203 +754,182 +555,320 +35,208 +701,75 +1022,322 +684,533 +320,623 +857,95 +18,770 +214,50 +7,777 +398,406 +261,176 +783,462 +709,98 +1123,815 +440,457 +708,168 +447,625 +359,418 +1278,485 +1012,143 +159,504 +38,796 +1230,332 +418,530 +877,255 +654,505 +28,136 +912,406 +1193,320 +485,46 +351,838 +1265,75 +758,143 +1300,226 +1282,527 +612,761 +575,556 +979,763 +77,70 +654,607 +688,261 +766,585 +145,385 +363,504 +676,287 +788,607 +857,465 +1128,35 +574,513 +1200,309 +10,668 +169,553 +654,57 +1064,868 +191,796 +45,686 +982,159 +795,79 +413,361 +761,863 +473,273 +0,401 +1017,579 +840,808 +99,434 +79,556 +162,784 +459,418 +798,10 +195,418 +651,404 +520,527 +959,887 +965,565 +288,217 +730,404 +1282,478 +602,364 +803,315 +962,304 +820,617 +741,534 +549,333 +862,714 +363,326 +102,222 +348,436 +1156,553 +1064,463 +97,214 +609,691 +214,722 +827,208 +372,688 +453,519 +385,401 +622,633 +70,40 +455,616 +949,763 +693,599 +194,758 +512,541 +1169,786 +617,536 +1086,837 +112,494 +910,161 +984,495 +959,56 +977,586 +454,262 +1141,341 +609,203 +748,19 +1143,560 +656,508 +541,703 +1181,495 +1183,246 +542,102 +736,189 +433,866 +661,756 +659,490 +331,446 +236,630 +610,688 +3,467 +446,268 +694,117 +308,35 +537,350 +1101,243 +951,418 +127,432 +979,110 +802,705 +741,86 +787,829 +1198,233 +808,890 +1279,12 +50,396 +1183,14 +23,255 +636,124 +448,714 +1236,205 +1193,798 +1103,625 +945,694 +1139,108 +522,287 +624,513 +997,33 +1190,658 +35,56 +1275,406 +773,208 +1125,716 +69,621 +1093,518 +1310,837 +1125,268 +865,448 +1102,94 +306,10 +373,483 +442,866 +858,105 +602,168 +624,159 +334,719 +480,162 +870,172 +602,736 +0,508 +1064,154 +1056,712 +582,161 +1261,591 +661,308 +35,200 +92,19 +214,390 + +fold along x=655 +fold along y=447 +fold along x=327 +fold along y=223 +fold along x=163 +fold along y=111 +fold along x=81 +fold along y=55 +fold along x=40 +fold along y=27 +fold along y=13 +fold along y=6 diff --git a/aoc2021/input/day13_provided.txt b/aoc2021/input/day13_provided.txt new file mode 100644 index 0000000..282114c --- /dev/null +++ b/aoc2021/input/day13_provided.txt @@ -0,0 +1,21 @@ +6,10 +0,14 +9,10 +0,3 +10,4 +4,11 +6,0 +6,12 +4,1 +0,13 +10,12 +3,4 +3,0 +8,4 +1,10 +2,14 +8,10 +9,0 + +fold along y=7 +fold along x=5 diff --git a/aoc2021/src/day13.rs b/aoc2021/src/day13.rs new file mode 100644 index 0000000..37f39f4 --- /dev/null +++ b/aoc2021/src/day13.rs @@ -0,0 +1,210 @@ +use std::collections::HashSet; +use std::fmt::Write; + +use anyhow::{anyhow, Context, Result}; + +const INPUT: &str = include_str!("../input/day13.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let (sheet, fold_instructions) = input.split_once("\n\n").context("couldn't split input")?; + let mut sheet: PaperSheet = sheet.parse()?; + let fold_instructions: Vec = fold_instructions + .lines() + .map(|l| l.trim().parse()) + .collect::>()?; + + sheet.apply( + *fold_instructions + .first() + .context("had 0 fold instructions")?, + ); + + Ok(sheet.num_points()) +} + +fn part2(input: &str) -> Result { + let (sheet, fold_instructions) = input.split_once("\n\n").context("couldn't split input")?; + let mut sheet: PaperSheet = sheet.parse()?; + let fold_instructions: Vec = fold_instructions + .lines() + .map(|l| l.trim().parse()) + .collect::>()?; + + for instr in fold_instructions { + sheet.apply(instr); + } + + Ok(format!("{}", sheet)) +} + +struct PaperSheet { + points: HashSet<(usize, usize)>, +} + +impl PaperSheet { + fn apply(&mut self, instr: FoldInstruction) { + let mut to_insert = Vec::new(); + let mut to_remove = Vec::new(); + + for point in &self.points { + match instr { + FoldInstruction::AlongX(x) => { + if point.0 <= x { + continue; + } + + let new_point = (x - (point.0 - x), point.1); + to_insert.push(new_point); + to_remove.push(*point); + } + FoldInstruction::AlongY(y) => { + if point.1 <= y { + continue; + } + + let new_point = (point.0, y - (point.1 - y)); + to_insert.push(new_point); + to_remove.push(*point); + } + } + } + + to_remove.iter().for_each(|point| { + self.points.remove(point); + }); + + to_insert.into_iter().for_each(|point| { + self.points.insert(point); + }); + } + + fn num_points(&self) -> usize { + self.points.len() + } +} + +impl std::fmt::Display for PaperSheet { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // make sure first row appears on its own line + writeln!(f)?; + + if self.points.is_empty() { + return writeln!(f, "`empty paper sheet`"); + } + + let (width, _) = self.points.iter().max_by_key(|point| point.0).unwrap(); + let (_, height) = self.points.iter().max_by_key(|point| point.1).unwrap(); + + for y in 0..=*height { + for x in 0..=*width { + let chr = if self.points.contains(&(x, y)) { + '#' + } else { + '.' + }; + f.write_char(chr)?; + } + writeln!(f)?; + } + + Ok(()) + } +} + +impl std::str::FromStr for PaperSheet { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut points = HashSet::new(); + + for l in s.lines() { + let (x, y) = l + .trim() + .split_once(',') + .context("couldn't parse paper sheet point coordinate")?; + let (x, y) = (x.parse()?, y.parse()?); + + points.insert((x, y)); + } + + Ok(PaperSheet { points }) + } +} + +#[derive(Clone, Copy)] +enum FoldInstruction { + AlongX(usize), + AlongY(usize), +} + +impl std::str::FromStr for FoldInstruction { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let (axis, coord) = s + .split_once('=') + .context("couldn't parse folding instruction")?; + let coord = coord.parse()?; + + match axis { + "fold along x" => Ok(FoldInstruction::AlongX(coord)), + "fold along y" => Ok(FoldInstruction::AlongY(coord)), + _ => Err(anyhow!("couldn't parse folding instruction")), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day13_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 17); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 753); + } + + #[test] + fn part2_provided() { + assert_eq!( + part2(PROVIDED).unwrap(), + " +##### +#...# +#...# +#...# +##### +" + ); + } + + #[test] + fn part2_real() { + assert_eq!( + part2(INPUT).unwrap(), + " +#..#.####.#....####.#..#...##.###..#..# +#..#....#.#....#....#..#....#.#..#.#.#. +####...#..#....###..####....#.#..#.##.. +#..#..#...#....#....#..#....#.###..#.#. +#..#.#....#....#....#..#.#..#.#.#..#.#. +#..#.####.####.####.#..#..##..#..#.#..# +" + ); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 6cbe7cd..5d8eeba 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -11,3 +11,4 @@ pub mod day08; pub mod day09; pub mod day10; pub mod day11; +pub mod day13; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index e5145c4..c21a96f 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -13,6 +13,7 @@ use aoc2021::day08; use aoc2021::day09; use aoc2021::day10; use aoc2021::day11; +use aoc2021::day13; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -27,6 +28,7 @@ fn main() -> Result<()> { day09::run, day10::run, day11::run, + day13::run, ]; aoc::run(days)