diff --git a/Cargo.lock b/Cargo.lock index 6712eef..ab5c98b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,9 +23,18 @@ version = "0.1.0" name = "day03" version = "0.2.0" dependencies = [ + "helpers", "regex", ] +[[package]] +name = "day04" +version = "0.1.0" + +[[package]] +name = "helpers" +version = "0.1.0" + [[package]] name = "memchr" version = "2.7.4" diff --git a/Cargo.toml b/Cargo.toml index 05c3d0c..c8afd37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,12 @@ [workspace] resolver = "2" -members = ["crates/day01", "crates/day02", "crates/day03"] +members = [ + "crates/helpers", + "crates/day01", + "crates/day02", + "crates/day03", + "crates/day04", +] [workspace.dependencies] regex = "1.11.1" diff --git a/c/day02.c b/c/day02.c index bc47b39..75914b7 100644 --- a/c/day02.c +++ b/c/day02.c @@ -7,7 +7,7 @@ #define MAX_VALUES 100 bool has_small_difference(int *vec, size_t size) { - for (size_t i = 0; i < size - 1; ++i) { + for (size_t i = 0; i < size - 1; i++) { int diff = abs(vec[i + 1] - vec[i]); if (diff < 1 || diff > 3) { return false; @@ -20,7 +20,7 @@ bool is_safe(int *e, size_t size) { bool non_increasing = true; bool non_decreasing = true; - for (size_t i = 0; i < size - 1; ++i) { + for (size_t i = 0; i < size - 1; i++) { if (e[i] < e[i + 1]) { non_increasing = false; } @@ -69,7 +69,7 @@ int main() { // --- Part One --- unsigned int safe_count = 0; - for (size_t i = 0; i < row_count; ++i) { + for (size_t i = 0; i < row_count; i++) { if (is_safe(report[i], MAX_VALUES)) { safe_count++; } @@ -78,17 +78,17 @@ int main() { // --- Part Two --- safe_count = 0; - for (size_t i = 0; i < row_count; ++i) { + for (size_t i = 0; i < row_count; i++) { if (is_safe(report[i], MAX_VALUES)) { safe_count++; } else { - for (size_t pos = 0; pos < MAX_VALUES; ++pos) { + for (size_t pos = 0; pos < MAX_VALUES; pos++) { if (report[i][pos] == 0) continue; int *new = malloc((MAX_VALUES - 1) * sizeof(int)); size_t new_count = 0; - for (size_t j = 0; j < MAX_VALUES; ++j) { + for (size_t j = 0; j < MAX_VALUES; j++) { if (j != pos) { new[new_count++] = report[i][j]; } @@ -106,7 +106,7 @@ int main() { } printf("Part Two solution: sum is %u\n", safe_count); - for (size_t i = 0; i < row_count; ++i) { + for (size_t i = 0; i < row_count; i++) { free(report[i]); } free(report); diff --git a/c/day03.c b/c/day03.c index dc4eaff..81848ad 100644 --- a/c/day03.c +++ b/c/day03.c @@ -78,8 +78,6 @@ static SizeVector create_size_vector(size_t initial_capacity) { return vec; } -static void free_size_vector(SizeVector *vec) { free(vec->data); } - static void push_back(SizeVector *vec, size_t value) { if (vec->size == vec->capacity) { vec->capacity = (vec->capacity * 3) / 2; // 1.5x growth @@ -127,8 +125,8 @@ static int parse_with_rules(const char *message) { if (do_positions.size == 0 && dont_positions.size == 0) { int result = count_mul(message); - free_size_vector(&do_positions); - free_size_vector(&dont_positions); + free(do_positions.data); + free(dont_positions.data); return result; } @@ -153,9 +151,8 @@ static int parse_with_rules(const char *message) { } } - free_size_vector(&do_positions); - free_size_vector(&dont_positions); - + free(do_positions.data); + free(dont_positions.data); return count; } diff --git a/cpp/day01.cc b/cpp/day01.cc index 9aa3af8..fcbe808 100644 --- a/cpp/day01.cc +++ b/cpp/day01.cc @@ -42,7 +42,7 @@ int main() { std::sort(left_column.begin(), left_column.end()); std::sort(right_column.begin(), right_column.end()); - for (size_t i = 0; i < left_column.size(); ++i) { + for (size_t i = 0; i < left_column.size(); i++) { sum += (static_cast(std::abs(left_column[i] - right_column[i]))); } diff --git a/cpp/day02.cc b/cpp/day02.cc index ad9cb4f..4ed1a27 100644 --- a/cpp/day02.cc +++ b/cpp/day02.cc @@ -6,7 +6,7 @@ #include bool has_small_difference(const std::vector &vec) { - for (size_t i = 0; i < vec.size() - 1; ++i) { + for (size_t i = 0; i < vec.size() - 1; i++) { int diff = std::abs(vec[i + 1] - vec[i]); if (diff < 1 || diff > 3) { return false; @@ -59,7 +59,7 @@ int main() { if (is_safe(e)) { safe++; } else { - for (size_t pos = 0; pos < e.size(); ++pos) { + for (size_t pos = 0; pos < e.size(); pos++) { std::vector new_e = e; new_e.erase(new_e.begin() + pos); diff --git a/cpp/day03.cc b/cpp/day03.cc index 4335729..4898bcd 100644 --- a/cpp/day03.cc +++ b/cpp/day03.cc @@ -51,43 +51,33 @@ class ProgramParser { std::string::const_iterator iterator; std::string::const_iterator end; - char peek() const { return iterator != end ? *iterator : '\0'; } + char peek() const { return (iterator != end) ? *iterator : '\0'; } void next() { - if (iterator != end) - ++iterator; + if (iterator != end) { + iterator++; + } } bool parse_mul() { - if (peek() == 'm') { - next(); - if (peek() == 'u') { - next(); - if (peek() == 'l') { - next(); - return true; - } + static const std::string target = "mul"; + for (char ch : target) { + if (peek() != ch) { + return false; } + next(); } - return false; + return true; } std::optional parseNumber() { std::string digits; - - for (int i = 0; i < 3; ++i) { - if (std::isdigit(peek())) { - digits.push_back(peek()); - next(); - } else { - break; - } - } - - if (!digits.empty()) { - return std::stoi(digits); + while (digits.size() < 3 && std::isdigit(peek())) { + digits.push_back(peek()); + next(); } - return std::nullopt; + return digits.empty() ? std::nullopt + : std::make_optional(std::stoi(digits)); } }; diff --git a/crates/day03/Cargo.toml b/crates/day03/Cargo.toml index 320bbb2..62bdfa9 100644 --- a/crates/day03/Cargo.toml +++ b/crates/day03/Cargo.toml @@ -8,6 +8,7 @@ workspace = true [dependencies] regex = { workspace = true, optional = true } +helpers = { path = "../helpers"} [features] regex=["dep:regex"] \ No newline at end of file diff --git a/crates/day03/src/main.rs b/crates/day03/src/main.rs index e699eb9..7deffbd 100644 --- a/crates/day03/src/main.rs +++ b/crates/day03/src/main.rs @@ -1,12 +1,9 @@ -use std::{ - fs::File, - io::{BufReader, Read}, - str::FromStr, -}; +use std::str::FromStr; #[cfg(not(feature = "regex"))] use std::{iter::Peekable, str::Chars}; +use helpers::read_file; #[cfg(feature = "regex")] use regex::Regex; @@ -17,25 +14,25 @@ pub struct Problem { impl FromStr for Problem { type Err = String; + fn from_str(s: &str) -> Result { Ok(Self { program: s.into() }) } } #[cfg(not(feature = "regex"))] +/// Parses and counts the product of numbers within a "mul(a, b)" format. /// # Errors -/// -/// Will return `Err` if there's an error in the parsing/regex +/// Returns an error if input parsing fails. pub fn count_mul(p: &str) -> Result> { - let Problem { program } = p.parse()?; - let mut parser = ProgramParser::new(&program); - + let program: Problem = p.parse()?; + let mut parser = ProgramParser::new(&program.program); Ok(parser.parse()) } fn main() { - // --- Part One --- let message = read_file("crates/day03/input.txt").unwrap(); + // --- Part One --- let mut count = count_mul(&message).unwrap(); println!("Part One solution: sum is {count}"); @@ -44,18 +41,6 @@ fn main() { println!("Part Two solution: sum is {count}"); } -fn find_all_indexes(haystack: &str, needle: &str) -> Vec { - let mut indexes = Vec::new(); - let mut start = 0; - - while let Some(pos) = haystack[start..].find(needle) { - indexes.push(start + pos); - start += pos + 1; - } - - indexes -} - #[cfg(not(feature = "regex"))] struct ProgramParser<'a> { iterator: Peekable>, @@ -73,26 +58,27 @@ impl<'a> ProgramParser<'a> { let mut result = 0; while self.iterator.peek().is_some() { - if self.parse_mul() { - if self.iterator.peek() == Some(&'(') { - let _ = self.iterator.next(); + if !self.parse_mul() { + self.iterator.next(); + continue; + } + if self.iterator.next_if_eq(&'(').is_none() { + continue; + } + let Some(a) = self.parse_number() else { + continue; + }; - if let Some(a) = self.parse_number() { - if self.iterator.peek() == Some(&',') { - let _ = self.iterator.next(); + if self.iterator.next_if_eq(&',').is_none() { + continue; + } - if let Some(b) = self.parse_number() { - if self.iterator.peek() == Some(&')') { - let _ = self.iterator.next(); + let Some(b) = self.parse_number() else { + continue; + }; - result += a * b; - } - } - } - } - } - } else { - let _ = self.iterator.next(); + if self.iterator.next_if_eq(&')').is_some() { + result += a * b; } } @@ -140,37 +126,39 @@ impl<'a> ProgramParser<'a> { } } -fn closest_greater_than(x: usize, y: &[usize]) -> Option { - let mut closest: Option = None; +fn find_all_indexes(haystack: &str, needle: &str) -> Vec { + let needle_len = needle.len(); + let mut indexes = Vec::new(); - for &value in y { - if value > x && (closest.is_none() || value < closest.unwrap()) { - closest = Some(value); + for (i, window) in haystack.as_bytes().windows(needle_len).enumerate() { + if window == needle.as_bytes() { + indexes.push(i); } } - closest + indexes } -fn parse_with_rules(message: &str) -> i32 { - let do_substring = "do()"; - let do_position = find_all_indexes(message, do_substring); +fn closest_greater_than(x: usize, y: &[usize]) -> Option { + y.iter().filter(|&&value| value > x).min().copied() +} - let dont_substring = "don't()"; - let dont_position = find_all_indexes(message, dont_substring); +fn parse_with_rules(message: &str) -> i32 { + let do_positions = find_all_indexes(message, "do()"); + let dont_positions = find_all_indexes(message, "don't()"); - if do_position.is_empty() && dont_position.is_empty() { + if do_positions.is_empty() && dont_positions.is_empty() { return count_mul(message).unwrap(); } - let first_substring = &message[..=do_position[0]]; + let first_substring = &message[..=do_positions[0]]; let mut count = 0; count += count_mul(first_substring).unwrap(); let mut next_dont: Option = None; - for i in do_position { + for i in do_positions { if next_dont < Some(i) || next_dont.is_none() { - if let Some(f) = closest_greater_than(i, &dont_position) { + if let Some(f) = closest_greater_than(i, &dont_positions) { let substring = &message[i..f]; count += count_mul(substring).unwrap(); @@ -197,11 +185,3 @@ fn count_mul(message: &str) -> Result> { Ok(result) } - -fn read_file(file_path: &str) -> Result> { - let file = File::open(file_path)?; - let mut reader = BufReader::new(file); - let mut content = String::new(); - reader.read_to_string(&mut content)?; - Ok(content) -} diff --git a/crates/day04/Cargo.toml b/crates/day04/Cargo.toml new file mode 100644 index 0000000..41e4f2c --- /dev/null +++ b/crates/day04/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day04" +version = "0.1.0" +edition = "2021" + +[lints] +workspace = true diff --git a/crates/day04/input.txt b/crates/day04/input.txt new file mode 100644 index 0000000..d30973c --- /dev/null +++ b/crates/day04/input.txt @@ -0,0 +1,140 @@ +SMXMMAXXXXMMMMSMMASASMSXMMAMSSMXSMMXMASAMXXMAMXAXXAMXAXASMSMSMMMSXXSXSXXAAMXXSXMASMAASXMXMSSMXXXXMMSSSMXSXXMASXMMSMSXMXSSMXSMMMSXMSAMSASXSAM +MASMMSXMMMMAMSMAXSAMXAXAXXAXSASAMASMMASAMAXMAXMMSXASMMMMSAAXAAAAXSMAAAAMAMXSSMMXMASMSAMXSAAAMSMMMSMAAAMMMXMXAXASAASXASAXMASMAAXXAXMAMXXSSMAM +MAMAAMXMAXSASAMMMXAMMMMAMMSMSAMXSAMXMASAMMSXSASAMXSMAAAMMXMMSMMXMAMSSMMAAMAMAXAAXMAMXAMSAMMSMAXAAAMMSMMAAXSMMSXMSMMSAMXSXMXXMMSSMMMSMMXMASXM +MAMMMXAMXMXXSASXAXAMSXMXSAAXMMMXMXSXMXSMMXMAXAMXXXXXSSSSXAMXXAMMAMXAXAXSAMMSMMMSMMSMSAMAAXMAMXSMSXXAXMSSSSMAXSAMXMMMSXAXAXAMMXMASXAMAMSXAMMX +SSSXXSMMSMMXSAAMSSSMMXSAMMSMMMMMMASASAMASMMMMXSSSSMXMAMMMXSASAMXXXSXMMMMASXAXASAMMAAMXMSMMSMXMXXAMXXSMAMMXMAMMXAAXMAMMSSMMXXAASAMMXSAMAMSSMM +AAXMASMAAASAMXMAMMAAXXMASAXXMAAAXMSAMXSAMAMXSAAAAXAAMAMAAXAMMMMSMAXMXSASAMMMMMAASMMSMAMAXXXMASAMXSAAMXAXMASXMSASMSMMMMMAXAAXSXMASAMSAMMXMAMA +MXMMAMASMMMXSXSASXSMMMMXMMSASMSMSAMXMXMMSSMAXMMMMMSXSASMSSMXXAAAMAMXMAMMAMXXAXSXMASAXSSSSMMSASAMASMMMSMSXAXXAAXXAAMAAXSMMMSMMAMMXXAMAMXMSMMS +MMXMAXXMMMAXMXMASXAXAAMMMMSAMXAMXMMAMXMMAAMXSXMXAAAASASAAXXSSMSSSMSSMSMSXMXXSXMXAXSMMMMXMMAMXMAMAMXAMAAMMMMMSMMMSMXMSMMXMXMAMMMSMMSSXMAAAXAM +MAASMXSAXSSMSAXXMMSSSMMAAAMXMMXXAXSXSASMSSMAMASMMXSAMXMMMXSAAMMXMAMAAAAXAASMMASXSMXXAAXMMMSSMSXMSSSXSMSMASAAAXMAMSMAMAMMXASXMSAMAAAMASXSMMSS +ASAMMAMXMXAAXMSAAXAAAASMMXSAXAMXMXAAAASMXMMASAMAAAMASXXMXMASMMMAMAMMSMSSMMXASAMAMAMSSMSAXMASAAXMXAXASXMXAXASMSMASMMMSAMXSASAMMASMMSSMMAAXAAS +MMAMMMSMSSMMAAMASMMXMASAAASASMAASAMSMXMXAXSAMASMMXSAMAMXAMXXMAMXSAMAXMAMAASAMASAMAMXAASMMMAXXMXMASMXMASMXSAMAXXXXAAAMAMAMXMAMAAMXMAMXMXMMMMS +XMAMSXMAAAXSXSMAMMXXXXXMMXMMMMSAXAXAXMMMMXMASAMAAXMXSAAMSSMXSSXMMMSSSMSXXMMXSMMXSXSMMMMAAMMMMSAMAXXXXMMAAAXMXMMSXSMMXAMXSSMSMMXXXMAMAMXMAMSS +SMSMXAXMMXMSMAMASXSXSAMXMAMMSXMASMMMAAAAXAMAMXSMMSMXSXSAAAMXMMXSAAAXAAAXMMSASAMXXMXMXSXSMSXAASAMSSMSAXMMMSXXXASAAXAMSSMMMMAAXMASMMSMSMSXXSAX +MAAMXSMMSXAXSXMMSXAAXMMASMSAXAMAMAAXMXSSSSSMSMAMXMMMMMMMSXMXAAAMMMSSMMMSMAAAMMAMSMAMAXAXMMMMXMAMXAAMAMXMXMXXMSMMSMAMSAAAAMMSMMMXAAXAMASAMMMM +MSMSAAAAAMSMMMXXXMMMMMSXSAAMSSMASXMMSMAMAMXMAAAMXMAXAASXMASXMMXSAMXMAAAAMAMMMXMMAMAMSSMSAMMXMSMMSMMMSSXXAAXMXAMMXXXMSXMMXMXMAXSMMMMAMAMAMAAX +XAAMXSMMMSXMMASXSMAXAAAMMMXXAXMAXAAAXMAMAMASXSASAMSSSXSASXMASAMMASASXMSAMXSXXMASASAMXMASAMXAMAXAAAMAXAASMSXMSMSAMXMMMMSMMMSMMMXAASMSMSSSSSSS +SMSMMMMSMXMAMXSAASMSMSMXAXMMASMXSSMSSSMSASMSAMAMAAMAMXSAMASXMAMSAMASXMAXMAMMAMXXASASAXXMXMSMSMSSSSMMMMMXAAMXAXMXMSAMXAAAXASAAMSSMSAXAXAAMAMM +MXMAAMAMAASAMAMXMMXAMXXSMSMMAMMAMXAAAAXSASXSASXXMMMAMXMAMXMXSAMMMMXMAXXXMASMSMSSXSAMMMMSSMMXAAAAXAAXAXXMMMASMSSSXMSSXSXSMASMMMAMXMMMSMSMMAMM +XASMMSASMMSASXXAMXAMSSMXAAAAASMMSMMMSMMMAMMMAMXXMXSSMMSAMAXXMMMAAMXMASMMSMXMAAMSAXXXXMAAXAAXMMMSMSMSMSAXAMMXXAAMAMXSAAAXMXMMMXXMXMXAXXAXMXMM +SMXXXMXMAMXAMXXSSMMXSAMMSMSSXSAMXXAMAXAMAMXMMMSXXAAAAXMAMAMXASMSSMXAAXAAMAMSMSMSXMASMMMSSMMXSAAXXXAXAMMXMSXSMMSMMSAMXMMSXAAAMAXMASMMMMMMSMSM +SAMSMMSSSXSAMXXMAAXXMAMAXMAMASAMXSASAMMMMMMXMMXAMSSSXMSAMXXSAMMMMAMSAMMMMAMXAMAXMAMXXAMAXXAAXMSMMMMMSMSMXMAXXAAMAAAXAMXXXMSSSMAMAXASAAAAAMAX +MAMSAMAAXMMAMXMSAMXSSMMSSXMMMMXSASXMAMMSMSMAMSMSMAAAXASASAAMMSAAMSMAAXSASASMSMAMSSXMASMMASMSSXMAXXXAXAAMAMSMXSXSMSMMAASAXMAMAMMSMSASMSMSSSMX +SAMMAMMSMSMSMAXSASAMAMXXMAMXMASMMSMMSAAAAASASXAXMMMMXMXAMMMMAMXMSMXMSMSASAMAAMXMAMAAAXAMAMMXMASXMASMMMMSASAMXMMMXAXXXMSAMXASMMAAXXXXXXMAXMXX +MXMXMMMAAAXAMXMMXMMSAMXMSSMAXMXMAMXAMXSMSMSMSMMMMSMSSSSSMXXMAMSSMXMMXAMMMMXSXSMMMSXSSSXMAXMASAXMAMAAASXSXSASXXAXMASMAXXMXSXMAMMSSXMSMSMXMXMS +SMSAMASMSMSXXAMMAXXSXMAMXMASMXAMAXMASAXXXAMAXAXAXAASAAXMAXXMAMSAMXAAMSMXSMXMASAAMXAMAMXSAXSAXXXXMSSSMMXXASMMMSSMMAXXXMASMXASMMSAMAXMASAXSAMX +XASXSASAAXAMMSXMMSMMSXMSASXMXSMMMSMAAMMMMMMMMMMMSMSMMMMSAMXMXXSAMXSXXAXAAXSSMSSMXMSMMMMMMXMASMSMAAXMMSSMAMMAAMXAMASMMSSMASAMXMMAXXAMXMAMSAMS +MXMAMASXSMXSAXASAMAASXMSAXASAMMSAAMMSXAXASASAMAMAMAMASMSXMXMMMSAXAMMMSMMSXMAXMASMSMSXXXAXSMMXAAMMMSMAAXMAMMXSSSXMXSAAXXXXMXSXXSMMSMXAMMMSMMA +AAMAMAMAXXAMMSAMASMASAMMAMSMMAAMXMMSMXMSMSASXSAXMSASASAMXXAXAAMMMXSAAXAXMMSMMSAMXAMSXXMASXMMMSMXSAXMMSSSMSAMAAAASXMMSMMMXMAAMMSAMASMXSAAXAMX +SXSXSXMMMMSSXMASMMMXSAMMAMXAMMSSMMSSMSMAAMAMASASASASXMAMXSMSSSMMSASMSSSMAAXSXMXMSXSMAMSMMAXMAAXMASMXAXXMASMMSSXMXAXSMXAAAMAMSASAMAMMMSMSMMMA +MAMAXAMSSXXAXMAMXMSMSXMXMXSXMAMAMMASAAXAMAAMMMAXAMAMXMAMXSAAAAAAMXSAAAAMMMSMXSSMAMAMAMAASMMMSXXAXXXMMSMMMMXAAAMXXMMMASXSXSSXMMSXMAMAASXXAMXM +MSSMMXXAXMSMXSAMXMAASASASXSSSXSAMXMMSMMMXSSSSMSMXMSMMSSSMMMMMMMMSMMMMMMMAXAAXSASASAMXSMMAASAAAXSAMXXAAAMMXMMSXSAAMAMMMXXMAMAMXMMSSXMMSASMMAM +AAAMMXXSXMXXASMSAXMSMAXASAMASAMXMSXAMXASMMMAMAXAXXXAAAAXAXXXXMXMAXXMASXSSSMSMSAMXSASXXMASMMMXSXMASMMSMSMMXSXAMMMMMASMSAMXASAMASXAAXSAMXMXSAM +MSSMMMMMXSMMMSASXSSMMMMMMXMAMSMAMXMMSSMMAAMAMMMMSSSMMMSMSXMMSMASAXMMMXMAXAAAAMAMXSAMXXSAXMASAMMSAMMAMSMASMMMMXSAMMXMASASXMSXSSSMMMMMASMMXXMX +MXAAAAAAXMAMSMMMMXXAAXSXMXMASMSMSXXAAAMSSMXMSMXAAAAAMAXXMASAMSMMMXSAAAMMMMMSSMMMXMAXSAMXSSXSAMAMSAMXMASAMAAAXXMASAMXMSASMASAXAMXSAAMAXAMXMSA +ASMMSSXMMMAMMAMXAMSMMSMAMAMXMXAMXMXMMSMAMXAXAMMMSSSMMASAMAMAMSXXAAMMXXMXMMAXAXXSXSMXMAMAMAMSXMXSMMSMSMMMSSSMSXSAMXMXAMAMMAMAMAMAMMMMMSMSAAMX +MSAMXXXASMSSSSMSSMXAMAXSSMSAXSXMAMMSAMMASMMXAMMMAMAAMMMMMASMMMMMMMSSMSMAMSMSMMMMASMXMXMXSAAMASXMMMAAAXAMAAAAXMXMMAMXMMXMMSMMAMMXMAXXXAAMMSMM +XSAMAMSAMAAAAXAMMXMASAMXAAMXMAMMASAMMXSASAXXSMAXASXMMMSMXASXASXMSAAAAAMAMAAAXMXMAMMXMAXASXMSAMAMXSMSMMMMMXMAMXAASASMXMXSAXAMXMAMSMSSMMSMAAXX +XXXMAXSXMMMMMMSMMAAMMAMSMMMMAMASMMMSMAMSMXMAXSXSAMXAAMAMAMXMXMAAXMSXSXSASMSMSSXMASXASMSMXMXMAMXMASAMASXMSMXXAMMMSASAAXMMASMMAMAMAMXAAXMASMMM +XMSSSXSAXMAMXMXASXSXSAMMAMMAMXXAXAMSMAXAMAMMMAMMMMMSXSASMMSXSMMMAMAAXMSAMXAMXXAMASMMAAXMASXMAASMMSASAMSAAXMSSSMAMMMXXSAMXMASMSSSSMSSMMXAASAM +AXMAMASAMMASAMSMMSXMSAMXAMXSXSMXMMSSSMSMXAXAMXMMASXAAMASMAAASXMAAMMMSAMAMSMSAMXMASASMXMSAMAAAXXAXSXMASXSMSAAAAAXXAXXMAMSASXSMAMAMXMAMXMMSMSX +MSMMMMMMMSASXXAASAMAXAASMMMXAAMASMAXXXAXSSSMSASAAXMMSMXMMMMXMASXXAXAMAMXMAAMAAXMXSAMXMXMASMXSSSMMXXXMMMMMSMMSMMSMSMSAMASASXXMAMAMMMAMSXXMAMX +AAMXAXAXMAMMXSSMMASMMSMAMAMMAMMAMMSMSAMXMMAASASMAMMAXMASAMXXSXMMMMMMMASMMMSMXSMSMMMMXMAMMMXAXMASASMMSAAMASAXXAAXAAASMSAMXMAMSMSASXXAMXMMMAMM +SMXSASMSMSAMXAMXMAMXAMXMMAXAMXMSSMAAXMXMSMAMMXMXXAMXMXMAMAMXMAXSAXMAXXSAAAMAMAAAMAMMMMMSMAMMMSXMXXAASASMASXMXMMMSMXMXMASMXSAAXAAAMSMMAMXMAMA +MXMAMMMAAXASXSSXSAMMSMAXSSSSSSXAAMMMMMAMAXAXSMSASXMSXMMMASXMSAASXMMSSXMXMXXAMMSMSASMSAAXMAMXAMASMSMMMAAMMMASXXXAXXXMSMXMXAMMMMMMMAAXXASMSSSS +MASXSAMXSSXMMXAXXAXAASXXMMAAAMMSMMXAASASMSMSMAMASAASAMAMAXAMXMMMXSAAXAXSMSSXMXMXSASASMMMSSSXMSAMXAAMMXMSXSAMXMMMMMXMAXMXMXSAASXSMSMSSMSAXMAX +SAMAMXSAXMASXMSMSSMXMAMXSMMMMMAAASMSXSXXXAXAMXMXSXMMAMXMMSMMXXXAAMMMSSMSAXAAXXMAMAMMMMSMAXAMMMASXSMXMSMAAMMMAXAAAAMXMSAMXSSXXXAXAAXXAAXXXMMM +MASMMMMXSMMSXSAAXAAMXSSXMASXSXMMSMAAXMASMMSXSXSXSXMMMMAAMAXXXAMMMMMXAMAMMMSMMAMSXSAXXXAASXMMSSXMAXXMXSMMSMASASMSMXSAAAXASMMXMMSMSMSSMMMMMSXA +XMAMXXSMXAAMMSXSMMMMMMAXXAMAXAMSAMXMSMAMAAAASAMMSXSAMSSMSASMMSAAMMSMMMAMXAAXAMXXAMXMASMSMAAAXXMMMSMMAXMAAXXMAMAAAASMMSMSMSAASMXAMXMMMSAAAMXS +XMASMMXAMMMSASAXXXMSAMXMASMMSSMAMXAXXXXXMMMMMAMASASAMAAXMAAAXASXSAMASXSSMSSSXMAMXMAXXAXAXMMMSXSAAAAMSSSSSMSMMMSMMMXMAXXAXMSMSAMMMAMAAXXXMMMM +XMAMASMSXMAMMMAMXMASMSXSXXAXAXXXMXMSSMMMXAASXSMMSASXMMSSMSMSMMMMMASMSAXXAAXMMMASAAASXSSSSSSXSASASMSMAXMAXAMXMAXAXSAMXSAMXMAMMMMASASMXXSSXSAS +MMASXMAXAMMSAMAMASXMASAXAMSMSSSSSSMAXAAASMMSAMXXMAMAXSAXAXXXAAAXSXMAMAMSASASXSXSAMXSAAAXAAMAMMMAXAAMXSMAMXMAMXMAMXASAAAXMXASXXSMSASMSAAMMMAS +XSAXAMMSXMXMASASASAXSMMMMXAMXAAMAAMASMMMXAAMAMXMMXMXSMMSAMASXSSXMAMXSAMXXMASASXMAMMMMMMMMMMAMAMXMMMSAXMASMSMSSSMMSSMMMMMMMASAMXXMASAAMXSXSAS +MMXXAMXSAMMSAMXMASMMMAASMMSSMMMMSMMASASMSMMMSMSMSSSXSAAMASXXMXXASMMAXXSXXMSMMMASMMMAAAXAMSXMXSSMMSAMMSMXXAAAXAAAMXMASXMASMSMMAAXMSMMMXXAXMAM +AAMSMMAXAXAAMMMMMMMMSSMSAAMXMMMXAMMXSAMAAXXXAAXAAAXASMMSAMXXSASMMMMMSMMMSSXASMAMAASXSSMMMASMAXAAAMASASXSMSMSMSSMMAMAMXMAMXXAMSMMMMAASMAMXMAM +MXMAXMXSMMSXMAAMAAXXMASMMSMAAASMMSMAMAMSMSSSMMMMMSMMMSMMAXSAMASAAXAAAAAAXXSMMMASMMMMMMAAAAAMMSSMMSAMAMAAAXAAAXAAMAMAMXMMXSSMMMMAASMMSXAXASAS +AMSSSMASAAAASXMMMSMSXMASAAXMMXMAAAMASAMXXAMASXSAAXXSASMMAMXMMAMMMMMSSSMSSMMMAMXMASXXAMXMMXSMXAAXAMAMAMMMXMSMSSMMSSSSSMSAXXAXMASXMMAMMMXMXSAS +XAXAXMASMMSXMAMSXXASAMXMSSXSSMMMMMSASMSMSMSAMXXMXXAMAMMSAMXSMMSSMXMAAXAMAAAXXXSXAXXMSSSMSMXXMMSMSMSSSSSSXAXAAAAMXAAMSAMXXSAMXAXMAMSASXSXMMMM +ASMSMMASXMMXMAAAAMMMXMMMMMMMMAASXMMAXAAAMXMAMSSMMSMMSMMASXAXXAAMAAMMSMSMSSMSSXSMSMXXAAAAXXSMSMMAMSAAAAAXMASMSSMMMMSMMMMXMAMAMMMMMXMAAAXMASAS +MAAXXXAXAXSXSMSMMMSMASAAAAAMMSMMAXMSSSMSMSSSXAAMXAAAXMSAMMSSMMSSSXSAMXXAMXAXMAMAMMMMMSMMMMAAAAMAMMMMMMMMMMAMAAAXXAXAMXMMMAMSMXASXSMMMXMASAMS +XMSMSMMXSMSAXAMXAAASAXXSSSXSAMASMMXAXAAXMAAMMSMMXSMMSAMASAAAXAXAAXMASMSMSMSAMXMAMMAAAAMAAAMSMSMSMMAXAAXMXSMXSSMMMXMXMSAASASXMSASAAXAXSAMAMXX +MXXASASAMXMAMSMSMSMMSSMMXMAMMMXMXMMMSMMMMMSMAMXMAMAMMXSSMMSSMMMMMXSXMASAXXMAMXMASXSMSASMSSMAMMAXAXMXSSSMAMXAXAMMSMSMMXMMMMMAXMMMMMMSXMASMXMA +MXXMMAMXXMMSXAAXAXXAAMXSAMXSSSXMXSAMAXAAXXXMMSAMASXXXXSXAAAAAXSXXXMAAMMAMXXMMSSMSMXXMXSMAXXAMSASMMSMMAMMAMMMMXMASAAASMMXAAMXMAXSAMAXXMAMXAAA +MSMSMSXMASMMSMSMMMMMMSASASAAMXASASASASMSSMMMASAMMMMMMMMSMMSSSMMXASMAMSSMSSMAMAAXSASASASMAMXMMSXXXAAAMSMSASXSASMAMXXMMAMMSMSMSSMMAMSSSMXXMMMM +XAAAAXAXAAXAMXAAXXXAAMASXMMSMSAMASAMMMXXMAAMASAMSSMAAAXAMAAXMAXXMASAXXAAAMSAMMSMMXMAMXSMASXSASAMMSMMXAAMASAXASMASXSMSSMAXASAAXXSAMXAMAASXMSS +XMMMXXXMSSMMSSSSMMMXXMAMAXXAMXAXAMMMMSMSSSMMXXAXAAXXMSMMMMASMXMSXMSMXSMMMXSMSXMXMAMAMXMMAAAMASMAAAMASMSMAMMMMMMXSAAAAXMXSAMMMMMMSXXMXMASAAAM +XSSSMSAAAMXAAMAXAXASMMSSMSSSMSSMXXXAXAAMAAASMSSMSSMMXXAMAXAMXXSXAMXXAMXSXXMASMSMSXXAXXSAMMMMXMXMAXXXMAXAMXSAAASAMMMMMMMXMXMAMXMAXMMXAXASMMMS +AXAAASMMMSXSMSAMXMMSAAXAXAAAMAXXXSSMSMSMMMMXAAXAMXXSASAMSMSXSXMXAMAMXSXXMMMXMAAXMAMSXMMXSMMXXXMSMSXMXSXMXAMXXMMASMXXSXSASASASMMAMAMSMSASXSSX +XMMMMMXXXAAXXMASXSXMXMMSMMSMMMMAMASAAMAAXAXMMMMMMAMMAMMMMAMXSASXSMXMAXMAXAXXMSMMMSMXASMSAMXAMAMAAAXMMXAMMMSMSSSMMMSMMASASASAMAMXMAMXAAAMAXXS +SAAAXAAMMMMMMSAMAMMSSMMXAXXMASASMAMXMSSSMSXAXAXAMAXMAMMAMAMAMAMAMASXMSSMMSMMMAMXMMAMAMMXXXAAAAXMSMMMAMAMAMAMXAAXXMAMMAMMMAMASXMSSSSMMMXMXMXM +ASXSSMMMAAAAAMMMSMSAXAASXMXMASAXMSSMXXMAAAASXMXSSSSSSXMASAMAMAMXMAMAXAAAXMAMSMSAAMAMSMMSMMSMSMSMAXAMSSSMXSASMMMMMSSMMASAMXSAMAAXAAXMXMMXMASX +MMXMAAASMSSMSXXAAXMASMMSXXXXXMMMMAAAXSXXMMAMAAAXMMAAMMSASXSSSMMXMASXMXMMMMSMMASXSMMSAAMAAAAAAAAMMMSMAAAXAXASMXAXXAAXSASXSASXSMMMMMMXAXMAXXXM +XMASMMMSAAAMXMMMXMXMXAAMMSSMMSMMMSSMMSXMXXXSMMMSAMMMMAMAMAMAMASMSASMMMASXAAAMAMSMAMAXXMMMXSSMSMAXAAMMMMMMSMXMSXSMMSMMASAMAXAXXAAMAMSMSSSXMAA +XXAMAAAXMXMMXAAAAMASMXXSAAAAAMAMAXAXAXAMMSMSXSXSAMAAMXSXSASMSAMAMASAASMXMXMXMMMXXAMMMMMXSAMAXXMMMSXMAAMAAAMAXSXMAAAAMXMAMMMSMSSSMAMAMXAAASMS +SMSSSMMSSSXMSSMSMSASAAMMMSSMMMAMMXAMSSXMAAMSAMXXXMSXXMAASASXMXSSMMMMMAMAMASMSMSSSMSXSAMAMAXSAMXXXAAXSSSSSSSMMSXXXMSXMXMASXAMAXMAXXXAMXMSMMAM +MXMAAASAXMAMAAMAAMAMMAXAMXAAASXSSMMMMXAMSMSMMMSMXMXSMAMMMMMMMMMAMSAXXMMAMMAAAAAAAAAAASMSSSMMAMSMMMSMAAXMAMAMAMMMMXXXSSMSSMXSSSSSMMSSSXMAMMMM +MSMSMMMMSSSMSSMMSMXMAMMASXXMXSMAXAAASXMMXXXXMAMSXSAMSXMAMXAASXSSMMXSMXSSSSMSMMMSMMMSMAMAAXAAAXAAXAAMMMMMSSSMMXAXAAMXMAMAMMASAMAMAXAXMASASAMX +XAAAXXAXMXAMXAMAAXXMAMSMMMASASMSMSSMSAMAXMXMASXAMMAMAMMSASMXSAMASMAXAMXAAAXXMXXAMAAMXAMMSMXXMSXXMMSMMASXAAXAXSSMSASXSAMAAAMMMMASAMXMXMXMMMMM +SMSMSSSSMXMSSXMSMSSMAXAAASMMAMAAMXMXXAMSSSXXAXMMMSMMXSAMXAXAMMMAAMAXMAMMMMSMSMSMSMSSSSSXXMAAXMMSSMXAMASMSMMXMXXAMAMMMXXSSXMAMMMXMAMSXSAMSMSM +AMAAMAAXASXAAAXAAMMSMSSXMXAMXMSMXAXXSXMXAMMMXXAXAXAAXMASMSMMSXMSSMMMSAMXAAAAAXSMMMAAAAAXAMXSXAAAAASAMAMAAXMAXAMMMAASXAMMAMSASAAMASMAAMMMAAAS +MSMSMMMMMMMMSSMXSMASXAXSSMMSAAMASXSMASAMAMMAMMSMSSSMXSAMAXAXAAMAMAAAMAMSMSSXSAMXSAMMMMMSASAAMMMSMMMMMMSSMMXAMMSSMSXMMXSMAMSASMSMMMMMSMSSMSMS +XAMXMSXMXAXXAAMAMMAMMXSAXAAXMMMAXAAAAMXSAMMMSAXAAAAMMMASMSXMSMMASMMMSMMXAXXAXASASAXMXMXMAMMXAXAAMAAAXAAAXSMMSAAMMXAXSAAMMMMMMMXXAXXAAAXMAAAX +AMXXXAASXMSSMMMXSMMSAMXMSMMSSXMXMSMMXSXSASAAMMMMMSMMSXAXAMXMAXSAMXXXAAXMSMMSMMMXSAMXASAMXXAASMSSSSSSMMSMMASAMXMSASMMMXSXSMSASMMSSMASMMMMAMSM +MSMSMSMMSAAXXXMMSAMXMAAXSXAAXXSSMAMSMSXSAMXSMXMAMAAAMMMSMXMMAXMASMXSSSMAMMAAAXAXMMMSMSMSXMAXXAMAAMAMAMMMSAMMXMXMAXSAMXXAMXSASMAAAXAMXSAMXMXM +XXAAAAXAMMSSMASAMAMMSMSXSMMSMMAXXASAAMAMXMSAMAMAMSXMSAMAXSMMSSSMAMXAAXMXMMMSSMSSMAXXMSXMAASAMXMXXMAMXSSXMAXXAMAMMMSXSAMAMXMXMMXSMMSAMXSSXSAS +MSSMSMMMXMXAMMMSMXMXSAMASXMAMMASMMXMXMAMAXAMSAXAXXAMSASXMXAAAXXMAMMXMMXSAMAMXAAAXMSAXMAXMAXAMMMASXXSAXMAXXMXASASAAXXMXSAMMMAMAXXXXMAXSAMASAS +XAAXMXMAAXSSMMAMXAMAMAMAMXXAXMAMAASXSSSSSSMMSMSMASAMSAMXMMMMSMSMSSMAXAMSAMSXMXSAMXMMMSMMMSXSMAMAMSAMAMSSMMSXASXXMXSMAMXAMAXASMMSMXSSMMAMAMXM +MSXMXAMSMXAMXMASXXMAXAMSSSMSAMXSMMMAAXAAXAAAXMAXMMMMMAMXMASAMAASMAXAMXMMXMXAMMMXMASMMMAXXXAXSMMMSMXMXMAMAAXMXMMXSSMAASXSSMSAMMAAMAMXXSXMSSSS +MMXMSXMAXMAMXMASMMMMSASAAXAXMAMMXAMMMMSMSSMMSSMSSXSASAMXXAMASXMMSAMXAAAXMASXMXMSXAAAAMAMMMMMAMSMAMXXXMXSMMMXMAXAMAXXASAXAAMXMAXAMXMMMSAMMAMX +XAAXXMASXSMMXMASAAAAMMMMSMMMMSAASXSASAAXAAMXXAXAAXSXSASXMAXMMAXXMSSMSXSASASAXMASMSXSMMAMMAMSAMXSASMMXSXSAAASMMMXSAMMMMMMSMXXMMSXMSAMASAMMAMA +MSMSASAMXMAMXMASMMSMSXMXXAXSAXMXMASAMMXSSXMASXMMSMMMXMMXAMXMSAMXAAXMMXMXMAXAMMMMAMMMMSMSXXMSXMXSXSAXMXASMMXMAMAXMMMSMAXAXXMXXXSAAAMMASXMSASX +XMXSXMXSAXAMXMASAMAMMASASMAMAXAAMXMAMMMAMAXMMMMXXXSAMSSSSSXMAMXMMMSMMASAMXMSXSAMMMAMXAXMASXMSAXXAMMSAMXMSMASMMSSMSAMSMMASMMMSASMMMXMAXMXSAMX +XMAMXMASMSXSAMXXMMXMMAMASMSMSMSASXSAMXAAXXMMAAMMMXMXSAAAXXXAXXAAAAAAXAMXMXXAASXMXMMSSMMMASAAAMMMXMXSMSXMASMXXAXSAMXXAXSXXAAMMMMAMMXSXXSAMAMM +SMSMXMAXXAAMASASASAMMSMMMMAMAAMASAMXMXMXMMMMAMXAAAAXMMSMSMMMSSSSXSSSMASXMSMMXMAMSSXAMSMMAMMMMXXAMSMSXSMSMSXXMSMMMMMSSMMMSMMSAAMSMSASXMMASXMA +SAAAAXXSMXSAAMAAAMMSAMAAAMAXMXMXMASASAXAMXAMSSSSSMSASAAAAAASMAMMMMAXXAMXMAAXXMASAAXMAAXMSMMASAMXSAASASAAXMMXSAAAMAAMXAMAXMASXSMXAMASXXXAMXXS +MXMXSXMMMMMMXMXMSMXMASXMSSMMMAXXSAMASXSAMSAMXAXMXAXMSSMMSMMSMMMMAMSMMMSSSSSXXXSXMMXXMMXMXASXSAMXSMSMAMMMMAMXSMSMSMSXSAMSSMASMMXMAMAMAAXSXMXM +SSMAXMMAAAXXAMMXAMAXAMAXAAXAASMMMASAMXMAXXAMMMMXMXMXMAMMMMMXAXAXXXAAXASAMXMMSMAMXXXSSXSASAMXSAMXXXAMAMSSSMMMMAXMXAXMMSXXAMXSXAASAMAMMMAMAMSX +SAMASASXSSSMXMASMSXSAMXMASMMMMAXSXMASXMAMSMMAAXSMMSSSMMASXMSSSMMSXMMMMXAAASAXXMAXMXMAAMMMAMAXAMAMSMXXSAXMAAAMSMSMMMXAMXXAXAMXSXSASXSMXMXAMAM +SAMASMMMXMAAAMMSAAMMAMXXXXAXASXMAMSAMMSMAAXSXSAAXASASXMMSAAAAXMASAMXAXXSMMMSSMXSXSAMMMMASMMXSSMSMAMSMMMSSSMSSXAXAMAMAMSSSMASMMAMMXMXMXMSMMAM +MMMMMMAXAMXSSSMMMMXSAMMSMXMSASAMXAMASAAMSMXXAMXMMXSAXMMXSMMMSMMMSAMASMMXAXAMXAXMASMSSXMMMAXXAXAXSMMAAAXAMAAMXMSMXXXSAMXAXSXMAMAMXAMSAMMAMMSS +XSASMSSSMSAXAAXMAAMSAAAAASXSXXMASASMMXXXAXSMXMAXXXMMMXMAMXXXXAXXMAMXAAASXMMSSSMMAMMMAASXSMMSMMMMXMSSXMMSAMXMAMAAMSMMMSMAMXMSMSMMSASMAMMASAAX +ASASAAXAXMMSSMMSMSMSSMMSSXMMASMXSASMAXXSASXMASASMMXSAMXSMMMMMMXSMMSMMMXMAAAAMASMAMAXSMMXAAAMXSAAAMAMMAAMMXMAMSMSMAAAXAMXMAAMXMXAMMXXMMSAMMSM +AMAMMMSMMXAAAAXXAMXMASMXMMAMAMAAMAMMXMXMXMXSAMSMXAMSAMAAXAAMASASAMXAXXMASMSXSAMSMMMXAXXXMMMMASXSXSASMMMSSSSMXSAMMSSMMXMASAMSAMMXSMMMMMMMSMMA +MMMMMAMXAMMSSMMSMSASAMXMASMMSSMSMXMAMSAMXMAMXXAMXXASMMSMSXMMAXASMMSAMMMAAXXAMAMXXASMSMSMMSAMXMAMXMAMXAAMMAAXAMAMXMXMAASMXMAMAXMXAMAAXAAASMMS +XASASXSXSSXAMMMSASAMAMAMAMXMXMXXMAMXXSXXXMASMSASMMMXMAMMXAMMSSMMXAXAMAMXSAMXMSAMMXSAMAAAASASMSXSAMAMMXMXMSMMXMAMXMAMSXMASMMSSMMSASMMSMMMSAAX +SXSASASMAMMMMSAMXMMSSMAMMSAMAMXMSMSMMMSMXMASAAAAXXASMXSASAXAMAASMXXMSXSXXMAMXMAXSAMXMXSMMSXMAAMMASXSXMMMXAMAMSMSAMSMMAMAAAXAMAXSAMXXMXSASMMS +SAMAMAMAAXXSAMXSAMXAAXXMAXASMMAXXMAXAAMMAMSSXMMMSAASAASAMAMSSSMMMMSMAAMMSSMASMXMMASXMXMAMSMMMMSSMMAAXMAAXMMAXAASMXMASXMSSMMSMSMMMMSAMAMXMAAS +MAMAMMMSMSXMASAXASMMSSSMXMAMXSMXSMAXXXAMXSAMMXSASMAMMMSAMXMAAAMAAAASMSMAXAMMXAMXMXMASMMAMXAMAAXXAMAMMSASXXSSSMXMMSMMMAMXAXAAXMAXSAXMMSSSXMXM +SXMASAAAMXASMMMMMMMXAXMAXMXMMAMASMMMSAMXMMXMMMMASMSXXASMMSAMXMMXMSMXSAMSSMMXXMSSXMMAXASXMSSSMSSXMMSXAMAXXAXAXXMMAAAASAMSXMSMMSAMMSSXMAAMMSSM +MAMAMMXMASXMAAAASASMSSMSMSAAAMMAMAAASMSXXSMMSAMXMAXMMXSMASXXMXSSMXAMMMXAMXAAASAMASMSMMMMAAAAAXAASAMXMXSMMXMXMMXMSSSMSAMXAXXXMXXAAMMAMMMMXAAM +SAMXXSMMAMASMMSMSASXMAAXASXMXXMSSSMMMXMXMXAMXAXSMMASMMXMASMMSAMXAMSSXMASXMMSSMASAMXXAXAMSMXMMMAXMASAMAMAXXMXXMAMAMXMXMMSMMMMMMMMMSSXMASXMSSM +MMXSAMAMASMAMXMAMAMASMMMASMXMAXAAXAXMAXASXSMSMMXXSAMAXXMAXAXMAMMXMAAMSAMAMXXAMMMMSSSMMXXAAASXSXSXXSAMASAMAXSSMXMMSAMXSAMAAXAAAAAMXMMSAMXXAAA +MAAMAMMSASXXMAXASASMMXXMXMAASAMMSMMASMSMXAMMSXAXMMMSMMSMMSSMXSSMMMXSMMASASMSMMXXXAXAAASXMSMSASASMMSASAMMSMAMAMAXXSASAMASXMXSSSSMSAMMMASMSSXM +MMSSMMASASMMMXSAMAXXSXMASMSMSAMAMASAAMAXMXMASMXMXSXAXAAAASAMXAAMXSAMAXXXAMAAMSMMMMSXMMMAXMAMAMAMMAMMMMXMAXXSSMSSXSAMXSMSASAMMAAMSASASAMXXAMA +MAAAXSXMASAXAAMXMAMMMXSASAMAMAMASMSMMSAMXSMMMMXSXMXSSSMMMSASMXXMAMASMMSMSMSMXAAAXXAXSMSMMMAMXMAMMSSSMMASMSMAMAXMAMXMXMAMAMSMMSMMSXMASASAMXAM +MMSSMSAXAMXMMSSXMASMAAXXSAMSMASXSAXMXMAMAXMMSSMMAMSXAAXAAMXXXSSMMSAMASAAAAAMXSMMSSSXSAAMMMXAXSMMMMXAASASAXMAMSMMAMASAMXMAMAXXAMXMSMXMMXXAAXS +MAMMAMXMMSXSAMXMSASMMMSMMAMXSXSXMMMSASXMMMSAAAASAMSMSMSMSMMMMAAAAMASMSMSMSMSAXAAAAMAMSAXAAMMMASXSSSSMMAMMMSASAAXSSMSXSXSXSMXXAXAXASAAMMMSSSM +MAXMSMXMAXXMMMSAMXXXXAXAXAAXAMXMXAAXMSMMSAMMSXMAMMXAAXAAAXAAXMSMMSAMXSXXAMAMASMMMMMAMAMSXSAMMAAXAAAMAMXMMXSMSXMMAAASAMAAXAXXXMMAXMMSMMAMAMAM +SMSAAAXASXXMMMAMMSSSMXSMMSMMXSAMXMXSASAAMAMAXXMASXMSMSMSMSSSSXXAMXMMMSAMSMSMMMXMAMMAMAXMAMMXMMMMMMMSSMMASASXMASMSMMMAMAMMMMSMSASMSMXXSXMXSAM +AAMXMMSAXASASMSXAAMAXXAAAXASMMAMSAMMXMMMSAMXMASASAAXAXXXAMXAMMMAXMASAMMXMAAMAMXXAASXSSSMMMSSMMXMAMXXAASAMXSXMAAMASXXAMASAAXAAAAXAAASMSASMSMS +MSMSMAMMAMMASAAMMXSAMXSMMSXMASMMAMXMMMAMXMXXSAMMXMMMMMAXASMMMAXAMXAMXXMAXSMSASMMMMMAAXAMXAAASAMSSSMSSMMASAMAMSMSASXSASXSMSXMXMMMMMSMASAMAXAX +AMAAMXMXAXMXMMMXMXMASAXAAMASMMSMAMMMASMSAMAMMMMMSSMSMASAMXAAMMSSMMMXAMXSMMXSXSAAAAMMMMMAMMXSMMMAAAMAAMSMMMSXMAXMASAMXMASAMXAASASXXXMXMMMMSXM +SMXMXSSSXSAMXXMSMMSAMASMMSAMXAAMAXXSXMMSAMASASAAXAAAAAXSXMSMSMAAXSSMXSAXAMASAMMSSSSXXAXSMSMXXSMMSMMSSXAXMAMXXXXMAMXMAXXMAMMXMSAXMMSSXXMSASAM +MAMXMMAAAMAXXAAXAAMASAMMMMXSMSSMXMAXASXSXMXSXSMSSMMMMMSMMMMMAMMSMAAMXSXXAMXXAAAMAAAMMMSMAAASAXSAXMXAXMMSMASMMSMMMSAMMSSMMMSXMMMMAXAXXSAMAMSM +XAAXAMSMMMAMSMAMMMSAMMMXAAXXXAAASMSMXXAXXMXMAMXMAMSXASXAASASASMMAMMMASASMMSSMMXMMMMXAXXMSMSMAMMMMMMMSMXXXXXXAAMXASMSAAMAMXMASAMSSSMMAAMMMMMX +SXSXSXXXAXMXXXAXAMMMSMMSMSMMMXAXMAMAMMMMXMAMAMAMMAMAXAMSMXASASMXAMXMASMSAAXXXMMXXSMSMXSMXMXXSXMMASAXAAXMXMXMSMXMXSASMXXAMAMAMAMAAAXAXMXMXAXA +XSAMXMMSMSMMMSXSXMASAMAAAAAAAMMSMXMASAAXASASXSSSMSASMMAAMSMMXMASAMXMASXSMMMMAMMSMSAAAMSASXAXMAMSASXSASMMMSAMASAAAMAMAMSSXSSSXSMMSMMSXXAMMXSM +SAMXMAAAAAXAXXAMXSMSASXMSSMMXSAAXMSASMXXAMXSXAAXAMAMXXSMXAXSXMMASAAXAMXXXMASAAAAAMSMXMMAMMSXSAMMMSXMAMAXASAMAXMSMMMMXMAMMXAMAAMXAXXXAMAXMMAM +AXMAMMSMSMSMMSSMAXXSMMAAAXAAAMMSMMMXSASAMXMMMSMMAMSSXAMXSMAMASXAXSMSSSMMSSMSXSXMSMXXSMMAMAXMMMMSAMAMXMMMMSMMMSAAMAAXXMMSSMAMMMMSXSASMSSMAMAA +MMSXSAAXAXAMAAAMASMMASMMMSMMMSAMAXSAMAMAXSXAAAXMXMMAMXSAMXMMAMMMMMMMMAASASMMMMMMMMMMSAMMMMXAAMAMASMMAMASXMXAXAXMSSSSXSAAAMXMXXAXAMAXXAAXXMAX +SAXAMASMXMXMMSAMAMAAAAXMASMAMMMSAMMASMMMMASMSSMMASMXMAMMMXSMXSAAAXAXXMMMASXMASAAAAAXMAMXAAMSMMAMXMASMSASAMMXSAMXAXXAAAMSMMSMMASMXMAMMMSMMSSM +XSMMSSMAXMMAMXXSXMSMMMMMSSXXXAXMXXSMMXAMXMXMAAASASXSMXSAXXSAASXSXSSSMXMMMMXSASMSSSSSMXMSMMAXMMSXXSMMAMASXMAMSXSMMSAMMMXMXAAASMMMAXSXAAXAMAAM +MXMAMAXMASAASXMXAAMMMSMXMMXMSMSXSXAMAXMSAXMSSSMMASAMMAAXAMMMMSAAAMMMXAAAAMMMMSAMXMAXMXMASMSMMAXSMMXMXMXMXMXMMMMAXMAMAXAXMMSAMXMSSSMMMXSAMSSM +SAMMSMMXAMMXSAAMMMAAMAAXASAAAAMAMSMMAASXMAXAAXXMXMAMMAMMXAASMMMMXMAAXMSMSMAAAMMMAMASXXMAXXMAMASAXMASASAMXXXASAMXMXSMMSMMAMXAMXMAXAXMSASAMXAX +SXSXMXMMSMMASXSXSSSSSMSSMXASMSMAMAMMMXSAMXMMSMXMASAMXSSMMSXSMAAXASMSSXAAMMSMSMXSAMXMASAXSASXMXSMMXMSMSASAMSMSASXMAXAXMXSSMSAMSMMSXMMMASMMSSM +SMMAMASMAAMASMMXMAXAAMAMMMMXMAXAMAXXMAMASXXXAXASXMMMXMAXAMMMMSXSMSAMXXMMSAXMXAAXXXXMAMMXMMMASMXMAAXMASMMAMAASAMAMAMMXMASAAMSAAXXSMMAMXMAMAMA +SAXMSAMXSMMSSXSMMMMMXMAXXAMXMMSMMMSSMMSAMMMMMMMMAAAMASMMXSASMMMSMMMSAMXAMAXAMMSXSSSMMMSAMXSAMXAXSXSXAXASMMMMMXSXMMMSAMXSAMXMSSSXMAXSSXSAMASX +XMMXMAXXMXSASXSAMXXSXMASXSMMXAAXAXXMAAMXSASAAASMSMMXMMAAXMMXAXAMXAMXMXMSSSMSXAMXXAAXAAMMSAMASMMMXMMMMSMMAASXSAMMMAASXMXMASXMAXMAXSMAAASASXSM +MSMMSSXAAXMASMSAMAMAMMASMMMSMSSSMSAMSMMXSASMSMSAMAAASXSMMMASMMMSSMSASXXMAXAXMASXMSMMMSSMMAMAMASAXAAAXSXMSMMAMXSAMMMSASAMASASXMASAAMXMMMMXMMA +XAAAAXSMMMMXMASMMAXMSMASMXAAAAAAAMXMAASAMMXAAAMAMMSMSAMAAXMSAXSAAXMAMSAMXMSMMSAXAAXXAMAXSSMMSAMXSSSSSXSAAAXSMASXSAASXMAMASAMSAAMMXXSAMXAAXSS +MSMMSXXXAXXSAMXXSASXMXSMXMSMSMMMMMASXSMXSMMSMSMMMAMXMXMSSSXSXMMMSMMMMXXXSAMXXMXMSMSMMSXMAMMXMASAXMMXMASXSSMMMXSXSMXSMSXMXMMMSMXSXMSMSXMSAMAM diff --git a/crates/day04/src/main.rs b/crates/day04/src/main.rs new file mode 100644 index 0000000..754ab21 --- /dev/null +++ b/crates/day04/src/main.rs @@ -0,0 +1,152 @@ +use std::{ + fs::File, + io::{BufRead, BufReader}, +}; + +fn main() { + let message = read_file("crates/day04/input.txt").unwrap(); + // --- Part One --- + let mut count = count_word(&message, "XMAS"); + println!("{count}"); + + // --- Part Two --- + count = count_x_pattern(&message, "MAS").unwrap(); + println!("{count}"); +} + +fn read_file(input: &str) -> Result>, Box> { + let file = File::open(input)?; + let reader = BufReader::new(file); + + let vec_of_vecs: Vec> = reader + .lines() // Split into lines + .map(|line| line.unwrap().chars().collect()) // Convert each line into Vec + .collect(); + + Ok(vec_of_vecs) +} + +fn floored_division(a: i32, b: i32) -> i32 { + let quotient = a / b; + if (a % b != 0) && ((a < 0) != (b < 0)) { + quotient - 1 + } else { + quotient + } +} + +fn count_x_pattern(grid: &[Vec], word: &str) -> Result { + let rows = grid.len(); + let cols = if rows > 0 { + grid[0].len() + } else { + return Err("Grid must be a valid grid".to_string()); + }; + let word_len = word.len(); + let mut count = 0; + + let bounded: usize = floored_division(word_len.try_into().unwrap(), 2) + .try_into() + .unwrap(); + let middle_char = word.chars().nth(bounded).unwrap(); + + let reverse = word.chars().rev().collect::(); + + for r in bounded..(rows - bounded) { + for c in bounded..(cols - bounded) { + if grid[r][c] == middle_char { + let mut first_diagonal = false; + let mut second_diagonal = false; + + // Check forward diagonal \ + if (0..word_len) + .all(|i| grid[r - bounded + i][c - bounded + i] == word.chars().nth(i).unwrap()) + { + first_diagonal = true; + } + // Check backward diagonal \ + else if (0..word_len).all(|i| { + grid[r - bounded + i][c - bounded + i] == reverse.chars().nth(i).unwrap() + }) { + first_diagonal = true; + } + + if first_diagonal { + // Check forward diagonal / + if (0..word_len).all(|i| { + grid[r + bounded - i][c - bounded + i] == word.chars().nth(i).unwrap() + }) { + second_diagonal = true; + } + // Check backward diagonal / + else if (0..word_len).all(|i| { + grid[r + bounded - i][c - bounded + i] == reverse.chars().nth(i).unwrap() + }) { + second_diagonal = true; + } + + if second_diagonal { + count += 1; + } + } + } + } + } + + Ok(count) +} + +fn count_word(grid: &[Vec], word: &str) -> usize { + let word_chars: Vec = word.chars().collect(); + let word_len = word_chars.len(); + let rows = grid.len(); + let cols = grid[0].len(); + let mut count = 0; + + let directions = vec![ + (0, 1), // Horizontal right + (0, -1), // Horizontal left + (1, 0), // Vertical down + (-1, 0), // Vertical up + (1, 1), // Diagonal down-right + (1, -1), // Diagonal down-left + (-1, 1), // Diagonal up-right + (-1, -1), // Diagonal up-left + ]; + + for row in 0..rows { + for col in 0..cols { + for (dx, dy) in &directions { + let mut found = true; + + for (i, _) in word_chars.iter().enumerate().take(word_len) { + let x = isize::try_from(row).unwrap() + isize::try_from(i).unwrap() * dx; + let y = isize::try_from(col).unwrap() + isize::try_from(i).unwrap() * dy; + + if x < 0 + || y < 0 + || x >= rows.try_into().unwrap() + || y >= cols.try_into().unwrap() + { + found = false; + break; + } + + let u_x: usize = usize::try_from(x).unwrap(); + let u_y: usize = usize::try_from(y).unwrap(); + + if grid[u_x][u_y] != word_chars[i] { + found = false; + break; + } + } + + if found { + count += 1; + } + } + } + } + + count +} diff --git a/crates/helpers/Cargo.toml b/crates/helpers/Cargo.toml new file mode 100644 index 0000000..cd84032 --- /dev/null +++ b/crates/helpers/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "helpers" +description = "a few helpers" +version = "0.1.0" +edition = "2021" + +[lints] +workspace = true + +[lib] +crate-type = ["lib"] diff --git a/crates/helpers/src/lib.rs b/crates/helpers/src/lib.rs new file mode 100644 index 0000000..71d9590 --- /dev/null +++ b/crates/helpers/src/lib.rs @@ -0,0 +1,14 @@ +use std::{ + fs::File, + io::{BufReader, Read}, +}; + +/// # Errors +/// Returns an error if reading file fails. +pub fn read_file(file_path: &str) -> Result> { + let file = File::open(file_path)?; + let mut reader = BufReader::new(file); + let mut content = String::new(); + reader.read_to_string(&mut content)?; + Ok(content) +}