diff --git a/Cargo.lock b/Cargo.lock index 21b9111..b560dfb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -199,6 +199,13 @@ dependencies = [ "criterion", ] +[[package]] +name = "day_13" +version = "0.1.0" +dependencies = [ + "criterion", +] + [[package]] name = "day_2" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 846c428..10bc2dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,5 @@ members = [ "day_10", "day_11", "day_12", + "day_13", ] diff --git a/day_12/input.txt b/day_12/input.txt index bc8429c..b4457af 100644 --- a/day_12/input.txt +++ b/day_12/input.txt @@ -21,4 +21,4 @@ start-ng end-FL fe-bi FL-ks -pg-start +pg-start \ No newline at end of file diff --git a/day_12/src/lib.rs b/day_12/src/lib.rs index 8c3d808..ade86f0 100644 --- a/day_12/src/lib.rs +++ b/day_12/src/lib.rs @@ -5,7 +5,7 @@ pub mod day_12 { #[derive(Debug)] pub struct Cave<'a> { is_big: bool, - name: &'a str, + _name: &'a str, } #[derive(Debug)] @@ -27,7 +27,10 @@ pub mod day_12 { let is_big = name.chars().next().unwrap().is_uppercase(); let i = caves.caves.len() as u16; mapping.insert(name, i); - caves.caves.push(Cave { is_big, name }); + caves.caves.push(Cave { + is_big, + _name: name, + }); caves.edges.push(HashSet::new()); if caves.start == 0 && name == "start" { caves.start = i; diff --git a/day_13/Cargo.toml b/day_13/Cargo.toml new file mode 100644 index 0000000..b6ec4b9 --- /dev/null +++ b/day_13/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "day_13" +version = "0.1.0" +authors = ["Smaug123 "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +[dev-dependencies] +criterion = "0.3" + +[[bench]] +name = "bench" +harness = false diff --git a/day_13/benches/bench.rs b/day_13/benches/bench.rs new file mode 100644 index 0000000..eec4ed9 --- /dev/null +++ b/day_13/benches/bench.rs @@ -0,0 +1,19 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use day_13::day_13::{input, part_1, part_2}; + +fn criterion_benchmark(c: &mut Criterion) { + let input = input(); + c.bench_function("day 13 part 1", |b| { + b.iter(|| { + black_box(part_1(&input)); + }) + }); + c.bench_function("day 13 part 2", |b| { + b.iter(|| { + black_box(part_2(&input)); + }) + }); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/day_13/day13.m b/day_13/day13.m new file mode 100644 index 0000000..eedbbf5 --- /dev/null +++ b/day_13/day13.m @@ -0,0 +1,14 @@ +(* ::Package:: *) + +nums=FromDigits/@StringSplit[StringTrim@ReadString[StringJoin[NotebookDirectory[], "/input.txt"]],","]; + +Clear[f]; +f[n_,days_]:=f[n,days]=If[days>n,f[0,days-n],1] +f[0,days_]:=f[0,days]=f[6,days-1]+f[8,days-1] +f[k_,0]:=1 + + +f[#,80]&/@nums//Total + + +f[#,256]&/@nums//Total diff --git a/day_13/input.txt b/day_13/input.txt new file mode 100644 index 0000000..abe9f16 --- /dev/null +++ b/day_13/input.txt @@ -0,0 +1,828 @@ +802,891 +773,324 +1125,3 +910,718 +433,626 +1310,809 +840,799 +415,74 +346,306 +1203,817 +793,877 +18,194 +120,554 +1016,887 +437,238 +249,730 +212,66 +955,457 +873,656 +607,155 +311,820 +98,824 +769,639 +547,172 +1059,596 +320,273 +676,457 +698,491 +661,535 +718,803 +212,28 +366,642 +862,563 +298,295 +1011,493 +370,779 +1118,416 +1285,576 +760,703 +22,466 +87,570 +391,84 +1115,737 +331,155 +1126,773 +684,485 +334,733 +1288,816 +681,576 +268,191 +375,152 +142,266 +604,596 +836,451 +763,396 +758,140 +323,739 +851,381 +301,877 +1261,371 +410,116 +248,677 +502,687 +724,565 +858,43 +430,376 +63,117 +776,564 +612,331 +1197,191 +331,610 +1250,878 +460,158 +1267,511 +719,187 +644,838 +333,402 +470,799 +567,379 +249,58 +1250,68 +288,252 +1242,117 +1007,654 +1222,845 +1041,519 +80,788 +206,115 +594,530 +25,241 +643,875 +432,191 +537,232 +263,551 +758,717 +251,596 +62,131 +944,611 +334,161 +659,535 +949,40 +918,387 +679,584 +20,437 +1044,829 +89,252 +55,4 +851,79 +266,513 +1262,878 +388,206 +448,872 +945,103 +224,327 +480,522 +228,51 +179,663 +959,576 +241,406 +800,210 +1044,152 +118,677 +1248,131 +107,15 +656,361 +1272,731 +209,423 +1190,106 +1082,51 +221,716 +25,576 +1158,655 +534,330 +1004,880 +3,359 +1092,23 +82,408 +45,438 +442,866 +602,494 +1083,814 +661,135 +269,519 +321,178 +666,838 +952,861 +687,530 +140,479 +1158,522 +218,107 +349,446 +857,481 +584,584 +1186,627 +918,497 +102,177 +435,767 +887,313 +266,206 +1136,541 +1140,173 +704,430 +787,551 +514,31 +326,743 +634,569 +1056,606 +1178,264 +423,313 +316,166 +654,501 +1285,352 +385,453 +704,28 +864,329 +370,227 +1179,551 +20,549 +99,586 +1036,400 +617,453 +1124,740 +678,18 +97,705 +228,70 +738,330 +1086,376 +1069,854 +962,327 +922,740 +1158,186 +731,570 +1124,708 +798,677 +388,152 +606,430 +279,739 +179,638 +1096,74 +527,261 +1158,708 +435,654 +796,31 +910,372 +820,757 +1036,494 +435,319 +22,18 +797,672 +656,393 +224,791 +146,796 +386,199 +684,35 +1131,638 +546,107 +179,784 +989,716 +1053,579 +361,854 +741,358 +393,396 +455,149 +1183,334 +1059,74 +234,372 +377,859 +195,135 +1179,595 +1211,590 +258,441 +632,620 +663,315 +1253,599 +749,567 +875,767 +1010,28 +760,191 +480,372 +960,516 +1193,570 +780,122 +68,777 +591,707 +1082,163 +1235,52 +880,70 +102,269 +1303,579 +228,731 +644,15 +743,379 +1047,791 +1164,796 +107,77 +918,61 +98,180 +1287,766 +38,88 +80,554 +1242,453 +335,756 +160,77 +1183,633 +1119,353 +512,714 +112,372 +388,812 +87,122 +259,805 +388,490 +262,397 +5,135 +580,789 +430,518 +440,64 +922,737 +1212,70 +0,85 +1169,670 +393,498 +1235,298 +1009,94 +890,746 +500,477 +377,390 +191,681 +550,373 +1104,22 +309,523 +1261,483 +1119,289 +343,105 +1069,406 +120,106 +131,807 +922,152 +1235,148 +940,115 +567,603 +366,611 +180,219 +426,714 +249,282 +453,413 +1216,777 +403,74 +894,768 +214,382 +924,423 +1170,863 +20,457 +1032,268 +935,152 +862,872 +75,52 +266,812 +470,95 +716,154 +1130,684 +796,414 +1108,851 +436,107 +842,634 +975,579 +964,434 +344,852 +758,306 +800,684 +1263,742 +1299,19 +1130,675 +140,414 +144,684 +1048,173 +947,73 +584,310 +592,803 +582,288 +924,689 +25,149 +231,133 +1098,380 +840,456 +966,115 +1267,383 +107,655 +408,780 +726,310 +108,3 +288,88 +1170,480 +308,882 +503,231 +157,247 +321,716 +113,703 +848,416 +180,451 +152,298 +913,91 +681,696 +902,780 +363,821 +42,128 +875,799 +415,372 +243,873 +597,841 +897,58 +328,295 +1252,471 +120,564 +421,567 +987,807 +1101,232 +899,873 +219,799 +266,65 +301,800 +569,596 +967,820 +579,74 +475,256 +944,546 +738,784 +663,138 +70,63 +719,707 +1228,564 +884,731 +195,513 +335,138 +1223,772 +288,59 +426,395 +257,579 +517,254 +1246,609 +453,481 +840,266 +736,486 +808,207 +15,7 +303,128 +917,396 +98,714 +626,485 +792,866 +89,364 +70,136 +1310,85 +469,443 +448,564 +647,756 +719,329 +858,346 +989,135 +356,491 +1000,779 +977,402 +960,722 +241,506 +1179,343 +1190,788 +319,315 +345,371 +415,820 +124,478 +1082,731 +266,152 +234,746 +212,514 +830,74 +1047,777 +1186,346 +274,494 +363,261 +1000,563 +430,70 +288,194 +852,586 +870,74 +862,51 +1305,135 +1031,379 +300,812 +234,592 +42,42 +1015,82 +683,885 +1169,84 +667,19 +726,63 +975,138 +383,890 +683,9 +1151,423 +1168,714 +1096,294 +222,191 +146,98 +1159,187 +1203,351 +743,772 +1116,288 +234,522 +405,730 +900,116 +1235,842 +411,469 +540,380 +361,152 +1052,441 +490,154 +1033,259 +607,742 +363,745 +425,189 +375,805 +1135,691 +186,186 +716,269 +703,600 +1004,569 +206,51 +840,95 +627,885 +214,858 +1021,103 +823,516 +396,453 +924,205 +42,766 +1088,821 +398,63 +1130,219 +855,143 +1091,575 +967,522 +694,358 +435,879 +796,303 +562,750 +1230,554 +984,743 +569,88 +3,162 +10,431 +780,346 +20,325 +802,796 +433,268 +1290,549 +634,457 +728,288 +510,449 +99,308 +1098,66 +1067,873 +345,84 +1210,875 +1288,18 +435,369 +574,786 +388,154 +802,236 +566,49 +1218,144 +192,478 +1111,149 +202,346 +631,310 +309,371 +803,336 +743,603 +689,628 +1043,255 +1061,826 +514,210 +1048,61 +944,806 +1108,43 +1071,372 +638,180 +1307,535 +994,166 +378,858 +704,464 +949,742 +82,486 +1048,397 +206,563 +413,806 +1164,98 +344,115 +842,740 +1136,820 +514,414 +366,252 +919,329 +108,252 +594,364 +321,807 +278,250 +1062,385 +550,191 +224,376 +1098,828 +1009,800 +387,507 +172,417 +897,88 +195,759 +131,299 +940,667 +1163,876 +5,359 +181,791 +731,324 +388,404 +1086,327 +736,106 +310,563 +174,820 +140,863 +75,148 +957,800 +776,106 +62,763 +398,831 +1088,546 +1108,100 +155,26 +1026,563 +164,137 +830,522 +323,162 +127,334 +676,773 +758,754 +398,735 +572,116 +120,788 +117,794 +961,672 +769,255 +1208,269 +596,504 +954,528 +289,847 +426,742 +629,653 +574,106 +736,277 +263,777 +1178,630 +92,750 +299,493 +209,232 +705,147 +1014,301 +855,149 +405,58 +1044,65 +503,635 +537,324 +1007,310 +58,471 +597,151 +147,784 +1263,155 +440,830 +1203,879 +1002,882 +1203,77 +366,806 +951,82 +1290,457 +271,442 +716,826 +565,252 +932,204 +954,483 +924,695 +492,309 +1228,486 +1235,827 +1169,810 +1031,739 +912,63 +1101,662 +392,833 +1303,586 +793,17 +693,453 +316,728 +1088,191 +227,814 +964,306 +527,633 +373,701 +934,626 +249,164 +1282,409 +124,627 +579,148 +698,122 +764,107 +416,768 +634,549 +1173,472 +654,395 +1047,117 +1001,810 +1115,513 +1190,554 +1087,194 +661,807 +1022,835 +216,494 +385,285 +629,696 +263,117 +546,227 +152,74 +1009,17 +497,247 +131,595 +857,413 +1126,438 +344,779 +378,690 +1168,180 +708,494 +1034,718 +951,364 +835,558 +798,180 +1056,718 +567,324 +1211,308 +954,366 +922,404 +905,58 +592,579 +1116,630 +1218,808 +1272,806 +862,330 +723,581 +797,222 +1250,157 +716,812 +835,256 +895,74 +541,639 +351,128 +959,878 +940,43 +388,42 +1072,320 +862,42 +1131,663 +152,655 +1247,859 +1183,261 +377,483 +694,194 +426,163 +512,441 +147,22 +587,581 +612,212 +137,640 +522,264 +345,362 +1310,533 +932,690 +612,213 +18,700 +1213,705 +514,479 +925,823 +400,718 +1179,147 +142,180 +448,22 +266,240 +159,516 +154,417 +20,264 +966,779 +934,644 +1076,302 +1056,288 +64,509 +175,411 +1163,448 +378,158 +842,186 +626,859 +92,144 +979,854 +800,642 +701,456 +884,742 +348,567 +1235,746 +1022,59 +135,737 +346,460 +918,507 +1307,827 +1178,712 +651,359 +428,105 +1115,381 +49,479 +1299,875 +730,789 +596,639 +463,737 +828,417 +1007,128 +654,499 +1206,73 +326,151 +489,357 +452,346 +508,763 +354,364 +218,787 +966,563 +1131,231 +514,415 +862,778 +676,569 +359,140 +584,383 +915,805 +914,117 +830,372 +405,612 +1001,523 +965,810 +1017,152 +1285,149 +1031,600 +932,288 +708,400 +487,378 +1295,455 +880,824 +979,40 + +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 \ No newline at end of file diff --git a/day_13/src/lib.rs b/day_13/src/lib.rs new file mode 100644 index 0000000..ba14690 --- /dev/null +++ b/day_13/src/lib.rs @@ -0,0 +1,381 @@ +pub mod day_13 { + + use std::cmp::max; + use std::fmt; + + // TODO: commonise with day 9 and 11 + #[derive(Debug, Clone)] + pub struct Array { + row_len: usize, + elts: Vec, + } + + impl Array { + fn col_len(&self) -> usize { + self.elts.len() / self.row_len + } + fn get(&self, row: usize, col: usize) -> Option + where + T: Copy, + { + if row * self.row_len + col >= self.elts.len() { + None + } else { + Some(self.elts[row * self.row_len + col]) + } + } + fn set(&mut self, row: usize, col: usize, val: T) + where + T: Copy, + { + self.elts[row * self.row_len + col] = val; + } + } + + #[derive(Debug, Clone)] + pub enum Axis { + X, + Y, + } + + impl std::fmt::Display for Axis { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Axis::X => { + write!(f, "X") + } + Axis::Y => { + write!(f, "Y") + } + } + } + } + + #[derive(Debug, Clone)] + pub struct Data { + paper: Array, + reversed_fold_list: Vec<(Axis, u16)>, + } + + impl std::fmt::Display for Data { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for row in 0..self.paper.col_len() { + for col in 0..self.paper.row_len { + let entry = self.paper.get(row, col).unwrap(); + if entry { + write!(f, "X")?; + } else { + write!(f, ".")?; + } + } + writeln!(f)?; + } + + for (axis, value) in self.reversed_fold_list.iter().rev() { + writeln!(f, "{}={}", axis, value)?; + } + + fmt::Result::Ok(()) + } + } + + fn chomp_int(iter: &mut I) -> Option + where + I: Iterator, + { + let mut answer = 0; + let mut is_empty = true; + loop { + match iter.next() { + None => { + return if is_empty { None } else { Some(answer) }; + } + Some(c) => match c.to_digit(10) { + None => { + return Some(answer); + } + Some(d) => { + answer = answer * 10 + (d as u16); + } + }, + } + is_empty = false; + } + } + + fn chomp_string(iter: &mut I, expected: &str) + where + I: Iterator, + { + for c in expected.chars() { + match iter.next() { + None => { + panic!("Expected '{}', got nothing", c); + } + Some(actual) => { + if actual != c { + panic!("Expected '{}', got '{}'", c, actual); + } + } + } + } + } + + fn should_end(iter: &mut I) + where + I: Iterator, + T: std::fmt::Display, + { + match iter.next() { + None => {} + Some(c) => { + panic!("Expected end of iterator, got {}", c); + } + } + } + + pub(crate) fn parse(s: &str) -> Data { + let mut coordinates = Vec::new(); + let mut lines = s.split('\n'); + + let mut max_x = 0; + let mut max_y = 0; + + // Consume coordinates + for line in &mut lines { + let mut chars = line.chars(); + match chomp_int(&mut chars) { + None => { + // Move to consuming folds + break; + } + Some(x) => { + if x > max_x { + max_x = x; + } + let y = chomp_int(&mut chars).unwrap(); + if y > max_y { + max_y = y; + } + coordinates.push((x, y)); + should_end(&mut chars); + } + } + } + + let mut folds = Vec::new(); + // Consume folds + for line in lines { + let mut chars = line.chars(); + chomp_string(&mut chars, "fold along "); + let axis = match chars.next() { + Some('x') => Axis::X, + Some('y') => Axis::Y, + None => { + panic!("Expected an axis, got nothing"); + } + Some(c) => { + panic!("Expected an axis, got '{}'", c); + } + }; + chomp_string(&mut chars, "="); + let value = chomp_int(&mut chars).unwrap(); + should_end(&mut chars); + folds.push((axis, value)); + } + + let row_len = max( + max_x as usize + 1, + folds + .iter() + .filter_map(|(axis, v)| match axis { + Axis::X => Some(*v * 2), + Axis::Y => None, + }) + .max() + .unwrap() as usize + + 1, + ); + let col_len = max( + max_y as usize + 1, + folds + .iter() + .filter_map(|(axis, v)| match axis { + Axis::X => None, + Axis::Y => Some(*v * 2), + }) + .max() + .unwrap() as usize + + 1, + ); + + let elts = (0..(row_len * col_len)).map(|_| false).collect(); + + let mut paper = Array { + elts, + row_len: row_len as usize, + }; + + for (col, row) in coordinates.iter() { + paper.set(*row as usize, *col as usize, true); + } + + folds.reverse(); + + Data { + reversed_fold_list: folds, + paper, + } + } + + pub fn input() -> Data { + parse(include_str!("../input.txt")) + } + + fn fold_once(data: &mut Data) -> Option<()> { + let (axis, value) = data.reversed_fold_list.pop()?; + let value = value as usize; + + match axis { + Axis::X => { + for col in (value + 1)..=(2 * value) { + for row in 0..data.paper.col_len() { + let new_value = data.paper.get(row, 2 * value - col).unwrap() + || data.paper.get(row, col).unwrap(); + data.paper.set(row, 2 * value - col, new_value); + data.paper.set(row, col, false); + } + } + } + + Axis::Y => { + for row in (value + 1)..=(2 * value) { + for col in 0..data.paper.row_len { + let value_one = data.paper.get(2 * value - row, col).unwrap(); + let value_two = match data.paper.get(row, col) { + None => { + panic!("Unwrapping at row {} col {}, value {}", row, col, value); + } + Some(v) => v, + }; + let new_value = value_one || value_two; + data.paper.set(2 * value - row, col, new_value); + data.paper.set(row, col, false); + } + } + } + } + + Some(()) + } + + pub fn part_1(data: &Data) -> u32 { + let mut data = data.clone(); + fold_once(&mut data).unwrap(); + + data.paper + .elts + .iter() + .fold(0, |i, &v| if v { i + 1 } else { i }) + } + + pub fn part_2(data: &Data) -> String { + let mut data = data.clone(); + let max_x_fold = data + .reversed_fold_list + .iter() + .filter_map(|(axis, v)| match axis { + Axis::X => Some(*v), + Axis::Y => None, + }) + .next() + .unwrap(); + let max_y_fold = data + .reversed_fold_list + .iter() + .filter_map(|(axis, v)| match axis { + Axis::X => None, + Axis::Y => Some(*v), + }) + .next() + .unwrap(); + + while let Some(()) = fold_once(&mut data) {} + + // +1 for the newlines + let mut result_str = String::with_capacity(((max_x_fold + 1) * max_y_fold) as usize); + + for row in 0..max_y_fold { + for col in 0..max_x_fold { + let character = if data.paper.get(row as usize, col as usize).unwrap() { + '#' + } else { + '.' + }; + result_str.push(character); + } + result_str.push('\n'); + } + + result_str + } +} + +#[cfg(test)] +mod tests { + use super::day_13::*; + + static TEST_INPUT: &str = "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"; + + #[test] + fn part1_known() { + let data = parse(TEST_INPUT); + assert_eq!(part_1(&data), 17); + } + + #[test] + fn part2_known() { + let data = parse(TEST_INPUT); + let expected = "##### +#...# +#...# +#...# +##### +..... +.....\n"; + assert_eq!(part_2(&data), expected); + } + + #[test] + fn test_day_13() { + let input = input(); + assert_eq!(part_1(&input), 693); + let expected = "#..#..##..#....####.###...##..####.#..#. +#..#.#..#.#.......#.#..#.#..#....#.#..#. +#..#.#....#......#..#..#.#..#...#..#..#. +#..#.#....#.....#...###..####..#...#..#. +#..#.#..#.#....#....#.#..#..#.#....#..#. +.##...##..####.####.#..#.#..#.####..##..\n"; + assert_eq!(part_2(&input), expected); + } +} diff --git a/day_13/src/main.rs b/day_13/src/main.rs new file mode 100644 index 0000000..828fbbe --- /dev/null +++ b/day_13/src/main.rs @@ -0,0 +1,7 @@ +use day_13::day_13::{input, part_1, part_2}; + +fn main() { + let input = input(); + println!("part 1 => {}", part_1(&input)); + println!("part 2 => \n{}", part_2(&input)); +} diff --git a/day_2/src/lib.rs b/day_2/src/lib.rs index 141dbfa..241ee02 100644 --- a/day_2/src/lib.rs +++ b/day_2/src/lib.rs @@ -94,7 +94,7 @@ pub mod day_2 { pub fn part_1(movements: &[Movement]) -> u32 { let start_pos = Position { x: 0, y: 0 }; - let final_pos = movements.iter().fold(start_pos, |pos, dir| step(pos, dir)); + let final_pos = movements.iter().fold(start_pos, step); final_pos.x * final_pos.y } @@ -130,9 +130,7 @@ pub mod day_2 { depth: 0, aim: 0, }; - let final_pos = movements - .iter() - .fold(start_pos, |pos, dir| step_2(pos, dir)); + let final_pos = movements.iter().fold(start_pos, step_2); final_pos.x * final_pos.depth } }