diff --git a/2023/data/12/example1.txt b/2023/data/12/example1.txt new file mode 100644 index 0000000..2b6db3e --- /dev/null +++ b/2023/data/12/example1.txt @@ -0,0 +1 @@ +.??..??...?##. 1,1,3 \ No newline at end of file diff --git a/2023/data/12/example10.txt b/2023/data/12/example10.txt new file mode 100644 index 0000000..71ec4d7 --- /dev/null +++ b/2023/data/12/example10.txt @@ -0,0 +1 @@ +???.???????????#?# 2,5,6,1 diff --git a/2023/data/12/example11.txt b/2023/data/12/example11.txt new file mode 100644 index 0000000..85f92a0 --- /dev/null +++ b/2023/data/12/example11.txt @@ -0,0 +1 @@ +.?#?##?.????????.??? 6,2,1,1,1,2 diff --git a/2023/data/12/example12.txt b/2023/data/12/example12.txt new file mode 100644 index 0000000..5848e45 --- /dev/null +++ b/2023/data/12/example12.txt @@ -0,0 +1 @@ +?.??..#?##?# 1,6 diff --git a/2023/data/12/example13.txt b/2023/data/12/example13.txt new file mode 100644 index 0000000..fede4be --- /dev/null +++ b/2023/data/12/example13.txt @@ -0,0 +1 @@ +?.#??#???#?.#????# 1,6,6 \ No newline at end of file diff --git a/2023/data/12/example14.txt b/2023/data/12/example14.txt new file mode 100644 index 0000000..7e4fe8d --- /dev/null +++ b/2023/data/12/example14.txt @@ -0,0 +1 @@ +?###.????????#####?? 3,12 diff --git a/2023/data/12/example15.txt b/2023/data/12/example15.txt new file mode 100644 index 0000000..d97f3df --- /dev/null +++ b/2023/data/12/example15.txt @@ -0,0 +1 @@ +???????#?#???..???? 1,8,1,1,2 \ No newline at end of file diff --git a/2023/data/12/example2.txt b/2023/data/12/example2.txt new file mode 100644 index 0000000..63f8e44 --- /dev/null +++ b/2023/data/12/example2.txt @@ -0,0 +1 @@ +?#?#?#?#?#?#?#? 1,3,1,6 \ No newline at end of file diff --git a/2023/data/12/example3.txt b/2023/data/12/example3.txt new file mode 100644 index 0000000..eaa8c26 --- /dev/null +++ b/2023/data/12/example3.txt @@ -0,0 +1 @@ +?###???????? 3,2,1 \ No newline at end of file diff --git a/2023/data/12/example4.txt b/2023/data/12/example4.txt new file mode 100644 index 0000000..023b5c4 --- /dev/null +++ b/2023/data/12/example4.txt @@ -0,0 +1 @@ +???.### 1,1,3 \ No newline at end of file diff --git a/2023/data/12/example5.txt b/2023/data/12/example5.txt new file mode 100644 index 0000000..e13fe9d --- /dev/null +++ b/2023/data/12/example5.txt @@ -0,0 +1 @@ +??#.???... 1,1 diff --git a/2023/data/12/example6.txt b/2023/data/12/example6.txt new file mode 100644 index 0000000..c5bec3a --- /dev/null +++ b/2023/data/12/example6.txt @@ -0,0 +1,6 @@ +???.### 1,1,3 +.??..??...?##. 1,1,3 +?#?#?#?#?#?#?#? 1,3,1,6 +????.#...#... 4,1,1 +????.######..#####. 1,6,5 +?###???????? 3,2,1 \ No newline at end of file diff --git a/2023/data/12/example7.txt b/2023/data/12/example7.txt new file mode 100644 index 0000000..e6492e1 --- /dev/null +++ b/2023/data/12/example7.txt @@ -0,0 +1 @@ +..??##?????..#?? 9,2 \ No newline at end of file diff --git a/2023/data/12/example8.txt b/2023/data/12/example8.txt new file mode 100644 index 0000000..14bc4af --- /dev/null +++ b/2023/data/12/example8.txt @@ -0,0 +1 @@ +?#?????#??.????? 9,1 \ No newline at end of file diff --git a/2023/data/12/example9.txt b/2023/data/12/example9.txt new file mode 100644 index 0000000..a4a1117 --- /dev/null +++ b/2023/data/12/example9.txt @@ -0,0 +1,3 @@ +#....#....? 1,1,1 +? 1 +.#????#?.????? 1,1,3,5 \ No newline at end of file diff --git a/2023/data/12/input.txt b/2023/data/12/input.txt new file mode 100644 index 0000000..c3590ac --- /dev/null +++ b/2023/data/12/input.txt @@ -0,0 +1,1000 @@ +#??????#??. 2,7 +???#.????#?? 1,1,1,1 +.?????#??#?? 1,2,1 +#.??#?#????? 1,2,1,1 +..????##?????.????? 6,2,1 +#?##???#?#.??.?#?# 1,8,2,1,1 +??????##??#??#??? 12,1 +??..???#?? 1,2,2 +??##..????.?#.?. 3,1,1,1,1 +?###????#??..???.? 5,1,1,3 +#??.???.?#?#?#???# 1,3,3,1,1,1 +??#????#???.?..??. 5,3,1,1 +?.??#??#.????# 1,2,1,5 +##??????#.?#??##?? 3,1,6,1 +#???.????? 1,1,2 +?????#?#??.?.?? 1,2,5,1 +..??##?????..#?? 9,2 +???????.??.#????? 2,2 +##?.?????#?#???? 2,9 +.?#??.??.???. 4,2 +.?#??##..?# 1,3,1 +???.??..?##?. 1,1,2 +???.???##.? 1,1,3 +??#?#?#???##?????? 3,11,1 +??...??#?#. 2,2,1 +?.#?????.??##??#??# 1,5,10 +?????.#.?????##??? 2,1,1,2,1,5 +.?#?.???#???. 1,6 +???##????#??#?????.? 2,3,6,1,1 +?????????? 1,1,1 +??.????.#?#???#?? 1,2,4,3 +?????#???#? 1,5,1 +?????????#?????.?##? 2,10,3 +????????????. 3,2 +????.???#??????? 2,6 +??#?#?###????.????. 11,2 +.??#??#.?#?##??.?? 1,1,1,6,1 +???#?#?.??? 5,1 +?.??###?##?..#?. 7,2 +..????????.?? 3,1 +#?????.?????#???. 1,4,6 +#.?????.?.?.???? 1,3,2,1 +??????#???????????? 1,1,1,5,1,1 +#??###?#.?#???#? 1,5,2,2 +?.?.##?????.???#? 1,1,7,4 +?#?#?#????????. 6,1,1 +?.???#???.??. 1,3,2 +?.??#?##?.?#?????.?. 1,5,3,2,1 +?##????#.# 3,2,1 +???????#????? 2,1,7 +?##?..?.??#? 3,1,4 +.???#???????#?????. 1,1,3,3,1,1 +?#?????#??.????? 9,1 +?#.#??#.????? 1,4,1,1 +???.????.???#?#..?. 2,3 +????##???#???? 1,9 +????.???#.?#?? 1,4,1,1 +.#?????????????.??# 8,1,1,1,1 +??#??#?#??##???#?? 7,2,1 +??#.?.???????? 1,1,3,2 +???#???.??#??#?? 5,1,1 +???#?????????##? 1,1,11 +????#?.##???#?????#? 5,2,4,1,2 +?#??..?.#?????##.??? 4,1,1,1,2,2 +??#??..?##?.? 2,3 +?#???.????.?? 1,1,4,1 +??????#????#?# 4,8 +??????#???? 1,6 +?????.???##??.#??. 1,1,2,2,1,2 +???#?#..??#. 2,3,3 +.#??#?????#?.. 1,8 +?#.###??.??##??? 1,3,5,1 +?????#?.#?? 5,1 +?????#????.?#?? 4,2 +.#?.#??#?? 1,1,1 +????#????.??## 1,2,1,2 +????.??.##.????? 1,1,2,4 +?#.??#?#??? 1,4 +###????????????#?#.? 8,2,6 +#????.??????.#?##? 5,1,2,5 +#?.?.???#??? 1,1,2 +..##?#.??#? 4,2 +?.?#??.??#?. 3,4 +?.?..?.#.. 1,1,1 +.??????..?#???????.? 2,8 +??.??##.???#.. 2,4,1,1 +??.#??#??. 1,1,4 +????????#??#?##?? 2,9 +???#????#..????????? 5,1,4 +.????.?##.??##?#?#. 4,3,6,1 +?#?#..?????.??#??#? 3,1,1,5 +.#????##??.??.??. 9,1 +????.??.?? 1,1,1 +?#????.??? 2,1,2 +.?#?##?.????????.??? 6,2,1,1,1,2 +??#????.???. 5,1 +.????#??#..?##?.?? 6,3 +#?????#?????????#.? 1,13 +?????#.?#????###???. 2,1,5,6 +?#??????.?. 2,4 +???#?#???..#?? 7,2 +??#.????.??##??? 2,2,1,2,1 +??#?.?.#?#?? 3,3 +?????????#?? 3,1,3 +#??#???#???#.?? 1,1,1,5,1 +.??.??????????? 1,3,2,1,1 +.?#???????.#?? 4,3,1 +??#??#?????.????#?#? 3,3,3,3,1,1 +#??????????##???#? 1,1,1,1,9 +?.???..#??? 1,1,4 +??#?.#?#?.?? 1,3,1 +.???????#??? 4,4 +???#????#??.#? 8,1 +.???##????#??????.?? 5,2,4 +???.????#?????#??#. 1,3,1,1,3,1 +???????????.? 1,2,3 +???????##???.? 1,6 +.??????????. 1,1,1,1 +#??#???#??###???#. 1,15 +??#??.#?#???? 3,3,2 +.??##?#????.??? 6,2,1 +.??.?#?#??#??????. 5,7 +?##.???#?#?#?###? 2,11 +?????.??????. 1,1,2,2 +..????...?.??? 1,1 +??####?#.???? 6,2 +.?..?##???.???????? 3,3 +???#????#??????#??? 11,2,1 +.???#??#?..?. 4,1,1 +?????##??##???? 3,2,2,1,1 +?#?.#?.?####? 2,1,6 +???#??.#?#??#????#?# 1,1,1,1,1,9 +??..#?#?#?##..??#? 1,1,3,2,3 +?????????? 1,5,1 +????.?#???#?#?? 2,6,1 +??#.???... 1,1 +.??#?????.??#??? 6,1 +?.???????.?#? 1,2 +???????.?#??? 6,2 +???#?#?.?? 2,2,1 +??.?#.?##????????#?? 1,1,4,3,3 +????.???????.?..? 1,1,4,1,1 +?.?#??.??#???? 1,1,3,1 +####??.??#? 4,1 +???#???####?. 2,6 +????????#.?##?.??. 1,5,3,2 +.??#.#??.???? 3,2 +?####??#??#?.#.?? 5,1,2,1,1 +?#??#?????.#???? 4,1,1,1,2 +.??..????#.??#? 1,3,3 +???#.##?##?????? 2,1,6,1 +?????????? 1,1,1 +#??#?#?.????#?#? 1,4,5,1 +##?.?#???#.????? 2,5,1 +.????.#?##??#???..?. 2,8,1 +?????#????#.????? 10,4 +?????#??.????#? 1,4,2,1 +#??#?#??.??#? 7,3 +??.#?????.#????? 1,3,1,3,1 +??#?????#????. 3,2,1,1 +?.?#??.??.?.????? 3,2 +??#?#?#???#??.????#? 11,5 +?#?????#?#??..?.? 2,2,3,1 +???.#??#?.? 1,2 +?#?#???.??#?? 5,1,1,2 +?#?????.?.?? 1,1,1,1 +?????#??.?? 4,1 +??.????#..#??#?#?.? 2,1,1,1,4,1 +??#????.?? 1,1,1 +#?.???????#.???? 2,2,1,2,1 +?.??.?????.? 1,1,1,1 +?????.??#????.?? 1,2,4,1,2 +?..?#??.#?? 1,3,3 +??????#?#?? 1,4 +??#.?.#??????#??..?? 1,1,1,2,4,1 +.????##???#??. 8,2 +????##..?..??.? 2,1 +?.???..#?. 3,1 +???????#??#??? 2,2,2 +???????.#?????? 1,3,2,1,1 +?#?#.??#???.# 3,2,1 +?#???.?#???#?#????#? 2,1,3,3,5 +?#????.??? 3,1,1 +??#?##?.????#?.? 4,1,3,1 +?.???.????. 2,3 +#?????#?#??#??. 4,7 +????????#??#??? 1,1,1,3,4 +#??.???#???#?#????? 3,4,5,1,1 +???????.?#?.#?. 6,2,2 +????#????? 1,4 +?.???????#? 2,3 +??.??????.?#?#? 5,4 +.?????#??.#??#..###. 1,2,2,2,1,3 +???.???.?##?????? 2,3,8 +#.?.???????.?## 1,1,3,1,3 +##.#??.?.?? 2,3,1 +?.???.??#?#. 1,4 +????#???.?. 6,1 +..??.##?.?? 1,2,1 +?#?##??????#?? 2,3,2,1 +?####?..??#?.?#?? 6,4,1 +?#????.#.?#???#? 4,1,1,2,2 +.??#????????#?#? 4,8 +????#?.???##? 1,3,6 +????.??????#???##? 1,2,4,2,3 +???#??.?????.??# 1,2,3,2 +.???#?##?#.????? 2,4,2,1 +?#???#?..??????. 2,2,3,1 +??????..#?.?##?#?.?? 5,1,4,1 +??????????????#?# 3,11 +?.#??????????#.? 4,7 +??????#?..#???# 1,4,5 +???.?#??###?#??.?#. 9,2 +?.???##????##?#?#? 10,1,1 +??#??????##????? 7,3,1,1 +????????.??. 2,1,1 +.???#???##? 2,2,4 +??#.#.????#????. 3,1,2,6 +???#..?.#? 1,1,1 +?#???####??#.???.?#. 9,1,1,1,2 +.???.#?.???? 1,1,1,1 +?.??#??#??.?#.?? 7,1,1 +.????????#? 5,2 +????#?.?.#? 3,1,2 +???#????.?????#??? 1,3,3,4 +?#.?#??#??##?????? 1,3,5,1,1 +??#?#??.#?? 4,1,1 +???#?????.##.???# 5,2,2,1,2 +?.?#???????????#?#?. 6,8 +?.??#?.?????.???# 3,2,1,1 +?#????????.?? 5,2 +??#..#?.??. 2,2 +?#???#????????#?#? 2,2,1,1,4 +.??#???.????..??. 5,1 +#???.#???? 4,2,1 +?????.##??.?# 2,4,1 +?#??###??? 3,5 +?#??#?#??.. 4,1 +?????????????.?????? 8,1,4 +#?#????????? 4,1,3 +?.??#??###? 1,1,4 +..#????????..##..?.? 1,3,1,2,1 +??#???#???## 4,6 +?.##??.?????#??.# 3,1,1,1 +?#..???????.# 2,1,3,1 +###??????#? 4,1,3 +??.#?#?#????#?????? 10,1 +?????#???????.. 6,2,1 +?#.?#?..#?#??. 1,1,5 +???#??#?#?????.. 3,9 +?.#??..?.???.?? 1,1,1,2,1 +??##???.??? 6,2 +??.?##?#??. 1,6 +?.????#?.#? 2,3,1 +?.#????.????#. 5,1 +?.????.##. 1,3,2 +?##?#?#???#??? 7,2 +?#?????#?.?#? 2,3,2 +#?#???#??#??????? 10,1,1,1 +?.?#??.?#???#??.?#?# 1,2,7,4 +???.#..???# 1,3 +#???????????? 7,1,1 +##?.????..? 3,3 +??.??####???..#? 4,1 +??##???##??#. 9,2 +?##?????#?#?#?##? 3,5,2 +?#?.???????.???????# 3,6,1,1,1,1 +???#?#??.?? 7,1 +??.#?#?#????.# 2,7,1 +????#?#?#? 1,6 +??#?###?????###? 9,1,3 +.????#?##.? 7,1 +?.?????#.????####?. 2,1,1,2,5 +#??.#?##??? 2,6 +.?.#??.??#??? 1,3 +?.#???#?.??#????? 6,4 +?.#?#.?#????#???? 3,1,2,3,1 +#.#?????#???? 1,7 +??#????##?.#.#? 4,5,1,1 +???????#?##????#???? 3,9,1,3 +?#??.?##?????#???##? 1,5,9 +?...???????#???.. 1,5 +??.#??.??? 1,1 +.??#?.?.###?? 3,3 +?.??.??????. 1,4 +?.??????????? 1,6 +#.##?#?#???#???# 1,4,1,4,1 +??.#??.????# 1,2,2,2 +..#???#??????.?.??? 9,1 +.????#?????.?.?? 8,2 +.?#.?????.??? 2,1,2,2 +?#.????..??? 2,1,1,1 +.??????????#?????#? 2,1,2,2,2 +?????????????#. 1,2,1,1,1 +?#?#??????#?.#?###? 12,5 +.?.?????????# 1,3,1,1 +?..##???????. 2,4 +#.??#???????? 1,4,1,2 +###????...??? 7,1 +??.....##?#??#? 1,8 +????????.?#?.#. 1,1,2,1,1 +..???????#?? 4,2 +??#?.?#??#??? 3,2,2 +.#???.?..??. 1,1,1,1 +??.?##?????.?.?#? 2,7,2 +??#??#???#??????##? 1,1,1,3,5 +??.???#??? 2,1 +??#??????.#. 2,2,1 +..#??#???.#??# 6,4 +?#.?#????###??????? 2,1,2,5,3 +?#??#??#???.#..?? 1,4,1,1 +???##??.??#??#??. 5,1,4 +?.#??#?##?.?###? 1,1,6,4 +.#.??#???#? 1,2,4 +??..????..#??? 4,1 +##????#???#??#??#??? 17,1 +?????#?#?.??.??? 2,6,1,1 +???#?..??? 2,2 +.?#??????##???.. 2,6 +??..?.??????#??? 1,1,1,4 +??#?.?##??##??#?? 1,4,7 +???.?????#???.????? 2,1,3,2,2,1 +.?#??????.?.?? 4,1,1,1 +?.??????.??? 3,1 +??###???..?????.? 8,1,2 +?.?#?????. 1,2 +?####??#?##.?.? 10,1 +#?##?.##?#????.#?# 4,2,5,1,1 +?....?.?????? 1,1,1,3 +#.?#???#???#??#??? 1,10,4 +?.????.??#?? 1,4 +??????#?#?? 1,1,3 +.?.?.#??.??#??#? 1,1,6 +#???#???????#?.????? 1,10,1,1,1 +???#??..??#?#.?.. 4,4 +??#????.##?#??????.? 4,1,5,1,1 +?.?????#???#??#?##?# 1,1,1,1,9 +????#?#?#??????? 1,1,1,3,1 +????.#??#.#?????? 1,1,4,2,3 +.#.???.??#??? 1,1,2,1 +?##??##?#??.? 7,1,1 +.???.??????????#?.? 1,1,6,3 +???????#???#.#???.? 1,1,5,1,1,1 +.???#?##??.????##?. 8,7 +??.??????? 1,1 +??#.?#??.???? 1,3 +????#???????.??.#?? 1,8,1,1,3 +.#???????#??##??? 6,6 +?##?#????? 2,4 +???#??#?.?#??##.# 6,3,2,1 +..?#??#???? 4,1 +??#?.?.#??#.###?? 1,1,1,1,4 +?####????###?###???. 4,9 +??#?#.???? 4,1 +?###??.??.?.???????? 4,2,1,6 +##????..?#? 2,1,2 +.?#???.#?#?#? 4,6 +??#???#.????.?.?.? 1,2,2,1,1,1 +??#?????#??????.? 4,3,1,1 +????.?#???##.???#? 1,1,6,1,1 +?#??#???#??? 4,3 +?#?????.?#?????## 2,1,9 +?.???????##?#??????? 1,1,1,7,2,1 +??.????#?? 1,1,1 +?????...?..???#?.. 3,3 +??.???????#???#???? 1,2,12 +???#?#..????#??#. 5,1,2,1 +#?.?..#??? 1,1,2 +.#??#????.#??..???#. 8,1,2,1 +.????#?.????????. 4,5 +?.??###?#?????????#? 10,1 +??#.????#?.. 1,1,1,1 +??????#.??#??. 7,3 +?.#??#???#?.#????# 1,6,6 +?????#?#??#?. 1,6,3 +#?..????##? 1,1,3 +???????##?#### 1,10 +?..#?.?##?#?#? 1,1,6 +?????..#??? 2,2 +??.???.#?. 1,1,2 +????#??##??????#??? 1,6,1,2,1 +#????#?#?????.?? 1,4,3,1 +???????#?#???..???? 1,8,1,1,2 +?????##?????? 1,1,8 +.??..????????# 1,1,6 +??.#???##??#.#?? 2,6,1,1,1 +.?##?????? 3,2 +.?..?..???? 1,1,1 +.???????????#?###?.? 1,8 +?????????##???#??#?? 1,1,12 +???????.?.??.#? 1,2,1,1,1 +???.??#??#???? 1,6,1 +?????#.##????#??#??? 4,1,4,2,2,1 +?#???.??#??#.?. 3,6 +?.?#?#???# 5,1 +#..?#???#??????.#? 1,3,3,1,2,2 +#??????????.?##? 1,6,3 +????????##?#?.#?.?? 1,1,1,5,1,1 +.??##?????##??#..?#? 12,2 +??##?????##?#?? 2,7 +.?#?#????####? 5,5 +?#??#?????????? 1,6,2 +??#????#..?#??##? 3,1,1,7 +????.#???.?###?# 2,4,5 +????#?.??# 1,2,1 +#?#?#??#????..#???? 1,4,1,1,4 +##?#???#???..??? 5,1,1,1 +??#?.????#?#?. 1,1,4 +.#????#?????#. 1,5,1,1 +?..?.???#?????. 1,1,4,2 +.?????.???? 2,1 +##?#????.??? 4,2,1,1 +???##????..?#? 9,1 +#???#?##???#??? 1,1,1,6,1 +?.????##?#.# 3,2,1,1 +??.?#?#?.?..???#.?? 2,4,1,1,1 +.?.???#???##????#? 1,1,9,1 +??.??#?###??? 2,1,6 +?.?.?#??..???????? 2,5 +.???.??????#? 2,5 +??.?##???# 1,3,1 +??.?.#??.??#. 1,3,1,1 +?#??.???.?. 3,1 +#???.?##?#.? 3,3,1,1 +##??????#?#????? 3,1,7 +??.??????????. 4,1,1 +?.##??#??#??.?#??? 1,2,1,4,1,2 +?????#??#?#?. 1,2,7 +?#??.???????. 2,1,4,2 +.?#??.?.#?.??? 3,1,1,3 +.?##?..#?#??#?????. 3,7,3 +?##?..???.. 4,1 +#???#..???.??? 2,1,2,1 +???#?#??..#?... 5,1 +????##???? 6,2 +#.?#???.????#?# 1,3,4,1 +????.#??.?##???.??#? 1,2,5,1,2 +??#??#???? 3,1,1 +??##?????#??? 5,3 +?.#???##?.???.#? 7,2,1 +#??.##?????.? 1,3,1,1 +?#????#?.??? 1,1,1,2 +..?.???????.? 1,4,2,1 +???#?.??.??. 2,1,1 +#???#??.#????.?# 1,2,1,4,2 +.??.#???.????#?#? 1,4,7 +.#???#?##????#?#??#? 1,11,2,1 +??????##?#??????? 1,8,1 +.??..???.?#?# 2,2,4 +????????.#?# 3,1,1,1 +###???????#?..???? 11,2 +?.?.????.??#??? 1,1,1,1,4 +????#??#?#.?? 1,6,1,1 +?#?.?.?#?#?.?? 3,5 +??.#??#??#???????. 1,2,7,1,1 +???.#???#??.? 2,3,1,1 +?#?#?#???. 1,3,1 +??.???.?##??##?. 1,8 +?#?#????.??? 3,1,1,2 +??#?.???#??#.?.?. 2,6,1 +?..#.#?#???????###? 1,1,1,1,9 +?????..???.. 5,2 +.?###..?#?#?????#? 4,6,2 +????###?????? 7,1 +##...?????.? 2,2,1 +.#??####???.? 8,1,1 +?????.#?????#? 2,8 +?..??????????# 2,3,2 +.??#??.???##???#???? 5,5,1,3 +#??.??????##?????? 1,1,1,1,6,1 +????.?###??#?.??? 1,8,1 +..??#?#?..#???#?. 6,6 +?#???##?????.???..? 8,3 +?#?????#.???????###? 7,1,7 +????#?.???#????? 1,2,1,3,3 +?###?????###??#???? 11,1,1 +???.??#??.?.??? 1,1,4,2 +..??#.#.?? 2,1,1 +.??.??????. 1,2,1 +.?..???.?? 1,1,1 +??#??????# 4,4 +?????#.?.??. 1,2,1 +?#?#?.####.???? 4,4,2 +.#??????#??? 3,4 +.?.???.????# 1,1,1,1 +?????#??#? 1,1,2 +.???.?.?##?.? 2,4,1 +??.???##???? 2,8 +??.????..?#? 1,1,2,2 +??.????##???.#??.? 1,1,5,1,2,1 +.#?..?#??? 1,3 +?????#?##???#??.?.?? 7,3 +?.??.?????#???.?.?? 2,1,3,1,1,2 +?.????#??.????.#?#? 1,1,2,3,1,1 +?#???..#??#??# 4,4,1 +???????.???? 5,1 +#??##??#???? 8,1 +##????#???##??? 7,3 +#?#??????????????? 1,1,3,1,1,1 +#???????.??.. 1,3,1,1 +??.#?#??#???#?. 1,11 +??.?#?##??.?#??#??? 1,6,8 +?.?#????????? 1,1,3,2 +???##??????# 1,4,1,1 +?#?###?#.??? 5,1,1 +??????#?#?? 1,4,1 +??#..?.???#??.#?.? 3,1,4,1,1 +???##?.?????? 5,4 +.#.#???.??..????#.? 1,4,1,1,1,1 +#??.#?.??.#.? 3,1,1,1 +??..?..???##..????? 3,3 +?.?.?#??##???...#? 1,1,9,1 +?#??##??#??#?##?? 2,6,5 +#?????.???.? 5,2 +???.?#?##?.???.? 1,6,1,1,1 +?.#??#?##??.?? 9,1 +?.?#?.?...##? 2,3 +?#??##?#???#?? 1,9,1 +.???.#??.?? 2,2,1 +??.??????#???? 1,4 +.?#????.#.?#???#? 2,1,1,1,6 +.?#??????# 1,1,3 +#..????.?.???.?#?? 1,4,1,3,3 +?.??##.????#????### 3,12 +#?????#??#.?? 8,1 +.#?##?#???###.?? 1,4,4 +??#..##??#? 1,5 +????#?????#.????# 2,7,1,1 +?.##????????#? 4,1,1,1 +?#?.?????????. 3,1,4,1 +?.??#?????#????? 1,2,6 +??#?????#.?????# 2,1,1,1,5 +???##?#????? 1,4,1,1 +#.????.????#?? 1,2,6 +??.??.?.?????.?. 2,1 +?.?#.?#????#???###? 2,1,1,8 +?#?#???##?..#??#??? 10,1,2,1 +??#...?.?. 1,1 +?#???#???.?? 1,5 +##?.?#??..??#?## 3,3,4 +????????#?#?? 9,1 +?????#???.??#? 7,1 +?.??????##.??###? 6,5 +?????#??##????# 1,1,1,5,1 +?##???#??###?#???.?. 2,9,1 +?#??..?????#???.#. 4,1,1,1,1,1 +???#...#?? 3,1 +?#????.?#? 3,2 +??##??????#??.??? 3,2,4,1 +#??#???#?###??#.??. 1,12,1 +.?###???????????# 4,1,1,1,1 +##??#?????#??#.??. 3,2,1,3,1,2 +???#??##???#?????? 7,1,1,1 +??????????? 5,2 +??#????#?#????? 9,1 +?????????#????????? 6,1,1,1,1 +?#???#.????##?#?# 2,2,3,6 +.????.???# 1,1,1 +.?##???#..? 4,1 +?????##?.??#.?#???# 8,1,1,1,1,1 +...###???#?#??#????. 9,6 +.#??.?.????#???? 3,4 +??????#?..??#??? 3,3,1,2 +?.?##.????# 3,2 +.???#??###??.?#. 1,1,3,2 +????#?????.#?? 1,2,1,3 +?????.???#? 2,2,4 +??#?#?#???##???.?? 13,2 +#.#.#????#?#?##?###? 1,1,1,1,10 +?????.??.?.?#?. 1,2,1,1,1 +.??#???.??????#? 5,2,3 +..??#???.???#??. 2,2,5 +???#?#??????????#??? 12,2 +..??#???????#??#?#? 1,3,8 +?????????#???#?? 1,1,1,1,6 +??????.??.?#? 2,1,2 +?.???##??##?#?#??? 1,1,11,1 +.?.???????#?#. 1,4,3 +.#???#?.??. 5,1 +.?#?????????#??. 2,11 +?????##???..?. 1,7,1 +??????????##??????? 2,12 +?.??..#?#????#????? 2,5,2 +??###??#???? 3,1,1 +##???#??##?#.?#???.# 6,3,1,1,1,1 +????#?#??#????#?.#?# 1,5,7,1,1 +????#??????#?.???.? 11,3 +#.??????.?#?.?#? 1,1,1,2,2 +..?.?#?#??? 4,1 +??.???????????#? 1,1,4,5 +???#???#?#??. 1,1,5 +?.#???##??.#??# 1,6,1,1,1 +#?????.??#???#??##?# 6,3,7 +.???????.?????? 6,1 +????#?##.#??..?#??# 6,3,2,2 +.?.#??#?.????# 1,2,2,1 +?#????.?#???.?? 6,2 +?????????.????#?? 1,1,4,5,1 +#?#???#????.? 4,2,1,1 +.??#.????#?????#? 1,1,3,1,3 +??.?#????###???# 1,2,5,1 +??????.?????????.??? 1,2 +????????.#?????? 3,3,2,1,1 +???..?#?#?#???? 1,8 +.?#??.????. 2,2 +..???????????..# 5,1 +#??.???????.??#?.?? 1,1,1,4,1,2 +??.?#.??.#..?. 1,1 +??????#??#???#?.??? 3,9,1 +#?#??##??????? 1,1,7,1 +.#?????###??????? 1,6,3 +##?????##?.#.???.# 4,4,1,1,1 +??????.????.?#?# 1,1,1,1,4 +#???????#.#?.? 5,1,2,1 +???.?##?#? 3,1 +???.#???##?#?#?#?.. 1,2,9 +.?????.#?????? 1,7 +?.?#???##??#????.# 1,11,1,1 +??##???#??#..?.. 1,3,3,1,1 +#.????#?.??#?? 1,1,2,5 +??.???..?#???.? 2,1,1,2,1 +?.#..??#?#?#.? 1,1,7 +?#?#####??#??.#??? 13,1,1 +.??.?#?#??????? 2,3,4 +?#??#???#?? 4,4 +?#??#????...????.?? 7,3 +.?.????????#?? 1,5,1 +?##?????#??? 5,2 +#????..?.?.?##???? 1,1,1,1,6 +?#####?#???????. 8,1,1 +?????????? 2,1 +#????.???.?? 4,2,2 +???.??#???? 2,2,2 +???.??.??.???? 1,2,1,3 +?#??????????.??? 2,1,3,1,1 +???.???????#..# 1,1,3,1,1 +??..??????#??###.?# 1,3,7,1 +?#???????.?? 4,1,1 +#?????..????????..? 2,1,5,1,1 +#????##?###?#??.??? 4,10,1 +?.??##?..#???.?? 1,3,1,1,2 +?????##?.??.#.??? 1,5,1,1,2 +?#???????????? 2,4,1,2 +???????#?.????????# 1,2,4,1,6 +?##.???#?????. 2,5,1 +#????#???#??????.?? 6,8,2 +##?##??.#?.??# 7,1,1,1 +???.?###?????#? 2,7,2 +#.????????? 1,5,2 +???#?.?#?????####??? 1,1,2,1,8 +??.????#?.????#?.? 2,4,3,1 +#??.???#???#?.??? 3,8,1 +??.???#??# 2,3,2 +????#.?.???##?? 2,1,1,1,3 +?.?.?.??.?.. 1,1,1,1 +???..?#?#?. 1,1,5 +#??.???#?###?????? 3,1,10 +?..?.?#???#??????? 1,1,4,1,2,1 +?.??##????#?? 3,3 +..??????..?#????? 2,6 +?????#??#?.???? 8,3 +...??#?.?? 1,1,1 +?#.????.#.#. 1,1,1,1 +????.?#?.???????#?? 1,1,2,4,4 +??#??#?#?.?.?.??#??. 8,2 +?#???##??##???#?? 1,11 +?#?###?.#?#????# 1,4,1,1,1 +??##????#????.?#??#. 8,3,1 +??.??#?..#???.. 2,2 +???#?.???.????? 3,1 +#???##?#?. 1,7 +#???.#????# 2,3,1 +?#???#?#?#?????##??? 1,1,7,3,1 +?#??#.??.??# 2,2,1,2 +??#??.???.???? 1,3,3,2 +?..#?????.?? 1,1 +???.???????????#?# 2,5,6,1 +.??????#??? 1,2,1 +??????????#????#? 1,1,2,6 +#??.??..????#.#??? 3,1,1,2,1,1 +?#?????????? 1,6 +##.????.?????##.? 2,1,1,1,5 +##??.??#?????#??.? 3,4,5 +.???..?#?? 1,3 +##??.???????#. 3,4,3 +?..??#???.? 3,1 +?#?#??????????. 8,1 +#???.?.#?#.? 1,2,3,1 +??????#.?? 1,3,2 +?.??...???#?????#?. 1,4,5 +##.?.?????????.#?.? 2,1,8,2,1 +?#??#???.??? 6,1,1 +??#?.?.?.# 2,1,1 +?.?#????#.????????#? 1,6,8 +?#????????.??? 6,1,2 +?.???.#?.????.??## 1,1,1,2,3,4 +#??.#???????????? 1,1,10 +?#?????##?#??????? 1,3,6,2,1 +?.?#???#??###.#??.#. 1,1,3,3,2,1 +????????????.??.? 1,1,4,1,1 +?#??#????.#?#. 1,5,1,1 +##?#??.#?.????????.. 5,1,2,4 +?..?????#..?#??.. 1,2,2,3 +.#?#.?##?????.#??? 1,1,7,1,1 +.#???.???#?.? 3,1,1,1 +?##??????????# 2,1,3,1 +?##??#??????? 5,2 +?#???.##?#?? 3,1,2,1 +???.?#???##?? 1,1,1,4 +???????#?.#???? 1,6,1,1,1 +???.#????#??. 1,8 +#??????#??? 1,5,2 +?#???#.??? 1,2,1 +????#??.## 1,1,2 +?.#.?#???#??.?#???#? 1,3,1,1,6 +?#??#??#..???#?? 2,1,1,1,4 +.#??????#?. 1,1,2 +????##??.??#. 7,2 +.?????#?.???#?? 4,1,1,1,1 +?????..#?. 2,1,2 +..??#???.?????#?.? 2,6 +???#??.??##? 3,3 +.#?.?????????.? 2,1,1,1 +??#??#??#.? 2,1,2 +#..???.???#??.?#?.? 1,1,4,1,1,1 +???#???.##?##?? 4,1,2,4 +????#####??##???? 8,2,1,1 +.#????#?.????? 1,1,3,5 +.??.????.????? 1,2 +?..?#.#????#???#.? 1,10 +???????###.#? 1,1,3,2 +??..?##?#??.?.? 6,1 +.???#???????.??#?#?? 4,1,1,1,5,1 +?#??.????.. 1,3 +??#?.?##.???.?##?? 2,2,3,3 +???#??#??#????.##? 1,1,1,3,1,3 +.#??.?.??#?#.#?#.# 1,1,4,3,1 +?#???.?.??? 2,1,1 +#..#??????#???.?#??? 1,8,3 +??#????##.?..?? 1,5,1,1 +.##?#????.?.???# 6,1,1,2,1 +??###???#???????.?? 11,1,1 +?#???##???#.??#????? 1,7,2,1,1 +#???#??.??.????? 5,1,1,4 +??#?.?##?#?#?#??#? 1,13 +??.#???#??? 1,1,4 +##???#??##????? 6,4,2 +?##?#?????. 5,1 +.????#?.??#????#??? 1,1,1,7,1 +?.#??#?#??#???.##?. 1,2,5,2 +?.???##??. 1,1,4 +?.?#??##?#??##?.? 1,11,1 +??#??.?#???? 3,2 +.???????.?##? 2,2,4 +?????##??.?????.??# 9,1,2,1,1 +??#???##?.???? 7,2 +???#?#??#??.?? 1,1,5,2 +???????#?#?? 2,4,3 +.???..##?? 1,2 +???..????..???#?? 1,4,1,1,1 +?????..????? 3,5 +???#?#???#???#???? 1,7,5 +????#?...??.?? 2,2 +???????#????????#? 2,2,7 +??##.??????? 2,2,2 +.#???#.????#???.?? 5,1,2,1,2 +??????.?.??? 4,1,1,1 +???.???????##?# 2,1,1,6 +##.?.??????????? 2,10 +???.#??#.? 1,1,1 +?#??#?#?.? 2,3 +???.#??#?#?##???#? 9,3 +?????.?????.# 2,2,1 +????..#???.? 1,4 +?????##????##????#?? 6,1,9 +??.#?#???????.??# 4,3,2 +?????.?#?#???.?????? 1,1,7,1,1,1 +????#??##.?????.? 6,2,1,1 +??##?...#?? 3,1,1 +??#???##?.????#??? 3,2,6 +#??#??????.?.??#?? 8,1,1,2 +.?.??#????????.#???? 6,5 +#????#??#? 1,7 +?.#????###????? 1,1,10 +??????????#?.? 4,4 +?.??#?..?.???.?.. 1,2 +.????..?## 3,2 +?#?..#..?? 2,1,1 +??????##?##.??????. 2,5,2,1,1,1 +???.?.??#?##? 3,7 +..?##?###?#?#?.??## 6,4,4 +??##????#??#???.? 5,6,1 +.?..???.??.?..? 1,1 +?????.?????? 3,4 +?.#?.??.??? 1,1 +###.??.#?? 3,1,1 +????...?????##.??. 2,4,2 +??#..???..???##?. 2,1,2 +?????????????##???? 1,6,4,1 +?.???????? 2,1 +?.??..#????? 1,4,1 +?#.?????##. 2,6 +#??##???#?????#? 1,3,4,4 +.?#???#?##????.?.? 13,1,1 +?#????#????##?#??#?# 1,9,3 +.??.???#??#. 1,1,1,1 +?????.?#?#?#??# 1,1,1,1,4 +.???.??##??#??.?? 2,9 +?.??##?.???#?? 5,3 +???#?##????#.???. 9,1 +.???????.#.#?.????# 1,1,1,1,1,5 +#??#??.??? 4,1,1 +?????.??.####??#??.? 1,1,1,1,9,1 +?..??.#???#?#????#? 1,1,1,7,2 +???#???.#.?????? 1,1,1,1,6 +?##??????.??.??? 2,4,1,2 +.?#??.???#??. 2,4 +???????#?# 1,1,4 +???..?.????? 2,1,1,1 +.?????.???? 2,1,2 +?.?????#??. 1,2,4 +.#????#??????? 7,1,2 +#?#???.?.??.?.????# 4,1,2,1,4 +?.#??????????. 4,3 +?#????.#??? 3,1,2 +???#???.???#? 3,4 +.????????? 2,6 +.??#???.???.#???? 5,3,1,2 +#?#??????. 3,3 +#.????#????? 1,1,5 +?.#???.??????#???# 1,1,1,5,1,3 +??????#?????.???. 5,3 +???..?.???? 1,1 +?.??.##??? 1,3 +#?.???#.?.#????? 2,3,1,3,2 +?????##??#??#??#??. 3,2,2,2,2 +..#??.?????.???. 3,1,1,1,1 +?#?#.?#??#?#?????#?# 4,8,5 +???#?.???????#? 1,1,3,2 +????####???#??#?? 1,14 +?.#???##??##.?????## 10,4 +???#?#???#??#???. 7,1,3,1 +???..?#??#??#??? 1,9 +???.?#???#? 1,1,6 +?##??????????#?????? 3,12,1 +?????#.#??? 4,3 +#???#??.????#???# 1,5,1,3,1 +??.?##?#?#???? 1,10 +#.??.???????#??? 1,2,5 +.#????.?#??##? 2,7 +???#?#???????? 7,1 +???#?????#?#? 1,2,4,1 +??#.?#.??????????. 1,1,1,1,8 +?.?.????????# 1,3,1 +?#?#?.??????##????? 1,1,10,1 +?##???.????.?#? 3,1,1,2 +.?????#..???#?#?#?# 6,10 +?###?#????? 6,1,1 +???#.????.?# 1,1,1,1 +?????.??????# 1,1,6 +.#??????###??#?.?? 4,1,3,2,1 +?#??.?.?#..?? 2,2,2 +??????#??? 2,2 +??#?#?????.? 5,1 +???.?##?.??#?#?? 3,4 +?.??.???#??? 1,2 +.????..??.? 2,1 +?#?#??.#????#???.. 5,7 +????????#?#????? 12,2 +?.??.??##??#??##??? 1,2,3,8 +....?#??.?#.???#???? 2,2,2 +????.???????#.?# 2,8,2 +?#????#.?#????#?? 3,3,4,1,1 +???????#????..#? 2,2,1,1,2 +#?.???#??#?? 1,8 +.????#??#? 1,1,5 +???#???..????? 6,1,1 +??????????? 2,4,1 +?.??#???#?????? 1,1,3,2 +#??????????..?. 1,1,2,2,1 +##..????#?.?.??# 2,2,1,1,1 +#??#.?#?##??#?. 4,8 +.?.#?#?#.?????? 1,3,1,1,3 +...?#??#.???.??? 5,3,2 +??#.?##??#.? 3,2,2,1 +???##??#????????#?# 1,6,1,1,1,1 +????????????? 2,4,1,1 +?.????..#?????#???? 1,1,1,3,6 +???.???.?#?#?##.#?? 1,1,6,2 +.?.??.??#.??. 2,1 +#.??..???? 1,1 +.??.?#???##?##??? 2,1,7,2 +#?###?????.?. 7,2,1 +?##?.?.????????.? 3,3,2,1 +???????#??????? 1,1,6,1 +??#??#???#???? 1,2,8 +##??#???.???? 5,1,1 +...#?????..??##??..? 6,3 +#?.??????#??#???# 2,1,5,1,1 +???????#?##?? 1,1,6,1 +#???????#?????##???? 2,11 +?.????#??.??????#?.# 1,1,5,1,4,1 +?.#????#?#?????.?? 11,1 +????#?###?#?#?????? 13,3 +??#??#?????. 4,5 +???????#??#?.???.? 1,4,2 +??#?#?#.???#?.?#?? 3,1,2,3 +??.##.????#????. 1,2,1,2,1 +??#???#????#.?.? 5,1,1,1,1 +?????#??##?#.?? 11,1 +?.?##????????.? 1,8,1,1 +??..???###?.???.##. 2,6,1,2 +??#???##??.??? 10,1 +?.?#???#??.??#? 6,3 +??#?###?#?..?.?????. 7,2,1,2,1 +????##?##?#???? 1,10,1 +#?..??????. 2,1,1 +.??#?.##?????? 3,4 +?#?.????##??.?? 2,7 +??#???.#??#???. 4,6 +?????.#.#?##???.??# 4,1,1,3,3 +?..?#.?###?#?? 1,2,8 +.????#????#????#.?.. 11,3 +.?#???.?????????#? 3,1,6 +??##?#?#???.??#? 9,2 +.?###?##.?#.?.?#???? 6,1,1,3,1 +?.#??????.? 2,3 +??#?????.?.??. 4,2,1,1 +??##??..#?????????# 1,2,1,1,7,1 +???##??????#? 7,1 +???#???#.???#.???? 3,1,1,1,1,3 +?.?????##..?#?#????# 1,1,2,7,1 +???####??##?#??#??? 1,4,5,1,1 +????#?#??##????.# 11,1 +??#??????##?... 4,5 +?#???????#?#???#..? 1,1,8,1 +#??#??.?????#?#? 2,1,1,7 +.???????...?.#??#? 1,3,1,1,3 +?###?#???.?? 8,1 +?#?##?#???#????#?.## 8,4,2,2 +??#?..?#???####????? 2,10,1 +.???#?##??#??#???? 10,3 +???????????.??? 4,5,2 +?#??????#???.? 2,5 +#??..#????????#?.?? 3,1,4,4 +.???#??#???##??????# 1,16 +???.?#???##??##????? 2,2,10 +.#.??????.##???#??? 1,1,1,8 +??????#?????? 6,1 +??.?#?##?#???#?#? 2,7,2,1 +#???.??????? 1,1,1,3 +???????.???????? 2,1,1 +???#???.??.??? 1,3,2,1 +???.??????.???.? 2,5,1 +??.??.????.?##?????? 1,1,2,1,7 +.?#?#??#?.??#? 7,3 +.#?##??##?.#?#?? 1,6,3 +?#????#??????.????? 7,2,2 +???#??.?#?#?? 4,1,2 +?????###???.. 1,8 +???##??#.????.?? 5,1,1,1,1 +?..???????? 1,3,2 +????.?##??????#??#? 1,1,4,6 +???#?##??.??????#?. 1,1,4,5,1 +.?#?##.?.???? 4,1,1 +??.?.??#.? 1,1,1 +?????.#??.???##?##?# 3,2,10 +????#???.? 5,1,1 +??????????.???#.?. 1,1,4,1,1,1 +??????#.#?????#? 1,1,2,5,2 +?#???#????#??#? 1,1,2,6 +?#.???????#????.??? 1,2,1,3,1,1 +?????.?.#??.???#.? 1,1 +?#?#?#????.#???#?. 1,1,1,2,1,3 +??.??#?##???. 1,5 +??#???????.??..## 5,4,2,2 +?..?.??.#?#????#???. 1,2,8,1 +..#??????#????? 2,2,1,3 +..?????#???##??.#? 1,9,2 +?.?###??..? 4,1 +?###.????????#####?? 3,12 +???##??#.#?#? 8,1,1 +?#?#??????.???? 4,1,1,3 +?..?.?????.? 1,3 +????#???.?? 3,1 +????#?#?.#??? 1,5,3 +?.?#?????. 3,1 +#???##???.?.???? 7,1,1,1 +#..#?????. 1,1,2 +??#????.#?????? 3,1,1,2 +?.???????#??##???? 1,9 +???.??#?????#?## 2,11 +?.?#...#?...?? 2,2,1 +???????????.??? 10,2 +...?#.???.??. 2,1,1 +.??.?#?????.? 2,6 +.???##??.????? 5,1,2,1 +#..?????#???#???#? 1,3,6,2 +..????##??????????? 14,2 +?.??..#?##?# 1,6 \ No newline at end of file diff --git a/2023/solvelib/02/day02.cpp b/2023/solvelib/02/day02.cpp index 81813de..7870cc8 100644 --- a/2023/solvelib/02/day02.cpp +++ b/2023/solvelib/02/day02.cpp @@ -7,7 +7,7 @@ #include "xmaslib/log/log.hpp" std::uint64_t Day02::part1() { - xmas::line_range range(this->input); + xmas::views::linewise range(this->input); constexpr std::int64_t max_red = 12; constexpr std::int64_t max_green = 13; @@ -36,15 +36,15 @@ std::uint64_t Day02::part1() { } std::uint64_t Day02::part2() { - xmas::line_range range(this->input); + xmas::views::linewise range(this->input); - return std::transform_reduce( - range.begin(), range.end(), 0u, std::plus{}, - [](std::string_view line) -> std::uint64_t { - const game g(line); + return std::transform_reduce(range.begin(), range.end(), 0u, std::plus{}, + [](std::string_view line) -> std::uint64_t { + const game g(line); - const auto p = static_cast(g.max.red * g.max.green * g.max.blue); - xlog::debug("Power value is {} for {}", p, g); - return p; - }); + const auto p = static_cast( + g.max.red * g.max.green * g.max.blue); + xlog::debug("Power value is {} for {}", p, g); + return p; + }); } diff --git a/2023/solvelib/05/day05.cpp b/2023/solvelib/05/day05.cpp index c6ad834..b33dbf3 100644 --- a/2023/solvelib/05/day05.cpp +++ b/2023/solvelib/05/day05.cpp @@ -2,6 +2,7 @@ #include "xmaslib/line_iterator/line_iterator.hpp" #include "xmaslib/log/log.hpp" +#include "xmaslib/parsing/parsing.hpp" #include #include @@ -16,36 +17,6 @@ namespace { -// parse_ints parses a list of integers inbetween other characters -// "534 [534, 13213, 5343] -std::vector parse_ints(std::string_view str) { - std::vector out; - - std::uint64_t n = 0; // Current value of number - bool parsing = false; // Are we parsing a number? - - for (auto ch : str) { - if (ch >= '0' && ch <= '9') { - parsing = true; - n = 10 * n + std::uint64_t(ch - '0'); - continue; - } - - if (parsing) { - out.push_back(n); - } - - n = 0; - parsing = false; - } - - if (parsing) { - out.push_back(n); - } - - return out; -} - // Parses the first line of the almanac into a list of ints std::vector parse_seeds(std::string_view first_line) { auto it = std::find(first_line.cbegin(), first_line.cend(), ':'); @@ -53,7 +24,7 @@ std::vector parse_seeds(std::string_view first_line) { throw std::runtime_error("first line contains no ':'"); } - return parse_ints({it + 1, first_line.cend()}); + return xmas::parse_ints({it + 1, first_line.cend()}); } // A mapping is a source->destination (len) triplet. @@ -197,15 +168,16 @@ struct layer { // // return.first: The layer that was parsed // return.second: An iterator pointing to the beginning of the next section -std::pair parse_layer(xmas::line_iterator begin, - xmas::line_iterator end) { +std::pair +parse_layer(xmas::views::linewise::iterator begin, + xmas::views::linewise::iterator end) { layer l; auto it = begin; // Skip title ++it; for (; it != end; ++it) { - auto ints = parse_ints(*it); + auto ints = xmas::parse_ints(*it); if (auto size = ints.size(); size == 0) { // End of section: skip empty line and leave ++it; @@ -268,7 +240,7 @@ void extend(std::vector &dst, std::vector const &src) { std::uint64_t Day05::part1() { // Parsing - auto rng = xmas::line_range(this->input); + auto rng = xmas::views::linewise(this->input); auto iline = rng.begin(); // Parse header @@ -306,7 +278,7 @@ std::uint64_t Day05::part1() { std::uint64_t Day05::part2() { // Parsing - auto rng = xmas::line_range(this->input); + auto rng = xmas::views::linewise(this->input); auto iline = rng.begin(); // Parse header diff --git a/2023/solvelib/12/day12.cpp b/2023/solvelib/12/day12.cpp new file mode 100644 index 0000000..07f1860 --- /dev/null +++ b/2023/solvelib/12/day12.cpp @@ -0,0 +1,387 @@ +#include "day12.hpp" + +#include "xmaslib/functional/functional.hpp" +#include "xmaslib/iota/iota.hpp" +#include "xmaslib/lazy_string/lazy_string.hpp" +#include "xmaslib/line_iterator/line_iterator.hpp" +#include "xmaslib/log/log.hpp" +#include "xmaslib/lru/lru.hpp" +#include "xmaslib/parsing/parsing.hpp" +#include "xmaslib/view/view.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +enum class cell : char { unknown = '?', set = '#', empty = '.' }; + +auto parse_line(std::string_view line) { + auto separator = std::ranges::find(line, ' '); + if (separator == line.end()) { + throw std::runtime_error(std::format("Line '%s' has no separator", line)); + } + + // Cheeky fast copy (only works because cells are a typedef'd char) + auto const size = static_cast(separator - line.begin()); + std::vector cells(size); + ::memcpy(cells.data(), line.data(), size); + + // Numbers + auto ranges = xmas::parse_ints({separator + 1, line.cend()}); + + return std::make_pair(cells, ranges); +} + +std::tuple trim(auto cells_base, + auto ranges_base) { + auto cells = xmas::view{cells_base.begin(), cells_base.end()}; + auto ranges = xmas::view{ranges_base.begin(), ranges_base.end()}; + + while (true) { + if (ranges.size() == 0) { + break; + } + + // Trim whitespace (..XXX,) -> (XXX,) + auto begin = std::ranges::find_if_not(cells, xmas::equals(cell::empty)); + cells.pop_front(begin - cells.begin()); + + if (cells.size() == 0) { + // Nothing left to trim + return {{}, {}, ranges.size() == 0}; + } + + if (cells.front() == cell::unknown) { + // No more trimming possible + break; + } + + if (static_cast(ranges.front()) > cells.size()) { + // Bad! Next range does not fit + return {{}, {}, false}; + } + + // Trimming prefixed ### + auto it = + std::find_if_not(cells.begin(), cells.end(), xmas::equals(cell::set)); + + auto const prefix_size = it - cells.begin(); + if (prefix_size > ranges.front()) { + // Bad! the prefix is longer than the range + return {{}, {}, false}; + } + + // The prefix is the entire string + if (it == cells.end()) { + if (ranges.front() != prefix_size) { + // Bad! the prefix does not match the range + return {{}, {}, false}; + } + + if (ranges.size() > 1) { + // Bad! Leftover ranges with no more cells + return {{}, {}, false}; + } + + cells.pop_front(cells.size()); + ranges.pop_front(); + break; + } + + // The prefix is followed by a . + if (*it == cell::empty) { + if (ranges.front() != prefix_size) { + // Bad! the prefix does not match the range + return {{}, {}, false}; + } + + cells.pop_front(prefix_size + 1); // +1 for the . + ranges.pop_front(); + continue; + } + + // The prefix is followed by ? + if (prefix_size == ranges.front()) { + // The prefix matches the range exactly + cells.pop_front(prefix_size + 1); // +1 because the next ? must be a . + ranges.pop_front(); + continue; + } + + // The prefix is shorter than the range: force ? into # to match the + // expected range + auto rng = cells.take(ranges.front()); + it = std::ranges::find(rng, cell::empty); + auto const prefixable_size = it - rng.begin(); + + if (it != rng.end()) { + // Bad! Range does not fit + return {{}, {}, false}; + } + + // Entire string is prefixable + if (it == cells.end()) { + if (ranges.size() != 1) { + // Bad! Leftover ranges with no more cells + return {{}, {}, false}; + } + + cells.pop_front(cells.size()); + ranges.pop_front(); + break; + } + + if (*it == cell::set) { + // Bad! collision with next range + return {{}, {}, false}; + } + + cells.pop_front(prefixable_size + + 1); // +1 because next . or ? is forced into . + ranges.pop_front(); + } + + return {cells_base.size() - cells.size(), ranges_base.size() - ranges.size(), + true}; +} + +auto stringify_line(auto const &cells, auto const &ranges) { + return xmas::lazy_string{[=]() { + std::stringstream ss; + ss << std::string_view{reinterpret_cast(&cells.front()), + cells.size()}; + ss << " "; + if (ranges.size() == 0) { + return ss.str(); + } + for (int x : ranges) { + ss << x << ","; + } + auto s = std::move(ss).str(); + s.pop_back(); // trailing comma + return s; + }}; +} + +auto trim_left(xmas::view::const_iterator> cells, + xmas::view::const_iterator> ranges) { + auto const [ctrim, rtrim, ok] = trim(cells, ranges); + cells.pop_front(ctrim); + ranges.pop_front(rtrim); + + return std::make_tuple(std::move(cells), std::move(ranges), ok); +} + +auto trim_right(xmas::view::const_iterator> cells, + xmas::view::const_iterator> ranges) { + + auto const [ctrim, rtrim, ok] = trim(std::ranges::views::reverse(cells), + std::ranges::views::reverse(ranges)); + cells.pop_back(ctrim); + ranges.pop_back(rtrim); + + return std::make_tuple(std::move(cells), std::move(ranges), ok); +} + +bool contains(xmas::view::const_iterator> v, cell c) { + auto it = std::find(v.begin(), v.end(), c); + return it != v.end(); +} + +struct state { + xmas::view::const_iterator> cells; + xmas::view::const_iterator> ranges; + + bool operator==(state const &other) const noexcept { + return (&*cells.begin() == &*other.cells.begin()) && + (cells.size() == other.cells.size()) && + (&*ranges.begin() == &*other.ranges.begin()) && + (cells.size() == other.cells.size()); + } + + std::size_t hash() const noexcept { + static_assert(sizeof(std::size_t) >= 8); + auto h1 = hash16bit(&*cells.begin()); + auto h2 = hash16bit(&*cells.end()); + auto h3 = hash16bit(&*ranges.begin()); + auto h4 = hash16bit(&*ranges.end()); + return h1 << 48 | h2 << 32 | h3 << 16 | h4; // or use boost::hash_combine + } + +private: + static std::size_t hash16bit(auto const *p) { + return std::hash{}(reinterpret_cast(p)) & + 0xffff; + } +}; + +} // namespace + +template <> struct std::hash { + + std::size_t operator()(const state &s) const noexcept { return s.hash(); } +}; + +namespace { + +[[nodiscard]] std::uint64_t +count_combinations(xmas::lru_cache &lru, + xmas::view::const_iterator> cells_base, + xmas::view::const_iterator> ranges_base) { + + if (auto opt = lru.get({cells_base, ranges_base}); opt.has_value()) { + return *opt; + } + + const auto result = [&]() -> std::uint64_t { + // Deterministic progress + // + // We consume # and . from left to write + auto [cells, ranges, ok] = trim_left(cells_base, ranges_base); + if (!ok) { + return 0; + } + + if (ranges.size() == 0) { + if (contains(cells, cell::set)) { + return 0; + } + return 1; + } + + const auto leftover = + static_cast(std::reduce(ranges.begin(), ranges.end())) + + ranges.size() - 1; + if (cells.size() < leftover) { + return 0; + } + + // Speculative progress + // + // We try to force ? into # and . and see if it breaks + auto pound = std::ranges::find(cells, cell::set); + auto size = std::min(1 + cells.size() - static_cast(leftover), + 1 + static_cast(pound - cells.begin())); + + const auto L = static_cast(ranges.front()); + xmas::views::iota iota(size); + return std::transform_reduce( + iota.begin(), iota.end(), std::uint64_t{0u}, std::plus{}, + [&lru, cells, ranges, L](std::size_t idx) -> std::uint64_t { + if (cells[idx] == cell::empty) { + return 0; + } + + if (idx != 0 && cells[idx - 1] == cell::set) { + // Collision with prev block + return 0; + } + + auto v = cells.drop(idx); + + auto prefix = v.take(L); + auto it = std::ranges::find(prefix, cell::empty); + if (it != prefix.end()) { + // Range does not fit + return 0; + } + + if (it != v.end() && *it == cell::set) { + // Collision with next block + return 0; + } + + if (ranges.size() == 1) { + // End of sequence + if (contains(v.drop(ranges.front()), cell::set)) { + return 0; + } + return 1; + } + + auto x = count_combinations(lru, v.drop(L + 1), ranges.drop(1)); + return x; + }); + }(); + + lru.set(state{cells_base, ranges_base}, result); + return result; +} + +template +std::uint64_t process_line(std::string_view line) { + auto [cells_base, ranges_base] = parse_line(line); + if (ranges_base.size() == 0) { + return 1; + } + + if constexpr (quintuple) { + auto cells0 = cells_base; + auto ranges0 = ranges_base; + + cells_base.reserve(cells_base.size() * 5 + 4); + ranges_base.reserve(ranges_base.size() * 5); + + for (std::size_t i = 0; i < 4; ++i) { + cells_base.push_back(cell::unknown); + std::copy(cells0.begin(), cells0.end(), std::back_inserter(cells_base)); + std::copy(ranges0.begin(), ranges0.end(), + std::back_inserter(ranges_base)); + } + } + + // Trim right. Left trim is done inside count_combinations + auto [cells, ranges, ok] = + trim_right(xmas::view{cells_base.cbegin(), cells_base.cend()}, + xmas::view{ranges_base.cbegin(), ranges_base.cend()}); + + if (!ok) { + xlog::warning("No combinations possible for line {} (error from the right)", + line); + return 0; + } + + xmas::lru_cache lru(128); + + const auto x = count_combinations(lru, cells, ranges); + if (x == 0) { + xlog::warning("No combinations possible for line {} (error from the left)", + line); + } else { + xlog::debug("{} -> ({}) -> {}", line, stringify_line(cells, ranges), x); + } + + return x; +} + +} // namespace + +std::uint64_t Day12::part1() { + auto in = xmas::views::linewise(this->input); + + return std::transform_reduce(std::execution::par_unseq, in.cbegin(), + in.cend(), std::uint64_t(0u), + std::plus{}, process_line); +} + +std::uint64_t Day12::part2() { + auto in = xmas::views::linewise(this->input); + + return std::transform_reduce(std::execution::par_unseq, in.cbegin(), + in.cend(), std::uint64_t(0u), + std::plus{}, process_line); +} \ No newline at end of file diff --git a/2023/solvelib/12/day12.hpp b/2023/solvelib/12/day12.hpp new file mode 100644 index 0000000..31b69b5 --- /dev/null +++ b/2023/solvelib/12/day12.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "xmaslib/solution/solution.hpp" + +class Day12 : public xmas::solution { +public: + int day() override { return 12; } + +public: + std::uint64_t part1() override; + std::uint64_t part2() override; +}; diff --git a/2023/solvelib/12/day12_test.hpp b/2023/solvelib/12/day12_test.hpp new file mode 100644 index 0000000..ee561d5 --- /dev/null +++ b/2023/solvelib/12/day12_test.hpp @@ -0,0 +1,161 @@ +#include "day12.hpp" +#include + +TEST_CASE("Day 12") { + + SUBCASE("Part 1, example 1") { + Day12 solution{}; + solution.set_input("./data/12/example1.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 4); + } + + SUBCASE("Part 1, example 2") { + Day12 solution{}; + solution.set_input("./data/12/example2.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 1); + } + + SUBCASE("Part 1, example 3") { + Day12 solution{}; + solution.set_input("./data/12/example3.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 10); + } + + SUBCASE("Part 1, example 4") { + Day12 solution{}; + solution.set_input("./data/12/example4.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 1); + } + + SUBCASE("Part 1, example 5") { + Day12 solution{}; + solution.set_input("./data/12/example5.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 4); + } + + SUBCASE("Part 1, example 6") { + Day12 solution{}; + solution.set_input("./data/12/example6.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 21); + } + + SUBCASE("Part 1, example 7") { + Day12 solution{}; + solution.set_input("./data/12/example7.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 1); + } + + SUBCASE("Part 1, example 8") { + Day12 solution{}; + solution.set_input("./data/12/example8.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 10); + } + + SUBCASE("Part 1, example 9") { + Day12 solution{}; + solution.set_input("./data/12/example9.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 3); + } + + SUBCASE("Part 1, example 10") { + Day12 solution{}; + solution.set_input("./data/12/example10.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 2); + } + + SUBCASE("Part 1, example 11") { + Day12 solution{}; + solution.set_input("./data/12/example11.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 2); + } + + SUBCASE("Part 1, example 12") { + Day12 solution{}; + solution.set_input("./data/12/example12.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 3); + } + + SUBCASE("Part 1, example 13") { + Day12 solution{}; + solution.set_input("./data/12/example13.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 2); + } + + SUBCASE("Part 1, example 14") { + Day12 solution{}; + solution.set_input("./data/12/example14.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 3); + } + + SUBCASE("Part 1, example 15") { + Day12 solution{}; + solution.set_input("./data/12/example15.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 4); + } + + SUBCASE("Part 2, example 1") { + Day12 solution{}; + solution.set_input("./data/12/example1.txt"); + solution.load(); + REQUIRE_EQ(solution.part2(), 16384); + } + + SUBCASE("Part 2, example 2") { + Day12 solution{}; + solution.set_input("./data/12/example2.txt"); + solution.load(); + REQUIRE_EQ(solution.part2(), 1); + } + + SUBCASE("Part 2, example 3") { + Day12 solution{}; + solution.set_input("./data/12/example3.txt"); + solution.load(); + REQUIRE_EQ(solution.part2(), 506250); + } + + SUBCASE("Part 2, example 4") { + Day12 solution{}; + solution.set_input("./data/12/example4.txt"); + solution.load(); + REQUIRE_EQ(solution.part2(), 1); + } + + SUBCASE("Part 2, example 6") { + Day12 solution{}; + solution.set_input("./data/12/example6.txt"); + solution.load(); + REQUIRE_EQ(solution.part2(), 525152); + } + + SUBCASE("Part 2, example 15") { + Day12 solution{}; + solution.set_input("./data/12/example15.txt"); + solution.load(); + REQUIRE_EQ(solution.part2(), 5184); + } + + SUBCASE("Real data") { + Day12 solution{}; + solution.set_input("./data/12/input.txt"); + solution.load(); + REQUIRE_EQ(solution.part1(), 7653); + REQUIRE_GT(solution.part2(), 2121046676); + REQUIRE_GT(solution.part2(), 75135490708); + } +} \ No newline at end of file diff --git a/2023/solvelib/CMakeLists.txt b/2023/solvelib/CMakeLists.txt index 65227c3..83f7db5 100644 --- a/2023/solvelib/CMakeLists.txt +++ b/2023/solvelib/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(solvelib 03/day03.hpp 03/day03.cpp 03/day03_test.hpp 04/day04.hpp 04/day04.cpp 04/day04_test.hpp 05/day05.hpp 05/day05.cpp 05/day05_test.hpp + 12/day12.hpp 12/day12.cpp 12/day12_test.hpp ) set_target_properties(solvelib PROPERTIES LINKER_LANGUAGE CXX) diff --git a/2023/solvelib/alldays.hpp b/2023/solvelib/alldays.hpp index e1eb472..beae6b6 100644 --- a/2023/solvelib/alldays.hpp +++ b/2023/solvelib/alldays.hpp @@ -7,6 +7,7 @@ #include "03/day03.hpp" #include "04/day04.hpp" #include "05/day05.hpp" +#include "12/day12.hpp" inline void populate_registry() { xmas::register_solution(); @@ -14,4 +15,5 @@ inline void populate_registry() { xmas::register_solution(); xmas::register_solution(); xmas::register_solution(); + xmas::register_solution(); } diff --git a/2023/test/test.cpp b/2023/test/test.cpp index f23f974..07d04ff 100644 --- a/2023/test/test.cpp +++ b/2023/test/test.cpp @@ -6,5 +6,7 @@ #include "solvelib/03/day03_test.hpp" #include "solvelib/04/day04_test.hpp" #include "solvelib/05/day05_test.hpp" +#include "solvelib/12/day12_test.hpp" #include "xmaslib/iota/iota_test.hpp" +#include "xmaslib/lru/lru_test.hpp" diff --git a/2023/xmaslib/functional/functional.hpp b/2023/xmaslib/functional/functional.hpp new file mode 100644 index 0000000..fb3d91a --- /dev/null +++ b/2023/xmaslib/functional/functional.hpp @@ -0,0 +1,13 @@ +namespace xmas { + +template class equals { +public: + explicit constexpr equals(T value) : value(value) {} + + constexpr bool operator()(T const &other) const { return value == other; } + +private: + T value; +}; + +} // namespace xmas \ No newline at end of file diff --git a/2023/xmaslib/iota/iota.hpp b/2023/xmaslib/iota/iota.hpp index b75b06c..825f7a0 100644 --- a/2023/xmaslib/iota/iota.hpp +++ b/2023/xmaslib/iota/iota.hpp @@ -16,9 +16,19 @@ template class iota { public: class iterator; + using size_type = std::size_t; + constexpr iota(T begin, T end) : m_begin(begin), m_end(end) { - assert(begin <= end); +#ifndef NDEBUG + if (begin > end) { + throw std::runtime_error(std::format( + "xmas::views::iota::iota begin (which is {}) >= end (which is {})", + begin, end)); + } + +#endif } + constexpr iota(T end) : iota(0, end) {} constexpr iota() : iota(0, std::numeric_limits::max()) {} @@ -28,31 +38,49 @@ template class iota { constexpr iterator cbegin() const noexcept { return iterator(m_begin); } constexpr iterator cend() const noexcept { return iterator(m_end); } - constexpr std::size_t size() const noexcept { - return safe_cast(m_end - m_begin); + constexpr size_type size() const noexcept { + return safe_cast(m_end - m_begin); } constexpr T front() const noexcept { return m_begin; } constexpr T back() const noexcept { return m_end - 1; } - constexpr T operator[](std::size_t index) const noexcept { + constexpr T operator[](std::integral auto index) const noexcept { #ifndef NDEBUG range_check(index); #endif - return safe_cast(m_begin + safe_cast(index)); + return safe_cast(safe_cast(m_begin) + + safe_cast(index)); } - constexpr T at(std::size_t index) const { - range_check(index); - return safe_cast(m_begin + safe_cast(index)); + constexpr T at(size_type index) const { + range_check(index); + return safe_cast(m_begin + index); } private: - constexpr void range_check(std::size_t index) const { + template + constexpr void range_check([[maybe_unused]] size_type index) const { +#ifndef NDEBUG + constexpr bool is_debug = true; +#else + constexpr bool is_debug = false; +#endif + if constexpr (debug_only && !is_debug) { + return; + } + + if (static_cast(index) < 0) { + throw std::runtime_error( + std::format("xmas::views::iota::range_check: index (which is {}) " + "< 0", + index)); + } + if (index >= size()) { throw std::runtime_error( - std::format("xmas::views::iota::range_check: index (which is %zu) " - ">= this->size() (which is %zu)", + std::format("xmas::views::iota::range_check: index (which is {}) " + ">= this->size() (which is {})", index, this->size())); } } @@ -83,7 +111,7 @@ template class iota { } constexpr iterator operator++(int) noexcept { - auto it = iterator{v + 1}; + auto it = iterator{v}; ++*this; return it; } @@ -132,8 +160,8 @@ template class iota { [[nodiscard]] constexpr value_type operator*() const noexcept { return v; } [[nodiscard]] constexpr value_type - operator[](std::size_t index) const noexcept { - return safe_cast(v + safe_cast(index)); + operator[](size_type index) const noexcept { + return safe_cast(v + index); } private: diff --git a/2023/xmaslib/lazy_string/lazy_string.hpp b/2023/xmaslib/lazy_string/lazy_string.hpp new file mode 100644 index 0000000..59313f0 --- /dev/null +++ b/2023/xmaslib/lazy_string/lazy_string.hpp @@ -0,0 +1,16 @@ +#include +#include +#include + +namespace xmas { +struct lazy_string { + std::function generate; +}; + +} // namespace xmas + +template <> struct std::formatter : std::formatter { + auto format(xmas::lazy_string const &s, format_context &ctx) const { + return formatter::format(s.generate(), ctx); + } +}; \ No newline at end of file diff --git a/2023/xmaslib/line_iterator/line_iterator.hpp b/2023/xmaslib/line_iterator/line_iterator.hpp index a50d797..a48b260 100644 --- a/2023/xmaslib/line_iterator/line_iterator.hpp +++ b/2023/xmaslib/line_iterator/line_iterator.hpp @@ -4,70 +4,70 @@ #include namespace xmas { +namespace views { -struct line_iterator { - using iterator_category = std::forward_iterator_tag; - using difference_type = std::ptrdiff_t; - using value_type = std::string_view; - using pointer = value_type *; - using reference = value_type &; +struct linewise { + class iterator; - static auto begin(std::string_view str) { - auto it = line_iterator(str.begin(), str.end()); - it.advance_endl(); - return it; - } + linewise(std::string_view ss) : view{ss} {} - static auto end(std::string_view str) { - return line_iterator(str.end(), str.end()); - } + iterator cbegin() const { return {view.begin(), view.end()}; } + iterator cend() const { return {view.end(), view.end()}; } - bool operator==(line_iterator const &other) { - return this->start == other.start; - } + auto begin() const { return cbegin(); } + auto end() const { return cend(); } - bool operator!=(line_iterator const &other) { return !(*this == other); } +private: + std::string_view view; - line_iterator operator++() { - start = endl; - if (start == endtext) { - return *this; - } +public: + class iterator { + friend linewise; - ++start; - advance_endl(); + public: + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = std::string_view; + using pointer = value_type *; + using reference = value_type &; - return *this; - } + bool operator==(iterator const &other) { + return this->start == other.start; + } - value_type operator*() const { return {start, endl}; } + bool operator!=(iterator const &other) { return !(*this == other); } -private: - using base = std::string_view::iterator; + iterator operator++() { + start = endl; + if (start == endtext) { + return *this; + } + + ++start; + advance_endl(); - void advance_endl() { - this->endl = - std::find(std::execution::unseq, this->start, this->endtext, '\n'); - } + return *this; + } - line_iterator(base start, base end) - : start(start), endl(start), endtext(end) { - advance_endl(); - } + value_type operator*() const { return {start, endl}; } - base start; - base endl; - base endtext; -}; + private: + using base = std::string_view::iterator; -struct line_range { - line_range(std::string_view ss) : view{ss} {} + void advance_endl() { + this->endl = + std::find(std::execution::unseq, this->start, this->endtext, '\n'); + } - auto begin() const { return line_iterator::begin(view); } - auto end() const { return line_iterator::end(view); } + iterator(base start, base end) : start(start), endl(start), endtext(end) { + advance_endl(); + } -private: - std::string_view view; + base start; + base endl; + base endtext; + }; }; +} // namespace views } // namespace xmas \ No newline at end of file diff --git a/2023/xmaslib/log/log.hpp b/2023/xmaslib/log/log.hpp index 96183fe..8790ddc 100644 --- a/2023/xmaslib/log/log.hpp +++ b/2023/xmaslib/log/log.hpp @@ -1,3 +1,5 @@ +#pragma once + #include namespace xlog { diff --git a/2023/xmaslib/lru/lru.hpp b/2023/xmaslib/lru/lru.hpp new file mode 100644 index 0000000..eb995c5 --- /dev/null +++ b/2023/xmaslib/lru/lru.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include +#include +#include +#include + +namespace xmas { + +template class lru_cache { +public: + lru_cache(std::size_t max_size) : max_size(max_size), by_key(max_size) {} + + [[nodiscard]] std::optional get(K const &k) const { + if (auto it = by_key.find(k); it != by_key.end()) { + return {data[it->second].value}; + } + + return {}; + } + + void set(K const &k, V const &v) { + if (auto it = by_key.find(k); it != by_key.end()) { + update(it->second, v); + return; + } + + add_new(k, v); + } + +private: + auto heap_comp() { + return [this](std::size_t i, std::size_t j) { + return data[i].time_stamp > data[j].time_stamp; + }; + } + + void add_new(K const &key, V const &value) { + if (data.size() < max_size) { + data.push_back(entry{.time_stamp = t++, .key = key, .value = value}); + by_age.push_back(data.size() - 1); + by_key[key] = data.size() - 1; + return; + } + + std::pop_heap(by_age.begin(), by_age.end(), heap_comp()); + std::size_t reuse_index = by_age.back(); + by_key.erase(data[reuse_index].key); + + data[reuse_index] = entry{ + .time_stamp = t++, + .key = key, + .value = value, + }; + + by_key[key] = reuse_index; + std::push_heap(by_age.begin(), by_age.end(), heap_comp()); + } + + void update(std::size_t idx, V const &value) { + data[idx].time_stamp = t++; + data[idx].value = value; + + std::make_heap(by_age.begin(), by_age.end(), heap_comp()); + return; + } + + std::size_t t = 0; + std::size_t max_size; + + using time_point = std::size_t; + struct entry { + time_point time_stamp; + K key; + V value; + }; + + std::unordered_map by_key; + std::vector by_age; + std::vector data; +}; + +} // namespace xmas \ No newline at end of file diff --git a/2023/xmaslib/lru/lru_test.hpp b/2023/xmaslib/lru/lru_test.hpp new file mode 100644 index 0000000..7b36fb7 --- /dev/null +++ b/2023/xmaslib/lru/lru_test.hpp @@ -0,0 +1,60 @@ +#include + +#include "lru.hpp" + +TEST_CASE("LRU cache") { + xmas::lru_cache cache(3); + + REQUIRE_FALSE(cache.get(15).has_value()); + + cache.set(1, 1000); + + auto opt = cache.get(1); + REQUIRE(opt.has_value()); + REQUIRE_EQ(*opt, 1000); + + cache.set(2, 2000); + + opt = cache.get(1); + REQUIRE(opt.has_value()); + REQUIRE_EQ(*opt, 1000); + opt = cache.get(2); + REQUIRE(opt.has_value()); + REQUIRE_EQ(*opt, 2000); + + cache.set(3, 3000); + + opt = cache.get(1); + REQUIRE(opt.has_value()); + REQUIRE_EQ(*opt, 1000); + opt = cache.get(2); + REQUIRE(opt.has_value()); + REQUIRE_EQ(*opt, 2000); + opt = cache.get(3); + REQUIRE(opt.has_value()); + REQUIRE_EQ(*opt, 3000); + + // Pushing it beyond its max capacity + + cache.set(4, 4000); + + // Old entry no loner exists + opt = cache.get(1); + REQUIRE_FALSE(opt.has_value()); + + opt = cache.get(2); + REQUIRE(opt.has_value()); + REQUIRE_EQ(*opt, 2000); + opt = cache.get(3); + REQUIRE(opt.has_value()); + REQUIRE_EQ(*opt, 3000); + opt = cache.get(4); + REQUIRE(opt.has_value()); + REQUIRE_EQ(*opt, 4000); + + // Override a key + cache.set(3, 3500); + opt = cache.get(3); + REQUIRE(opt.has_value()); + REQUIRE_EQ(*opt, 3500); +} \ No newline at end of file diff --git a/2023/xmaslib/parsing/parsing.hpp b/2023/xmaslib/parsing/parsing.hpp new file mode 100644 index 0000000..4b6a01c --- /dev/null +++ b/2023/xmaslib/parsing/parsing.hpp @@ -0,0 +1,39 @@ +#include +#include + +namespace xmas { + +// parse_ints parses a list of integers inbetween other characters +// "534 [534, 13213, 5343] +template +[[nodiscard]] std::vector parse_ints(std::string_view str) { + std::vector out; + out.reserve(str.size()); + + T n = 0; // Current value of number + bool parsing = false; // Are we parsing a number? + + for (auto ch : str) { + if (ch >= '0' && ch <= '9') { + parsing = true; + n = 10 * n + T(ch - '0'); + continue; + } + + if (parsing) { + out.push_back(n); + } + + n = 0; + parsing = false; + } + + if (parsing) { + out.push_back(n); + } + + out.shrink_to_fit(); + return out; +} + +} // namespace xmas \ No newline at end of file diff --git a/2023/xmaslib/view/view.hpp b/2023/xmaslib/view/view.hpp new file mode 100644 index 0000000..eacbc19 --- /dev/null +++ b/2023/xmaslib/view/view.hpp @@ -0,0 +1,71 @@ +#pragma once +#include +#include + +#include + +namespace xmas { + +template class view { + It m_begin, m_end; + +public: + view(It begin, It end) : m_begin(begin), m_end(end) {} + + auto begin() const { return m_begin; } + auto end() const { return m_end; } + + auto &front() const { return *m_begin; } + auto size() const { return static_cast(m_end - m_begin); } + + template void pop_front(N n = 1) { + check_bounds(n, __PRETTY_FUNCTION__); + m_begin += static_cast(n); + } + + template void pop_back(N n = 1) { + check_bounds(n, __PRETTY_FUNCTION__); + m_end -= static_cast(n); + } + + template + [[nodiscard]] view subview(N begin, N end) const { + return view{m_begin + static_cast(begin), + m_begin + static_cast(end)}; + } + + template + [[nodiscard]] view take(N n) const { + check_bounds(n, __PRETTY_FUNCTION__); + return view{m_begin, m_begin + static_cast(n)}; + } + + template + [[nodiscard]] view drop(N n) const { + check_bounds(n, __PRETTY_FUNCTION__); + return view{m_begin + static_cast(n), m_end}; + } + + template + [[nodiscard]] auto &operator[](N n) const { + check_bounds(n, __PRETTY_FUNCTION__); + return *(m_begin + static_cast(n)); + } + +private: + void check_bounds([[maybe_unused]] std::integral auto n, + [[maybe_unused]] std::string_view funcname) const { +#ifndef NDEBUG + if (n < 0) { + throw std::runtime_error( + std::format("{}: index (which is {}) < 0", funcname, n)); + } + if (static_cast(n) > size()) { + throw std::runtime_error( + std::format("{}: index (which is {}) > this->size() (which is {})", + funcname, n, this->size())); + } +#endif + } +}; +} // namespace xmas \ No newline at end of file