Compare commits

...

76 Commits

Author SHA1 Message Date
Philippe Zwietering
121a9a02cb Day 2 aoc in progress 2026-01-09 17:00:16 +01:00
Philippe Zwietering
4ad2ec5240 Dag 1 advent of code 25 afgetikt 2026-01-05 16:48:32 +01:00
afe7131f31 Part 2 bruteforced, wasnt that hard and quick enough, day 18 2025-01-06 22:46:56 +01:00
5c8c774757 Day 18 part 1 aoc done 2025-01-06 17:32:32 +01:00
a2dbfb47da Advent of code day 17, rough doing the decompilation 2025-01-06 16:47:43 +01:00
6c949c0657 Dag 16 aoc af, vrij elegant en snel 2024-12-19 16:41:15 +01:00
98a82b523e wat heeft deze guy met plattegrondjes, aoc dag 15 2024-12-18 17:35:58 +01:00
0a039cb562 dag 14 aoc klaar, deel 2 gedaan met minimale safety factor 2024-12-18 11:33:16 +01:00
4ab100300d Dag 13 af, was makkelijk als je het gewoon direct uitrekende 2024-12-17 16:52:09 +01:00
1cf9bbcaca Assert instead of asssert 2024-12-17 11:07:10 +01:00
c972d803a4 Geen ongedefinieerd gedrag, enkel vergeten dat een plant onderdeel kan zijn van verschillende eigen hekkies 2024-12-17 11:06:07 +01:00
4e3e081db4 Dag 9 aoc, zonder trees maar gewoon met een vieze O(n^3) vector 2024-12-16 15:16:16 +01:00
58b80a84a3 Dag 11 aoc done, ik vind dp stom 2024-12-11 17:43:00 +01:00
764850905e Meer aan default toegevoegd 2024-12-11 14:09:05 +01:00
455be27007 Dag 10 aoc, deel 2 was makkelijker dan deel 1 2024-12-11 14:01:17 +01:00
569f2ff6d9 Bezig met dag 9 aoc 2024-12-10 17:24:52 +01:00
9e513412c1 Dag 7 aoc klaar, basically een soort 3-sat 2024-12-10 15:22:12 +01:00
05998b3b4f Poging tot dag 7 aoc, hele rare bug in rust lijkt het wel bijna, krijg niet eens een lijst normaal gevouwen 2024-12-09 23:38:57 +01:00
266e0cf180 Start van dag 9 aoc, nog geen inhoud 2024-12-09 17:29:40 +01:00
91bfb654c3 Dag 8 aoc voltooid, opeens heel eenvoudig 2024-12-09 16:24:55 +01:00
14c3e3006c Dag 6 aoc, duurt een minuut dus kan wrs slimmer 2024-12-06 17:26:32 +01:00
a950017272 Deel 1 van dag 5 aoc af, verder op pc 2024-12-05 20:56:19 +01:00
968961e58b dag 4 aoc, deed meer dan verwacht werd, wat ervoor zorgde dat ik teveel kruizen telde 2024-12-04 17:12:18 +01:00
bbba418f55 dag 3 aoc, eindelijk parser werkend, daadwerkelijke opgave was niet zo moeilijk 2024-12-04 14:48:27 +01:00
273841b7c8 Day 2 first part done, aoc 2020 2024-12-02 17:39:23 +01:00
2c038b2760 Completed day 1 of 2020 aoc 2024-12-02 15:56:34 +01:00
9c227df6e3 Default advent of code rust main 2024-12-02 14:24:02 +01:00
32fa833654 Dag 2 voltooid, niet prachtig, maar het voldoet 2024-12-02 13:16:26 +01:00
0dc8d476a6 A new advent of code, day 1 finished 2024-12-01 22:44:52 +01:00
fb41ac47f1 Ëerste poging projecteuler 90 2024-10-28 13:41:26 +01:00
a7d13bd73c Day 8 2023 aoc part 1 solved, part 2 naive attempt that is very much too slow 2024-02-13 09:44:52 +01:00
1866aefc5b Day 5 aoc, stuck on b, works on test input, enters infinite loop on one entry of the real input 2023-12-07 18:27:35 +01:00
e73fc141fd Day 7 aoc was a breeze 2023-12-07 18:26:28 +01:00
5a34125164 Finished complete day 6 aoc, was way easier than previous day 2023-12-06 11:39:07 +01:00
6f8d539c0c Finished day 4 aoc 2023, just in time for the end of the day 2023-12-04 16:53:45 +01:00
fef86c8b84 Day 4 aoc part 1 finished, almost caught up now 2023-12-04 16:32:37 +01:00
b0f8da2b5d Finished day 3 aoc, going smooth so far, fearing for the next days 2023-12-04 15:35:14 +01:00
1d6b0f2468 aoc day 3 part 1 done, annoying bug: you need to add a number if it's still counting up per line 2023-12-04 14:49:33 +01:00
a671d0abaf aoc day 2 finished, part 2 was almost easier than part 1 2023-12-04 11:36:23 +01:00
048c66102b Finished day 1 aoc 2023 2023-12-04 10:31:19 +01:00
c414be2200 Aoc 2023 day 1 part 1 finished, warming my fingers 2023-12-04 09:00:17 +01:00
2a60712f44 WIP aoc 2015 day 9 2023-12-04 08:46:18 +01:00
1910caab51 If it works it works, the fugliest code ever hehe 2023-11-29 15:50:26 +01:00
8e277d86f5 Finally finished the puzzle (aoc day 7 2015); I firmly believe that the circuit can do a whole lot more than what is described in the puzzle text 2023-11-29 15:08:10 +01:00
1884a9075d Finished day 6 aoc 2015 2023-11-08 16:17:07 +01:00
e242d0b32f Finished part 1 day 6 aoc 2015, brute force is fast here?? 2023-11-08 15:56:07 +01:00
a6786e6160 Finished day 5 aoc 2015, but part 2 is faulty, I just guessed one higher than my outcome and somehow that worked... 2023-11-07 16:11:12 +01:00
57d678de5c Day 4 2015 advent of code 2023-10-13 14:27:00 +02:00
d644336030 Finished aoc year 2015 day 3 2023-10-12 12:11:50 +02:00
c009060c48 Finished first year day 2 aoc 2023-10-12 10:57:25 +02:00
941da35416 Started on aoc 2015, finished day 1 2023-10-11 13:16:21 +02:00
c1ac8c30e5 Ran autoformatter 2023-10-11 12:49:53 +02:00
4f1a3b8e7a Priority queue added on aoc 15 2023-09-19 16:32:57 +02:00
7a0bc59bd2 Idee op papier voor aoc 15 dat zou moeten werken 2023-09-18 23:51:58 +02:00
fdf044144f Finished PE 099, usings logs it was quite easy 2023-06-28 15:31:56 +02:00
b4f2968846 Finished PE 097, easy introduction to mod 2023-06-28 12:58:09 +02:00
3d4e350b89 WIP PE 095, getting bullied by the borrow checker 2023-06-27 17:11:35 +02:00
419269d0a0 Finished PE 94, a tale of floats and integers 2023-06-27 13:29:55 +02:00
958ee4651e Finished PE 092 with brute force, not hard 2023-06-26 16:01:39 +02:00
863f051f7d Finished PE 091, fairly straightforward, just brute-forced 2023-06-26 15:38:35 +02:00
10d9d26c5e Finished abc051 b very dirty, first look at c 2023-05-05 16:58:48 +02:00
3abb97ae34 Started on ABC051, finished a 2023-05-01 17:15:01 +02:00
adb33aa593 Finished abc050 2023-05-01 15:49:18 +02:00
5d6af06d5b Merge branch 'master' of https://git.zwietering.eu/flip/contests 2023-04-28 17:08:03 +02:00
963340d14a abc050 c finished 2023-04-28 17:06:07 +02:00
e1dd7bee6a Added Cargo.lock to gitignore 2023-04-27 21:00:19 +02:00
ff59a34ac1 Started on ABC 50 2023-04-18 16:58:49 +02:00
ea301ea3cb Started out with PE 090, but it's pretty hard 2023-04-16 21:46:58 +02:00
a28244231a PE 088 WIP, hard problem 2023-04-16 21:21:18 +02:00
e7d501f936 PE 088 in progress, hard problem 2023-04-16 16:53:12 +02:00
ce8daa9e3d Merge branch 'master' of ssh://git.pzwietering.nl:55555/flip/contests 2023-04-08 22:41:41 +02:00
Philippe Zwietering
49784eea22 That was a bitch to debug damn, but PE 089 finished now 2023-03-30 09:23:37 +02:00
Philippe Zwietering
091ef1f518 Apparently a bug in PE 089 but can't for the life of me figure out what goes wrong 2023-03-20 17:02:05 +01:00
fedb474b4b Finished projecteuler 086 with ugly solution but hey it works 2023-03-14 19:00:49 +01:00
Philippe Zwietering
5bb1e5b31c Finished projecteuler 087 quite quickly 2023-03-14 12:50:59 +01:00
Philippe Zwietering
3af4295850 Bug fixed in projecteuler in base.rs 2023-03-14 12:50:06 +01:00
196 changed files with 31859 additions and 48 deletions

2
.gitignore vendored
View File

@@ -181,3 +181,5 @@ cabal.project.local~
# VS code
.vscode/
# rust stuff
Cargo.lock

View File

@@ -0,0 +1,8 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,32 @@
fn main() {
println!("Hello, this is Patrick!");
let input_txt = include_str!("../input.txt");
let mut floor = 0;
for parenthesis in input_txt.chars() {
match parenthesis {
'(' => floor += 1,
')' => floor -= 1,
_ => (),
}
}
println!("Santa needs to go to floor {}", floor);
let input_txt = include_str!("../input.txt");
let mut floor = 0;
for (idx, parenthesis) in input_txt.chars().enumerate() {
match parenthesis {
'(' => floor += 1,
')' => floor -= 1,
_ => (),
}
if floor == -1 {
println!("Santa first reaches the basement at position {}", idx + 1);
break;
}
}
}

View File

@@ -0,0 +1,9 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.3"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
use nom::{
bytes::complete::tag,
character::complete::{self, newline},
combinator::map,
multi::separated_list1,
sequence::separated_pair,
IResult,
};
fn parse_input(input: &str) -> IResult<&str, Vec<(u64, u64, u64)>> {
let (input, dimensions) = separated_list1(
newline,
map(
separated_pair(
complete::u64,
tag("x"),
separated_pair(complete::u64, tag("x"), complete::u64),
),
|(x, (y, z))| (x, y, z),
),
)(input)?;
Ok((input, dimensions))
}
fn solve_first(dimensions: &[(u64, u64, u64)]) -> u64 {
dimensions
.iter()
.map(|&(l, w, h)| {
2 * l * w + 2 * w * h + 2 * l * h + std::cmp::min(l * w, std::cmp::min(w * h, h * l))
})
.sum()
}
fn solve_second(dimensions: &[(u64, u64, u64)]) -> u64 {
dimensions
.iter()
.map(|&(l, w, h)| smallest_perimeter(l, w, h) + l * w * h)
.sum()
}
fn smallest_perimeter(l: u64, w: u64, h: u64) -> u64 {
(l + w + h - std::cmp::max(l, std::cmp::max(w, h))) * 2
}
fn main() {
println!("Hello, this is Patrick!");
let input_txt = include_str!("../input.txt");
let (_rest, dimensions) = parse_input(input_txt).unwrap_or(("", vec![]));
let first_result = solve_first(&dimensions[..]);
println!(
"The elves will need {} square feet of wrapping paper",
first_result
);
let second_result = solve_second(&dimensions[..]);
println!("The elves will need {} feet of ribbon", second_result);
}

View File

@@ -0,0 +1,8 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,69 @@
use std::{borrow::BorrowMut, collections::HashSet};
fn solve_first(input: &str) -> usize {
let mut coord = (0, 0);
let mut visited = HashSet::new();
visited.insert(coord);
for c in input.chars() {
match c {
'>' => coord.0 += 1,
'<' => coord.0 -= 1,
'^' => coord.1 += 1,
'v' => coord.1 -= 1,
_ => (),
}
visited.insert(coord);
}
visited.len()
}
fn solve_second(input: &str) -> usize {
let mut santa_coord = (0, 0);
let mut robo_coord = (0, 0);
let mut visited = HashSet::new();
visited.insert(santa_coord);
for (idx, c) in input.chars().enumerate() {
let coord = if idx % 2 == 0 {
santa_coord.borrow_mut()
} else {
robo_coord.borrow_mut()
};
match c {
'>' => coord.0 += 1,
'<' => coord.0 -= 1,
'^' => coord.1 += 1,
'v' => coord.1 -= 1,
_ => (),
}
visited.insert(coord.clone());
}
visited.len()
}
fn main() {
println!("Hello, this is Patrick!");
let input_txt = include_str!("../input.txt");
let result_first = solve_first(input_txt);
println!(
"The number of houses that receive at least one present is {}",
result_first
);
let result_second = solve_second(input_txt);
println!(
"The number of houses that receive at least one present in the year after is {}",
result_second
);
}

View File

@@ -0,0 +1,9 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
md5 = "0.7.0"

View File

@@ -0,0 +1,47 @@
const INPUT: &str = "iwrupvqb";
fn solve(input: &str, desired_start: &str) -> u64 {
let mut postfix = 1;
loop {
let digest = md5::compute(format!("{input}{postfix}"));
let digest = format!("{:x?}", digest);
if digest.starts_with(desired_start) {
return postfix;
}
postfix += 1;
}
}
fn main() {
println!("Hello, this is Patrick!");
let first_result = solve(INPUT, "00000");
println!(
"Santa needs to use a safer hashing, but his result is: {}",
first_result
);
let second_result = solve(INPUT, "000000");
println!(
"The extra zero costs a lot and has the answer: {}",
second_result
);
}
#[test]
fn test_first1() {
let s = solve("abcdef", "00000");
assert_eq!(s, 609043);
}
#[test]
fn test_first2() {
let s = solve("pqrstuv", "00000");
assert_eq!(s, 1048970);
}

View File

@@ -0,0 +1,8 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,159 @@
use std::collections::HashSet;
fn solve_first(input: &str) -> usize {
let mut result = 0;
for s in input.lines() {
if is_nice(s) {
result += 1;
}
}
result
}
fn is_nice(string: &str) -> bool {
let mut vowels = 0;
let mut iter = string.chars();
let (mut a, mut b) = (' ', iter.next().unwrap_or(' '));
if b == 'a' || b == 'e' || b == 'i' || b == 'o' || b == 'u' {
vowels += 1;
}
let mut doubles = false;
let mut no_evil_substrings = true;
for c in iter {
a = b;
b = c;
if a == b {
doubles = true;
}
if (a, b) == ('a', 'b')
|| (a, b) == ('c', 'd')
|| (a, b) == ('p', 'q')
|| (a, b) == ('x', 'y')
{
no_evil_substrings = false;
}
if b == 'a' || b == 'e' || b == 'i' || b == 'o' || b == 'u' {
vowels += 1;
}
}
doubles && no_evil_substrings && vowels >= 3
}
fn solve_second(input: &str) -> usize {
let mut result = 0;
for s in input.lines() {
if is_nice2(s) {
result += 1;
}
}
result
}
fn is_nice2(line: &str) -> bool {
let mut iter = line.chars();
let (mut a, mut b, mut c) = (' ', iter.next().unwrap_or(' '), iter.next().unwrap_or(' '));
let mut double_pair = false;
let mut trio = false;
let mut visited_pairs = HashSet::new();
for d in iter {
a = b;
b = c;
c = d;
trio |= a == c;
visited_pairs.insert((a, b));
if let Some(_) = visited_pairs.get(&(b, c)) {
if !(a == b && b == c) {
double_pair = true;
}
}
}
double_pair && trio
}
fn main() {
println!("Hello, this is Patrick!");
let input_txt = include_str!("../input.txt");
let first_result = solve_first(input_txt);
println!("The number of nice strings is {}", first_result);
let second_result = solve_second(input_txt);
println!(
"The number of new and improved nice strings is {}",
second_result
);
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn aaa_is_nice() {
assert!(is_nice("aaa"));
}
#[test]
fn ugknbfddgicrmopn_is_nice() {
assert!(is_nice("ugknbfddgicrmopn"));
}
#[test]
fn jchzalrnumimnmhp_is_naughty() {
assert!(!is_nice("jchzalrnumimnmhp"));
}
#[test]
fn haegwjzuvuyypxyu_is_naughty() {
assert!(!is_nice("haegwjzuvuyypxyu"));
}
#[test]
fn dvszwmarrgswjxmb_is_naughty() {
assert!(!is_nice("dvszwmarrgswjxmb"));
}
#[test]
fn qjhvhtzxzqqjkmpb_is_nice2() {
assert!(is_nice2("qjhvhtzxzqqjkmpb"));
}
#[test]
fn xxyxx_is_nice2() {
assert!(is_nice2("xxyxx"));
}
#[test]
fn uurcxstgmygtbstg_is_naughty2() {
assert!(!is_nice2("uurcxstgmygtbstg"));
}
#[test]
fn ieodomkazucvgmuy_is_naughty2() {
assert!(!is_nice2("ieodomkazucvgmuy"));
}
#[test]
fn aaa_is_naughty2() {
assert!(!is_nice2("aaa"));
}
}

View File

@@ -0,0 +1,9 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.3"

View File

@@ -0,0 +1,300 @@
turn on 887,9 through 959,629
turn on 454,398 through 844,448
turn off 539,243 through 559,965
turn off 370,819 through 676,868
turn off 145,40 through 370,997
turn off 301,3 through 808,453
turn on 351,678 through 951,908
toggle 720,196 through 897,994
toggle 831,394 through 904,860
toggle 753,664 through 970,926
turn off 150,300 through 213,740
turn on 141,242 through 932,871
toggle 294,259 through 474,326
toggle 678,333 through 752,957
toggle 393,804 through 510,976
turn off 6,964 through 411,976
turn off 33,572 through 978,590
turn on 579,693 through 650,978
turn on 150,20 through 652,719
turn off 782,143 through 808,802
turn off 240,377 through 761,468
turn off 899,828 through 958,967
turn on 613,565 through 952,659
turn on 295,36 through 964,978
toggle 846,296 through 969,528
turn off 211,254 through 529,491
turn off 231,594 through 406,794
turn off 169,791 through 758,942
turn on 955,440 through 980,477
toggle 944,498 through 995,928
turn on 519,391 through 605,718
toggle 521,303 through 617,366
turn off 524,349 through 694,791
toggle 391,87 through 499,792
toggle 562,527 through 668,935
turn off 68,358 through 857,453
toggle 815,811 through 889,828
turn off 666,61 through 768,87
turn on 27,501 through 921,952
turn on 953,102 through 983,471
turn on 277,552 through 451,723
turn off 64,253 through 655,960
turn on 47,485 through 734,977
turn off 59,119 through 699,734
toggle 407,898 through 493,955
toggle 912,966 through 949,991
turn on 479,990 through 895,990
toggle 390,589 through 869,766
toggle 593,903 through 926,943
toggle 358,439 through 870,528
turn off 649,410 through 652,875
turn on 629,834 through 712,895
toggle 254,555 through 770,901
toggle 641,832 through 947,850
turn on 268,448 through 743,777
turn off 512,123 through 625,874
turn off 498,262 through 930,811
turn off 835,158 through 886,242
toggle 546,310 through 607,773
turn on 501,505 through 896,909
turn off 666,796 through 817,924
toggle 987,789 through 993,809
toggle 745,8 through 860,693
toggle 181,983 through 731,988
turn on 826,174 through 924,883
turn on 239,228 through 843,993
turn on 205,613 through 891,667
toggle 867,873 through 984,896
turn on 628,251 through 677,681
toggle 276,956 through 631,964
turn on 78,358 through 974,713
turn on 521,360 through 773,597
turn off 963,52 through 979,502
turn on 117,151 through 934,622
toggle 237,91 through 528,164
turn on 944,269 through 975,453
toggle 979,460 through 988,964
turn off 440,254 through 681,507
toggle 347,100 through 896,785
turn off 329,592 through 369,985
turn on 931,960 through 979,985
toggle 703,3 through 776,36
toggle 798,120 through 908,550
turn off 186,605 through 914,709
turn off 921,725 through 979,956
toggle 167,34 through 735,249
turn on 726,781 through 987,936
toggle 720,336 through 847,756
turn on 171,630 through 656,769
turn off 417,276 through 751,500
toggle 559,485 through 584,534
turn on 568,629 through 690,873
toggle 248,712 through 277,988
toggle 345,594 through 812,723
turn off 800,108 through 834,618
turn off 967,439 through 986,869
turn on 842,209 through 955,529
turn on 132,653 through 357,696
turn on 817,38 through 973,662
turn off 569,816 through 721,861
turn on 568,429 through 945,724
turn on 77,458 through 844,685
turn off 138,78 through 498,851
turn on 136,21 through 252,986
turn off 2,460 through 863,472
turn on 172,81 through 839,332
turn on 123,216 through 703,384
turn off 879,644 through 944,887
toggle 227,491 through 504,793
toggle 580,418 through 741,479
toggle 65,276 through 414,299
toggle 482,486 through 838,931
turn off 557,768 through 950,927
turn off 615,617 through 955,864
turn on 859,886 through 923,919
turn on 391,330 through 499,971
toggle 521,835 through 613,847
turn on 822,787 through 989,847
turn on 192,142 through 357,846
turn off 564,945 through 985,945
turn off 479,361 through 703,799
toggle 56,481 through 489,978
turn off 632,991 through 774,998
toggle 723,526 through 945,792
turn on 344,149 through 441,640
toggle 568,927 through 624,952
turn on 621,784 through 970,788
toggle 665,783 through 795,981
toggle 386,610 through 817,730
toggle 440,399 through 734,417
toggle 939,201 through 978,803
turn off 395,883 through 554,929
turn on 340,309 through 637,561
turn off 875,147 through 946,481
turn off 945,837 through 957,922
turn off 429,982 through 691,991
toggle 227,137 through 439,822
toggle 4,848 through 7,932
turn off 545,146 through 756,943
turn on 763,863 through 937,994
turn on 232,94 through 404,502
turn off 742,254 through 930,512
turn on 91,931 through 101,942
toggle 585,106 through 651,425
turn on 506,700 through 567,960
turn off 548,44 through 718,352
turn off 194,827 through 673,859
turn off 6,645 through 509,764
turn off 13,230 through 821,361
turn on 734,629 through 919,631
toggle 788,552 through 957,972
toggle 244,747 through 849,773
turn off 162,553 through 276,887
turn off 569,577 through 587,604
turn off 799,482 through 854,956
turn on 744,535 through 909,802
toggle 330,641 through 396,986
turn off 927,458 through 966,564
toggle 984,486 through 986,913
toggle 519,682 through 632,708
turn on 984,977 through 989,986
toggle 766,423 through 934,495
turn on 17,509 through 947,718
turn on 413,783 through 631,903
turn on 482,370 through 493,688
turn on 433,859 through 628,938
turn off 769,549 through 945,810
turn on 178,853 through 539,941
turn off 203,251 through 692,433
turn off 525,638 through 955,794
turn on 169,70 through 764,939
toggle 59,352 through 896,404
toggle 143,245 through 707,320
turn off 103,35 through 160,949
toggle 496,24 through 669,507
turn off 581,847 through 847,903
turn on 689,153 through 733,562
turn on 821,487 through 839,699
turn on 837,627 through 978,723
toggle 96,748 through 973,753
toggle 99,818 through 609,995
turn on 731,193 through 756,509
turn off 622,55 through 813,365
turn on 456,490 through 576,548
turn on 48,421 through 163,674
turn off 853,861 through 924,964
turn off 59,963 through 556,987
turn on 458,710 through 688,847
toggle 12,484 through 878,562
turn off 241,964 through 799,983
turn off 434,299 through 845,772
toggle 896,725 through 956,847
turn on 740,289 through 784,345
turn off 395,840 through 822,845
turn on 955,224 through 996,953
turn off 710,186 through 957,722
turn off 485,949 through 869,985
turn on 848,209 through 975,376
toggle 221,241 through 906,384
turn on 588,49 through 927,496
turn on 273,332 through 735,725
turn on 505,962 through 895,962
toggle 820,112 through 923,143
turn on 919,792 through 978,982
toggle 489,461 through 910,737
turn off 202,642 through 638,940
turn off 708,953 through 970,960
toggle 437,291 through 546,381
turn on 409,358 through 837,479
turn off 756,279 through 870,943
turn off 154,657 through 375,703
turn off 524,622 through 995,779
toggle 514,221 through 651,850
toggle 808,464 through 886,646
toggle 483,537 through 739,840
toggle 654,769 through 831,825
turn off 326,37 through 631,69
turn off 590,570 through 926,656
turn off 881,913 through 911,998
turn on 996,102 through 998,616
turn off 677,503 through 828,563
turn on 860,251 through 877,441
turn off 964,100 through 982,377
toggle 888,403 through 961,597
turn off 632,240 through 938,968
toggle 731,176 through 932,413
turn on 5,498 through 203,835
turn on 819,352 through 929,855
toggle 393,813 through 832,816
toggle 725,689 through 967,888
turn on 968,950 through 969,983
turn off 152,628 through 582,896
turn off 165,844 through 459,935
turn off 882,741 through 974,786
turn off 283,179 through 731,899
toggle 197,366 through 682,445
turn on 106,309 through 120,813
toggle 950,387 through 967,782
turn off 274,603 through 383,759
turn off 155,665 through 284,787
toggle 551,871 through 860,962
turn off 30,826 through 598,892
toggle 76,552 through 977,888
turn on 938,180 through 994,997
toggle 62,381 through 993,656
toggle 625,861 through 921,941
turn on 685,311 through 872,521
turn on 124,934 through 530,962
turn on 606,379 through 961,867
turn off 792,735 through 946,783
turn on 417,480 through 860,598
toggle 178,91 through 481,887
turn off 23,935 through 833,962
toggle 317,14 through 793,425
turn on 986,89 through 999,613
turn off 359,201 through 560,554
turn off 729,494 through 942,626
turn on 204,143 through 876,610
toggle 474,97 through 636,542
turn off 902,924 through 976,973
turn off 389,442 through 824,638
turn off 622,863 through 798,863
turn on 840,622 through 978,920
toggle 567,374 through 925,439
turn off 643,319 through 935,662
toggle 185,42 through 294,810
turn on 47,124 through 598,880
toggle 828,303 through 979,770
turn off 174,272 through 280,311
turn off 540,50 through 880,212
turn on 141,994 through 221,998
turn on 476,695 through 483,901
turn on 960,216 through 972,502
toggle 752,335 through 957,733
turn off 419,713 through 537,998
toggle 772,846 through 994,888
turn on 881,159 through 902,312
turn off 537,651 through 641,816
toggle 561,947 through 638,965
turn on 368,458 through 437,612
turn on 290,149 through 705,919
turn on 711,918 through 974,945
toggle 916,242 through 926,786
toggle 522,272 through 773,314
turn on 432,897 through 440,954
turn off 132,169 through 775,380
toggle 52,205 through 693,747
toggle 926,309 through 976,669
turn off 838,342 through 938,444
turn on 144,431 through 260,951
toggle 780,318 through 975,495
turn off 185,412 through 796,541
turn on 879,548 through 892,860
turn on 294,132 through 460,338
turn on 823,500 through 899,529
turn off 225,603 through 483,920
toggle 717,493 through 930,875
toggle 534,948 through 599,968
turn on 522,730 through 968,950
turn off 102,229 through 674,529

View File

@@ -0,0 +1,110 @@
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{self, multispace1},
multi::separated_list1,
sequence::tuple,
IResult, Parser,
};
const GRID_MAX: usize = 1000;
enum LightSwitch {
On,
Off,
Toggle,
}
struct Coord<T> {
x: T,
y: T,
}
struct Instruction<T> {
switch: LightSwitch,
first_coord: Coord<T>,
second_coord: Coord<T>,
}
fn parse_input(input: &str) -> IResult<&str, Vec<Instruction<i64>>> {
let (input, result) = separated_list1(
multispace1,
tuple((
alt((tag("toggle "), tag("turn on "), tag("turn off "))),
complete::i64,
tag(","),
complete::i64,
tag(" through "),
complete::i64,
tag(","),
complete::i64,
))
.map(|(switch, x_1, _, y_1, _, x_2, _, y_2)| Instruction {
switch: match switch {
"toggle " => LightSwitch::Toggle,
"turn on " => LightSwitch::On,
"turn off " => LightSwitch::Off,
_ => unreachable!(),
},
first_coord: Coord { x: x_1, y: y_1 },
second_coord: Coord { x: x_2, y: y_2 },
}),
)(input)?;
Ok((input, result))
}
fn solve_first(input: &[Instruction<i64>]) -> usize {
let mut lights = vec![false; GRID_MAX * GRID_MAX];
for instruction in input.iter() {
for y in instruction.first_coord.y..=instruction.second_coord.y {
for x in instruction.first_coord.x..=instruction.second_coord.x {
lights[x as usize + y as usize * GRID_MAX] = match instruction.switch {
LightSwitch::Toggle => !lights[x as usize + y as usize * GRID_MAX],
LightSwitch::Off => false,
LightSwitch::On => true,
}
}
}
}
lights.into_iter().fold(0, |acc, e| match e {
true => acc + 1,
false => acc,
})
}
fn solve_second(input: &[Instruction<i64>]) -> i64 {
let mut lights = vec![0; GRID_MAX * GRID_MAX];
for instruction in input.iter() {
for y in instruction.first_coord.y..=instruction.second_coord.y {
for x in instruction.first_coord.x..=instruction.second_coord.x {
let pos = x as usize + y as usize * GRID_MAX;
lights[pos] = match instruction.switch {
LightSwitch::Toggle => lights[pos] + 2,
LightSwitch::Off => std::cmp::max(0, lights[pos] - 1),
LightSwitch::On => lights[pos] + 1,
}
}
}
}
lights.into_iter().sum()
}
fn main() {
println!("Hello, this is Patrick!");
let input_txt = include_str!("../input.txt");
let (_, light_instructions) = parse_input(input_txt).unwrap();
let first_result = solve_first(&light_instructions[..]);
println!("The number of lit light is {}", first_result);
let second_result = solve_second(&light_instructions[..]);
println!("The total brightness is {}", second_result);
}

View File

@@ -0,0 +1,10 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.3"
petgraph = "0.6.4"

View File

@@ -0,0 +1,339 @@
NOT dq -> dr
kg OR kf -> kh
ep OR eo -> eq
44430 -> b
NOT gs -> gt
dd OR do -> dp
eg AND ei -> ej
y AND ae -> ag
jx AND jz -> ka
lf RSHIFT 2 -> lg
z AND aa -> ac
dy AND ej -> el
bj OR bi -> bk
kk RSHIFT 3 -> km
NOT cn -> co
gn AND gp -> gq
cq AND cs -> ct
eo LSHIFT 15 -> es
lg OR lm -> ln
dy OR ej -> ek
NOT di -> dj
1 AND fi -> fj
kf LSHIFT 15 -> kj
NOT jy -> jz
NOT ft -> fu
fs AND fu -> fv
NOT hr -> hs
ck OR cl -> cm
jp RSHIFT 5 -> js
iv OR jb -> jc
is OR it -> iu
ld OR le -> lf
NOT fc -> fd
NOT dm -> dn
bn OR by -> bz
aj AND al -> am
cd LSHIFT 15 -> ch
jp AND ka -> kc
ci OR ct -> cu
gv AND gx -> gy
de AND dk -> dm
x RSHIFT 5 -> aa
et RSHIFT 2 -> eu
x RSHIFT 1 -> aq
ia OR ig -> ih
bk LSHIFT 1 -> ce
y OR ae -> af
NOT ca -> cb
e AND f -> h
ia AND ig -> ii
ck AND cl -> cn
NOT jh -> ji
z OR aa -> ab
1 AND en -> eo
ib AND ic -> ie
NOT eh -> ei
iy AND ja -> jb
NOT bb -> bc
ha OR gz -> hb
1 AND cx -> cy
NOT ax -> ay
ev OR ew -> ex
bn RSHIFT 2 -> bo
er OR es -> et
eu OR fa -> fb
jp OR ka -> kb
ea AND eb -> ed
k AND m -> n
et RSHIFT 3 -> ev
et RSHIFT 5 -> ew
hz RSHIFT 1 -> is
ki OR kj -> kk
NOT h -> i
lv LSHIFT 15 -> lz
as RSHIFT 1 -> bl
hu LSHIFT 15 -> hy
iw AND ix -> iz
lf RSHIFT 1 -> ly
fp OR fv -> fw
1 AND am -> an
ap LSHIFT 1 -> bj
u LSHIFT 1 -> ao
b RSHIFT 5 -> f
jq AND jw -> jy
iu RSHIFT 3 -> iw
ih AND ij -> ik
NOT iz -> ja
de OR dk -> dl
iu OR jf -> jg
as AND bd -> bf
b RSHIFT 3 -> e
jq OR jw -> jx
iv AND jb -> jd
cg OR ch -> ci
iu AND jf -> jh
lx -> a
1 AND cc -> cd
ly OR lz -> ma
NOT el -> em
1 AND bh -> bi
fb AND fd -> fe
lf OR lq -> lr
bn RSHIFT 3 -> bp
bn AND by -> ca
af AND ah -> ai
cf LSHIFT 1 -> cz
dw OR dx -> dy
gj AND gu -> gw
jg AND ji -> jj
jr OR js -> jt
bl OR bm -> bn
gj RSHIFT 2 -> gk
cj OR cp -> cq
gj OR gu -> gv
b OR n -> o
o AND q -> r
bi LSHIFT 15 -> bm
dy RSHIFT 1 -> er
cu AND cw -> cx
iw OR ix -> iy
hc OR hd -> he
0 -> c
db OR dc -> dd
kk RSHIFT 2 -> kl
eq LSHIFT 1 -> fk
dz OR ef -> eg
NOT ed -> ee
lw OR lv -> lx
fw AND fy -> fz
dz AND ef -> eh
jp RSHIFT 3 -> jr
lg AND lm -> lo
ci RSHIFT 2 -> cj
be AND bg -> bh
lc LSHIFT 1 -> lw
hm AND ho -> hp
jr AND js -> ju
1 AND io -> ip
cm AND co -> cp
ib OR ic -> id
NOT bf -> bg
fo RSHIFT 5 -> fr
ip LSHIFT 15 -> it
jt AND jv -> jw
jc AND je -> jf
du OR dt -> dv
NOT fx -> fy
aw AND ay -> az
ge LSHIFT 15 -> gi
NOT ak -> al
fm OR fn -> fo
ff AND fh -> fi
ci RSHIFT 5 -> cl
cz OR cy -> da
NOT ey -> ez
NOT ju -> jv
NOT ls -> lt
kk AND kv -> kx
NOT ii -> ij
kl AND kr -> kt
jk LSHIFT 15 -> jo
e OR f -> g
NOT bs -> bt
hi AND hk -> hl
hz OR ik -> il
ek AND em -> en
ao OR an -> ap
dv LSHIFT 1 -> ep
an LSHIFT 15 -> ar
fo RSHIFT 1 -> gh
NOT im -> in
kk RSHIFT 1 -> ld
hw LSHIFT 1 -> iq
ec AND ee -> ef
hb LSHIFT 1 -> hv
kb AND kd -> ke
x AND ai -> ak
dd AND do -> dq
aq OR ar -> as
iq OR ip -> ir
dl AND dn -> do
iu RSHIFT 5 -> ix
as OR bd -> be
NOT go -> gp
fk OR fj -> fl
jm LSHIFT 1 -> kg
NOT cv -> cw
dp AND dr -> ds
dt LSHIFT 15 -> dx
et RSHIFT 1 -> fm
dy RSHIFT 3 -> ea
fp AND fv -> fx
NOT p -> q
dd RSHIFT 2 -> de
eu AND fa -> fc
ba AND bc -> bd
dh AND dj -> dk
lr AND lt -> lu
he RSHIFT 1 -> hx
ex AND ez -> fa
df OR dg -> dh
fj LSHIFT 15 -> fn
NOT kx -> ky
gk OR gq -> gr
dy RSHIFT 2 -> dz
gh OR gi -> gj
lj AND ll -> lm
x OR ai -> aj
bz AND cb -> cc
1 AND lu -> lv
as RSHIFT 3 -> au
ce OR cd -> cf
il AND in -> io
dd RSHIFT 1 -> dw
NOT lo -> lp
c LSHIFT 1 -> t
dd RSHIFT 3 -> df
dd RSHIFT 5 -> dg
lh AND li -> lk
lf RSHIFT 5 -> li
dy RSHIFT 5 -> eb
NOT kt -> ku
at OR az -> ba
x RSHIFT 3 -> z
NOT lk -> ll
lb OR la -> lc
1 AND r -> s
lh OR li -> lj
ln AND lp -> lq
kk RSHIFT 5 -> kn
ea OR eb -> ec
ci AND ct -> cv
b RSHIFT 2 -> d
jp RSHIFT 1 -> ki
NOT cr -> cs
NOT jd -> je
jp RSHIFT 2 -> jq
jn OR jo -> jp
lf RSHIFT 3 -> lh
1 AND ds -> dt
lf AND lq -> ls
la LSHIFT 15 -> le
NOT fg -> fh
at AND az -> bb
au AND av -> ax
kw AND ky -> kz
v OR w -> x
kk OR kv -> kw
ks AND ku -> kv
kh LSHIFT 1 -> lb
1 AND kz -> la
NOT kc -> kd
x RSHIFT 2 -> y
et OR fe -> ff
et AND fe -> fg
NOT ac -> ad
jl OR jk -> jm
1 AND jj -> jk
bn RSHIFT 1 -> cg
NOT kp -> kq
ci RSHIFT 3 -> ck
ev AND ew -> ey
1 AND ke -> kf
cj AND cp -> cr
ir LSHIFT 1 -> jl
NOT gw -> gx
as RSHIFT 2 -> at
iu RSHIFT 1 -> jn
cy LSHIFT 15 -> dc
hg OR hh -> hi
ci RSHIFT 1 -> db
au OR av -> aw
km AND kn -> kp
gj RSHIFT 1 -> hc
iu RSHIFT 2 -> iv
ab AND ad -> ae
da LSHIFT 1 -> du
NOT bw -> bx
km OR kn -> ko
ko AND kq -> kr
bv AND bx -> by
kl OR kr -> ks
1 AND ht -> hu
df AND dg -> di
NOT ag -> ah
d OR j -> k
d AND j -> l
b AND n -> p
gf OR ge -> gg
gg LSHIFT 1 -> ha
bn RSHIFT 5 -> bq
bo OR bu -> bv
1 AND gy -> gz
s LSHIFT 15 -> w
NOT ie -> if
as RSHIFT 5 -> av
bo AND bu -> bw
hz AND ik -> im
bp AND bq -> bs
b RSHIFT 1 -> v
NOT l -> m
bp OR bq -> br
g AND i -> j
br AND bt -> bu
t OR s -> u
hz RSHIFT 5 -> ic
gk AND gq -> gs
fl LSHIFT 1 -> gf
he RSHIFT 3 -> hg
gz LSHIFT 15 -> hd
hf OR hl -> hm
1 AND gd -> ge
fo OR fz -> ga
id AND if -> ig
fo AND fz -> gb
gr AND gt -> gu
he OR hp -> hq
fq AND fr -> ft
ga AND gc -> gd
fo RSHIFT 2 -> fp
gl OR gm -> gn
hg AND hh -> hj
NOT hn -> ho
gl AND gm -> go
he RSHIFT 5 -> hh
NOT gb -> gc
hq AND hs -> ht
hz RSHIFT 3 -> ib
hz RSHIFT 2 -> ia
fq OR fr -> fs
hx OR hy -> hz
he AND hp -> hr
gj RSHIFT 5 -> gm
hf AND hl -> hn
hv OR hu -> hw
NOT hj -> hk
gj RSHIFT 3 -> gl
fo RSHIFT 3 -> fq
he RSHIFT 2 -> hf

View File

@@ -0,0 +1,702 @@
use core::fmt;
use std::{collections::HashMap, iter::zip};
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{self, alpha1, multispace1},
multi::separated_list1,
sequence::tuple,
IResult, Parser,
};
#[derive(Debug, Clone)]
enum Instruction {
Assign(u16, String),
Connect(String, String),
Not(String, String),
And(String, String, String),
OneAnd(String, String),
Or(String, String, String),
Lshift(u16, String, String),
Rshift(u16, String, String),
}
impl fmt::Display for Instruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Instruction::Assign(value, wire) => write!(f, "{} -> {}", value, wire),
Instruction::Connect(source, target) => write!(f, "{} -> {}", source, target),
Instruction::Not(source, target) => write!(f, "NOT {} -> {}", source, target),
Instruction::And(source1, source2, target) => {
write!(f, "{} AND {} -> {}", source1, source2, target)
}
Instruction::OneAnd(source, target) => write!(f, "1 AND {} -> {}", source, target),
Instruction::Or(source1, source2, target) => {
write!(f, "{} OR {} -> {}", source1, source2, target)
}
Instruction::Lshift(value, source, target) => {
write!(f, "{} LSHIFT {} -> {}", source, value, target)
}
Instruction::Rshift(value, source, target) => {
write!(f, "{} RSHIFT {} -> {}", source, value, target)
}
}
}
}
#[derive(Debug, Clone, Copy)]
enum Port {
Noop,
Not,
And,
Or,
Lshift(u16),
Rshift(u16),
}
impl fmt::Display for Port {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Port::Noop => write!(f, "Noop"),
Port::Not => write!(f, "Not"),
Port::And => write!(f, "And"),
Port::Or => write!(f, "Or"),
Port::Lshift(_) => write!(f, "Lshift"),
Port::Rshift(_) => write!(f, "Rshift"),
}
}
}
fn parse_input(input: &str) -> IResult<&str, Vec<Instruction>> {
let (input, result) = separated_list1(
multispace1,
alt((
tuple((complete::u16::<&str, _>, tag(" -> "), alpha1))
.map(|(val, _, target)| Instruction::Assign(val, target.to_string())),
tuple((alpha1::<&str, _>, tag(" -> "), alpha1)).map(|(source, _, target)| {
Instruction::Connect(source.to_string(), target.to_string())
}),
tuple((tag("NOT "), alpha1::<&str, _>, tag(" -> "), alpha1)).map(
|(_, source, _, target)| Instruction::Not(source.to_string(), target.to_string()),
),
tuple((alpha1::<&str, _>, tag(" AND "), alpha1, tag(" -> "), alpha1)).map(
|(source_1, _, source_2, _, target)| {
Instruction::And(
source_1.to_string(),
source_2.to_string(),
target.to_string(),
)
},
),
tuple((tag("1 AND "), alpha1::<&str, _>, tag(" -> "), alpha1)).map(
|(_, source, _, target)| {
Instruction::OneAnd(source.to_string(), target.to_string())
},
),
tuple((alpha1::<&str, _>, tag(" OR "), alpha1, tag(" -> "), alpha1)).map(
|(source_1, _, source_2, _, target)| {
Instruction::Or(
source_1.to_string(),
source_2.to_string(),
target.to_string(),
)
},
),
tuple((
alpha1::<&str, _>,
tag(" LSHIFT "),
complete::u16,
tag(" -> "),
alpha1,
))
.map(|(source, _, shift_amount, _, target)| {
Instruction::Lshift(shift_amount, source.to_string(), target.to_string())
}),
tuple((
alpha1::<&str, _>,
tag(" RSHIFT "),
complete::u16,
tag(" -> "),
alpha1,
))
.map(|(source, _, shift_amount, _, target)| {
Instruction::Rshift(shift_amount, source.to_string(), target.to_string())
}),
)),
)(input)?;
Ok((input, result))
}
type Node = (Port, Vec<String>, Option<u16>);
fn solve_first(instructions: &[Instruction], output_wire: &str) -> (u16, HashMap<String, Node>) {
// Because the graph is centered around the edges instead of nodes, we have to go through a lot of gymnastics to build it
let mut signals = HashMap::<String, Node>::new();
// For OneAnd operator
signals.insert("one".to_string(), (Port::Noop, vec![], Some(1)));
for instruction in instructions {
match instruction {
Instruction::Assign(value, wire) => {
signals.insert(wire.to_owned(), (Port::Noop, vec![], Some(*value)));
}
Instruction::Connect(source, target) => {
signals.insert(
target.to_owned(),
(Port::Noop, vec![source.to_owned()], None),
);
}
// We could already preprocess a bit by calculating the result if we know the input, but that might make it overly complicated a this point
// Instead, we do the actual traversal and calculations later
Instruction::Not(source, target) => {
signals.insert(
target.to_owned(),
(Port::Not, vec![source.to_owned()], None),
);
}
Instruction::And(source_1, source_2, target) => {
signals.insert(
target.to_owned(),
(
Port::And,
vec![source_1.to_owned(), source_2.to_owned()],
None,
),
);
}
Instruction::OneAnd(source, target) => {
signals.insert(
target.to_owned(),
(Port::And, vec!["one".to_string(), source.to_owned()], None),
);
}
Instruction::Or(source_1, source_2, target) => {
signals.insert(
target.to_owned(),
(
Port::Or,
vec![source_1.to_owned(), source_2.to_owned()],
None,
),
);
}
Instruction::Lshift(shift, source, target) => {
signals.insert(
target.to_owned(),
(Port::Lshift(*shift), vec![source.to_owned()], None),
);
}
Instruction::Rshift(shift, source, target) => {
signals.insert(
target.to_owned(),
(Port::Rshift(*shift), vec![source.to_owned()], None),
);
}
};
}
let mut edges_to_calc = vec![output_wire.to_string()];
while !edges_to_calc.is_empty() {
let edge_to_calc = edges_to_calc.pop().unwrap();
if let Some(signal) = signals.get(&edge_to_calc) {
match signal {
(port, incoming_wires, None) => {
let incoming_signals: Vec<Option<u16>> = incoming_wires
.iter()
.map(|x| match signals.get(x).unwrap() {
(_, _, None) => None,
(_, _, s) => s.to_owned(),
})
.collect();
if incoming_signals.iter().any(|s| s.is_none()) {
edges_to_calc.push(edge_to_calc);
for (s, w) in zip(incoming_signals, incoming_wires) {
if s.is_none() {
edges_to_calc.push(w.to_owned());
}
}
} else {
match port {
Port::Noop => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(*port, incoming_wires.to_owned(), incoming_signals[0]),
);
}
Port::Not => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(!incoming_signals[0].unwrap()),
),
);
}
Port::And => {
assert_eq!(incoming_signals.len(), 2);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(
incoming_signals[0].unwrap()
& incoming_signals[1].unwrap(),
),
),
);
}
Port::Or => {
assert_eq!(incoming_signals.len(), 2);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(
incoming_signals[0].unwrap()
| incoming_signals[1].unwrap(),
),
),
);
}
Port::Lshift(shift) => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(incoming_signals[0].unwrap() << shift),
),
);
}
Port::Rshift(shift) => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(incoming_signals[0].unwrap() >> shift),
),
);
}
}
}
}
(_, _, Some(_)) => { /* do nothing */ }
}
} else {
unreachable!();
}
}
let result = signals.get(&output_wire.to_string()).unwrap().to_owned();
match result {
(_, _, None) => (0, HashMap::new()),
(_, _, Some(s)) => (s, signals.to_owned()),
}
}
fn solve_second(
instructions: &[Instruction],
output_wire: &str,
override_wire: &str,
) -> (u16, HashMap<String, Node>) {
// Because the graph is centered around the edges instead of nodes, we have to go through a lot of gymnastics to build it
let mut signals = HashMap::<String, Node>::new();
// For OneAnd operator
signals.insert("one".to_string(), (Port::Noop, vec![], Some(1)));
for instruction in instructions {
match instruction {
Instruction::Assign(value, wire) => {
signals.insert(wire.to_owned(), (Port::Noop, vec![], Some(*value)));
}
Instruction::Connect(source, target) => {
signals.insert(
target.to_owned(),
(Port::Noop, vec![source.to_owned()], None),
);
}
// We could already preprocess a bit by calculating the result if we know the input, but that might make it overly complicated a this point
// Instead, we do the actual traversal and calculations later
Instruction::Not(source, target) => {
signals.insert(
target.to_owned(),
(Port::Not, vec![source.to_owned()], None),
);
}
Instruction::And(source_1, source_2, target) => {
signals.insert(
target.to_owned(),
(
Port::And,
vec![source_1.to_owned(), source_2.to_owned()],
None,
),
);
}
Instruction::OneAnd(source, target) => {
signals.insert(
target.to_owned(),
(Port::And, vec!["one".to_string(), source.to_owned()], None),
);
}
Instruction::Or(source_1, source_2, target) => {
signals.insert(
target.to_owned(),
(
Port::Or,
vec![source_1.to_owned(), source_2.to_owned()],
None,
),
);
}
Instruction::Lshift(shift, source, target) => {
signals.insert(
target.to_owned(),
(Port::Lshift(*shift), vec![source.to_owned()], None),
);
}
Instruction::Rshift(shift, source, target) => {
signals.insert(
target.to_owned(),
(Port::Rshift(*shift), vec![source.to_owned()], None),
);
}
};
}
let mut edges_to_calc = vec![output_wire.to_string()];
while !edges_to_calc.is_empty() {
let edge_to_calc = edges_to_calc.pop().unwrap();
if let Some(signal) = signals.get(&edge_to_calc) {
match signal {
(port, incoming_wires, None) => {
let incoming_signals: Vec<Option<u16>> = incoming_wires
.iter()
.map(|x| match signals.get(x).unwrap() {
(_, _, None) => None,
(_, _, s) => s.to_owned(),
})
.collect();
if incoming_signals.iter().any(|s| s.is_none()) {
edges_to_calc.push(edge_to_calc);
for (s, w) in zip(incoming_signals, incoming_wires) {
if s.is_none() {
edges_to_calc.push(w.to_owned());
}
}
} else {
match port {
Port::Noop => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(*port, incoming_wires.to_owned(), incoming_signals[0]),
);
}
Port::Not => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(!incoming_signals[0].unwrap()),
),
);
}
Port::And => {
assert_eq!(incoming_signals.len(), 2);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(
incoming_signals[0].unwrap()
& incoming_signals[1].unwrap(),
),
),
);
}
Port::Or => {
assert_eq!(incoming_signals.len(), 2);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(
incoming_signals[0].unwrap()
| incoming_signals[1].unwrap(),
),
),
);
}
Port::Lshift(shift) => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(incoming_signals[0].unwrap() << shift),
),
);
}
Port::Rshift(shift) => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(incoming_signals[0].unwrap() >> shift),
),
);
}
}
}
}
(_, _, Some(_)) => { /* do nothing */ }
}
} else {
unreachable!();
}
}
let result = signals.get(&output_wire.to_string()).unwrap().to_owned();
for instruction in instructions {
match instruction {
Instruction::Assign(value, wire) => {
signals.insert(wire.to_owned(), (Port::Noop, vec![], Some(*value)));
}
Instruction::Connect(source, target) => {
signals.insert(
target.to_owned(),
(Port::Noop, vec![source.to_owned()], None),
);
}
// We could already preprocess a bit by calculating the result if we know the input, but that might make it overly complicated a this point
// Instead, we do the actual traversal and calculations later
Instruction::Not(source, target) => {
signals.insert(
target.to_owned(),
(Port::Not, vec![source.to_owned()], None),
);
}
Instruction::And(source_1, source_2, target) => {
signals.insert(
target.to_owned(),
(
Port::And,
vec![source_1.to_owned(), source_2.to_owned()],
None,
),
);
}
Instruction::OneAnd(source, target) => {
signals.insert(
target.to_owned(),
(Port::And, vec!["one".to_string(), source.to_owned()], None),
);
}
Instruction::Or(source_1, source_2, target) => {
signals.insert(
target.to_owned(),
(
Port::Or,
vec![source_1.to_owned(), source_2.to_owned()],
None,
),
);
}
Instruction::Lshift(shift, source, target) => {
signals.insert(
target.to_owned(),
(Port::Lshift(*shift), vec![source.to_owned()], None),
);
}
Instruction::Rshift(shift, source, target) => {
signals.insert(
target.to_owned(),
(Port::Rshift(*shift), vec![source.to_owned()], None),
);
}
};
}
signals.insert(
override_wire.to_string(),
(Port::Noop, vec![], Some(result.2.unwrap())),
);
let mut edges_to_calc = vec![output_wire.to_string()];
while !edges_to_calc.is_empty() {
let edge_to_calc = edges_to_calc.pop().unwrap();
if let Some(signal) = signals.get(&edge_to_calc) {
match signal {
(port, incoming_wires, None) => {
let incoming_signals: Vec<Option<u16>> = incoming_wires
.iter()
.map(|x| match signals.get(x).unwrap() {
(_, _, None) => None,
(_, _, s) => s.to_owned(),
})
.collect();
if incoming_signals.iter().any(|s| s.is_none()) {
edges_to_calc.push(edge_to_calc);
for (s, w) in zip(incoming_signals, incoming_wires) {
if s.is_none() {
edges_to_calc.push(w.to_owned());
}
}
} else {
match port {
Port::Noop => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(*port, incoming_wires.to_owned(), incoming_signals[0]),
);
}
Port::Not => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(!incoming_signals[0].unwrap()),
),
);
}
Port::And => {
assert_eq!(incoming_signals.len(), 2);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(
incoming_signals[0].unwrap()
& incoming_signals[1].unwrap(),
),
),
);
}
Port::Or => {
assert_eq!(incoming_signals.len(), 2);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(
incoming_signals[0].unwrap()
| incoming_signals[1].unwrap(),
),
),
);
}
Port::Lshift(shift) => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(incoming_signals[0].unwrap() << shift),
),
);
}
Port::Rshift(shift) => {
assert_eq!(incoming_signals.len(), 1);
signals.insert(
edge_to_calc.to_owned(),
(
*port,
incoming_wires.to_owned(),
Some(incoming_signals[0].unwrap() >> shift),
),
);
}
}
}
}
(_, _, Some(_)) => { /* do nothing */ }
}
} else {
unreachable!();
}
}
let result = signals.get(&output_wire.to_string()).unwrap().to_owned();
match result {
(_, _, None) => (0, HashMap::new()),
(_, _, Some(s)) => (s, signals.to_owned()),
}
}
fn main() {
println!("Hello, this is Patrick!");
let input_txt = include_str!("../input.txt");
let (_, instructions) = parse_input(input_txt).unwrap();
let (first_result, _) = solve_first(&instructions[..], "a");
println!("The provided signal at wire 'a' is {}", first_result);
let (second_result, _) = solve_second(&instructions[..], "a", "b");
println!(
"The signal at 'a' is {} when overriding 'b' with it and running it again",
{ second_result }
);
}

View File

@@ -0,0 +1,8 @@
123 -> x
456 -> y
x AND y -> d
x OR y -> e
x LSHIFT 2 -> f
y RSHIFT 2 -> g
NOT x -> h
NOT y -> i

View File

@@ -0,0 +1,9 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.3"

View File

@@ -0,0 +1,28 @@
Faerun to Norrath = 129
Faerun to Tristram = 58
Faerun to AlphaCentauri = 13
Faerun to Arbre = 24
Faerun to Snowdin = 60
Faerun to Tambi = 71
Faerun to Straylight = 67
Norrath to Tristram = 142
Norrath to AlphaCentauri = 15
Norrath to Arbre = 135
Norrath to Snowdin = 75
Norrath to Tambi = 82
Norrath to Straylight = 54
Tristram to AlphaCentauri = 118
Tristram to Arbre = 122
Tristram to Snowdin = 103
Tristram to Tambi = 49
Tristram to Straylight = 97
AlphaCentauri to Arbre = 116
AlphaCentauri to Snowdin = 12
AlphaCentauri to Tambi = 18
AlphaCentauri to Straylight = 91
Arbre to Snowdin = 129
Arbre to Tambi = 53
Arbre to Straylight = 40
Snowdin to Tambi = 15
Snowdin to Straylight = 99
Tambi to Straylight = 70

View File

@@ -0,0 +1,33 @@
use nom::{
bytes::complete::tag,
character::complete::{alpha1, i64, multispace1},
multi::separated_list1,
sequence::tuple,
IResult,
};
fn parse_input(input: &str) -> IResult<&str, Vec<(String, String, i64)>> {
let (input, result) = separated_list1(
multispace1,
tuple((alpha1, tag(" to "), alpha1, tag(" = "), i64))
.map(|(from, _, to, _, distance)| (from.to_string(), to.to_string(), distance)),
)(input)?;
Ok((input, result))
}
fn solve_first(distances: &[(String, String, i64)]) -> i64 {
todo!()
}
fn main() {
println!("Hello, Patrick!");
let input_txt = include_str!("../input.txt");
let (_, distances) = parse_input(input_txt).unwrap();
let first_result = solve_first(&distances[..]);
println!("The shortest route is {}", first_result);
}

View File

@@ -0,0 +1,6 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -0,0 +1,200 @@
1645
1995
1658
1062
1472
1710
1424
1823
1518
1656
1811
1511
1320
1521
1395
1996
1724
1666
1637
1504
1766
534
1738
1791
1372
1225
1690
1949
1495
1436
1166
1686
1861
1889
1887
997
1202
1478
833
1497
1459
1717
1272
1047
1751
1549
1204
1230
1260
1611
1506
1648
1354
1415
1615
1327
1622
1592
1807
1601
1026
1757
1376
1707
1514
1905
1660
1578
1963
1292
390
1898
1019
1580
1499
1830
1801
1881
1764
1442
1838
1088
1087
1040
1349
1644
1908
1697
1115
1178
1224
1810
1445
1594
1894
1287
1676
1435
1294
1796
1350
1685
1118
1488
1726
1696
1190
1538
1780
1806
1207
1346
1705
983
1249
1455
2002
1466
1723
1227
1390
1281
1715
1603
1862
1744
1774
1385
1312
1654
1872
1142
1273
1508
1639
1827
1461
1795
1533
1304
1417
1984
28
1693
1951
1391
1931
1179
1278
1400
1361
1369
1343
1416
1426
314
1510
1933
1239
1218
1918
1797
1255
1399
1229
723
1992
1595
1191
1916
1525
1605
1524
1869
1652
1874
1756
1246
1310
1219
1482
1429
1244
1554
1575
1123
1194
1408
1917
1613
1773
1809
1987
1733
1844
1423
1718
1714
1923
1503

View File

@@ -0,0 +1,68 @@
fn solve_1(input: &str) -> u32 {
let numbers: Vec<u32> = input
.lines()
.map(|number| number.parse::<u32>().unwrap())
.collect();
for n in numbers.iter() {
for m in numbers.iter() {
if n + m == 2020 {
return n * m;
}
}
}
return 0;
}
fn solve_2(input: &str) -> u32 {
let numbers: Vec<u32> = input
.lines()
.map(|number| number.parse::<u32>().unwrap())
.collect();
for n in numbers.iter() {
for m in numbers.iter() {
if n + m > 2020 {
continue;
}
for v in numbers.iter() {
if n + m + v == 2020 {
return n * m * v;
}
}
}
}
return 0;
}
fn main() {
println!("Hello, this is Patrick!");
let input = include_str!("../input.txt");
let result_1 = solve_1(input);
println!("The magic number is {}", result_1);
let result_2 = solve_2(input);
println!("The bigger magic number is {}", result_2);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), 514579);
}
#[test]
fn test_2() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_2(test_input), 241861950);
}
}

View File

@@ -0,0 +1,6 @@
1721
979
366
299
675
1456

View File

@@ -0,0 +1,7 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
[dependencies]
nom = "7.1.3"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,67 @@
use nom::{
bytes::complete::tag,
character::complete::{alpha1, anychar, multispace1, u32},
multi::separated_list1,
sequence::{preceded, tuple},
IResult,
};
fn parse_input(input: &str) -> IResult<&str, Vec<(u32, u32, char, &str)>> {
let (input, result) = separated_list1(
multispace1,
tuple((
u32,
preceded(tag("-"), u32),
preceded(tag(" "), anychar),
preceded(tag(": "), alpha1),
)),
)(input)?;
Ok((input, result))
}
fn solve_1(input: &str) -> usize {
let (_, input) = parse_input(input).unwrap();
input
.into_iter()
.filter(|(min, max, c, s)| {
let mut cs = 0;
for ch in s.chars() {
if ch == *c {
cs += 1;
}
}
return cs >= *min && cs <= *max;
})
.count()
}
fn solve_2(input: &str) {}
fn main() {
println!("Hello, this is Patrick!");
let input = include_str!("../input.txt");
let result_1 = solve_1(input);
println!("The number of valid passwords is {}", result_1);
let result_2 = solve_2(input);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), 2);
}
#[test]
fn test_2() {}
}

View File

@@ -0,0 +1,3 @@
1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc

View File

@@ -2,11 +2,34 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "main"
version = "0.1.0"
dependencies = [
"nom",
"priority-queue",
]
[[package]]
@@ -30,3 +53,13 @@ dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "priority-queue"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff39edfcaec0d64e8d0da38564fad195d2d51b680940295fcc307366e101e61"
dependencies = [
"autocfg",
"indexmap",
]

View File

@@ -7,3 +7,4 @@ edition = "2021"
[dependencies]
nom = "7.1.2"
priority-queue = "1.3.2"

View File

@@ -1,30 +1,25 @@
use std::{collections::HashSet, hash::Hash};
use nom::{
bytes::streaming::tag,
character::complete::{self, multispace1},
multi::separated_list1,
sequence::{preceded, separated_pair},
IResult,
character::complete::{self,multispace1},
multi::separated_list1,
sequence::{preceded, separated_pair}, bytes::streaming::tag,
};
use priority_queue::PriorityQueue;
use std::collections::HashSet;
fn parse_input(input: &str) -> IResult<&str, Vec<((i32, i32), (i32, i32))>> {
let (input, coords) = separated_list1(
multispace1,
multispace1,
preceded(
tag("Sensor at x="),
separated_pair(
separated_pair(
complete::i32,
tag(", y="),
complete::i32,
),
tag(": closest beacon is at x="),
separated_pair(
complete::i32,
tag(", y="),
complete::i32,
))
)
)(input)?;
separated_pair(complete::i32, tag(", y="), complete::i32),
tag(": closest beacon is at x="),
separated_pair(complete::i32, tag(", y="), complete::i32),
),
),
)(input)?;
Ok((input, coords))
}
@@ -33,7 +28,11 @@ fn manhattan_dist(a: (i32, i32), b: (i32, i32)) -> i32 {
return (a.0 - b.0).abs() + (a.1 - b.1).abs();
}
fn fill_map(beacon_map: &mut HashSet<(i32, i32)>, sensor_coord: (i32, i32), beacon_coord: (i32, i32)) {
fn _fill_map(
beacon_map: &mut HashSet<(i32, i32)>,
sensor_coord: (i32, i32),
beacon_coord: (i32, i32),
) {
let dist = manhattan_dist(sensor_coord, beacon_coord);
let (sx, sy) = sensor_coord;
@@ -47,7 +46,12 @@ fn fill_map(beacon_map: &mut HashSet<(i32, i32)>, sensor_coord: (i32, i32), beac
}
}
fn fill_line(beacon_line: &mut HashSet<i32>, sensor_coord: (i32, i32), beacon_coord: (i32, i32), test_line: i32) {
fn fill_line(
beacon_line: &mut HashSet<i32>,
sensor_coord: (i32, i32),
beacon_coord: (i32, i32),
test_line: i32,
) {
let dist = manhattan_dist(sensor_coord, beacon_coord);
let (sx, sy) = sensor_coord;
@@ -60,6 +64,21 @@ fn fill_line(beacon_line: &mut HashSet<i32>, sensor_coord: (i32, i32), beacon_co
}
}
#[derive(PartialEq, Eq, Hash)]
enum EventType {
Start,
Intersection,
Middle,
End,
}
#[derive(PartialEq, Eq, Hash)]
struct Event {
coord: (i32, i32),
t: EventType,
line_id: u32,
}
fn main() {
let test_y = 2000000;
@@ -72,7 +91,6 @@ fn main() {
// println!("Sensor at x={sx}, y={sy}: closest beacon is at x={bx}, y={by}");
// }
// Naive method
// let mut beacon_map = HashSet::new();
@@ -85,14 +103,74 @@ fn main() {
// println!("Number of positions with y={test_y}: {positions}");
// A slightly less naive approach
let mut beacon_line = HashSet::new();
for (sensor, beacon) in coord_list {
for (sensor, beacon) in coord_list.clone() {
fill_line(&mut beacon_line, sensor, beacon, test_y);
}
println!("Number of positions with y={test_y}: {}", beacon_line.len() - 1);
println!(
"Number of positions with y={test_y}: {}",
beacon_line.len() - 1
);
// Part 2
//
// Ik denk dat dit misschien wel met een sweep line zou moeten kunnen.
// Je weet immers waar alle ruiten liggen en je kan die hele mik sorteren.
// Je krijgt dan 3 event-types: start van een lijnstuk, een kruising en het einde van een lijnstuk.
// Enige is dat je alleen in de daadwerkelijke coordinaat-range zoals in de opgave dingen wilt
// mee laten tellen.
const MAX_COORD: i32 = 8000000;
let mut event_queue: PriorityQueue<Event, (i32, i32)> = PriorityQueue::new();
let mut line_id = 0;
for &(sensor, beacon) in coord_list.iter() {
let sensor = (sensor.0 * 2, sensor.1 * 2);
let beacon = (beacon.0 * 2, beacon.1 * 2);
let dist = manhattan_dist(sensor, beacon);
let begin = (sensor.0 + dist, sensor.1);
let middle_1 = (sensor.0, sensor.1 - dist);
let middle_2 = (sensor.0, sensor.1 + dist);
let end = (sensor.0 - dist, sensor.1);
event_queue.push(
Event {
coord: begin,
t: EventType::Start,
line_id,
},
begin,
);
event_queue.push(
Event {
coord: middle_1,
t: EventType::Middle,
line_id,
},
middle_1,
);
event_queue.push(
Event {
coord: middle_2,
t: EventType::Middle,
line_id,
},
middle_2,
);
event_queue.push(
Event {
coord: end,
t: EventType::End,
line_id,
},
end,
);
line_id += 1;
}
}

View File

@@ -1,11 +1,11 @@
use nom::{
IResult,
multi::separated_list1,
sequence::{tuple, preceded},
character::complete::{self, multispace1},
branch::alt,
bytes::complete::take,
bytes::streaming::tag,
branch::alt, Parser,
character::complete::{self, multispace1},
multi::separated_list1,
sequence::{preceded, tuple},
IResult, Parser,
};
#[derive(Debug, PartialEq, PartialOrd, Clone)]
@@ -19,25 +19,21 @@ fn parse_input(input: &str) -> IResult<&str, Vec<(String, u32, Vec<String>)>> {
let (input, valve_tuples) = separated_list1(
multispace1,
tuple((
preceded(
tag("Valve "),
take(2 as usize).map(|s| String::from(s))),
preceded(
tag(" has flow rate="),
complete::u32),
preceded(tag("Valve "), take(2 as usize).map(|s| String::from(s))),
preceded(tag(" has flow rate="), complete::u32),
alt((
preceded(
tag("; tunnels lead to valves "),
separated_list1(
tag(", "),
take(2 as usize).map(|s| String::from(s)))),
tag("; tunnels lead to valves "),
separated_list1(tag(", "), take(2 as usize).map(|s| String::from(s))),
),
preceded(
tag("; tunnel leads to valve "),
take(2 as usize).map(|s| vec![String::from(s)])),
tag("; tunnel leads to valve "),
take(2 as usize).map(|s| vec![String::from(s)]),
),
)),
))
)),
)(input)?;
Ok((input, valve_tuples))
}
@@ -54,10 +50,12 @@ fn main() {
// println!();
// }
let valves : Vec<Valve> = valve_tuples
let valves: Vec<Valve> = valve_tuples
.into_iter()
.map(|(i, f, t)| Valve {id: i, flow: f, tunnels: t})
.map(|(i, f, t)| Valve {
id: i,
flow: f,
tunnels: t,
})
.collect();
}

View File

@@ -0,0 +1,8 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,160 @@
fn solve_1(input: &str) -> u32 {
input
.lines()
.map(|l| {
// Digits are 0-9, so we know that if they
// are still 10 they haven't been changed
let mut first = 10;
let mut last = 10;
for c in l.chars() {
if let Some(digit) = c.to_digit(10) {
if first == 10 {
first = digit;
}
last = digit;
}
}
first * 10 + last
})
.sum()
}
fn digitify(chars: &str) -> u32 {
let mut chars_left = &chars[..];
while chars_left.len() > 0 {
if chars_left.len() >= 3 {
if let Some(digit) = chars_left.chars().next().unwrap().to_digit(10) {
return digit;
} else if &chars_left[0..3] == "one" {
return 1;
} else if &chars_left[0..3] == "two" {
return 2;
} else if &chars_left[0..3] == "six" {
return 6;
} else if chars_left.len() >= 4 {
if &chars_left[0..4] == "four" {
return 4;
} else if &chars_left[0..4] == "five" {
return 5;
} else if &chars_left[0..4] == "nine" {
return 9;
} else if chars_left.len() >= 5 {
if &chars_left[0..5] == "three" {
return 3;
} else if &chars_left[0..5] == "seven" {
return 7;
} else if &chars_left[0..5] == "eight" {
return 8;
} else {
chars_left = &chars_left[1..];
}
} else {
chars_left = &chars_left[1..];
}
} else {
chars_left = &chars_left[1..];
}
} else if let Some(digit) = chars_left.chars().next().unwrap().to_digit(10) {
return digit;
} else {
chars_left = &chars_left[1..];
}
}
return 0;
}
fn digitify_backwards(line: &str) -> u32 {
let chars_left = line.chars().rev().collect::<String>();
let mut chars_left = chars_left.as_str();
while chars_left.len() > 0 {
if chars_left.len() >= 3 {
if let Some(digit) = chars_left.chars().next().unwrap().to_digit(10) {
return digit;
} else if &chars_left[0..3] == "eno" {
return 1;
} else if &chars_left[0..3] == "owt" {
return 2;
} else if &chars_left[0..3] == "xis" {
return 6;
} else if chars_left.len() >= 4 {
if &chars_left[0..4] == "ruof" {
return 4;
} else if &chars_left[0..4] == "evif" {
return 5;
} else if &chars_left[0..4] == "enin" {
return 9;
} else if chars_left.len() >= 5 {
if &chars_left[0..5] == "eerht" {
return 3;
} else if &chars_left[0..5] == "neves" {
return 7;
} else if &chars_left[0..5] == "thgie" {
return 8;
} else {
chars_left = &chars_left[1..];
}
} else {
chars_left = &chars_left[1..];
}
} else {
chars_left = &chars_left[1..];
}
} else if let Some(digit) = chars_left.chars().next().unwrap().to_digit(10) {
return digit;
} else {
chars_left = &chars_left[1..];
}
}
return 0;
}
fn solve_2(input: &str) -> u32 {
input
.lines()
.map(|l| {
let first = digitify(&l[..]);
let last = digitify_backwards(&l[..]);
first * 10 + last
})
.sum()
}
fn main() {
println!("Hello, this is Patrick!");
let input_txt = include_str!("../input.txt");
let result_1 = solve_1(input_txt);
println!("The sum of all calibration values is {}", result_1);
let result_2 = solve_2(input_txt);
println!("The sum of all improved calibration values is {}", result_2);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), 142);
}
#[test]
fn test_2() {
let test_input = include_str!("../test2.txt");
assert_eq!(solve_2(test_input), 281);
}
}

View File

@@ -0,0 +1,4 @@
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet

View File

@@ -0,0 +1,7 @@
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen

View File

@@ -0,0 +1,9 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.3"

View File

@@ -0,0 +1,100 @@
Game 1: 4 red, 1 green, 15 blue; 6 green, 2 red, 10 blue; 7 blue, 6 green, 4 red; 12 blue, 10 green, 3 red
Game 2: 3 green, 18 blue; 14 green, 4 red, 2 blue; 3 red, 14 green, 15 blue
Game 3: 12 green, 2 blue; 9 green; 1 red, 11 blue, 4 green
Game 4: 4 blue, 8 green, 5 red; 6 red, 7 blue, 9 green; 2 green, 2 red, 2 blue; 2 green, 6 blue, 9 red; 10 red, 9 green
Game 5: 12 red, 1 green, 7 blue; 13 red, 16 blue; 16 blue, 10 red; 4 blue; 16 blue, 7 red; 1 blue, 7 red
Game 6: 17 blue, 2 red; 5 blue, 6 green, 2 red; 5 green, 5 blue; 5 green, 12 blue, 4 red
Game 7: 2 red, 1 blue, 10 green; 8 red, 14 green, 9 blue; 15 red, 1 blue, 6 green; 9 blue, 3 green, 10 red; 7 blue, 13 red, 4 green
Game 8: 1 green, 2 blue; 7 red, 2 blue, 1 green; 1 red, 2 green; 4 red, 1 blue; 11 red, 2 green, 2 blue; 1 blue, 2 green, 11 red
Game 9: 11 green, 11 blue, 6 red; 2 green, 3 blue, 2 red; 2 red, 11 blue, 14 green; 5 green, 7 red, 7 blue; 7 green, 1 red, 12 blue; 1 red, 8 green, 7 blue
Game 10: 2 red, 8 green, 7 blue; 10 red, 5 green, 2 blue; 4 red, 8 green, 16 blue; 10 blue, 3 green, 15 red
Game 11: 2 blue, 2 green, 5 red; 1 green, 3 red, 3 blue; 11 green, 1 red, 2 blue
Game 12: 8 blue, 11 green, 14 red; 10 green, 13 red, 2 blue; 1 red, 6 green, 4 blue; 13 red, 11 green, 6 blue
Game 13: 15 red, 17 green, 1 blue; 12 red, 1 blue, 1 green; 2 red, 1 blue, 14 green
Game 14: 6 green, 11 red, 3 blue; 6 green, 2 blue; 2 green, 10 red, 8 blue; 2 red; 1 green, 9 red; 3 blue, 1 green, 3 red
Game 15: 11 blue, 11 green, 4 red; 3 green, 10 blue; 2 red, 9 green, 9 blue
Game 16: 2 blue, 11 green; 1 red, 1 blue, 11 green; 12 green, 1 blue, 1 red; 3 blue, 14 green, 1 red; 14 green, 4 blue; 2 blue, 12 green
Game 17: 1 red, 2 blue, 4 green; 4 blue, 3 green; 1 green, 1 red, 6 blue; 1 red, 7 blue; 2 green
Game 18: 3 red, 3 blue, 7 green; 2 blue, 2 red, 2 green; 4 red, 12 green; 5 green, 2 blue, 4 red; 3 red
Game 19: 15 red, 7 blue, 10 green; 5 green, 8 red; 9 green, 8 red; 5 red, 10 green
Game 20: 15 blue, 6 green, 11 red; 13 red, 9 blue, 1 green; 15 blue, 10 red, 11 green
Game 21: 15 red, 4 green; 11 red, 2 blue, 4 green; 5 blue, 2 green, 4 red; 4 red, 5 blue; 6 red, 3 blue, 1 green
Game 22: 4 green, 4 red, 13 blue; 3 red, 7 blue, 9 green; 12 blue, 13 green, 5 red
Game 23: 20 green, 4 red; 6 blue, 9 red, 7 green; 6 green
Game 24: 1 green, 3 blue, 6 red; 1 green, 1 blue, 2 red; 3 blue, 5 red, 1 green
Game 25: 2 red, 9 blue, 2 green; 2 green, 1 red, 5 blue; 3 red, 1 green, 3 blue; 8 blue, 2 green, 3 red; 12 blue, 3 red; 1 blue, 2 green, 1 red
Game 26: 2 blue, 5 green, 20 red; 2 blue, 6 red, 9 green; 3 red, 2 blue, 5 green
Game 27: 17 blue, 2 red, 14 green; 15 green, 16 blue, 2 red; 13 blue, 13 green; 1 red, 7 green, 3 blue; 1 blue, 2 green
Game 28: 5 blue, 6 red, 3 green; 7 red, 19 green; 11 blue, 13 green
Game 29: 1 blue, 8 red, 7 green; 1 green, 1 red; 8 red, 7 green, 1 blue; 7 green, 2 red; 1 blue, 7 red; 1 blue, 2 red, 5 green
Game 30: 3 red, 17 blue; 11 red, 3 blue, 8 green; 7 green, 12 blue, 10 red; 5 blue, 2 green
Game 31: 14 blue, 7 green; 12 green, 14 blue, 2 red; 17 blue, 2 red, 8 green; 2 red, 3 blue, 11 green; 9 green, 4 blue; 1 red, 3 green, 1 blue
Game 32: 15 red, 1 blue, 10 green; 15 green, 10 red, 1 blue; 2 red, 6 green, 1 blue
Game 33: 10 green, 1 red, 16 blue; 11 blue, 14 green, 3 red; 14 green, 13 blue; 17 blue, 2 red, 3 green
Game 34: 8 red, 7 blue, 8 green; 3 green, 1 red; 1 red, 1 green, 5 blue; 6 red, 8 green, 2 blue; 7 red, 8 blue, 3 green
Game 35: 5 blue, 19 red; 2 blue, 11 red, 1 green; 16 red, 10 blue; 7 green, 3 blue, 6 red; 3 green, 18 red, 5 blue; 8 blue, 5 red
Game 36: 9 red, 6 green, 10 blue; 9 red, 15 green, 6 blue; 6 red, 1 blue, 14 green
Game 37: 7 green, 8 red, 2 blue; 3 blue, 5 red, 16 green; 1 green, 1 red, 3 blue
Game 38: 5 green, 5 red, 3 blue; 10 blue, 19 red, 9 green; 2 red, 3 blue, 11 green
Game 39: 15 red, 11 blue, 5 green; 11 green, 2 red, 6 blue; 2 blue, 3 green, 6 red; 15 red, 3 blue, 13 green
Game 40: 7 green, 4 red, 1 blue; 6 blue, 6 green, 2 red; 2 blue, 3 red, 1 green; 1 blue, 3 red, 3 green; 2 red, 5 green, 3 blue
Game 41: 10 blue, 8 green, 9 red; 7 blue, 9 red, 2 green; 10 blue, 4 red, 5 green
Game 42: 8 blue, 13 green, 14 red; 8 blue, 1 green, 11 red; 4 red, 6 green, 3 blue; 14 green, 4 red, 2 blue
Game 43: 2 red, 10 green, 19 blue; 5 blue, 4 green, 9 red; 9 green, 9 red, 2 blue
Game 44: 6 red, 2 green, 3 blue; 2 blue, 12 red, 6 green; 1 red, 10 blue; 12 red, 6 green, 2 blue; 14 red, 13 green, 3 blue; 10 green, 9 blue, 11 red
Game 45: 2 blue, 1 red, 1 green; 1 green, 1 blue; 2 green, 2 blue
Game 46: 7 green, 1 red; 1 green, 4 blue, 1 red; 3 blue, 4 green, 1 red; 1 red, 4 green; 1 blue, 12 green, 1 red; 16 green, 1 blue
Game 47: 4 blue, 8 green, 3 red; 6 red, 1 green, 3 blue; 16 green, 4 blue, 1 red; 4 blue, 8 red
Game 48: 1 blue, 9 red, 8 green; 8 green, 2 blue, 6 red; 2 green; 4 blue, 5 red; 1 blue, 9 red, 9 green; 1 red, 1 blue, 3 green
Game 49: 3 green, 2 blue; 7 blue, 4 red; 20 green, 5 red, 13 blue; 20 green, 1 red, 6 blue
Game 50: 3 red, 3 green; 3 green, 3 red; 2 blue, 10 red; 3 blue, 5 green; 14 red, 2 green, 2 blue; 7 red, 2 green
Game 51: 3 green, 3 blue, 2 red; 4 green, 16 red, 3 blue; 1 blue, 3 red; 9 red, 1 blue, 4 green
Game 52: 6 red, 18 green, 7 blue; 2 blue, 1 red, 5 green; 8 blue, 6 red, 1 green; 1 red, 1 blue; 6 red, 3 green, 10 blue
Game 53: 1 blue, 10 red, 3 green; 13 red, 2 green, 1 blue; 1 green, 2 red
Game 54: 4 blue, 6 green, 2 red; 5 blue, 6 red, 2 green; 6 blue, 4 green, 8 red; 13 red, 10 blue, 1 green; 5 red, 5 green, 9 blue
Game 55: 4 green, 18 red, 4 blue; 9 blue, 7 green, 16 red; 5 red, 6 blue, 14 green; 13 green, 11 red, 9 blue; 6 blue, 13 green, 1 red; 10 blue, 12 red, 14 green
Game 56: 8 green, 5 blue, 10 red; 10 green, 7 red, 12 blue; 11 red, 12 blue, 1 green; 4 blue, 6 red, 10 green; 17 blue, 8 green, 2 red
Game 57: 1 green, 2 red; 2 green, 5 red, 1 blue; 13 red, 3 green, 4 blue; 3 blue, 13 red, 9 green
Game 58: 1 red, 7 blue, 4 green; 2 green, 1 blue, 1 red; 1 green, 11 blue; 12 blue; 1 blue, 5 green, 1 red; 3 green, 11 blue, 1 red
Game 59: 5 green, 3 blue, 17 red; 2 red, 9 green; 1 blue, 4 green
Game 60: 5 red, 5 green, 1 blue; 2 red, 2 blue, 6 green; 2 red, 3 blue, 3 green
Game 61: 2 green, 3 blue, 4 red; 17 green, 1 blue; 1 green, 6 red, 4 blue; 3 blue, 9 green, 3 red; 18 green, 7 red, 2 blue
Game 62: 5 red; 3 blue, 9 green; 3 red, 13 blue, 10 green; 14 green, 1 red, 2 blue; 7 blue, 13 green
Game 63: 12 blue, 5 green; 5 green, 1 red, 1 blue; 4 red, 7 green, 9 blue; 8 blue, 2 green, 7 red
Game 64: 3 blue, 11 green; 5 blue, 2 red, 5 green; 17 green, 5 blue, 1 red; 4 red, 3 blue, 4 green
Game 65: 2 red, 1 blue, 2 green; 7 green, 2 red, 1 blue; 2 blue, 7 green, 1 red; 3 blue, 8 green, 3 red
Game 66: 4 red, 12 blue, 1 green; 20 blue, 3 green, 2 red; 11 blue, 1 green
Game 67: 12 blue, 10 red, 13 green; 19 green, 4 red, 7 blue; 12 red, 9 blue, 13 green
Game 68: 2 blue, 17 green; 12 green, 2 red; 5 red, 2 green, 4 blue; 4 blue
Game 69: 17 blue, 3 red, 1 green; 4 green, 8 blue, 8 red; 4 green, 7 red, 1 blue; 8 red, 1 green, 11 blue; 13 blue, 10 red, 9 green; 14 blue, 5 green, 6 red
Game 70: 1 red, 2 blue, 4 green; 13 blue, 3 red, 2 green; 6 green, 8 blue
Game 71: 5 red, 7 green, 1 blue; 11 green, 4 red, 1 blue; 1 red, 12 green, 10 blue; 1 red, 7 blue, 12 green
Game 72: 9 blue, 4 green, 1 red; 6 green, 4 blue; 8 green, 5 blue, 1 red
Game 73: 1 blue, 10 green, 14 red; 4 green; 2 blue, 9 red, 4 green; 2 blue, 13 green; 13 green, 13 red; 7 red, 5 green, 2 blue
Game 74: 3 red, 1 blue, 3 green; 4 green, 1 blue, 1 red; 2 blue, 10 green, 1 red; 1 blue, 3 red, 1 green
Game 75: 1 red, 1 blue, 1 green; 2 red, 1 green, 4 blue; 2 red, 4 blue; 1 blue, 1 red
Game 76: 4 green, 2 blue, 6 red; 7 green, 1 red; 8 green, 4 red
Game 77: 8 green, 7 blue, 5 red; 6 red, 14 green, 7 blue; 8 green, 7 blue; 1 red, 8 green, 8 blue
Game 78: 6 red, 3 blue, 3 green; 7 blue, 10 red; 5 green, 10 blue, 1 red; 3 green, 11 blue, 4 red; 14 red, 9 blue, 2 green; 16 red, 2 green, 12 blue
Game 79: 1 green; 5 green; 11 green, 3 blue, 2 red; 3 blue
Game 80: 2 green, 2 red; 1 blue, 1 green, 1 red; 1 blue, 1 green, 2 red; 2 red; 5 green
Game 81: 10 blue, 2 red, 9 green; 4 red, 12 blue, 5 green; 7 green, 4 blue, 6 red; 1 red, 13 green, 14 blue; 13 green, 11 blue
Game 82: 4 blue, 2 green; 7 blue, 3 green, 5 red; 1 red, 4 blue, 3 green; 5 blue, 1 red, 6 green; 6 green, 4 red; 11 blue, 3 red, 5 green
Game 83: 12 green; 5 red, 8 green; 11 red, 14 green, 1 blue; 9 green, 4 red
Game 84: 5 blue, 1 red; 16 blue, 5 green; 1 red, 9 blue, 3 green; 11 blue; 1 green, 2 blue; 1 red, 7 blue, 4 green
Game 85: 17 red, 5 blue; 18 blue, 2 red, 2 green; 18 blue, 2 green, 8 red
Game 86: 4 red, 1 blue, 11 green; 6 blue, 7 green, 1 red; 3 green, 4 blue; 2 red, 7 blue, 2 green
Game 87: 4 red, 5 blue; 1 green, 15 red, 1 blue; 11 blue, 12 red
Game 88: 11 green, 3 red, 1 blue; 6 green, 1 blue, 1 red; 1 blue, 3 green; 2 blue, 4 green, 2 red
Game 89: 2 green; 1 red, 2 green, 3 blue; 4 blue, 1 red, 10 green; 4 blue, 5 green; 6 blue, 1 red, 10 green
Game 90: 15 red, 7 green, 17 blue; 7 blue, 1 red; 7 green, 6 red, 3 blue
Game 91: 2 blue, 17 red, 6 green; 1 green, 1 blue, 6 red; 6 red, 4 blue; 10 green, 14 red, 1 blue; 7 blue, 10 green, 10 red; 16 red, 11 green, 9 blue
Game 92: 1 green, 8 blue, 4 red; 4 green, 4 red, 4 blue; 1 green, 7 red, 4 blue
Game 93: 11 blue, 12 red, 1 green; 9 blue, 2 green, 5 red; 7 red, 5 blue, 2 green
Game 94: 7 blue, 10 green; 9 green, 9 blue, 2 red; 1 red, 5 green, 4 blue
Game 95: 1 green, 1 blue, 2 red; 6 red; 1 blue; 1 green, 1 blue, 6 red
Game 96: 1 blue, 1 red, 2 green; 4 red, 13 green, 1 blue; 1 blue, 13 green, 5 red; 7 green, 4 red
Game 97: 10 blue, 5 red, 5 green; 4 red, 8 green, 2 blue; 5 red, 2 green, 15 blue; 2 red, 1 green, 4 blue; 2 red, 14 blue; 14 blue, 4 green
Game 98: 11 red, 8 green, 9 blue; 3 blue, 1 green, 14 red; 10 blue, 2 red, 4 green; 7 blue, 11 red, 3 green; 5 red, 12 blue, 4 green; 7 green, 7 blue, 8 red
Game 99: 3 green, 2 blue, 1 red; 15 red, 8 blue, 7 green; 18 red, 12 blue, 2 green
Game 100: 11 red, 1 blue, 2 green; 3 red, 3 green; 1 blue, 8 red, 4 green; 5 green, 5 blue, 1 red; 2 green, 1 red, 6 blue; 2 green, 8 red, 1 blue

View File

@@ -0,0 +1,132 @@
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{self, multispace1},
multi::separated_list1,
sequence::{pair, tuple},
IResult, Parser,
};
use std::cmp::max;
#[derive(Debug, Clone, Copy)]
enum Color {
Red,
Green,
Blue,
}
fn parse_input(input: &str) -> IResult<&str, Vec<(u32, Vec<(u32, u32, u32)>)>> {
let (input, result) = separated_list1(
multispace1,
tuple((
tag("Game "),
complete::u32,
tag(": "),
separated_list1(
tag("; "),
separated_list1(
tag(", "),
alt((
pair(complete::u32, tag(" red")).map(|(d, _)| (d, Color::Red)),
pair(complete::u32, tag(" green")).map(|(d, _)| (d, Color::Green)),
pair(complete::u32, tag(" blue")).map(|(d, _)| (d, Color::Blue)),
)),
)
.map(|list_of_colors_with_number| {
let mut r = (0, 0, 0);
for (number, color) in list_of_colors_with_number {
match color {
Color::Red => r.0 = number,
Color::Green => r.1 = number,
Color::Blue => r.2 = number,
}
}
r
}),
),
))
.map(|(_, iter, _, game_results)| (iter, game_results)),
)(input)?;
Ok((input, result))
}
fn solve_1(game_results: &[(u32, Vec<(u32, u32, u32)>)]) -> u32 {
let red_max = 12;
let green_max = 13;
let blue_max = 14;
game_results
.iter()
.filter(|(_, list_of_game_results)| {
list_of_game_results
.iter()
.all(|&(red, green, blue)| red <= red_max && green <= green_max && blue <= blue_max)
})
.map(|(iter, _)| iter)
.sum()
}
fn solve_2(game_results: &[(u32, Vec<(u32, u32, u32)>)]) -> u32 {
game_results
.iter()
.map(|(_, list_of_game_results)| {
let mut minima = (0, 0, 0);
for game_result in list_of_game_results {
minima.0 = max(minima.0, game_result.0);
minima.1 = max(minima.1, game_result.1);
minima.2 = max(minima.2, game_result.2);
}
minima.0 * minima.1 * minima.2
})
.sum()
}
fn main() {
println!("Hello, this is Patrick!");
let input_txt = include_str!("../input.txt");
let (_, game_results) = parse_input(input_txt).unwrap();
let result_1 = solve_1(&game_results[..]);
println!(
"The sum of the IDs of the games that were possible is {}",
result_1
);
let result_2 = solve_2(&game_results[..]);
println!(
"The sum of the power of of minimum of present sets is {}",
result_2
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test_input.txt");
let (_, game_results) = parse_input(test_input).unwrap();
assert_eq!(solve_1(&game_results[..]), 8);
}
#[test]
fn test_2() {
let test_input = include_str!("../test_input.txt");
let (_, game_results) = parse_input(test_input).unwrap();
assert_eq!(solve_2(&game_results[..]), 2286);
}
}

View File

@@ -0,0 +1,5 @@
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green

View File

@@ -0,0 +1,9 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.3"

View File

@@ -0,0 +1,140 @@
.............65..................998.........453...................................845..773.........................307....527...........541
............*..........125.......*...331......*.....................30.76......./...*....*..861.......*.........298*......*.........700.....
................942.......*...874...*......407...558............752......*196.274.240.345...*.....-..105...................164...........466
....+............&.....593...........516............-....=.....*....74.....................377..157................128...........175*.......
....314.750......................497...........258.....549...70.....*....745.....289*418.................351........../..............839....
..........*.......786......283......*366..........*...............899.....*......................652.......@...219..........................
........468..=249..........*..........................866.797*960..........234.......252-.686.......=............$...................&......
..386.............582....681...52....$369.+.......969..+........................276........*.................873.....824.......%627..51..25.
.....-......835..@....*....................101.......*.......444...........587...*..33....847...............&.......=.......................
...........*.......513.45.125......................883.......*...............=.988.$.............962.*595.....................*....674.534..
........180.........................891*129..957...........+.584......................291*59..71*..................../.....707.646....*.....
...................=530.....................*.......610..790........314...$....991..................231*926....29..870.264..................
......132-..............#..............$....93.........*...............*...537...$.139..........70...............&.....................131..
...36.......#.514%.......99..684.......21.........852.886../...191.....892...........*....456..-.....172...../..............................
.....*...508................&......615...........$.........964....*...................627...............*242.945..........457.....512..880..
.....211.............430...........*.......%..........702.........243..747.......506................24.......................*873....*......
.........................988..570........-..72....726*.................-........=.....340............*.555....526......................&....
........&..........#928....&../.......785..............971..585......................+............860....%...#..........628.....=....952....
..165..541......................822........930.........*...%............*737..................940..............#561......=...=..685.........
....+...........248..-...40...................*521....897............698.................................558...............52........-......
..................*...19..%...........674.....................110.........................*296.............*...........78#.........495......
................753.....................*..............@.....#....199......353.604.....737.......483.366....242....720......................
...407....973#...............352.........397............144......*............*............799....%..................#....845.......539.....
......*................*........*..............643............443..726....=......*939..439*.....*....478$.....#.............-........-......
...165.........3....599.943..840..424..268.389...*..........=.........*83.827.318............135.55........924..535*...........%............
.......163........@...............*..........+..688.......529.........................858............137............681.347...187...........
...541....*.299.340.....@..+645.492...................................#....830*.................897.*.......782$...................352......
........740.%........549..............500...-..899......671=.807.....334.......313...26........+....366.701.............330........*........
....125.....................928../......@..243...................225......182........=..................*................&.......346........
......%....814.665.........*......573.....................69.......%.........*484.................+...64.........910.........273.....450....
...............*...........383.........433.................*...........#22...........62..#569....396........736.....*708.......&....*.......
.383.........774......................*.....#............&..265.............812......*...............305*....*...................657........
.....467.392.......936...806.......373...929...463....484.............337....%...415..465.@..............154..326...........................
....../..*.....+.......=....*.....................*........517*24.-.................*.....297.......................................*.......
..........599..820.....342.438...........482...200................49..........-312..847.............548...$.....581..909.........879.616....
............................................&................&475........................528...578....@..211......*....%....791.............
..............802..............250....................................*229........923......#.....*.................635......................
552......762..#...................$..%......940......651...........461........900*.............654...673....................*437..993.......
..........$.............52............602......%........*...105..$.................938...431.............................157......#...310...
...581../...............$.........309.......*...........846.../..718..........568@..*.......*...261...............22.........-852......*....
......*.969.349..354.....................156.666....@................-378..-................632....*..........363*........./......976.871...
.....60.....*.......*....10...@..684#..............225....248.............904..........638$......896....%.................906.926...*.......
.............602.....958.....103..........703..........................$.........456.........704.........149...785.2=...........*.87...95...
....228..589.................................*...770..588...........411..902..................................................645...........
.......*....*...135.......*...909.857.207-.602.....*.....*......=.........*..........358..............535......*................../235......
.....126..747............513..*.....$...........125.....389..956.....164...797........*.....807..34......%..754.734.....140..............969
.................919*213.....232............530..................583...................986....*...*.................186...=.%881..859.......
...937......881..........774......*345.......*......894#...644*.....$....588.................520..323..218...%...../..................#.....
.....-.401.*.......359.....*....19.........728.................670.................674.511*...........*......580........203%.........470....
........*..610......-.......836.....299.........832..........................690...........528.......21.....................................
......991......#.......365................447....#...857...227.605.........%.-...599.........................*602...529...........10........
..........+471..443.....+................*..........*......=......*252..417.....*.....653.............412.727.......*.....634.304.*.....42..
.....494......................&...........552.....852...................................*....550*520............80.174.............437......
......-.....+...536.........$..969............519.......448........251..............$...794.....................*.........701...............
..373.....930.....*......298.............76+.....*...@.....*......*................856......@899..............96..40......*.......574.......
.....*........518..575...........957.112.......479.579....288..306...+.......$817........................785.....*...9.......127..#...=907..
...698.......*..........329.....$....*......92........................203..........168.....................*..346....*..........*...........
.......470........68/..............263.....*.........337..................433............................666........92......20..784..978*194
.........%................465-.............297..............193.259.............................................17.........*................
.............*.................................................*.......*............580.......763.......@.........*747....519....628..647...
......900.....261..........722.553.....284*513......*429..............155....&....$....%..914...*......468.......................$......*...
........#........................................932......413....414......829.....528.......+...527................382...835...........744..
....918......103*37..207...676.297........422..............*........*993................140...................945.#.......*...686...........
.......................$.../...*......423....*..459=...&....602..........................................................978..*.............
.........&........414.........41.........*..673......543..........848*276.......388%..792...*....700*152......596/....*........791...%...485
.....615..55.........+......+........%.859...............@363..........................*..858.........................556............748....
......../....................775..467..........700..............*492.....$..862.......266..........319............88..........724........291
........................942.............530....*.....#.259...872........157./...287...........#687..*..../...........438$........*..233.....
............../...641........534.546...+......802.847.....*........................*...................13.......................677..*......
....604.......158........818....*.........................947................24....516.......&...332...........573...................697....
...%....2................*............/..........................162....27.....$.......#860.284.....*540..309...+...........................
........................678........337........105.469.......49.....................641.....................*......644$..............128.....
.....................%..................386.............203*.....497.404.............................795..................670.........*.....
....+..............369......814.........#.......359...........-.....*.......+.......41...........353....*263.........-.........700....102...
...862......430........=.....*............*682..............195.456..........379......+...........*..........790...987......................
....................565................689......................*...296.........................599..689.829...*..............$....910......
513......721.................................645*343.105........1....*..............=349.............&.....%...785..........832../...*......
........=............50*15..............272............*....242...306...........................................................159.59......
..............190...............88#.%.........229......310....#.......330...........149*.........89.......333.....771.....701..........522..
....354.........+....................561........*..........73.....336*....$40..906......16.........-.......+.......*........*...563....*....
.......*.............948..844......#.......556...51.........*......................=...........744.....361...$.....15.644=..9...........686.
........535.796.....*......#......907.........%......286...918....714..............688.232.................51......................284......
............*........755................@255.........*...........*......=.292............./.........453.........913................$....810.
............354...................................361..406*802...112..461............162.....$......=......991/./........&..................
.......+............#892.......654/....705..........................................*........385.........................506....*506........
.444/.482.................................*.....................619.....19*239.....187.993......................*............718........884.
..............906.182..473............/..58...407.591.583...=.....%......................*.......$......1....310.196....................*...
......820@......%....@.%.........343..61........*.......-.663.............490.....209..921....288.......*..............484...956.........324
...+.........................189*.............963...878.......782..955....%..........*................72...........406*......*....-.........
...188......861....239.818..........................*.................*......7....892.............705....197.20*..........204......429......
........*....*......./....#............*236.425*147..816..............739.....*........%..../.....*.............473...455...................
.....718.939..679........................................182.281@...........597.......360..324.161.......8*671...............971............
....................+318.698*778..691......648*806..387$../..............*......174/................+133............25......................
.............620*..................*...986...............................587.....................................15......264%..128.....998..
.......%436......267..557%..#827.......................746%.48.411*309.............+.....547......-.............*.................*....*....
..690..........#.................724....*.....772...........+..........787........462...+........89.#777.....794...-.........120.662....429.
....&....$575.874........450.379...%.120.944.....*....10......378*888.%..........................................542........................
..................388.....+.....*..............108........243..............468...........363......132....-....&...............*....391......
.....*.............%....$.....554.494....784.........310.&............458...%........753*..............217...174..23*108...853.233...*......
..636.425....343.........455........$........87........*.................-........%..............823.....................-...........898....
................*728.747.......770.......913.*....855.159.....&618...*.............779...94-..........375/.318*410...324.209................
........................*399......*.......=...905.*.......24........192.......760................785...................#...............468..
.......674.414....108/.......498..443.............660.......*................*....................*....980..................................
.462.........*..............................654..............669...........427......$..............14..*...921.......897.............862....
...@.......292..370....751....639....................403..............74.......537.504.130.............779..&....89..*....615.423.%....*....
...............+..........*........958......23...160./..................*228.....*........*....66.....................378....*....735.......
......#...............&68.584..125.$....898..+....*.........130.................927.....75......*....613....414.............................
....909..968...................$.....=...#......@.935..............966.......................374.......*.....*...&......73.......*611.=888..
............*231...................93.........157..............252..%..900.869...269................550...352..123......*...7.888...........
.......833%..............277%.+860............................*...........*......*............973....................697...#........765..153
..............920@..569.........................499................44..........36....................406.98...+..295..........94*....@......
.....28...............*.413......-333......984.*............984...........878.............*.................958.....*43...829....746........
......*............320...@...799.......696..$..211...%.......+.........%...*......232$.915.....209...........................*........510...
.......429.....................*........$...........624.736..........342....960..................*..................186....402..............
....16.........838*............477....&...................%...............................977..996..........255.212.........................
245........88......209.................283.920*456...............410.............$353.....%....................*....................846.....
.......699..*....................................................*...580......................659*......=..................184....#..#......
..890...*...485..........=......................................16...*......589...................754.802........485..%...-......784...+....
.......28.........303....405.@442.......768......476..273*961......843.....*.....161....813.....................*....470..............111...
.............#...*...........................303.*..........................255.+........&.......326*309.+814.469..............5............
....208.....910.514..148..261..334.......$...*...674..597..........................*439......36.....................=876...468*.............
....*....*..........*........*...@.....205...525.....*.....863..190.......115................./..@..+17......731................626.....&...
..984....994.......396.......587....................558....*..............................112...364.........................599*.......824..
......./...............................................................935*56........146................#......%............................
.......563..................896....216*192.......................588...........423......*......657...894..678...57............&.....813*....
............#......186.-....*...................796.916........./..........810...*...532..........@.......*........394.......885........871.
..../.......484...*....101.208........%..42........*......623.....*592.....*.....572.......545.........677.....*...*........................
.479....25........535...............627..*...........652.....+.808.......926.522............*...............671.33.499.............514......
..........*............951*472............215.......*.....................................451.....152...........................58...%...903
..........178.....=....................64......22.244...898.................514.......460........-......947..........823....368...%.........
...................120.....=.....289...*........*.......................723..../...........................*....368.................349..304
..........................402...........914..707.............630/...*.............................419.....654......*..............*.....*...
......981.131....809*755...........318*.............248...........#.195........338..........23....*...............395..223.....626.498.681..
.....*.....................+.271.......457.........*......384...633.......#.....*...638..46........144........@...........*.................
...915....................14../..............595..806......*...............523.603..&....*....................165.824.....789.....347$......
.................*47.............761.265.150................967........565............=...296......-..............*...........671......379..
..............967......./.&197......*.........=.....................&................660..........292.............993...........=..581..#...
......................279........+.........755........@..............712..........*...................827....../...................*........
...........$.....*................115..................400................=......1.292..@602..=.................321..............728........
..579..410..3..44.291..........................538..................148....873.................461....................................722...

View File

@@ -0,0 +1,259 @@
use std::collections::HashSet;
use std::fmt;
#[derive(Debug, Clone, Copy, Default)]
enum Tile {
#[default]
Empty,
Symbol(char),
Digit(u64),
}
impl fmt::Display for Tile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Tile::Empty => write!(f, "."),
Tile::Symbol(s) => write!(f, "{}", s),
Tile::Digit(d) => write!(f, "{}", d),
}
}
}
fn parse_input(input: &str) -> Vec<Vec<Tile>> {
let mut result = vec![];
for line in input.lines() {
let mut line_result = vec![];
for c in line.chars() {
if let Some(d) = c.to_digit(10) {
line_result.push(Tile::Digit(d as u64));
} else {
line_result.push(match c {
'.' => Tile::Empty,
s => Tile::Symbol(s),
})
}
}
result.push(line_result);
}
result
}
fn get_engine_part_positions(engine: &Vec<Vec<Tile>>) -> Vec<(u64, usize, (usize, usize))> {
let mut engine_parts = vec![];
for (row_number, row) in engine.iter().enumerate() {
let mut engine_part = 0;
let mut engine_part_start = 0;
let mut checking_engine_part = false;
for (column_number, tile) in row.iter().enumerate() {
match tile {
Tile::Digit(d) => {
if !checking_engine_part {
engine_part_start = column_number;
checking_engine_part = true;
}
engine_part = engine_part * 10 + d;
}
_ => {
if checking_engine_part {
checking_engine_part = false;
engine_parts.push((
engine_part,
row_number,
(engine_part_start, column_number - 1),
));
engine_part = 0;
}
}
}
}
if checking_engine_part {
engine_parts.push((engine_part, row_number, (engine_part_start, row.len() - 2)));
}
}
engine_parts
}
fn get_positions_to_check(
engine_part_position: (usize, (usize, usize)),
engine_width: usize,
engine_height: usize,
) -> Vec<(usize, usize)> {
let mut positions_to_check = vec![];
let (row, (column_start, column_end)) = engine_part_position;
if row > 0 {
for column in column_start..=column_end {
positions_to_check.push((row - 1, column));
}
if column_start > 0 {
positions_to_check.push((row - 1, column_start - 1));
}
if column_start < engine_width - 1 {
positions_to_check.push((row - 1, column_end + 1));
}
}
if row < engine_height - 1 {
for column in column_start..=column_end {
positions_to_check.push((row + 1, column));
}
if column_start > 0 {
positions_to_check.push((row + 1, column_start - 1));
}
if column_end < engine_width - 1 {
positions_to_check.push((row + 1, column_end + 1));
}
}
if column_start > 0 {
positions_to_check.push((row, column_start - 1));
}
if column_end < engine_width - 1 {
positions_to_check.push((row, column_end + 1));
}
positions_to_check
}
fn get_gear_positions(engine: &Vec<Vec<Tile>>) -> Vec<(usize, usize)> {
let mut result = vec![];
for (row_number, row) in engine.iter().enumerate() {
for (column_number, tile) in row.iter().enumerate() {
match tile {
Tile::Symbol('*') => result.push((row_number, column_number)),
_ => {}
}
}
}
result
}
fn get_gear_ratio_number(engine: &Vec<Vec<Tile>>, starting_point: (usize, usize)) -> u64 {
let mut starting_column = starting_point.1;
while let Some(Tile::Digit(_)) = engine[starting_point.0].get(starting_column - 1) {
starting_column -= 1;
if starting_column == 0 {
break;
}
}
let mut result = 0;
let mut column = starting_column;
while let Some(Tile::Digit(d)) = engine[starting_point.0].get(column) {
result = result * 10 + d;
column += 1;
}
result
}
fn solve_1(engine: &Vec<Vec<Tile>>) -> u64 {
let mut result = 0;
let engine_width = engine[0].len();
let engine_height = engine.len();
let engine_part_positions = get_engine_part_positions(&engine);
for (part_number, row, (column_start, column_end)) in engine_part_positions {
let positions_to_check = get_positions_to_check(
(row, (column_start, column_end)),
engine_width,
engine_height,
);
if positions_to_check.iter().any(|&(x, y)| match engine[x][y] {
Tile::Symbol(_) => true,
_ => false,
}) {
result += part_number;
}
}
result
}
fn solve_2(engine: &Vec<Vec<Tile>>) -> u64 {
let mut result = 0;
let engine_width = engine[0].len();
let engine_height = engine.len();
let gears_to_check = get_gear_positions(&engine);
for (gear_x, gear_y) in gears_to_check {
let positions_to_check =
get_positions_to_check((gear_x, (gear_y, gear_y)), engine_width, engine_height);
let mut adjacent_engine_part_positions = HashSet::new();
for (x, y) in positions_to_check {
match engine[x][y] {
Tile::Digit(_) => {
if !(adjacent_engine_part_positions.contains(&(x, y - 1))
|| adjacent_engine_part_positions.contains(&(x, y + 1)))
{
adjacent_engine_part_positions.insert((x, y));
}
}
_ => {}
}
}
if adjacent_engine_part_positions.len() == 2 {
result += adjacent_engine_part_positions
.into_iter()
.map(|coord| get_gear_ratio_number(&engine, coord))
.product::<u64>();
}
}
result
}
fn main() {
println!("Hello, this is Patrick!");
let input_txt = include_str!("../input.txt");
let engine = parse_input(input_txt);
println!(
"The sum of all the part numbers in the engine schematic is {}",
solve_1(&engine)
);
println!(
"The sum of all gear ratios in the engine schematic is {}",
solve_2(&engine)
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test_input.txt");
let engine = parse_input(test_input);
assert_eq!(solve_1(&engine), 4361);
}
#[test]
fn test_2() {
let test_input = include_str!("../test_input.txt");
let engine = parse_input(test_input);
assert_eq!(solve_2(&engine), 467835);
}
}

View File

@@ -0,0 +1,10 @@
467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..

View File

@@ -0,0 +1,9 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.3"

View File

@@ -0,0 +1,213 @@
Card 1: 71 88 83 5 15 54 89 55 69 79 | 83 39 58 32 99 54 91 19 44 5 57 29 88 9 95 15 79 71 90 69 43 66 55 12 89
Card 2: 33 11 66 48 67 95 78 71 98 65 | 66 2 1 59 77 95 61 71 8 38 18 62 10 65 53 17 75 92 64 50 67 21 51 78 98
Card 3: 28 58 71 40 25 13 7 19 61 72 | 47 89 96 3 84 77 81 76 93 20 34 7 25 91 71 22 36 9 40 98 60 67 35 54 49
Card 4: 58 26 74 94 42 29 9 90 76 54 | 74 90 41 32 19 80 27 97 9 2 57 45 29 42 76 37 83 58 25 46 94 86 63 24 12
Card 5: 70 65 54 14 32 29 39 98 9 51 | 61 14 43 9 45 94 40 69 62 29 54 50 15 92 30 4 49 31 55 98 28 1 70 39 20
Card 6: 2 88 60 55 45 19 59 95 79 4 | 61 65 19 88 34 74 93 4 70 28 60 18 75 55 2 49 3 67 86 57 91 59 95 79 45
Card 7: 16 87 54 73 30 43 95 74 50 9 | 9 79 13 71 11 87 82 78 50 12 1 18 24 54 73 42 85 3 7 31 40 30 43 83 92
Card 8: 48 72 63 92 40 70 53 84 37 31 | 72 40 37 60 82 70 7 88 65 6 92 83 56 48 46 33 31 53 14 34 26 63 61 84 91
Card 9: 28 94 84 98 23 81 95 37 66 31 | 25 16 46 35 79 87 93 49 1 66 43 84 60 94 20 82 57 90 73 42 83 54 27 63 44
Card 10: 69 76 8 54 49 77 95 26 86 67 | 98 75 82 94 39 90 32 49 37 57 64 24 11 60 59 33 88 52 35 30 10 83 25 20 29
Card 11: 34 35 98 12 47 28 21 27 83 90 | 59 80 84 73 64 13 7 76 10 92 38 97 71 89 69 67 32 37 70 56 15 87 45 5 6
Card 12: 24 36 10 93 97 39 35 13 45 7 | 23 74 62 18 63 98 44 17 46 88 83 40 68 48 55 33 86 91 20 27 89 49 11 50 99
Card 13: 49 78 43 7 52 89 50 66 11 99 | 28 62 16 87 69 97 7 65 66 8 31 89 49 86 23 78 51 11 52 43 42 73 76 50 32
Card 14: 16 86 45 72 79 99 96 66 1 65 | 33 16 21 86 1 68 56 95 96 74 60 99 45 79 29 49 7 66 27 72 78 81 53 65 38
Card 15: 69 94 51 93 36 78 52 71 9 46 | 90 88 99 29 97 51 20 14 45 53 31 50 17 40 44 24 54 28 25 96 83 15 92 34 62
Card 16: 12 35 59 86 76 16 13 95 80 52 | 62 26 70 77 21 35 87 12 58 52 55 63 7 94 6 13 93 44 15 22 47 76 95 59 11
Card 17: 49 43 92 26 74 54 3 71 12 94 | 27 81 79 42 65 7 40 67 76 86 38 83 85 99 88 84 21 5 35 20 69 80 96 62 44
Card 18: 54 68 44 79 86 27 77 71 89 73 | 33 89 70 74 38 41 52 18 43 10 88 5 21 1 4 93 28 2 25 87 97 81 64 36 62
Card 19: 90 89 36 94 75 25 62 99 78 88 | 20 34 31 83 92 23 56 2 43 64 30 61 36 12 89 62 41 98 55 65 24 47 81 38 99
Card 20: 41 96 39 25 18 66 88 26 90 82 | 90 35 12 6 29 73 4 76 59 26 91 34 74 36 88 55 39 70 21 94 9 62 47 1 60
Card 21: 57 46 97 63 91 67 74 43 12 79 | 70 57 36 26 64 79 93 60 92 27 88 48 41 51 75 83 46 25 10 82 85 14 61 59 80
Card 22: 35 53 32 89 2 88 58 43 80 5 | 58 87 41 6 47 3 57 60 85 12 46 86 94 44 83 15 78 59 73 95 62 82 25 11 30
Card 23: 46 34 61 86 15 4 48 91 42 59 | 25 71 45 58 49 84 26 2 67 92 32 53 31 64 73 59 1 14 41 70 62 9 39 98 85
Card 24: 40 48 39 46 44 87 57 78 2 35 | 9 37 61 3 95 34 22 15 73 89 71 80 13 53 43 60 20 82 30 75 62 97 7 28 14
Card 25: 83 22 51 35 59 65 45 41 46 78 | 59 21 80 33 29 41 35 51 2 10 83 99 9 12 45 24 22 78 97 84 70 46 86 16 65
Card 26: 66 73 14 61 92 63 13 68 90 94 | 95 91 67 69 46 48 74 7 92 68 13 73 10 63 66 97 94 65 84 14 71 90 61 59 72
Card 27: 25 49 37 59 51 78 54 68 70 2 | 23 59 37 68 70 54 79 14 40 94 2 49 12 26 35 78 25 71 7 51 8 32 17 72 81
Card 28: 58 30 69 17 18 70 5 29 84 57 | 5 81 35 21 69 95 57 83 93 68 84 29 18 82 55 86 70 7 58 28 17 30 59 38 72
Card 29: 5 88 2 71 68 39 83 45 36 63 | 35 49 97 13 51 32 31 68 21 2 28 58 26 12 99 94 29 55 74 44 63 66 22 46 30
Card 30: 56 1 19 30 42 17 50 37 5 53 | 38 65 36 56 75 1 5 50 63 81 90 64 88 33 17 53 30 93 52 19 67 95 37 28 42
Card 31: 97 36 49 23 98 83 64 77 73 76 | 71 64 92 20 61 12 69 9 83 99 98 18 23 76 86 73 68 10 41 97 36 57 77 49 63
Card 32: 76 79 96 17 57 80 89 9 78 88 | 48 34 31 49 8 58 25 44 65 43 23 66 91 72 47 74 50 18 28 84 98 59 15 94 30
Card 33: 3 91 62 38 44 42 81 66 17 12 | 62 80 12 39 77 52 19 71 17 26 35 91 34 25 5 11 98 1 24 9 94 49 66 93 58
Card 34: 97 42 39 51 28 49 3 77 8 29 | 13 35 98 50 14 76 69 93 56 62 68 80 24 71 90 92 31 5 66 73 74 48 95 87 82
Card 35: 67 27 89 21 77 31 85 71 26 38 | 7 18 27 31 16 52 78 38 71 65 67 80 85 77 79 95 24 84 59 97 69 36 32 75 68
Card 36: 2 38 40 26 15 45 98 55 81 39 | 25 77 56 26 63 55 19 45 10 64 90 37 40 3 33 78 69 36 2 14 91 15 61 1 98
Card 37: 55 58 59 90 52 75 77 65 8 71 | 4 9 69 80 18 38 52 89 76 57 75 64 51 42 95 5 63 39 10 28 47 33 1 36 65
Card 38: 71 89 56 6 65 72 55 40 66 37 | 85 29 70 12 51 74 87 92 97 19 26 6 83 40 80 3 38 62 11 36 52 93 94 47 69
Card 39: 26 59 87 70 48 79 43 18 64 10 | 95 9 66 36 98 54 97 96 3 59 79 48 34 56 42 37 18 1 15 6 57 26 84 61 94
Card 40: 75 98 95 99 9 73 43 3 8 47 | 52 91 16 60 51 1 48 4 59 15 20 95 62 34 87 50 28 55 64 70 65 56 22 37 97
Card 41: 79 1 71 12 14 3 40 46 43 94 | 75 7 88 50 26 76 58 30 21 97 5 57 22 74 92 29 17 82 41 33 73 83 4 60 86
Card 42: 5 97 79 75 39 69 62 76 17 89 | 92 11 66 82 99 30 75 88 59 73 29 7 26 85 20 54 57 49 32 87 9 25 78 12 96
Card 43: 32 95 76 39 10 84 65 29 44 52 | 18 83 64 95 56 66 53 70 93 51 62 2 78 1 52 28 67 61 30 13 38 23 86 19 12
Card 44: 56 44 27 72 90 50 88 20 94 2 | 23 99 5 74 64 39 41 14 15 1 76 10 3 9 80 91 40 84 60 13 45 32 96 34 85
Card 45: 13 99 96 30 49 6 17 68 55 80 | 87 12 70 97 78 9 83 71 46 33 44 94 41 22 72 74 76 59 85 20 15 25 66 8 58
Card 46: 23 70 40 78 5 74 4 64 79 29 | 33 73 75 1 4 13 53 65 45 58 78 82 42 30 83 66 74 29 72 49 23 64 50 36 71
Card 47: 5 42 30 34 10 12 11 84 28 73 | 18 10 23 84 58 31 25 5 38 28 93 34 9 11 88 42 12 87 40 30 86 73 33 62 57
Card 48: 68 73 41 50 13 32 45 86 27 24 | 90 41 50 5 45 4 13 77 39 24 17 49 33 99 18 91 32 86 27 23 73 52 80 68 53
Card 49: 1 47 76 75 90 28 68 53 93 73 | 38 83 8 20 41 75 64 6 44 93 7 69 80 96 39 30 50 71 27 88 1 47 56 61 58
Card 50: 54 12 73 88 51 81 35 2 39 9 | 45 4 84 2 33 11 46 79 38 78 88 63 59 39 94 54 55 64 73 41 66 30 51 14 35
Card 51: 49 76 79 24 44 27 40 57 56 11 | 46 71 51 70 82 93 60 75 1 98 45 24 89 48 22 94 35 23 38 47 50 36 83 90 26
Card 52: 3 35 89 18 36 91 52 98 24 54 | 43 50 25 41 14 13 17 55 81 95 40 59 99 44 11 57 60 65 4 92 20 42 97 21 1
Card 53: 35 50 38 97 51 99 48 22 31 59 | 97 55 49 74 33 12 64 23 52 31 18 9 89 43 45 96 13 32 92 99 86 26 59 91 46
Card 54: 27 84 72 69 67 60 74 48 81 18 | 3 63 19 85 65 15 1 83 81 98 22 73 40 12 39 11 79 50 28 61 86 89 31 6 93
Card 55: 50 35 94 27 87 46 75 92 65 25 | 61 43 89 30 31 72 37 63 85 80 4 26 15 71 22 53 36 67 79 48 62 47 19 84 13
Card 56: 39 42 44 41 10 35 31 46 51 61 | 94 99 96 41 45 61 8 25 85 48 31 67 3 80 75 42 7 52 78 39 46 37 59 82 29
Card 57: 82 54 26 93 62 9 38 8 39 99 | 97 22 29 45 86 37 5 59 99 75 30 55 6 12 58 19 61 74 85 23 17 53 48 26 24
Card 58: 39 77 12 21 85 27 50 36 88 93 | 31 12 34 92 97 89 15 96 46 78 75 85 74 41 2 18 49 76 94 57 50 60 95 77 83
Card 59: 83 30 32 59 41 96 94 75 46 93 | 73 5 8 88 14 69 94 49 61 68 91 9 41 44 50 53 66 48 93 96 65 43 47 59 82
Card 60: 76 74 70 63 43 21 56 23 24 35 | 91 55 98 28 31 57 97 15 35 93 53 61 99 18 26 94 24 95 34 64 33 49 74 82 20
Card 61: 76 6 88 96 87 99 85 45 79 9 | 51 72 87 45 47 11 5 55 60 52 29 19 9 82 33 26 94 85 77 32 22 49 75 76 70
Card 62: 95 19 6 47 33 54 25 36 64 78 | 54 32 14 70 69 44 8 99 56 82 66 83 86 17 65 31 1 47 60 9 10 62 42 48 88
Card 63: 33 69 15 41 68 76 97 88 94 55 | 98 2 33 64 63 17 67 32 70 24 31 62 56 21 38 12 95 14 52 20 84 13 8 79 1
Card 64: 55 7 30 90 72 77 14 50 1 78 | 68 39 19 34 42 10 80 4 25 63 22 47 54 70 8 97 37 44 98 83 99 32 15 31 21
Card 65: 36 56 93 64 83 86 7 96 99 79 | 5 94 73 95 47 91 14 39 82 36 68 13 19 11 25 38 1 57 40 16 77 53 59 21 18
Card 66: 55 69 60 50 99 11 57 81 52 96 | 23 82 3 27 18 94 6 8 87 36 26 65 72 98 89 76 75 61 15 13 37 38 46 29 88
Card 67: 63 19 25 60 87 39 66 70 26 9 | 66 36 30 26 87 25 63 7 46 34 71 9 98 89 69 19 52 8 64 97 78 60 24 45 79
Card 68: 51 66 43 14 67 2 88 15 80 74 | 5 90 60 14 74 44 10 82 88 80 99 68 43 98 67 15 97 42 66 49 16 51 94 37 2
Card 69: 43 2 90 92 37 91 35 8 9 88 | 90 75 58 37 9 88 69 8 18 43 32 86 99 2 28 97 6 91 35 3 73 33 85 53 98
Card 70: 2 6 87 30 45 41 86 34 78 84 | 78 73 21 45 38 77 6 86 30 71 84 79 61 41 70 87 2 34 93 8 64 53 69 12 99
Card 71: 3 67 92 7 35 48 12 20 54 57 | 65 71 57 23 91 7 49 3 92 95 53 67 12 89 29 54 72 20 48 84 15 51 46 35 39
Card 72: 68 47 43 65 61 46 62 27 67 92 | 27 51 28 92 1 46 43 68 67 82 93 2 15 38 61 16 70 42 6 47 49 65 62 89 94
Card 73: 84 29 19 79 98 73 76 43 55 52 | 77 4 68 23 84 11 32 62 7 95 40 13 90 98 55 14 81 8 1 54 57 9 86 46 99
Card 74: 91 48 72 22 34 4 90 84 66 9 | 72 91 34 93 94 6 38 41 48 87 17 53 92 1 9 84 4 45 27 35 39 42 90 66 22
Card 75: 42 2 70 8 68 61 51 78 72 94 | 72 78 63 68 1 85 27 96 51 31 74 39 57 18 41 14 97 86 95 71 59 69 90 15 20
Card 76: 93 19 51 32 72 34 99 16 11 71 | 90 75 22 17 27 11 4 55 7 16 29 30 19 61 78 72 42 95 2 67 10 34 69 93 39
Card 77: 82 62 19 13 42 80 51 20 60 29 | 62 17 20 29 15 49 63 5 80 42 85 40 48 51 82 6 60 88 77 19 99 13 18 65 35
Card 78: 86 8 32 7 6 79 60 64 98 85 | 3 14 1 75 20 79 24 50 32 53 43 90 44 60 29 33 52 64 70 45 56 97 41 23 48
Card 79: 47 33 77 60 48 43 89 37 17 50 | 22 10 62 78 56 72 67 92 28 95 21 9 44 11 30 3 58 46 36 59 42 81 76 82 49
Card 80: 30 41 23 99 79 74 80 54 95 7 | 20 69 53 7 43 57 19 63 54 91 23 37 2 41 70 18 98 99 58 9 79 26 93 8 80
Card 81: 22 21 90 33 30 34 47 4 31 18 | 93 87 3 43 63 59 14 64 9 97 48 35 60 84 92 67 25 71 89 55 13 1 27 74 44
Card 82: 37 34 4 56 14 45 50 18 75 67 | 93 73 25 26 9 23 8 67 70 28 96 41 38 24 86 12 71 6 88 84 92 58 94 18 14
Card 83: 89 49 62 13 99 56 74 37 94 95 | 14 85 17 42 36 73 51 9 82 77 98 93 45 88 39 69 43 15 71 32 94 46 6 5 63
Card 84: 10 95 35 43 15 80 11 9 34 8 | 19 70 55 25 3 57 81 30 75 17 68 63 67 2 33 87 27 58 53 39 74 36 14 51 32
Card 85: 6 98 38 32 88 12 70 93 55 19 | 16 9 53 91 90 14 85 25 69 70 52 24 17 58 23 81 4 47 13 82 74 18 6 15 21
Card 86: 76 56 70 72 48 40 23 26 85 90 | 30 98 97 53 62 18 76 4 81 65 21 93 77 8 16 66 61 72 94 26 96 14 71 58 27
Card 87: 84 21 79 35 23 1 22 65 6 38 | 91 55 1 13 16 40 56 28 27 11 12 81 19 99 7 80 25 46 74 36 9 49 97 29 59
Card 88: 9 6 26 37 96 59 36 40 11 66 | 41 94 58 43 74 49 98 16 90 57 54 70 7 60 14 69 97 79 33 52 35 48 27 61 37
Card 89: 69 80 19 92 1 9 60 25 43 59 | 23 49 37 42 38 99 16 51 34 6 27 32 78 93 84 2 56 70 71 98 15 7 76 39 4
Card 90: 70 79 23 8 24 69 81 2 20 43 | 80 79 1 70 62 14 13 63 54 16 12 33 21 75 22 83 74 65 23 2 81 56 69 72 24
Card 91: 81 10 96 62 43 4 85 9 57 14 | 8 26 17 81 34 4 10 61 71 96 43 9 85 79 1 62 51 60 73 50 23 99 14 57 55
Card 92: 90 41 54 40 28 63 53 72 59 24 | 63 72 82 90 51 16 91 71 70 15 40 21 37 41 34 68 97 28 86 14 89 65 66 39 55
Card 93: 62 50 55 59 44 47 24 13 41 99 | 27 79 29 66 96 25 44 99 13 51 81 50 54 59 41 45 86 80 11 55 14 47 62 28 84
Card 94: 16 58 2 88 37 73 89 32 94 52 | 53 7 92 2 46 61 62 47 9 3 71 58 17 75 51 94 65 60 67 64 54 88 56 28 89
Card 95: 70 67 87 52 47 89 17 57 8 37 | 73 51 70 50 54 25 67 33 57 64 23 52 99 37 47 8 58 89 17 39 97 28 87 53 10
Card 96: 26 1 34 71 49 80 79 86 9 43 | 14 86 40 36 57 15 30 52 12 10 4 76 80 39 79 18 9 60 51 29 19 83 33 63 85
Card 97: 54 52 95 32 19 96 15 46 35 90 | 45 54 30 39 4 75 23 78 33 36 65 86 58 89 77 72 29 96 73 11 52 43 61 27 19
Card 98: 93 59 51 89 8 55 53 85 31 70 | 66 18 51 32 82 59 44 31 12 38 21 53 55 98 50 16 4 93 33 8 70 29 45 11 89
Card 99: 41 62 14 52 85 50 10 56 71 65 | 56 55 7 35 40 67 94 68 45 88 71 19 23 14 65 89 62 2 91 58 33 10 15 70 37
Card 100: 13 11 28 12 63 50 10 49 83 98 | 3 81 63 26 77 98 4 19 22 32 67 46 38 41 71 78 59 6 39 68 82 79 40 37 11
Card 101: 20 39 57 59 96 32 74 1 84 29 | 38 6 31 18 29 34 63 68 45 83 42 78 20 11 96 88 40 91 66 61 43 58 55 76 3
Card 102: 96 77 67 50 37 11 39 99 65 57 | 43 69 79 87 45 82 66 15 39 56 46 34 28 17 74 93 76 40 78 77 20 30 89 71 16
Card 103: 71 64 5 68 26 41 94 49 69 66 | 7 42 38 25 10 37 23 35 32 76 15 29 81 96 91 9 36 50 51 86 88 79 22 59 54
Card 104: 89 47 29 42 48 76 39 21 12 68 | 22 88 75 20 41 73 48 10 95 38 91 40 62 78 80 65 7 31 1 87 96 46 4 25 94
Card 105: 40 12 18 26 85 79 76 19 15 62 | 81 78 24 61 71 5 32 25 22 21 4 82 88 66 95 40 1 83 16 93 23 43 65 51 84
Card 106: 82 94 35 70 16 97 54 2 93 57 | 15 16 43 83 45 60 22 18 40 87 4 53 68 92 96 71 84 63 52 64 1 56 93 67 62
Card 107: 60 27 80 91 23 82 90 35 66 19 | 51 4 78 40 39 11 13 71 41 86 97 42 56 16 46 62 79 22 2 48 20 88 15 36 26
Card 108: 18 75 48 24 87 74 73 46 32 37 | 40 39 27 15 97 42 6 66 49 3 60 82 68 13 73 46 33 28 58 95 16 79 31 67 80
Card 109: 39 84 48 75 1 46 55 95 43 67 | 13 56 34 99 27 54 35 60 2 23 18 49 50 74 83 8 15 71 3 64 68 66 52 86 70
Card 110: 60 28 49 54 36 33 50 68 1 26 | 69 3 78 35 34 24 92 13 67 15 10 97 37 79 62 52 6 18 93 77 25 2 19 46 85
Card 111: 40 44 75 55 48 16 64 97 28 10 | 76 50 26 72 18 41 67 96 82 30 49 1 66 29 95 77 45 33 69 6 88 21 62 91 31
Card 112: 13 6 4 57 32 56 8 86 44 59 | 55 58 57 64 84 71 61 46 8 6 38 94 24 41 74 48 34 98 19 56 16 13 86 23 83
Card 113: 49 87 71 19 10 47 72 41 13 84 | 10 87 52 33 72 76 41 81 67 78 49 86 36 31 63 84 7 55 47 9 38 22 59 79 13
Card 114: 62 5 87 64 45 74 98 40 69 60 | 10 98 67 5 6 32 27 18 54 77 9 21 82 87 88 35 64 31 68 93 17 44 43 66 99
Card 115: 90 77 96 67 56 71 12 24 39 2 | 3 32 57 69 65 56 15 58 47 44 46 91 87 55 21 29 75 95 36 52 73 12 81 1 24
Card 116: 28 56 74 20 7 27 37 22 41 69 | 54 77 41 22 5 81 69 82 61 92 3 2 7 28 56 90 50 20 37 47 4 27 74 49 53
Card 117: 88 27 73 60 99 82 14 69 6 48 | 52 92 23 46 13 24 95 98 86 17 94 78 58 41 87 29 77 74 26 97 21 67 8 71 2
Card 118: 49 20 27 58 22 56 5 43 72 14 | 58 73 82 33 62 48 64 14 99 68 5 79 74 49 21 26 20 95 96 4 56 66 53 30 22
Card 119: 15 98 49 95 36 48 34 88 99 65 | 53 73 69 48 37 15 50 49 28 4 22 52 98 65 85 90 32 34 25 63 40 42 88 17 99
Card 120: 4 1 22 40 27 55 12 20 29 78 | 27 5 64 39 33 34 44 87 77 79 21 84 50 78 85 62 18 94 19 91 54 24 52 22 81
Card 121: 63 13 19 41 27 62 18 10 97 82 | 13 41 86 31 78 42 71 12 29 64 54 34 55 66 59 15 90 63 97 11 10 28 68 48 60
Card 122: 93 54 83 34 87 84 72 55 24 11 | 25 83 44 60 16 80 73 39 87 76 15 79 77 38 54 72 24 30 78 11 34 64 7 8 61
Card 123: 9 89 77 35 86 55 22 46 32 27 | 44 53 49 34 28 93 72 37 32 62 43 51 57 50 70 80 19 11 23 12 92 45 56 89 13
Card 124: 15 79 46 18 87 40 78 9 61 51 | 18 24 15 38 12 44 94 19 3 92 50 4 9 31 56 46 99 1 97 30 61 40 72 98 82
Card 125: 39 52 23 10 84 7 69 97 59 31 | 36 65 61 27 3 48 90 71 70 51 96 56 21 83 73 53 64 9 74 16 49 79 87 86 77
Card 126: 20 89 33 16 75 63 19 24 95 69 | 39 80 82 23 66 38 96 92 32 58 90 35 50 26 60 25 10 64 99 83 37 34 49 45 7
Card 127: 15 8 51 74 38 47 87 17 41 16 | 44 33 42 3 49 66 80 85 75 79 32 83 5 16 45 25 95 17 90 74 86 52 64 1 24
Card 128: 65 40 98 1 9 91 67 83 7 12 | 23 21 76 37 80 77 85 2 56 53 41 84 11 69 24 89 30 50 44 72 55 82 29 26 33
Card 129: 21 75 32 9 73 29 10 58 22 19 | 70 14 76 45 27 74 4 79 93 13 39 56 31 33 97 83 42 84 62 51 50 96 30 26 58
Card 130: 59 98 97 34 10 30 73 1 92 25 | 86 47 68 62 79 76 81 29 12 91 17 15 74 45 7 70 85 24 28 84 90 38 36 4 80
Card 131: 39 73 50 54 94 89 14 46 6 72 | 88 27 36 34 72 54 73 17 82 6 89 85 74 69 50 93 14 94 39 44 75 80 46 42 38
Card 132: 29 88 9 33 73 2 43 14 36 28 | 10 77 88 13 2 9 90 6 25 48 38 69 97 46 40 58 28 45 36 65 14 63 98 43 60
Card 133: 8 64 69 68 60 87 29 51 39 10 | 9 29 14 53 68 99 92 2 79 51 95 16 71 94 33 39 66 69 7 40 20 87 65 70 35
Card 134: 69 12 15 98 94 20 66 22 8 40 | 15 94 17 78 18 88 73 70 1 55 24 8 43 41 23 82 58 90 48 52 98 99 6 40 62
Card 135: 20 93 99 39 91 14 28 11 52 32 | 13 59 41 87 56 60 78 49 79 73 28 20 61 85 89 67 93 45 31 71 17 97 39 95 98
Card 136: 23 99 24 72 7 38 31 17 50 40 | 51 96 86 43 53 19 16 42 67 1 20 45 61 88 30 48 71 54 29 25 38 6 65 73 18
Card 137: 51 16 2 63 32 52 18 75 30 33 | 6 15 46 3 32 71 12 1 56 49 68 44 77 35 17 87 55 95 9 34 74 80 69 89 38
Card 138: 80 25 93 18 43 34 60 77 70 36 | 48 93 34 18 25 13 42 52 3 35 44 55 87 17 1 66 85 70 16 53 73 10 77 80 82
Card 139: 16 77 76 42 52 27 32 23 51 83 | 46 81 6 18 31 61 9 83 25 55 72 65 63 49 79 3 91 76 77 23 1 73 85 16 35
Card 140: 57 51 65 74 54 46 41 17 15 89 | 52 92 5 21 99 27 98 77 30 65 47 43 18 11 90 31 33 58 8 17 45 57 2 82 9
Card 141: 29 70 64 91 88 44 86 48 25 74 | 85 94 26 78 75 64 21 16 38 92 74 19 89 52 81 90 97 17 29 91 9 10 60 30 54
Card 142: 99 21 93 71 1 74 84 89 98 37 | 34 96 2 64 4 51 61 1 87 60 73 31 7 28 21 99 38 69 80 78 12 81 94 76 33
Card 143: 20 67 93 61 97 51 28 40 60 14 | 50 39 1 6 31 13 55 10 98 46 95 75 38 14 20 25 28 91 7 56 8 53 99 72 51
Card 144: 8 1 26 79 47 45 5 20 90 43 | 74 75 62 47 30 45 50 14 70 32 7 39 34 5 68 61 90 79 83 1 93 2 72 22 87
Card 145: 83 51 89 3 58 33 86 60 63 47 | 29 80 93 43 58 77 49 6 73 69 42 22 33 90 98 39 55 16 18 37 13 68 10 92 2
Card 146: 12 84 88 41 51 5 90 42 4 65 | 66 96 25 19 43 31 42 39 22 59 1 52 89 8 15 7 40 77 73 51 3 33 58 29 56
Card 147: 89 41 51 59 93 6 31 87 95 28 | 93 72 24 58 16 89 27 87 70 92 28 21 66 59 53 1 55 4 44 86 94 19 20 40 9
Card 148: 53 77 60 71 70 61 56 85 39 14 | 2 68 3 6 22 35 86 34 78 43 29 54 49 90 27 89 74 69 75 73 41 25 99 36 98
Card 149: 56 20 14 24 89 72 17 32 12 98 | 36 32 16 80 92 22 4 21 93 69 85 51 83 27 44 88 28 40 98 38 65 71 45 26 76
Card 150: 30 37 4 74 89 46 69 6 13 80 | 56 87 82 95 38 63 27 23 28 96 5 57 75 53 58 39 79 86 41 43 55 31 72 45 48
Card 151: 52 45 23 28 1 16 93 6 31 15 | 13 72 3 22 69 27 77 80 47 63 62 89 12 79 6 4 16 67 48 40 44 41 95 91 9
Card 152: 63 39 31 58 74 53 95 5 18 68 | 72 49 50 16 15 61 96 1 80 89 88 90 41 40 53 56 84 29 25 46 13 75 34 24 57
Card 153: 61 11 85 76 93 73 96 20 28 83 | 8 21 89 88 74 16 71 25 4 59 32 36 84 13 51 7 95 90 6 38 30 94 22 70 31
Card 154: 30 61 20 8 9 35 33 5 55 88 | 42 53 85 74 1 63 97 57 98 18 6 99 58 29 89 90 70 11 50 23 37 21 64 49 3
Card 155: 94 24 89 18 32 27 97 77 98 51 | 51 98 62 44 88 54 91 50 18 7 72 74 94 28 24 27 32 2 97 58 22 77 89 53 30
Card 156: 81 70 87 64 4 29 13 93 97 32 | 83 62 26 67 48 63 30 35 97 66 86 70 15 56 43 78 96 24 60 59 47 41 13 19 84
Card 157: 8 29 90 52 64 33 18 49 7 79 | 3 11 79 34 91 84 45 2 5 29 55 8 85 1 49 6 7 18 64 12 92 33 25 38 52
Card 158: 36 46 15 48 51 38 14 66 50 54 | 44 14 51 24 66 98 78 69 19 68 26 43 41 13 36 46 62 6 29 54 7 92 63 38 15
Card 159: 29 27 85 90 61 62 16 10 33 72 | 10 37 90 71 94 4 46 32 64 62 21 48 49 83 9 98 14 15 52 77 86 3 72 53 17
Card 160: 3 1 36 92 62 53 87 83 67 46 | 80 75 63 25 7 28 35 67 65 53 29 93 9 52 33 95 27 18 10 87 98 56 42 37 16
Card 161: 19 12 30 25 2 94 48 43 41 32 | 32 42 34 14 82 47 80 70 69 74 29 58 43 27 30 10 86 51 2 46 84 33 85 98 53
Card 162: 71 77 23 55 79 61 99 97 27 26 | 37 26 86 84 52 54 97 62 83 3 91 60 55 69 61 20 12 98 70 39 35 59 21 99 85
Card 163: 88 59 91 51 33 71 87 15 50 93 | 35 65 58 66 80 79 51 62 71 38 43 11 31 72 33 41 37 61 12 88 87 30 99 59 50
Card 164: 33 10 66 40 85 78 63 31 81 42 | 23 90 63 46 42 66 57 20 95 52 99 82 2 85 68 43 89 35 33 12 81 51 17 22 70
Card 165: 97 17 74 94 53 49 99 24 95 25 | 65 38 99 28 19 18 27 4 10 33 58 82 86 17 8 76 66 54 88 84 29 91 43 2 97
Card 166: 46 65 72 77 30 29 21 5 97 38 | 75 76 48 19 89 83 98 97 8 87 2 93 26 74 35 53 80 73 82 91 71 39 60 70 61
Card 167: 51 84 70 21 83 43 54 39 86 81 | 62 33 56 31 3 66 96 20 48 75 11 76 43 67 37 15 53 27 95 34 89 41 78 73 1
Card 168: 29 69 32 52 53 43 36 27 12 82 | 81 9 71 34 10 92 97 57 36 68 54 88 77 73 87 65 93 27 40 85 67 26 82 49 61
Card 169: 77 96 30 17 68 33 92 12 65 87 | 77 93 6 39 63 26 99 88 66 15 65 55 69 73 46 32 64 10 70 40 27 25 42 95 21
Card 170: 69 31 8 74 60 12 64 52 56 85 | 4 93 87 46 9 17 91 28 96 66 67 53 70 71 63 37 3 1 58 7 22 40 44 50 35
Card 171: 72 74 97 56 3 10 90 89 14 92 | 82 21 15 40 44 23 12 64 73 19 2 33 31 78 8 83 24 18 98 42 66 50 49 51 5
Card 172: 11 71 73 53 84 25 29 34 3 61 | 74 61 9 75 62 29 15 25 87 34 11 71 91 3 19 73 59 93 13 22 66 53 57 43 84
Card 173: 53 98 87 91 22 71 65 84 81 83 | 56 98 67 72 54 53 41 20 55 81 65 71 38 11 22 25 83 31 84 94 91 1 87 77 28
Card 174: 82 41 3 52 36 89 43 99 63 59 | 54 92 43 59 96 38 79 78 56 15 65 52 3 99 41 82 83 80 74 40 89 63 87 61 36
Card 175: 76 8 53 21 52 54 12 55 85 91 | 4 26 90 72 21 6 61 94 37 66 3 12 76 70 65 24 29 45 41 74 10 33 2 75 62
Card 176: 76 85 52 44 23 16 53 83 65 63 | 33 76 16 92 54 65 63 83 53 44 55 15 45 91 88 22 23 52 84 87 71 85 4 11 97
Card 177: 49 47 24 12 44 22 30 52 92 88 | 17 97 55 88 18 30 6 12 46 96 92 22 8 47 80 44 52 61 49 69 64 33 24 70 21
Card 178: 3 30 99 94 86 98 5 57 43 49 | 48 99 91 57 41 5 68 44 66 1 39 52 95 94 3 26 27 49 73 30 86 80 40 81 98
Card 179: 47 14 58 96 9 70 76 23 6 80 | 9 10 70 14 72 82 47 96 61 62 49 58 35 6 3 30 89 39 71 45 74 84 80 76 23
Card 180: 87 21 20 73 17 46 58 18 14 75 | 75 88 84 67 11 41 44 81 16 21 87 78 96 17 93 46 37 73 99 18 20 14 5 77 58
Card 181: 58 95 49 35 39 86 97 1 75 38 | 1 9 86 38 97 77 51 19 44 71 4 91 42 75 39 49 35 21 17 58 30 95 92 60 68
Card 182: 84 52 77 87 29 93 15 33 16 97 | 87 11 57 79 34 58 6 33 69 17 39 40 22 31 83 27 16 15 5 73 52 55 3 48 32
Card 183: 43 1 98 22 49 7 27 81 66 48 | 26 47 43 79 3 9 91 40 39 98 1 69 49 80 93 8 64 55 61 37 66 7 54 6 81
Card 184: 97 14 31 56 53 46 84 26 11 83 | 83 19 41 46 31 84 48 25 11 67 12 1 95 94 29 88 56 97 87 96 50 7 53 26 77
Card 185: 63 11 46 36 42 41 29 34 92 44 | 70 40 99 19 54 63 4 34 41 75 29 46 85 66 48 49 88 90 7 37 6 81 76 58 61
Card 186: 97 80 49 66 83 58 47 87 89 32 | 85 65 80 53 75 57 46 33 34 96 7 48 24 45 87 99 12 89 69 60 91 47 83 49 97
Card 187: 6 50 46 39 71 49 80 34 86 45 | 16 22 64 60 73 53 59 95 54 31 63 65 14 92 94 41 76 77 26 5 52 61 30 20 62
Card 188: 49 60 66 37 29 38 48 76 59 46 | 48 21 3 95 76 70 83 86 30 52 46 37 40 78 67 49 45 50 60 58 55 65 54 4 59
Card 189: 50 74 47 7 37 73 1 6 45 85 | 18 15 77 48 54 85 74 38 69 84 63 8 42 72 16 68 61 51 6 91 47 92 21 45 1
Card 190: 45 30 42 67 53 95 35 13 19 46 | 39 12 92 22 25 90 61 70 52 31 15 10 73 88 68 56 26 93 42 94 46 53 59 72 45
Card 191: 54 3 43 42 63 26 52 89 18 11 | 17 46 39 56 9 89 85 53 60 6 32 27 76 98 91 30 16 94 71 67 58 79 61 97 47
Card 192: 50 89 39 56 84 10 7 38 30 16 | 22 74 37 16 32 27 20 82 98 84 54 59 64 18 73 41 49 96 52 31 50 69 80 39 76
Card 193: 31 55 2 53 20 8 77 4 69 32 | 70 11 93 14 61 89 23 82 83 86 3 95 33 16 87 75 6 26 45 43 78 13 7 65 10
Card 194: 4 25 98 37 14 57 48 51 32 49 | 1 76 22 36 90 98 69 66 75 5 51 7 11 34 77 82 50 33 19 15 27 35 40 68 62
Card 195: 71 53 67 95 17 30 70 3 45 34 | 21 18 33 89 79 5 86 90 8 1 47 26 52 19 77 23 35 32 98 67 50 28 84 25 74
Card 196: 92 31 21 61 43 30 59 60 69 97 | 94 51 64 36 16 22 13 48 20 65 52 90 34 2 42 79 19 5 91 26 29 54 78 87 47
Card 197: 23 31 94 44 51 27 8 13 14 85 | 20 89 92 5 11 67 3 66 50 99 18 9 34 69 86 81 21 59 16 80 35 15 38 28 77
Card 198: 32 86 91 57 48 52 69 22 59 56 | 9 28 29 83 80 4 57 32 38 47 91 52 56 19 86 48 6 59 93 22 69 36 96 74 25
Card 199: 56 75 88 61 80 4 90 82 62 19 | 69 52 32 9 14 11 88 60 37 76 54 55 30 79 61 49 18 35 83 29 77 47 45 73 75
Card 200: 4 81 76 51 59 48 2 7 78 20 | 22 78 31 7 46 17 76 41 51 6 88 82 81 95 26 52 2 20 42 4 16 5 72 59 91
Card 201: 90 38 92 41 6 54 2 44 36 14 | 90 48 41 61 8 92 11 70 26 63 42 85 80 7 84 5 32 67 51 36 73 57 45 18 9
Card 202: 49 48 4 87 99 12 55 27 65 3 | 41 24 57 49 12 66 27 76 38 15 19 9 79 60 81 7 84 33 51 32 71 6 54 85 94
Card 203: 36 56 3 21 28 68 1 84 8 95 | 66 85 3 11 27 73 76 34 13 53 92 36 14 47 84 72 24 32 68 44 26 83 77 12 4
Card 204: 70 63 32 11 64 17 7 88 89 78 | 56 63 74 48 36 89 40 11 28 41 66 32 78 91 2 57 59 64 60 4 96 12 9 88 52
Card 205: 23 13 30 95 93 49 39 57 61 37 | 24 86 36 6 14 39 85 57 51 75 68 1 94 46 47 17 90 92 64 18 4 34 31 26 33
Card 206: 58 31 3 94 61 15 98 10 72 97 | 38 37 40 96 91 46 86 18 6 14 36 75 78 4 62 55 53 28 60 81 17 23 43 99 64
Card 207: 90 11 26 6 87 5 89 43 32 70 | 70 65 43 11 3 73 66 83 82 68 64 54 30 53 77 97 13 14 87 20 40 23 9 63 94
Card 208: 18 73 43 67 86 16 62 52 23 17 | 80 19 31 85 50 88 9 22 23 58 35 71 95 94 91 16 49 3 93 56 66 13 24 60 11
Card 209: 89 92 77 37 50 32 73 86 17 1 | 63 35 58 28 68 77 4 74 40 57 65 81 11 21 75 99 56 79 25 10 76 18 26 48 12
Card 210: 95 51 91 92 29 43 24 76 8 71 | 76 90 7 9 38 87 56 36 33 12 27 3 54 30 59 58 64 82 23 98 97 65 93 43 35
Card 211: 15 96 18 17 95 64 83 51 49 80 | 16 53 69 1 66 42 89 39 83 35 49 63 98 61 70 59 57 78 62 47 12 9 68 48 76
Card 212: 89 63 7 28 91 90 97 44 4 42 | 74 66 82 95 23 2 93 88 17 75 39 33 21 31 11 59 96 57 14 51 26 56 9 72 91
Card 213: 7 36 25 23 22 93 18 88 50 30 | 57 51 62 87 48 64 4 20 95 73 26 2 43 5 83 94 96 29 67 59 14 33 81 42 49

View File

@@ -0,0 +1,114 @@
use std::cmp::min;
use std::collections::HashSet;
use nom::{
bytes::complete::tag,
character::complete::{digit1, multispace1, u32},
multi::separated_list1,
sequence::{preceded, separated_pair, tuple},
IResult,
};
fn parse_input(input: &str) -> IResult<&str, Vec<(Vec<u32>, Vec<u32>)>> {
let (input, result) = separated_list1(
multispace1,
preceded(
tuple((tag("Card"), multispace1, digit1, tag(":"), multispace1)),
separated_pair(
separated_list1(multispace1, u32),
tuple((multispace1, tag("|"), multispace1)),
separated_list1(multispace1, u32),
),
),
)(input)?;
Ok((input, result))
}
fn card_score(card: &(Vec<u32>, Vec<u32>)) -> u32 {
let winning_numbers: HashSet<&u32> = HashSet::from_iter(card.0.iter());
let wins = card
.1
.iter()
.filter(|&number| winning_numbers.contains(number))
.count();
if wins == 0 {
0
} else {
2_u32.pow(wins as u32 - 1)
}
}
fn card_wins(card: &(Vec<u32>, Vec<u32>)) -> u32 {
let winning_numbers: HashSet<&u32> = HashSet::from_iter(card.0.iter());
card.1
.iter()
.filter(|&number| winning_numbers.contains(number))
.count() as u32
}
fn solve_1(scratchcards: &[(Vec<u32>, Vec<u32>)]) -> u32 {
scratchcards.iter().map(card_score).sum()
}
fn solve_2(scratchcards: &[(Vec<u32>, Vec<u32>)]) -> u32 {
let mut number_of_cards = vec![1; scratchcards.len()];
let card_wins = scratchcards.iter().map(card_wins).collect::<Vec<_>>();
for card_number in 0..scratchcards.len() {
for winner_card_numbers in (card_number + 1)
..min(
scratchcards.len(),
card_number + 1 + card_wins[card_number] as usize,
)
{
number_of_cards[winner_card_numbers] += number_of_cards[card_number];
}
}
number_of_cards.iter().sum()
}
fn main() {
println!("Hello, this is Patrick!");
let input_txt = include_str!("../input.txt");
let (_, scratchcards) = parse_input(input_txt).unwrap();
println!(
"The scratchcards are worth {} points",
solve_1(&scratchcards[..])
);
println!(
"The total number of scratchcards is {}",
solve_2(&scratchcards[..])
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let input_text = include_str!("../test_input.txt");
let (_, scratchcards) = parse_input(input_text).unwrap();
assert_eq!(solve_1(&scratchcards[..]), 13);
}
#[test]
fn test_2() {
let input_text = include_str!("../test_input.txt");
let (_, scratchcards) = parse_input(input_text).unwrap();
assert_eq!(solve_2(&scratchcards[..]), 30);
}
}

View File

@@ -0,0 +1,6 @@
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11

View File

@@ -0,0 +1,9 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.3"

View File

@@ -0,0 +1,254 @@
seeds: 1132132257 323430997 2043754183 4501055 2539071613 1059028389 1695770806 60470169 2220296232 251415938 1673679740 6063698 962820135 133182317 262615889 327780505 3602765034 194858721 2147281339 37466509
seed-to-soil map:
1280158874 0 45923291
0 1431836695 234754481
2476778759 365219074 73714061
3997869725 4152785341 16553125
3014496893 3731980396 420804945
3435301838 2667516045 60128827
2784964719 2727644872 187996890
792043155 613341484 49447658
1444573280 2476024240 74468580
2728723659 3675739336 56241060
2704677524 4236229588 24046135
2360313001 1780050354 116465758
1326082165 226504189 118491115
3495430665 3630596320 3607732
1519041860 662789142 56785021
3973462947 3383860003 24406778
1575826881 45923291 119425025
1695251906 766775600 665061095
2667516045 3323175190 6512477
4240794960 3329687667 54172336
720792676 344995304 20223770
489053726 438933135 143852141
741016446 746305099 20470501
3499038397 4169338466 66891122
761486947 582785276 30556208
3565929519 3249598798 73576392
659636803 165348316 61155873
234754481 2221724995 254299245
2674028522 4260275723 30649002
841490813 1896516112 325208883
632905867 719574163 26730936
1166699696 1666591176 113459178
2972961609 3634204052 41535284
4195000071 3408266781 45794889
4190957500 4290924725 4042571
3639505911 2915641762 333957036
4014422850 3454061670 176534650
soil-to-fertilizer map:
528009375 3804807330 65591757
3608285775 3569685636 235121694
432120564 3045118038 95888811
3843407469 1792428879 363149111
4206556580 2155577990 88410716
3441777 3141006849 428678787
1019419908 3870399087 424568209
593601132 2619299262 425818776
1443988117 3441777 1788987102
3232975219 2243988706 375310556
fertilizer-to-water map:
3768646817 2541098841 42522952
657445332 493998363 293094466
3153469588 3947073749 287697992
2513829777 3047249136 215146452
968568929 29638292 96921246
1600806946 1111339724 96961929
3880726440 2687212715 52238929
416544049 1090614661 20725063
1749924539 4274983783 15782292
1306572576 1208301653 21184719
2134505230 4234771741 40212042
1697768875 0 29638292
3811169769 2617656044 69556671
487527141 787092829 169918191
3932965369 2583621793 34034251
178562138 1471396125 237981911
2728976229 3010972799 36276337
2174717272 3262395588 176952386
3035746039 1749924539 117723549
2794475974 2764473831 241270065
437269112 443740334 50258029
2790274753 4290766075 4201221
3441167580 3767315650 179758099
3966999620 3439347974 327967676
2351669658 2236446487 162160119
1585319642 1229486372 15487304
1327757295 186177987 257562347
2765252566 2739451644 25022187
950539798 1709378036 18029131
1765706831 1867648088 368798399
1199093816 1363917365 107478760
3763417914 3005743896 5228903
1065490175 957011020 133603641
3620925679 2398606606 142492235
59618449 1244973676 118943689
0 126559538 59618449
water-to-light map:
2368177077 1928300684 68416280
3459327457 4032125413 181740227
2874128303 2996109939 93290692
40167335 1203835270 50270286
2984608918 3988581415 43543998
1295445723 891961544 129160430
232873619 72411133 344405432
4002859459 4225073350 66563582
3451555101 2874128303 4441992
3957368975 2950619455 45490484
4192270745 3148930063 6297777
1638782153 2125726715 498901151
3028152916 2912054150 38565305
577279051 1504061698 367203335
3418071246 2878570295 33483855
3897839543 3089400631 59529432
2967418995 3166056654 3449280
3641067684 3835626234 152955181
4147219041 3436688572 45051704
2436593357 1021121974 182713296
3066718221 3484273209 351353025
2647866375 1254105556 189577037
4198568522 3340289798 96398774
2619306653 39188438 21015758
2982075985 3481740276 2532933
4069423041 3155227840 10828814
2186332185 1443682593 52835141
90437621 678875874 142435998
980629741 2624627866 212815546
2239167326 1996716964 129009751
1424606153 571958210 106917664
0 1871265033 40167335
2980967789 4223965154 1108196
1619041805 450217426 19740348
1193445287 469957774 102000436
944482386 426277008 23940418
4080251855 3169505934 66967186
1548392133 821311872 70649672
1531523817 1911432368 16868316
2970868275 4213865640 10099514
3455997093 4291636932 3330364
2137683304 416816565 9460443
3794022865 3236473120 103816678
2147143747 0 39188438
2640322411 1496517734 7543964
968422804 60204196 12206937
light-to-temperature map:
224631556 2579077346 68012835
93390978 2647090181 93292258
836334842 260175809 93895333
3305235739 4175688657 119278639
2495493200 354071142 67947352
2563440552 648390650 214063090
4184988573 4065709934 109978723
930230175 2740382439 151863620
2777503642 1813071562 114742417
3424514378 3772814840 292895094
1492090043 422018494 226372156
3717409472 3176683751 126763710
3273297 2243837725 90117681
1216313119 2511603925 67473421
4104753748 3096448926 80234825
2392410003 1112358810 103083197
759707869 2434976952 76626973
2031212648 2333955406 101021546
2132234194 0 260175809
1718462199 1931087276 312750449
186683236 1682505485 37948320
1174711552 1070757243 41601567
292644391 1215442007 467063478
3844173182 3512234274 260580566
1283786540 862453740 208303503
3096448926 3303447461 208786813
1082093795 1720453805 92617757
0 1927813979 3273297
temperature-to-humidity map:
1908382071 0 48093237
1668173777 369927146 108464980
2454615458 3265918092 19222900
2948843885 2383489773 582426713
1291899323 304752282 65174864
4051886972 3793288156 243080324
2849120094 3285140992 99723791
2415628816 3186987107 38986642
724194709 716571124 379381363
1103576072 2070505932 18664072
3531270598 1602200086 102620550
4020906946 3755760878 30980026
1122240144 2285968817 97520956
2779959793 1533039785 69160301
1357074187 2089170004 196798813
1823337263 624772153 85044808
561911923 1433912547 99127238
2538151277 1095952487 222368482
1776638757 709816961 6754163
2248869517 1776958859 59989455
2760519759 48093237 3497277
3770981692 4278303020 16664276
3755760878 4263082206 15220814
2497298857 263899862 40852420
2473838358 1900103862 23460499
234010997 51590514 212309348
661039161 1836948314 63155548
0 1923564361 87630970
1219761100 1704820636 72138223
87630970 478392126 146380027
1956475308 3462247498 171643650
3787645968 3786740904 6547252
2764017036 2054563175 15942757
2171486802 3384864783 77382715
446320345 1318320969 115591578
1783392920 3225973749 39944343
2308858972 2965916486 106769844
1553873000 3072686330 114300777
3794193220 4036368480 226713726
2128118958 2011195331 43367844
humidity-to-location map:
2944942064 3820503519 61983659
3834803738 3234323053 106874653
2156211251 3962463577 28956273
483302901 3882487178 79976399
2282996952 2161034243 46548053
2629999410 1876993734 225283872
3370099006 3129013552 105309501
1029930529 620272722 135507476
3572091970 2932598747 109287331
3739626327 942443797 51739908
3311342369 2102277606 58756637
3941678391 399929037 136325691
1245368468 58880743 172279414
790057642 1189404679 239872887
1498307968 3341197706 67668316
273081010 616914814 3357908
2501095485 2803694822 128903925
3475408507 4198283833 96683463
1860675375 3456652816 219039792
245544342 2207582296 27536668
3006925723 1666468371 210525363
3791366235 3733939634 11933242
1165438005 1502653815 79930463
1691906495 231160157 168768880
1590576804 994183705 101329691
2079715167 2235118964 76496084
276438918 3991419850 206863983
563279300 2507766048 226778342
2855283282 3408866022 47786794
1565976284 2311615048 24600520
3217451086 1095513396 93891283
3803299477 1429277566 31504261
4161888175 2757743175 45951647
2903070076 1460781827 41871988
3681379301 3675692608 58247026
4207839822 3041886078 87127474
2185167524 2734544390 23198785
2329545005 2336215568 171550480
4078004082 1582584278 83884093
1417647882 536254728 80660086
58880743 755780198 186663599
2208366309 3745872876 74630643

View File

@@ -0,0 +1,338 @@
use nom::{
bytes::complete::tag,
character::complete::{i64, multispace0, multispace1},
multi::separated_list1,
sequence::{delimited, tuple},
IResult, Parser,
};
/// This function assumes your input vector is sorted.
/// It might break if this is not the case.
/// We don't check if this is actually true, because that would take O(n) time,
/// while we aim for this function to only take up O(log n) time.
fn binary_search<'a, Item: Ord + Eq>(
value_to_find: &Item,
vector_to_find_it_in: &'a Vec<Item>,
) -> Option<&'a Item> {
if vector_to_find_it_in.is_empty() {
None
} else {
let mut index = vector_to_find_it_in.len() / 2;
let mut lower = 0;
let mut upper = vector_to_find_it_in.len() - 1;
while upper != lower {
if vector_to_find_it_in[index] <= *value_to_find {
upper = index;
} else {
lower = index;
}
index = (upper - lower) / 2;
}
if vector_to_find_it_in[index] == *value_to_find {
Some(&vector_to_find_it_in[index])
} else {
None
}
}
}
fn give_map_parser<'a: 'b, 'b: 'a>(
map_name: &'a str,
) -> impl FnMut(&'a str) -> IResult<&'b str, Vec<(i64, i64, i64)>> {
delimited(
tag(map_name),
separated_list1(
multispace1,
tuple((i64, multispace1, i64, multispace1, i64)).map(|(a, _, b, _, c)| (a, b, c)),
),
multispace0,
)
}
fn parse_input(
input: &str,
) -> IResult<
&str,
(
Vec<i64>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
),
> {
let (input, result) = tuple((
delimited(tag("seeds: "), separated_list1(tag(" "), i64), multispace1),
give_map_parser("seed-to-soil map:\n"),
give_map_parser("soil-to-fertilizer map:\n"),
give_map_parser("fertilizer-to-water map:\n"),
give_map_parser("water-to-light map:\n"),
give_map_parser("light-to-temperature map:\n"),
give_map_parser("temperature-to-humidity map:\n"),
give_map_parser("humidity-to-location map:\n"),
))(input)?;
Ok((input, result))
}
fn destination_to_source_mapping(source: i64, mappings: &Vec<(i64, i64, i64)>) -> i64 {
mappings
.iter()
.filter(|&(_destination_start, source_start, range)| {
source >= *source_start && source < *source_start + *range
})
.next()
.map(|(destination_start, source_start, _range)| {
destination_start + (source - source_start)
})
.unwrap_or(source)
}
fn solve_1(
almanac: &(
Vec<i64>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
),
) -> i64 {
almanac
.0
.iter()
.map(|&seed| {
let soil = destination_to_source_mapping(seed, &almanac.1);
let fertilizer = destination_to_source_mapping(soil, &almanac.2);
let water = destination_to_source_mapping(fertilizer, &almanac.3);
let light = destination_to_source_mapping(water, &almanac.4);
let temperature = destination_to_source_mapping(light, &almanac.5);
let humidity = destination_to_source_mapping(temperature, &almanac.6);
destination_to_source_mapping(humidity, &almanac.7)
})
.min()
.unwrap()
}
fn search_range(
input_range: (i64, i64),
mappings: &Vec<(i64, i64, i64)>,
) -> Option<(i64, i64, i64)> {
if mappings.is_empty() {
None
} else {
let mut index = mappings.len() / 2;
let mut lower = 0;
let mut upper = mappings.len() - 1;
while upper != lower {
if mappings[index].1 <= input_range.0
&& mappings[index].1 + mappings[index].2 > input_range.0
{
return Some(mappings[index]);
} else if mappings[index].1 < input_range.0 {
lower = index;
} else {
upper = index - 1;
}
index = (upper + lower).div_ceil(2);
}
if index >= mappings.len() - 1 && mappings[index].1 + mappings[index].2 < input_range.1 {
None
} else if mappings[index].1 == input_range.0 {
mappings.get(index + 1).copied()
} else {
Some(mappings[index])
}
}
}
/// We will assume the mappings are sorted on the source, so we can more quickly, using binary search, find
/// the suitable ranges. This is relevant because of the large numbers involved.
fn get_suitable_range(input_range: (i64, i64), mappings: &Vec<(i64, i64, i64)>) -> Vec<(i64, i64)> {
let mut found_until = input_range.0;
let mut result = vec![];
while found_until < input_range.1 {
println!(
"{} {:?} {:?}",
found_until,
mappings,
search_range((found_until, input_range.1), mappings)
);
if let Some((destination_start, source_start, range)) =
search_range((found_until, input_range.1), mappings)
{
if source_start > found_until {
println!("ding");
result.push((found_until, std::cmp::min(source_start, input_range.1)));
found_until = std::cmp::min(source_start, input_range.1);
} else {
println!("dong");
let max_source = std::cmp::min(source_start + range, input_range.1);
result.push((
found_until + (destination_start - source_start),
destination_start + (max_source - source_start),
));
found_until = max_source;
}
} else {
println!("dang");
result.push((found_until, input_range.1));
found_until = input_range.1;
}
}
result
}
fn get_suitable_ranges(
input_ranges: &Vec<(i64, i64)>,
mappings: &Vec<(i64, i64, i64)>,
) -> Vec<(i64, i64)> {
let mut output_ranges_uncompressed = input_ranges
.iter()
.map(|&(range_start, range_length)| {
get_suitable_range((range_start, range_start + range_length), mappings)
})
.collect::<Vec<Vec<(i64, i64)>>>()
.into_iter()
.flatten()
.collect::<Vec<(i64, i64)>>();
output_ranges_uncompressed.sort_unstable();
let (mut lower, mut upper) = output_ranges_uncompressed[0];
let mut output_ranges = vec![];
for (range_low, range_up) in output_ranges_uncompressed {
if range_low <= upper {
upper = range_up;
} else {
output_ranges.push((lower, upper));
lower = range_low;
upper = range_up;
}
}
output_ranges.push((lower, upper));
output_ranges = output_ranges
.iter()
.map(|&(range_start, range_end)| (range_start, range_end - range_start))
.collect::<Vec<_>>();
output_ranges
}
fn solve_2(
almanac: &(
Vec<i64>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
Vec<(i64, i64, i64)>,
),
) -> i64 {
let mut lowest_location_numbers = vec![];
let mut seed_iter = almanac.0.iter();
let mut soil_almanac = almanac.1.iter().map(|&n| n).collect::<Vec<_>>();
soil_almanac.sort_unstable_by(|&(_d1, source1, _r1), (_d2, source2, _r2)| source1.cmp(source2));
let mut fertilizer_almanac = almanac.2.iter().map(|&n| n).collect::<Vec<_>>();
fertilizer_almanac
.sort_unstable_by(|&(_d1, source1, _r1), (_d2, source2, _r2)| source1.cmp(source2));
let mut water_almanac = almanac.3.iter().map(|&n| n).collect::<Vec<_>>();
water_almanac
.sort_unstable_by(|&(_d1, source1, _r1), (_d2, source2, _r2)| source1.cmp(source2));
let mut light_almanac = almanac.4.iter().map(|&n| n).collect::<Vec<_>>();
light_almanac
.sort_unstable_by(|&(_d1, source1, _r1), (_d2, source2, _r2)| source1.cmp(source2));
let mut temperature_almanac = almanac.5.iter().map(|&n| n).collect::<Vec<_>>();
temperature_almanac
.sort_unstable_by(|&(_d1, source1, _r1), (_d2, source2, _r2)| source1.cmp(source2));
let mut humidity_almanac = almanac.6.iter().map(|&n| n).collect::<Vec<_>>();
humidity_almanac
.sort_unstable_by(|&(_d1, source1, _r1), (_d2, source2, _r2)| source1.cmp(source2));
let mut location_almanac = almanac.7.iter().map(|&n| n).collect::<Vec<_>>();
location_almanac
.sort_unstable_by(|&(_d1, source1, _r1), (_d2, source2, _r2)| source1.cmp(source2));
while let (Some(&lower_seed), Some(&range_length)) = (seed_iter.next(), seed_iter.next()) {
println!("ding");
let seed_range = vec![(lower_seed, range_length)];
let soil_ranges = get_suitable_ranges(&seed_range, &soil_almanac);
println!("soil");
let fertilizer_ranges = get_suitable_ranges(&soil_ranges, &fertilizer_almanac);
println!("fertilizer");
let water_ranges = get_suitable_ranges(&fertilizer_ranges, &water_almanac);
println!("water");
let light_ranges = get_suitable_ranges(&water_ranges, &light_almanac);
println!("light");
let temperature_ranges = get_suitable_ranges(&light_ranges, &temperature_almanac);
println!("temperature");
let humidity_ranges = get_suitable_ranges(&temperature_ranges, &humidity_almanac);
println!("humidity");
lowest_location_numbers.push(
get_suitable_ranges(&humidity_ranges, &location_almanac)
.iter()
.map(|&(range_min, _range_max)| range_min)
.min()
.unwrap(),
);
}
*lowest_location_numbers.iter().min().unwrap()
}
fn main() {
println!("Hello, this is Patrick!");
let input_text = include_str!("../input.txt");
let (_, almanac) = parse_input(input_text).unwrap();
println!(
"The lowest location number corresponding to the initial seed numbers is {}",
solve_1(&almanac)
);
println!(
"The lowest location number for any of the initial seed ranges is {}",
solve_2(&almanac)
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let input_text = include_str!("../test_input.txt");
let (_, almanac) = parse_input(input_text).unwrap();
assert_eq!(solve_1(&almanac), 35);
}
#[test]
fn test_2() {
let input_text = include_str!("../test_input.txt");
let (_, almanac) = parse_input(input_text).unwrap();
assert_eq!(solve_2(&almanac), 46);
}
}

View File

@@ -0,0 +1,33 @@
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

View File

@@ -0,0 +1,9 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.3"

View File

@@ -0,0 +1,2 @@
Time: 35 93 73 66
Distance: 212 2060 1201 1044

View File

@@ -0,0 +1,100 @@
use std::iter::zip;
use nom::{
bytes::complete::tag,
character::complete::{multispace0, multispace1, u64},
multi::separated_list1,
sequence::tuple,
IResult,
};
fn parse_input(input: &str) -> IResult<&str, Vec<(u64, u64)>> {
let (input, result) = tuple((
tag("Time:"),
multispace0,
separated_list1(multispace1, u64),
multispace0,
tag("Distance:"),
multispace0,
separated_list1(multispace1, u64),
))(input)
.map(|(i, (_, _, times, _, _, _, distances))| (i, (times, distances)))?;
let result = zip(result.0, result.1).collect();
Ok((input, result))
}
fn record_beating_ways(time_distance_pair: (u64, u64)) -> usize {
(1..=time_distance_pair.0)
.into_iter()
.filter(|&time_charging| {
(time_distance_pair.0 - time_charging) * time_charging > time_distance_pair.1
})
.count()
}
fn solve_1(time_distance_pairs: &[(u64, u64)]) -> u64 {
time_distance_pairs
.iter()
.map(|&pair| record_beating_ways(pair) as u64)
.product()
}
fn solve_2(time_distance_pairs: &[(u64, u64)]) -> u64 {
let time_distance_pair = time_distance_pairs.iter().fold(
(0, 0),
|(output_time, output_distance), &(time, distance)| {
let time_len = (time as f64).log10().floor() as u32 + 1;
let distance_len = (distance as f64).log10().floor() as u32 + 1;
(
output_time * 10u64.pow(time_len) as u64 + time,
output_distance * 10u64.pow(distance_len) as u64 + distance,
)
},
);
record_beating_ways(time_distance_pair) as u64
}
fn main() {
println!("Hello, this is Patrick!");
let input_text = include_str!("../input.txt");
let (_, time_distance_pairs) = parse_input(input_text).unwrap();
println!(
"The product of the number of ways you could beat the record is {}",
solve_1(&time_distance_pairs[..])
);
println!(
"The longer race can be won in {} ways",
solve_2(&time_distance_pairs[..])
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let input_text = include_str!("../test_input.txt");
let (_, time_distance_pairs) = parse_input(input_text).unwrap();
assert_eq!(solve_1(&time_distance_pairs[..]), 288);
}
#[test]
fn test_2() {
let input_text = include_str!("../test_input.txt");
let (_, time_distance_pairs) = parse_input(input_text).unwrap();
assert_eq!(solve_2(&time_distance_pairs[..]), 71503);
}
}

View File

@@ -0,0 +1,2 @@
Time: 7 15 30
Distance: 9 40 200

View File

@@ -0,0 +1,7 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
[dependencies]
nom = "7.1.3"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,263 @@
use std::{cmp::Ordering, collections::HashMap, iter::zip};
use nom::{
character::complete::{alphanumeric1, multispace1, u64},
multi::separated_list1,
sequence::separated_pair,
IResult, Parser,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum HandType {
HighCard,
OnePair,
TwoPair,
ThreeKind,
FullHouse,
FourKind,
FiveKind,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum CardType {
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
T,
Jack,
Queen,
King,
Ace,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum CardType2 {
Jack,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
T,
Queen,
King,
Ace,
}
fn parse_input(input: &str) -> IResult<&str, Vec<(String, u64)>> {
let (input, result) = separated_list1(
multispace1,
separated_pair(alphanumeric1::<&str, _>, multispace1, u64)
.map(|(hand, bid)| (hand.to_string(), bid)),
)(input)?;
Ok((input, result))
}
fn classify_hand(hand: &String) -> HandType {
use HandType::*;
let mut card_numbers: HashMap<char, i32> = HashMap::new();
for c in hand.to_owned().chars() {
card_numbers.insert(
c,
match card_numbers.get(&c) {
Some(n) => n + 1,
None => 1,
},
);
}
let mut card_numbers = card_numbers.values().collect::<Vec<_>>();
card_numbers.sort_unstable();
match card_numbers[..] {
[1, 1, 1, 1, 1] => HighCard,
[1, 1, 1, 2] => OnePair,
[1, 2, 2] => TwoPair,
[1, 1, 3] => ThreeKind,
[2, 3] => FullHouse,
[1, 4] => FourKind,
[5] => FiveKind,
_ => unreachable!(),
}
}
fn classify_hand2(hand: &String) -> HandType {
use HandType::*;
let mut card_numbers: HashMap<char, i32> = HashMap::new();
for c in hand.to_owned().chars() {
card_numbers.insert(
c,
match card_numbers.get(&c) {
Some(n) => n + 1,
None => 1,
},
);
}
if let Some(jokers) = card_numbers.remove(&'J') {
let mut card_numbers = card_numbers.values().collect::<Vec<_>>();
card_numbers.sort_unstable();
let highest = card_numbers.pop().unwrap_or(&0) + jokers;
card_numbers.push(&highest);
match card_numbers[..] {
[1, 1, 1, 2] => OnePair,
[1, 1, 3] => ThreeKind,
[2, 3] => FullHouse,
[1, 4] => FourKind,
[5] => FiveKind,
_ => unreachable!(),
}
} else {
let mut card_numbers = card_numbers.values().collect::<Vec<_>>();
card_numbers.sort_unstable();
match card_numbers[..] {
[1, 1, 1, 1, 1] => HighCard,
[1, 1, 1, 2] => OnePair,
[1, 2, 2] => TwoPair,
[1, 1, 3] => ThreeKind,
[2, 3] => FullHouse,
[1, 4] => FourKind,
[5] => FiveKind,
_ => unreachable!(),
}
}
}
fn classify_card(card: char) -> CardType {
use CardType::*;
match card {
'A' => Ace,
'K' => King,
'Q' => Queen,
'J' => Jack,
'T' => T,
'9' => Nine,
'8' => Eight,
'7' => Seven,
'6' => Six,
'5' => Five,
'4' => Four,
'3' => Three,
'2' => Two,
_ => unreachable!(),
}
}
fn classify_card2(card: char) -> CardType2 {
use CardType2::*;
match card {
'A' => Ace,
'K' => King,
'Q' => Queen,
'T' => T,
'9' => Nine,
'8' => Eight,
'7' => Seven,
'6' => Six,
'5' => Five,
'4' => Four,
'3' => Three,
'2' => Two,
'J' => Jack,
_ => unreachable!(),
}
}
fn compare_hands(hand_1: &String, hand_2: &String) -> Ordering {
let (hand_type_1, hand_type_2) = (classify_hand(hand_1), classify_hand(hand_2));
if hand_type_1 == hand_type_2 {
for (card_1, card_2) in zip(hand_1.to_owned().chars(), hand_2.to_owned().chars()) {
if card_1 != card_2 {
return classify_card(card_1).cmp(&classify_card(card_2));
}
}
Ordering::Equal
} else {
hand_type_1.cmp(&hand_type_2)
}
}
fn compare_hands2(hand_1: &String, hand_2: &String) -> Ordering {
let (hand_type_1, hand_type_2) = (classify_hand2(hand_1), classify_hand2(hand_2));
if hand_type_1 == hand_type_2 {
for (card_1, card_2) in zip(hand_1.to_owned().chars(), hand_2.to_owned().chars()) {
if card_1 != card_2 {
return classify_card2(card_1).cmp(&classify_card2(card_2));
}
}
Ordering::Equal
} else {
hand_type_1.cmp(&hand_type_2)
}
}
fn solve_1(plays: &Vec<(String, u64)>) -> u64 {
let mut plays = plays.clone();
plays.sort_unstable_by(|(hand_1, _bid1), (hand_2, _bid2)| compare_hands(hand_1, hand_2));
plays
.into_iter()
.enumerate()
.map(|(rank, (_hand, bid))| (rank as u64 + 1) * bid)
.sum()
}
fn solve_2(plays: &Vec<(String, u64)>) -> u64 {
let mut plays = plays.clone();
plays.sort_unstable_by(|(hand_1, _bid1), (hand_2, _bid2)| compare_hands2(hand_1, hand_2));
plays
.into_iter()
.enumerate()
.map(|(rank, (_hand, bid))| (rank as u64 + 1) * bid)
.sum()
}
fn main() {
println!("Hello, this is Patrick!");
let input_text = include_str!("../input.txt");
let (_, plays) = parse_input(input_text).unwrap();
println!("The total winnings are {}", solve_1(&plays));
println!("The new total winnings are {}", solve_2(&plays));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let input_text = include_str!("../test_input.txt");
let (_, plays) = parse_input(input_text).unwrap();
assert_eq!(solve_1(&plays), 6440);
}
#[test]
fn test_2() {
let input_text = include_str!("../test_input.txt");
let (_, plays) = parse_input(input_text).unwrap();
assert_eq!(solve_2(&plays), 5905);
}
}

View File

@@ -0,0 +1,5 @@
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483

View File

@@ -0,0 +1,9 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.3"

View File

@@ -0,0 +1,800 @@
LLRLRLLRRLRLRLLRRLRRRLRRRLRRLRRLRLRLRRRLLRLRRLRLRRRLRLLRRLRLRLLRRRLLRLRRRLRLRRLRRLRLLRRLRRLRLRLRLLRLLRRLRRLRRLRRLRRLRLLRLRLRRRLRRRLRRLRLRLRRLRRRLRLRRRLRLRLRLRRRLRRLRRLRRRLLLLRRLRRLRLRRRLRLRRRLRRLLLLRLRLRRRLRRRLRLRRLLRLRLRRRLRLRLRRRLRLLRRRLRRLRLRLRRRLRLLRRLLRRRLRRRLRRRLRRLRLRLRRRLRRRLRRRLLRRRR
NNN = (TNT, XDJ)
GKJ = (TQD, PDP)
VPC = (TST, FDJ)
MNG = (GQS, RVK)
JQF = (LLK, BQH)
HPS = (XDJ, TNT)
VSD = (GNK, HJS)
VGT = (KXR, FMP)
GQB = (GTX, HLC)
PLJ = (QCS, TVN)
BXM = (GMB, LBC)
XJQ = (NHG, NQD)
NKX = (KBJ, GTS)
PKT = (XFK, SKR)
HJB = (LRX, KQG)
SNM = (PLN, CJT)
LQD = (MTK, KMS)
KTN = (SSC, KPL)
LVJ = (CQJ, GPP)
GSV = (SNM, JKK)
CPH = (DCQ, FCP)
TDV = (JFD, HKH)
SBS = (NFC, CGC)
DBG = (GST, LGH)
LHS = (GHG, TRD)
BPP = (DLF, NJT)
TNT = (VNX, PTR)
VTN = (XHM, NMQ)
BRD = (KLF, HXJ)
TJT = (BVD, PFN)
GNK = (NMT, LLX)
DVH = (GQS, RVK)
KRJ = (QSP, TTQ)
KQC = (TNX, MDC)
XVS = (LRC, DLC)
XLP = (XCH, BJQ)
KQG = (LKK, TVP)
QHB = (JPL, JPL)
RGV = (SXB, FKH)
GSK = (JQN, THB)
XDT = (GLG, XKD)
XCT = (MMN, XDM)
KLF = (NPB, RRB)
XLT = (QRB, VHB)
HKS = (NNN, HPS)
NMT = (MSL, VXC)
PML = (NHN, FQH)
FMQ = (HGC, FBH)
JGG = (XTB, XTB)
KMC = (PPS, SVT)
GLG = (SPG, KFK)
QJN = (HJB, QCP)
SGH = (FDV, QPX)
DFM = (BFX, PNS)
CSK = (MDQ, GFX)
MXG = (MXC, BJV)
JTX = (SQN, JBK)
KFN = (VQM, PFH)
SFJ = (KDF, NKB)
JNK = (DLK, LHV)
DTG = (XHQ, DSR)
SHC = (FQV, HKK)
DBM = (VDP, PGK)
PNC = (LMH, RXH)
HXJ = (RRB, NPB)
MKS = (KMX, FKS)
NPA = (TPC, SNK)
LJK = (FPF, SHP)
LBH = (HQB, TTC)
JML = (LTN, SFS)
MXS = (FDL, SXH)
HHV = (VRL, JVC)
NQD = (KVJ, DXM)
HMA = (TVC, RBX)
BCP = (SQD, RGD)
SLP = (CQF, HXG)
KGF = (RPN, PKQ)
TGG = (VQM, PFH)
HQD = (MDV, GND)
BJX = (LCN, QMG)
NBQ = (NSV, VJR)
BBX = (KHG, FDC)
SSQ = (BNQ, MXX)
TST = (MJB, TDV)
JQL = (SDG, DLJ)
TVN = (SJM, KMC)
XHD = (DDG, RSG)
GQA = (NQS, CNH)
QFL = (QSQ, VVN)
THG = (FBM, VQX)
QLZ = (RBX, TVC)
TPM = (DQN, MGG)
QXV = (MTK, KMS)
VNX = (PTP, VSD)
STQ = (XDC, JFR)
XVQ = (PJM, MRN)
XTT = (BHF, RBR)
LQS = (DBB, HNR)
KXG = (FKS, KMX)
XCP = (MXK, DBX)
QRV = (JSK, STC)
VVG = (DRF, QNR)
FTC = (CSK, FPC)
GFV = (VSK, GFQ)
JSM = (LNC, XTF)
LJC = (JFG, XBK)
TQD = (XJQ, MFM)
HJS = (LLX, NMT)
CBP = (PTX, LGD)
LGT = (CTD, CTD)
HMP = (FQJ, KGC)
MSL = (MSD, BFL)
QPX = (QFH, JMK)
KBH = (MGF, TMH)
XMT = (MXC, BJV)
XGR = (KPF, DLH)
RGH = (MBM, KNT)
CDP = (BLG, NVN)
BLG = (TQC, DTD)
MSD = (RVP, RQP)
KXT = (CVM, JQL)
MRN = (MNX, PNC)
RLG = (BNP, VNR)
PSH = (XQG, SLP)
XTF = (NTT, VGT)
KVJ = (JVX, HPJ)
PGF = (KRJ, CRS)
VSV = (NKQ, PJG)
TLV = (QHJ, GFG)
BNP = (NFR, PGR)
XQG = (CQF, HXG)
KGC = (FKF, KCS)
HQF = (QPX, FDV)
PFN = (JGX, FMQ)
HFD = (DBG, CBD)
KQZ = (HXJ, KLF)
HPM = (VSV, LTR)
FGX = (SVR, GQB)
SGJ = (THB, JQN)
NKK = (QHB, QHB)
FLF = (RLC, MXP)
SRV = (QHM, LQS)
NPB = (BPG, CVQ)
VNR = (NFR, PGR)
FNF = (TXL, CXT)
PTB = (QXQ, BDK)
BXN = (HQF, SGH)
RGT = (MGN, GFN)
FSP = (VRK, QNN)
GHT = (PML, HTJ)
CBD = (LGH, GST)
LMH = (TJC, DNN)
PTP = (GNK, HJS)
XDC = (GHT, JTR)
HTJ = (NHN, FQH)
XFK = (NKX, HTV)
PBP = (CJJ, GKS)
KMX = (XSJ, PMK)
CVQ = (FKX, GXP)
SFV = (MXS, FLR)
BQH = (VMH, PKT)
NFR = (RTX, SBJ)
KCS = (XGR, JXT)
GND = (SFJ, DGL)
DTF = (JCC, LVC)
KLM = (XLP, QRQ)
VQV = (DNC, SST)
NKF = (KFN, TGG)
CJT = (LDP, QKM)
NPF = (TNC, LXF)
MHK = (MLX, NHX)
LGD = (DLP, CNJ)
MLF = (QKK, QRK)
LQB = (NKJ, SHN)
SNS = (KMV, HCG)
VPN = (HFV, LNX)
XTB = (XLT, VRF)
LNX = (HFB, QVF)
XGF = (NRN, KCF)
PNS = (JNQ, MCT)
BJG = (DNC, SST)
PQN = (SCL, VPX)
NGQ = (DGT, RLF)
GGX = (LQS, QHM)
VVT = (MHK, LTJ)
QJH = (XTF, LNC)
BBP = (FNX, RTK)
DDP = (JBR, KLD)
GDV = (KXT, BJT)
GDT = (CFB, PSH)
LGH = (CRK, SCF)
JNB = (DXQ, FBK)
DLH = (XJD, GDT)
NCQ = (MXP, RLC)
LXP = (SPR, RTF)
GRQ = (FNX, RTK)
KBJ = (DNB, TDP)
LXK = (CTD, JML)
DBB = (TJD, FNF)
RBR = (JTX, XKN)
GPD = (LXN, PLD)
JNM = (QRM, MSV)
LNC = (VGT, NTT)
GVT = (VVN, QSQ)
KCD = (GFB, MFL)
HDG = (VFQ, DTF)
RGD = (GGX, SRV)
KJK = (SRJ, QGV)
DSL = (MNG, DVH)
DSR = (VQV, BJG)
NHB = (HPS, NNN)
JVX = (JRT, GDQ)
TGB = (DCG, VXK)
MXN = (PST, GBF)
CTP = (XGM, SFV)
BPG = (GXP, FKX)
HRT = (LXF, TNC)
SST = (HDG, VJS)
PDP = (XJQ, MFM)
BDK = (TFM, GRM)
PPS = (RQV, BXN)
SSS = (TJQ, GNQ)
TXL = (QRV, PPH)
RRQ = (RXF, PGF)
PSX = (LLM, FXM)
FBK = (JDQ, DSX)
JLR = (LSM, NXT)
SPR = (DTG, RKQ)
PGC = (TJT, HXC)
LLD = (LHS, RLV)
NRH = (XBB, FGX)
SXH = (HMP, LSK)
JVC = (MLN, XKM)
MGF = (GGT, XMS)
TTS = (TNX, TNX)
FCP = (PLJ, KND)
LRX = (TVP, LKK)
VKJ = (PGN, XPX)
VRL = (XKM, MLN)
RQV = (SGH, HQF)
CRS = (QSP, TTQ)
BJC = (FCJ, TSC)
CSP = (BNM, FLN)
XHQ = (BJG, VQV)
CRK = (DKC, QQQ)
HFB = (BVM, VMP)
SQN = (QJN, KKV)
DGK = (FVX, RGT)
HTP = (HCF, HFR)
RFT = (NMF, DRL)
TRJ = (SHN, NKJ)
XJD = (PSH, CFB)
FQJ = (FKF, KCS)
VHB = (KDM, DSB)
SKR = (NKX, HTV)
LCN = (TLV, FMC)
MTC = (PST, GBF)
QRK = (XNR, SPD)
TCK = (MDK, BCP)
DNN = (HHV, MVS)
JNQ = (PBP, VDG)
NKQ = (MKX, HVD)
FTV = (MNG, DVH)
SJM = (SVT, PPS)
KCB = (NKK, CNF)
KJN = (PRV, BVK)
PRV = (SVP, FTM)
HFV = (HFB, QVF)
NFC = (FVC, TBN)
LMC = (QRK, QKK)
KNF = (CHN, GFV)
XNP = (SGJ, GSK)
QQB = (MLF, LMC)
CVM = (DLJ, SDG)
RSG = (LBH, TLD)
PGR = (RTX, SBJ)
VTD = (QGV, SRJ)
LBC = (PRH, CSP)
RKX = (NHL, XMM)
MXK = (XJN, PTB)
MJD = (DLC, LRC)
GDR = (FCX, KNF)
VXK = (THG, BPN)
GPP = (NRC, DHQ)
SDN = (FKH, SXB)
KJH = (BJX, VHX)
RNQ = (DNX, GPL)
VQX = (RXP, SSS)
PPH = (JSK, STC)
KKV = (HJB, QCP)
ZZZ = (FGX, XBB)
PTN = (KCD, HPQ)
GMP = (KHG, FDC)
NTT = (KXR, FMP)
GBF = (KXG, MKS)
VPX = (JFB, HSN)
SVG = (BPP, RPK)
PJG = (MKX, HVD)
HNR = (TJD, FNF)
XBB = (SVR, GQB)
FBM = (SSS, RXP)
RTX = (QJQ, KJN)
MSV = (KQH, LRF)
MGN = (LGT, LXK)
QDH = (CFV, DHZ)
NPR = (GDR, DCF)
HSN = (VLG, QNC)
PTM = (VGG, CQX)
VCP = (BCL, XDT)
LBP = (MPD, MPD)
NRK = (NNL, XKC)
QCT = (BBL, SVH)
RPL = (MMH, CDP)
RXH = (TJC, DNN)
DGL = (KDF, NKB)
GTQ = (PGF, RXF)
FXG = (BGH, MTH)
FQH = (VCJ, HPM)
LTN = (SCP, SCP)
JMK = (LPX, JNM)
SCL = (JFB, HSN)
TKV = (XHC, HQD)
BDT = (TTS, KQC)
MXX = (SKB, LPC)
RPN = (QJK, BXM)
MFL = (NDC, TPM)
DXM = (HPJ, JVX)
QXM = (LHS, RLV)
QHM = (HNR, DBB)
QRB = (KDM, DSB)
JMG = (PLD, LXN)
QSQ = (BNS, XNC)
CXA = (XLT, VRF)
MXC = (LQD, QXV)
CNJ = (QQP, PXV)
BPM = (BRD, BRD)
BFV = (FCJ, TSC)
KPL = (RPL, HBT)
JJR = (QNN, VRK)
KHG = (VDS, LKJ)
DRC = (HFR, HCF)
DLF = (RFT, STN)
GKS = (QQB, RLT)
TBD = (LFP, PQN)
XNC = (QBD, DDP)
TGC = (JNB, JXF)
KCF = (LBP, JHT)
NKB = (CCJ, RGH)
NPH = (JQF, QJC)
BJQ = (LJC, QMT)
GTS = (TDP, DNB)
XSJ = (KTN, VXJ)
QXQ = (GRM, TFM)
FCJ = (FKJ, DSK)
FPF = (CQH, HML)
VCJ = (LTR, VSV)
QJK = (LBC, GMB)
PMK = (VXJ, KTN)
FXM = (BNT, VVG)
DDG = (TLD, LBH)
MDB = (FDJ, TST)
BSF = (VXK, DCG)
BVK = (FTM, SVP)
RTG = (JSH, LKD)
BPN = (VQX, FBM)
BJT = (CVM, JQL)
DFS = (BCP, MDK)
GRM = (MDB, VPC)
TRD = (NRK, HPF)
FKH = (XHD, SNT)
LXF = (BDX, TKV)
JBK = (KKV, QJN)
JBP = (BNP, VNR)
PKF = (BJX, VHX)
DLK = (DGK, XST)
TFM = (MDB, VPC)
VDP = (VVR, MHR)
RDP = (VJR, NSV)
PTX = (CNJ, DLP)
DCG = (THG, BPN)
BCV = (LTJ, MHK)
FKJ = (NBQ, RDP)
PHK = (KGF, SBX)
JDQ = (PTN, RFF)
TNC = (BDX, TKV)
KCJ = (RPK, BPP)
DLJ = (FTC, TGF)
FQG = (GVT, QFL)
LFP = (SCL, VPX)
PBG = (KNC, PFX)
QCP = (LRX, KQG)
NRC = (GPD, JMG)
PHH = (DGT, RLF)
XCH = (LJC, QMT)
VXJ = (KPL, SSC)
TNX = (BPM, BPM)
PTR = (VSD, PTP)
NDC = (DQN, DQN)
SVT = (RQV, BXN)
NTJ = (SHC, QCM)
SHM = (SNM, JKK)
TLD = (TTC, HQB)
MMN = (JNK, RRS)
NPC = (MTC, MXN)
NMF = (QBM, CTP)
CQX = (NRH, ZZZ)
BNT = (DRF, QNR)
BJZ = (CNH, NQS)
KFK = (XCT, PPG)
SDG = (TGF, FTC)
CBB = (HFV, LNX)
VFQ = (LVC, JCC)
LRF = (KLM, JGL)
TTC = (JLR, GFT)
PFH = (SHG, XTT)
RLT = (MLF, LMC)
XPJ = (JPL, BJZ)
PKQ = (BXM, QJK)
TNS = (GDR, DCF)
FKX = (PKG, QQL)
MJB = (HKH, JFD)
JTN = (JSM, QJH)
QTG = (NRN, KCF)
MPX = (CHR, TGC)
JKK = (CJT, PLN)
LKK = (DRC, HTP)
RXF = (KRJ, CRS)
QNC = (LFB, FQG)
RKQ = (DSR, XHQ)
LCX = (PGK, VDP)
KSG = (LLD, QXM)
RPK = (NJT, DLF)
KDM = (KSG, PLL)
TVP = (HTP, DRC)
DCB = (NKK, NKK)
DQN = (STJ, STJ)
JSH = (TRS, GKJ)
LDP = (XGS, LJK)
QRM = (LRF, KQH)
VGG = (NRH, NRH)
LLK = (VMH, PKT)
VSK = (PHH, NGQ)
JFB = (VLG, QNC)
BCL = (XKD, GLG)
RTF = (RKQ, DTG)
KPF = (GDT, XJD)
DHZ = (SNK, TPC)
LPC = (DCB, KCB)
KDF = (RGH, CCJ)
PLL = (QXM, LLD)
XHS = (FXM, LLM)
BHF = (JTX, XKN)
RRS = (DLK, LHV)
FFL = (HKS, NHB)
VRF = (QRB, VHB)
LSQ = (MRN, PJM)
SCD = (MXK, DBX)
SPD = (FXG, RDX)
CFM = (PQN, LFP)
QKK = (SPD, XNR)
LVC = (JJR, FSP)
RLV = (TRD, GHG)
HKK = (SSP, XNP)
JCC = (FSP, JJR)
JHT = (MPD, SCN)
RVP = (XVQ, LSQ)
HPQ = (GFB, MFL)
JRT = (VTN, SKP)
DTD = (TGB, BSF)
PKG = (SKX, DGB)
VMP = (RLG, JBP)
DSX = (RFF, PTN)
QRQ = (BJQ, XCH)
LLX = (VXC, MSL)
SVH = (DFS, TCK)
XNR = (RDX, FXG)
QKM = (LJK, XGS)
MMH = (BLG, NVN)
SKB = (DCB, KCB)
JXT = (KPF, DLH)
SVV = (BCV, VVT)
KLD = (MHM, PVJ)
QNN = (SVV, NQK)
FCX = (GFV, CHN)
BNS = (QBD, DDP)
SHP = (HML, CQH)
TJD = (TXL, CXT)
BQF = (FCP, DCQ)
MKX = (SNS, CCN)
JKF = (NPH, KGL)
LFB = (QFL, GVT)
DCQ = (PLJ, KND)
SVP = (VGX, JCR)
PGN = (XMT, MXG)
NVZ = (VRF, XLT)
VBR = (BDM, LXP)
GTX = (PHK, DSN)
BDX = (XHC, HQD)
JGX = (HGC, FBH)
BBL = (DFS, TCK)
KNT = (BBX, GMP)
TLP = (LXH, TKF)
TDS = (CBB, VPN)
CTD = (LTN, LTN)
HCG = (RRQ, GTQ)
VRG = (TTS, KQC)
RLC = (TLP, FQX)
FBH = (DBM, LCX)
SCP = (TVC, RBX)
CGC = (TBN, FVC)
JFG = (NQP, GDV)
BVM = (RLG, JBP)
DCF = (KNF, FCX)
BJV = (QXV, LQD)
QBD = (JBR, KLD)
QFG = (BBL, SVH)
RFF = (HPQ, KCD)
QJQ = (PRV, BVK)
FMC = (QHJ, GFG)
PXV = (STQ, VHK)
VVN = (XNC, BNS)
NHG = (DXM, KVJ)
SSP = (SGJ, GSK)
QMT = (JFG, XBK)
VRK = (NQK, SVV)
SNT = (DDG, RSG)
RRB = (BPG, CVQ)
DXQ = (JDQ, DSX)
FMP = (SHM, GSV)
VMF = (FJX, VBR)
NKJ = (GKP, SBS)
XGM = (FLR, MXS)
SKX = (NLH, RTG)
XMS = (FDP, PRK)
SPG = (PPG, XCT)
QNR = (MPX, SXC)
MDC = (BPM, CTR)
SMR = (TJT, HXC)
TBN = (FJS, TDS)
BGH = (NPF, HRT)
VDS = (XHS, PSX)
RBX = (CDJ, PBG)
VLC = (CQJ, GPP)
SVR = (GTX, HLC)
MDV = (DGL, SFJ)
GMB = (CSP, PRH)
QSP = (TBD, CFM)
GFQ = (PHH, NGQ)
HXG = (BDT, VRG)
PPG = (XDM, MMN)
MSH = (SHC, QCM)
CHR = (JXF, JNB)
RDX = (MTH, BGH)
VXC = (MSD, BFL)
DLP = (PXV, QQP)
MXP = (FQX, TLP)
TTQ = (TBD, CFM)
GHG = (HPF, NRK)
SNK = (BQF, CPH)
MGG = (STJ, QDH)
CCJ = (MBM, KNT)
NNL = (KBH, LKC)
LKD = (GKJ, TRS)
GFN = (LGT, LXK)
QBM = (XGM, SFV)
STJ = (CFV, CFV)
DSK = (RDP, NBQ)
TSC = (FKJ, DSK)
NSV = (LQB, TRJ)
FKF = (XGR, JXT)
DNX = (NTJ, MSH)
NLH = (JSH, LKD)
CFV = (TPC, SNK)
DRP = (VBR, FJX)
BDM = (SPR, RTF)
TGF = (FPC, CSK)
CNH = (VXD, LFX)
BFL = (RQP, RVP)
XHC = (GND, MDV)
CJJ = (RLT, QQB)
HPH = (XMM, NHL)
PRH = (FLN, BNM)
JCR = (THT, VCP)
VHK = (XDC, JFR)
NQP = (KXT, BJT)
CDJ = (KNC, PFX)
SCF = (DKC, QQQ)
JBR = (MHM, PVJ)
TPC = (BQF, CPH)
FDC = (LKJ, VDS)
KNC = (XCQ, VKJ)
VQM = (SHG, XTT)
KND = (QCS, TVN)
MDM = (GPL, DNX)
FJX = (LXP, BDM)
BDV = (XTB, NVZ)
LBM = (KFN, TGG)
XKC = (KBH, LKC)
QVF = (VMP, BVM)
SHG = (RBR, BHF)
DNB = (SVC, SSQ)
SCN = (JGG, BDV)
SXC = (TGC, CHR)
XSL = (KCJ, SVG)
TKF = (VLC, LVJ)
LKJ = (XHS, PSX)
VHX = (QMG, LCN)
HGC = (LCX, DBM)
MLN = (HFD, KVM)
XDM = (JNK, RRS)
RTK = (PKD, NPC)
QQQ = (DSL, FTV)
VJS = (DTF, VFQ)
LLM = (VVG, BNT)
MFM = (NHG, NQD)
NQK = (VVT, BCV)
NHN = (HPM, VCJ)
SKP = (NMQ, XHM)
HXC = (BVD, PFN)
LSK = (FQJ, KGC)
FPC = (GFX, MDQ)
STC = (RBF, PTM)
CTR = (BRD, KQZ)
BNQ = (SKB, LPC)
QQL = (SKX, DGB)
NHX = (RKX, HPH)
QHJ = (GRQ, BBP)
XCQ = (XPX, PGN)
HTV = (GTS, KBJ)
JXF = (DXQ, FBK)
JTR = (HTJ, PML)
JHB = (JSM, QJH)
CQF = (BDT, VRG)
GNQ = (QCT, QFG)
TQC = (TGB, BSF)
SFS = (SCP, QLZ)
MDQ = (MJD, XVS)
DLC = (TMM, DFM)
FLN = (RGV, SDN)
PVJ = (QTG, XGF)
JFR = (JTR, GHT)
PGK = (VVR, MHR)
TDP = (SSQ, SVC)
RLF = (RKP, SKK)
HJN = (NHB, HKS)
VJR = (TRJ, LQB)
VGX = (VCP, THT)
DSB = (PLL, KSG)
FTM = (VGX, JCR)
MHR = (LBM, NKF)
JFD = (CBP, HLJ)
HKH = (CBP, HLJ)
FDV = (QFH, JMK)
NHL = (RQG, JKF)
CQJ = (DHQ, NRC)
HVD = (SNS, CCN)
PLN = (QKM, LDP)
THT = (BCL, XDT)
FDP = (SCD, XCP)
TJC = (HHV, MVS)
QCM = (HKK, FQV)
TJQ = (QCT, QFG)
HFR = (KJH, PKF)
RQG = (NPH, KGL)
SRJ = (TNS, NPR)
LTR = (NKQ, PJG)
XST = (FVX, RGT)
MBM = (GMP, BBX)
KVM = (CBD, DBG)
MVS = (VRL, JVC)
SSC = (RPL, HBT)
QQP = (VHK, STQ)
CHQ = (SVG, KCJ)
BVD = (FMQ, JGX)
FNX = (NPC, PKD)
FJS = (CBB, VPN)
PLD = (FFL, HJN)
TVC = (CDJ, PBG)
DBX = (XJN, PTB)
MDK = (SQD, RGD)
JPL = (NQS, CNH)
VDG = (GKS, CJJ)
HQB = (GFT, JLR)
GQS = (VMF, DRP)
PST = (MKS, KXG)
XGS = (SHP, FPF)
XDJ = (VNX, PTR)
MHM = (QTG, XGF)
SHN = (SBS, GKP)
LFX = (FLF, NCQ)
BFX = (JNQ, MCT)
XHM = (RNQ, MDM)
LXN = (HJN, FFL)
HPJ = (JRT, GDQ)
NVN = (DTD, TQC)
KGL = (QJC, JQF)
MCT = (PBP, VDG)
QFH = (LPX, JNM)
FVC = (FJS, TDS)
DRL = (QBM, CTP)
LTJ = (MLX, NHX)
THB = (JTN, JHB)
SBX = (RPN, PKQ)
KMV = (RRQ, GTQ)
MNX = (LMH, RXH)
LKC = (TMH, MGF)
TMM = (BFX, PNS)
TMH = (XMS, GGT)
LPX = (QRM, MSV)
STN = (DRL, NMF)
RKP = (CHQ, XSL)
DNC = (HDG, VJS)
XMM = (JKF, RQG)
GFT = (LSM, NXT)
LSM = (SMR, PGC)
FKS = (XSJ, PMK)
MPD = (JGG, JGG)
DKC = (DSL, FTV)
HLC = (DSN, PHK)
KMS = (BJC, BFV)
NJT = (RFT, STN)
JSK = (RBF, RBF)
HLJ = (LGD, PTX)
QMG = (TLV, FMC)
GPL = (NTJ, MSH)
RQP = (XVQ, LSQ)
GGT = (FDP, PRK)
XKN = (JBK, SQN)
FVX = (MGN, GFN)
GST = (CRK, SCF)
MTK = (BFV, BJC)
CCN = (KMV, HCG)
TRS = (PDP, TQD)
NRN = (LBP, JHT)
GFG = (GRQ, BBP)
XBK = (NQP, GDV)
CXT = (QRV, PPH)
FQV = (SSP, XNP)
GFB = (NDC, TPM)
VXD = (NCQ, FLF)
XPX = (MXG, XMT)
SQD = (SRV, GGX)
GKP = (NFC, CGC)
AAA = (XBB, FGX)
KXR = (SHM, GSV)
DGB = (RTG, NLH)
PJM = (PNC, MNX)
QGV = (NPR, TNS)
CFB = (SLP, XQG)
FDJ = (TDV, MJB)
DSN = (KGF, SBX)
FLR = (FDL, SXH)
JGL = (QRQ, XLP)
JQN = (JTN, JHB)
MTH = (NPF, HRT)
PRK = (SCD, XCP)
VHA = (KLF, HXJ)
VVR = (NKF, LBM)
CQH = (VTD, KJK)
DRF = (MPX, SXC)
FDL = (LSK, HMP)
PFX = (XCQ, VKJ)
HPF = (XKC, NNL)
LXH = (LVJ, VLC)
SVC = (MXX, BNQ)
GFX = (XVS, MJD)
DGT = (SKK, RKP)
XKD = (KFK, SPG)
XJN = (BDK, QXQ)
KQH = (KLM, JGL)
VMH = (SKR, XFK)
CHN = (VSK, GFQ)
LHV = (DGK, XST)
HCF = (PKF, KJH)
CNF = (QHB, XPJ)
QCS = (SJM, KMC)
GXP = (QQL, PKG)
SBJ = (QJQ, KJN)
DHQ = (GPD, JMG)
VLG = (FQG, LFB)
GDQ = (VTN, SKP)
NMQ = (MDM, RNQ)
XKM = (KVM, HFD)
BNM = (SDN, RGV)
MLX = (RKX, HPH)
QJC = (LLK, BQH)
HML = (KJK, VTD)
SKK = (CHQ, XSL)
FQX = (TKF, LXH)
PKD = (MXN, MTC)
NQS = (LFX, VXD)
HBT = (CDP, MMH)
LRC = (DFM, TMM)
NXT = (SMR, PGC)
SXB = (XHD, SNT)
RBF = (VGG, VGG)
RXP = (GNQ, TJQ)
RVK = (DRP, VMF)

View File

@@ -0,0 +1,174 @@
use nom::{
bytes::complete::tag,
character::complete::{alpha1, alphanumeric1, multispace1},
multi::separated_list1,
sequence::{separated_pair, tuple},
IResult, Parser,
};
use std::collections::HashMap;
#[derive(Debug, Clone, Copy)]
enum Dir {
Right,
Left,
}
fn parse_input(input: &str) -> IResult<&str, (Vec<Dir>, Vec<(String, String, String)>)> {
use Dir::*;
let (input, result) = (separated_pair(
alpha1,
multispace1,
separated_list1(
multispace1,
tuple((
alphanumeric1::<&str, _>,
tag(" = ("),
alphanumeric1,
tag(", "),
alphanumeric1,
tag(")"),
))
.map(|(start, _, left, _, right, _)| {
(start.to_string(), left.to_string(), right.to_string())
}),
),
))(input)?;
let result = (
result
.0
.chars()
.map(|c| match c {
'R' => Right,
'L' => Left,
_ => unreachable!(),
})
.collect(),
result.1,
);
Ok((input, result))
}
fn create_network(network: &[(String, String, String)]) -> HashMap<String, (String, String)> {
let mut result = HashMap::new();
for (source, left, right) in network {
result.insert(source.to_owned(), (left.to_owned(), right.to_owned()));
}
result
}
fn solve_1(route: &[Dir], network: &Vec<(String, String, String)>) -> u32 {
use Dir::*;
let network = create_network(&network[..]);
let mut current_node = "AAA".to_string();
let mut steps = 0;
let mut route_iter = route.iter();
loop {
if current_node == "ZZZ".to_string() {
return steps;
}
steps += 1;
let direction = match route_iter.next() {
None => {
route_iter = route.iter();
route_iter.next().unwrap()
}
Some(dir) => dir,
};
current_node = match direction {
Right => network.get(&current_node).unwrap().1.to_owned(),
Left => network.get(&current_node).unwrap().0.to_owned(),
}
}
}
fn solve_2(route: &[Dir], network: &Vec<(String, String, String)>) -> u32 {
use Dir::*;
let mut current_nodes = network
.iter()
.filter(|(start, _left, _right)| start.ends_with('A'))
.map(|(start, _left, _right)| start.to_owned())
.collect::<Vec<String>>();
let network = create_network(&network[..]);
let mut steps = 0;
let mut route_iter = route.iter();
loop {
if current_nodes.iter().all(|node| node.ends_with('Z')) {
return steps;
}
steps += 1;
let direction = match route_iter.next() {
None => {
route_iter = route.iter();
route_iter.next().unwrap()
}
Some(dir) => dir,
};
for node in current_nodes.iter_mut() {
let target_node = match direction {
Right => network.get(node).unwrap().1.to_owned(),
Left => network.get(node).unwrap().0.to_owned(),
};
*node = target_node.to_owned();
}
}
}
fn main() {
println!("Hello, this is Patrick!");
let input_text = include_str!("../input.txt");
let (_, (route, network)) = parse_input(input_text).unwrap();
println!(
"There are {} steps required to reach ZZZ",
solve_1(&route[..], &network)
);
println!(
"There are {} steps required to reach only nodes ending on Z, when starting from nodes ending only on A",
solve_2(&route[..], &network)
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test1_part1() {
let input_text = include_str!("../test_input1.txt");
let (_, (route, network)) = parse_input(input_text).unwrap();
assert_eq!(solve_1(&route[..], &network), 2);
}
#[test]
fn test2_part1() {
let input_text = include_str!("../test_input2.txt");
let (_, (route, network)) = parse_input(input_text).unwrap();
assert_eq!(solve_1(&route[..], &network), 6);
}
#[test]
fn test_part2() {
let input_text = include_str!("../test_input3.txt");
let (_, (route, network)) = parse_input(input_text).unwrap();
assert_eq!(solve_2(&route[..], &network), 6);
}
}

View File

@@ -0,0 +1,9 @@
RL
AAA = (BBB, CCC)
BBB = (DDD, EEE)
CCC = (ZZZ, GGG)
DDD = (DDD, DDD)
EEE = (EEE, EEE)
GGG = (GGG, GGG)
ZZZ = (ZZZ, ZZZ)

View File

@@ -0,0 +1,5 @@
LLR
AAA = (BBB, BBB)
BBB = (AAA, ZZZ)
ZZZ = (ZZZ, ZZZ)

View File

@@ -0,0 +1,10 @@
LR
11A = (11B, XXX)
11B = (XXX, 11Z)
11Z = (11B, XXX)
22A = (22B, XXX)
22B = (22C, 22C)
22C = (22Z, 22Z)
22Z = (22B, 22B)
XXX = (XXX, XXX)

View File

@@ -0,0 +1,6 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
[dependencies]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
use std::{collections::HashMap, iter::zip};
fn distance<A>(a: A, b: A) -> A
where
A: std::ops::Sub<Output = A> + Ord,
{
if a < b {
return b.sub(a);
} else {
return a.sub(b);
}
}
fn solve_1(input: &str) -> u32 {
let input: Vec<Vec<u32>> = input
.lines()
.map(|element| {
element
.split_ascii_whitespace()
.map(|numbers| numbers.parse::<u32>().unwrap())
.collect()
})
.collect();
// Double collect(), wowsers that's ugly but it works?
let mut left: Vec<u32> = input.iter().map(|v| v[0].to_owned()).collect();
let mut right: Vec<u32> = input.iter().map(|v| v[1].to_owned()).collect();
left.sort();
right.sort();
return zip(left, right).fold(0, |x, (l, r)| x + distance(l, r));
}
fn solve_2(input: &str) -> u32 {
let input: Vec<Vec<u32>> = input
.lines()
.map(|element| {
element
.split_ascii_whitespace()
.map(|numbers| numbers.parse::<u32>().unwrap())
.collect()
})
.collect();
let left: Vec<u32> = input.iter().map(|v| v[0].to_owned()).collect();
let right: Vec<u32> = input.iter().map(|v| v[1].to_owned()).collect();
let mut occurrences: HashMap<u32, u32> = HashMap::new();
for r in right.into_iter() {
occurrences.insert(
r,
match occurrences.get(&r) {
None => 1,
Some(v) => v + 1,
},
);
}
return left
.into_iter()
.fold(0, |s, l| s + l * occurrences.get(&l).unwrap_or(&0));
}
fn main() {
println!("Hello, this is Patrick!");
let input_text = include_str!("../input.txt");
let result_1 = solve_1(input_text);
println!("The total distance between the two lists is {}", result_1);
let result_2 = solve_2(input_text);
println!("The similarity score of the two lists is {}", result_2);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), 11);
}
#[test]
fn test_2() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_2(test_input), 31);
}
}

View File

@@ -0,0 +1,6 @@
3 4
4 3
2 5
1 3
3 9
3 3

View File

@@ -0,0 +1,6 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -0,0 +1,55 @@
0123450128945212434498107654876212322345432110787870123
1214563287654302345347278923945003411276741025696983254
2307874390901201436256361010232156500985891234899874765
3458965481896543457101454322121267898764210348760565856
4547889332787612898654456541010128709654321409651487943
9656971245610502348742363456723489214545670512342396512
8746560330541461059231072019894876523039987651229603401
0130450101232878762108981923785955432128896560318712101
1221321432543969456676870831276843201017698431105657892
4349898540158950387985106740189652122012587120234598761
0456797643267341293234203651076561043403436011231034650
1245687653212210982178312312345878654312345190345125141
4334567064307807891089425405658969763233438987656776032
5321018165616906702376596534787439890120107678949889120
6910789278965215610345687321096521763011234589030672101
7821898347654334321256786543212310652101347654121543432
6734787658901223456105897610105432543276978903443430563
2105676987911010897834978923076501034789877412352321694
3456989876854323708929870134589632385676966543261430785
4367810105763432612210165245678745690123457898170567014
3210121234176501523878954354776544787430342347089698923
2345665893080787438965410167889432156561231456798789654
1058756702191898341014321054974321047892120321887018763
0569845212012567634323015123125410430121011010986323454
6578954307623498765487654304034543221030345654345432125
5434356788545349854599001216787652107845210787216701034
0125643699237898703678104325894567856956789891209834345
7876212765103203612363215454383898945787698900340125876
0980101894454114503054356965212432430694543215489876965
1098234583467023212125407870106541021583210676098920145
2347899602898908763256910187017865652678701587187813236
3256678711743219854567823298894976569549652490296704367
0100345620651278343289654350765987478230743321345410198
9251201234230341230178760541034300300121890120034326789
8349212945145650789078921632133211212010581631128965632
7658767876054787632107634780124504321123498745489874541
6107323945763096549616543995435665210898589654788103450
5236014539892124328723012876343786789867670123694012367
4345867622101015610654322301212891270184561054543231018
2109988913412126789961001454309750301293432163210102309
3458776804569234697872156545678543432789430673456943212
4567566543678985586543267836787612545676521982987856103
0103457012987876487434586927898707654568701201276547894
1212388967876567393325698810989898965439632320567030985
0327890658905058212016784543298781012344543011498121076
9456541243014149801134569650185632307655676322399876125
8767632332123232100123678745670546998764985431087565436
3498234501104343034598988764321457884643891056016501098
2567107698612352125667639058901210745012342347121432167
1989278786783961012787540147654323654321435218930345236
0876989695894878109896039236569456788760324306543210145
0105874504185769854385128545478998699354413457850105256
1234763213096854763014537654360187543263509766969876567
2303452342187943212323456963201236984102678876878103498
3212301056789810103410567870102345676101278987989012567

View File

@@ -0,0 +1,143 @@
use std::collections::{HashMap, HashSet};
fn parse(input: &str) -> Vec<Vec<u32>> {
const RADIX: u32 = 10;
input
.lines()
.map(|l| l.chars().map(|c| c.to_digit(RADIX).unwrap()).collect())
.collect()
}
fn solve_1(input: &str) -> u32 {
let map = parse(input);
let h = map.len();
let w = map[0].len();
let mut map_info: HashMap<(usize, usize), HashSet<(usize, usize)>> = HashMap::new();
for (j, row) in map.iter().enumerate() {
for (i, elevation) in row.iter().enumerate() {
if *elevation == 9 {
map_info.insert((i, j), HashSet::from([(i, j)]));
}
}
}
for e in (0..=8).rev() {
let mut new_map_info: HashMap<(usize, usize), HashSet<(usize, usize)>> = HashMap::new();
for ((i, j), trailheads) in map_info.into_iter() {
let mut positions = vec![];
if i > 0 {
positions.push((i - 1, j));
}
if i < w - 1 {
positions.push((i + 1, j));
}
if j > 0 {
positions.push((i, j - 1));
}
if j < h - 1 {
positions.push((i, j + 1));
}
for (x, y) in positions.into_iter() {
if map[y][x] == e {
match new_map_info.get(&(x, y)) {
None => new_map_info.insert((x, y), trailheads.clone()),
Some(&ref t) => new_map_info.insert(
(x, y),
t.union(&trailheads).map(|ts| ts.to_owned()).collect(),
),
};
}
}
}
map_info = new_map_info;
}
map_info
.values()
.map(|trailheads| trailheads.len() as u32)
.sum()
}
fn solve_2(input: &str) -> u32 {
let map = parse(input);
let h = map.len();
let w = map[0].len();
let mut map_info: HashMap<(usize, usize), u32> = HashMap::new();
for (j, row) in map.iter().enumerate() {
for (i, elevation) in row.iter().enumerate() {
if *elevation == 9 {
map_info.insert((i, j), 1);
}
}
}
for e in (0..=8).rev() {
let mut new_map_info: HashMap<(usize, usize), u32> = HashMap::new();
for ((i, j), rating) in map_info.into_iter() {
let mut positions = vec![];
if i > 0 {
positions.push((i - 1, j));
}
if i < w - 1 {
positions.push((i + 1, j));
}
if j > 0 {
positions.push((i, j - 1));
}
if j < h - 1 {
positions.push((i, j + 1));
}
for (x, y) in positions.into_iter() {
if map[y][x] == e {
match new_map_info.get(&(x, y)) {
None => new_map_info.insert((x, y), rating),
Some(r) => new_map_info.insert((x, y), r + rating),
};
}
}
}
map_info = new_map_info;
}
map_info.values().sum()
}
fn main() {
println!("Hello, this is Patrick!");
let input = include_str!("../input.txt");
let result_1 = solve_1(input);
println!("The sum of scores of all trailheads is {}", result_1);
let result_2 = solve_2(input);
println!("The sum of ratings of all trailheads is {}", result_2);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), 36);
}
#[test]
fn test_2() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_2(test_input), 81);
}
}

View File

@@ -0,0 +1,8 @@
89010123
78121874
87430965
96549874
45678903
32019012
01329801
10456732

View File

@@ -0,0 +1,6 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -0,0 +1 @@
6563348 67 395 0 6 4425 89567 739318

View File

@@ -0,0 +1,121 @@
use std::collections::HashMap;
fn parse(input: &str) -> Vec<u64> {
input
.split_whitespace()
.map(|stone| stone.parse().unwrap())
.collect()
}
fn solve_1(input: &str) -> usize {
let stones = parse(input);
let mut current_stones = stones.clone();
// I know, this is very naive
for _ in 0..25 {
let mut new_stones = vec![];
for stone in current_stones {
if let 0 = stone {
new_stones.push(1);
} else {
let ss = stone.to_string();
if ss.len() % 2 == 0 {
let (front, back) = ss.split_at(ss.len() / 2);
new_stones.push(front.parse().unwrap());
new_stones.push(back.parse().unwrap());
} else {
new_stones.push(stone * 2024);
}
}
}
current_stones = new_stones;
}
current_stones.len()
}
fn solve_2(input: &str) -> u64 {
let stones = parse(input);
// Now for the dynamic programming version
let mut dp: HashMap<u64, u64> = HashMap::new();
for stone in stones {
dp.insert(stone, 1);
}
for _ in 0..75 {
let mut new_dp: HashMap<u64, u64> = HashMap::new();
for (stone, cnt) in dp.into_iter() {
let ss = stone.to_string();
if stone == 0 {
match new_dp.get_mut(&1) {
None => {
new_dp.insert(1, cnt);
}
Some(c) => *c += cnt,
};
} else if ss.len() % 2 == 0 {
let (front, back) = ss.split_at(ss.len() / 2);
let front = front.parse::<u64>().unwrap();
let back = back.parse::<u64>().unwrap();
match new_dp.get_mut(&front) {
None => {
new_dp.insert(front, cnt);
}
Some(c) => *c += cnt,
}
match new_dp.get_mut(&back) {
None => {
new_dp.insert(back, cnt);
}
Some(c) => *c += cnt,
}
} else {
let new_stone = 2024 * stone;
match new_dp.get_mut(&new_stone) {
None => {
new_dp.insert(new_stone, cnt);
}
Some(c) => *c += cnt,
}
}
}
dp = new_dp;
}
dp.values().sum()
}
fn main() {
println!("Hello, this is Patrick!");
let input = include_str!("../input.txt");
let result_1 = solve_1(input);
println!(
"The number of stones after blinking 25 times is {}",
result_1
);
let result_2 = solve_2(input);
println!(
"After blinking 75 times, the number of stones is {}",
result_2
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), 55312);
}
}

View File

@@ -0,0 +1 @@
125 17

View File

@@ -0,0 +1,6 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -0,0 +1,140 @@
UUUUUUUUUUUUUUUUHHHDDDDDDDDDDDDLLLLLLLLLLLLSSSSSSSBBBBBBBBBBHHHHHHKKHHHHHHHHHHHHHZZZZZZMMMMMMMMMMMMMVVVVVVVVVVVVVVVVHHHHHHUUUUUUUUTTTTTTTTTT
UUUUUUUUUUUUUUUUUHHDDDDDDDDDDDLLLLLLLLLLLXLSSSSSSSBBBBBBBBBBBHHHHHHHHHHHHHHHHHHHHHHZZZZMMMMMMMMMMMMMVVVVVVVVVVVVVVVVHHHHHUUUUUUUTTTTTTTTTTTT
UUUUUUUUUUUUUUUUUUHDDDDDDDDDDDLLLLLLLLLLLLFLLSSSSSBBBBBBBBBBBBHHHVVHHHHHHHHHHHHHHBHZZMMMMMMMMMMMMMMMDVVVVVVVVVVVVVVVWWHHHUUHUTTTTTTTTTTTTTTT
UUUUUUUUUUUUUUUUDDDDDTDDDDDDLLLLLLLLLLLLLLLLFFSSSBBBBBBBBBBBBBBVVVHHHHHHHHHHHHHHHHHZZZMMMMMMMMMMMMMDDVVVVVVVVVVVVVVVHHHHHHHHUUTTTTTTTTTTTTTT
UUUUUUUUUUUUUUUDDDDDDDDDDDDDDELLLLLLLLLLLLLLFFFSFBBBBBBBBBBBBVVVVVVVHHHHHHHHHHHZHHHZDZMMMMMMMMMMDDDDDDVVVVVVVVVVVVFHHHHHHHHHUUTTTTTTTTTTTTTT
UUUUUUUUUUUUUUUDDDDDDDDDDDDDDEELLLLLLLLLLLLLFFFFFBBBBBBBBBBBBBVVVVVVHHHHHHHHHHZZHHXDDDDDMMMMMMMMMDDDDDDDVVVVVVVVVVHHHHHHHHHHUUUTTTTTTTTGGTTT
UUUUUUUUUUUDUDUDDDDDDDDDDGGDDEEELLLLLLLLLLLFFFFFFFFFBBBBBBBBBBVVVVVVHVHHHHHHHHXXXXXDDDDMMMMMMMMMMDDDDDDVVNVVVVVVVVHHHHHHHHHHUUUTTTTTTTTTGGTT
UUUUUUUUDDUDDDDDDDYDYDDDGGGGGEELLLLLLLLLLLFFFFFFFFFBBBBBBBBBBBVVVVVVVVVVHHHHHHHXXXXXXXDXXMMMMYYMYDDADDDLVVVVVVVVVHHHHHHHHHHHHUUTTGTGTTTTGGTT
UUUUDDUDDDUDDDDDDDYYYYZZGGGGGEEEELLLLLLLLLFFFFFFFFBBBBBBBBBBQQVVVVVVVVVVHHHHHHHXXXXXXXXXMMMYYYYYYYYYDDDDTVVVVVVVVVHHHHHHHHHHHUUUGGGGTTGGGGTT
UNUUUDUUDDDDDDDDDYYYYYYZZGGGGEEEELLLLLLFFEFFFFFFFFFFFBFSSBBBBVVVVVVVVVVVVHHHHHHXXXXXXXXXMMMMMYYYYYYYYDDDDVVVVVVVVVVHHHHHHHHHUUUUUUGGGGGGGGGG
DUUUDDDDDDDDDDYYYYYYYYYZZGGGGGGLLLLLLLLLFFFFFFFFFFFFFFFSSSSBBBVVVVVVVVVVVVVHHHHXXXXXXXXXMMMYBYYYYYYYYDQQVVVVVVVJVVVHLHHHHBHHUUUUUUGGGGGGGGGG
DDDDDDDDDDDDDDYYYYYYYZZZZSSSGGGLLJLLLLLLFFFFFFFFFFFFFFFFFSSSSSSSSSVVVVVVVVHHHXXXXXXXXXXMMMMYYYYYYYYYYYYYYYVVVSVJVZZHZSSHHHUUUUUUUGGGGGGGGGGG
DDDDDDDDDDMDDYYYYYYYYYSSSSSSGGGGGJLLLJJJJJFFFFFFFFFFFFFFFSSSSSSSSSVVVVVVVVVVHVXXXXXXXXMMMMYYYYYYYYYYYYYYYYVVVSZZZZZZZSSSHHBUUUUUUUGGGGGGGGGG
DDDCDDDDMMMMDYYYYYYYYSSSSSZSGGGGGOOOOOOOOOOFFFFFFFFFFFFCFFFSSSSSSSVVVVVVVVVVVVXXXXXXXMMMMYYYYYYYYYYYYYYYYYVVSSZZZZZZZSSSSHBBBUUUUUUGGGGGGGGG
CCDCCCCDMMMMMZYFFFYSSSSSSZZGGRRRGOOOOOOOOOOOOOOOOOFFFFFFFFFSSSSSSSSVVVVVVVVVVVXXXXXXMMMMMMMMYYYYYYYYYYYYYYYYYSSZZZZZZSSSSBBBBBUUUUUUGGGGGGGG
CCCCCCCDMMMMMMFFFFSSSSSSSZZRGRRJJOOOOOOOOOOOOOOOOOFFFFFKKSSSSSSSSSPVVVVVVVVVFVVXXXXXMMMMMMMYYYYYYYYYYYYYYYYYSSSZZZZZSSSBBBBBBUUUUUUGGGGGGGGG
CCCCCCCMMMMMMMMFFSSSSSSSYYYRRRRRJOOOOOOOOOOOOOOOOOKKKFKKKSSSSSSSSVVVVVVVVVVVFFVVXXWWMMMMMMMYPPIIYYYYYYYYYYSSSSSSSSSSSSSSBBBBBUUUUUUGGGGGGGGG
CCCCCCQMMMMMMMMMMSSSSSSSYOOOOOOOOOOOOOOOOOOOOOOOOOFKKKKKKSSSDSSDDDDVHHHVVVVVFFFXXXWWWMMMMQMMPPIIIYYYYYYYSSSSSSSSSSSSSSSSSBBBBUUUUUUUGGGGGGGG
CCCCCMMMMMMMMMMMMYYSSYYYYOOOOOOOOOOOOOOOOOOOOOOOOOQQKKDDDDDDDDDDDDDHHHHVVVVYYFYZXXWWMMEEMMMMPPIIIIIIYYYSSSSSSSSSMMSSSSSSSSSSBBUUUUUUUUGGGGGG
CCCCCMMMMMMMMMMMMMSSSSYYYOOOOOOOOOOOOOOOOOOOOOOOOOQQQKKLLLLDDDDDDDHHHHHHYVYYYYYYXWWWMEEEMPPPPPPIIIIFYYYSSSSSSSMMMMSSSSSSSSSSBBBUUUUUUUUGJGGG
CCCCCMRMMMMMMMMMMWWWWWYYYOOOOOOOOOOOOOOOOOOOOOOOOOQQQKKLKLLLDDDDDDHHHHHYYYYYYYZZJWWWWCCCMPPPPPIIIIIFISYSSSSSMMMMMMSSSSSSSSSSBBBUUUUUUUGGJJGG
CCCCCMMMMMMMMMMMWWWWWWWWYOOOOOOOOOOOOOOOOOOOOOOOOOQQQKLLLLLDDDLDDDDHHHYYYYYYJJJJJJJWCCCCCPPIIIIIIIIIISSSJJJSMMMMMMSSSSSSSSSSBUUUUNNNNNNGJJJG
CCCCCCMMMMMMMMWWWWWWWWYYYOOOOOOOOOOOOOOOOOOOOOOOOOQNNKLLLLLIDLLDDHHHHHYYYYYYYJJJJCCCCCCCCPIIIIIIIIIISSSSJJJMMMMMMMSSSSSSSSSSUUUUUNNNNWNNNJJJ
CCQCCCMMMMMMMMWWWWWWWWWYYOOOOOOOOOOOOOOOOOOOOQQNNNNNNLLLLLLLLLLLDDHHHHXYYJYYJJJJJJCCCCCCCIIIIUUIIISSSSSJJJMMMMMMMMMMMMMMMBNNUUNNNNNNNNNNNJNN
QQQCCCCCMMYMMWWWWWWWWYYYYOOOOOOOOOOOOOOOOOOOOQQNNNNNNLLLLLLLLLLLHHHHMXXYYJJJJJJJJJJZCCCCCIIIUUIIISSJJJJJJJJMMMMMMMMMMMMLLLNNNUNNNNNNNNNNNNNB
OQQQCCCCMMMCMWWWWWWWWYYYYYYYYYYYOOOOOOOOOOOOOQQNNNNNNLLLLLLLLLLHHHHHMXXPXXXJJJJJJJJIICCCIIIIIUIJIJSJJJJJJJMMMMMMMMMMLLLLLLLLNNNNNNNNNNNNNNNN
OOQCCCCCMCCCCWWWWWWWWWYYYYYYYYYYYYYOOOOOOOOOOQNNNNNNNLLLLLLLJJJJHHMMMMXXXXXJJJJJJIIQIIIIIIIIIJIJJJJJJJJJJJMMTTMGMMMMLLLLLLLLLNNNNNNNNNNNNNNN
OQQQQQCCCCCCCCCWWWWWWWYYYYYYYYYYYYSOOOOOOOOOOQNNNNNNNNLLLLLLJJJJHMMMMXXXXXXXXJDDDDDDDDIIIIIIJJJJJJJJJJJJJJJJJTMGGGLLLLLLLLLLLLLLNNNNNNNNNNNN
QQQQQQQCCCCCCCWWWWWWWYYYYYYYYYYYYYGOOOOOOOOOCCMNNWWNNNLLLLLLJJJJJMMMMMXXXXXXXXDDDDDDDDIIIIIJJJJJJJJJJJJJJJJJTTTGGGVLLLLLLLLLLLLLNNNNNNNNNNNN
QQQQQCCCCCCCCCWWWWWWWYYYYYYYYYGGYYGOOOOOOOOOCCWNNWWWNNLLLLLJJJJJJJMMMMMXXXXXXXDDDDDDDDIIIIIIJJJJJJJJJJJJJJTTTTTGGGVVVLLLLLLLLLLLNNNNNNNNNOON
QQQQQCCCCCCCCCCCVVWVVYYYYYYYYGGGGGGGSCCCCCCCCWWWWWWWRRAAALLJJJJMJJMMMMMXXXXHXXDDDDDDDDZZIIIIJJJQJJJJJJJJJJTTTTTGHPVVLLLLLLLLLLLNNNNNNNNNOOOO
QQQQQCCVECMMMMVVVVVVVVYYYYYYGGGGGGGSSCCCCCCCWWWWWWWWWAAAAAJJJJJMJMMMMMMMMXXMXXDDDDDDDDZZIIIIBJJJJJJJJJJJJJTTTTTTTPPPPLLLLLLLLLZNNNNNNNNOOOOO
QQQQQCCCEEVVVVVVVVVVVVVVHYGGGGGUUGGGGCCCCCCCWWWWWWWWWAAAAAJJJJJMMMMMMMMMMMXMMMDDDDDDDDZZZJIILJJJPJJJJJJJJJTTTTTTPPPPPLLLLLLLLLZZZZNNNNNOOOOO
RQQQQQCCEEEEVVVVVVVVVVVVVXYGYGGUUGGGCCCCCCCCWWWWWWWWWWAAAJJJJJJJMMMMMMMMMMMMMMTZZDDDZZZZZJIILLLLJJJJJJJJJTTTTTFFFPPPPLLLLLLLLLZZZNNNNNNOIOOO
RRRRRRREEEEENNVVVVVVVVVVVXYYYYGYUUCCCCCCCCCCWWWWWWWWWSAAAAJJJJMMMMMMMMMMMEMMMMMMUDDDZZZZZZLLLKLLJJJJJJJZJJTTTFFFFTPPLLLLLLLLLLZZZNNNNNNOIIOO
ZZRRRRRREEENNNNNVVVVVVVVVVYYYYYYYKKCCCCCCCCCWCWWWWWWWWAAAAJJJJMMMMMMIIMEEEEEMMMMMDDDZZZZZZZLLLLLLJLLLLJZTTTTFFFFFFLLLLLLLLLLLLLZZNNNOOOOIIII
ZZZRRRRRENENNNNNVVVVVVVVVVYYYYYYYYYBCCCCCCZZZZZDWWWWWWAAAAJJJJJIMMIIIIMEEEEJJMDDDDDDZZZZZZZLLLLLLLLLLLJTTTLTFFWFFFFFFLLLLLLLLLZZZZZZIIOOIIII
ZZRRRNNNNNNNNNNNNVVVVVVVVVYYYYYYYYYYEECCCCZZZZZDDDDLDWWJAAJJJJIIIMIIIIMEEEEEDDDDDDDDDDDZZZZLLLLLLLLLLLJLLTLLFFFFFFFFFLLLLLLLLLZZZZZZZIIIIIII
ZZZZRNNNNNNNNNNNVVVVVVVVVVYYYYYYYYYYYYCCCCZZZZZDDDDLDJJJJJJJJJIUIIIIIMMEEEEEDDDDDDDDDDDZZZZLLLLLLLLLLLLLLLLLFFFFFFFFFLFLLLLLZLZZZZZZZIIIIIII
ZZZZNNNNNNNNNNNNVVVVVVVVVVYYYYYYYYYYQQCCCCZZZZZDDDDDDDJJJJJIIIIIIIIIHIMMEEEEDDDDDDDDDDDZZZZLLLLLLLLLLLLLLLLOFFFFFFFFFFFLZLLZZZZZZZZZZZIIIIII
ZZZZZZNNNNNNNNNVVVVVVVVVVVYYYYYYYYYYYYNNCCZZZZZDDDDDDDDJIIIIIIIIVVVVIIIMMEEEDDDDDDDDDDDJJZLLLLLLLLLLVVVVVLOOFFFFFFFFFFFZZZZZZZZZZZZZIIIIIIII
ZZZZZNNNNNNNNNNVVVVRRVVVVVYYYYYYYYYHDNNNNNZZZZZDDDDDDDDJJIIIIIIIIIIIIIIMMMMMDDDDDDDDDDDJIZLLLLLLLLLVVVVVVVVVFFFFFFFFFFFZZZZZZDDDZZZZZZZEIIII
ZZZZZNENNNNNNNNNVVVRRRVVVVVYYYYHHHHHHNNNNODDDDDDDDDDDDDJIIIIIIIIIIIIIIIIMMMMDDDDDDDDDDIIILLLLLLLLLVVVVVVVVVVVFFFFFFFFFFIIDDZZDDXDZZZZZEEENII
ZZZZZNNNNNNNNNNNVVRRRRVYVVYYHHHHHHHHHNNNNNDDDDDDDDDDDBBIIIIIIIIIVVVIVVVMMMMMJJJJIIIIIIIIIILLLLVVVVVVVVVVVVVVVFFFFFFIFFFIIDDDZDDXDZZZZZEEENII
ZZZZZZZNNNNNRRRRRVRRRYYYYYYYYHHHHHHHHHNNNNNCCDDDDDDDDBIIIIRIIIIVVVVVVVVVMMMRRRRJJIIIIIIIIILLLIVVVVVVVVVVVVVVVVFFFFFIIIIIEDDDDDDDDDDDZZZEENNN
ZZZZZZZNNNNNNNNORRRRYYYYYYYYHHHHHHHHHHNNNNNNNKDDEDDDDBBBIIIIIIIVVVVVVVVQMMRRRRRRIIIIIIIIIIIIIIIIIIVVVVVVVVVVVVFFHIIIIIIIEDDDDDDDDDWDZZEEEENN
ZZZZZZZNFNNNNOOOOORRYYYYYYYYHHHHHHHHHHNNNNNNNNTTFDDDDJJBIIIIIIIVVVQQVVQQQQRRRRRRIIIIIIIIIIIIIIIIVIVVVVVVVVVVVVVHHHHIIDIIDDXDDDDDDDDDDZEEEEEN
ZZZZZZZNNNNNNUUOOOOOOYYYYYYYYHHHHHHHHHHNNNNNNNTFFFFDDJJBJJIIVIIIIVQQQQQQQDRRRRSRRIIIIIIIIIIIIIIIVVVVVVVVVVVVVVVHHHYIDDDIDDXXDDDDDDDDEEEEEEEE
ZZZZZZNNNNNNNUUOOOOOOOOYYYYYYHHHHHHHHHHNNNNNNNFFFFFDDJJJJJJIVIIVVVQQQQQQQQRRRRRPPPPIQIIIIIIIIIIIVVVVVVVVVVVVVVHHHYYLYDDDDDDDDDDDDDEEEEEEEEEE
ZZZZZZUUUUNNUUUUOOOOPPOYYYXYIIHHHHHHHHHNNNNUUFFFFFFDAJJJJNJJVIVVVVQQQQQQQQNRRRRPPPPQQILQQIIIIIIIVIIVVVVVVVVVVVYHYYYLYDDDDDDDDDDEEEEEEEEEEEEE
ZZZZZUUUUUUUUUUOOOOPPPPYYYXYIIIHHHOHXXXNNNNNNJJFJFFJJJJJJJJJVVVVVVVQQQQQQRRRRRRPPPPQQQQQQQIIIIIIIIIVIVVVVVVVVVYYYYYYYDDDDDDDDDEEEEEEEEEEEEEE
ZZZZZUUUUUUUUUUOUUUUUPYYYYYYYIIHHHHHXXXXXNXXXJJFJJFJJJJJJJJJJJVVVVVQQQQQRRRRRRRPPPQQQQQQQQEEEIIIIIIIIIIVVVVVVVYYYYYYYYDDDDDUUEEEEEEEEEEEEEEE
ZZZZZZUUUUUUUUUUUUUUUPPPYYYYIIXHHHHHHXXXXXXXXXXXXFFJJVVVVJJJJJJVVVVQQQQQRRRRRRRRRPQQQQQQQEEEEEEEEIIIIHIKIVBBGGYYYYYYYDDDDDDUUUEEEEEEEEEEEXEE
ZZZZZZUUUUUUUUUUUUUUUPPPPYYYXXXXXXXXXXXXXXXXXXXXDDJJJVVVVJJJJJJVVVVVVRRRRRRRRPPPPPQQQQQQEEEEEBEEEEIIIHIIIVBGGGYYYYYYYDDUUUUUUUUUEZEEEEEEEEEE
ZZZZZUUUUUUUUUUUUUUUUPPPPYYYXXXXXXXXXXXXXXXXVVVXDDJJJVVVVJJJJJVVVVVVVRRRRRRRRRPPPPQQQQEEEEEEEEEEEEEIIHHJJGGGGGGGYYYYYYDDUUUUUUZUEZEEEEEEEEEE
ZZZUUYUUUUUUUUUUUUUUUPPPPPYYWXXXXXXXXXXXXXXXVVVXPPVVVVVVVJJJJJJVVFVVVRRRRRRRRRPPPPKQKKKEEEEEEEEEEVVVHHHHJGGGGGGGYYYYYDDDDUUUUZZZZZEEEEEEEEEQ
ZZZZUUUUUUUKKUUUUUUUPPPPPPPYWXXXXXXXXXXXXYYXVVVPPPVVVVVVVJJJJJJJJFVVVRRRRRNEEEKPKKKKKKKEEEEEEEEEEEEHHHHHHYYYGGGGYYYYYDDDDZZZZZZZZZEEEEEUEEEE
ZZZZZUUUUUUKKUUUUUUUPPPPPPPXXXXXXXXXXXXYYYYVVVVVVVVVVVVVVJJJJJJJFFFFVRRRRKNNKKKKKKKKKKKKEEEEEEEEEEHHHHHHHYYYGGGGGGGGGYDDDZZZZZZZZZZZZZZUEEEE
ZZZZZDUULLKKKUKKUUUPPPPPPPPXXXXXXXXXXXXYYYYVVVVVVVVVVVVVVYYJJJJJFFFFFRRRRRNNKKKKKKKKKEEKEEEEEEEEEEEHHQHHHYYYGGGGGGGGGDDDDZZZZZZZZZZZZZZZZQQQ
XZZZZDKKKKKKKKKKFXXXXPPPPPPPXXXXXXXXYYYYYYYVVVVVVVVVVVVVVYJJJJJFFFFFRRFFFFFSSKKKKKKKKEEEEEEEEEEEEEQQQQHHHYYYGGGGGGGGGDDDZZZZZZZZZZZZZZZQQQQQ
XZZZZKKKKKKKKKKKKXXXXPPPPPPPXXXXXXXXYYMYYYYVVVVVVVVVVVVPPPQJJJSFFFFFFFFFFFJSJJJJKKKKKKKKEEEEEEEEQQQQQQQHYYYYGGGGGGGGGDDDZZZZZTTTTTZZZZZQQQQQ
XZWWKKKKKKKKKKKKKXXXXXPPPPPPMMXMMXXXXXMYYYYRRYPPPPVVVVVVVVQQJSSFGOFFFFFFFFJSJJJJKKKKKKKKKEKEEEEEQQQQQQQQEBYYGGGGGGGGGDEDZZZZZTTTTTZZZDDZQQQQ
XXKWKKKKKKKKKKKKKKXXXXPPPPPPMMSMMMMMXMMXYYYYYYXPPPVVVVVVVVQQJOSSOOOFFFFFFFJJJJJJKKKKKKKKKEKKQEEEPQQQQQEQEEEEGGGGGGGGGDEEZZZZZTTTTTZZZZZZQQQQ
KKKKKKKKKKKKKKKKKWXXXXXXPPPPMMMMMMMMMMMXXYXXYYXPPPVVVVVVVVQQQOOOOOFFFFFFFFFJJJJJJKKJKKKKKKKKKKKCPPPPQQEEEEEEGGGGGGGGGEEEZZZZZTTTTTZZZAZZQQQQ
KKKKKKKKKKKKKKKKKKXXXXPPPPPMMMMMMMMMMMMXXXXXXXXXPPPPPPPPPQQQQOOOOOOOOFFFFJJJJJJJJJJJKKKKKKKKKKKCCCPPQQEEEEEEGGGGGGGGGDEEEEZZZTTTTTZTTTTTQQQQ
FFKKKKKKKKKKKKKKKKXXXXPPPPPMKMMMMMMMMMMMMXXXTXXXXPPPPPPPQQQQOOOOOOOOOFFFJJLJJJJJJJJJJJKKKKKKKKPPPPPPQQEEEEEEGGGGGGGGGEEEEEZZITTTTTTTTTTTQWWQ
KKKKKKKKKKKKKKKKKKKXXXXPPPPMKMMMMMMMMMMMXXXXTTXXXXXPPPPPQQQOOOOOOOOOUJJJJJJJJJJJJJJJJJKKKKKKKPPPPPPPEEEEEEEEGGGGGGGGGEDDEEZZZTTTTTTTTTTTWWWQ
KKKKKKKKKKKKKKKKAAAAAAPPPKPKKMMMMMMMMMMMXXXXTTTXXXXXPPPPQQQOOOOOOOOOOJJJJJJJJJJJJJJJJKKKKKKKKPPPPPPPPEEEEEEEEEEGGGGGGDDDEEEIITTTTTTTTTTTWWWQ
KKKKKKKKKKKKKLKAAAAAAAPPKKKKKMMMMMMMMMMMMTTTTTTXTTXXPPPQQQQQOOOOOOOOOJSSJJJJJJJJJJJKKKKKKKKKKKKPPPPPPZEVEEEEEEEGGGGGGDDDEEDIITTTTTTTTTTTWWWQ
KKKKKKKKKKKLLLLLAAAAAAPKKKKKKMMMMMMMMMTMTTTTTTTTTTTXPXPQQQQQQOVOOOOOOOJJJJJJJJJTJJJPPDKKKKKKKKKPPPPPPZQQEEEEEEEGGGGGGDDDDDDIITTTTTTTTTWWWWWW
KKKKKKKKKKKLLLLAAAAAAAKKKKKKKKKKMMOMMMTTTTTTTTTTTXXXXXPQQQQQQQQZOOOOTTTTJJJJJJJJJJJPPPKKKKKKKKPPPPPPPQQQEEEEEEEGGGGGGZDDZZZVITTTTTTTTTWWWWWW
KKKKKKKKKKLLLLAAAAAAAKKKKKKKKKKKKMMMMMTTTTTTTTTTTTTXXXQQQQQQQQQQSOOTTTTTTTJTJJJJJJJJPPPPPKKKKPPPPPPPOOQQHEEEEEEGGGGGGZZZZZJIITTTTTTTTTWWWWWW
KKKKKKKKKKKZZLAAAAAAAAKKKKKKKKKKKKKTTTTTTTTTTTTTTTTXUUQQQQQQQQQQTTTTTTTTTTTTJJJJJPPPPPPPPPKKKKKKKKOOOQQQHEEEEEEGGGGGGZZZZZJIITTTTTTTTTWWWWWW
KKKKKKKKKZLZZZPPZAAAAAKKGKKKKKKKKKKKTTTTTTTTTTTTOTTTUUUQQQQQQQQQTTTTTTTTTTTTJPJPPPPPPPPPPKKKKKKKKOOOJOOOGGGGGGGGGGGGGZZZZZZIIIIIIIIWWWWWWWWW
KKKKKKKKZZZZZZZZZZZAAAAKGKKKKKKKKKKKVTTTTNTTTTTTOTTUUUUUQQQQQQQQUTTTTTTTTTTTJPPPPPPPPPPPPPPKKOKOOOOOOCOOGGGGGGGGGGZZZZZZZZZIIQIIIWWWWWWWWWWW
KKKKKKKKZZZZZZZZZZZZAKKKKKKKKKKKKVVVVTTTNNNNTTCCCCTUUUUUJJQQQQQUUTTTTTTTTTTTTPPPPPPPPPYPPPPOKOOOOOOOOOOOGGGGGGGGGGZZZZZZZZYYIWIIWWWWWWWWWWWV
KKKKKKKZZZZZZZZZZZAAAKKKKKKKKKKKKKKKVNNTNNNNNNCCLCCCUUUUJJJJQQUUTTTTTTTTTTTTTPPPPPPPYYYKKKOOOOOOOOOOOOODGGGGGGGGGGZZZZZZZYYYYWWWWWWWWWWWWWWV
KKKKZZZZZZZZZZZZZZZAAKOKKKKKKKVVVVVVVVNNNNNNNNCCCCCUUUUUUCCJQQQUTTWTTTTTTTTTTTPPPPPPPYYKKKKOOOOOOOOOOOODGGGGGGGGGGZZZZZZYYYYYWWWWWWWWWWWWWWW
ZZZZZZZZZZZZZZZZZZAAAAKKKKKKKKVVVVVVBNNNNNNJNNCCCCUUUUCCCCCCRUUUUTWWTGTGGTTTTPPPPPPPPYYYKKOOOOOOOOOOOOODGGGGGGGGGGZZZZUUYYYYWWGGWWWWWWWWWWWW
ZZZZZZZZZZZZZZZZAAAAAAKKKAKKKVVVBBBVBBNNNNNJNNCCCCCUCCCCCCCCRRRRRTWWWGGGTTTTPPPPPPPYYYYYOOOOOOOOOOOOOOOOGGGGGGGGGGZZZZUUYYYUUUUGWWWWWWWWGGGW
EZZZZZZZZZZZZZZZZAAAAAAAAAAGBVVVBBBBBBNNNNNNNCCCCCCCCCQCCCCCQQQRTTWWRGGGGGTTPPPPPPPPYYYYYOOOOOOOOOOOOGGGGGGGGGGGGGZZZZUUUUUUUFFWWWWWWWWWGGGG
EEEEESSSZZZZZRRRRRAAAAAAAAAPBBVVBBBBBBCCGGGGGGCCCCCCCQQCCCCQQQRRRRRRRGGGGTTPPPPPPPPKYYYYYPPOOOOOOOOOOGGGGGGGGUUUUUUUUUUUUUUUUUFFWWWWWETWWTTT
EEEEESSSGGGZZRRRRRRRRAAAAAPPBBBBBBBBBBBCGGGGGGCCCCCCQQGGGGGGQRRRRRRRGGGGGMTMMPPPPPPKKYYYYPPOOOOOOOOOOGGGGGGGGUUUUUUUUUUUUUUUUUFWWFFFEETTTTTT
EESEESSSGGSZZRRRRRRRRRRAAAPPBBBBBBBBBBBGGGGGGGGGGGGGGGGGGGGGGRRRRRRRGGGGGMMMMMPPMMPYYYYYYPPPOOOOOOOOOGGGGGGGGUUUUVVUUUUUUUUUVFFFWWFFEEEWTTTT
SSSSSSSSSGSCCRRRRRRRRRQAAAVPBBBBBBBBBBHGGGGGGGGGGGGGGGGGGGGGGRRRRRRGGGGGGGGMMMPMMMMMMYMMMSSPPOROOROORGGGGGGGUUUGVVVUUUUUUUUUVVFFFFFEEEWWTTTT
SSSSSSSSSSSSCRRRRRRRRRQQAAPPABBBBBBBHBHGGGGGGGGGGGGGGGGGGGGGGRRRGGGGGGGGGGGMMMMMMMMMMMMSSSSPSRROOROOOGGGGGGGUGGGGVVUUUUUUUUCVVVFFFFEFFTTTTTT
SLLSSSSSSSSSRRRRRRRRRRRAAPPPBBPHBBBBHHHHGGGGGGGGGGGGGGGGGGGGGRRRFFGGGGGGGGMMMMMMMMMMMMMSSSSSSRRRRROORGGGGGGGUGGVVVVUUUUUUUVVVVVFVFFFFFFFTTTT
SSSSSSSSSSSSSRRRRRRRRRHHPPPPPPPHBBHHHHHHGGGGGGGGGGGGGGQQQQQJJJJRFFGGGGGGGCMMMKMMMMMMMMMSSSSSSRRRRRRRRGGGGGGGGGVVVVVVLLUUUVVVVVVVVFFFFFFCTTTT
VSSSSSSSSSSSSRRRRRRXXRHHHPPPPPPPPHHHHHHHGGGGGGGGGGGGGQQQLQQJJJJRRFFGGGGGGCCCKKMMMMMMMSSSSSSSSSRRRRRRRGGGGGGGGGRVVVIITTTTVVVVVVVVVVVFCCFCCECC
SSSSSSSSSSSSSRRRRRRRXRHHHPPPPPPPPHHHHHHHGGGGGGGGGGGGGQQVMMJJMJMMMFFFFFFFGECKKKKMMMMMMMMMSSSSSSSSSRRRRGGGGGGGAGGVFTTITTTVVVVVVVVVVLCCCNCCCCCC
SSSSSSSSSSSSSRRRRRRRRRHHPPPPPPPPIIHHHHHHHHHIGGGGGGGGGQMMMMJJMMMMFFFFFFFFGCCKKKKKMMMMMMMMMMMSSSHHHHRRRRGGGGAAAGGGFTTTTTTVVVVVVVVVVVVCCCCCCCCC
SSSSSSSSSSSSRRRRRRRRXXPPPPPPPPPPHHHHHHHHHTIIGGGGGGGGGMMMMMMJMMMMMFFFFFFFCCCCKKKKMMMMMMMMMMMMSHHHHHHRRRGGGGGGGGGGTTTTTTTVTVVVVVVCCCCCCCCCCYCC
SSSSSSSSSSHSRRRRRRRRXXPPDPPPPPPPHHHHHHHHHTIIGGGGGGGGGMMMMMMMMMMMMMFFFFFFCCBKKKKKMMMMMMMMMMMXXXHHHHHRHHYYGGGGGGGGTTTTTTTTTVVVVVVVCCCCCCCCCYCB
VSSSSSSSSSSRRRRRRRRBBBMPPPPPPPPPEHHHHHHHHHIIIIIIIIIIMMMMMMMMMMMMMMFFFFFCCCCCCCKKKKKMMMMMMMMXXHHHHHRRHHYYGGGGGGGGTTTTTTTTHVVVVVVCCCCCCCCCCCBB
SSSSSSSSSSSRRRRRRRBBBBMMPPPPPPPMHHHHHHHHHHYDDIIYYIIIIMMMMMMMMMMFFFFFFFFFCCCCCKKKKKKMMMMMMMXXXXHHHHHHHYYYGGGGGGGGTTTTTZZZVVVVVVVCCCCCCCCCCBBB
NNNNNSSSSSSRRRRRRRBBBBMPPPPPPPPMHHHHPPHHHHYDYYIYYYMMMMMMMMMMMMFFFFFFFFFFCBBBBBBBBBBMMMMMHMMXXXHHHHHHHHHHHGGGGGGGTTTGGZZZVVVVVCCCCCCCCCCCCBBB
NNNNNNNSRRRRRRRRRRRRBBMPPPPPPPMMMHHPPPPPHYYYYYIYYYYYYYMMMMMMMMFFFFFFFFFFKBBBBBBBBBBKMMMMBDDBXXBBHHHHHHHHHGGGGGGGGGGGGGZZVVVVVVVOOCCCCCCCCBBB
NNNNNNNSRRRRRRRRRRRRRBMMPPPPPPMMMHHPPPPPPYYYYYYYYYYYYMMMMMMMMFFFFFFFFFFKKBBBBBBBBBBKKMMKBBBBBBBBHHHHHHHHHGGGGLGGGGGGGGGVVVVVVOOOOOCCCCCBCBBB
NNNNNNNSSRRRRRRRRRRRRMMMMMMMMMMMMMHCCCPPYYLYYYYYYYYYYMMMMMMMMIIFFFFFFFKKKBBBBBBBBBBKKKKKBBBBBBBBYHHHHHHGHGGGGLLGGGGGZGGOVVVOOOOONNCCCCCBBBBB
NNINNNNSSRRRRRRRRRRRRMRRMMMMMMMMMMCCCCBBBBBYYYYYYYYYMMMMMMMMMFIFFFFFFFFBBBBBBBBBBBBKKKKKBBBBBBBBBHHHHHJGGGLLLLLGGGGGGGGOVVOOOOOBBBBCCCCCBXBX
IIIINNNNRRRRRRRRRRRRRRRRMMMMMMMMMMCCCJBBBBBBYYYYYYYYYMMMMMMFFFFFFFFFFFBBBBBBBBBBBBBKKKKKOOOBBBBBBHBHHHJJLLLLLLLLGGGGGGOOOOOOOOOBBBBCCBBBBXXX
IIIIIIRRRRRRRRRRRRRRRRRRMMMMMMMMMCCCCCCCBBBBYYYYYYYYYMWWWWWFFFFFFFFFFFFBBBBBBBBBBBBKKKKOOOBBBBBBBCBHHHJJLLLLLLLGGGGGOOOOOOOOOBBBBBBBBBBBBBXX
IIIIIIIIRIIRRRRRRRRRRRRMMMMMMMMMMMCCCCCCBBBBBBBYYYYYYMWWWWWWWFFFFFBBBBBBBBBBBBBBBBBKKKKKBBBBBBBBBBBBJJJLLLLLLLGGGGGGGOOOOOOOBBBBBBBBBBBBBBXX
IIIIIIIIIIIRRRRRRRRRRMMMMMMMMMMMMMMCCBCCBBBBBBBYYYYYYMWWWWWTTGFFFFFFBBBBBBBBBBBBBBBKKKKKBBBBBBBBBBBBBJLLLLLLLLGGGGUGGGOOOOOOOBBBBBBBBBBBBBXX
IIIIIIIIIIIRRRRRRRMMRMMMMMMMMMMMUUMMCBBBBBBBBBBYYYYYJJWWWWWTTTFGFFBBBBBBBBBBBBKHHHKKKKKKBBBBBBBBBBBBBJLLLLLJJJRGGUUGGGOOOOOOOOBBBBBBBBBBBBXX
IIIIIIIOOIIIRRMRRMMMMMMMMMMMMMMMUUUCCUUUBBBBBBBBYJJYJJJJWTTTTTFGKRKKBBBBBBBBBBBTHHHHHHHHBBBBBBBBBBBBJJLQQJLJJJUUUUUOOGOOORORRBBBBBBBBBBBEEEE
IIIIIIOOOIIIRRMMMMLLMMLLLLMMMMUUUUUUUUUUUBBBBBJOJJJJSJJWWWTTTTFKKKKBBBBBBBBBBTTTHHHHHHBBBBBBBBBBBBBBJJJQJJJJJFFUUUUUOOOOORRRRRBBBBBBBBCCEEEE
TIIIIIOOOOIIIMMMMMLLLLLLLMMIIUUUUUUUUUUUUUBBBBJJJJJJJJJWXTTTTTKKKKKKKKBBBBBBBTTTTTTHHHHBBBBBBBBBBBBBVVJQJJJJJJFUUUUUOUUORRRRRRBBBBBBBBCCCECE
IIIJJIOOOIIIIIIMMLLLLLLLLLLIIIIUIUUUUUUUUUBBDDJJJJJJJJJJXTTTTTKKKKKKKBBBBTTTTTTTTTTTHHBBBBBBBBBVVBBBVVVJJJJJJJUUUUUUUUUORRRRRRBBRBBBBBCCCECE
IIIJJJOOOIIIIIIMMMCLLLLLLLLHIIIIIUUUUUUUUUDDDDJJJJJJJJXXXTTTKKKKKKKKKBBBBTTTTTTTTTTHHHHHHHBBBBBVVBBVVVVVVVJJJJPUUUUUPUUORRRRRRRRRBBBBCCCCECC
PPJJJOOOOIIIIIIMMMRRULLLLLLHIIIIIIUUUUUUUUDDDJJJJJJJJJXXXTTKKKKKKKKKKBBBTTTTTTTTTTTTHHHHHHBBBBBBVVVVVVVVVVJJJJPUUUUUPUUORRRRRRRRRBBCCCCCCCCC
PPPPJOOIIIIIIIIMMMRRRLLLLLHHIIIIIIIIUUUUUUUUJJJJJJJJJJXIIIKKKKKKKKKKKBBBTTTTTTTTTTYTHHHHHHHBBBVVVVVVVVVVVVJJPPPPPUPPPURRRRRRRRRRRTBBBCCCCCCG
PPPPOOIIIIVVVIIRRRRRRHHHHHHIIIIIIUUUUUUUUUUDJJJJJJJJJJJOIIKKKKKKKKNKKBBTTTTTTTTTTTTTHQQQHHHBVVVVVVVVVVVVVVVJPPPPPUPPUUUUURRRRRRRMTBBBTTCCCCC
PPVVVVVVVVVVIIRRRRRRRRHRHHHIIIIIIUYYYYUYUUUDDJJJJJJJJJJJIIKKKKKKKKNNNNNTTTTTTTTTTTTTQQQQHHHPVVVVVVVVVVVVVVVPPPPPPPPPUUUUUURRRRRXTTTTBTTCCCCC
PVVVVVVVVVVVVRRRRRRRRRHRRHHHIIIHIYYYEEUUUUZMDDDJJJJJJJJJIIIIIIIKKNNNNNTTTTTTTTTTTTTTTQQQPPHPPPPPVVVVVVVVVEEEEPPPPPPJJXXXURRRRRRXXTTTTTTGTCCC
PPPYVVVVVVVVRRRRRRRRRRRRHHHHHIHHIEEYEEEEEMMMMMJJJJJJIJIIIIIIIIINNQQNNNNNTTTTTTTTTTTTTQQQPPPPPGPPPVVVVVVVVVEEEEPPPFFSJJXFURRRRRVRXTTGTTTTTTKC
PPPVVVVVVVVVVTRRRRRRRRRRRRRHHHHHHHEEEEEEEMMMMYMJJJJJIIIIIIIIIILNNNNNNNNTTTTTTTTTTTTTTEQQPPPPPPPPVVVVVVVEEEEEEEEEPFFFJJFFFFRRRRRRRCCTTTTTTTKK
PPVVVVVVVVVVVVVRRRRRRRRRRRRHHHHHHHEEEEEEMMMMMMMMJJJJIIIIIIIIIILLNNNNNNNTTTTTTTTTTTTTTPPPPPPPPPPPVVVVVVEEEEEEEEPPPFFFQQFFIRRRRRRRRRCTTTTTTKKK
PVVVVVVVVVVVVVVVRRRRRRRHRHHHHHHHHHHEEHEEEMMMMMMMMJJJIIIIIIIILLLLNNNNNNNNNTTTTTYTYTTTTTPPPPPNNNPPPPVVVVVEEEEEEEEEPFFFQFFFIIIRRRRRRKTTTTTTTTKK
PPVVVVVVVVVVVVVRRRRRRERHHHHHHHHHHHHHHHEEEMMMMMMMMMMJJIIIIIIIILLLLNNNNNNNNOTYYTYYYTPVVPPPPPPNVNNNNNVVVVVEEEEEEEEEPPFFFFFFFFIIIIIRIKITTTTTTTVV
PPVPVVVVVVVVVVWRRREEBERHHHHHHHHHHHHMHHEEMMMMMMMMMMMIJIIIIIILLLLGLGNNNNNOOOOOYYYYYPPPPPPPPPPNNNNNNNNNNVVEEEEEEEEFFFFFFFFFFIIIIIIIIIITTTVVVVVV
PPPVVVVVVVVVVVVRREEEEEHHHHHHHHHHHHHMMMMMMMMMMMMMMMLIIIIIIIIIIGGGGGGNNNNOOOOOYYYYYPPPPPPPPPNNNNNNNNNNVVVVVEEEEEEEFFFFFFFFFIIIIIIIIIIMVVVVVVVV
PPPVVVVVVVVVOVVRREEEEEEEEHEHHHHHHHMMMMMMMMMMMMMLLLLIIIIIIIIIIGGGGGNNNNNOOOOOYYYYYYPPPPPNPPNYNNNNNNNNNNVVVEEEEEEEFFFFFFFJJJIIIIIIIIVVVVVVVVVV
PPPPVPPVVVVVOVVHREEEEEEEEEEHHHHHHHMMMMMMMMMMMLLLLLSLLLIIIIIIIGGGGGGQQOOOOOOOYYYYYYYPPPPNNNNYNNNNNNNNNVVVEEEEEEEEFFFFFFFFFJIIIIIIIIIIIVVVVVVV
PPPPVPPVPPVOOVVHEEEEEEEEEEEEEHHHHHHHHHMMMMMMMLLLLLLLLJLILIYLLGGGGGQQQQOOOOOOOYYYYYYYYPPNNNNNNNNNNNVVVVVVVEEEYEEEFFFFFFFJJJIIIIIICCYIIIVVVVVV
PPPPPPPPPPPOOOOESEEEEEEEEEEEEEIIHHIHHHMMMMMMLLLLLLLLLLLLLLLLLLGGGQQQQOOOOOOOOYYYYYYYYYNNNNNNNNNNNNVVVVVVVEEEYYYYFFFFFFJJJJIIIIIICCYYIIVVVVVV
PPPPPPPPPPPPPOOEEEEEEEEEEEEEEIAIIIIHHHIYYMMMMMLLLLLLLLLLLLLLLLGGGQQQOOOOOOYOOYYYYYYYYYYYYYYYNNNDDNJVVVVVVEEYYGYTTTTFFJJJJJIIIIICCCCIIIIIVVVV
PPPCPPPCCCCPPPOEQEEEEEEEEEEEIIIIIIIIIIIIIIMMMMLLLLLLLLLLLLLLLLLGGQRQQQOOQYYOYYYYYYYYYYYYYYZYNNNNDVVVVVVVVVGGYGTTTTTFFFJJJJJIIICCCIIIIIIIIVVV
PPCCCCCCCCCCOOOOCEEECCEEEEBBOOIIIIIIIIIIVVMVVVVVVVVLLLLLLLLLLMGGGRRRQQOQQYYYYYYYYYYYYZZZZZZYNNNDDVVVVVVVVVGGGGGGTTTTFTTJJJJIICCCIIINIIIIIVVV
PPCCCCCCCCCOOOOOCECCCCCCCNBBBBIIIIIIIIIIIVVVVVVVVVLLLLLLLLMMMMGGMMRCCQQQQQQQQYYYYYYYYZZZZZZZNDDDDDDDDDVVVGGGGGGGTTTTTTTJJJJJJCCCICINIYIYYYYV
PPCCCCCCCCCCCOOCCECCCCCCQBBBBBIIIIIIIIIIVVVVVVVVVVLLLLLLLLLMMMMMMMRCCQQQQQCCCRYYYYAZZZZZZZZZZDDDDDDDDDVOOGGGGGTGGTTTTTJJJJJJCCCCCCIYYYYYYYYY
PPCCCCCCCCCCOOOCCCCCCCCCCBBBBIIIIIIIIIIIVVVVVVVVVVLLLLLLLLLMMMMMMMCCCCCCCCCCRRYYRZZZZZZZZZZZZZDDDDDQQDQOQLGGGGGGTTTTTTJJJJJJJJCCYYYYYYYYYYYY
PPCCCCCCCCCCOOCCCCCCCCCCBBBBBIIIIIIIIIIYYYYYVVVVVVVLLLLLLMMMMMMMCCCCCCCCCCCRRRRYRZZZZZZZZZZZZDDBDQQQQQQQQQQQGGGGTTTTTTTJJJJJCCCCYYYYYYYYYJYY
PPPPCCCCCCCCCCCCCCCCCCCCCBBBBIIIIIIIIIICYYYYVVJVVVLLLLLLMMMMMMMMCCCCCCCCCCCRRRRRRRZFLLLZZZZZDDDBBBQQQQQQQQQQGGGGTTTTTTTTTJJJCCCCYYYYYYYYYYYY
PPPPCCCCCCCCCCCCCCCCCCCCCBBBBBBIIIIPIIIIYYYYVJJJVVVLYYYLMRMMMMMMMDCCCCCCCCRRRRRRRRLLLLLLZZZZDDDBBBBBQQQQQQGGGGGTTTTTTTTTTJJJCCCCCUYYYYYYYYYY
PPPPPPPCCCCCCLLLLCCCCCCCCCCBBBIIIIPPIIIIIIIYVJJJJJJJYYYYYMMMMMMMCCCCCCCCCCRCCCRRRRLLLLLZZZZZZBBBBBBBQQQQQGGGGGGTTTTTTTTTTTJJJCCPCYYYYYYYYYYY
PEPEEPPPCLLLLLLLLCCCCCCCCCCCCIIIPPPPIIIIIIVVVJJJJJJJYYYYYYMMMMMMCCCCCCCCCCCCCRRRRLLLLLAAZZBBBBBBBBBBQQQQQQQQQGGGQTTTTTTTTTTRRCCPPPYYYYYYYYHY
PEEEEEELLLLLLLLLLCCCCCCCCCCIIIIIPPPPPPPVIVVVVVVJJJJYYYYYYYYMMMMMMCCCCCCCCCCCCCRRLLLLLLLALLLLBBBBBBBBBQQQQQQQQQQQQTTTTTTTTTTCCCCCPPPYYYYYYYYD
PEEEEEELLLLLLLLCCCCCCCCCCCCCCIIIPPPPPPPVVVVVVVJJJJYYYYYYYYMMMMMCCCCCCCCCCCCCCRRRRRLLLLLLLLLLBBBBBBBBBBBBBQQQQQQQQQTTTTTTTTTTUCZCPPPYYYYYYDDD
EEEEEEELLLLLLLLCCCCCCCCCCCCCCIIPPPPPPPPPVVVVVJJEJJYYYYYYYYMMMMMCCCCCCCCCCCCCCRRRRRLLLLLLLLLPBBBBBBBBBBBRQQQQQQQQQQTTTTTTTTTTTZZCCPPYYYYDDDDD

View File

@@ -0,0 +1,193 @@
use std::collections::{HashMap, HashSet};
fn parse(input: &str) -> HashMap<(i64, i64), char> {
let mut result = HashMap::new();
for (j, l) in input.lines().enumerate() {
for (i, c) in l.chars().enumerate() {
result.insert((i as i64, j as i64), c);
}
}
result
}
fn solve_1(input: &str) -> i64 {
let original_map = parse(input);
let mut visited: HashSet<(i64, i64)> = HashSet::new();
let mut result = 0;
for (&(x, y), plant) in original_map.iter() {
if !visited.contains(&(x, y)) {
let mut stack = vec![(x, y)];
let mut area = 0;
let mut perimeter = 0;
visited.insert((x, y));
while !stack.is_empty() {
let cur = stack.pop().unwrap_or_default();
area += 1;
let up = (cur.0, cur.1 - 1);
let right = (cur.0 + 1, cur.1);
let down = (cur.0, cur.1 + 1);
let left = (cur.0 - 1, cur.1);
let candidates = vec![up, right, down, left];
for candidate in candidates {
if let Some(p) = original_map.get(&candidate) {
if p == plant {
if !visited.contains(&candidate) {
stack.push(candidate);
visited.insert(candidate);
}
} else {
perimeter += 1;
}
} else {
perimeter += 1;
}
}
}
result += area * perimeter;
}
}
result
}
fn turn(dir: (i64, i64)) -> (i64, i64) {
match dir {
(0, -1) => (1, 0),
(1, 0) => (0, 1),
(0, 1) => (-1, 0),
(-1, 0) => (0, -1),
_ => unreachable!(),
}
}
fn rev_turn(dir: (i64, i64)) -> (i64, i64) {
turn(turn(turn(dir)))
}
fn solve_2(input: &str) -> u64 {
let original_map = parse(input);
let mut visited: HashSet<(i64, i64)> = HashSet::new();
let mut result = 0;
for (&(x, y), plant) in original_map.iter() {
if !visited.contains(&(x, y)) {
let mut stack = vec![(x, y)];
let mut area = 0;
visited.insert((x, y));
let mut edges = HashSet::new();
while !stack.is_empty() {
let cur = stack.pop().unwrap_or_default();
area += 1;
let up = (0, -1);
let right = (1, 0);
let down = (0, 1);
let left = (-1, 0);
let candidates = vec![up, right, down, left];
for candidate in candidates {
let cand_coord = (cur.0 + candidate.0, cur.1 + candidate.1);
if let Some(p) = original_map.get(&cand_coord) {
if p == plant {
if !visited.contains(&cand_coord) {
stack.push(cand_coord);
visited.insert(cand_coord);
}
} else {
edges.insert((cur, candidate));
}
} else {
edges.insert((cur, candidate));
}
}
}
let mut sides = 0;
while edges.len() > 0 {
let start_edge = edges.iter().next().unwrap().to_owned();
let edge_side = start_edge.1;
let start_dir = turn(edge_side);
let mut dir = start_dir.clone();
let mut cur_edge = start_edge.clone().0;
let mut visited_edges_dir: HashSet<((i64, i64), (i64, i64))> = HashSet::new();
while !visited_edges_dir.contains(&(start_edge.0, start_dir)) {
let next = (cur_edge.0 + dir.0, cur_edge.1 + dir.1);
if let Some(p) = original_map.get(&next) {
if p == plant {
cur_edge = next;
let left = rev_turn(dir);
let left_edge = (cur_edge.0 + left.0, cur_edge.1 + left.1);
if let Some(p2) = original_map.get(&left_edge) {
if p2 == plant {
dir = left;
cur_edge = left_edge;
sides += 1;
}
}
} else {
dir = turn(dir);
sides += 1;
}
} else {
dir = turn(dir);
sides += 1;
}
edges.remove(&(cur_edge, rev_turn(dir)));
visited_edges_dir.insert((cur_edge, dir));
}
}
result += area * sides;
}
}
result
}
fn main() {
println!("Hello, this is Patrick!");
let input = include_str!("../input.txt");
let result_1 = solve_1(input);
println!("The total price of all fencing is {}", result_1);
let result_2 = solve_2(input);
println!("The new total price of all fencing is {}", result_2);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), 1930);
}
#[test]
fn test_2() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_2(test_input), 1206);
}
}

View File

@@ -0,0 +1,10 @@
RRRRIICCFF
RRRRIICCCF
VVRRRCCFFF
VVRCCCJFFF
VVVVCJJCFE
VVIVCCJJEE
VVIIICJJEE
MIIIIIJJEE
MIIISIJEEE
MMMISSJEEE

View File

@@ -0,0 +1,7 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
[dependencies]
nom = "7.1.3"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,163 @@
use nom::{
bytes::complete::tag,
character::complete::{i64, multispace1},
multi::many1,
sequence::{delimited, separated_pair, tuple},
IResult,
};
fn parse(input: &str) -> IResult<&str, Vec<((i64, i64), (i64, i64), (i64, i64))>> {
let (_input, result) = many1(tuple((
delimited(
tag("Button A: X+"),
separated_pair(i64, tag(", Y+"), i64),
multispace1,
),
delimited(
tag("Button B: X+"),
separated_pair(i64, tag(", Y+"), i64),
multispace1,
),
delimited(
tag("Prize: X="),
separated_pair(i64, tag(", Y="), i64),
multispace1,
),
)))(input)?;
Ok((input, result))
}
// For a / b
fn divisible(a: f64, b: f64, epsilon: f64) -> bool {
let div = a / b;
(div - div.round()).abs() < epsilon
}
fn equal(a: f64, b: f64, epsilon: f64) -> bool {
(a - b).abs() < epsilon
}
fn linear_solve_1(a: (i64, i64), b: (i64, i64), prize: (i64, i64)) -> Option<i64> {
const EPS: f64 = 0.000001;
let (fa1, fb1) = (a.0 as f64, a.1 as f64);
let (fa2, fb2) = (b.0 as f64, b.1 as f64);
let (p1, p2) = (prize.0 as f64, prize.1 as f64);
let y_denominator = fb2 - fb1 * fa2 / fa1;
if equal(y_denominator, 0.0, EPS) {
return None;
}
let y_nominator = p2 - fb1 * p1 / fa1;
if !divisible(y_nominator, y_denominator, EPS) {
return None;
}
let x_nominator = p1 - fa2 * (p2 - fb1 * p1 / fa1) / (fb2 - fb1 * fa2 / fa1);
if !divisible(x_nominator, fa1, EPS) {
return None;
}
let y = (y_nominator / y_denominator).round() as i64;
let x = (x_nominator / fa1).round() as i64;
if x < 0 || y < 0 || x > 100 || y > 100 {
return None;
} else {
return Some(x * 3 + y);
}
}
fn linear_solve_2(a: (i64, i64), b: (i64, i64), prize: (i64, i64)) -> Option<i64> {
const EPS: f64 = 0.001;
const BONUS: i64 = 10000000000000;
let (fa1, fb1) = (a.0 as f64, a.1 as f64);
let (fa2, fb2) = (b.0 as f64, b.1 as f64);
let (p1, p2) = ((prize.0 + BONUS) as f64, (prize.1 + BONUS) as f64);
let y_denominator = fb2 - fb1 * fa2 / fa1;
if equal(y_denominator, 0.0, EPS) {
return None;
}
let y_nominator = p2 - fb1 * p1 / fa1;
if !divisible(y_nominator, y_denominator, EPS) {
return None;
}
let x_nominator = p1 - fa2 * (p2 - fb1 * p1 / fa1) / (fb2 - fb1 * fa2 / fa1);
if !divisible(x_nominator, fa1, EPS) {
return None;
}
let y = (y_nominator / y_denominator).round() as i64;
let x = (x_nominator / fa1).round() as i64;
if x < 0 || y < 0 {
return None;
} else {
return Some(x * 3 + y);
}
}
fn solve_1(input: &str) -> i64 {
let (_, result) = parse(input).unwrap();
result
.into_iter()
.filter_map(|(a, b, prize)| linear_solve_1(a, b, prize))
.sum()
}
fn solve_2(input: &str) -> i64 {
let (_, result) = parse(input).unwrap();
result
.into_iter()
.filter_map(|(a, b, prize)| linear_solve_2(a, b, prize))
.sum()
}
fn main() {
println!("Hello, this is Patrick!");
let input = include_str!("../input.txt");
let result_1 = solve_1(input);
println!("The fewest tokens spent to get all prizes is {}", result_1);
let result_2 = solve_2(input);
println!(
"With the huge positions, the fewest tokens to get all prizes is now {}",
result_2
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), 480);
}
#[test]
fn test_2() {
let test_input = include_str!("../test.txt");
let ts = parse(test_input).unwrap().1;
for (i, t) in ts.into_iter().enumerate() {
if i % 2 == 0 {
assert!(linear_solve_2(t.0, t.1, t.2).is_none());
} else {
assert!(linear_solve_2(t.0, t.1, t.2).is_some());
}
}
}
}

View File

@@ -0,0 +1,15 @@
Button A: X+94, Y+34
Button B: X+22, Y+67
Prize: X=8400, Y=5400
Button A: X+26, Y+66
Button B: X+67, Y+21
Prize: X=12748, Y=12176
Button A: X+17, Y+86
Button B: X+84, Y+37
Prize: X=7870, Y=6450
Button A: X+69, Y+23
Button B: X+27, Y+71
Prize: X=18641, Y=10279

View File

@@ -0,0 +1,7 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
[dependencies]
nom = "7.1.3"

View File

@@ -0,0 +1,500 @@
p=62,65 v=-96,-93
p=50,44 v=72,74
p=33,42 v=-6,-83
p=68,100 v=36,21
p=45,36 v=3,-44
p=9,48 v=-14,47
p=55,21 v=-71,-7
p=65,10 v=-58,-9
p=22,11 v=93,36
p=25,38 v=58,-46
p=82,16 v=-73,49
p=93,31 v=-51,-77
p=42,70 v=32,35
p=17,0 v=-46,-26
p=36,55 v=70,85
p=94,101 v=53,-18
p=4,73 v=17,-39
p=17,4 v=89,7
p=99,17 v=-50,-40
p=20,101 v=-49,11
p=82,24 v=13,-71
p=11,64 v=49,-76
p=2,98 v=94,90
p=41,62 v=69,-43
p=100,99 v=-50,-26
p=84,60 v=16,68
p=8,20 v=16,-50
p=50,6 v=34,52
p=17,50 v=-40,41
p=90,88 v=-62,74
p=25,36 v=-11,-46
p=93,29 v=12,22
p=47,62 v=61,-25
p=68,22 v=-97,-36
p=49,70 v=67,58
p=31,13 v=-74,-71
p=22,29 v=-77,47
p=8,81 v=-14,87
p=24,31 v=-41,26
p=16,77 v=17,-18
p=18,89 v=-79,83
p=98,44 v=83,20
p=66,73 v=-58,-51
p=96,49 v=-52,-25
p=82,5 v=-26,56
p=63,16 v=6,-36
p=8,25 v=-38,48
p=85,38 v=38,34
p=39,48 v=-39,16
p=64,29 v=43,-87
p=99,33 v=26,60
p=52,91 v=53,30
p=0,98 v=-12,7
p=45,93 v=64,85
p=67,55 v=90,-39
p=19,78 v=90,-14
p=87,92 v=-86,-7
p=14,50 v=55,47
p=79,23 v=-63,32
p=61,66 v=-78,-5
p=55,67 v=1,16
p=90,10 v=-57,94
p=21,76 v=-78,60
p=83,76 v=-89,-29
p=24,8 v=57,-63
p=71,55 v=-57,51
p=66,62 v=71,-91
p=86,11 v=-54,-17
p=81,21 v=-22,18
p=92,6 v=14,75
p=30,24 v=89,-83
p=63,0 v=63,-19
p=16,59 v=17,-89
p=61,27 v=-63,30
p=93,27 v=49,14
p=17,39 v=-77,51
p=75,97 v=-98,77
p=21,63 v=86,-4
p=4,72 v=-95,-89
p=92,96 v=79,-88
p=94,20 v=-84,-1
p=73,15 v=38,-65
p=81,0 v=12,-57
p=6,61 v=-83,-86
p=59,29 v=67,47
p=58,40 v=31,-50
p=61,55 v=-99,-99
p=24,82 v=-47,6
p=16,60 v=-84,-68
p=92,30 v=-87,-52
p=56,10 v=64,-98
p=75,86 v=54,-30
p=50,15 v=28,80
p=14,81 v=-12,-10
p=90,87 v=-87,-26
p=98,53 v=-18,35
p=11,16 v=-48,63
p=62,86 v=71,58
p=97,95 v=-28,72
p=16,63 v=-29,35
p=63,51 v=41,-63
p=44,16 v=41,35
p=9,72 v=14,-1
p=7,37 v=51,63
p=63,60 v=4,10
p=83,77 v=80,64
p=42,0 v=-37,-84
p=99,101 v=99,5
p=66,92 v=8,95
p=91,68 v=16,-82
p=59,37 v=-66,82
p=99,2 v=-52,9
p=53,2 v=-99,5
p=87,97 v=-10,4
p=15,48 v=63,-29
p=100,7 v=14,7
p=93,85 v=15,25
p=73,6 v=-60,15
p=53,6 v=45,62
p=83,79 v=-22,-43
p=100,93 v=17,-84
p=1,51 v=-83,76
p=98,30 v=-86,12
p=78,24 v=-27,-3
p=53,73 v=2,29
p=43,19 v=-3,-7
p=42,35 v=-35,55
p=55,70 v=73,-9
p=55,73 v=-99,-12
p=82,88 v=77,-84
p=52,82 v=49,-50
p=99,5 v=-18,-61
p=96,87 v=6,-58
p=73,93 v=41,79
p=39,34 v=99,-46
p=78,38 v=14,26
p=38,39 v=-6,53
p=68,27 v=73,90
p=57,43 v=-24,57
p=7,66 v=-87,43
p=0,13 v=-18,67
p=72,69 v=12,-43
p=66,61 v=-12,-90
p=67,0 v=-99,-55
p=43,94 v=37,-84
p=70,15 v=-94,-1
p=4,83 v=52,25
p=57,41 v=-3,47
p=18,89 v=-46,21
p=64,12 v=37,98
p=36,84 v=-41,-37
p=47,62 v=-68,66
p=40,13 v=96,-30
p=100,0 v=-84,-59
p=14,62 v=88,-99
p=90,27 v=13,-48
p=14,50 v=-33,-95
p=57,1 v=-46,-70
p=25,42 v=87,7
p=82,77 v=-90,-41
p=79,11 v=8,48
p=64,51 v=43,-64
p=93,6 v=-92,5
p=41,55 v=-1,-23
p=20,89 v=88,-49
p=31,2 v=-44,-42
p=40,100 v=-73,-92
p=62,14 v=-14,-97
p=9,4 v=-56,94
p=81,69 v=10,-45
p=25,1 v=30,-36
p=3,28 v=83,82
p=62,79 v=-62,62
p=4,74 v=16,31
p=43,54 v=33,-4
p=87,43 v=-87,53
p=0,25 v=-52,4
p=49,63 v=-94,18
p=87,31 v=45,22
p=53,30 v=79,-38
p=80,92 v=41,5
p=36,99 v=-77,56
p=74,13 v=42,-25
p=78,85 v=-97,-24
p=42,33 v=-73,83
p=62,66 v=1,4
p=100,64 v=-46,-2
p=53,86 v=-38,-92
p=53,13 v=93,-67
p=74,75 v=41,21
p=16,25 v=2,19
p=39,74 v=-5,-2
p=79,56 v=-37,-94
p=28,54 v=-80,-21
p=50,18 v=-77,-83
p=33,98 v=-11,1
p=89,79 v=-16,-51
p=88,96 v=80,9
p=49,90 v=-71,39
p=95,89 v=-67,-16
p=48,80 v=-99,13
p=4,0 v=-51,7
p=94,61 v=53,76
p=13,36 v=-31,-44
p=21,25 v=59,-44
p=8,3 v=-80,11
p=13,0 v=-80,-59
p=26,72 v=90,-29
p=51,98 v=-9,41
p=95,92 v=87,-49
p=6,65 v=-16,23
p=63,87 v=72,8
p=7,29 v=85,-7
p=58,56 v=69,-10
p=87,68 v=7,39
p=10,32 v=54,-13
p=43,100 v=31,11
p=46,19 v=74,6
p=31,96 v=99,58
p=39,34 v=44,-11
p=30,55 v=58,76
p=79,94 v=10,83
p=85,99 v=-87,-47
p=92,96 v=14,-92
p=35,43 v=-40,-52
p=73,57 v=7,-35
p=6,7 v=-37,-43
p=64,72 v=2,31
p=89,100 v=14,50
p=11,47 v=-14,76
p=64,3 v=-61,41
p=73,102 v=41,-4
p=62,45 v=5,-52
p=42,81 v=-72,-76
p=55,18 v=70,-1
p=74,72 v=-60,62
p=69,100 v=-66,92
p=74,45 v=-60,6
p=70,23 v=6,24
p=8,63 v=18,57
p=83,58 v=44,2
p=88,28 v=-50,34
p=91,12 v=52,63
p=56,94 v=-67,-97
p=3,73 v=51,35
p=3,48 v=6,-98
p=83,83 v=-5,39
p=40,13 v=-7,10
p=9,21 v=-49,-85
p=98,7 v=18,40
p=58,42 v=3,20
p=65,2 v=5,-30
p=69,12 v=40,-79
p=37,70 v=29,-70
p=91,101 v=47,-96
p=28,4 v=89,-18
p=2,1 v=81,-3
p=10,57 v=-13,-33
p=22,31 v=-10,-13
p=16,39 v=21,-83
p=41,59 v=68,65
p=34,19 v=-4,28
p=38,33 v=59,-93
p=42,26 v=23,-80
p=56,10 v=5,94
p=38,63 v=-73,-68
p=59,94 v=-96,-65
p=16,35 v=57,53
p=30,62 v=-45,71
p=32,98 v=-28,-42
p=3,0 v=80,52
p=39,84 v=-38,17
p=58,17 v=36,-3
p=14,9 v=-84,-77
p=27,86 v=-75,60
p=54,12 v=-97,5
p=59,9 v=-30,-34
p=57,1 v=-42,-53
p=12,1 v=-9,-5
p=5,59 v=-82,41
p=30,34 v=56,-53
p=15,84 v=30,-30
p=44,13 v=-97,-97
p=3,101 v=-16,88
p=13,60 v=38,-63
p=19,31 v=-42,61
p=35,13 v=94,3
p=22,52 v=-81,-4
p=30,60 v=12,32
p=74,84 v=80,-4
p=11,44 v=68,23
p=23,44 v=88,24
p=48,24 v=-11,-72
p=52,49 v=33,84
p=27,47 v=-72,51
p=80,31 v=76,88
p=40,34 v=63,-50
p=34,11 v=-41,-32
p=3,84 v=90,-12
p=57,76 v=-38,-61
p=76,63 v=-92,-56
p=6,80 v=-9,50
p=77,62 v=77,4
p=37,44 v=57,-22
p=94,40 v=13,-19
p=43,52 v=66,41
p=18,91 v=-79,-55
p=90,79 v=65,-40
p=7,7 v=-87,32
p=11,47 v=-47,-17
p=47,0 v=-36,47
p=66,37 v=10,-48
p=34,96 v=30,-16
p=83,81 v=16,-9
p=13,85 v=-54,-41
p=51,7 v=26,78
p=5,94 v=47,-75
p=33,90 v=59,91
p=61,92 v=90,-53
p=7,18 v=-75,-93
p=8,32 v=89,-46
p=86,28 v=80,-15
p=49,88 v=5,-51
p=12,99 v=-46,-47
p=91,66 v=80,37
p=69,35 v=7,90
p=78,9 v=7,-61
p=97,80 v=21,4
p=39,70 v=1,-35
p=0,77 v=50,-41
p=38,43 v=71,2
p=31,42 v=61,-15
p=43,76 v=97,-63
p=51,15 v=-32,69
p=78,42 v=-87,6
p=71,18 v=40,38
p=95,4 v=-47,-13
p=11,1 v=-82,44
p=58,101 v=75,61
p=57,5 v=93,20
p=50,71 v=41,28
p=89,78 v=-19,-33
p=35,61 v=-63,-1
p=56,12 v=35,-34
p=91,76 v=-76,-69
p=33,31 v=-11,-13
p=88,84 v=12,-10
p=89,90 v=-26,-86
p=18,19 v=-10,-42
p=37,95 v=61,-20
p=48,83 v=84,-58
p=15,85 v=-30,-50
p=13,58 v=19,49
p=45,35 v=94,-75
p=46,81 v=-3,89
p=74,6 v=-25,77
p=91,22 v=-53,-7
p=2,9 v=35,-88
p=89,101 v=73,28
p=20,11 v=-87,28
p=48,71 v=-77,8
p=1,69 v=22,-37
p=36,57 v=97,84
p=25,37 v=-82,-52
p=25,87 v=62,7
p=0,58 v=16,68
p=77,73 v=79,-35
p=66,91 v=-96,21
p=44,83 v=33,-76
p=29,29 v=-10,-64
p=89,24 v=98,-5
p=92,63 v=83,-66
p=10,70 v=20,-39
p=78,16 v=-88,90
p=18,22 v=-11,-81
p=8,54 v=-15,-23
p=4,15 v=52,98
p=32,68 v=68,-6
p=19,98 v=-12,-24
p=85,66 v=-24,33
p=36,39 v=-75,-13
p=81,66 v=-71,-19
p=1,27 v=-87,-37
p=2,87 v=-15,19
p=92,41 v=13,78
p=100,40 v=-97,-75
p=31,53 v=-99,49
p=24,99 v=57,35
p=55,17 v=40,-30
p=24,60 v=59,-37
p=33,62 v=-73,41
p=99,58 v=50,37
p=5,84 v=-44,-80
p=83,65 v=34,88
p=84,33 v=-95,-77
p=69,63 v=1,-64
p=8,88 v=-16,-18
p=24,29 v=60,-69
p=9,0 v=21,79
p=42,87 v=2,-16
p=64,44 v=33,8
p=78,66 v=-88,-25
p=63,76 v=72,29
p=98,31 v=82,26
p=74,62 v=42,35
p=97,66 v=-74,-41
p=86,31 v=12,-77
p=31,81 v=63,68
p=51,31 v=1,51
p=77,18 v=3,-10
p=64,57 v=72,-27
p=60,56 v=-64,-87
p=69,60 v=34,32
p=8,90 v=-53,5
p=3,70 v=62,37
p=62,71 v=-35,66
p=64,42 v=-71,97
p=6,93 v=-99,-1
p=5,24 v=89,3
p=19,42 v=-73,49
p=92,20 v=-92,53
p=35,66 v=-73,37
p=93,86 v=-91,99
p=92,87 v=-22,58
p=14,8 v=-49,-55
p=86,56 v=-24,41
p=50,15 v=99,-65
p=92,81 v=79,-43
p=25,63 v=-41,2
p=71,19 v=43,-71
p=3,21 v=51,18
p=73,55 v=-94,41
p=74,6 v=80,-94
p=23,9 v=-9,10
p=18,82 v=-16,19
p=10,20 v=66,-7
p=18,57 v=56,6
p=1,89 v=-86,-47
p=72,55 v=-95,-29
p=95,50 v=-61,1
p=97,10 v=48,38
p=80,57 v=79,-97
p=71,19 v=69,36
p=27,71 v=-41,-78
p=35,58 v=29,62
p=31,73 v=28,66
p=37,32 v=65,59
p=60,102 v=85,-78
p=38,54 v=16,96
p=11,41 v=-80,20
p=14,68 v=22,99
p=48,46 v=-20,-19
p=3,79 v=17,19
p=10,9 v=-91,-66
p=79,0 v=-25,-28
p=38,26 v=-69,30
p=80,40 v=77,-58
p=36,69 v=62,-33
p=97,60 v=-68,41
p=70,59 v=-29,-76
p=81,22 v=-92,-11
p=15,55 v=57,43
p=59,19 v=75,-28
p=41,47 v=-3,18
p=28,72 v=23,68
p=2,26 v=85,67
p=91,13 v=42,-77
p=64,78 v=71,97
p=91,35 v=14,-17
p=41,69 v=63,29
p=35,7 v=-69,96
p=19,64 v=-12,-68
p=77,44 v=70,55
p=84,21 v=46,-71
p=28,38 v=-76,18
p=81,82 v=-20,-19
p=91,10 v=48,36
p=23,10 v=57,-22
p=49,34 v=-77,-4
p=73,25 v=75,-48
p=67,25 v=-95,-11
p=79,16 v=-26,-34
p=27,81 v=-3,-47
p=3,102 v=61,-94
p=85,82 v=-54,21
p=84,27 v=-89,94
p=40,94 v=64,15
p=97,57 v=-98,1
p=6,80 v=86,-12
p=42,77 v=30,2
p=44,5 v=74,-49
p=65,99 v=-24,-34
p=64,6 v=73,-69
p=37,65 v=-5,-29
p=23,60 v=-77,-95
p=25,35 v=-38,30
p=9,9 v=64,87
p=54,27 v=-69,63
p=53,21 v=-14,-36
p=42,31 v=2,30

View File

@@ -0,0 +1,115 @@
use nom::{
bytes::complete::tag,
character::complete::{i64, multispace1},
multi::separated_list1,
sequence::{preceded, separated_pair},
IResult,
};
fn parse(input: &str) -> IResult<&str, Vec<((i64, i64), (i64, i64))>> {
let (input, result) = separated_list1(
multispace1,
separated_pair(
separated_pair(preceded(tag("p="), i64), tag(","), i64),
tag(" v="),
separated_pair(i64, tag(","), i64),
),
)(input)?;
Ok((input, result))
}
fn calc_pos(
start_pos: (i64, i64),
velocity: (i64, i64),
width: i64,
height: i64,
time: i64,
) -> (i64, i64) {
let x = (start_pos.0 + velocity.0 * time).rem_euclid(width);
let y = (start_pos.1 + velocity.1 * time).rem_euclid(height);
(x, y)
}
fn solve_1(input: &str, width: i64, height: i64) -> i64 {
let (_, result) = parse(input).unwrap();
let (mut q1, mut q2, mut q3, mut q4) = (0, 0, 0, 0);
for (x_end, y_end) in result
.into_iter()
.map(|(pos, vel)| calc_pos(pos, vel, width, height, 100))
{
if x_end < width / 2 && y_end < height / 2 {
q1 += 1;
} else if x_end > width / 2 && y_end < height / 2 {
q2 += 1;
} else if x_end < width / 2 && y_end > height / 2 {
q3 += 1;
} else if x_end > width / 2 && y_end > height / 2 {
q4 += 1;
}
}
q1 * q2 * q3 * q4
}
fn solve_2(input: &str, width: i64, height: i64) -> i64 {
let (_, mut robots) = parse(input).unwrap();
let mut min_e = i64::MAX;
let mut time = 0;
for t in 0..=100000 {
let (mut q1, mut q2, mut q3, mut q4) = (0, 0, 0, 0);
for (pos, vel) in robots.iter_mut() {
*pos = calc_pos(*pos, *vel, width, height, 1);
if pos.0 < width / 2 && pos.1 < height / 2 {
q1 += 1;
} else if pos.0 > width / 2 && pos.1 < height / 2 {
q2 += 1;
} else if pos.0 < width / 2 && pos.1 > height / 2 {
q3 += 1;
} else if pos.0 > width / 2 && pos.1 > height / 2 {
q4 += 1;
}
}
let e = q1 * q2 * q3 * q4;
if min_e > e {
time = t;
min_e = e;
}
}
time + 1
}
fn main() {
println!("Hello, this is Patrick!");
let input = include_str!("../input.txt");
let result_1 = solve_1(input, 101, 103);
println!("The safety factor will be {}", result_1);
let result_2 = solve_2(input, 101, 103);
println!("The time that the easter egg occurs is {}s", result_2);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input, 11, 7), 12);
}
//#[test]
//fn test_2() {
// //let test_input = include_str!("../test.txt");
// //assert_eq!(solve_2(test_input), _);
//}
}

View File

@@ -0,0 +1,12 @@
p=0,4 v=3,-3
p=6,3 v=-1,-3
p=10,3 v=-1,2
p=2,0 v=2,-1
p=0,0 v=1,3
p=3,0 v=-2,-2
p=7,6 v=-1,-3
p=3,0 v=-1,-2
p=9,3 v=2,3
p=7,3 v=-1,2
p=2,4 v=2,-3
p=9,5 v=-3,-3

View File

@@ -0,0 +1,7 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"
[dependencies]
nom = "7.1.3"

View File

@@ -0,0 +1,71 @@
##################################################
#.#..OO.OO...O..OO..#.....O....#OO.#....#..OO....#
#O..O......O#...O.....#..OO..O....O...OO##O..O#..#
##.O.O...O.#.O...O#O...O.#O..#..#....#O.O.OOO...##
###...O...O.OO..OO....O.........OO..OO..#..O...#O#
#OOOOO...O.OO.O..OO.O.....O.O...OO..O#......O.O.##
#..#..#..##.OOO.#O..O....................O#.O..#.#
#.....O.O.O.OO..#.#.O...OOO.O.#.........O.#......#
#........#....O..O.OOO.OOO..O...O.O.OOO.O...O.O.O#
#..O..O........O..O#...O.O....#..O......O..O.#O..#
#O....O.O...O.........#...#.....OO....O......OOOO#
#..O.....OOO#O..O.O.#.............O.#OO....OO.O.O#
#...OO.....#....OO......O#..OOO....O.O..#OO......#
#....O#.......O....#.#.O..#.OO#O..O...OO..#O#O..O#
#..O..O.........O..#.OO.#O......OO.OO......O...#.#
#...............#...#.#...O#............O.......O#
#OO...O.OOOO#O.....O........OO.OOO.OO....OO#.#...#
#.O.#O..OO.OO..O..#..#..#..O...OOOO...........O#.#
#...OO......O...O..O...O.O.O#..OOO......O#..O....#
##..OO....OO.....#.O...O..OO.O.O..O##..O....#....#
#......O...O....#OO..#.OO.O.O.O.#.OO...O....OO.#.#
##.....#.OO.O.............#O......OOO#..........O#
#.........O...#OO.....#.....O..#.....OO.O.#O.....#
#.........#O...OO..O...#.OOO......O....O...O.O.#.#
#....O..#...OO.OOO......@..#..O.O..O.O.......#O.O#
#.OO.#O.O..#..O.......OO.....#.O.O...##O.......#.#
#..O....O.O.....#.O.OO..O...#OOO.O...OO.O..#.....#
#.#.O.OO.#...O.....#...O#.O..#O#O.OO............##
#....#.O....O..O...OO...........O.O.OO.O.OO..#.O.#
#O..O.O.O.OOO.O..O...#O.O..OOO.O#O...#.O...OO.O.O#
#OO....#.....O.O..#.#.O.O..........OO.#..O#......#
#..O......O#..O...##O.O..O.O.#...O.OO.O....O..O..#
#.#..O.O.....#O.O...OOOO....O#O.OO#....O......OOO#
##..#...OO###.O..O.OOO.O.O.........#..O..O.O..O..#
##...OOOOO.OOOO#..O##...O.....O.O..OO....OOO#....#
#....O.O..OO..#O..#...O........OOO.O.##.O.#.##..O#
#.....OO..OO..O...#.....O.......#..........O.#.#O#
##..#.....#.O...O#..O.....#.....#..#...OO....O...#
#.OO...O.OO..#O#...#...O.O.##..O..#O#.........O..#
#......O.O..O.OO.#.O.O..O...OOO....#.O.OO.O..O...#
#..#...O...O..OOO..............O.#...O..O....O.###
#........OOO...O..#.....OO...OO....O......#.OOO#O#
#.##.OO..O.....##.OO.OO.#.O.##..#..........OO....#
#..O.O..O.O.#.OOO...#....O..#..#.O.O....#.O..O..##
#O..O..O..O.O.............OOO.O..O..O..O..O.OO##.#
#...O#OO..OO...O.....O..#O.O...O...O.OO...OO.....#
#..O...#..#.O....#.....#.OOO#........O.....#.O...#
#.OO...OOOO.....#O......#.....O..O.O.O.#.........#
#.....O.O#.O..OO......O..O.O.O....##O#..O.#...#..#
##################################################
vvv>>><v^v<v>^<v>^^v<>v>^>^^>v<v^^^<^<<>v<^vvv<^<v^><><^^<v>^^^^^><<>v<vvv^>^^<^vv<>v^v<^<<^<<v^vvv>>><>v<>vv>^<><^^v^>^>^^^<^^^>^^<<<><v>vv^^<>><v^^<vv>^vv^v^<v^>>>>^v<^><vv<^<<<<>><^^^v^v<>v>^v^<^^>>^^>^<<^v<^<>v<>v<vv><^<^<^><>>><<<>>v>>>>v>v^<><<<><>^<>^<^v>><v^v>v<^^<<>vv^v^<v<<^v<v<^^vvv<^<^v<^<^^>v^>v^>vv<v>>>vv>>^>^v<v<>>><v<<^<>v<>v^^^v<>>v^<><<vv>vv^<^v^^>^vv<>^<^vvv<<<v<>^^><vv<<<>>^><>>>>^^^^^vv>><>^vv<>v><v>v^^^>>v<<><v^v<^<^^vv<<^v>>v^<v<^<<^><>vv<vvv^><><^v^v<^><>>>^^>^>^^<v<<^>>vv<<v^^><^<vv<vv<<vv<<><^^^<v<<^<<^>>>><<<>^<<vv>^<>vv^<<^>^<^<v^v>v^<<><>>v^<>vvv>^^<>^<v^<v>v^><v<^v>^vv<>^<^<>^<^><<<v^><v^>^>^^<^<v^^><<^v^^>>>v<>vv<<v<<<^><vv<>><>>^><vvv^vv>^<^vv>v<^^>^>>^>v^<<<>><^^vv>^^<^^>>^<<v>><>v^><^^v^^v>^<<>>v<v^v^><<><^>^>^<^<>^<<v>vvv^^^<<>>><v^<>^^><^v^>^<v>^>v><>><^>v^><^<><vv^<<<^><<>vv><^^><v<^v>v><<<><<>^><v^<<>^><v>^^v<>v>^^^<><><^v>>v><<^<v>>v^<^<>^^v>v>^>>>v><>^^>^^v>v^^v<v^>>vvvv^v^<^vv^>>^^<v<v><^^^><><v<>>v>v<v^>^vv<>>^^>^vvv>v^^v>>^<^>>^>v^>>v><vvvv^>v
v<^<><v^<v<vv<<v>v^<>^><vv<<<<v^>^>v<^^>v<v>v<>>^>>v<^^^v^^>v^><v>^^>>>^>v>>>v^><><<><v^v^vv^^^^v<<^>>v<^><<v^>v^>^^<v<<><^v<><v^^<vv^^<v^>^>>^v<v^v^<v^v<<^<^>v^<><<v><vvv^<^^^^<><><^^^vv^^>vv^>v<v^^<<^^<<<<<>^v^vv^vv^>>>vv<^<vv<^v<><^^>>v<<<<^^<v>>>v^><>^>>vv>>v<<><v>>v>>><<v^<v>>^<>v><^<<^<<<<v^^^vv<^>v<v<^><><<>^v^vv><v>^vv><<^v^v>vv^v<v>>v>^>v>>><<><><><v^<v>^<>^<>^v^v<>vv>>^<>><>^v^v<<^>v<<v<^>><>>^^v>v^vv><vv>^^>^v^>v>><<v><vvvv><>>>^<^v>v<<>>v^<<v>^<><v^v<><^^v<>^vv>^>v<^vvv<><>>vv>^^<v>^v<<v^^^<><>>>^<<>vv<><v><<>v<v>v>>^v>>v<vvv><<^>^^<^<>>>>v<^v^^^<<<<<^>^>>>^<^<^><vv<>^>^^v^><v^>>^<<^>^<v^^vv>v<>v><v^><>>>vvv><>v<vv^>>v<<><^<>>v>>><vv<>v>><vvvvv^><<<^><>>^^><v^<^^^v<^<^>^<v^<v^^^><^<v>v>^<<^<>^>v^<v>vvvv>v>>>v^vvvv>><>^>>><>vvv^<^<v>^^^>>^vv>>^v>>^>^^>^>>vv^^>><^<>>^^^^<^v><>^>^v>>><^vvv^vvvv<>^><^vv>>^^v<>^<<^v<^^<v>>v^<v>^><^><vv<<^<<<v^vv<<>v<v^^<><>^^>^v<<^<><v^v^><v>^><<v>^vv>^v^^v^><<vv>v><vvv><>^<>v>v>^<<^<<>vvv>>>><<>vv<^<><>^<^v><^<vvv^<>^^>>vv>v<>v>^^^vv<><<^>v<v^v
<>^<^^v<vv>^>>^<^>^<v^vv<v<<v<^>>v^^v>^^v>v<<<<^<<v^<v>>v>v^v<^^<><<^v>^^^<v^^><v>vv<^^^<>>^<><^v><>><><^>^<<<v<<v>v<<v^vv^v<v>^^>v<v>><>v<v<<^>v>^<<v><<>^^^>^v<vvv<^<>><<>>v<^<>^v<>v>v>v<<<><^<^<>^<^<v>^<v>>>^<v>>>v<^v<^^^^>^<v>^><^><<><v>^>vv^>^v<<>>>v^v<>^<v<><><><<><<>^>v<>><<>^v<^<<<^v^>v^^^^>>><<^v>>>^><^v^^<<^^v><>>v^^^>>v<>^>vv<vvv^>>>>v<v<v^<^<>>^v<vv>^>^v^vvv<<^^><v<^v^v<vv^v>><^^<^>vv<v^^v><>>v^>>v<<>v^^<<^>>><<><><<<>^v>><<vvv<v^v<^<>>>>><^<<^<^><v>v>v^>v^v><v>v<^<^>v>><>v^<<v<<><^>v<^>v<^<v^v<>v^v^v>vvv<<><<>><^>vv^<^^^^<>>^v>>v^v>>v<v<<<v<><v^<>>v>>^><^>^^><^^v<<<><^>^v^>><><^>v><<v^>>><>^^v<>^<^v>v><<><>^<><<<^v>^^><>>^>><^v^v>>^><>v>v<^>><<><v>v^>^>v^vv>vv<^v^^v><<vv>v>vvv>^><v>v<>v>^^^v^>>^>>v^^>^>vv>v><^<>><^v>v>>>^<v<^vvv<vv>^>>^<^>^<<>>v<<^^<v><<^<^<<vv>^<>>^<>v<>>^v>vv<>^v<v>^>>v>^v^>^^<><><vv<>^v<^><<vvv^<><><<>^<<^>>>vvvv^v^v^<^<v<vvv<v>^vv<<>v><>^><>^v>v>>v>^v>v>^^^v<v<^vv<><><vvvv>^><^v><>>>v^<^v^>^>>>>><><<<>vv><v^>^v^>v<>>>v^>vvv<>v^v<v<^><v<<v^vv^^><v^<v^<^v
>>>v<v^<<><^>>v^<>v<<^>>>^>><<<<>><v>><v<>>>v<>><vv^<>vvv>v<v>v^^<<^>^<<^>^v^^^<<>v>^<><^^<vv<>v<^>^<^^>^^^vv>>^<v<v>v^vv>^><v<^^v^v><<<^^v<v<v^><v^v>>v>^>v>vv>>>^^vv>^vv<^>^><v^v<>vv^<v^<<<><>vv>>vv>v>v^>>^vv^>v^<^>^><<>v>>><<>><v>^>>>^<<vvv>>^v<<<><>v^v^<vvv>vv<>^<<>^v><vv><v^>v>v^>^<<v<^<^<<v<<^^^<^v<vvv>^>v<<<v>vvv>^><<^<v<v>^>vv^<>v>^^^^<><^>^<<<<v<<^vv<<^v<>v<<<v^<^vv^><<vv<>vv^v>v><<>vv^><v>^vv<^v<^><^^v^^^^vvv<>><^<<<>>v>^^>^<^^^><<>><<^^^^vv^<<><<<v>^v^^v>vv><>v<>^<><^<<><><>^<v>v<>^vv^^<><<^<<<v<<<<>v><><>v<>>^v^^<^<><vv<>>><v<^v<^v<v^v<^^^^^<vv<<v^<<^<<vv<<vvv><^v^^<>^v<^<><><<v>v^^^v^>^<<v>>v>v^vvv^>>^>^<>>vvv><v<v><^^><v^<<v^^<<>v><<<v^<><^><^v^<<^<v<<<<v^<^^v^<>v>v><<v>^v<>>v<v^v^v^>^<v^^^>><^^^^v^<^^<<^<>^<v^><vvv><v<><><^^^v>v>><^<v<<>^^vv<vvv>>>>v<vv^<v>vv^^><<>^vv<^^<^<v>>vvvvv^v^>>vv<v>v<v<^v<>v^^<v^vv<v^>^^<<v^<<><^<<>v>v>^^<v>^^>v<>v<vvv<>v>v<v^>^<vv^<>>v^v<<^^v^>^<vv^v<<^vvv^^<>^v<><v<^<vv<>vvvv<v<^v>^>>><<v^v^<<^vv^v>^>vv^^>>>^>^<^>^v^^<><>^<<v<<^v<^<^v^<^^vv^^vv
>>v<^><<v^>>^<<^^v>^<<^<<v<vvvv<<^^<^v>^^<<<vv><v>^<^^^^v>v>^<^><^^<>^vv<v<>>v><^<vv>v<>^^^><>vvv<>vv>>vvv^>^><<<<<>^>v^>v^^<^<^><><<^<<><<^<>v>^>>v<^<^^<<^^<>>>>^v><><v^^^v^v>>>vv>v<^^v<^^>>>>^^^^<>^v>^^<^^>^^vvvv^v>v<<^v>^v<>^>^^v>^><>v>vv>^v>^^v^><<<^^>^v^v^v^v>^>^>v<^<^>>v^<<><v><^^^^>^>>>v<<v^^^<><^v<>v^>>>><^v<>>v><vv^>>>vv^<>>v>vv>^>^v>>^><>v<v<>v<^>>v<>^>^<<^v^>v<>><^^<^vv><^v<<<v^v^<^^^^v<^><<vv<<>^vvv<^v^v^^>^>^v^^v>^<><<vvv>v>^^^^><v<<vv>v^<v<^^vv<<v<^<<<<<^v<vv<v>^<<>>vv^v^><^^^^<v<v>^^^v^v^^vv<v^v^<^>>^^<<<^v>vvvvv<><<>^<v^<^v>vv^v^<v<v^>^^<v>>>>>v^<<>^><v<^^><<v^><>^^>>v>v^<>v^^>>>>><>v^v>^^v<<^<<<<><v^<<vv^>>v<<^<<v<v^>>^^<><v>v>>^vv<<<v<v><v^vvvv>vv^<v<<^vvv^^^^v>^<^>^<<><v<<^>>^><>^v<v>^<v><><<v<<<^<v^>^^v^v><v<<><v<vv^^<v<<^^>^<<^<vv<>v>^>^<<<^^^^>^<^^vv<<v<<vv>>>>v><<>>><vv><<>>>v><<v>^>><>v<v>v^^^<>^><^v><>v<><>v>>^^<<<>><^^<><^><>>v>vv^<v^>>>v<<<>v<^^<^^<v^><><>v^<v>^^>>v^>^>vv>^^^<vv>^v<<<v<^^^>v<^<<^^v^vv>^>^v<^v>^<vv>v^v^^^v<^v>^>v<<vv^<<^^^vv<<^>vv^<v^vv><<<v>>
<^>v^>>><<^v<^>>v^v>vv<^v^>>>^>^>v<>v>v<^^><<>^>^v<><^^v^>^>><^>^>v^<>^><<>>>^>>v><><<^^v<<^^>^>^v>vvv>>>vv>v<^^v^^v<vv<^>^<vv><v<vv^^<<><^<>v^vv>>^^vvv^<vv^<<><<<v^^<>v^^v<^<v^>>>^>^^v^^^^^<<vv><^<<v^v<v>>v>v<><^<<v<>>^>v><v>v<>vv<>vv<<^<v><>^^<>v><v<^>^^>^^vv<v^^<<<>>^^v<>^^>^vv<>v<>^v^v^v<>v<>^v^^^v<^<><v^v^>>^v<<<^>v>^^^v<>v<v^><^v>v<<>v^vv<>>><^<v^>v^<v^^v>^v^<<^<v><v^<^^>^>v<^>><>^^^vv<>^v<v^<^^<<>vv^><v>v<v<vv^v>>v<><<>^>^^>^<>v>>^^>v>>><<<^v^v<^^^v>>v>v<<>>^>><v^v<>^v<>v<><<<^>>v>vv^<v>^>><^v^><><>v>>^v>^>^<<v^v>v<vv^vvv^<^>v<^>^<v<vvv<^^<<<><v^><<>^>v^vv^^^v<vv<v^<>v^<^^<<><<v<<v^>^><>^<>>>^v<vvv<v<<<>vv<v>^>>v>>v>>^<v^vv<^^^<>>v<^^^vv<^>v<<><<<v^<^^^^<^>v<<>>>^<^vv>>>><>^<<<v<>v^<>^><v<<>>^>^^^<^vv<<<v<v^^>v>>v>^^>^<<<^<>^>><v^v<^<^>>^vv^<^^vv<v<vvv<^^^>^vv>>>^^v<v<^<<<^vv<><^><>><<<^<<>^<<>v<<^v><>^^^<<>v><^>^><><^^^<^vv<^>^<<^>>>>^^^<>v<v<v>><><>>^^vvv><^v<>^<v^^<^v<v<vvv^<<vv<<v<^v^v<v>^^vv>>>v<<<>vv<vv<v^>>^vv^v^><^<^<^<v><v><^<v<<v^^>><><<v><^><vv^^<<v><vv<><<^vvvv<v^vv>
><<<<>^>>>^><><<vv^<<<vv<v^<v<<><<^<v<^>>^><>^><<>><>^<v<><^<^^^^vv^>v^><>v^^<vv>>v<^<v^^^^^^>v>^>v<v>><><^vv>v>>>>v^v^^v<^^<v>v>>v^v><<>v>v^^><^<v<<><><<^>>^vv><<^v^vv^vv<<^vv>vv<^^v<^^vv<v^<<>v<>v^<^^v^<vvvv^v><vvv<vv^><vv<v>v>v<>^>>><v>v>>vv^^>vv<>>^<>^>^><v<>>>>><>>v><<>>^<<>vv^<>^^>><<^^^<><^<v<v>^<<<>v<v^v>v>^>vv>>^^vv^>><>><>v^v>><^^<>>^^>^^>^^^^vvv^>v>^>v><>>vv^><^^v<>v<v<vv><>>^^>>vv^^^v^^v^^<>v<^<v<v^^vv<vv^><^>v>>^<<^^><^<^vv<^><^^>^<^><v<^^^>>><^^<^^v<v>^>^vvv<<vv>^<^<>^v<<>^^v<^^^<><>>v^v^><>>vv^^^^^^<<^^^v^^^v><>v<vv>vv<^^^^<^v<v>^^^><v^<^v^v>^>><vv><v>vv>>^<>^^><<>>>^v<>>v^><^<^><^^><<v<v^>v<<<^^<v>>>vv<v^v^^^^^^^>>^^><^v^<vv<<<>^^v>v>v<vv^^<v^^^>^^^v<v>v^^>^v><>^>v>v^^v<><<>>>v>^^<v^>>vv^<^^^^<^^<>^^<^v>^><>v<>^^^<vv><<vvv^^<<^v>>vv<>vv<v^^>>^<v>><^<v>>^v^^<<v<>>^^>><v^^>vvv^v<^v<^^^v^^>v^><v^vv<>vvv<<^v>v<^>v><vvvv<^v>v<>>>^<><>^^^>^<<vv>^v>v<<<^<^>>v<<vv^>>^^<<>^^^>>>v>>^<^^^<<>v>vv<^v><<v>>v^^<<^<vv<<><^<<^^>^v><><>v^v>>^^>vv<v<vv<v<v>v<>vv>v^><^v<^>^^^><><<>^^v<v<v^
><^<<v^><<<<<<^>>^^<^^<^^^>^vvv>^<>^vv<><^vvv><vv^v<<v>>v^v>v>>v^vv^^^^^vv<><v>v<>v^vv>><^v^>^<>v<><v<<v^v<<^v<<<^<^vv>>>><^><^>>^>^<vvvv><<>>v<^<v>>^<>vv<>vvv^>>v^^>vvv<vvv^>>><v^<>^<><>v^v<^<v><>^^<^^vv<<>>^><>v<<>^<<>^^>>^>><^<v^>^<<>v^><vv^v<^^>^<>^>>^v^<<>>^<<<<^>><<^^^<^^<v^>v^^vv><<^^<>v<<v<^<^><^>><>v^>^v<^v>>>^>vvv<v^>vv^<><<>>v<^v>v<><v>>><<<^^<^<v^<v<<><vv<><v<^<vv>v^>^v^^<^^<>^<v<<<v^vv^^>v>^>^v<>^>v^<^^<>^^>vv^v^v<^v<v<<^>^>v<<>v^>v>><^v<>^<>><<^^v><>^^>>v^v><<<vv<^^<>v>^>>^^vv>^^>>v<<v<vvvv^^><v>^>>v>v^^^v><<v^vv><>><^<>^<>>v^v<^^v<vv<<^<<>v<>v>vv<>^>vv^>^v<<v<vv^<><>>^vv<^<v>>v<vv^^^^vv^^<^>>>>><^^<<^<<v>v>vv>><^v^v<^<vv>><>^^>v><^><^>>v^^>^^>>^^<v<<v>>v<<<><>>v^>vv>><<^<^v<^v<^<v<<>vv>v<<><v<^^^>^^<<v<v^>>><^v^>^>v<<>>>>^>>><v^^>v^>><>><v>>vv<>^>vv>v>>>^<v<^vv^><vv<^^vv^><>^<v><^>v<>><<v<<v^<v>v><^>v>>><<v^^<<^>>>^vv^>><^>>vv^v>^>^v>^<^v^>^<>v^>><<v<>^v^^><vvv>^><>>>^v<^<>v<>^<<><^>^>^v<^<v>v>>^<^^^v<<<^^<^v>^>^>^>^>^v^<^>^>^<v^><>^<v<^><>>v>^>v<<><<<v<^v>^<<^v<<<<^<<><
^<>^v^<^<><>^>><v<^<>^><<<>^v>v^^v><<>>^^^^v^^^>^^v>v^v^^>><<^<^v>^<>>^><v^>vv^vv^^v<vv<^>v>v<v>^>v>>v<>><v^>>v><^^<>^^<^^v<^>vvv^>^<>^^v>>^v>>>>v>vv<^^^^<>vv^><>^^vv<^<^>^<>^v>^vv><^^<^v><<>v^^v<vvvv<>v>>v<^^>^<<>^<>>><<>v>^><<^>^^v^<v<vv<><v><>>^<^v><v<>>><^>vvvvv^^v^>^^^>v<<<><<^^^<v>^<vv>>>^<<^<<<^<vv><^>^^><<<v<>v^^>vvv^v^^vv^>>><v<^vvvv>^<<<<>><v>v<v^<<^<^<<^^<^vv>^>>>^v^^>v^^vv>^^<^v^<v>^<vv>v^>^>><<v>^vvv>v<v<<>^<v>>><>^^<v^>^>^v>v<^>>^^>^>v^vv^>^<>^<^v^<^<v<v<>>><<><><>v^<>v^v^v><^^v^v^<vvv>^<>>v^<><<v^v^^v>v^^<><v^>v>^><^v<<<v<^v>v<^<>v><<><>v^<<v^<^v^v<<^><^<>v<v><^<^<vv^>^^>^vv^<^^<><v><^>^v>^><^v<>v<<<<<<^<<^v<^^><^<^<<>><<>^<v<<<<^>vvv>v^v<<>v<^<>><<><<^^<<v<><<vvv^<^^v>vv<v<vv<vv^<<><vv<<<><vvv>>v^^<vvv<v>vv^><><^>^>^<<v^vv>^>>vv^<v>><^<>>>^>^v^v^^^<^v<^^v^<^><v<v^^>v>>^^>vv>><^<>v><vv^^^^^^^><v^vv>v^v><^v<><v<<v>v<^^>vv<v<v>v^^^^^<>vv^v^<^>>v^^^vvv^>>v^<v<<<>v<>v<<^>>>v>v^v><>>^v^^^v<>>^><>><>vv<>^>>>v<>><>^<<>v<v<v^vv>v^^<><>v><<^<^vv<^v^>^><v^^^<>v<>^^>><<>><v>^v>vv^v
><v^v<v<^>>vvv<><>><^^vv>vv>><>><><>><>^vvv>>>><v>^^>^^^v>>><^<<v^v>><^^><^v<><v<^<<<>><<v<^v^v<^<v^<vv<^^^^^v<<vv><^>^>v>>>^<v^<<^<<^^^>>^v<>><^vv>v^^>v>^^<v^^><>v>>^v^><>>^>v<<>>^vv><v<^^v<<v<v><v^<><^>>v^v>^<<>>^v^^vv>>^<<<v>^>>vv><vv>>^>^^v^vvvvv>>>vv><>^<<v^^v^<>v^v>>^<v<<v>v<^>vv^>^>v>><^v^v>>^<v><>v>^><^<^<v^v>^^v^<><^<<<^v^^<><v<v<vv^v>v^^<^<v<v<^<><^v<<<>v^>v^<<>vv>>v^><^<^^vv^<^<<v^v<<^>^<^<^>v^^<v<><>><^^v>^<<<^v<>vvv^>vv>>>>v^vvvv^^<^^^v^<<v<v<><<v<vv^<v<v<>v<v<v^^v^vv><<^<<>>v<>^<>vv>^^vvv^>>>v>>>v^v>vvv<>v<<^^v><<<><<>>v>vv<<v<^^vvv<<<v^v<vv<vv>>vvv>>^v<>>^vvv><v^<>^<v><<^<v<>v<<v<^>>v<>v^^^<>vv^>><^><^>v<^^<>^>v>>>><vv^<>^^^v<^^<^<>v<v>v<v^<v<^v<^v<><><v<><<><>^>>>>^>v<^^vv^><v<v^>^<^^>>>^<v^^vv<<<^^>^^^>>^<^<>^v<<><vv^<^^^^v^<v<><^<v<vv<>^v><<^<<^v><>><^<>v><^<>^<^v^<>^^>^v^^^^>^<<vvv<^<<v>^^<^>^<<>v<<v<v>>>>^>v>><v<v<>^<<^v><<>v^^v^>v^^<^v^^><v<<v<vv^<v^<<<^v>>^<vv>>v^v^v^^<^v>><><><>v>>vvv>^<<><^>vv<^v>^<>><><<^>^>><<<<^^^vv><v<>v>>^<vvv>>^v><>^^^v>v><<>v<v>v>^v^^v>^v
>v<^^>>^^<v<><><<>^<>>>v^^^<><^v<v^v>><>>^<^<><v^^vv^<<<>>><>>vv^>^vv^<^vv><v^>><^^v^vvvv^v<^v^^<^>>v^<vvv><>^v<v^<<<>v<<<>^v<v>v^>^^v>><<>^v^<vv>><<<vv^v>^^v<<^<<^<>^vvvv<>v^>^>vv<v>^vvv<<^><<^><<v^^^v^<>><^>>><^^><v>^v^v<^<>v^^<^vv<^^>vvv<v<^^v^<>v<>v<<^>>>><v^vvv>^>v<<<v<<>v>>v<^<<>^v<v^<vv<^v><v>>^>>><v>><<<>>^<<<>vv<<<>^>><>^<^>><<>^<vv>^><>>v<^<^<>^><<>^v^<^vv<<>v^>>>^>>^>^v>^<^>v>>^^v>v>>>^v^^^><^<^v^>vvv>v<v^<vvv><<^>^>><<>^^^>v>^<>v<><v<v<^<^^v>><vv>v^^v^>>^v<^^vv><><v^<v<<^v>vv><<><<<v^<v<^><v<^vv>v^>vv^<v^<^<vv^^<v^><^>^^><<v><<^^<>v^<<v^>v^<^><v^v>>><>v><v>>>v><<vv^v>v^>^<>^<vv<>vv>v>v><v^>>^>v^<vv^<>^><<>>>>>><vvv><><v<^>><<<^<^^<<v^><>^vv^>>vv>vv<>>><<^^<><<^<^>vv<><^>vv^^v>v^^v^^v<^^<v<vv^<v>v^^>><<^<v><<<>><<>v<>>^>>>^^^>v<<>v><>><^>>v>vvv>v<>><>>v>^<><>>v^>><>>vv<^>^>>>^>^><vv^<^>v<^vvv><><v<<<>>^<<^>^^^^vv><^><^>><>^<^<>><>^^v^^<v>>>>^vv^vv>^<^vv<<v><>>^<<>^^^v<><<^^>>v>vvv><^>>^^<<>>v<>v^<^>>><v<v^^<<><><>^v><<<>v^vv<>^<v^><v>^><^^>^^<>^>^<^^v><^v<v<<>^<<^>^^v<<<v<<v
v<<<>v^<<v><v^v^^<vv<v>^v<<^<^v><^v<>^^v><v^^>^<vv<^v<v>>>>^v<<vv><>><^^vv^><<<^<<^v>v><><>vv>^<^vvv<^v>^<v<v<<<>>><>>^vvv<v^^<>v^<>v^><<<>><<<<^^><<v^vv^v^v<vv^^v<><<v<<^^<v^^><><^v^>>vv>vv>v^^^vv<>>v<vv>v<>><<^^^<vv^>v^><v<<v<<vv^<<>>>vv<><^^>^>vv^^><vvv^<><^<>>^><v<<<^>v^<><^^>vv<<vv<vv<^^^vvv^>><><<v>^vv>v<<^>vv^^>^v>v>v>v>v<>>vv<<>>^><<v>><<>^<vv^<>vvv<>^v>^^v<^v<v><<v^<^>v>^^v<<>^v<>>vv<^^^<^<><<v^<^>vv^^v^>>vv>^^>vv>^>vv^>^^v^>v<<^>vv>v>^<^<v><<v>>>v><^<<^^<>^v^><^<<v<v<vv^v^^^>v^v<<<v<v>^^<><^>^>>>v<v<^<><<v>^v^><<^<v>^<v>^v^<<^><v>v^<>^vv><vv^^^<^><<<vvv<>v>v<<><v>^vv<v<^<>>>^^v^^v<<^v>v>>^>^<v^>vv^v>v>^<>>v><v>>>><^v<v^>v<<vv^<v>>><>^<<>><<<>><>>>^^>^<vv>>v<>v^v^^<<><^^><v^vv>v<vvv^<v^>^v>v>v>^>^v><^<v<><>>v<^>^>>>v^>v><v^<>v>^><v<^^>^<^>>>>^^^^<>^<>>^v^<>v<v^v<<^v^^^v<v<><^^><<^^vv<>^vv<vv<>><><^<^^><^><v<<^>>><>^^>v<<<>^vv<>^>v>>^^><v>^<^>>v<<<vv><v^<^^<<><^<>^v^<vv^<<^^<^v^>^<^^^<^><>><>>^<>^<^vv<^vv^^>v><^>v><^>><^<^v><v<<^^^^v<vv<^>^v><<^<>>^<vv<vvv^v^vv^<vv>>>v<<<>v<^v>
^^<<v<^>^v^>>v>v>><v<>^><>vv>v<<^^^<>^><vv^v>>v><<^>^<<^^>vvv<v>^>v>^^vv<^v<v<v^<<<<vvv>v^^<<^><v><^v><vv^vv<^^^>>>v^^vv^><<>>v^<vvv<<<^^>^<>>>^<>^<><>><<><^v^vv^^><^^<>>^<vvv<^^>>vv^>^^<vvv^<^><^^^vv>>>>v^<^<^<>^<^>>^v^^>v^^^v<>><^>^<>^>v^v>vvv^>^<^^>v>^>>v^<^<<>v>vv<v^^>v<^^vvv<>vv^^v^<<>^v>>^<^<v<>^^><>^^v><>v^^^<^>vv<<>vvvv^^><><v>^<>^>>^<v^v<>^>^v>>^^v<><>v^<<><<<v<vv^<>v>>^v><>>v^v<^v<^v<v<>vv^v<^vvvv<^><^v^<>^>^^>v><^^^vv><<^^>v^<^>><>v>v>v^^vv<^<^^<^<v<v<<vvvv^<><<<<<^<>^><>^^><^^v^v>v^><^v^>^<^><^vv><>^vv<><^^^^v^>^><><><><><^v^v<<<>^<<^v>><<<>>>^^<<vv^v><v^<<^>v^v>^<^^<<>vvv<>><<>v><<^><vv<^><v>^>>>^^<>v>v>^>><^>v>v<^<>v<v<><vvv^v>><^^^<>v<>^vv><v><<v^vv<^<v<v^<<vv<^v^v<<^v<v>v<>^^v>v>^^<<<^<><v><vvvvv<>vv>><v<v^<>^>^^>><>^^^<^>^<>^>^<<>v>v>^^vvv^<>v<^><^^^>v<<^>>^^<<^^<v><vv<v>vvvv>v<<<<>v>^^^^<<<v^>v^^>><^><^^>^v^>v<<^<v^><><>>^^^^>^^^^v^^<<^^><<><v<<v<v^v^><><^<^^<>^<v<^<^^^v<>>^><v^vv>><^v<<<>^>^vv^>v>><^v>^<>^^^^<v<>v>>^<vv<^>v<v>v<>>><>^<<<<<<^v<>^>><^^>><v^>>><<v<^^><<
^^v>>v^<^<vv^^^><^>v^>><<<<>^^^vv<>v<^v^v<<<v>>>vv^<^vv<^v^^<<v>^^<^v^><>v<>^^vv><^<^v>>vvv<^>v>^><<v>^<>^^>v>>>>^>v^v<v<>>v^v<v^^<<><><>v<>v<^^<<^v>v^<v><vvvv>>v<^v^v<<v^<<><<><^><^vv^v<>>v^>v^^v><^v^>^<<v>^>>vv<vv^<><^^^v^>^^^v^^^<<v<>v>^>^<>^v^><^v^>^^<<>^v<v<^v^v^>>><vvv<^v^>^^^v^<<^^v>^v^^^>>v^<v^vv><>v<v^>^v<<<<v^<^<v>vv>><^^v^v<<^^v<vv><>>v<^<>vv>>^<<v<v^><v^^v>>>^>^>v^>vvv>^^<^>>^<^v<<><v^<v^>^>^^vvvv>^v^<vv>>v>v<^v^<^<^vvv^<>v>^vvvv>>^>^<>v<<<^^^<^>v>^^<^>>v<v<<v<^>^><v<v^<^^v<v<^^<>vv>v<<<vv^vv<^><<><<^^v<^<>>v<<^^<<<><v>v>><^<>>^>>v^><vv<v<>v^v^>^<^vv<^<^>v^^>^^vv<>^vvv>><<^v>>>>vvvvv^^>>^^><vv>>>v^v<><^<>v<vv>^>vvv<<<<>>>^<<>vvvv<v<^<vv^>vv<>vv<v>>v^>^^>^v<>>>><>^v<v<>^<v<^^<>><><<vv<<<<^><<>><v^vv<<v<v><<<v^<<^^>^^^<<<>v^v><v<<<>vv<v>^<v<v<<v>><^<^vv>>^^<vv^^<>v<^^<>>vv<>^^^v>v^<<<><vv>v>vv<<^<<^<><v<^v^><>vv^<<^>^^^<^^<v^^>v><>^<<v^<^<<<<<<v><^>>v<<v>>^^^>>^<<v<vvvv^<v<v>v>v>vv<<v<<v^v>vv>v><><^^^v<^^>^vv<<v^<^<vvv<^<>v>^v>>vvv><>>>v<<>>>>^^<vv^>>>^v^>>v^^>><<^^v^>^<><^<v
v<>^v^<^>^>v<v>v>>>v^<v>>>v><vvv^><^>^vv^>>v<^<v><v^>>>>v^v^>^^^<>^>^^vvv>v<<^vv>^<>vv<<><><^>>^^^<^^^v<^>^v^^^^>v<><<<>>>vv^^<v>^<^^^>vv<<vv<><>v^<><v^>^<v<>^<<<^<v^^v<<^<vv<><v>v^<<><^^vv<<<<<^<>^>>v<<<vv^<^^v>v^<<v<^v>><^^^>^<^^<<v>><^^vv^^v>^>>>vvvv>vv^^^<>^^v>>vvvvv>><><v<>^v^>vvv>^><^><^^v>v>v<<v>v^<<^v<v<<>>v>><v>^v^<<^vvv^<><>v^><v^<v>^>^vvv^v^^^vv^>^<<<v<v^^^>><^^^<^><<><^>^^v<v<vvv^^v^v>^><v>>><>^^v<<vv><v>>>>>>v>>>^<><v<>v>^vv<vv><^^v>vv>>^><<^^v>^>vv<>v^^<^>>v><<>>^<><><>v>^<v<>>v>>v<<^v>>>><v<>>>v><<><v><^<<><><v^^v^>^v>^>^^v^>v<v>^^>^><^vv^<v<><<v>^<<^^>>^><^^<<v^<^^^<>>>v^^v^^v<vvv<<<^^v^>^>>^<<^^vv<<^<v<<^^v>v<v<<^<<vv>>>vv><^vvv<>^>><>>><>v<vv>>v>><>vvv<^><vvv<v<>^v^>^^vv>^<<<^^vv>v<v<v^<^v^<^v>v^>vv><v^<^^><^^<>^v^<^<><<^>>v>vv<<^^^v^^v>v^v<>^v>>>>>^^^><v^^^^^^vv^vv<<>^<<<<<>^^<v<^v<>^vvv^>v^<<>^<>^v^>^<v^^v<^v<<^<>v><vv<<>>v>>v<vv>><v^v^<><<vv<>>>>>v^>^<<>>><^v^>>>v><>v^>^>^^^>vv><v<v^^v^<><><^v>>^^<vv<<>><>>vv<<>v<>v^^>^<v^<<v<<^^^v>>^^^<><^v<<^><^>><>^v^<<>^<<><vv^
vv<<^v<>vv^>v^<<<v<v<><<^vv^>v>^<<<>>>vv^><<<v^^^vv><^^><^^<^<v>>>>v<^v<>^<>v^v^vv<^vv^^^<<v<<^v^^^>vv>>v<^>v>^v^>v^^v^^v><><^<<^^^>vv>^<v>^v<vvv^v>v^^<vv<^v>>v^v<>v>vvv^v<>><^<^^<>vv<>>^^<^^^^<>>^>vv>^vv>vv<v^v^v>v>>^>^v^>v<^^<<^>><<<v<v^<^^v><<vv<>^>^<v^^<v<^<>v^v<^>>vv>^>^vv^^vv^<^v<v><v^^<^<>^<>v>>>^v><v><v<v<^<^>^<vv^><^^>>>>>vv^>v^<>><v<>><><^^>>^>^^v^<>><>vvvvv<^><>^vv>>^>>v^v^^<^<v>>^vvv><<<^<<>v>>v<<<<<^>v^^^v<>^v<v>>><v<<^vv<^>>>>>^>>^^^<^<<<v<<^>>vvv>v<v>^^^^><^^^v>vv<v^v^^<v>^^<>^>v<>v<><^v>^^<^<<^^>>>vvv^>v^<v^^<<v^v>^v>><v^<>^v<^^>^<>^<>^v<<>^^v>^v^^v^v>^>>vvv^>><v<^>^^><><^^>>^<^<^vv>>vv><^<<vvvv^^^vv^>><v^^v<^>^v<>v><vvvv^<^^<<>v>><v>><<<v<v>>^>v<>>v^<<<^v<v>v<^v>>>v>v>>>v^v>^^v>^^v^<<<<<>v^<v>>^>vv><^>v<^>>>>>^>v>><vvv<v>>>>v<v^^<^^^><v<v^^v<v^v<^<>^>^^>>v>^^v>>>^<v<<>^<>><v>^<^v<><>^v<^<><<<^v^v^^<<^<>>>><>>^<^v<><vv>>>^>vv>^^^v^>>v>><<<>^vvv^v^v>vv<<<^<<^>><>^v>>^v>^>vv^^v><^^vv^^<>>^v>^^<<^v<v^<><v<><^><<v>><<v<v<^<<<<v^<<v>>v>^<^^<^><^^vv^<<<><>v>>^v^<>^>vvv>>vv<<v
><v<vv>>><<<^v^>>v>vv><><^><v^^>v^<<<vvv^<>^v^^^^<^<>vvv^<vv>^^>^^v^v^>^>^v<v<>><<>^v^^v><v<><vv<v^>v>>>v^^>^<>v>v>^vv<<>vvvv^v>^<>^<^^vvvvv>>>v>^^^<>>v<^>vvv<<v><v>^v^vvv<>v<>^v^v>v^^<v^v^v^<^v>vvv^vv^^^<>>^^<^>vvvvv<<^^v>^>v<^^vv^>>>^v^^<v^<>^>>>>>^<vv<<<><v><v>>^v>^vv^<<<<>v>vv<<^<^>>>vv><v^<v^v<<<^>v>^<<><v^vvv><<^vv>^^>>>v>><^^><v<v>v>v>^>v^>>v^v>^<><<^<<<>>^>v<^<v<<^><<v<v>><vv^<>>vv><^>^v<v^<<>>v<vv>^><<^<>v><^<>^<<^^<<<^v^>^^><vv^^^>^><^^^^<vv>v^^v><<v>>vv^>><v^v^^>v^<v^^>^^>^^^^<<^>^vvv<^>v^^>>>>><<>v>v^v><^>><v<vvv^<^>^^^>v^<<^<^^<>><^^v<><<<>^><<>v^<<^^>^v>v<<<<<>><^^^^>v>><^v>v>>^>^v^v>^vv>^vv<<<^><v<^v>^v<^<><^><^>^><<vv>>>^^^^vv><<v><^^v<v^v^>^<>v>^^^<v<v>><^^^>v^^<>><^<<>>^>>v>^v>>vv^^v>v<v><v^^>><vv>^^<<^vvv^v<^vvv><v><v<><<><<<^<v^^<v<^>vvv>v<<<<^>>^^<vv<>>^v^vv<^v><<>><vv^^><vv>vv><v^v^vvv>^v^v>><vv^<>v^vv>v><v>^^v<^^^<^<vv^vv<vv>v<>v<>v^><vv^^vv>^v>v<^^>>>v><>><^^>^^><^^<>>><^v^>v<vv><<v<<^v<^v><^^^>^v<>v>^v^><vvvv^v<>>><<<v>vv^^<^v>>^<<>v>>>>^>v<^<^^^vvvv>^<<<<^>^<>
v<^vvv>vv<^v<v^^v<vvv>^^>^<v<^vv><>v<>vv^>^^><^^<<<^<>v><v<>><^<>^v^<><><<<><<v<<>vv><<<vv^vv^>><v^<^<^>><v><<<v<<v^<^<vv<<v^^v^vv>^v<^^v<<^>>^<>^<<^>v>>v^>><<^>vv^v<vvv>v^<^^^^<<^^^>><>v^^v><vv^^v<^>^v^v>v^^^v>v^>>^>v^^^>^>vv^vv^<><^vv^^<^v>v>v>^^^v<v^>vv><>v>v<<v^^>^<v^<>>v>>><><^<<v^v>^^<><v^v<<v<^<<^<<vv<^^v<v<vv>>>^v^^^v<^^>^>>>^v^<v^>>>>^>>v<>^^<<<vvvv^><<^^^<><<<><><>>^v<>^>>^^><<><<v<<<^v^v^^^<<<<>v>v>><<><v<v>>^vv^>v<<<<^><v>^<<v>v<<v<^>^<^^><<>^v^>>vvv<<>><<vv>^v^^^^<^^><>v^<^>>>^v^<^<v<vvvv^>v<v^v<v>^v^v>v<<^^v^<<<v^><v>>v><^<vv>>v<>^vvv<<<<v^^>vv>^>>^<<^<<>v>^^vv<^<vvv^^<^v<v^<>>v<>><<>>><<v^<<^^v>><^<<^v><^<^^^<^>>>>v>>^<<<vv><v<vv^<><<>^vvvv>v>v>>v><^v^>v>v>^v>vv^<<vvvvv^<>^^<v><^vv<v>^>v><<v>>^>^vv<<<^<^>vv^<<><><>v^><vv><<>v^v>v>>v^^^<<v<^>v>v^^<<v<>>^>>^<v<v^v<>>>>>^<>^v<<><v<<^>^^^^<^v^^^<>>^^><v>>>v<><<<^<^<v<^>^vvv<^^><^v>^^vv<<^<<<^v^^>v<<vv^<v>v>><^v>vvv<v>>^>v<>>><<><<><<>v><v^^><><<<^<^<>>v^>>^v<>vvvv^<vv>>v<vv^v^v^^><<v^<<>^>v^v<<>v^v<v<<^<>><<>>><<^vv<<v>v^<^v
^<^^^<><^^v<v><<^<<^<<>>v^<<vv<<^^><>^^^<>><>>>^<vvvvv^<>v<v^^>><vvv^<>v^>^<><v^^>>^><>>^v>^vvv^^vv<v>>v^<v<vvv>v<>^>>vv^^>v<vv<<<>v^^^<<>>>>v<<^v^^^>^<^^><>><<vv<<><>>v^vv>^><<><^^>><vv^>>>^<^v^<<<>^^v<>vv>>><^^^<v>v<>><<vv<>v^>v>>v<>^^><>^>v<^>^vvv^>^>^vv<^>^>^v^>v<<v<<^^^>>>>v>>v<<<<^<^<v><><vv^>>><>vv<<v^v><<^^v<^<>^v^v^>vv^>v^vvv><<v^<<^^v<<^^<<><vvv^<>vv>v<<vvv>^<v^v<>v>^^vvv><^v<<v^>><^vv^^^^v>>>>v<<>>>v^>^^<<>^^v^<^<^vv^>>><v^>>>^v^>v^^<^>vvv<>^^v^<v<<v^><>^^<><>^^>^^vv<><^>v^<><^vv^v>^>v<>v^^v<^>v><<v<<<<v^^^><vvvv^<v<>^v>^^v<<^<vv^v^<<<vv>v^v<^v^^<<^>>v^v>^v^>^<<^>v<<><^<^^vv>^v<vvv>v^^<^>^<^<^vv^^v>^<^^v<><^<^^vv<v^v<<vvvvv^v><v<<^^vvv^v^^>><>vv><<<><^>^v<>vv>vv^>^v><v<v<v<><v<<^<>^>>vv^v><^>>v><>^^v>^<<><vv>^<^v><>>>^<vv>^^vv^>><>>v<<><>vvv>^^v><^<>>>^>v><^>><^v>^<<v<^vv>^v^<^v<<v<v^>>v^v<^^v<^<v>>>>^v^>v^>^>>v<^^><<><><^>^>>^>^^^^^v^^<vv^>v^<>vvv^><v>^<><vv><>v<<><vv>v^<>v<^^^vv<v^<>>>>^vv>v<<>v<>^>>>v>^v>>^<<<><^vv^>>>>v<^v<^>v>><<v<<vv<<>^<><<>^v^<>vvv>vv<><v>>v^><<<<v^>
>vv>v<^vv^^v>v>^^^<>vvv<^<>vv^^vvv>>v^<><^v<^v>>>>>^<<v<^^^><vv>^<^>v^^>v<>>>v^v>^^v^>^v<v>v<><>^^<^^^^>^^<<><^<>^^>v><^v>v^>vvv>>^>v><^<<>^v<v<>^^vv><^^<v<^v>>>^v>>>^<>v^^><v^<^<<<<<v^<^vvvv<v<v<<v><v>^<vv<<<v>>v^^<>v>^<>>^>v^<^<^^v^^<<v<^>^vvv>^<^v^<^<<vv<v^>>v<<vvv>>><v<v<vv^v><><>>>v><v><v<<^^>^<><><><>^<^<^^<<<v<v>>^vv^>>>v^>^vv^>^>^<v>><^v<><><>>>>v<^v^>vvv>v^<^^^>v^<^<^v<v^v<^<v<v>>>>v^v>>>^>vv^><^^>vv<^^<v>>^>^^<vv<^<vvv^v>vv^<><>>vvv><vv^<^vvv><^^>>v^^^<>v^^<<>v>>^<^v<>^>>vv<^vv>^^>>v^v^<<^^>^<<^^^<>v^^^^^<^^v<>^^><<><^^<^^>><^>>>>vv<v<v^<><>>^<vv><<vv>vvv^^vv^<><v<>^<v^vv><^vv>v<>>^>^<v<>v<>^<>^><^<^>vvv^^^<>v<>^v^v<^^^vv<><^<v>v^<^^<v>^<<<<>>^><<^v>vv<<^v<v<>v^v>vv<^v>^<<^^>vvv<>v^><^^>^^<<<<^vv<v<<^^<^<<v^>>v<^v>vv<><^v^vv^<<>^<>>>^>>>^><<v><^<><><^<^<>>v<^>v<^><<v<v^><><v^v^<v^vv^v<v><<<>^^><vv^^v>^vv>^>v^<v>><<<<^>^^<<^v<<<^>vv><<<>^^<^^^<v<>>v^>^>v<>v<^><<<v>^>^^>v^^<vvv<>^>vv>v<>^>>^v<^<><<>>>v^v<><<vv^><^<>>><vvv<vv<v>vv^><^<^>>^<>><<<^<^vv^<<^>v^<<><>>^>>v><<^>><^v<>^

View File

@@ -0,0 +1,392 @@
use std::collections::HashSet;
use nom::{
branch::alt,
character::complete::{char, multispace1},
multi::{many1, separated_list1},
sequence::separated_pair,
IResult, Parser,
};
#[derive(Debug, Clone, PartialEq, Eq)]
enum Tile {
Empty,
Wall,
Box,
Player,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum UpgradedTile {
Empty,
Wall,
Player,
LeftBox,
RightBox,
}
#[derive(Debug, Clone, PartialEq, Eq)]
enum Move {
Up,
Right,
Down,
Left,
}
fn parse(input: &str) -> IResult<&str, (Vec<Vec<Tile>>, Vec<Move>)> {
let (input, result) = separated_pair(
separated_list1(
multispace1,
many1(alt((char('#'), char('.'), char('@'), char('O'))).map(|c| {
use Tile::*;
match c {
'#' => Wall,
'.' => Empty,
'@' => Player,
'O' => Box,
_ => unreachable!(),
}
})),
),
multispace1,
separated_list1(
multispace1,
many1(alt((char('^'), char('>'), char('<'), char('v'))).map(|c| {
use Move::*;
match c {
'^' => Up,
'>' => Right,
'<' => Left,
'v' => Down,
_ => unreachable!(),
}
})),
)
.map(|x| x.into_iter().flatten().collect()),
)(input)?;
Ok((input, result))
}
fn calc_score(map: &Vec<Vec<Tile>>) -> u64 {
let mut score = 0;
for (j, row) in map.iter().enumerate() {
for (i, t) in row.iter().enumerate() {
if *t == Tile::Box {
score += 100 * j + i;
}
}
}
score as u64
}
fn calc_upgraded_score(map: &Vec<Vec<UpgradedTile>>) -> u64 {
let mut score = 0;
for (j, row) in map.iter().enumerate() {
for (i, t) in row.iter().enumerate() {
if *t == UpgradedTile::LeftBox {
score += 100 * j + i;
}
}
}
score as u64
}
fn move_one(coord: &(usize, usize), m: &Move) -> (usize, usize) {
use Move::*;
let (x, y) = *coord;
match m {
Up => (x, y - 1),
Right => (x + 1, y),
Down => (x, y + 1),
Left => (x - 1, y),
}
}
fn move_player(map: &mut Vec<Vec<Tile>>, pos: &mut (usize, usize), m: Move) {
use Tile::*;
let (x, y) = *pos;
assert_eq!(map[y][x], Player);
let (tx, ty) = move_one(&pos, &m);
match map[ty][tx] {
Empty => {
map[y][x] = Empty;
map[ty][tx] = Player;
*pos = (tx, ty);
}
Wall => {}
Box => {
let (mut bx, mut by) = (tx, ty);
while map[by][bx] == Box {
(bx, by) = move_one(&(bx, by), &m);
}
match map[by][bx] {
Empty => {
map[by][bx] = Box;
map[ty][tx] = Player;
map[y][x] = Empty;
*pos = (tx, ty);
}
Wall => {}
Box => unreachable!(),
Player => unreachable!(),
}
}
Player => unreachable!(),
}
}
fn solve_1(input: &str) -> u64 {
use Tile::Player;
let (_, (mut map, moves)) = parse(input).unwrap();
let (mut x, mut y) = (0, 0);
for (j, row) in map.iter().enumerate() {
let mut found = false;
for (i, t) in row.iter().enumerate() {
if *t == Player {
x = i;
y = j;
found = true;
break;
}
}
if found {
break;
}
}
let mut pos = (x, y);
for m in moves {
move_player(&mut map, &mut pos, m);
}
calc_score(&map)
}
fn upgrade_map(map: &Vec<Vec<Tile>>) -> Vec<Vec<UpgradedTile>> {
let mut new_map = vec![];
for row in map {
let mut new_row = vec![];
for t in row {
match t {
Tile::Empty => {
new_row.push(UpgradedTile::Empty);
new_row.push(UpgradedTile::Empty);
}
Tile::Wall => {
new_row.push(UpgradedTile::Wall);
new_row.push(UpgradedTile::Wall);
}
Tile::Box => {
new_row.push(UpgradedTile::LeftBox);
new_row.push(UpgradedTile::RightBox);
}
Tile::Player => {
new_row.push(UpgradedTile::Player);
new_row.push(UpgradedTile::Empty);
}
}
}
new_map.push(new_row);
}
new_map
}
fn rev_move(m: &Move) -> Move {
use Move::*;
match m {
Up => Down,
Right => Left,
Down => Up,
Left => Right,
}
}
fn upgraded_move_player(map: &mut Vec<Vec<UpgradedTile>>, pos: &mut (usize, usize), m: Move) {
use Move::*;
use UpgradedTile::*;
let (x, y) = *pos;
assert_eq!(map[y][x], Player);
let (tx, ty) = move_one(&pos, &m);
// These are all the tiles that need to be checked yet
let mut stack = vec![];
// These are all the tiles we have checked, in order to shift them if needed
let mut visited = HashSet::new();
match map[ty][tx] {
Empty => {}
Wall => return,
Player => unreachable!(),
LeftBox => {
if m == Up || m == Down {
stack.push((tx, ty));
stack.push((tx + 1, ty));
visited.insert(((tx, ty), LeftBox));
visited.insert(((tx + 1, ty), RightBox));
} else if m == Right {
let (mut bx, mut by) = (tx, ty);
while map[by][bx] == LeftBox || map[by][bx] == RightBox {
visited.insert(((bx, by), map[by][bx].clone()));
(bx, by) = move_one(&(bx, by), &m);
}
match map[by][bx] {
Empty => {}
Wall => return,
_ => unreachable!(),
}
} else {
unreachable!();
}
}
RightBox => {
if m == Up || m == Down {
stack.push((tx, ty));
stack.push((tx - 1, ty));
visited.insert(((tx, ty), RightBox));
visited.insert(((tx - 1, ty), LeftBox));
} else if m == Left {
let (mut bx, mut by) = (tx, ty);
while map[by][bx] == LeftBox || map[by][bx] == RightBox {
visited.insert(((bx, by), map[by][bx].clone()));
(bx, by) = move_one(&(bx, by), &m);
}
match map[by][bx] {
Empty => {}
Wall => return,
_ => unreachable!(),
}
} else {
unreachable!();
}
}
}
while !stack.is_empty() {
let (sx, sy) = stack.pop().unwrap_or_default();
let (bx, by) = move_one(&(sx, sy), &m);
match map[by][bx] {
Empty => {}
Wall => return,
Player => unreachable!(),
LeftBox => {
if visited.insert(((bx, by), LeftBox)) {
stack.push((bx, by));
}
if visited.insert(((bx + 1, by), RightBox)) {
stack.push((bx + 1, by));
}
}
RightBox => {
if visited.insert(((bx, by), RightBox)) {
stack.push((bx, by));
}
if visited.insert(((bx - 1, by), LeftBox)) {
stack.push((bx - 1, by));
}
}
}
}
let old_map = map.clone();
// Because of early returns in case of wall and empty and the empty stack in the case of a
// horizontal move, we can always assume we hit a box somewhere along the way and we have
// to move all those boxes here
for ((vx, vy), vt) in visited.iter() {
let (px, py) = move_one(&(*vx, *vy), &rev_move(&m));
if !visited.contains(&((px, py), old_map[py][px].clone())) {
map[*vy][*vx] = Empty;
}
let (nx, ny) = move_one(&(*vx, *vy), &m);
map[ny][nx] = vt.clone();
}
map[y][x] = Empty;
map[ty][tx] = Player;
*pos = (tx, ty);
}
fn solve_2(input: &str) -> u64 {
use UpgradedTile::Player;
let (_, (map, moves)) = parse(input).unwrap();
let mut map = upgrade_map(&map);
let (mut x, mut y) = (0, 0);
for (j, row) in map.iter().enumerate() {
let mut found = false;
for (i, t) in row.iter().enumerate() {
if *t == Player {
x = i;
y = j;
found = true;
break;
}
}
if found {
break;
}
}
let mut pos = (x, y);
for m in moves {
upgraded_move_player(&mut map, &mut pos, m);
}
calc_upgraded_score(&map)
}
fn main() {
println!("Hello, this is Patrick!");
let input = include_str!("../input.txt");
let result_1 = solve_1(input);
println!("The sum of all boxes' GPS coordinates is {}", result_1);
let result_2 = solve_2(input);
println!("The sum of all big boxes' GPS coordinates is {}", result_2);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), 10092);
}
#[test]
fn test_2() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_2(test_input), 9021);
}
}

View File

@@ -0,0 +1,21 @@
##########
#..O..O.O#
#......O.#
#.OO..O.O#
#..O@..O.#
#O#..O...#
#O..O..O.#
#.OO.O.OO#
#....O...#
##########
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^

Some files were not shown because too many files have changed in this diff Show More