Compare commits

..

47 Commits

Author SHA1 Message Date
ad6a39e82a move env.h -> scripts/ 2023-12-29 18:37:52 +01:00
3a857e4d53 2022 day 16 (C): use same eval() for parts 1 & 2. 2023-04-20 08:31:16 +02:00
f80a051177 2022 day 17 init 2023-04-19 14:09:42 +02:00
129fa07787 2022 day 16: Part 2, sooo slooowww (6m40s) 2023-04-18 17:12:41 +02:00
1472082c86 2022 day 16 part 1 (C) - before cleaning useless permutation code 2023-04-11 09:42:58 +02:00
e8bed49e13 2022 day 16 (C): first parse and helper functions 2023-04-09 12:00:41 +02:00
83d70dcc7a 2022: update (C) notices 2023-04-09 11:59:26 +02:00
56d2e63fac 2022 day 15 (C): remove hash for part 1, simplify code 2023-04-03 18:15:37 +02:00
5c91de5d40 2022 day 15: final version (C) 2023-04-02 20:57:44 +02:00
40a9c7b12e 2022 day 15 part 2: improved solution (20,000 times faster) 2023-04-02 19:50:00 +02:00
34b6cd7b57 2022 day 15 part 2 (C). First version: 18s, ~30,000,000 func calls 2023-04-02 19:45:55 +02:00
5ad5c87fd8 2022: init day 16 2023-04-01 13:54:28 +02:00
11e7b45676 2022 day 15: start part 2 data structure 2023-03-30 10:38:03 +02:00
3f2a5648df debug: add debug_level_get() 2023-03-25 13:32:03 +01:00
0a3b404c4c 2022 day 15: part 2 (C) 2023-03-25 13:31:40 +01:00
a214d2b70d common C code: add "-t" option for test mode. 2023-03-22 08:43:46 +01:00
f490c2353e 2022 day 15 (C) part 1 (dirty and even more) 2023-03-21 11:17:04 +01:00
2ed6284bcd 2022 day 15 init 2023-03-18 17:50:59 +01:00
5fc204744a 2022 day 14 (C): final version. Too hacky for me... 2023-03-18 17:30:26 +01:00
d1cf8d96b8 2022 day 14, parts 1 & 2, before cleaning 2023-03-18 16:35:08 +01:00
b285f74997 2022 day 14: init 2023-01-20 20:25:55 +01:00
c949c64da2 day 22 day 13 (C) simplify/comment code 2023-01-12 10:34:32 +01:00
357e8ce087 fix wrong org conversion (brackets become links in code blocks) 2023-01-11 20:16:51 +01:00
5cde9051ec 2022 day 13 (C) final version - more cleanup needed 2023-01-10 22:14:59 +01:00
111fde4fbd 2022 day 13 (C) before cleaning 2023-01-10 22:00:55 +01:00
f54479189b 2022 day 13 part 1 (C) 2023-01-07 18:17:02 +01:00
8e00fec33c PJW hash: add credits 2023-01-07 18:16:18 +01:00
d0376f21c3 2022 day 12 (C, parts 1 & 2) 2022-12-24 21:06:10 +01:00
04a856dc47 Makefile: clean keeps compile_commands.json 2022-12-24 21:05:33 +01:00
0658ffdd7d 2022 day 13 init 2022-12-23 11:41:30 +01:00
efe0dec8f0 2022 day 12 Bash final version 2022-12-22 21:38:26 +01:00
6d4a8dd85b Bash 2022 day 12 (parts 1 & 2), before cleaning code 2022-12-22 21:33:29 +01:00
11cb3c5c64 2022 day 11 final (C) 2022-12-21 15:46:07 +01:00
7e0a21704e 2022 day 11: C first version (parts 1 and 2) 2022-12-21 13:34:28 +01:00
008599e79c 2022 day 11, Bash speedup (40-50%) 2022-12-20 17:29:47 +01:00
fe381ae7f0 Bash: 2022 day 11. Part 2 is ~29 secs 2022-12-20 15:03:42 +01:00
4a0749999e 2022 day 11: Bash parts 1 & 2, before cleaning 2022-12-20 14:47:29 +01:00
18720b9e09 2022 day 10: C, parts 1 and 2. Should be useful if this "machine"...
... comes back in next days puzzles (my guess is that it will ;-)
2022-12-18 14:33:45 +01:00
17e140f235 br.h: add __unused and __used macros 2022-12-18 14:22:18 +01:00
a1e436babc C: remove dead code in 2022/day 9 2022-12-17 18:50:10 +01:00
02a1dda786 2022 day 10: Bash parts 1 & 2 2022-12-17 16:05:49 +01:00
ef29ca28a1 2022: init day 10 2022-12-17 12:25:11 +01:00
c1b3e83c68 2022 day 9: C parts 1 and 2 2022-12-17 11:28:12 +01:00
bd2548fca9 pjwhash: char* to void* 2022-12-17 11:27:40 +01:00
3f5b282883 2022 day 9 Bash: reduce code by 40%, increase speed by 40% 2022-12-13 19:33:29 +01:00
38ef781f0a 2022 day 9: Bash part 2, same code for both part (slower #1) 2022-12-13 18:38:24 +01:00
13d183de79 2022 day 9, Bash part 1 2022-12-13 16:02:50 +01:00
81 changed files with 8352 additions and 4 deletions

View File

@@ -173,3 +173,145 @@ aoc.bash: res=672280
aoc-c: res=672280
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+91
=========================================
================= day09 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=5619
time: 0:00.69 real, 0.69 user, 0.00 sys
context-switch: 38+1, page-faults: 0+430
aoc-c: res=5619
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+158
+++++++++++++++++ part 2
aoc.bash: res=2376
time: 0:03.25 real, 3.24 user, 0.00 sys
context-switch: 46+1, page-faults: 0+340
aoc-c: res=2376
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+131
=========================================
================= day10 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=13220
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+260
aoc-c: res=13220
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+88
+++++++++++++++++ part 2
aoc.bash: res=
###..#..#..##..#..#.#..#.###..####.#..##
#..#.#..#.#..#.#.#..#..#.#..#.#....#.#..
#..#.#..#.#..#.##...####.###..###..##..#
###..#..#.####.#.#..#..#.#..#.#....#.#.#
#.#..#..#.#..#.#.#..#..#.#..#.#....#.#..
#..#..##..#..#.#..#.#..#.###..####.#..#.
time: 0:00.01 real, 0.00 user, 0.00 sys
context-switch: 3+1, page-faults: 0+262
###..#..#..##..#..#.#..#.###..####.#..##
#..#.#..#.#..#.#.#..#..#.#..#.#....#.#..
#..#.#..#.#..#.##...####.###..###..##..#
###..#..#.####.#.#..#..#.#..#.#....#.#.#
#.#..#..#.#..#.#.#..#..#.#..#.#....#.#..
#..#..##..#..#.#..#.#..#.###..####.#..#.
aoc-c: res=0
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+88
=========================================
================= day11 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=54253
time: 0:00.05 real, 0.04 user, 0.00 sys
context-switch: 1+1, page-faults: 0+268
aoc-c: res=54253
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
+++++++++++++++++ part 2
aoc.bash: res=13119526120
time: 0:16.49 real, 16.48 user, 0.00 sys
context-switch: 106+1, page-faults: 0+270
aoc-c: res=13119526120
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 13+1, page-faults: 0+87
=========================================
================= day12 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=408
time: 0:00.81 real, 0.80 user, 0.00 sys
context-switch: 223+1, page-faults: 0+486
aoc-c: res=408
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+170
+++++++++++++++++ part 2
aoc.bash: res=399
time: 0:00.55 real, 0.54 user, 0.01 sys
context-switch: 25+1, page-faults: 0+460
aoc-c: res=399
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+171
=========================================
================= day13 =================
=========================================
+++++++++++++++++ part 1
aoc-c: res=5843
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+192
+++++++++++++++++ part 2
aoc-c: res=26289
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 1+1, page-faults: 0+190
=========================================
================= day14 =================
=========================================
+++++++++++++++++ part 1
aoc-c: res=665
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+109
+++++++++++++++++ part 2
aoc-c: res=25434
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+121
=========================================
================= day15 =================
=========================================
+++++++++++++++++ part 1
aoc-c: res=5176944
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+152
+++++++++++++++++ part 2
aoc-c: res=13350458933732
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+88

View File

@@ -283,3 +283,465 @@ So, there are =13= positions the tail visited at least once.
Simulate your complete hypothetical series of motions. /How many
positions does the tail of the rope visit at least once?/
Your puzzle answer was =5619=.
** --- Part Two ---
A rope snaps! Suddenly, the river is getting a lot closer than you
remember. The bridge is still there, but some of the ropes that broke
are now whipping toward you as you fall through the air!
The ropes are moving too quickly to grab; you only have a few seconds to
choose how to arch your body to avoid being hit. Fortunately, your
simulation can be extended to support longer ropes.
Rather than two knots, you now must simulate a rope consisting of /ten/
knots. One knot is still the head of the rope and moves according to the
series of motions. Each knot further down the rope follows the knot in
front of it using the same rules as before.
Using the same series of motions as the above example, but with the
knots marked =H=, =1=, =2=, ..., =9=, the motions now occur as follows:
#+begin_example
== Initial State ==
......
......
......
......
H..... (H covers 1, 2, 3, 4, 5, 6, 7, 8, 9, s)
== R 4 ==
......
......
......
......
1H.... (1 covers 2, 3, 4, 5, 6, 7, 8, 9, s)
......
......
......
......
21H... (2 covers 3, 4, 5, 6, 7, 8, 9, s)
......
......
......
......
321H.. (3 covers 4, 5, 6, 7, 8, 9, s)
......
......
......
......
4321H. (4 covers 5, 6, 7, 8, 9, s)
== U 4 ==
......
......
......
....H.
4321.. (4 covers 5, 6, 7, 8, 9, s)
......
......
....H.
.4321.
5..... (5 covers 6, 7, 8, 9, s)
......
....H.
....1.
.432..
5..... (5 covers 6, 7, 8, 9, s)
....H.
....1.
..432.
.5....
6..... (6 covers 7, 8, 9, s)
== L 3 ==
...H..
....1.
..432.
.5....
6..... (6 covers 7, 8, 9, s)
..H1..
...2..
..43..
.5....
6..... (6 covers 7, 8, 9, s)
.H1...
...2..
..43..
.5....
6..... (6 covers 7, 8, 9, s)
== D 1 ==
..1...
.H.2..
..43..
.5....
6..... (6 covers 7, 8, 9, s)
== R 4 ==
..1...
..H2..
..43..
.5....
6..... (6 covers 7, 8, 9, s)
..1...
...H.. (H covers 2)
..43..
.5....
6..... (6 covers 7, 8, 9, s)
......
...1H. (1 covers 2)
..43..
.5....
6..... (6 covers 7, 8, 9, s)
......
...21H
..43..
.5....
6..... (6 covers 7, 8, 9, s)
== D 1 ==
......
...21.
..43.H
.5....
6..... (6 covers 7, 8, 9, s)
== L 5 ==
......
...21.
..43H.
.5....
6..... (6 covers 7, 8, 9, s)
......
...21.
..4H.. (H covers 3)
.5....
6..... (6 covers 7, 8, 9, s)
......
...2..
..H1.. (H covers 4; 1 covers 3)
.5....
6..... (6 covers 7, 8, 9, s)
......
...2..
.H13.. (1 covers 4)
.5....
6..... (6 covers 7, 8, 9, s)
......
......
H123.. (2 covers 4)
.5....
6..... (6 covers 7, 8, 9, s)
== R 2 ==
......
......
.H23.. (H covers 1; 2 covers 4)
.5....
6..... (6 covers 7, 8, 9, s)
......
......
.1H3.. (H covers 2, 4)
.5....
6..... (6 covers 7, 8, 9, s)
#+end_example
Now, you need to keep track of the positions the new tail, =9=, visits.
In this example, the tail never moves, and so it only visits =1=
position. However, /be careful/: more types of motion are possible than
before, so you might want to visually compare your simulated rope to the
one above.
Here's a larger example:
#+begin_example
R 5
U 8
L 8
D 3
R 17
D 10
L 25
U 20
#+end_example
These motions occur as follows (individual steps are not shown):
#+begin_example
== Initial State ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
...........H.............. (H covers 1, 2, 3, 4, 5, 6, 7, 8, 9, s)
..........................
..........................
..........................
..........................
..........................
== R 5 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
...........54321H......... (5 covers 6, 7, 8, 9, s)
..........................
..........................
..........................
..........................
..........................
== U 8 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
................H.........
................1.........
................2.........
................3.........
...............54.........
..............6...........
.............7............
............8.............
...........9.............. (9 covers s)
..........................
..........................
..........................
..........................
..........................
== L 8 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
........H1234.............
............5.............
............6.............
............7.............
............8.............
............9.............
..........................
..........................
...........s..............
..........................
..........................
..........................
..........................
..........................
== D 3 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
.........2345.............
........1...6.............
........H...7.............
............8.............
............9.............
..........................
..........................
...........s..............
..........................
..........................
..........................
..........................
..........................
== R 17 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
................987654321H
..........................
..........................
..........................
..........................
...........s..............
..........................
..........................
..........................
..........................
..........................
== D 10 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
...........s.........98765
.........................4
.........................3
.........................2
.........................1
.........................H
== L 25 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
...........s..............
..........................
..........................
..........................
..........................
H123456789................
== U 20 ==
H.........................
1.........................
2.........................
3.........................
4.........................
5.........................
6.........................
7.........................
8.........................
9.........................
..........................
..........................
..........................
..........................
..........................
...........s..............
..........................
..........................
..........................
..........................
..........................
#+end_example
Now, the tail (=9=) visits =36= positions (including =s=) at least once:
#+begin_example
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
#.........................
#.............###.........
#............#...#........
.#..........#.....#.......
..#..........#.....#......
...#........#.......#.....
....#......s.........#....
.....#..............#.....
......#............#......
.......#..........#.......
........#........#........
.........########.........
#+end_example
Simulate your complete series of motions on a larger rope with ten
knots. /How many positions does the tail of the rope visit at least
once?/
Your puzzle answer was =2376=.
Both parts of this puzzle are complete! They provide two gold stars: **

200
2022/day09/aoc-c.c Normal file
View File

@@ -0,0 +1,200 @@
/* aoc-c.c: Advent of Code 2022, day 9
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "aoc.h"
#include "br.h"
#include "debug.h"
#include "pool.h"
#include "list.h"
#include "hashtable.h"
#include "pjwhash-inline.h"
#define HBITS 12 /* 12 bits: 4096 buckets */
typedef struct pos {
int x;
int y;
} pos_t;
typedef struct visited {
uint hash;
pos_t coord;
short nvisits;
struct hlist_node hlist;
} visited_t;
enum dir {
D = 'D',
L = 'L',
R = 'R',
U = 'U'
};
typedef struct move {
enum dir dir;
int nmoves;
struct list_head list;
} move_t;
DEFINE_HASHTABLE(h_visited, HBITS);
LIST_HEAD(moves);
static pool_t *pool_visited;
static pool_t *pool_move;
/**
* find_visited - find entry in an hashtable bucket
*/
static visited_t *find_visited(struct hlist_head *bucket, uint hash, pos_t *pos)
{
visited_t *cur;
hlist_for_each_entry(cur, bucket, hlist)
if (cur->hash == hash && cur->coord.x == pos->x && cur->coord.y == pos->y)
return cur;
return NULL;
}
static visited_t *add_visited(pos_t *pos, uint hash, uint bucket)
{
visited_t *new = pool_get(pool_visited);
new->hash = hash;
new->coord.x = pos->x;
new->coord.y = pos->y;
hlist_add_head(&new->hlist, &h_visited[bucket]);
return new;
}
static int add_visited_maybe(pos_t *pos)
{
uint hash = pjwhash(pos, sizeof (*pos));
uint bucket = hash_32(hash, HBITS);
if (! find_visited(h_visited + bucket, hash, pos)) {
add_visited(pos, hash, bucket);
return 1;
}
return 0;
}
static int move_tails(pos_t *pos, int ntails)
{
int i;
pos_t *cur, *next;
int didmove = 1;
for (i = 0; i < ntails && didmove; ++i) {
didmove = 0;
pos_t diff;
cur = pos + i;
next = cur + 1;
diff.x = cur->x - next->x;
diff.y = cur->y - next->y;
if (abs(diff.x) > 1 || abs(diff.y) > 1) { /* do move */
if (diff.x)
next->x += diff.x / abs(diff.x);
if (diff.y)
next->y += diff.y / abs(diff.y);
didmove = 1;
}
}
return didmove? add_visited_maybe(pos+ntails): 0;
}
static void move_head(pos_t *pos, move_t *move)
{
log_f(3, "(%d,%d,%c) -> ", pos->x, pos->y, move->dir);
switch (move->dir) {
case U:
pos->y++;
break;
case R:
pos->x++;
break;
case D:
pos->y--;
break;
case L:
pos->x--;
break;
default:
log(3, "ERR=%x ", move->dir);
}
log_f(3, "(%d,%d)\n", pos->x, pos->y);
}
static pos_t *part1(int *ntails)
{
static pos_t nodes[] = { [0 ... 1] = {.x = 0, .y = 0}};
*ntails = ARRAY_SIZE(nodes) - 1;
return nodes;
}
static pos_t *part2(int *ntails)
{
static pos_t nodes[] = { [0 ... 9] = {.x = 0, .y = 0}};
*ntails = ARRAY_SIZE(nodes) - 1;
return nodes;
}
static int solve(int part)
{
int ntails;
pos_t *nodes = part == 1? part1(&ntails): part2(&ntails);
move_t *move;
int res = 1; /* for (0,0) */
add_visited_maybe( &(pos_t) {0, 0});
list_for_each_entry(move, &moves, list) {
for (int i = 0; i < move->nmoves; ++i) {
move_head(nodes, move);
res += move_tails(nodes, ntails);
}
}
return res;
}
static int parse()
{
char dir;
int nmoves;
int count = 0;
move_t *move;
while (scanf(" %c %d", &dir, &nmoves) == 2) {
move = pool_get(pool_move);
move->dir = dir;
move->nmoves = nmoves;
list_add_tail(&move->list, &moves);
count++;
}
return count;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
pool_visited = pool_create("visited", 128, sizeof(visited_t));
pool_move = pool_create("dirs", 128, sizeof(move_t));
parse();
printf("%s: res=%d\n", *av, solve(part));
pool_destroy(pool_visited);
pool_destroy(pool_move);
exit(0);
}

63
2022/day09/aoc.bash Executable file
View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 9
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
. common.bash
declare -a h{0..10} # h0 is head
declare -A visited=() # keep count of visited
declare -i last=1 # tail (last knot)
move() {
local -i _dx="$1" _dy="$2" _m="$3" _i _n
local -i __dx __dy __sx __sy
local -n _l="h$last"
for ((_i = 0; _i < _m; ++_i)); do # for each move
(( h0[0] += _dx, h0[1] += _dy )) # head move
for (( _n = 0; _n < last; ++_n )); do # for each other node
local -n _h="h$_n" _t="h$((_n+1))"
(( __dx = _h[0] - _t[0], __dy = _h[1] - _t[1] ))
(( __sx = __dx? __dx > 0? 1: -1 : 0 ))
(( __sy = __dy? __dy > 0? 1: -1 : 0 ))
if (( __sx * __dx > 1 || __sy * __dy > 1)); then
(( _t[0] += __sx ))
(( _t[1] += __sy ))
fi
done
visited["${_l[0]}"/"${_l[1]}"]=1
done
}
parse() {
local dir moves dx dy
(( $1 == 2)) && last=9
while read -r dir moves; do
dx=0
dy=0
case "$dir" in
L) dx=-1 ;;
R) dx=1 ;;
U) dy=1 ;;
D) dy=-1 ;;
esac
move "$dx" "$dy" "$moves"
done
}
solve() {
res=${#visited[@]}
}
main "$@"
exit 0

View File

@@ -0,0 +1,8 @@
R 5
U 8
L 8
D 3
R 17
D 10
L 25
U 20

111
2022/day10/Makefile Normal file
View File

@@ -0,0 +1,111 @@
# AOC daily Makefile - GNU make only.
#
# Copyright (C) 2021-2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
INPUT := input/input.txt
SHELL := /bin/bash
CC := gcc
BEAR := bear
CCLSFILE:= compile_commands.json
LIB := aoc_$(shell uname -m)
INCDIR := ../include
LIBDIR := ../lib
LDFLAGS := -L$(LIBDIR)
#LDLIB := -l$(LIB) -lm
LDLIB := -l$(LIB)
export LD_LIBRARY_PATH = $(LIBDIR)
CFLAGS += -std=gnu11
CFLAGS += -O2
CFLAGS += -g
# for gprof
# CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
# Next one may be useful for valgrind (some invalid instructions)
# CFLAGS += -mno-tbm
CFLAGS += -Wmissing-declarations
CFLAGS += -Wno-unused-result
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
CFLAGS += -DDEBUG_POOL # memory pools management
VALGRIND := valgrind
VALGRINDFLAGS := --leak-check=full --show-leak-kinds=all --track-origins=yes \
--sigill-diagnostics=yes --quiet --show-error-list=yes
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
export PATH := .:$(PATH)
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 part1 part2 ccls bear org
all: README.org ccls part1 part2
memcheck: memcheck1 memcheck2
memcheck1: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
memcheck2: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
@#@valgrind -s --track-origins=yes aoc-c -p 2 < $(INPUT)
compile: aoc-c
cpp: aoc-c.i
assembly: aoc-c.s
part1: aoc-c
@$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 1 < $(INPUT)
part2: aoc-c
@$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html compile_commands.json
aoc-c: aoc-c.c common.c
@echo compiling $<
$(CC) $(CFLAGS) $(LDFLAGS) -I $(INCDIR) $^ $(LDLIB) -o $@
# generate pre-processed file (.i) and assembler (.s)
%.i: %.c
@echo generating $@
@$(CC) -E $(CFLAGS) -I $(INCDIR) $< -o $@
%.s: %.c
@echo generating $@
@$(CC) -S -fverbose-asm $(CFLAGS) -I $(INCDIR) $< -o $@
# generate README.org from README.html (must cleanup !)
org: README.org
%.org: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@touch .ccls-root
@$(BEAR) -- make compile

389
2022/day10/README.org Normal file
View File

@@ -0,0 +1,389 @@
** --- Day 10: Cathode-Ray Tube ---
You avoid the ropes, plunge into the river, and swim to shore.
The Elves yell something about meeting back up with them upriver, but
the river is too loud to tell exactly what they're saying. They finish
crossing the bridge and disappear from view.
Situations like this must be why the Elves prioritized getting the
communication system on your handheld device working. You pull it out of
your pack, but the amount of water slowly draining from a big crack in
its screen tells you it probably won't be of much immediate use.
/Unless/, that is, you can design a replacement for the device's video
system! It seems to be some kind of
[[https://en.wikipedia.org/wiki/Cathode-ray_tube][cathode-ray tube]]
screen and simple CPU that are both driven by a precise /clock circuit/.
The clock circuit ticks at a constant rate; each tick is called a
/cycle/.
Start by figuring out the signal being sent by the CPU. The CPU has a
single register, =X=, which starts with the value =1=. It supports only
two instructions:
- =addx V= takes /two cycles/ to complete. /After/ two cycles, the =X=
register is increased by the value =V=. (=V= can be negative.)
- =noop= takes /one cycle/ to complete. It has no other effect.
The CPU uses these instructions in a program (your puzzle input) to,
somehow, tell the screen what to draw.
Consider the following small program:
#+begin_example
noop
addx 3
addx -5
#+end_example
Execution of this program proceeds as follows:
- At the start of the first cycle, the =noop= instruction begins
execution. During the first cycle, =X= is =1=. After the first cycle,
the =noop= instruction finishes execution, doing nothing.
- At the start of the second cycle, the =addx 3= instruction begins
execution. During the second cycle, =X= is still =1=.
- During the third cycle, =X= is still =1=. After the third cycle, the
=addx 3= instruction finishes execution, setting =X= to =4=.
- At the start of the fourth cycle, the =addx -5= instruction begins
execution. During the fourth cycle, =X= is still =4=.
- During the fifth cycle, =X= is still =4=. After the fifth cycle, the
=addx -5= instruction finishes execution, setting =X= to =-1=.
Maybe you can learn something by looking at the value of the =X=
register throughout execution. For now, consider the /signal strength/
(the cycle number multiplied by the value of the =X= register) /during/
the 20th cycle and every 40 cycles after that (that is, during the 20th,
60th, 100th, 140th, 180th, and 220th cycles).
For example, consider this larger program:
#+begin_example
addx 15
addx -11
addx 6
addx -3
addx 5
addx -1
addx -8
addx 13
addx 4
noop
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx -35
addx 1
addx 24
addx -19
addx 1
addx 16
addx -11
noop
noop
addx 21
addx -15
noop
noop
addx -3
addx 9
addx 1
addx -3
addx 8
addx 1
addx 5
noop
noop
noop
noop
noop
addx -36
noop
addx 1
addx 7
noop
noop
noop
addx 2
addx 6
noop
noop
noop
noop
noop
addx 1
noop
noop
addx 7
addx 1
noop
addx -13
addx 13
addx 7
noop
addx 1
addx -33
noop
noop
noop
addx 2
noop
noop
noop
addx 8
noop
addx -1
addx 2
addx 1
noop
addx 17
addx -9
addx 1
addx 1
addx -3
addx 11
noop
noop
addx 1
noop
addx 1
noop
noop
addx -13
addx -19
addx 1
addx 3
addx 26
addx -30
addx 12
addx -1
addx 3
addx 1
noop
noop
noop
addx -9
addx 18
addx 1
addx 2
noop
noop
addx 9
noop
noop
noop
addx -1
addx 2
addx -37
addx 1
addx 3
noop
addx 15
addx -21
addx 22
addx -6
addx 1
noop
addx 2
addx 1
noop
addx -10
noop
noop
addx 20
addx 1
addx 2
addx 2
addx -6
addx -11
noop
noop
noop
#+end_example
The interesting signal strengths can be determined as follows:
- During the 20th cycle, register =X= has the value =21=, so the signal
strength is 20 * 21 = /420/. (The 20th cycle occurs in the middle of
the second =addx -1=, so the value of register =X= is the starting
value, =1=, plus all of the other =addx= values up to that point: 1 +
15 - 11 + 6 - 3 + 5 - 1 - 8 + 13 + 4 = 21.)
- During the 60th cycle, register =X= has the value =19=, so the signal
strength is 60 * 19 = =1140=.
- During the 100th cycle, register =X= has the value =18=, so the signal
strength is 100 * 18 = =1800=.
- During the 140th cycle, register =X= has the value =21=, so the signal
strength is 140 * 21 = =2940=.
- During the 180th cycle, register =X= has the value =16=, so the signal
strength is 180 * 16 = =2880=.
- During the 220th cycle, register =X= has the value =18=, so the signal
strength is 220 * 18 = =3960=.
The sum of these signal strengths is =13140=.
Find the signal strength during the 20th, 60th, 100th, 140th, 180th, and
220th cycles. /What is the sum of these six signal strengths?/
Your puzzle answer was =13220=.
** --- Part Two ---
It seems like the =X= register controls the horizontal position of a
[[https://en.wikipedia.org/wiki/Sprite_(computer_graphics)][sprite]].
Specifically, the sprite is 3 pixels wide, and the =X= register sets the
horizontal position of the /middle/ of that sprite. (In this system,
there is no such thing as "vertical position": if the sprite's
horizontal position puts its pixels where the CRT is currently drawing,
then those pixels will be drawn.)
You count the pixels on the CRT: 40 wide and 6 high. This CRT screen
draws the top row of pixels left-to-right, then the row below that, and
so on. The left-most pixel in each row is in position =0=, and the
right-most pixel in each row is in position =39=.
Like the CPU, the CRT is tied closely to the clock circuit: the CRT
draws /a single pixel during each cycle/. Representing each pixel of the
screen as a =#=, here are the cycles during which the first and last
pixel in each row are drawn:
#+begin_example
Cycle 1 -> ######################################## <- Cycle 40
Cycle 41 -> ######################################## <- Cycle 80
Cycle 81 -> ######################################## <- Cycle 120
Cycle 121 -> ######################################## <- Cycle 160
Cycle 161 -> ######################################## <- Cycle 200
Cycle 201 -> ######################################## <- Cycle 240
#+end_example
So, by [[https://en.wikipedia.org/wiki/Racing_the_Beam][carefully]]
[[https://www.youtube.com/watch?v=sJFnWZH5FXc][timing]] the CPU
instructions and the CRT drawing operations, you should be able to
determine whether the sprite is visible the instant each pixel is drawn.
If the sprite is positioned such that one of its three pixels is the
pixel currently being drawn, the screen produces a /lit/ pixel (=#=);
otherwise, the screen leaves the pixel /dark/ (=.=).
The first few pixels from the larger example above are drawn as follows:
#+begin_example
Sprite position: ###.....................................
Start cycle 1: begin executing addx 15
During cycle 1: CRT draws pixel in position 0
Current CRT row: #
During cycle 2: CRT draws pixel in position 1
Current CRT row: ##
End of cycle 2: finish executing addx 15 (Register X is now 16)
Sprite position: ...............###......................
Start cycle 3: begin executing addx -11
During cycle 3: CRT draws pixel in position 2
Current CRT row: ##.
During cycle 4: CRT draws pixel in position 3
Current CRT row: ##..
End of cycle 4: finish executing addx -11 (Register X is now 5)
Sprite position: ....###.................................
Start cycle 5: begin executing addx 6
During cycle 5: CRT draws pixel in position 4
Current CRT row: ##..#
During cycle 6: CRT draws pixel in position 5
Current CRT row: ##..##
End of cycle 6: finish executing addx 6 (Register X is now 11)
Sprite position: ..........###...........................
Start cycle 7: begin executing addx -3
During cycle 7: CRT draws pixel in position 6
Current CRT row: ##..##.
During cycle 8: CRT draws pixel in position 7
Current CRT row: ##..##..
End of cycle 8: finish executing addx -3 (Register X is now 8)
Sprite position: .......###..............................
Start cycle 9: begin executing addx 5
During cycle 9: CRT draws pixel in position 8
Current CRT row: ##..##..#
During cycle 10: CRT draws pixel in position 9
Current CRT row: ##..##..##
End of cycle 10: finish executing addx 5 (Register X is now 13)
Sprite position: ............###.........................
Start cycle 11: begin executing addx -1
During cycle 11: CRT draws pixel in position 10
Current CRT row: ##..##..##.
During cycle 12: CRT draws pixel in position 11
Current CRT row: ##..##..##..
End of cycle 12: finish executing addx -1 (Register X is now 12)
Sprite position: ...........###..........................
Start cycle 13: begin executing addx -8
During cycle 13: CRT draws pixel in position 12
Current CRT row: ##..##..##..#
During cycle 14: CRT draws pixel in position 13
Current CRT row: ##..##..##..##
End of cycle 14: finish executing addx -8 (Register X is now 4)
Sprite position: ...###..................................
Start cycle 15: begin executing addx 13
During cycle 15: CRT draws pixel in position 14
Current CRT row: ##..##..##..##.
During cycle 16: CRT draws pixel in position 15
Current CRT row: ##..##..##..##..
End of cycle 16: finish executing addx 13 (Register X is now 17)
Sprite position: ................###.....................
Start cycle 17: begin executing addx 4
During cycle 17: CRT draws pixel in position 16
Current CRT row: ##..##..##..##..#
During cycle 18: CRT draws pixel in position 17
Current CRT row: ##..##..##..##..##
End of cycle 18: finish executing addx 4 (Register X is now 21)
Sprite position: ....................###.................
Start cycle 19: begin executing noop
During cycle 19: CRT draws pixel in position 18
Current CRT row: ##..##..##..##..##.
End of cycle 19: finish executing noop
Start cycle 20: begin executing addx -1
During cycle 20: CRT draws pixel in position 19
Current CRT row: ##..##..##..##..##..
During cycle 21: CRT draws pixel in position 20
Current CRT row: ##..##..##..##..##..#
End of cycle 21: finish executing addx -1 (Register X is now 20)
Sprite position: ...................###..................
#+end_example
Allowing the program to run to completion causes the CRT to produce the
following image:
#+begin_example
##..##..##..##..##..##..##..##..##..##..
###...###...###...###...###...###...###.
####....####....####....####....####....
#####.....#####.....#####.....#####.....
######......######......######......####
#######.......#######.......#######.....
#+end_example
Render the image given by your program. /What eight capital letters
appear on your CRT?/
Your puzzle answer was =RUAKHBEK=.
Both parts of this puzzle are complete! They provide two gold stars: **

167
2022/day10/aoc-c.c Normal file
View File

@@ -0,0 +1,167 @@
/* aoc-c.c: Advent of Code 2022, day 10
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "br.h"
#include "debug.h"
#include "aoc.h"
#define MAXARGS 1 /* max arguments to opcode */
typedef enum opcode { /* available opcodes */
ERR = -1,
NOOP = 0,
ADDX
} opcode_t;
typedef struct hw { /* hardware */
int tick; /* clock */
int regx; /* x register */
int signal; /* signal strength */
int alrm; /* next tick signal */
int rearm; /* rearm signal value */
void (* tickfct)(struct hw *hw); /* tick function */
void (* alrmfct)(struct hw *hw); /* signal function */
int part; /* puzzle part */
} hw_t;
typedef struct op { /* operators indormation */
char *mnemo;
opcode_t opcode;
int ticks;
void (* fct)(hw_t *hw, int *);
int nargs;
} op_t;
static inline void alarm1(hw_t *hw)
{
hw->signal += hw->tick * hw->regx;
hw->alrm = hw->rearm;
}
static inline void alarm2(hw_t *hw)
{
putchar('\n'); /* '.' fixes last column garbage */
hw->alrm = hw->rearm;
}
static inline void tick1(__unused hw_t *hw)
{
}
static inline void tick2(hw_t *hw)
{
int pos = abs(hw->tick % 40 - hw->regx - 1);
putchar(pos < 2? '#': '.');
}
static void bootstrap(hw_t *hw, int part)
{
hw->tick = 0;
hw->regx = 1;
hw->signal = 0;
hw->alrm = part == 1? 20: 40;
hw->rearm = 40;
hw->alrmfct = part == 1? alarm1: alarm2;
hw->tickfct = part == 1? tick1: tick2;
hw->part = part;
}
static inline void tick(hw_t *hw)
{
hw->tick++;
hw->alrm--;
hw->tickfct(hw);
if (!hw->alrm)
hw->alrmfct(hw);
}
static inline void ticks(hw_t *hw, int ticks)
{
for (int i = 0; i < ticks; ++i)
tick(hw);
}
static void do_noop(__unused hw_t *hw, __unused int *args)
{
}
static void do_addx(hw_t *hw, int *args)
{
hw->regx += *args;
}
static op_t opcodes[] = {
{ "noop", NOOP, 1, do_noop, 0 },
{ "addx", ADDX, 2, do_addx, 1 }
};
#define NOPS ARRAY_SIZE(opcodes)
static op_t *getop(const char *mnemo)
{
for (ulong i = 0; i < NOPS; ++i)
if (!strcmp(mnemo, opcodes[i].mnemo))
return opcodes + i;
return NULL;
}
static int part1(hw_t *hw)
{
return hw->signal;
}
static int part2(hw_t *hw)
{
return hw->signal;
}
static int parse(hw_t *hw)
{
size_t alloc = 0;
char *buf = NULL;
ssize_t buflen;
char *token;
op_t *op;
int args[MAXARGS];
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
buf[--buflen] = 0;
if ((token = strtok(buf, " "))) {
if ((op = getop(token))) {
ticks(hw, op->ticks);
for (int i = 0; i < op->nargs; ++i)
args[i] = atoi(strtok(NULL, " "));
op->fct(hw, args);
} else {
fprintf(stderr, "Fatal: opcode [%s] not found\n", token);
exit(1);
}
}
}
return 1;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
hw_t hw;
bootstrap(&hw, part);
parse(&hw);
printf("%s: res=%d\n", *av, part == 1? part1(&hw): part2(&hw));
exit(0);
}

67
2022/day10/aoc.bash Executable file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 10
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
. common.bash
declare -i cycle=0 regx=1
draw() {
local -i pos
(( pos = cycle % 40 - regx - 1, pos = pos < 0? -pos: pos ))
(( pos < 2 )) && res+="#" || res+="."
if ! (( cycle % 40 )); then
res+=$'\n'
fi
}
tick() {
(( cycle ++ ))
if (( part == 1 )); then
(( (cycle + 20) % 40 )) || (( res += cycle * regx ))
else
draw
fi
}
do_noop() {
tick
}
do_add() {
tick
tick
(( regx += $1 ))
}
parse() {
while read -r instr value; do
# not too hacky, to prepare for next puzzles ;-)
case "$instr" in
"addx")
do_add "$value"
;;
"noop")
do_noop
;;
esac
done
}
solve() {
# remove last '\n', add starting '\n'
(( part == 2 )) && res=$'\n'${res::-1}
}
main "$@"
exit 0

17
2022/day10/aoc.h Normal file
View File

@@ -0,0 +1,17 @@
/* aoc.c: Advent of Code 2022
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#ifndef _AOC_H_
#define _AOC_H_
extern int parseargs(int ac, char**av);
#endif /* _AOC_H_ */

68
2022/day10/common.bash Executable file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# common.bash: Advent of Code 2022, common bash functions
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
# shellcheck disable=2034
export cmdname=${0##*/}
export debug=0
export res
export LANG=C
shopt -s extglob
set -o noglob
usage() {
printf "usage: %s [-d DEBUG] [-p PART]\n" "$cmdname"
exit 1
}
checkargs() {
local part=1
while getopts p:d: todo; do
case "$todo" in
d)
if [[ "$OPTARG" =~ ^[[:digit:]+]$ ]]; then
debug="$OPTARG"
else
printf "%s: illegal [%s] debug level.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
p)
if [[ "$OPTARG" =~ ^[12]$ ]]; then
part="$OPTARG"
else
printf "%s: illegal [%s] part.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
*)
usage
;;
esac
done
# Now check remaining argument (backup directory)
shift $((OPTIND - 1))
(( $# > 1 )) && usage
return "$part"
}
main() {
local -i part
checkargs "$@"
part=$?
parse "$part"
solve "$part"
printf "%s: res=%s\n" "$cmdname" "$res"
}

49
2022/day10/common.c Normal file
View File

@@ -0,0 +1,49 @@
/* common.c: Advent of Code 2022, common functions
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "aoc.h"
#include "debug.h"
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int parseargs(int ac, char **av)
{
int opt, part = 1;
while ((opt = getopt(ac, av, "d:p:")) != -1) {
switch (opt) {
case 'd':
debug_level_set(atoi(optarg));
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
case 'i':
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
return part;
}

View File

@@ -0,0 +1,146 @@
addx 15
addx -11
addx 6
addx -3
addx 5
addx -1
addx -8
addx 13
addx 4
noop
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx -35
addx 1
addx 24
addx -19
addx 1
addx 16
addx -11
noop
noop
addx 21
addx -15
noop
noop
addx -3
addx 9
addx 1
addx -3
addx 8
addx 1
addx 5
noop
noop
noop
noop
noop
addx -36
noop
addx 1
addx 7
noop
noop
noop
addx 2
addx 6
noop
noop
noop
noop
noop
addx 1
noop
noop
addx 7
addx 1
noop
addx -13
addx 13
addx 7
noop
addx 1
addx -33
noop
noop
noop
addx 2
noop
noop
noop
addx 8
noop
addx -1
addx 2
addx 1
noop
addx 17
addx -9
addx 1
addx 1
addx -3
addx 11
noop
noop
addx 1
noop
addx 1
noop
noop
addx -13
addx -19
addx 1
addx 3
addx 26
addx -30
addx 12
addx -1
addx 3
addx 1
noop
noop
noop
addx -9
addx 18
addx 1
addx 2
noop
noop
addx 9
noop
noop
noop
addx -1
addx 2
addx -37
addx 1
addx 3
noop
addx 15
addx -21
addx 22
addx -6
addx 1
noop
addx 2
addx 1
noop
addx -10
noop
noop
addx 20
addx 1
addx 2
addx 2
addx -6
addx -11
noop
noop
noop

View File

@@ -0,0 +1,3 @@
noop
addx 3
addx -5

137
2022/day10/input/input.txt Normal file
View File

@@ -0,0 +1,137 @@
noop
noop
addx 5
addx 3
addx -2
noop
addx 5
addx 4
noop
addx 3
noop
addx 2
addx -17
addx 18
addx 3
addx 1
noop
addx 5
noop
addx 1
addx 2
addx 5
addx -40
noop
addx 5
addx 2
addx 3
noop
addx 2
addx 3
addx -2
addx 2
addx 2
noop
addx 3
addx 5
addx 2
addx 3
addx -2
addx 2
addx -24
addx 31
addx 2
addx -33
addx -6
addx 5
addx 2
addx 3
noop
addx 2
addx 3
noop
addx 2
addx -1
addx 6
noop
noop
addx 1
addx 4
noop
noop
addx -15
addx 20
noop
addx -23
addx 27
noop
addx -35
addx 1
noop
noop
addx 5
addx 11
addx -10
addx 4
addx 1
noop
addx 2
addx 2
noop
addx 3
noop
addx 3
addx 2
noop
addx 3
addx 2
addx 11
addx -4
addx 2
addx -38
addx -1
addx 2
noop
addx 3
addx 5
addx 2
addx -7
addx 8
addx 2
addx 2
noop
addx 3
addx 5
addx 2
addx -25
addx 26
addx 2
addx 8
addx -1
addx 2
addx -2
addx -37
addx 5
addx 3
addx -1
addx 5
noop
addx 22
addx -21
addx 2
addx 5
addx 2
addx 13
addx -12
addx 4
noop
noop
addx 5
addx 1
noop
noop
addx 2
noop
addx 3
noop
noop

111
2022/day11/Makefile Normal file
View File

@@ -0,0 +1,111 @@
# AOC daily Makefile - GNU make only.
#
# Copyright (C) 2021-2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
INPUT := input/input.txt
SHELL := /bin/bash
CC := gcc
BEAR := bear
CCLSFILE:= compile_commands.json
LIB := aoc_$(shell uname -m)
INCDIR := ../include
LIBDIR := ../lib
LDFLAGS := -L$(LIBDIR)
#LDLIB := -l$(LIB) -lm
LDLIB := -l$(LIB)
export LD_LIBRARY_PATH = $(LIBDIR)
CFLAGS += -std=gnu11
CFLAGS += -O2
CFLAGS += -g
# for gprof
# CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
# Next one may be useful for valgrind (some invalid instructions)
# CFLAGS += -mno-tbm
CFLAGS += -Wmissing-declarations
CFLAGS += -Wno-unused-result
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
CFLAGS += -DDEBUG_POOL # memory pools management
VALGRIND := valgrind
VALGRINDFLAGS := --leak-check=full --show-leak-kinds=all --track-origins=yes \
--sigill-diagnostics=yes --quiet --show-error-list=yes
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
export PATH := .:$(PATH)
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 part1 part2 ccls bear org
all: README.org ccls part1 part2
memcheck: memcheck1 memcheck2
memcheck1: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
memcheck2: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
@#@valgrind -s --track-origins=yes aoc-c -p 2 < $(INPUT)
compile: aoc-c
cpp: aoc-c.i
assembly: aoc-c.s
part1: aoc-c
@$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 1 < $(INPUT)
part2: aoc-c
@$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html compile_commands.json
aoc-c: aoc-c.c common.c
@echo compiling $<
$(CC) $(CFLAGS) $(LDFLAGS) -I $(INCDIR) $^ $(LDLIB) -o $@
# generate pre-processed file (.i) and assembler (.s)
%.i: %.c
@echo generating $@
@$(CC) -E $(CFLAGS) -I $(INCDIR) $< -o $@
%.s: %.c
@echo generating $@
@$(CC) -S -fverbose-asm $(CFLAGS) -I $(INCDIR) $< -o $@
# generate README.org from README.html (must cleanup !)
org: README.org
%.org: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@touch .ccls-root
@$(BEAR) -- make compile

364
2022/day11/README.org Normal file
View File

@@ -0,0 +1,364 @@
** --- Day 11: Monkey in the Middle ---
As you finally start making your way upriver, you realize your pack is
much lighter than you remember. Just then, one of the items from your
pack goes flying overhead. Monkeys are playing
[[https://en.wikipedia.org/wiki/Keep_away][Keep Away]] with your missing
things!
To get your stuff back, you need to be able to predict where the monkeys
will throw your items. After some careful observation, you realize the
monkeys operate based on /how worried you are about each item/.
You take some notes (your puzzle input) on the items each monkey
currently has, how worried you are about those items, and how the monkey
makes decisions based on your worry level. For example:
#+begin_example
Monkey 0:
Starting items: 79, 98
Operation: new = old * 19
Test: divisible by 23
If true: throw to monkey 2
If false: throw to monkey 3
Monkey 1:
Starting items: 54, 65, 75, 74
Operation: new = old + 6
Test: divisible by 19
If true: throw to monkey 2
If false: throw to monkey 0
Monkey 2:
Starting items: 79, 60, 97
Operation: new = old * old
Test: divisible by 13
If true: throw to monkey 1
If false: throw to monkey 3
Monkey 3:
Starting items: 74
Operation: new = old + 3
Test: divisible by 17
If true: throw to monkey 0
If false: throw to monkey 1
#+end_example
Each monkey has several attributes:
- =Starting items= lists your /worry level/ for each item the monkey is
currently holding in the order they will be inspected.
- =Operation= shows how your worry level changes as that monkey inspects
an item. (An operation like =new = old * 5= means that your worry
level after the monkey inspected the item is five times whatever your
worry level was before inspection.)
- =Test= shows how the monkey uses your worry level to decide where to
throw an item next.
- =If true= shows what happens with an item if the =Test= was true.
- =If false= shows what happens with an item if the =Test= was false.
After each monkey inspects an item but before it tests your worry level,
your relief that the monkey's inspection didn't damage the item causes
your worry level to be /divided by three/ and rounded down to the
nearest integer.
The monkeys take turns inspecting and throwing items. On a single
monkey's /turn/, it inspects and throws all of the items it is holding
one at a time and in the order listed. Monkey =0= goes first, then
monkey =1=, and so on until each monkey has had one turn. The process of
each monkey taking a single turn is called a /round/.
When a monkey throws an item to another monkey, the item goes on the
/end/ of the recipient monkey's list. A monkey that starts a round with
no items could end up inspecting and throwing many items by the time its
turn comes around. If a monkey is holding no items at the start of its
turn, its turn ends.
In the above example, the first round proceeds as follows:
#+begin_example
Monkey 0:
Monkey inspects an item with a worry level of 79.
Worry level is multiplied by 19 to 1501.
Monkey gets bored with item. Worry level is divided by 3 to 500.
Current worry level is not divisible by 23.
Item with worry level 500 is thrown to monkey 3.
Monkey inspects an item with a worry level of 98.
Worry level is multiplied by 19 to 1862.
Monkey gets bored with item. Worry level is divided by 3 to 620.
Current worry level is not divisible by 23.
Item with worry level 620 is thrown to monkey 3.
Monkey 1:
Monkey inspects an item with a worry level of 54.
Worry level increases by 6 to 60.
Monkey gets bored with item. Worry level is divided by 3 to 20.
Current worry level is not divisible by 19.
Item with worry level 20 is thrown to monkey 0.
Monkey inspects an item with a worry level of 65.
Worry level increases by 6 to 71.
Monkey gets bored with item. Worry level is divided by 3 to 23.
Current worry level is not divisible by 19.
Item with worry level 23 is thrown to monkey 0.
Monkey inspects an item with a worry level of 75.
Worry level increases by 6 to 81.
Monkey gets bored with item. Worry level is divided by 3 to 27.
Current worry level is not divisible by 19.
Item with worry level 27 is thrown to monkey 0.
Monkey inspects an item with a worry level of 74.
Worry level increases by 6 to 80.
Monkey gets bored with item. Worry level is divided by 3 to 26.
Current worry level is not divisible by 19.
Item with worry level 26 is thrown to monkey 0.
Monkey 2:
Monkey inspects an item with a worry level of 79.
Worry level is multiplied by itself to 6241.
Monkey gets bored with item. Worry level is divided by 3 to 2080.
Current worry level is divisible by 13.
Item with worry level 2080 is thrown to monkey 1.
Monkey inspects an item with a worry level of 60.
Worry level is multiplied by itself to 3600.
Monkey gets bored with item. Worry level is divided by 3 to 1200.
Current worry level is not divisible by 13.
Item with worry level 1200 is thrown to monkey 3.
Monkey inspects an item with a worry level of 97.
Worry level is multiplied by itself to 9409.
Monkey gets bored with item. Worry level is divided by 3 to 3136.
Current worry level is not divisible by 13.
Item with worry level 3136 is thrown to monkey 3.
Monkey 3:
Monkey inspects an item with a worry level of 74.
Worry level increases by 3 to 77.
Monkey gets bored with item. Worry level is divided by 3 to 25.
Current worry level is not divisible by 17.
Item with worry level 25 is thrown to monkey 1.
Monkey inspects an item with a worry level of 500.
Worry level increases by 3 to 503.
Monkey gets bored with item. Worry level is divided by 3 to 167.
Current worry level is not divisible by 17.
Item with worry level 167 is thrown to monkey 1.
Monkey inspects an item with a worry level of 620.
Worry level increases by 3 to 623.
Monkey gets bored with item. Worry level is divided by 3 to 207.
Current worry level is not divisible by 17.
Item with worry level 207 is thrown to monkey 1.
Monkey inspects an item with a worry level of 1200.
Worry level increases by 3 to 1203.
Monkey gets bored with item. Worry level is divided by 3 to 401.
Current worry level is not divisible by 17.
Item with worry level 401 is thrown to monkey 1.
Monkey inspects an item with a worry level of 3136.
Worry level increases by 3 to 3139.
Monkey gets bored with item. Worry level is divided by 3 to 1046.
Current worry level is not divisible by 17.
Item with worry level 1046 is thrown to monkey 1.
#+end_example
After round 1, the monkeys are holding items with these worry levels:
#+begin_example
Monkey 0: 20, 23, 27, 26
Monkey 1: 2080, 25, 167, 207, 401, 1046
Monkey 2:
Monkey 3:
#+end_example
Monkeys 2 and 3 aren't holding any items at the end of the round; they
both inspected items during the round and threw them all before the
round ended.
This process continues for a few more rounds:
#+begin_example
After round 2, the monkeys are holding items with these worry levels:
Monkey 0: 695, 10, 71, 135, 350
Monkey 1: 43, 49, 58, 55, 362
Monkey 2:
Monkey 3:
After round 3, the monkeys are holding items with these worry levels:
Monkey 0: 16, 18, 21, 20, 122
Monkey 1: 1468, 22, 150, 286, 739
Monkey 2:
Monkey 3:
After round 4, the monkeys are holding items with these worry levels:
Monkey 0: 491, 9, 52, 97, 248, 34
Monkey 1: 39, 45, 43, 258
Monkey 2:
Monkey 3:
After round 5, the monkeys are holding items with these worry levels:
Monkey 0: 15, 17, 16, 88, 1037
Monkey 1: 20, 110, 205, 524, 72
Monkey 2:
Monkey 3:
After round 6, the monkeys are holding items with these worry levels:
Monkey 0: 8, 70, 176, 26, 34
Monkey 1: 481, 32, 36, 186, 2190
Monkey 2:
Monkey 3:
After round 7, the monkeys are holding items with these worry levels:
Monkey 0: 162, 12, 14, 64, 732, 17
Monkey 1: 148, 372, 55, 72
Monkey 2:
Monkey 3:
After round 8, the monkeys are holding items with these worry levels:
Monkey 0: 51, 126, 20, 26, 136
Monkey 1: 343, 26, 30, 1546, 36
Monkey 2:
Monkey 3:
After round 9, the monkeys are holding items with these worry levels:
Monkey 0: 116, 10, 12, 517, 14
Monkey 1: 108, 267, 43, 55, 288
Monkey 2:
Monkey 3:
After round 10, the monkeys are holding items with these worry levels:
Monkey 0: 91, 16, 20, 98
Monkey 1: 481, 245, 22, 26, 1092, 30
Monkey 2:
Monkey 3:
...
After round 15, the monkeys are holding items with these worry levels:
Monkey 0: 83, 44, 8, 184, 9, 20, 26, 102
Monkey 1: 110, 36
Monkey 2:
Monkey 3:
...
After round 20, the monkeys are holding items with these worry levels:
Monkey 0: 10, 12, 14, 26, 34
Monkey 1: 245, 93, 53, 199, 115
Monkey 2:
Monkey 3:
#+end_example
Chasing all of the monkeys at once is impossible; you're going to have
to focus on the /two most active/ monkeys if you want any hope of
getting your stuff back. Count the /total number of times each monkey
inspects items/ over 20 rounds:
#+begin_example
Monkey 0 inspected items 101 times.
Monkey 1 inspected items 95 times.
Monkey 2 inspected items 7 times.
Monkey 3 inspected items 105 times.
#+end_example
In this example, the two most active monkeys inspected items 101 and 105
times. The level of /monkey business/ in this situation can be found by
multiplying these together: =10605=.
Figure out which monkeys to chase by counting how many items they
inspect over 20 rounds. /What is the level of monkey business after 20
rounds of stuff-slinging simian shenanigans?/
Your puzzle answer was =54253=.
** --- Part Two ---
You're worried you might not ever get your items back. So worried, in
fact, that your relief that a monkey's inspection didn't damage an item
/no longer causes your worry level to be divided by three/.
Unfortunately, that relief was all that was keeping your worry levels
from reaching /ridiculous levels/. You'll need to /find another way to
keep your worry levels manageable/.
At this rate, you might be putting up with these monkeys for a /very
long time/ - possibly /=10000= rounds/!
With these new rules, you can still figure out the monkey business after
10000 rounds. Using the same example above:
#+begin_example
== After round 1 ==
Monkey 0 inspected items 2 times.
Monkey 1 inspected items 4 times.
Monkey 2 inspected items 3 times.
Monkey 3 inspected items 6 times.
== After round 20 ==
Monkey 0 inspected items 99 times.
Monkey 1 inspected items 97 times.
Monkey 2 inspected items 8 times.
Monkey 3 inspected items 103 times.
== After round 1000 ==
Monkey 0 inspected items 5204 times.
Monkey 1 inspected items 4792 times.
Monkey 2 inspected items 199 times.
Monkey 3 inspected items 5192 times.
== After round 2000 ==
Monkey 0 inspected items 10419 times.
Monkey 1 inspected items 9577 times.
Monkey 2 inspected items 392 times.
Monkey 3 inspected items 10391 times.
== After round 3000 ==
Monkey 0 inspected items 15638 times.
Monkey 1 inspected items 14358 times.
Monkey 2 inspected items 587 times.
Monkey 3 inspected items 15593 times.
== After round 4000 ==
Monkey 0 inspected items 20858 times.
Monkey 1 inspected items 19138 times.
Monkey 2 inspected items 780 times.
Monkey 3 inspected items 20797 times.
== After round 5000 ==
Monkey 0 inspected items 26075 times.
Monkey 1 inspected items 23921 times.
Monkey 2 inspected items 974 times.
Monkey 3 inspected items 26000 times.
== After round 6000 ==
Monkey 0 inspected items 31294 times.
Monkey 1 inspected items 28702 times.
Monkey 2 inspected items 1165 times.
Monkey 3 inspected items 31204 times.
== After round 7000 ==
Monkey 0 inspected items 36508 times.
Monkey 1 inspected items 33488 times.
Monkey 2 inspected items 1360 times.
Monkey 3 inspected items 36400 times.
== After round 8000 ==
Monkey 0 inspected items 41728 times.
Monkey 1 inspected items 38268 times.
Monkey 2 inspected items 1553 times.
Monkey 3 inspected items 41606 times.
== After round 9000 ==
Monkey 0 inspected items 46945 times.
Monkey 1 inspected items 43051 times.
Monkey 2 inspected items 1746 times.
Monkey 3 inspected items 46807 times.
== After round 10000 ==
Monkey 0 inspected items 52166 times.
Monkey 1 inspected items 47830 times.
Monkey 2 inspected items 1938 times.
Monkey 3 inspected items 52013 times.
#+end_example
After 10000 rounds, the two most active monkeys inspected items 52166
and 52013 times. Multiplying these together, the level of /monkey
business/ in this situation is now =2713310158=.
Worry levels are no longer divided by three after each item is
inspected; you'll need to find another way to keep your worry levels
manageable. Starting again from the initial state in your puzzle input,
/what is the level of monkey business after 10000 rounds?/
Your puzzle answer was =13119526120=.
Both parts of this puzzle are complete! They provide two gold stars: **

164
2022/day11/aoc-c.c Normal file
View File

@@ -0,0 +1,164 @@
/* aoc-c.c: Advent of Code 2022, day 11
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "br.h"
#include "debug.h"
#include "list.h"
#include "pool.h"
#include "aoc.h"
#define MAXMONKEYS 8
typedef struct monkey {
char op; /* '+' or '*' */
long values[2]; /* formula operands */
uint visits; /* total visits */
int div; /* divisor */
struct list_head *dest[2]; /* destination monkey */
struct list_head items; /* monkey items */
} monkey_t;
typedef struct item {
long item;
struct list_head list;
} item_t;
static pool_t *pool_item;
/* TODO: the following 3 variables should not be global
*/
static monkey_t monkeys[MAXMONKEYS];
static int nmonkeys;
static u64 lcm = 1;
static char *getnth(char *buf, int n)
{
char *ret;
for (; n >= 0; n--) {
ret = strtok(buf, " ,\n");
buf = NULL;
}
return ret;
}
static char *getnext()
{
return strtok(NULL, " ,\n");
}
static int parse()
{
size_t alloc = 0;
char *buf = NULL, *tok;
monkey_t *m = monkeys;
while (getline(&buf, &alloc, stdin) > 0) {
INIT_LIST_HEAD(&m->items);
getline(&buf, &alloc, stdin); /* starting items */
tok = getnth(buf, 2);
while (tok) {
item_t *item = pool_get(pool_item);
item->item = atoi(tok);
list_add_tail(&item->list, &m->items);
tok = getnext();
}
getline(&buf, &alloc, stdin); /* operation */
tok = getnth(buf, 3);
m->values[0] = (*tok == 'o') ? -1: atoi(tok); /* first operand */
m->op = *getnext(); /* operator */
tok = getnext();
m->values[1] = *tok == 'o' ? -1: atoi(tok); /* second operand */
getline(&buf, &alloc, stdin); /* divisible */
m->div = atoi(getnth(buf, 3));
lcm *= m->div;
getline(&buf, &alloc, stdin); /* true */
m->dest[0] = &(monkeys + atoi(getnth(buf, 5)))->items;
getline(&buf, &alloc, stdin); /* false */
m->dest[1] = &(monkeys + atoi(getnth(buf, 5)))->items;
getline(&buf, &alloc, stdin); /* skip empty line */
nmonkeys++;
m++;
}
free(buf);
return 1;
}
static __always_inline void inspect(monkey_t *m, int divide)
{
item_t *item, *tmp;
long op1, op2;
list_for_each_entry_safe(item, tmp, &m->items, list) {
m->visits++;
/* I wonder if we could not find some mathematical properties to
* simplify the following three lines
*/
op1 = m->values[0] < 0 ? item->item: m->values[0];
op2 = m->values[1] < 0 ? item->item: m->values[1];
item->item = (((m->op == '+')? op1 + op2: op1 * op2) / divide ) % lcm;
list_move_tail(&item->list, m->dest[!!(item->item % m->div)]);
}
}
static u64 doit(int rounds, int divide)
{
u64 max1 = 0, max2 = 0;
monkey_t *m = monkeys;
for (int r = 0; r < rounds; ++r)
for (int i = 0; i < nmonkeys; ++i)
inspect(monkeys + i, divide);
for (int i = 0; i < nmonkeys; ++i, m++) {
if (m->visits > max1) {
max2 = max1;
max1 = m->visits;
} else if (m->visits > max2) {
max2 = m->visits;
}
}
return max1 * max2;
}
static u64 part1()
{
return doit(20, 3);
}
static u64 part2()
{
return doit(10000, 1);
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
pool_item = pool_create("item", 64, sizeof(item_t));
parse();
printf("%s: res=%lu\n", *av, part == 1? part1(): part2());
pool_destroy(pool_item);
exit(0);
}

86
2022/day11/aoc.bash Executable file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 11
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
. common.bash
declare -ai div ttrue tfalse vis
declare -a it # (1 2) is "1 2"
declare -a op1 op op2
declare -i lcm=1 monks=0 divisor=3
calc() {
local -n _res="$1"
local -i _m1=0 _m2=0 _i
for _i in "${vis[@]}"; do # find the 2 biggest numbers
if ((_i > _m1)); then
((_m2 = _m1, _m1 = _i))
elif ((_i > _m2)); then
((_m2 = _i))
fi
done
(( _res = _m1 * _m2 ))
}
parse() {
local -a _it
while read -r; do # ignore Monkey number
IFS=" :," read -ra _it # starting items
it[$monks]="${_it[*]:2}"
IFS=" :=" read -r _ _ op1[$monks] op[$monks] op2[$monks]
[[ ${op[$monks]} == "+" ]] && unset "op[$monks]"
[[ ${op1[$monks]} == old ]] && unset "op1[$monks]"
[[ ${op2[$monks]} == old ]] && unset "op2[$monks]"
IFS=" :=" read -r _ _ _ div[$monks] # divisor
(( lcm *= div[monks] ))
read -r _ _ _ _ _ ttrue[$monks] # throw if true
read -r _ _ _ _ _ tfalse[$monks]
read -r
(( monks++ ))
done
}
solve() {
local -i _loops=20 round m _op1 _op2 i
(( part == 2 )) && (( _loops = 10000, divisor = 1 ))
for ((round = 0; round < _loops; ++round)); do
for ((m = 0; m < monks; ++m)); do
_op1=${op1[$m]}
_op2=${op2[$m]}
# shellcheck disable=SC2068
for i in ${it[$m]}; do
(( vis[m]++ ))
[[ -v op1[$m] ]] || _op1=$i
[[ -v op2[$m] ]] || _op2=$i
if [[ -v op[$m] ]]; then
(( _tmp = (_op1 * _op2) / divisor % lcm ))
else
(( _tmp = (_op1 + _op2) / divisor % lcm ))
fi
if (( _tmp % div[m] )); then
it[${tfalse[$m]}]+=" $_tmp"
else
it[${ttrue[$m]}]+=" $_tmp"
fi
done
it[$m]=""
done
done
calc res
}
main "$@"
exit 0

17
2022/day11/aoc.h Normal file
View File

@@ -0,0 +1,17 @@
/* aoc.c: Advent of Code 2022
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#ifndef _AOC_H_
#define _AOC_H_
extern int parseargs(int ac, char**av);
#endif /* _AOC_H_ */

68
2022/day11/common.bash Normal file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# common.bash: Advent of Code 2022, common bash functions
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
# shellcheck disable=2034
export cmdname=${0##*/}
export debug=0
export res
export LANG=C
shopt -s extglob
set -o noglob
usage() {
printf "usage: %s [-d DEBUG] [-p PART]\n" "$cmdname"
exit 1
}
checkargs() {
local part=1
while getopts p:d: todo; do
case "$todo" in
d)
if [[ "$OPTARG" =~ ^[[:digit:]+]$ ]]; then
debug="$OPTARG"
else
printf "%s: illegal [%s] debug level.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
p)
if [[ "$OPTARG" =~ ^[12]$ ]]; then
part="$OPTARG"
else
printf "%s: illegal [%s] part.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
*)
usage
;;
esac
done
# Now check remaining argument (backup directory)
shift $((OPTIND - 1))
(( $# > 1 )) && usage
return "$part"
}
main() {
local -i part
checkargs "$@"
part=$?
parse "$part"
solve "$part"
printf "%s: res=%s\n" "$cmdname" "$res"
}

49
2022/day11/common.c Normal file
View File

@@ -0,0 +1,49 @@
/* common.c: Advent of Code 2022, common functions
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "aoc.h"
#include "debug.h"
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int parseargs(int ac, char **av)
{
int opt, part = 1;
while ((opt = getopt(ac, av, "d:p:")) != -1) {
switch (opt) {
case 'd':
debug_level_set(atoi(optarg));
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
case 'i':
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
return part;
}

View File

@@ -0,0 +1,27 @@
Monkey 0:
Starting items: 79, 98
Operation: new = old * 19
Test: divisible by 23
If true: throw to monkey 2
If false: throw to monkey 3
Monkey 1:
Starting items: 54, 65, 75, 74
Operation: new = old + 6
Test: divisible by 19
If true: throw to monkey 2
If false: throw to monkey 0
Monkey 2:
Starting items: 79, 60, 97
Operation: new = old * old
Test: divisible by 13
If true: throw to monkey 1
If false: throw to monkey 3
Monkey 3:
Starting items: 74
Operation: new = old + 3
Test: divisible by 17
If true: throw to monkey 0
If false: throw to monkey 1

View File

@@ -0,0 +1,55 @@
Monkey 0:
Starting items: 98, 70, 75, 80, 84, 89, 55, 98
Operation: new = old * 2
Test: divisible by 11
If true: throw to monkey 1
If false: throw to monkey 4
Monkey 1:
Starting items: 59
Operation: new = old * old
Test: divisible by 19
If true: throw to monkey 7
If false: throw to monkey 3
Monkey 2:
Starting items: 77, 95, 54, 65, 89
Operation: new = old + 6
Test: divisible by 7
If true: throw to monkey 0
If false: throw to monkey 5
Monkey 3:
Starting items: 71, 64, 75
Operation: new = old + 2
Test: divisible by 17
If true: throw to monkey 6
If false: throw to monkey 2
Monkey 4:
Starting items: 74, 55, 87, 98
Operation: new = old * 11
Test: divisible by 3
If true: throw to monkey 1
If false: throw to monkey 7
Monkey 5:
Starting items: 90, 98, 85, 52, 91, 60
Operation: new = old + 7
Test: divisible by 5
If true: throw to monkey 0
If false: throw to monkey 4
Monkey 6:
Starting items: 99, 51
Operation: new = old + 1
Test: divisible by 13
If true: throw to monkey 5
If false: throw to monkey 2
Monkey 7:
Starting items: 98, 94, 59, 76, 51, 65, 75
Operation: new = old + 5
Test: divisible by 2
If true: throw to monkey 3
If false: throw to monkey 6

114
2022/day12/Makefile Normal file
View File

@@ -0,0 +1,114 @@
# AOC daily Makefile - GNU make only.
#
# Copyright (C) 2021-2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
INPUT := input/input.txt
SHELL := /bin/bash
CC := gcc
BEAR := bear
CCLSFILE:= compile_commands.json
LIB := aoc_$(shell uname -m)
INCDIR := ../include
LIBDIR := ../lib
LDFLAGS := -L$(LIBDIR)
#LDLIB := -l$(LIB) -lm
LDLIB := -l$(LIB)
export LD_LIBRARY_PATH = $(LIBDIR)
CFLAGS += -std=gnu11
CFLAGS += -O2
#CFLAGS += -g
# for gprof
# CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
# Next one may be useful for valgrind (some invalid instructions)
# CFLAGS += -mno-tbm
CFLAGS += -Wmissing-declarations
CFLAGS += -Wno-unused-result
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
CFLAGS += -DDEBUG_POOL # memory pools management
VALGRIND := valgrind
VALGRINDFLAGS := --leak-check=full --show-leak-kinds=all --track-origins=yes \
--sigill-diagnostics=yes --quiet --show-error-list=yes
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
export PATH := .:$(PATH)
.PHONY: clean cleanall all compile assembly memcheck memcheck1 memcheck2 part1 part2 ccls bear org
all: README.org ccls part1 part2
memcheck: memcheck1 memcheck2
memcheck1: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
memcheck2: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
@#@valgrind -s --track-origins=yes aoc-c -p 2 < $(INPUT)
compile: aoc-c
cpp: aoc-c.i
assembly: aoc-c.s
part1: aoc-c
@$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 1 < $(INPUT)
part2: aoc-c
@$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html
cleanall: clean
@rm -f compile_commands.json
aoc-c: aoc-c.c common.c
@echo compiling $<
$(CC) $(CFLAGS) $(LDFLAGS) -I $(INCDIR) $^ $(LDLIB) -o $@
# generate pre-processed file (.i) and assembler (.s)
%.i: %.c
@echo generating $@
@$(CC) -E $(CFLAGS) -I $(INCDIR) $< -o $@
%.s: %.c
@echo generating $@
@$(CC) -S -fverbose-asm $(CFLAGS) -I $(INCDIR) $< -o $@
# generate README.org from README.html (must cleanup !)
org: README.org
%.org: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@touch .ccls-root
@$(BEAR) -- make compile

100
2022/day12/README.org Normal file
View File

@@ -0,0 +1,100 @@
** --- Day 12: Hill Climbing Algorithm ---
You try contacting the Elves using your handheld device, but the river
you're following must be too low to get a decent signal.
You ask the device for a heightmap of the surrounding area (your puzzle
input). The heightmap shows the local area from above broken into a
grid; the elevation of each square of the grid is given by a single
lowercase letter, where =a= is the lowest elevation, =b= is the
next-lowest, and so on up to the highest elevation, =z=.
Also included on the heightmap are marks for your current position (=S=)
and the location that should get the best signal (=E=). Your current
position (=S=) has elevation =a=, and the location that should get the
best signal (=E=) has elevation =z=.
You'd like to reach =E=, but to save energy, you should do it in /as few
steps as possible/. During each step, you can move exactly one square
up, down, left, or right. To avoid needing to get out your climbing
gear, the elevation of the destination square can be /at most one
higher/ than the elevation of your current square; that is, if your
current elevation is =m=, you could step to elevation =n=, but not to
elevation =o=. (This also means that the elevation of the destination
square can be much lower than the elevation of your current square.)
For example:
#+begin_example
Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi
#+end_example
Here, you start in the top-left corner; your goal is near the middle.
You could start by moving down or right, but eventually you'll need to
head toward the =e= at the bottom. From there, you can spiral around to
the goal:
#+begin_example
v..v<<<<
>v.vv<<^
.>vv>E^^
..v>>>^^
..>>>>>^
#+end_example
In the above diagram, the symbols indicate whether the path exits each
square moving up (=^=), down (=v=), left (=<=), or right (=>=). The
location that should get the best signal is still =E=, and =.= marks
unvisited squares.
This path reaches the goal in =31= steps, the fewest possible.
/What is the fewest steps required to move from your current position to
the location that should get the best signal?/
Your puzzle answer was =408=.
** --- Part Two ---
As you walk up the hill, you suspect that the Elves will want to turn
this into a hiking trail. The beginning isn't very scenic, though;
perhaps you can find a better starting point.
To maximize exercise while hiking, the trail should start as low as
possible: elevation =a=. The goal is still the square marked =E=.
However, the trail should still be direct, taking the fewest steps to
reach its goal. So, you'll need to find the shortest path from /any
square at elevation =a=/ to the square marked =E=.
Again consider the example from above:
#+begin_example
Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi
#+end_example
Now, there are six choices for starting position (five marked =a=, plus
the square marked =S= that counts as being at elevation =a=). If you
start at the bottom-left square, you can reach the goal most quickly:
#+begin_example
...v<<<<
...vv<<^
...v>E^^
.>v>>>^^
>^>>>>>^
#+end_example
This path reaches the goal in only =29= steps, the fewest possible.
/What is the fewest steps required to move starting from any square with
elevation =a= to the location that should get the best signal?/
Your puzzle answer was =399=.
Both parts of this puzzle are complete! They provide two gold stars: **

172
2022/day12/aoc-c.c Normal file
View File

@@ -0,0 +1,172 @@
/* aoc-c.c: Advent of Code 2022, day 12
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "br.h"
#include "list.h"
#include "pool.h"
#include "aoc.h"
#define MAX_LINES 128 /* should be dynamic */
typedef struct coord {
int x, y;
} coord_t;
typedef struct square {
char height;
int dfs;
coord_t coord;
struct list_head queue;
} square_t;
typedef struct grid {
int nx, ny;
coord_t start, end;
square_t **map;
} grid_t;
pool_t *pool_lines;
LIST_HEAD(dfs);
#define CELL(g, x, y) (&(g)->map[y][x])
static inline void push(square_t *s)
{
list_add_tail(&s->queue, &dfs);
}
static inline square_t *pop()
{
square_t *s = list_first_entry_or_null(&dfs, square_t, queue);
if (s)
list_del(&s->queue);
return s;
}
static int parse(grid_t *grid)
{
size_t alloc = 0;
ssize_t buflen;
char *buf = NULL;
int line = 0;
square_t *pline;
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
buf[--buflen] = 0;
if (line == 0) {
pool_lines = pool_create("lines", 128, buflen * sizeof(square_t));
grid->nx = buflen;
}
grid->map[line] = pool_get(pool_lines);
pline = grid->map[line];
for (int i = 0; i < buflen; ++i) {
pline[i].coord.x = i;
pline[i].coord.y = line;
pline[i].dfs = 0;
if (buf[i] == 'S') {
grid->start.x = i;
grid->start.y = line;
pline[i].height = 'a';
} else if (buf[i] == 'E') {
grid->end.x = i;
grid->end.y = line;
pline[i].height = 'z';
} else {
pline[i].height = buf[i];
}
}
line++;
}
grid->ny = line;
free(buf);
return 1;
}
static square_t *dfs_add(grid_t *g, square_t *s, int n)
{
static coord_t dirs[4] = { { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 } };
int x = s->coord.x + dirs[n].x, y = s->coord.y + dirs[n].y;
square_t *ret = NULL;
if (x >= 0 && y >= 0 && x < g->nx && y < g->ny) {
ret = CELL(g, x, y);
if (!ret->dfs)
return ret;
}
return NULL;
}
static int part1(grid_t *g)
{
square_t *s, *n;
s = CELL(g, g->start.x, g->start.y);
s->dfs = 1;
push(s);
while((s = pop())) {
//log_f(3, "");
for (int i = 0; i < 4; i++) {
if (!(n = dfs_add(g, s, i)))
continue;
if (n->height <= s->height+1) {
if (n->coord.x == g->end.x && n->coord.y == g->end.y)
return s->dfs;
n->dfs = s->dfs + 1;
push(n);
}
}
}
return -1;
}
static int part2(grid_t *g)
{
square_t *s, *n;
//int ret = 0;
s = CELL(g, g->end.x, g->end.y);
s->dfs = 1;
push(s);
while((s = pop())) {
//log_f(3, "");
for (int i = 0; i < 4; i++) {
if (!(n = dfs_add(g, s, i)))
continue;
if (n->height >= s->height - 1) {
if (n->height == 'a')
return s->dfs;
n->dfs = s->dfs + 1;
push(n);
}
}
}
return -1;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
square_t *board[MAX_LINES];
grid_t grid = { 0, 0, { 0, 0 }, {0, 0}, board };
parse(&grid);
printf("%s: res=%d\n", *av, part == 1? part1(&grid): part2(&grid));
pool_destroy(pool_lines);
exit(0);
}

146
2022/day12/aoc.bash Executable file
View File

@@ -0,0 +1,146 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 12
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
. common.bash
#declare -a map map2
declare -A height map visited
declare -i X Y
declare start end push=push1
declare -a queue
printmap() {
local -i x y
for (( y = 0; y < Y; ++y )); do
for (( x = 0; x < X; ++x )); do
printf "%2d " "${map["$x,$y"]}"
done
echo
done
}
printvis() {
local -i x y
for (( y = 0; y < Y; ++y )); do
for (( x = 0; x < X; ++x )); do
printf "%2d " "${visited["$x,$y"]}"
done
echo
done
}
push1() { # push part 1
local -i _d="$1" _x="$2" _y="$3" _h="$4"
local _c="$_x,$_y"
if (( !visited[$_c] && map[$_c] <= (_h + 1) )); then
(( _d++ ))
visited["$_c"]=$_d
queue+=("$_d:$_c")
fi
}
push2() { # push part 2
local -i _d="$1" _x="$2" _y="$3" _h="$4"
local _c="$_x,$_y"
if (( !visited[$_c] && map[$_c] >= (_h - 1) )); then
(( _d++ ))
visited["$_c"]=$_d
queue+=("$_d:$_c")
fi
}
pop() {
local -n _d="$1" _x="$2" _y="$3"
local head
((!${#queue[@]})) && echo pop: queue empty. && exit 1
head="${queue[0]}"
_d=${head%:*}
head=${head#*:}
_x=${head%,*}
_y=${head#*,}
unset 'queue[0]'
queue=("${queue[@]}")
return 0
}
# initialize height values
init() {
declare -i i=1
for c in {a..z}; do
(( height[$c] = i++ ))
done
height[S]=1
height[E]=26
}
parse() {
local -i part="$1"
local -a _map
local -i x y
local c
((part == 2)) && push=push2
init
readarray -t _map
X=${#_map[0]}
Y=${#_map[@]}
# create array map[x,y]
for (( y = 0; y < Y; ++y )); do
for (( x = 0; x < X; ++x )); do
c=${_map[$y]:x:1}
map["$x,$y"]=${height[$c]}
case "$c" in
S) start="$x,$y"
((part == 1)) && $push 0 "$x" "$y" 1
;;
E) end="$x,$y"
((part == 2)) && $push 0 "$x" "$y" 1
;;
esac
done
done
}
solve() {
local -i h d x y
while pop d x y; do
(( h=${map["$x,$y"]} ))
if [[ $part == 1 ]]; then
if [[ "$x,$y" == "$end" ]]; then
res=$((d-1))
return
fi
else
if [[ "${map["$x,$y"]}" == 1 ]]; then
res=$((d-1))
return
fi
fi
if ((y > 0)); then # north
$push "$d" "$x" "$((y-1))" "$h"
fi
if ((x+1 < X)); then # east
$push "$d" "$((x+1))" "$y" "$h"
fi
if ((y+1 < Y)); then # south
$push "$d" "$x" "$((y+1))" "$h"
fi
if ((x > 0)); then # west
$push "$d" "$((x-1))" "$y" "$h"
fi
done
}
main "$@"
exit 0

17
2022/day12/aoc.h Normal file
View File

@@ -0,0 +1,17 @@
/* aoc.c: Advent of Code 2022
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#ifndef _AOC_H_
#define _AOC_H_
extern int parseargs(int ac, char**av);
#endif /* _AOC_H_ */

68
2022/day12/common.bash Normal file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# common.bash: Advent of Code 2022, common bash functions
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
# shellcheck disable=2034
export cmdname=${0##*/}
export debug=0
export res
export LANG=C
shopt -s extglob
set -o noglob
usage() {
printf "usage: %s [-d DEBUG] [-p PART]\n" "$cmdname"
exit 1
}
checkargs() {
local part=1
while getopts p:d: todo; do
case "$todo" in
d)
if [[ "$OPTARG" =~ ^[[:digit:]+]$ ]]; then
debug="$OPTARG"
else
printf "%s: illegal [%s] debug level.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
p)
if [[ "$OPTARG" =~ ^[12]$ ]]; then
part="$OPTARG"
else
printf "%s: illegal [%s] part.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
*)
usage
;;
esac
done
# Now check remaining argument (backup directory)
shift $((OPTIND - 1))
(( $# > 1 )) && usage
return "$part"
}
main() {
local -i part
checkargs "$@"
part=$?
parse "$part"
solve "$part"
printf "%s: res=%s\n" "$cmdname" "$res"
}

49
2022/day12/common.c Normal file
View File

@@ -0,0 +1,49 @@
/* common.c: Advent of Code 2022, common functions
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "aoc.h"
#include "debug.h"
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int parseargs(int ac, char **av)
{
int opt, part = 1;
while ((opt = getopt(ac, av, "d:p:")) != -1) {
switch (opt) {
case 'd':
debug_level_set(atoi(optarg));
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
case 'i':
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
return part;
}

View File

@@ -0,0 +1,5 @@
Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi

View File

@@ -0,0 +1,41 @@
abaaaaaccccccccccccccccccaaaaaaaaaaaaaccccaaaaaaaccccccccccccccccccccccccccccaaaaaa
abaaaaaaccaaaacccccccccccaaaaaaaaacaaaacaaaaaaaaaacccccccccccccccccccccccccccaaaaaa
abaaaaaacaaaaaccccccccccaaaaaaaaaaaaaaacaaaaaaaaaacccccccccccccaacccccccccccccaaaaa
abaaaaaacaaaaaacccccccccaaaaaaaaaaaaaaccaaacaaaccccccccccccccccaacccccccccccccccaaa
abccaaaccaaaaaacccaaaaccaaaaaaaaaaaaaccccaacaaacccccccccaacaccccacccccccccccccccaaa
abcccccccaaaaaccccaaaacccccaaaaacccaaaccaaaaaaccccccccccaaaaccccccccccccccccccccaac
abcccccccccaaaccccaaaacccccaaaaacccccccccaaaaaccccccccccklllllccccccccccccccccccccc
abcccccccccccccccccaaccccccccaaccccccccaaaaaaaccccccccckklllllllcccccddccccaacccccc
abaccccccccccccccccccccccccccaaccccccccaaaaaaaaccccccckkkklslllllcccddddddaaacccccc
abacccccccccccccccccccccccccccccccaaaccaaaaaaaaccccccckkkssssslllllcddddddddacccccc
abaccccccccccccccccccccccccccccccccaaaaccaaacaccccccckkksssssssslllmmmmmdddddaacccc
abcccccccccccccccaaacccccccccccccaaaaaaccaacccccccccckkkssssusssslmmmmmmmdddddacccc
abcccccccaaccccaaaaacccccccccccccaaaaaccccccaaaaaccckkkrssuuuussssqmmmmmmmmdddccccc
abcccccccaaccccaaaaaacccccccaaccccaaaaacccccaaaaacckkkkrruuuuuussqqqqqqmmmmdddccccc
abccccaaaaaaaacaaaaaacccccccaaaaccaaccaccccaaaaaacjkkkrrruuuxuuusqqqqqqqmmmmeeccccc
abcaaaaaaaaaaacaaaaaccccccaaaaaacccccaaccccaaaaajjjjrrrrruuuxxuvvvvvvvqqqmmmeeccccc
abcaacccaaaaccccaaaaaaacccaaaaacccacaaaccccaaaajjjjrrrrruuuxxxxvvvvvvvqqqmmeeeccccc
abaaaaccaaaaacccccccaaaccccaaaaacaaaaaaaacccaajjjjrrrrtuuuuxxxyvyyyvvvqqqnneeeccccc
abaaaaaaaaaaacccaaaaaaaccccaacaacaaaaaaaacccccjjjrrrttttuxxxxxyyyyyvvvqqnnneeeccccc
abaaaaaaaccaacccaaaaaaaaacccccccccaaaaaaccccccjjjrrrtttxxxxxxxyyyyyvvvqqnnneeeccccc
SbaaaaaacccccccccaaaaaaaaaccccccccaaaaacccccccjjjrrrtttxxxEzzzzyyyvvrrrnnneeecccccc
abaaaaacccccccccccaaaaaaacccccccccaaaaaaccccccjjjqqqtttxxxxxyyyyyvvvrrrnnneeecccccc
abaaacccccccccccaaaaaaaccaaccccccccccaaccaaaaajjjqqqttttxxxxyyyyyyvvrrrnnneeecccccc
abaaacccccccccccaaaaaaaccaaacaaacccccccccaaaaajjjjqqqtttttxxyywyyyywvrrnnnfeecccccc
abcaaacccccccaaaaaaaaaaacaaaaaaaccccccccaaaaaaciiiiqqqqtttxwyywwyywwwrrrnnfffcccccc
abcccccccccccaaaaaaaaaaccaaaaaacccccccccaaaaaacciiiiqqqqttwwywwwwwwwwrrrnnfffcccccc
abccccccccccccaaaaaacccaaaaaaaacccccccccaaaaaaccciiiiqqqttwwwwwswwwwrrrrnnfffcccccc
abccccccccccccaaaaaacccaaaaaaaaacccccccccaaacccccciiiqqqtswwwwssssrrrrrroofffcccccc
abccccccaaaaacaaaaaacccaaaaaaaaaaccccccccccccccccciiiqqqssswsssssssrrrrooofffaccccc
abccccccaaaaacaaccaaccccccaaacaaacccccccccccccccccciiiqqssssssspoorrrooooofffaacccc
abcccccaaaaaacccccccccccccaaacccccccccccccccccccccciiiqppssssspppooooooooffffaacccc
abcccccaaaaaacccccccccccccaacccccccccccccccccccccccciipppppppppppoooooooffffaaccccc
abcccccaaaaaaccccccccccccccccccccccccccccccccccccccciihppppppppgggggggggfffaaaccccc
abccccccaaacccccccccccccccccccccccaccccccccccccccccchhhhpppppphggggggggggfaaaaccccc
abaaaccccccccccccccccccccccaccccaaacccccccccccccccccchhhhhhhhhhgggggggggcaacccccccc
abaaccaaaccaccccccccccccccaaacccaaacaacccaaaaacccccccchhhhhhhhhgaaccccccccccccccccc
abaaacaaacaacccccccccaaaccaaaacaaaaaaaaccaaaaaccccccccchhhhhhaaaaacccccccccccccccca
abaaaccaaaaaccccccccccaaacaaaaaaaacaaaaccaaaaaaccccccccccaaacccaaaacccccccccccaccca
abcccaaaaaaccccccccccaaaaaaaaaaaaacaaaaccaaaaaaccccccccccaaaccccaaaccccccccccaaaaaa
abcccaaaaaaaacccccccaaaaaaaaaaaaaaaaaccccaaaaaacccccccccccccccccccccccccccccccaaaaa
abcccaacaaaaaccccccaaaaaaaaaaaaaaaaaaacccccaacccccccccccccccccccccccccccccccccaaaaa

111
2022/day13/Makefile Normal file
View File

@@ -0,0 +1,111 @@
# AOC daily Makefile - GNU make only.
#
# Copyright (C) 2021-2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
INPUT := input/input.txt
SHELL := /bin/bash
CC := gcc
BEAR := bear
CCLSFILE:= compile_commands.json
LIB := aoc_$(shell uname -m)
INCDIR := ../include
LIBDIR := ../lib
LDFLAGS := -L$(LIBDIR)
#LDLIB := -l$(LIB) -lm
LDLIB := -l$(LIB)
export LD_LIBRARY_PATH = $(LIBDIR)
CFLAGS += -std=gnu11
CFLAGS += -O2
CFLAGS += -g
# for gprof
# CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
# Next one may be useful for valgrind (some invalid instructions)
# CFLAGS += -mno-tbm
CFLAGS += -Wmissing-declarations
CFLAGS += -Wno-unused-result
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
CFLAGS += -DDEBUG_POOL # memory pools management
VALGRIND := valgrind
VALGRINDFLAGS := --leak-check=full --show-leak-kinds=all --track-origins=yes \
--sigill-diagnostics=yes --quiet --show-error-list=yes
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
export PATH := .:$(PATH)
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 part1 part2 ccls bear org
all: README.org ccls part1 part2
memcheck: memcheck1 memcheck2
memcheck1: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
memcheck2: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
@#@valgrind -s --track-origins=yes aoc-c -p 2 < $(INPUT)
compile: aoc-c
cpp: aoc-c.i
assembly: aoc-c.s
part1: aoc-c
@#$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 1 < $(INPUT)
part2: aoc-c
@#$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html compile_commands.json
aoc-c: aoc-c.c common.c
@echo compiling $<
$(CC) $(CFLAGS) $(LDFLAGS) -I $(INCDIR) $^ $(LDLIB) -o $@
# generate pre-processed file (.i) and assembler (.s)
%.i: %.c
@echo generating $@
@$(CC) -E $(CFLAGS) -I $(INCDIR) $< -o $@
%.s: %.c
@echo generating $@
@$(CC) -S -fverbose-asm $(CFLAGS) -I $(INCDIR) $< -o $@
# generate README.org from README.html (must cleanup !)
org: README.org
%.org: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@touch .ccls-root
@$(BEAR) -- make compile

197
2022/day13/README.org Normal file
View File

@@ -0,0 +1,197 @@
** --- Day 13: Distress Signal ---
You climb the hill and again try contacting the Elves. However, you
instead receive a signal you weren't expecting: a /distress signal/.
Your handheld device must still not be working properly; the packets
from the distress signal got decoded /out of order/. You'll need to
re-order the list of received packets (your puzzle input) to decode the
message.
Your list consists of pairs of packets; pairs are separated by a blank
line. You need to identify /how many pairs of packets are in the right
order/.
For example:
#+begin_example
[1,1,3,1,1]
[1,1,5,1,1]
[[1],[2,3,4]]
[[1],4]
[9]
[[8,7,6]]
[[4,4],4,4]
[[4,4],4,4,4]
[7,7,7,7]
[7,7,7]
[]
[3]
[[[]]]
[[]]
[1,[2,[3,[4,[5,6,7]]]],8,9]
[1,[2,[3,[4,[5,6,0]]]],8,9]
#+end_example
Packet data consists of lists and integers. Each list starts with =[=,
ends with =]=, and contains zero or more comma-separated values (either
integers or other lists). Each packet is always a list and appears on
its own line.
When comparing two values, the first value is called /left/ and the
second value is called /right/. Then:
- If /both values are integers/, the /lower integer/ should come first.
If the left integer is lower than the right integer, the inputs are in
the right order. If the left integer is higher than the right integer,
the inputs are not in the right order. Otherwise, the inputs are the
same integer; continue checking the next part of the input.
- If /both values are lists/, compare the first value of each list, then
the second value, and so on. If the left list runs out of items first,
the inputs are in the right order. If the right list runs out of items
first, the inputs are not in the right order. If the lists are the
same length and no comparison makes a decision about the order,
continue checking the next part of the input.
- If /exactly one value is an integer/, convert the integer to a list
which contains that integer as its only value, then retry the
comparison. For example, if comparing =[0,0,0]= and =2=, convert the
right value to =[2]= (a list containing =2=); the result is then found
by instead comparing =[0,0,0]= and =[2]=.
Using these rules, you can determine which of the pairs in the example
are in the right order:
#+begin_example
== Pair 1 ==
- Compare [1,1,3,1,1] vs [1,1,5,1,1]
- Compare 1 vs 1
- Compare 1 vs 1
- Compare 3 vs 5
- Left side is smaller, so inputs are in the right order
== Pair 2 ==
- Compare [[1],[2,3,4]] vs [[1],4]
- Compare [1] vs [1]
- Compare 1 vs 1
- Compare [2,3,4] vs 4
- Mixed types; convert right to [4] and retry comparison
- Compare [2,3,4] vs [4]
- Compare 2 vs 4
- Left side is smaller, so inputs are in the right order
== Pair 3 ==
- Compare [9] vs [[8,7,6]]
- Compare 9 vs [8,7,6]
- Mixed types; convert left to [9] and retry comparison
- Compare [9] vs [8,7,6]
- Compare 9 vs 8
- Right side is smaller, so inputs are not in the right order
== Pair 4 ==
- Compare [[4,4],4,4] vs [[4,4],4,4,4]
- Compare [4,4] vs [4,4]
- Compare 4 vs 4
- Compare 4 vs 4
- Compare 4 vs 4
- Compare 4 vs 4
- Left side ran out of items, so inputs are in the right order
== Pair 5 ==
- Compare [7,7,7,7] vs [7,7,7]
- Compare 7 vs 7
- Compare 7 vs 7
- Compare 7 vs 7
- Right side ran out of items, so inputs are not in the right order
== Pair 6 ==
- Compare [] vs [3]
- Left side ran out of items, so inputs are in the right order
== Pair 7 ==
- Compare [[[]]] vs [[]]
- Compare [[]] vs []
- Right side ran out of items, so inputs are not in the right order
== Pair 8 ==
- Compare [1,[2,[3,[4,[5,6,7]]]],8,9] vs [1,[2,[3,[4,[5,6,0]]]],8,9]
- Compare 1 vs 1
- Compare [2,[3,[4,[5,6,7]]]] vs [2,[3,[4,[5,6,0]]]]
- Compare 2 vs 2
- Compare [3,[4,[5,6,7]]] vs [3,[4,[5,6,0]]]
- Compare 3 vs 3
- Compare [4,[5,6,7]] vs [4,[5,6,0]]
- Compare 4 vs 4
- Compare [5,6,7] vs [5,6,0]
- Compare 5 vs 5
- Compare 6 vs 6
- Compare 7 vs 0
- Right side is smaller, so inputs are not in the right order
#+end_example
What are the indices of the pairs that are already /in the right order/?
(The first pair has index 1, the second pair has index 2, and so on.) In
the above example, the pairs in the right order are 1, 2, 4, and 6; the
sum of these indices is =13=.
Determine which pairs of packets are already in the right order. /What
is the sum of the indices of those pairs?/
Your puzzle answer was =5843=.
** --- Part Two ---
Now, you just need to put /all/ of the packets in the right order.
Disregard the blank lines in your list of received packets.
The distress signal protocol also requires that you include two
additional /divider packets/:
#+begin_example
[[2]]
[[6]]
#+end_example
Using the same rules as before, organize all packets - the ones in your
list of received packets as well as the two divider packets - into the
correct order.
For the example above, the result of putting the packets in the correct
order is:
#+begin_example
[]
[[]]
[[[]]]
[1,1,3,1,1]
[1,1,5,1,1]
[[1],[2,3,4]]
[1,[2,[3,[4,[5,6,0]]]],8,9]
[1,[2,[3,[4,[5,6,7]]]],8,9]
[[1],4]
[[2]]
[3]
[[4,4],4,4]
[[4,4],4,4,4]
[[6]]
[7,7,7]
[7,7,7,7]
[[8,7,6]]
[9]
#+end_example
Afterward, locate the divider packets. To find the /decoder key/ for
this distress signal, you need to determine the indices of the two
divider packets and multiply them together. (The first packet is at
index 1, the second packet is at index 2, and so on.) In this example,
the divider packets are /10th/ and /14th/, and so the decoder key is
=140=.
Organize all of the packets into the correct order. /What is the decoder
key for the distress signal?/
Your puzzle answer was =26289=.

240
2022/day13/aoc-c.c Normal file
View File

@@ -0,0 +1,240 @@
/* aoc-c.c: Advent of Code 2022, day 13
*
* Copyright (C) 2022-2023 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "br.h"
#include "list.h"
#include "pool.h"
#include "aoc.h"
typedef enum { SUBLIST, INT } type_t;
typedef struct node { /* node */
type_t car_t;
union { /* CAR */
struct list_head sub; /* sublist */
int value; /* value */
};
struct list_head cdr; /* CDR */
} node_t;
typedef struct { /* packets ordered list */
struct list_head node; /* packet head */
struct list_head list; /* packets lists */
} packets_t;
LIST_HEAD(packets);
/* dummy node for integer vs list */
static struct list_head dummy_list; /* tentative definition */
static node_t dummy = {
.car_t = INT, .value = 0, .cdr = LIST_HEAD_INIT(dummy_list)
};
static struct list_head dummy_list = LIST_HEAD_INIT(dummy.cdr);
pool_t *pool_node, *pool_packets;
/* int getnode - allocate and initialize a new node
* @type: The node type_t (INT/LIST)
* @val: The value if @type is INT
*
* Return: The new node.
*/
static node_t *getnode(type_t type, int val)
{
node_t *node = pool_get(pool_node);
node->car_t = type;
INIT_LIST_HEAD(&node->cdr);
if (type == INT)
node->value = val;
else
INIT_LIST_HEAD(&node->sub);
return node;
}
/* int compare tree - compare two packets trees
* @h1: The first packet list head
* @h2: The second packet list head
*
* Return: 1 if h1 and h2 are ordered, -1 if not ordered, 0 if undecided
*/
static int compare_tree(struct list_head *h1, struct list_head *h2)
{
struct list_head *cur1, *cur2;
node_t *n1, *n2;
int res;
/* get lists first entries */
cur1 = h1->next;
cur2 = h2->next;
while (cur1 != h1 && cur2 != h2) {
n1 = container_of(cur1, node_t, cdr);
n2 = container_of(cur2, node_t, cdr);
if (n1->car_t == n2->car_t) {
if (n1->car_t == INT) {
if (n1->value < n2->value) {
return 1;
} else if (n1->value > n2->value) {
return -1;
}
} else { /* both sublists */
if ((res = compare_tree(&n1->sub, &n2->sub)))
return res;
}
} else { /* one number, one list */
if (n1->car_t == INT) {
dummy.value = n1->value;
res = compare_tree(&dummy_list, &n2->sub);
} else {
dummy.value = n2->value;
res = compare_tree(&n1->sub, &dummy_list);
}
if (res)
return res;
}
cur1 = cur1->next;
cur2 = cur2->next;
}
/* at least one list came to end */
if (cur1 == h1 && cur2 == h2) /* both are ending */
return 0;
else if (cur1 == h1) /* first list did end */
return 1;
else
return -1;
}
/* int add_node - add a packet to the sorted packets list
* @new: The new packets list head
*
* Return: The new packet position in list (first is 1)
*/
static int add_node(packets_t *new)
{
packets_t *first, *iter;
struct list_head *node_next = &packets;
int num = 1;
if (list_empty(&packets))
goto ins_node;
first = iter = list_first_entry(&packets, packets_t, list);
do {
if (compare_tree(&new->node, &iter->node) > 0) {
node_next = &iter->list;
break;
}
iter = list_entry(iter->list.next, packets_t, list);
num++;
} while (iter != first);
ins_node:
list_add_tail(&new->list, node_next);
return num;
}
static struct list_head *create_tree(char *s, int *consumed, struct list_head *head)
{
node_t *node = NULL;
LIST_HEAD(sub);
int val, depth = 0, subconsumed;
*consumed = 1;
INIT_LIST_HEAD(head);
for (; *s; s++, (*consumed)++) {
switch (*s) {
case '[':
if (++depth == 2) { /* we skip first depth level */
node = getnode(SUBLIST, 0);
list_add_tail(&node->cdr, head);
create_tree(s, &subconsumed, &node->sub);
s += subconsumed - 1;
*consumed += subconsumed - 1;
depth--;
}
break;
case ',':
break;
case ']':
if (!--depth)
goto end;
break;
default: /* number */
sscanf(s, "%d%n", &val, &subconsumed);
*consumed += subconsumed - 1;
s += subconsumed - 1;
node = getnode(INT, val);
list_add_tail(&node->cdr, head);
break;
}
}
end:
return head;
}
static int parse()
{
size_t alloc = 0;
ssize_t buflen;
char *buf = NULL;
packets_t *head[2];
int i = 0, dummy, res = 0;
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
buf[--buflen] = 0;
if (buflen > 0) { /* non empty line */
head[i % 2] = pool_get(pool_packets);
create_tree(buf, &dummy, &head[i % 2]->node);
add_node(head[i % 2]);
}
if (buflen != 0) { /* non empty line or EOF */
if (i % 2 && compare_tree(&head[0]->node, &head[1]->node) == 1)
res += (i >> 1) + 1; /* (i / 2) + 1 */
i++;
}
}
return res;
}
static int part1()
{
return parse();
}
static int part2()
{
char *dividers[] = { "[[2]]", "[[6]]" };
int dummy, res = 1;
parse();
for (ulong i = 0; i < ARRAY_SIZE(dividers); ++i) {
packets_t *h = pool_get(pool_packets);
create_tree(dividers[i], &dummy, &h->node);
res *= add_node(h);
}
return res;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
pool_node = pool_create("node", 512, sizeof(node_t));
pool_packets = pool_create("packets", 512, sizeof(packets_t));
printf("%s: res=%d\n", *av, part == 1? part1(): part2());
pool_destroy(pool_node);
pool_destroy(pool_packets);
exit(0);
}

17
2022/day13/aoc.h Normal file
View File

@@ -0,0 +1,17 @@
/* aoc.c: Advent of Code 2022
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#ifndef _AOC_H_
#define _AOC_H_
extern int parseargs(int ac, char**av);
#endif /* _AOC_H_ */

68
2022/day13/common.bash Normal file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# common.bash: Advent of Code 2022, common bash functions
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
# shellcheck disable=2034
export cmdname=${0##*/}
export debug=0
export res
export LANG=C
shopt -s extglob
set -o noglob
usage() {
printf "usage: %s [-d DEBUG] [-p PART]\n" "$cmdname"
exit 1
}
checkargs() {
local part=1
while getopts p:d: todo; do
case "$todo" in
d)
if [[ "$OPTARG" =~ ^[[:digit:]+]$ ]]; then
debug="$OPTARG"
else
printf "%s: illegal [%s] debug level.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
p)
if [[ "$OPTARG" =~ ^[12]$ ]]; then
part="$OPTARG"
else
printf "%s: illegal [%s] part.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
*)
usage
;;
esac
done
# Now check remaining argument (backup directory)
shift $((OPTIND - 1))
(( $# > 1 )) && usage
return "$part"
}
main() {
local -i part
checkargs "$@"
part=$?
parse "$part"
solve "$part"
printf "%s: res=%s\n" "$cmdname" "$res"
}

49
2022/day13/common.c Normal file
View File

@@ -0,0 +1,49 @@
/* common.c: Advent of Code 2022, common functions
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "aoc.h"
#include "debug.h"
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int parseargs(int ac, char **av)
{
int opt, part = 1;
while ((opt = getopt(ac, av, "d:p:")) != -1) {
switch (opt) {
case 'd':
debug_level_set(atoi(optarg));
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
case 'i':
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
return part;
}

View File

@@ -0,0 +1,23 @@
[1,1,3,1,1]
[1,1,5,1,1]
[[1],[2,3,4]]
[[1],4]
[9]
[[8,7,6]]
[[4,4],4,4]
[[4,4],4,4,4]
[7,7,7,7]
[7,7,7]
[]
[3]
[[[]]]
[[]]
[1,[2,[3,[4,[5,6,7]]]],8,9]
[1,[2,[3,[4,[5,6,0]]]],8,9]

449
2022/day13/input/input.txt Normal file
View File

@@ -0,0 +1,449 @@
[[[5,1,[],[8,1,3],6],[[7]]],[10,[]],[6],[[],[[0,6,4,10,5],[2,2,9],[4,4],[2,10,4,10,8]],7,7],[[5],5,[[6],[8,2],[5],[]],[9,3,2,[9,4,8,6,8]]]]
[[5]]
[[[5,3,[],[5,3,10],2],[[5,0,9,1]]],[[[9,0],[9,6,3]]],[[[1],1,[7,6],10],4],[2]]
[[],[[2,[9,2,6,9],10],[[2,8,10],[4,6],[1,6,4,6],[2,10,1,0,6]],6,[7,6,3,[10,6,4,5],4]],[],[2,2,[]],[2,9,[[3,3,9,6],[6,8,7,9,6],10,2,[6,9,8,7,0]],[7]]]
[[[4,6,7]],[[1,10,8,[7,2]],10],[10],[[3,7,8,[6,7],[]],8,[4,[5,0,9,1],[6,1,2,6,5]]]]
[[[3,[1,8,7,6],[3,8,7,7],[],[8,5]],[[1,8,10],[10,8,9]],8,[[8],9,[],3],[7,9,8,[2,10,7]]],[8,2],[6]]
[[3]]
[[2,[],[]],[[5,8,[6]],[[0,6,8,10],[]],[[9,6],6,8]],[[],4,2,[0,[1,4,2,7],6],[0,7]]]
[[[0,2,[10,5,8]],[[],7,[],[5,2,0,1]],6,10],[],[[],8,0,3,[4,0,[8,5,8,3]]],[0,[1,5],[[8,5,2],9,[8,5,2],[9,9,7,8]],5]]
[[0,6,[[5,8,6],6,[1,8,2]],[[],[10],[],3,7],2],[[[],3],7,[6,2,[]],[[]]]]
[[6,8],[[9,[2,0,7],4,10],[[0,2,10,6,4],8,[7,7,2,8,7]]],[],[6,[]],[[[3,0,6]]]]
[[9,[[],[1,6,1,0,6],[8],[2]],[8,[2,5,10,0,10],1,[7],[6,5]]],[2,[9,0,[1,5,5,0,8]],9,2],[]]
[[7,0,1,[[2,1],[8],[9,9,4,8,6],10]],[7,[5,[10,5,6],6,[4,10,7,5,10]],[1]]]
[[1,[],[[4]],3],[[[8],[4,5]],[[10],[],[3],[6,2,9],[0,8]]]]
[[[2,[],4],[],3,[4,[8,0,1,2],[],[4,0,2],[0,7,4,5,6]]]]
[[1,[],[[6],[10],[6,4,6,1,7],[0,7,1]],[],[[1],[0,8,3],[6],[2,5,7,8,10],[5,5,3]]],[[4,5,2,2,[]],4,[[6,1,7,3],8,[0,5,0]]]]
[[[0,[2,6,4],3,[8,0,10],[5]]],[[[10,4,3,0,3],[3,0,9,3,5],5,[5,7,3]],[2,3],[]]]
[[3,[[5,5,3,10,10],4,[]],7,1],[3],[[[7,7,3,7],10,[9,8,9,9],[],8],6,1,[]],[[1,[8],1],3,[[9,5,4],9,0,[0],2]],[[[1],6],4,1,[]]]
[[[10,0,[7]],4,6,[4,5]],[[2,4,[0,3,7,10,9]]],[[[6,5,9],[6,9,6,3],[1,8,4,5],8],[9],[[9,3],3,[7,5],7]],[[[]],[[2,5,4],[],[],[0,1,2,2],[5,1,1,7,8]]],[3,6,8,6,[[6,1],[]]]]
[[6,2],[4,[],[[7,7,5,9],8,[6,10,2,0,9]],2,[1,6]],[[[1,5,10,8]],8,0,0,8],[6,4,[[6,4,6,7],4],[[1,3,7,1],[0,2,4,1,10],[1]],10],[]]
[[[5,[1,6,2,5,5],[3],[7,3]],[[4,6,2,1,2]],9,7],[0,5,10],[9]]
[[10,0],[[2,[7,4,6],9,3,[0,7,10,9,1]],5,[4,[],2,8,[0,8,6]]]]
[[],[[[],6,9],[[8],[2,5,4,6],[5,6,8],[5,4,4,6],[]],[[2,6,8,1],0,[7,1,9,6]]],[2,0,1,2],[]]
[[[[],[7,5,5],[3]]],[[[6,7,6],[7,1,1]],4,[7,[2,10],4,[2,2]],0,[[7],10,5,4,[2,5,5,2,1]]]]
[[[[3,4,6,2,6],[],6],[[1],5,[1],2,[5]],10,0],[9,[]]]
[[],[[]],[[[],2,[0,3,9,10],5]],[]]
[[[[2,6,0,9],[],[],[9,3,2,9],[9,10]],6,[[4,1,6,2],1],[[10,1],[0,5,5,4],[],4,[8,8,0,1,6]]],[[5],6,[[9,4],4,0],7],[9,[],[6,4]],[],[]]
[[[[9,3,0,2],[4,10],[0],[5,5,0]],1,7,[[0]]],[],[[[2,10,10],[6]],6,[7,0,[4,0,8],6,5],2],[],[8]]
[[1,1,3],[[[],7,[0,5,0,2],[10]]]]
[[],[[[3,4,7],[7,2],[1]],[[1],9,[3,1,3],[3],10]],[[[],5,[2],4],10],[[[2,6,6,8,3],[6,0,7],1],[[8,8,3,0,3],[4,8,10],0],6,[[10],[10,2,6,6,7]]]]
[[9,2,3]]
[[],[],[[[],[10,8,7,4],0,5],3,7,[6,[1,4,5,10]],1],[[],[1,5,[7,3]],[7,10,[10],[3]],[8],2],[]]
[1,5,3,3,5]
[1,5,3,3]
[[8,[[2,6,0,9],[4,9,5,5,3],[8],8,3],[1]],[0,[7,[8,8,8,1]],[],[[0],[8,6,9,9,1],2,6,2]],[],[1,[2,1,[1],8],[],8],[[9,7],[7,10],[[],9,9,7,3],[2,[],6],[[],5,[7,6,7,6,0],[3],[3,10,10,10]]]]
[[[[8],1,[1,1,3,5,1],[0,3]],[],4,0,5],[],[3,3,[9,4,5,[4,2,3]],7,9],[7],[[[2,1]],[[2,9,10,0,6],[3,0,8],[0,3,2,9,1]]]]
[[[[5],7],3,[9,[2,6,0,2,3]],[],3],[4]]
[[10,7,8,[[],[9,10],1],[4,5,[2]]],[[5,[3,9,6,5],[],2],[9,4],[6,[2,4,8,1,7],10],1,[2,[3,6,1,5],1,[5,10],[]]],[9,8],[7,9,4,[5,[4,4,0],[9,10]],9],[]]
[[2,0,[2,8,10],[[10,9,4,0],[7,6,8,1,9],[2,5,6,9,5],[]]],[8],[6,7,4,[[0,5],4,5,3,[8,6,4,6]]]]
[[[[3,6,5,5],[6,10,3,2,9],[8,7],[6,5,7]],[[3,10,7,10,5],[9],5,[1,9,1,5,5]],5,10,[[2,1,2,3],[1,0,10,1],[1,5,3]]]]
[[1,7,[9,[2,2,5,4,5],4],[[0]]]]
[[[[8],9,5,2]],[7],[0,8,[1,3,[6,5,10,2,6],9],9],[[[7,0,6,3]],[[2,1,5,9],7,[4,2,1,7],[3,0,0,10],10],[],[[4,9,3],[]],[]],[4]]
[[1]]
[[[],[9,[4,2],4,8],[8,8,0,[5,8,10],[4,1,7,10,0]]],[0,6]]
[[2,[[1,7,10,3,10],4,5],6,[[3,9,7,8,5],[]]]]
[[[[]]],[[[5,2,9,7,2],2,5,8],2,9,[5,3],2],[4,[[],4,7,[1,10],[2,1,0,0,8]],4,7],[8,[8,3,2,5,10],[4,[10,4],[2,10,9,5],[2,6],[3]],2]]
[[[[5,5,2,7,6]],[],[]],[10,6,[6,9,7]],[[[8,1]],[],0,[[],[1,0],[]],0]]
[[4,[[10,1,5]],1],[],[1,5,8,[[6,10]],[[6],9,[0,3],[],[6,3,7]]],[10,[],[[1,4],8,[5,8]],[3,5,2,[],0]],[10,[3,[4,1,6,5]]]]
[[6,10,[10,[6]]],[8,[[8,8],2,1]],[9,[6,2,[0,0,9,10,9]],1,1]]
[[],[10,[[7,5],[3,10,7,8]]],[[]],[[10,[2,9],8,2,4],[1,[2],[10,5,3],1],0,3],[[[0,4,6]],[[6,0,9]],[[6,4,6,10],[1,8,8],3,7,4],[3,2,[0]]]]
[[3,5],[[7,[8,2],[9,8]],[[3,1,0,6,10],[],[7,8,1,10]],[[],10,[4,6,7],5,[2,10,7,6,5]],[6,[3,7,8,2,7],5],[[6,3],[7,8,4,0,8],9,[0],[0,10,7,0,2]]],[[],[[4,6,1,9]],3,[],[8,[6,3,4],[5,10,6,0,9]]],[[],9,0,[[1,7,9,10],0,10,4],4],[]]
[[],[[4],[[],0],[5,[4,7,5,9,6],[8,10,0,5,0],10,[1,0,7,6,1]]],[],[]]
[[2,6,3],[],[[7,[3,9,2,10],2,[10,0,1,3,6]],[3,[3,8,9,7,3],6],[],[[],1,0],8],[8,4,[],0],[8]]
[[7],[10,5],[[[2,6,10,9,1],7,[]],[[4,1,10,4],10,10],0],[2,7,[[9,7],[7,3,9,9],[1,8]],[],[[7,10,4],[5,2,2,6],[],2]],[[8,9],9,4]]
[[[7,[9,10,1,4,0],[4,10,2,1]],7]]
[[10],[[4,9,3],9],[4],[],[7,[7],[[10,9,8,4,10],3]]]
[[9,6,[],[],[9]],[8,[4,[1,1,10,8]],1,9,10],[[],[6,4,[9,0,2,6]]],[[4,[0,8],7,[8,1]],5]]
[[2,8],[[[1,6,6],[6]],[8,[2,10],[1,2,6,3,9],[9],4]],[[3,3,[7,0,9,8,8]],[[9,7,7],4,[4,1],[10,3],[]],[[9,8],[2]],7],[],[10,[6,[],7],[[],[5,10],[5,4],2]]]
[[[[0],[2],3,[4,1,8,8,8]]],[],[[[7,5,3]],[8]]]
[[[[3],0,[0,3,7,1],9,2],[3,2,3,[6]],[],[],0]]
[[1,4,[]],[0,0,10,10,[]],[[0,[8],[4,0]],[10],[2]],[[[],[7,1,1,10]],[7,[],[8],4,[2,9,3]],[1],[[10,8,10,5],2,[5],[10,10]],[[3,2,1,9,5],9,[5,3,7],3]]]
[[[8],7,1,0],[6,1],[[2],1,[],[7]],[]]
[[6,2,[],[4,3,5,2,8],[[4,5,4,7],3,[2,9,1,7,0],[7,4,6,6,7]]],[],[10,[[9,10],4],7,0],[4],[3,[],9,8]]
[[[10,[7,3,4,7,6],6,4,[9]],[9,[],8,[6],[5,4,7]],[5,6],[5,2,[3,1,10,0],[9]]],[[1]]]
[[],[[[3],10,3,7]],[]]
[[],[[],4,[2,[0],0,[]],4],[],[[5,0,10,6,9],2]]
[[4],[[8,[4,4,3,2]],[],[],5],[[]],[],[[3,6],10,8,[[3],6,7,2]]]
[[7,[2,[2,0,8],[6]],[]],[],[]]
[[[[3,8,2,9],5,[5,5,5,0],[10,7,1,0]]],[[[5]],[[9,4,5]],[],0],[[],8,2]]
[[0,[8],7],[[0,0,0],[[3,7,9,2]],1],[5,6,[[9],[9,7,2,3,2],[0,8,1,4]],10,2]]
[[0,[8,[6,6],[0,7],8],4,10],[6,10,[9],[8,[5,2,8,8,6]]],[6,5,9,[]]]
[]
[[[[],10,[10,9,6,5,5],5],4,2,6],[],[],[],[]]
[[5,[[],[]],[]],[8,[[10,8,6],9,[0,5,6],5],[0,[]],4],[[]]]
[[5,5,[],6,3],[[[1,9,7,8],[6]],[[6,2,2,10],[3,10,4,1],6,1],0,3,[[1,6,7,5,2],0,[],[9,2,3],4]],[7,8,[[5,1,3],[],9],[2]],[],[[[9,1,4,7,5]],8,[9,0,[1,5,10]],9,[3,[],[],1]]]
[[],[2,[1,0,0,[5,4],[]],[[2,10,7],9,0],4],[[3,10],7,[2,1],[[6],10],[10,[7,6,3,6,9],[10,6,6],[],5]],[6,[[9,3,10,10],[0,7,10,7],5,0],3],[[9,[3],[8,8],[1,6]],[[9,9,4,8,4]],[4],3]]
[[[0,8,9,[9,4,9],[10,5,0,0]],2],[9],[[[6,8]]]]
[[[0],[[0,1]],6,7,7]]
[[[[3,9,8]]],[3,[7,[7,7,4]]],[[4],[3,7,[3,10,9,2],2],[4,[8,5,7],0]],[],[[]]]
[[[[7,7],[0,3,9]],6,[7,6],[2,5,[2]]],[],[[[0,5,7,6],[3,5,2],[4,5,6,9],[5,8,10,1,0]],2,[9,[7,10]],4,7],[9,[[9,0,5,9,10],7],9,9,[[10,2,6],[10,5,9],4,1]]]
[[7,[[0,1,2],7,3,6,[6,8,10,9]],[[1,10]]],[[9,5,3],[[2,0,4,9,8],4,[9]]]]
[[0,4,5,2]]
[[[[0,8]],[7,9,[4,1]]],[[[7]]]]
[[[[5,6],[6]],[[],[]],[0,[9,6]]],[2],[[7,6,2,5,1],[[1],[9,5,8],[]],6],[[0,2,9,4,7],[3,[5],10,[],[10]]]]
[[[[0,4,8,6]],3,[9,[9,4,1],[10,0,3],[]],6],[],[],[[[3,8,6,8,3],[],[0],0,3],10]]
[[2,4,8,3,[[10,0,0,7],[1],[10,8],[9,4],[]]],[0,10,4],[10,[2,7,3]],[7,8,4,2,3],[]]
[[6],[6,[8,[0]],8,[]]]
[[[],10],[2,[[4,10,1,2,10],[1,10,3,10],[],[4,6,1],1],[[4]],10],[4,1,2,4,[[6,0,10,8,3]]],[[[6,2]]]]
[[[8],[1,5,3],[]]]
[[],[[[7,1,5,2],[0,9],5,[6,8,8,1,4]],[6,[7],5,[],[2]],[1,7,3,[0,8,8,2,8],[4,0,0]],3,1],[8,[[]],[10,0,6,[2,8,1,4,0],8]],[],[3,[[1,6,3,10],1],[],[[5],[10,6,4],[4]]]]
[[[],[[1],[8,5,5,5,9],[3],[]],3,9],[],[[],[5,[7,4],[]]]]
[[[[1,10,2]],4,[9,[8,6,7,1,4],8],9,9],[4,10,[[4,0,9],[7],5,[]],[7,[2,9,7],[],1]],[[[9,7,9,2],4]],[[1,2,[3,1],[10,9,1,10,10],10],9,3,10,3]]
[[],[10,[0,[10,10,1,2,10]],1,[]],[[],[[7,5,1,8],2,0],4,[9,5]],[[10,6]],[]]
[[6,[1,8,1,3]],[[0,[2,2,9,8,5],6,[5,2,5]],0,1,7],[[9,[1],0,5,6],3,[9]],[[[3,4,1,0],[5,3,2,8,10],[9,6],[9,5,1,8],2]]]
[[7],[[9,[10],[4,9],5],[2,[6,0,1],4,3]],[9],[[]]]
[[[3,[],[6]],[10],0,[[6,5,8,0,1],[8,9,4,7,0]],[]]]
[[4,[[],[],[7,4,8,3]],[],[[4,7,7,0,5]],[5,7,7]],[9,[],[[8,8,8,5,9],7,[5,3,7,10]]],[[7,[7],4,[],[9,5,6,10,9]],[10]]]
[[6,[[6,10,10],[5,3,10,7]],[10,9,[4]],9],[7,[]],[[[9,2,0,3,0]],9,[[1,6,9,6],4,[9,2],[2,9,7]]]]
[[],[[[4],8],4,[8],[2,3]]]
[[10,[[0,8,10,6],2],[[8,5,6],[2,4,2,9],[2],7]],[],[[7,4,[9,5]],1,0,[[0,8,4,3,7]],8],[[4,9,2,[6,8,3,6,2],10]],[]]
[[[],0,4],[10,8,[],6,7]]
[[2,[5,7]],[10]]
[[[[3],8,4,[6,8,7,3],9],[[9,9,10,4,2],3,[0,8,2]],9,[]],[9,6],[6,[[4,9],2],6,[[],[9,0,6,6,6],[6]]],[[2,[8,9,7,8],10,10],[]],[]]
[[[[1,7],[4,8,9,1,9],[3,9,5,3],5,8],2,1,[6,5],7],[]]
[[7,0,[4],[[6,7,3],7,3,[6,4,3,5,6],4]],[],[2,[[],[0,0]],[[0,3,3,4,5],5,3,[7,9,8,3,3],6]]]
[[8,1,1,[0,[],6,[7,5]],10],[[]],[3,[[0]],8,0,2],[7,[0,[2,7,4],1]],[[],[],3]]
[[1,6,[]]]
[[[[]],[10,[6,1,4,2,10]],[[7,2,7],1],[[3,8,5,2],[3],[10],8,10],0],[2],[[[7,8,5],2,9,[4,0,0],[]]]]
[[7,[6,10,5,5],1,5,[[2,7,3],7,1,9,5]],[[2,2,[8]],[],[5,9,0]],[[9],6,[[4,7,1,0,5],5,9,[3,10]]]]
[[0],[0,9,[1,10,10],3,[[8],[0],[],[3,8]]],[4,1,1,8,[[0]]]]
[[[]],[[[1,9,8,5,8],[3,2,10,7,10]],[[1,8,4],1,[9,3,10,0,4]],0,4],[3,2],[4,4,[[10,0,9,1],[],6,[3,10,8,0]],7,4],[4,[],2,[[8],0,[10,2]]]]
[[10],[[[2],[0],[]],5,[4,[4,6,6,2],[0,9,10,8],[10,3,4],0]],[6,4],[7,[[3],[4,8,5,1,5],7],[5,[8],10],[5],[1,[4,9,10],6,10,9]]]
[[],[6,3,5,5]]
[[6,6],[[[6,9,5,0],10,[9,3,2]],[2],[]]]
[[4,[[],1],3,[[3,4,0,6,0]]],[6,9,5,4],[[6,0,2,[]],[[10,3],[5],1,[3,2],[10,10,2,0,4]]]]
[[[[0,5,7,2,1],[1,0,7],[1,8]],10],[9,10],[[0]]]
[[[5,[8,0,0],[4,1,10,3],0],[[5,4],[8,10,9,5],5,1],7,3],[],[9,[5,[4,8],[8,1,5,3,2],[1,4,6,1,5]],[[1,5,1,2,4]]],[[10],6,[],3],[[[0,9,7,4,3],9,[6,5,5,2,5]],8,9,5]]
[[[[9,10,2],[6,8],6,[8,2,3]],4,[]],[[1],[10,[10,6,9],8,[9,9,4,7]],[[3]]],[],[6,[[],[4,9,5],[],9],[[8,2,6,1,6]],[[2,8,8],10,[5,9,0],[1,1,6,6],[9]],8],[]]
[[4],[9,[7,[7,7,3,10,1],6],0],[2,5],[[],1,9,[]]]
[[[],[],[3,[6,4],[7,3],9]],[[3,[6],1],[[],8,1],4,[5,4,7,4,[5,10,1,8]],[10,7,0,4]],[[2,[9,3],[10,2,2,5,1],7,[]]]]
[[[[2,6],[4,9,6,1]],[[5,7,9,4,10],[8],7],[0],[5,8]]]
[[[1,2,4,[1,1,2,10],10],1]]
[[10,[]],[6,9,[],2,[5,[5],[4,4,1,2],[9,0,5],[]]]]
[[],[[7,10,[3,10]]]]
[[1,[[7,6,5,4,10],6,3,[10,8,1]],[[5,0,1,4],[8,8,4]],[10,[2,4,4,3,8],[10,8],2],4],[[],[6],[1,6],0],[[[4],[6,5,7,10]],9,[]]]
[[],[1,0,2,[8,[8,0],10,5]],[[[9,1,4,4,6],8,8,1,5],[3,10,8,3],[]]]
[[[],[4,7,8],[3,5,1,10,[7,2,5]]]]
[[[[8,8,10,8],[9,5,2,4,5],[5,2]],[]],[2,9],[[4,[3,0,7],[2,1,3]]]]
[[[10,7,9],3],[[2,[6,8,10,0],9,10,[]],[],1,10,[2,[8,8,10,10],10]],[[[8,7,5,4]],[[],7,[4,9,2,0,4],[0],1],7,2],[],[[8],[[0,0,7,8,1],2,0,[]],[[0,9,6,7,4]],[4]]]
[[[],[[6,1,9,1]]],[[7,[]],2,4]]
[[7,10,9,10],[[[6,8,7]],10,10,[10,[1,7,1],9,7,[7]]]]
[[[],[7,8,[0,10,7,5]],10],[8],[[],[[],6,10,[],[9,10,10]]]]
[[3,[],[]],[[[9,2,3],[6,8,9,5],[0,6,7,6,7],0,10],10],[],[],[3,[[0],[6,7],3,[1,2,10,2,9]]]]
[[],[3,[[5],6,[1,3,1,5],[5,9,4]],[4],[],9],[0,9,10],[[4,8,[8,6]]],[[]]]
[[[7,[5],[1],[4,8,4,2,2]],8,1,0],[[5,[10,7,8,0],[7,4,9],[9]],1,4],[9,[],[10],3,2]]
[[5],[[2]]]
[[1],[],[]]
[[[[9,7,5,10],1],[],[]],[4,[0,[4],5,2,8],8],[[9,[1,0],3,0]],[8,0,[6,4,[10],5]],[[9,[6,3,1,0],[8,8]]]]
[[8,5,[9]],[2],[9,[],5,5,8],[3,5],[0,6,[],8,[3,0]]]
[[10,10],[6,[[0,7,6],8,[0,4,8,1]],0,4,6],[3,10,[5,7]],[[3],[[10],1,5]]]
[[2,[[9,10],[1,8,8,6,1],[]]],[[[],2,[7,6,9,2,4],[],10],[[8,7,1,10,4],9,[5,4],0,1],[0,[2,2,9,0],9],9,4]]
[[[6,1,1,[3,8],[9,4,3,6,8]],7,4,[]],[9,[],[[10],[8,8,3,1]],3]]
[[[[8,4,5]],5,[5,2,[3,1,10,8]]],[[[2,7,8,2,0]],[[3,10,4,4],10,0],6,9,3],[[],[10,1,1,[]],10,3]]
[[[[7]],[],9,4],[[7,5],[],[[7,4,2],[8,9,2,0],4,1,[8,9,2,8]],1,[[6,5,6,5],[5],[],1]],[]]
[[[9],[8,8],10,[[6,5,0],3,6,[10,4],[10,4]],[10,[10,0,7,4,5]]],[]]
[[3,[4,[],6]],[0]]
[[],[6,[7,9,9,[],2],[[],[5],10,3,7]],[2,1],[],[[],[[],4,[3],0,1],3,10,[9,0,5,5,0]]]
[[[6,[6,2,0,10],0],[2,[9,4,8,0,6],[10,8,7,4,2],[],[]],0,0,[6,2,10,[6,7,10,1]]],[[]]]
[[[[2],4],6,8,4],[2,[[8,8,3,8]],[[9,8,10],[2,2,4,7]],[5,[2,8,7],4]],[[[]],[[2,1,2,9,2]],[[9],[6,10,0]]]]
[[[[10,6,1]],[],[],[2,[2]],6],[[5,[0],[9],0,0],[3],5,[0,6,[3],10]],[],[[[],4,1],[4,0],2,2,[4,0,[2,6,4,5],10,[10,6]]]]
[[[],7,[2],[9]],[[],[[0,9,6],[0,5,4,5,2],[],7,3]]]
[[],[10]]
[[[[],[7],[2,5]],3],[4,1,1,6],[]]
[[]]
[[2,[[],[5],10,[7,10,5,6],[9,8,7]],[[8,9,4,10],0],[],[[0,7,8]]],[[9,3,0,2,7],1,[5,[3,10,7,7,2],[],[0,8,2],[3,0,6]],[],0]]
[[[7],8,10,[[5,6,2,5]]],[[3,[]],8,[[],4],4],[[],[[9,0]]],[[[4,5,6,3,0],[6,1,4,2],[0],[7,10,3],7],[[5,2]],5,[[1,1,4,10,7],3,[1]]],[[8,[],[8],2],[8,[0,7],[10,8,9,4,4]],[5,[10]],[],5]]
[[2],[9,8,4],[7,9,4]]
[[3,[[],3,[1,6,8,1,6],[],[3,3,10,6,8]],1,8,[0,0,[1,7,2],[0,0]]]]
[[10,[0,3,[8]],10],[],[[8,[],1,[5,0,6]]],[1],[4]]
[[[[7,1,10,4,9]],1,[]],[[[4]],8,9,5]]
[[7,[3,6,6],7,[[9]],[[5,8]]]]
[[],[[6,9,4,5],[0],[],4],[[9,[3],[5,1,5,9],3],[]],[[0,10,[5,4,6]],[[0,3]]]]
[[5,[0],0,[5]],[[[],[6,9,1,4,9],6,[9,9],[2,1,6,2,2]],5,10,[[0,9,6]],7]]
[[8,1,6],[10,[4,[2,5,3,2,2],[6,1,3,3]],5,[[10,4,7,1],[9,2],1]],[9,[2]],[],[[[9,6,10],[0,0],[2]]]]
[[10,0,10],[[[0,6,1],[7,3,5,5,0]]],[0,[[4,7,3,4],[],[3],8,[9,3]],6]]
[[4,[[3],9,[1,3,5,2,5],[9]]],[[6,7],9],[],[]]
[[[[0,9,4,3],[9],1,[7,2]],[[],1,2,[9,2,1,5,5],[5,5,7]]],[]]
[[[[6,1],9],1],[[[2,6,2]],2,3],[3,6,[4,[9,1],7,[0,10,6]],[1,[10,7],[2,8,7,3,1],[6,5]],[7,2,0]]]
[[[[3],8,[10,5,9,10,5],5]],[]]
[[7,8,5,6],[[7,[1],[1,9,1],[],4],[[10,4,9,10],[7,1,1,6,3],6],10]]
[[[[8,7,5],8,[1],7]],[[3]]]
[[[8,[1,0,7,6],[],[1,3,8,3]]],[1,[8,2,[1]],[[4],7,0,5,6],[[],0,0,7,9],4],[6,6,2,6,0],[],[7]]
[[4],[[0,[9,9],4,0,[2,3]],[3,5,[7,3,8,4,9],5],[2,9,10],[6,[6],5,4]],[]]
[[[6,9,[3,4],0,[]]],[10,7,3,[[6,2,4,10],[3,7],10],5],[],[[10,[9,8,0],0,1,[8,8,9]],[[0,5,1,5,6],7,6],[[8,7,1],10,[0]]]]
[[10,[[3,4],5,5,8,[1,7,8]],7,[10,[7,1,1,7,0],[8,2,9],9,[]],[[6,9],8,3,[4,7,9]]],[8,8,[[1,1,7,5],[8],1,0,9]],[[[2,10,6,7],[6,10,3,4,6]],[]],[6]]
[[[5,3,[4]],4,4,1,[3,[],4,[4],9]],[[10,10,[2,8]]],[]]
[[5,8,0,9,6],[],[3],[[[10,3,6,9]],3,7,[0]],[[]]]
[[1,[]]]
[[9,[[],7,[2],5,[6]],[]],[[6,6,2],4],[],[0],[[5,[3,9,0,2],[],9],[[1],[1,3,1,2,4],6],1,[[7,9],0,[],5]]]
[[],[1,6,8,[4,7]],[[[1,0,4,7],[0]],[[9,8],0,[8,7,8]],[[2,3,2,6,1]]],[[],[[8,4,8],[0,6],7,5],[[7,10,2,6],[5,3,8,10,6],5,2],4,2]]
[[],[7],[5,10,[[5,10,1,7],[4],8],[[],2,9,[7,2]],4]]
[[[[7,8,3],0],8,2]]
[[7,2,[[10],[5,2,1,3,8],0,5]],[],[5,[5],3],[[[10,2,6,9],0,[5,8,6,2,3],10,[4,6,10,10,3]],[[10,1,9],1,[0,2,6],4,[7,5,10]],7,[[1,7,4,6]],10],[[[0],7,5,[9,4],2],0,[[],[4,7],[9,2,7,3,4]]]]
[[[],[[1,10,6,1,10],5,10],4],[9,[[]],1]]
[[7],[]]
[[[[9,2,10,10,7],[1,6,6],[10,0,9]]],[[8,9,4,10,0],[[],5],4],[[]]]
[[[[9,7,10],9,7,[6,10]],[[8,0,7,2]],[8,4,[10]]],[],[7,[8,[6,3,5]],[7,[0,4,4,9,9]]],[[[4,10,2],[5,7,3,3],[1,4,6,4,2],[8,7,10,7,1],4],[2],3,[[],9,10,[2,4]]],[[[]],[0,[4,7]],[]]]
[[],[7],[10,6,10,[[]]],[9,[[],6],[[4,2,5,5]],[[7,1,9],7]],[0,5,3,10,7]]
[[5],[0,[[0],10,[1,2]],10,[],8],[[[6,0],6,7,[]]],[2,[8,[7,0,5,5],[0,3,0],[],[1]],2,[2,10,[5,5,3,0,1],0,[1,2]]],[]]
[[],[[3,[],[],[9,4,2,9],[]],[6,9,8,6,[7,9,4,2]],6,0,[[],[10,5]]],[]]
[[],[]]
[[7,4,[9,3]],[2,[[]],[[4],[1,3],6,[8],8],[1,[8,5],1,3]],[6,0,8],[4,5,2,7]]
[[[[9],[5,6,7,1],10,9],7],[[[3],[9,7,1],4,[7,9]],5,6,6]]
[[],[[],[8],[9,1,[6,3,6,8,9],[5,7,9,5]]]]
[[],[5,[[8]],2,[]],[9],[10],[10]]
[[[[4,10],9,[5,9,8,5,3],1],[[5,0,7],[10,10,5,5,4],[9,10,7,6],[1,2]]],[2,7,1,[1,4]],[[],[[2]],8],[8,4,[5,8,[8],[2,10]]],[]]
[[],[1],[0],[],[6]]
[[],[[5]]]
[[[[0,6,9,5,10],6,[0],0]],[[7,[]]],[3],[3,8,[[0,3],6,10,[4],[]]]]
[[1,[],8,[[1,3],8,8],[[],1,[8,9],6]],[[[6,2,6,4],[4,5],[3,6,4,6],7,[]]],[2,5],[8,[1,[9,9,9,8,6],[10]],9,[[2,5],7,[5,4,8],3],7],[8,0,[4,9,9,9,[5,6,2]]]]
[[[5,[2,0,3]],[[],5,4],2],[3,[4],[[2,3,0,6]],9,1],[],[[0,6,1,[1,10,0],5],5,[1,1,5,9,[2,8]],10],[7,[[],[7],[4,3,4],7,[8,8]]]]
[[],[7,10,9,[[2,8,5,5],[2,1,9],4,[],[6,8]],[7,4]]]
[[[[],[1],[8,9,3,9],8],[[5],5,10,8],[3,5]],[[4,4,10,0],3,[[4,9,3],[6],[6,7,4,7,10],4,[4,9,2]],[10,7,[],[6,4],[7,7]],4]]
[[[[2,5],1,0]],[[[0],10,[2,1,9],[3,7,8,10,7]],7,[[6,7,3],10,0,[10,8,6],[9,9,5,4]],[4,4,3,[7,4,10,4,1],[1]]]]
[[[0,[9,1,6,7,10],7],3],[3],[[1,10],[[4,3,1,7,10],6,2,[9,3,3]],4],[[6,[]],[2,[9,2,6,5]]]]
[[3,7,[],2,[[],[1,4,9,1,10],0]],[8,[7,1,6],[4,[0,9,4,1]]],[4,[[9,9,2],4]],[2,8,[7,[8],[9],[6,7]],1]]
[[8,9,[[2,0],[],4,[8]],7,[[10,10],[9,3,1,1],7,6]],[[9],[[],5,[2,1,2,6]]],[[]],[[9,[7,3,2,2],10],4]]
[[[]]]
[[1,3]]
[[[2,[2,1,9,5,3],1,9],4],[[[2,3,9,5],9,[9,2,4,3],0]],[[[3]]]]
[[6,5,[[6,4,7,5,7]],[[]]],[[[5]],4],[[2]]]
[[],[5,[[2],8,1,[1,3,7,5,0],6],[[1,4,4,8,10],[2,7,9,9,4],1,0],9]]
[[[10,[6,0],10,2,7],[[6,1,7,1,6],[],3,[9,8,2,0],10],[2,[8,0],6,0,[6,2,4]],5,5],[[[6,1,5,3]],[[10],5,[]]]]
[[],[10,6,5,10,9],[1,4,8]]
[[[[1,0,10,3,8],[10],[7,8,3,6],3],[5,[10,6,9],1,8],0,[[],[5],[]],[[7,3,3],0,[0,7,9,0,10]]],[[[3]]],[10],[1,4,[[],[0,1],[9,9,4,8],10,10],[]]]
[[[1,[4,6,1]]],[6,5,8,6],[1,[[6]]],[3,[[1],[]]],[[5,[4,3,10],[6,1,10,1],[7,4]],[[9,10]],[10,3,1,[6,5],[0,5]]]]
[[1,[5,[6,5],9,10]],[[[1,5,0,5,5],[9,1,6,8],7,7,[7,5]],[[8,10,3,9],3,4],1],[10,8,3,[8,1,9,6],[4]]]
[[7,1,[8,[10,9,0],[4,2],10,9]]]
[[[[4],[7,3,8],[10,9]],[[8],4,[],[9,9,7,9,2]]],[],[[[],10,4],3,4,1,[9,5,6]]]
[[[]],[[0,[1],7,[1,4,10,7],[10,10,9]]],[[[4,7,0],3,3,2]],[9,0,0,5],[10,[6,8,0,[7,8],7]]]
[[[4,9,9,6],10,[[],[4,1,4,9,1],7,4,7],[5,[],4],[1,9,[9,1],0,0]],[10,[2,1,[7,3,7]],[0,[1,5,8,6,8],[3,5,2],[9],1]],[4,8,10],[[[],7,1,10,[8,8,5]]]]
[[[]],[[6,1],[[2]]],[[[]]]]
[0,0,1,4]
[0,0,1,4,10]
[[],[10,[[4,5,7,1],[9,0,9,0,0],[6,10,1],4],[[2,4,6,0],2,8,[]]]]
[[[7],10,[],8,[[2,7,10,0]]],[10]]
[[6],[],[9,9]]
[[[],1,[8,[5,7,5,0,10],6,[7,5]]],[[],[],7,5],[[0],[10,4,9],8,[[2],[1,7,0,9],1,[1,3]]],[10,[],[],6,[[0,6,7],10,7]]]
[[9,8,[[10,10,9,5,10],[8,2,1]],10,5],[2,[9,[1],9],[[4,10,3]],[[4,9,4],9,[4,1,5,10]]]]
[[10,0,7],[],[]]
[[1,[9,9,2,9],4,7],[10,[6,9,[7,6],8]],[],[[2,2,[6,3],[10,1]],6],[]]
[[3,10],[],[[],[[10],10,[7],[6]],[]],[4]]
[[4,7,[8,1],[[9],0,[3,6,0,7],9,9]],[10],[1,8,[]],[],[[],4]]
[[4,[1,9,5,0,2],9],[[[4,7,8],[6,0]]],[],[5,[0,[],[2,10,0,2],[1,6],8],6,7],[]]
[[2,[]],[[[10,9,8,7],5,[],[3],[10,2]],[9,[8,9],[8,1,4,3],4],7,2,6],[[[0],2,9,2,[]],[8,[6,0,7,10],1,1,5]]]
[[[3],[0],[[2,5,10,0],[],9],2],[4,[9,[7],[7,9],[9,2,5,3,6]],4,[[],1,[],1],10],[[[2,10,2,1,3],[3,8,5,3,10],[5,4,5,5],[],6],[[5],5,6]]]
[[9]]
[[[10],[[9,4,8]],[[],1,[10],[7,1]],[[1,0],[4,2],[1,5,5,3,9],1]],[5]]
[[[6,5,[2,3,10],9,8],[[],[8,1],3],[[],7,[5,4],[0,1,8,7,0],4],[3],[[2,0,0],1,[4,7,0,4],[],[]]],[4],[2,8,[[4],7,[10,10,9]],5]]
[[5,0],[[1,4,[0]],[[1],[8,7,7,8]],[[7,7,9,1],4,7,6],[10],7],[[],9],[[5,[10,8],0],8],[9,[[8],7,10],[0,[10,3],1,5,3]]]
[[0,[6,10],[[4,1,9],[],10,[10,6,2,7,3]]]]
[[[[1],[1],[],10],10,9,8,[[]]]]
[[[],1,[[8,1,9,5],0,10,[1],[9,1,5,0]],6,4],[[[8,2,7,0,6],6,1]],[[[6,3,10]],6],[[],[[5,0,8,10,9],[2]],8],[]]
[[[],5,[6,[0,6,8],[7,5,5,0,6],6,[]],[]],[[],3,0,3,[3,6]],[7,5,[[7,0,6,8],[9,5],[]]],[[[2],5,[1,0,5]],8,4,[[5,10,9],[0,2],10,[2]]],[]]
[[[2,3]]]
[[[[],[6],[4,9,10,6,3]],4,[]],[],[[],7,[],2],[]]
[[9,[5,8,9],1,1,6],[[[8,6]],3],[8,[[8,7,10],[]]]]
[[1,7,[7,7,4,[10,0,0],[10,10,10,10]]],[[[],[9,5]],[0,2,[8,4],[],[7,8,2]],[]],[[6,[7,0],[9,1],8,[]],4,1],[]]
[[],[6,1,[[2,1,10],7,4,[7]],[],0],[]]
[[[],8,[4,[9,9],3]],[]]
[[],[8],[[[9,3,10],[]],[10,[1,0,1],2]]]
[[[[7,9,3,3,10],4,8,[7,0,2,10,10],4],4,[8,10,[0,1,1]],6,[]]]
[[[3,8,10],0]]
[[1,[],3,[[5],[2,4,3,5],1,[6,8,6,2],[0,10]],[[6,6,3],[4,4]]],[9]]
[[],[],[[8,[0,7,9],2]]]
[[6,4],[[6,6,9],[[0,10,1]],[[],0,1,[],3],[[1,4,4,8,4]]],[4,[[3,1,5,7,6],7,[9,3,6,10]],[8,[0,10,1,10,10]],[[8,7,7],[8,2,7,7,8],0],[[7,7,8,5]]],[10,1,5,[[2,5,4],10,[]],1],[[4],1]]
[[1,[9,10,[7,4,7,9],0,[7]],3,[[1,2,8],[7,6,8],[4,9,8,1,6],6],9],[5,9,7,[[7,2,6,4,8]]]]
[[[[5,2,3],[0,8,2],2],[0,3,[9,1,5,2]],[2,6,6,4],1]]
[[7,[9,[0,9],5],[[4,3,6,7],7],2,2],[[[0,4,1,8,4],3,[],[]],[],5]]
[[[],[[],3,1,9],10],[]]
[[3,[8],8,4],[8,3,[[2,0,8,9,0],6,6]]]
[[[7,3,[6,5,5],5],8,6,2],[[[],1,[2,8,5],[],[4,10,9]],7,[],[8]]]
[[],[[[6,3,8,3],[6,4,7,2,9],0],6,[]],[9,[],6,8,[]],[]]
[[[[],[],1,[0,9,8],3],6,7],[[0,[5,7,3,0,10],0,[],7],3,9,[[6],[3],2],7]]
[[8,0,[[5,5],[0,2,4],3,[5],[2]],6],[0]]
[[5,10,7,0,[[7,9,10,2,6],[8,6]]],[[6,[9,4,3,1]],[8,3],[[3,6,7,8,6],3,[],[9],[1,2,4,7,10]]],[[],2,9,8]]
[[],[3,[[4,5,5,9,0]],8,[],[[3,7,8,10,2],7,10,[0,2,1,7]]],[[[2,6,2,0,10]]],[7,[]],[6,[],6,[[2,1,8],7,0],[[9,9,1],[],[9,4,3,1,5],[10,6,3,6,9]]]]
[[4,1,[],10,10],[[5,7],[],5]]
[[[[],7],4,3,[[],4,[4,8,3,3,3],2,10],[5]],[[7],[10,[],[9,9,3,9],[8,8,5,4],[5,6,4,10]],[7,10,[6,4,0,4],[7,0,0]]],[3,[1]],[3,[[9,8,3,4,9],10,[0,1]]],[[[3,6],6]]]
[[],[9,2,5,4],[[[0,9,2,3],7,[1,10,2],6,10],4,5,2],[[[4,9],[7,1,0,1],4],[[2,2,8],[4,3,10,9,2],4,9,[]],3,7,8],[]]
[[7],[8,[8,[2,7],7,3]],[],[[]]]
[[],[[8,10,2],8]]
[[5,[]],[[[4],8]]]
[[[[],7,2,3],9,[],[[1],9,[]],1]]
[[5],[6,[8,1,[6,7,9,5],9],0]]
[[6,5,2]]
[[0,[[8,6,3,8],1,6,[1,4],[2,2,1,0]],1,8],[[4,3,[],[],3],6,[],[3,[0,0,7,6]],[3,[],[9,6,10,10,2],0,[3]]],[],[[1,[]],6,[[0,9,6,1,4],2,2],8,[[7],6,8,7]],[3,1,8,9]]
[[4],[[[10,3,10,5,0],[],[5,1,1,9],[9,8],2],2,9],[6,0,[[4,4,5,6,8]]],[[1,6]]]
[[8,9,7,6],[9,[9,[9]],1],[[],[6,[]],[[2],1,[4,5,8,8,7]]],[0,4,[[4,7,7,0],[10,2],4,9],[[]],5],[4]]
[[],[9],[9],[9],[[[],[],[1,0],[5,10,6]],6,[[9,0],2,4],8]]
[[],[10],[[[4],[],[5,6],[7,10,5,2]]]]
[[[],6],[[8,3],[2,5,2,[10,7,8,4]]],[[0,1,9,[10,3,7],8],4,3,[[9],7],0]]
[[6],[],[[[6],[7,5,2,7],[3,7]],1,[[7,0,3],[],[7]],6],[5,5],[[9,1,[0,10,10],[3,0,4,0],3],[6,8,1],2]]
[[[9,10,[1,8,4],10]],[1,[]],[]]
[[2,[[9,5,4],4,[10]],[[10],[8,9,10,6,3],[6],9,[8,5,3]],[]],[[[9,8],[0,6],1,10,[0,10,4,6,8]],[[9,8,6]]],[3,4,[1,1,2,[1,4,5,2,2]]]]
[[7,[8,[1,8,1,8,8]],[[0,10],9],[],4]]
[[[[2,0,4,1],2],[3,7,[8,2,1]],4,[[10,3]]],[6,9,[[1,6,9,6,6],4,[]]],[[7,10],9],[5,[[4,2,9,1],[6,6],[4,4,0],[7,2,2]]]]
[[[0,10]],[]]
[[4,4,4],[1,[10,[],10,6,[8,8,3,7,7]],6],[[0,8,[9],4,[3,6]],[[4,5,3,6,8],4]],[1,[[3],[]]]]
[[10,4,7,[[8,9],7,7,[10,1,2],10],[[9,8],1]],[],[[4,10,[]]]]
[[[[4]],3,[[9,3,3,8,3],5,[1,3,9],5,[4,4]],[1,[5]],[[6,9,8],2,5,[1,5],4]],[[[],4]],[]]
[[],[[9,1,[5,8],[8,9],1],[[]]],[7,0,[[3],4,5],8],[],[1,[3,[0,0,6],[],[]],6,8,1]]
[[4],[8,4,[3,6,[],2]],[[[2,10,8,0,5],[7,4,9,5],[5,10,7],[10,2,5,0,7]]]]
[[],[[[3,0],0],[],[[4,4],[1]],[5,[7,7,8,9,10]]],[9]]
[[],[[[3,9,10],0],[9,10,[10,10,10,2,2],[5,10,0,6,9],6],[9,3,10,7,[2,5]]]]
[[7]]
[[[],7],[6],[2,8,[5,6,[9,0,2,10,8],3,5],7],[4,9,[[1,10,1,6],3,4],1],[2]]
[[],[[[8,3,0,10],6,0,[10,7,2]]],[5,9,0,4]]
[[[[1,4],8,10,6],[0],1],[],[5,4,0],[[6,4,6,6]],[]]
[[[8,3,[0,8,4,4]]],[],[[7,[],[3,8,1,1]],10,[[],[],6,[9,7,1,10,9]],[8,[3,2,0],4,[7,9,2,5,3],[9,6,7,6]],3]]

111
2022/day14/Makefile Normal file
View File

@@ -0,0 +1,111 @@
# AOC daily Makefile - GNU make only.
#
# Copyright (C) 2021-2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
INPUT := input/input.txt
SHELL := /bin/bash
CC := gcc
BEAR := bear
CCLSFILE:= compile_commands.json
LIB := aoc_$(shell uname -m)
INCDIR := ../include
LIBDIR := ../lib
LDFLAGS := -L$(LIBDIR)
#LDLIB := -l$(LIB) -lm
LDLIB := -l$(LIB)
export LD_LIBRARY_PATH = $(LIBDIR)
CFLAGS += -std=gnu11
CFLAGS += -O2
CFLAGS += -g
# for gprof
# CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
# Next one may be useful for valgrind (some invalid instructions)
# CFLAGS += -mno-tbm
CFLAGS += -Wmissing-declarations
CFLAGS += -Wno-unused-result
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
CFLAGS += -DDEBUG_POOL # memory pools management
VALGRIND := valgrind
VALGRINDFLAGS := --leak-check=full --show-leak-kinds=all --track-origins=yes \
--sigill-diagnostics=yes --quiet --show-error-list=yes
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
export PATH := .:$(PATH)
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 part1 part2 ccls bear org
all: README.org ccls part1 part2
memcheck: memcheck1 memcheck2
memcheck1: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
memcheck2: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
@#@valgrind -s --track-origins=yes aoc-c -p 2 < $(INPUT)
compile: aoc-c
cpp: aoc-c.i
assembly: aoc-c.s
part1: aoc-c
@#$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 1 < $(INPUT)
part2: aoc-c
@#$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html compile_commands.json
aoc-c: aoc-c.c common.c
@echo compiling $<
$(CC) $(CFLAGS) $(LDFLAGS) -I $(INCDIR) $^ $(LDLIB) -o $@
# generate pre-processed file (.i) and assembler (.s)
%.i: %.c
@echo generating $@
@$(CC) -E $(CFLAGS) -I $(INCDIR) $< -o $@
%.s: %.c
@echo generating $@
@$(CC) -S -fverbose-asm $(CFLAGS) -I $(INCDIR) $< -o $@
# generate README.org from README.html (must cleanup !)
org: README.org
%.org: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@touch .ccls-root
@$(BEAR) -- make compile

232
2022/day14/README.org Normal file
View File

@@ -0,0 +1,232 @@
** --- Day 14: Regolith Reservoir ---
The distress signal leads you to a giant waterfall! Actually, hang on -
the signal seems like it's coming from the waterfall itself, and that
doesn't make any sense. However, you do notice a little path that leads
/behind/ the waterfall.
Correction: the distress signal leads you behind a giant waterfall!
There seems to be a large cave system here, and the signal definitely
leads further inside.
As you begin to make your way deeper underground, you feel the ground
rumble for a moment. Sand begins pouring into the cave! If you don't
quickly figure out where the sand is going, you could quickly become
trapped!
Fortunately, your [[/2018/day/17][familiarity]] with analyzing the path
of falling material will come in handy here. You scan a two-dimensional
vertical slice of the cave above you (your puzzle input) and discover
that it is mostly /air/ with structures made of /rock/.
Your scan traces the path of each solid rock structure and reports the
=x,y= coordinates that form the shape of the path, where =x= represents
distance to the right and =y= represents distance down. Each path
appears as a single line of text in your scan. After the first point of
each path, each point indicates the end of a straight horizontal or
vertical line to be drawn from the previous point. For example:
#+begin_example
498,4 -> 498,6 -> 496,6
503,4 -> 502,4 -> 502,9 -> 494,9
#+end_example
This scan means that there are two paths of rock; the first path
consists of two straight lines, and the second path consists of three
straight lines. (Specifically, the first path consists of a line of rock
from =498,4= through =498,6= and another line of rock from =498,6=
through =496,6=.)
The sand is pouring into the cave from point =500,0=.
Drawing rock as =#=, air as =.=, and the source of the sand as =+=, this
becomes:
#+begin_example
4 5 5
9 0 0
4 0 3
0 ......+...
1 ..........
2 ..........
3 ..........
4 ....#...##
5 ....#...#.
6 ..###...#.
7 ........#.
8 ........#.
9 #########.
#+end_example
Sand is produced /one unit at a time/, and the next unit of sand is not
produced until the previous unit of sand /comes to rest/. A unit of sand
is large enough to fill one tile of air in your scan.
A unit of sand always falls /down one step/ if possible. If the tile
immediately below is blocked (by rock or sand), the unit of sand
attempts to instead move diagonally /one step down and to the left/. If
that tile is blocked, the unit of sand attempts to instead move
diagonally /one step down and to the right/. Sand keeps moving as long
as it is able to do so, at each step trying to move down, then
down-left, then down-right. If all three possible destinations are
blocked, the unit of sand /comes to rest/ and no longer moves, at which
point the next unit of sand is created back at the source.
So, drawing sand that has come to rest as =o=, the first unit of sand
simply falls straight down and then stops:
#+begin_example
......+...
..........
..........
..........
....#...##
....#...#.
..###...#.
........#.
......o.#.
#########.
#+end_example
The second unit of sand then falls straight down, lands on the first
one, and then comes to rest to its left:
#+begin_example
......+...
..........
..........
..........
....#...##
....#...#.
..###...#.
........#.
.....oo.#.
#########.
#+end_example
After a total of five units of sand have come to rest, they form this
pattern:
#+begin_example
......+...
..........
..........
..........
....#...##
....#...#.
..###...#.
......o.#.
....oooo#.
#########.
#+end_example
After a total of 22 units of sand:
#+begin_example
......+...
..........
......o...
.....ooo..
....#ooo##
....#ooo#.
..###ooo#.
....oooo#.
...ooooo#.
#########.
#+end_example
Finally, only two more units of sand can possibly come to rest:
#+begin_example
......+...
..........
......o...
.....ooo..
....#ooo##
...o#ooo#.
..###ooo#.
....oooo#.
.o.ooooo#.
#########.
#+end_example
Once all =24= units of sand shown above have come to rest, all further
sand flows out the bottom, falling into the endless void. Just for fun,
the path any new sand takes before falling forever is shown here with
=~=:
#+begin_example
.......+...
.......~...
......~o...
.....~ooo..
....~#ooo##
...~o#ooo#.
..~###ooo#.
..~..oooo#.
.~o.ooooo#.
~#########.
~..........
~..........
~..........
#+end_example
Using your scan, simulate the falling sand. /How many units of sand come
to rest before sand starts flowing into the abyss below?/
Your puzzle answer was =665=.
** --- Part Two ---
You realize you misread the scan. There isn't an endless void at the
bottom of the scan - there's floor, and you're standing on it!
You don't have time to scan the floor, so assume the floor is an
infinite horizontal line with a =y= coordinate equal to /two plus the
highest =y= coordinate/ of any point in your scan.
In the example above, the highest =y= coordinate of any point is =9=,
and so the floor is at =y=11=. (This is as if your scan contained one
extra rock path like =-infinity,11 -> infinity,11=.) With the added
floor, the example above now looks like this:
#+begin_example
...........+........
....................
....................
....................
.........#...##.....
.........#...#......
.......###...#......
.............#......
.............#......
.....#########......
....................
<-- etc #################### etc -->
#+end_example
To find somewhere safe to stand, you'll need to simulate falling sand
until a unit of sand comes to rest at =500,0=, blocking the source
entirely and stopping the flow of sand into the cave. In the example
above, the situation finally looks like this after =93= units of sand
come to rest:
#+begin_example
............o............
...........ooo...........
..........ooooo..........
.........ooooooo.........
........oo#ooo##o........
.......ooo#ooo#ooo.......
......oo###ooo#oooo......
.....oooo.oooo#ooooo.....
....oooooooooo#oooooo....
...ooo#########ooooooo...
..ooooo.......ooooooooo..
#########################
#+end_example
Using your scan, simulate the falling sand until the source of the sand
becomes blocked. /How many units of sand come to rest?/
Your puzzle answer was =25434=.
Both parts of this puzzle are complete! They provide two gold stars: **

194
2022/day14/aoc-c.c Normal file
View File

@@ -0,0 +1,194 @@
/* aoc-c.c: Advent of Code 2022, day 14
*
* Copyright (C) 2022-2023 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <string.h>
#include "br.h"
#include "list.h"
#include "pool.h"
#include "debug.h"
#include "aoc.h"
pool_t *pool_segment;
#define INF (-1) /* found infinite fall position */
typedef enum { /* map cells */
EMPTY = '.',
STONE = '#',
SAND = 'o',
} type_t;
typedef struct segment {
int x1, y1, x2, y2;
struct list_head list;
} segment_t;
LIST_HEAD(segments);
typedef struct map {
int xmin, xmax, ymin, ymax;
int size_x, size_y;
int deltax, deltay;
int dropcol; /* drop sand here */
int dropped; /* number of sand units */
char *m;
} map_t;
#define XY(m, x, y) ((y) * m->size_x + (x))
#define P(m, x, y) (m->m[XY(m, (x), (y))])
static int drop_sand(struct map *m, int x, int y)
{
int ret = 0, tmp;
if (y >= m->ymax) /* part 1: nothing left under */
return INF;
if (P(m, x, y+1) == EMPTY) { /* down */
if ((tmp = drop_sand(m, x, y+1)) < 0)
return INF;
ret += tmp;
}
if (P(m, x-1, y+1) == EMPTY) { /* left */
if ((tmp = drop_sand(m, x-1, y+1)) < 0)
return INF;
ret += tmp;
}
if (P(m, x+1, y+1) == EMPTY) { /* right */
if ((tmp = drop_sand(m, x+1, y+1)) < 0)
return INF;
ret += tmp;
}
/* the 3 lower adjacent cells are filled */
P(m, x, y) = SAND;
m->dropped++;
if (y == 0) /* part 2 */
return INF;
return ret;
}
static struct map *gen_map(struct map *m, int part)
{
segment_t *cur;
if (part == 1) {
m->size_x = (m->xmax - m->xmin) + 3;
m->size_y = m->ymax + 1;
m->deltax = m->xmin - 1;
} else {
m->ymax += 2;
m->xmin = 500 - m->ymax - 1;
m->xmax = 500 + m->ymax + 1;
m->deltax = m->xmin;
m->size_x = (m->xmax - m->xmin);
m->size_y = m->ymax + 3;
}
m->dropcol = 500 - m->deltax;
m->dropped = 0;
m->m = malloc(m->size_x * m->size_y);
memset(m->m, '.', m->size_x * m->size_y);
list_for_each_entry(cur, &segments, list) {
int x1 = cur->x1 - m->deltax, y1 = cur->y1 - m->deltay,
x2 = cur->x2 - m->deltax, y2 = cur->y2 - m->deltay;
int dx = 0, dy = 0;
if (x1 == x2)
dy = y2 - y1 > 0 ? 1 : -1;
else
dx = x2 - x1 > 0 ? 1 : -1;
do {
P(m, x1, y1) = '#';
x1 += dx, y1 += dy;
} while (x1 != x2 || y1 != y2);
P(m, x2, y2) = '#';
}
if (part == 2)
for (int i = 0; i < m->size_x; ++i)
P(m, m->xmin - m->deltax + i, m->ymax) = STONE;
return m;
}
static struct map *parse(map_t *m)
{
size_t alloc = 0;
ssize_t buflen;
char *buf = NULL, *cur;
int i, scanned;
int x1, y1, x2, y2, x, y, n;
segment_t *segment;
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
i = 0;
buf[--buflen] = 0;
cur = buf;
while (1) {
scanned = sscanf(cur, "%d,%d ->%n", &x, &y, &n);
if (scanned != 2)
break;
m->xmin = min(x, m->xmin);
m->xmax = max(x, m->xmax);
m->ymin = min(y, m->ymin);
m->ymax = max(y, m->ymax);
if (i) {
x1 = x2;
y1 = y2;
}
x2 = x;
y2 = y;
if (!i) /* first point */
goto next;
segment = pool_get(pool_segment);
segment->x1 = x1;
segment->y1 = y1;
segment->x2 = x2;
segment->y2 = y2;
list_add_tail(&segment->list, &segments);
next:
i++;
cur += n;
if (cur - buf >= buflen)
break;
}
}
free(buf);
return m;
}
static int doit(map_t *m, int part)
{
m = gen_map(parse(m), part);
drop_sand(m, m->dropcol, 0);
return m->dropped;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
static map_t m;
m.xmin = INT_MAX; m.xmax = INT_MIN;
m.ymin = INT_MAX, m.ymax = INT_MIN;
pool_segment = pool_create("segment", 512, sizeof(segment_t));
printf("%s: res=%d\n", *av, doit(&m, part));
free(m.m);
pool_destroy(pool_segment);
exit(0);
}

17
2022/day14/aoc.h Normal file
View File

@@ -0,0 +1,17 @@
/* aoc.c: Advent of Code 2022
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#ifndef _AOC_H_
#define _AOC_H_
extern int parseargs(int ac, char**av);
#endif /* _AOC_H_ */

68
2022/day14/common.bash Normal file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# common.bash: Advent of Code 2022, common bash functions
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
# shellcheck disable=2034
export cmdname=${0##*/}
export debug=0
export res
export LANG=C
shopt -s extglob
set -o noglob
usage() {
printf "usage: %s [-d DEBUG] [-p PART]\n" "$cmdname"
exit 1
}
checkargs() {
local part=1
while getopts p:d: todo; do
case "$todo" in
d)
if [[ "$OPTARG" =~ ^[[:digit:]+]$ ]]; then
debug="$OPTARG"
else
printf "%s: illegal [%s] debug level.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
p)
if [[ "$OPTARG" =~ ^[12]$ ]]; then
part="$OPTARG"
else
printf "%s: illegal [%s] part.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
*)
usage
;;
esac
done
# Now check remaining argument (backup directory)
shift $((OPTIND - 1))
(( $# > 1 )) && usage
return "$part"
}
main() {
local -i part
checkargs "$@"
part=$?
parse "$part"
solve "$part"
printf "%s: res=%s\n" "$cmdname" "$res"
}

49
2022/day14/common.c Normal file
View File

@@ -0,0 +1,49 @@
/* common.c: Advent of Code 2022, common functions
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "aoc.h"
#include "debug.h"
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int parseargs(int ac, char **av)
{
int opt, part = 1;
while ((opt = getopt(ac, av, "d:p:")) != -1) {
switch (opt) {
case 'd':
debug_level_set(atoi(optarg));
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
case 'i':
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
return part;
}

View File

@@ -0,0 +1,2 @@
498,4 -> 498,6 -> 496,6
503,4 -> 502,4 -> 502,9 -> 494,9

168
2022/day14/input/input.txt Normal file
View File

@@ -0,0 +1,168 @@
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
490,15 -> 501,15 -> 501,14
503,68 -> 508,68
513,60 -> 513,61 -> 523,61 -> 523,60
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
524,136 -> 529,136
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
509,64 -> 514,64
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
518,46 -> 522,46
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
521,71 -> 521,73 -> 514,73 -> 514,79 -> 527,79 -> 527,73 -> 525,73 -> 525,71
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
518,82 -> 518,83 -> 529,83 -> 529,82
530,124 -> 535,124
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
542,112 -> 547,112
536,118 -> 541,118
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
528,139 -> 528,141 -> 521,141 -> 521,146 -> 534,146 -> 534,141 -> 531,141 -> 531,139
534,133 -> 539,133
543,118 -> 548,118
508,49 -> 508,52 -> 504,52 -> 504,55 -> 516,55 -> 516,52 -> 514,52 -> 514,49
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
508,49 -> 508,52 -> 504,52 -> 504,55 -> 516,55 -> 516,52 -> 514,52 -> 514,49
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
500,18 -> 500,20 -> 496,20 -> 496,24 -> 511,24 -> 511,20 -> 504,20 -> 504,18
530,130 -> 535,130
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
508,49 -> 508,52 -> 504,52 -> 504,55 -> 516,55 -> 516,52 -> 514,52 -> 514,49
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
546,115 -> 551,115
524,46 -> 528,46
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
521,71 -> 521,73 -> 514,73 -> 514,79 -> 527,79 -> 527,73 -> 525,73 -> 525,71
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
537,124 -> 542,124
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
528,139 -> 528,141 -> 521,141 -> 521,146 -> 534,146 -> 534,141 -> 531,141 -> 531,139
500,18 -> 500,20 -> 496,20 -> 496,24 -> 511,24 -> 511,20 -> 504,20 -> 504,18
539,115 -> 544,115
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
521,71 -> 521,73 -> 514,73 -> 514,79 -> 527,79 -> 527,73 -> 525,73 -> 525,71
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
533,127 -> 538,127
518,82 -> 518,83 -> 529,83 -> 529,82
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
506,66 -> 511,66
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
535,161 -> 535,162 -> 544,162 -> 544,161
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
500,18 -> 500,20 -> 496,20 -> 496,24 -> 511,24 -> 511,20 -> 504,20 -> 504,18
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
490,15 -> 501,15 -> 501,14
535,161 -> 535,162 -> 544,162 -> 544,161
508,49 -> 508,52 -> 504,52 -> 504,55 -> 516,55 -> 516,52 -> 514,52 -> 514,49
518,82 -> 518,83 -> 529,83 -> 529,82
513,66 -> 518,66
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
558,124 -> 563,124
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
528,139 -> 528,141 -> 521,141 -> 521,146 -> 534,146 -> 534,141 -> 531,141 -> 531,139
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
554,121 -> 559,121
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
508,49 -> 508,52 -> 504,52 -> 504,55 -> 516,55 -> 516,52 -> 514,52 -> 514,49
540,121 -> 545,121
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
547,121 -> 552,121
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
500,18 -> 500,20 -> 496,20 -> 496,24 -> 511,24 -> 511,20 -> 504,20 -> 504,18
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
512,46 -> 516,46
544,124 -> 549,124
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
521,71 -> 521,73 -> 514,73 -> 514,79 -> 527,79 -> 527,73 -> 525,73 -> 525,71
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
528,139 -> 528,141 -> 521,141 -> 521,146 -> 534,146 -> 534,141 -> 531,141 -> 531,139
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
528,139 -> 528,141 -> 521,141 -> 521,146 -> 534,146 -> 534,141 -> 531,141 -> 531,139
533,121 -> 538,121
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
521,43 -> 525,43
500,18 -> 500,20 -> 496,20 -> 496,24 -> 511,24 -> 511,20 -> 504,20 -> 504,18
527,133 -> 532,133
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
531,136 -> 536,136
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
515,43 -> 519,43
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
521,71 -> 521,73 -> 514,73 -> 514,79 -> 527,79 -> 527,73 -> 525,73 -> 525,71
521,71 -> 521,73 -> 514,73 -> 514,79 -> 527,79 -> 527,73 -> 525,73 -> 525,71
513,60 -> 513,61 -> 523,61 -> 523,60
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
537,130 -> 542,130
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
508,49 -> 508,52 -> 504,52 -> 504,55 -> 516,55 -> 516,52 -> 514,52 -> 514,49
545,136 -> 550,136
538,136 -> 543,136
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
528,139 -> 528,141 -> 521,141 -> 521,146 -> 534,146 -> 534,141 -> 531,141 -> 531,139
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
508,49 -> 508,52 -> 504,52 -> 504,55 -> 516,55 -> 516,52 -> 514,52 -> 514,49
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
503,37 -> 503,31 -> 503,37 -> 505,37 -> 505,29 -> 505,37 -> 507,37 -> 507,29 -> 507,37 -> 509,37 -> 509,29 -> 509,37 -> 511,37 -> 511,32 -> 511,37 -> 513,37 -> 513,29 -> 513,37 -> 515,37 -> 515,34 -> 515,37 -> 517,37 -> 517,36 -> 517,37 -> 519,37 -> 519,36 -> 519,37
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
510,68 -> 515,68
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
550,118 -> 555,118
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
528,139 -> 528,141 -> 521,141 -> 521,146 -> 534,146 -> 534,141 -> 531,141 -> 531,139
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
532,109 -> 532,103 -> 532,109 -> 534,109 -> 534,106 -> 534,109 -> 536,109 -> 536,102 -> 536,109 -> 538,109 -> 538,107 -> 538,109 -> 540,109 -> 540,107 -> 540,109 -> 542,109 -> 542,100 -> 542,109 -> 544,109 -> 544,106 -> 544,109
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
521,71 -> 521,73 -> 514,73 -> 514,79 -> 527,79 -> 527,73 -> 525,73 -> 525,71
541,133 -> 546,133
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
513,60 -> 513,61 -> 523,61 -> 523,60
518,40 -> 522,40
517,68 -> 522,68
500,18 -> 500,20 -> 496,20 -> 496,24 -> 511,24 -> 511,20 -> 504,20 -> 504,18
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
520,96 -> 520,92 -> 520,96 -> 522,96 -> 522,86 -> 522,96 -> 524,96 -> 524,92 -> 524,96 -> 526,96 -> 526,93 -> 526,96 -> 528,96 -> 528,95 -> 528,96 -> 530,96 -> 530,88 -> 530,96 -> 532,96 -> 532,88 -> 532,96 -> 534,96 -> 534,91 -> 534,96 -> 536,96 -> 536,92 -> 536,96 -> 538,96 -> 538,88 -> 538,96
529,159 -> 529,153 -> 529,159 -> 531,159 -> 531,151 -> 531,159 -> 533,159 -> 533,156 -> 533,159 -> 535,159 -> 535,152 -> 535,159 -> 537,159 -> 537,154 -> 537,159 -> 539,159 -> 539,156 -> 539,159
535,161 -> 535,162 -> 544,162 -> 544,161
551,124 -> 556,124
500,18 -> 500,20 -> 496,20 -> 496,24 -> 511,24 -> 511,20 -> 504,20 -> 504,18

111
2022/day15/Makefile Normal file
View File

@@ -0,0 +1,111 @@
# AOC daily Makefile - GNU make only.
#
# Copyright (C) 2021-2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
INPUT := input/input.txt
SHELL := /bin/bash
CC := gcc
BEAR := bear
CCLSFILE:= compile_commands.json
LIB := aoc_$(shell uname -m)
INCDIR := ../include
LIBDIR := ../lib
LDFLAGS := -L$(LIBDIR)
#LDLIB := -l$(LIB) -lm
LDLIB := -l$(LIB)
export LD_LIBRARY_PATH = $(LIBDIR)
CFLAGS += -std=gnu11
CFLAGS += -O2
CFLAGS += -g
# for gprof
# CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
# Next one may be useful for valgrind (some invalid instructions)
# CFLAGS += -mno-tbm
CFLAGS += -Wmissing-declarations
CFLAGS += -Wno-unused-result
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
CFLAGS += -DDEBUG_POOL # memory pools management
VALGRIND := valgrind
VALGRINDFLAGS := --leak-check=full --show-leak-kinds=all --track-origins=yes \
--sigill-diagnostics=yes --quiet --show-error-list=yes
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
export PATH := .:$(PATH)
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 part1 part2 ccls bear org
all: README.org ccls part1 part2
memcheck: memcheck1 memcheck2
memcheck1: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
memcheck2: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
@#@valgrind -s --track-origins=yes aoc-c -p 2 < $(INPUT)
compile: aoc-c
cpp: aoc-c.i
assembly: aoc-c.s
part1: aoc-c
@#$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 1 < $(INPUT)
part2: aoc-c
@#$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html compile_commands.json
aoc-c: aoc-c.c common.c
@echo compiling $<
$(CC) $(CFLAGS) $(LDFLAGS) -I $(INCDIR) $^ $(LDLIB) -o $@
# generate pre-processed file (.i) and assembler (.s)
%.i: %.c
@echo generating $@
@$(CC) -E $(CFLAGS) -I $(INCDIR) $< -o $@
%.s: %.c
@echo generating $@
@$(CC) -S -fverbose-asm $(CFLAGS) -I $(INCDIR) $< -o $@
# generate README.org from README.html (must cleanup !)
org: README.org
%.org: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@touch .ccls-root
@$(BEAR) -- make compile

163
2022/day15/README.org Normal file
View File

@@ -0,0 +1,163 @@
** --- Day 15: Beacon Exclusion Zone ---
You feel the ground rumble again as the distress signal leads you to a
large network of subterranean tunnels. You don't have time to search
them all, but you don't need to: your pack contains a set of deployable
/sensors/ that you imagine were originally built to locate lost Elves.
The sensors aren't very powerful, but that's okay; your handheld device
indicates that you're close enough to the source of the distress signal
to use them. You pull the emergency sensor system out of your pack, hit
the big button on top, and the sensors zoom off down the tunnels.
Once a sensor finds a spot it thinks will give it a good reading, it
attaches itself to a hard surface and begins monitoring for the nearest
signal source /beacon/. Sensors and beacons always exist at integer
coordinates. Each sensor knows its own position and can /determine the
position of a beacon precisely/; however, sensors can only lock on to
the one beacon /closest to the sensor/ as measured by the
[[https://en.wikipedia.org/wiki/Taxicab_geometry][Manhattan distance]].
(There is never a tie where two beacons are the same distance to a
sensor.)
It doesn't take long for the sensors to report back their positions and
closest beacons (your puzzle input). For example:
#+begin_example
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
Sensor at x=9, y=16: closest beacon is at x=10, y=16
Sensor at x=13, y=2: closest beacon is at x=15, y=3
Sensor at x=12, y=14: closest beacon is at x=10, y=16
Sensor at x=10, y=20: closest beacon is at x=10, y=16
Sensor at x=14, y=17: closest beacon is at x=10, y=16
Sensor at x=8, y=7: closest beacon is at x=2, y=10
Sensor at x=2, y=0: closest beacon is at x=2, y=10
Sensor at x=0, y=11: closest beacon is at x=2, y=10
Sensor at x=20, y=14: closest beacon is at x=25, y=17
Sensor at x=17, y=20: closest beacon is at x=21, y=22
Sensor at x=16, y=7: closest beacon is at x=15, y=3
Sensor at x=14, y=3: closest beacon is at x=15, y=3
Sensor at x=20, y=1: closest beacon is at x=15, y=3
#+end_example
So, consider the sensor at =2,18=; the closest beacon to it is at
=-2,15=. For the sensor at =9,16=, the closest beacon to it is at
=10,16=.
Drawing sensors as =S= and beacons as =B=, the above arrangement of
sensors and beacons looks like this:
#+begin_example
1 1 2 2
0 5 0 5 0 5
0 ....S.......................
1 ......................S.....
2 ...............S............
3 ................SB..........
4 ............................
5 ............................
6 ............................
7 ..........S.......S.........
8 ............................
9 ............................
10 ....B.......................
11 ..S.........................
12 ............................
13 ............................
14 ..............S.......S.....
15 B...........................
16 ...........SB...............
17 ................S..........B
18 ....S.......................
19 ............................
20 ............S......S........
21 ............................
22 .......................B....
#+end_example
This isn't necessarily a comprehensive map of all beacons in the area,
though. Because each sensor only identifies its closest beacon, if a
sensor detects a beacon, you know there are no other beacons that close
or closer to that sensor. There could still be beacons that just happen
to not be the closest beacon to any sensor. Consider the sensor at
=8,7=:
#+begin_example
1 1 2 2
0 5 0 5 0 5
-2 ..........#.................
-1 .........###................
0 ....S...#####...............
1 .......#######........S.....
2 ......#########S............
3 .....###########SB..........
4 ....#############...........
5 ...###############..........
6 ..#################.........
7 .#########S#######S#........
8 ..#################.........
9 ...###############..........
10 ....B############...........
11 ..S..###########............
12 ......#########.............
13 .......#######..............
14 ........#####.S.......S.....
15 B........###................
16 ..........#SB...............
17 ................S..........B
18 ....S.......................
19 ............................
20 ............S......S........
21 ............................
22 .......................B....
#+end_example
This sensor's closest beacon is at =2,10=, and so you know there are no
beacons that close or closer (in any positions marked =#=).
None of the detected beacons seem to be producing the distress signal,
so you'll need to work out where the distress beacon is by working out
where it /isn't/. For now, keep things simple by counting the positions
where a beacon cannot possibly be along just a single row.
So, suppose you have an arrangement of beacons and sensors like in the
example above and, just in the row where =y=10=, you'd like to count the
number of positions a beacon cannot possibly exist. The coverage from
all sensors near that row looks like this:
#+begin_example
1 1 2 2
0 5 0 5 0 5
9 ...#########################...
10 ..####B######################..
11 .###S#############.###########.
#+end_example
In this example, in the row where =y=10=, there are =26= positions where
a beacon cannot be present.
Consult the report from the sensors you just deployed. /In the row where
=y=2000000=, how many positions cannot contain a beacon?/
Your puzzle answer was =5176944=.
** --- Part Two ---
Your handheld device indicates that the distress signal is coming from a
beacon nearby. The distress beacon is not detected by any sensor, but
the distress beacon must have =x= and =y= coordinates each no lower than
=0= and no larger than =4000000=.
To isolate the distress beacon's signal, you need to determine its
/tuning frequency/, which can be found by multiplying its =x= coordinate
by =4000000= and then adding its =y= coordinate.
In the example above, the search space is smaller: instead, the =x= and
=y= coordinates can each be at most =20=. With this reduced search area,
there is only a single position that could have a beacon: =x=14, y=11=.
The tuning frequency for this distress beacon is =56000011=.
Find the only possible position for the distress beacon. /What is its
tuning frequency?/
Your puzzle answer was =13350458933732=.
Both parts of this puzzle are complete! They provide two gold stars: **

408
2022/day15/aoc-c.c Normal file
View File

@@ -0,0 +1,408 @@
/* aoc-c.c: Advent of Code 2022, day 15
*
* Copyright (C) 2022-2023 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <string.h>
#include "br.h"
#include "list.h"
#include "pool.h"
#include "debug.h"
#include "aoc.h"
static pool_t *pool_segment, *pool_pair;
#define HBITS 20 /* 20 bits: 1,048,576 buckets */
struct coord {
int x, y;
};
#define TOP 0
#define RIGHT 1
#define BOTTOM 2
#define LEFT 3
/**
* struct pair - input file pair list
* @sensor, @beacon: struct coord sensor and beacon coordinates.
* @manhattan: manhattan distance between sensor and beacon.
* @parity: beacon coordinates parity (as bishop color in chess).
* @corners: coordinates of rhombus immediately out of sensor range (clockwise).
* @list: list of pairs.
*/
struct pair {
struct coord sensor, beacon;
int manhattan;
int parity;
struct coord corners[4];
struct list_head list;
};
LIST_HEAD(pairs_head);
/**
* struct row - row description
* @row: row number.
* @segments: segments list.
* @hlist: htable bucket list.
*/
struct row {
int row;
int beacons[64];
int nbeacons;
struct list_head segments;
};
/**
* struct map - full map
* @min, @max: map's min and max coordinates.
* @hash: rows hash table
*/
static struct map {
struct coord min, max;
struct row row; /* for part 1 */
//hlist_head *hash;
} map = {
.min = { INT_MIN, INT_MIN }, .max = {INT_MAX, INT_MAX },
.row = { 0, {0}, 0, LIST_HEAD_INIT(map.row.segments) }
};
/**
* struct segment - The main segment structure
* @row: the row number
* @start, @end: segment start and end
* @list: sorted row's segments list
*
* If a row contains 2 segments 1-3 and 7-8, it would be represented as:
* +----------+ +----------+
* | start: 1 |<------>| start: 7 |
* | end: 3 | | end: 8 |
* +----------+ +----------+
*
* This implies adding a segment must manage merging. For example, adding
* segment 2-4 above would change the first segment to 1-4, or adding 0-9
* should change the first segment to 0-9 and remove the second one.
*/
struct segment {
int row;
int start, end;
struct list_head list;
};
static struct segment *get_segment(int row, int start, int end)
{
struct segment *new = pool_get(pool_segment);
log_f(5, "alloc segment (%d,%d) on row (%d)\n", start, end, row);
new->row=row;
new->start=start;
new->end=end;
INIT_LIST_HEAD(&new->list);
return new;
}
static void merge_segment(int start, int end)
{
struct segment *seg, *new;
struct list_head *cur, *tmp;
static int l = 9;
new = get_segment(map.row.row, start, end);
if (list_empty(&map.row.segments)) {
list_add(&new->list, &map.row.segments);
goto end;
}
list_for_each_safe(cur, tmp, &map.row.segments) {
seg = list_entry(cur, struct segment, list);
/* 1) check for disjoint segments */
if (start > seg->end + 1) {
continue;
}
if (end < seg->start - 1) {
list_add_tail(&new->list, &seg->list);
goto end;
}
/* 2) new is inside cur: do nothing */
if (start >= seg->start && end <= seg->end) {
log_f(l, " overlap IN, do nothing\n");
pool_add(pool_segment, new);
goto end;
}
/* 3) cur inside new: remove cur */
if (start <= seg->start && end >= seg->end) {
log_f(l, " overlap OUT, remove current\n");
// TODO: avoid this
list_del(cur);
pool_add(pool_segment, seg);
continue;
}
/* 4) new segment start is within current one */
if (start >= seg->start && start <= seg->end + 1) {
new->start = seg->start;
list_del(cur);
pool_add(pool_segment, seg);
continue;
}
/* 5) new segment is left-adjacent to current */
if (end == seg->start - 1) {
seg->start = start;
pool_add(pool_segment, new);
goto end;
}
/* from here, we know there is an overlap */
/* 6) adjust new start to current start */
if (start >= seg->start)
new->start = seg->start;
/* 7) remove current if covered by new */
if (end >= seg->end){
list_del(cur);
pool_add(pool_segment, seg);
continue;
}
/* 8) replace current with new - finished */
new->end = seg->end;
list_add_tail(&new->list, cur);
list_del(cur);
pool_add(pool_segment, seg);
goto end;
}
list_add_tail(&new->list, &map.row.segments);
end:
return;
}
static __always_inline void add_beacon(int bx)
{
for (int i = 0; i < map.row.nbeacons; ++i) {
if (map.row.beacons[i] == bx)
return;
}
map.row.beacons[map.row.nbeacons++] = bx;
}
/**
* is_off_range() - test if a point is off range from all sensors.
*/
static __always_inline int is_off_range(struct coord *point)
{
struct pair *pair;
/* reverse loop, because higher manhattan means higher chances to fail */
list_for_each_entry_reverse(pair, &pairs_head, list) {
if ((abs(point->x - pair->sensor.x) +
abs(point->y - pair->sensor.y)) <= pair->manhattan)
return 0;
}
return 1;
}
static struct pair *parse()
{
int ret;
struct pair *pair = NULL, *cur;
struct coord sensor, beacon;
ret = scanf("%*[^-0-9]%d%*[^-0-9]%d%*[^-0-9]%d%*[^-0-9]%d",
&sensor.x, &sensor.y, &beacon.x, &beacon.y);
if (ret == 4) {
pair = pool_get(pool_pair);
pair->sensor = sensor;
pair->beacon = beacon;
pair->manhattan = abs(beacon.x - sensor.x) + abs(beacon.y - sensor.y);
pair->parity = (pair->beacon.x + pair->beacon.y) % 2;
pair->corners[TOP] = (struct coord) {
sensor.x, sensor.y - pair->manhattan - 1
};
pair->corners[BOTTOM] = (struct coord) {
sensor.x, sensor.y + pair->manhattan + 1
};
pair->corners[RIGHT] = (struct coord) {
sensor.x + pair->manhattan + 1, sensor.y
};
pair->corners[LEFT] = (struct coord) {
sensor.x - pair->manhattan - 1, sensor.y
};
/* keep list ordered by manhattan */
if (!list_empty(&pairs_head)) {
list_for_each_entry(cur, &pairs_head, list) {
if (cur->manhattan > pair->manhattan) {
list_add_tail(&pair->list, &cur->list);
goto end;
}
}
}
list_add_tail(&pair->list, &pairs_head);
}
end:
return pair;
}
/**
* /#\
* /#\ /# #\
* /# #\ /# #\
* /# #\O/# <--- O is a possible point
* #X#
* rhomb A /#\ rhom B
* /# #\
* /# #\
* /# #\
* /# #\
* /# rhombs #\
* A & B
* (intersection)
*/
/**
* intersect() - find intersection of two segments
*
*/
static __always_inline struct coord *intersect(struct coord *p1, struct coord *p2,
struct coord *q1, struct coord *q2,
struct coord *ret)
{
int a1, a2, b1, b2, x, y;
/* a1, b1, a2, b2 are the formulas of (p1, p2) and (q1, q2), such as:
* y = ax + b
* a = (y2 - y1) / (x2 - x1) x2 ≠ x1
* b = y - a * x We can take either p1 or p2 coordinates
*/
a1 = (p2->y - p1->y) / (p2->x - p1->x);
b1 = p1->y - p1->x * a1;
a2 = (q2->y - q1->y) / (q2->x - q1->x);
b2 = q1->y - q1->x * a2;
/* Lines intersection (x,y) is at:
* (a1 * x) + b1 = (a2 * x) + b2
* x * (a1 - a2) = b2 - b1
* x = (b2 - b1) / (a1 - a2) a2 ≠ a1
* Then we find y = ax + b
*/
x = (b2 - b1) / (a1 - a2);
y = a1 * x + b1;
/* check if intersection is:
* 1) Within p1-p2 and q1-q2 segments
* 2) Within map area
*/
if (x >= min(min(p1->x, p2->x), min(q1->x, q2->x)) &&
x <= max(max(p1->x, p2->x), max(q1->x, q2->x)) &&
y >= min(min(p1->y, p2->y), min(q1->y, q2->y)) &&
y <= max(max(p1->y, p2->y), max(q1->y, q2->y)) &&
x >= map.min.x && x <= map.max.x &&
y >= map.min.y && y <= map.max.y) {
*ret = (struct coord) {x, y};
} else {
ret = NULL;
}
return ret;
}
#define T_R(p) &p->corners[TOP], &p->corners[RIGHT]
#define R_B(p) &p->corners[RIGHT], &p->corners[BOTTOM]
#define B_L(p) &p->corners[BOTTOM], &p->corners[LEFT]
#define L_T(p) &p->corners[LEFT], &p->corners[TOP]
static struct coord *check_intersect(struct coord *ret)
{
struct pair *pair, *second;
list_for_each_entry(pair, &pairs_head, list) {
second = list_prepare_entry(pair, &pairs_head, list);
list_for_each_entry_continue(second, &pairs_head, list) {
if (second->parity == pair->parity) {
/* top right segment */
if ((intersect(T_R(pair), R_B(second), ret) && is_off_range(ret)) ||
(intersect(T_R(pair), L_T(second), ret) && is_off_range(ret)))
return ret;
/* bottom left segment */
if ((intersect(B_L(pair), R_B(second), ret) && is_off_range(ret)) ||
(intersect(B_L(pair), L_T(second), ret) && is_off_range(ret)))
return ret;
/* right bottom segment */
if ((intersect(R_B(pair), T_R(second), ret) && is_off_range(ret)) ||
(intersect(R_B(pair), B_L(second), ret) && is_off_range(ret)))
return ret;
/* left top segment */
if ((intersect(L_T(pair), T_R(second), ret) && is_off_range(ret)) ||
(intersect(L_T(pair), B_L(second), ret) && is_off_range(ret)))
return ret;
}
}
}
return NULL;
}
static u64 part1(void)
{
u64 res = 0;
struct pair *pair;
struct segment *cur;
map.row.row = map.min.y = map.max.y = testmode() ? 10: 2000000;
while ((pair = parse())) {
if (map.row.row >= pair->sensor.y - pair->manhattan &&
map.row.row <= pair->sensor.y + pair->manhattan) {
int half = pair->manhattan - abs(map.row.row - pair->sensor.y);
int x1 = max(pair->sensor.x - half, map.min.x);
int x2 = max(pair->sensor.x + half, map.min.x);
merge_segment(x1, x2);
if (map.row.row == pair->beacon.y)
add_beacon(pair->beacon.x);
}
}
list_for_each_entry(cur, &map.row.segments, list)
res += cur->end - cur->start + 1;
return res - map.row.nbeacons;
}
static u64 part2()
{
u64 res = 0;
struct coord result = {0, 0};
map.min.x = map.min.y = 0;
map.max.x = map.max.y = testmode()? 20: 4000000;
while (parse())
;
check_intersect(&result);
res = ((u64)result.x) * 4000000UL + (u64)result.y;
return res;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
pool_segment = pool_create("segments", 8192, sizeof(struct segment));
pool_pair = pool_create("pair", 32, sizeof(struct pair));
printf("%s: res=%lu\n", *av, part == 1? part1(): part2());
pool_destroy(pool_segment);
pool_destroy(pool_pair);
exit(0);
}

17
2022/day15/aoc.h Normal file
View File

@@ -0,0 +1,17 @@
/* aoc.c: Advent of Code 2022
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#ifndef _AOC_H_
#define _AOC_H_
extern int parseargs(int ac, char**av);
extern int testmode(void);
#endif /* _AOC_H_ */

68
2022/day15/common.bash Normal file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# common.bash: Advent of Code 2022, common bash functions
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
# shellcheck disable=2034
export cmdname=${0##*/}
export debug=0
export res
export LANG=C
shopt -s extglob
set -o noglob
usage() {
printf "usage: %s [-d DEBUG] [-p PART]\n" "$cmdname"
exit 1
}
checkargs() {
local part=1
while getopts p:d: todo; do
case "$todo" in
d)
if [[ "$OPTARG" =~ ^[[:digit:]+]$ ]]; then
debug="$OPTARG"
else
printf "%s: illegal [%s] debug level.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
p)
if [[ "$OPTARG" =~ ^[12]$ ]]; then
part="$OPTARG"
else
printf "%s: illegal [%s] part.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
*)
usage
;;
esac
done
# Now check remaining argument (backup directory)
shift $((OPTIND - 1))
(( $# > 1 )) && usage
return "$part"
}
main() {
local -i part
checkargs "$@"
part=$?
parse "$part"
solve "$part"
printf "%s: res=%s\n" "$cmdname" "$res"
}

59
2022/day15/common.c Normal file
View File

@@ -0,0 +1,59 @@
/* common.c: Advent of Code 2022, common functions
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "aoc.h"
#include "debug.h"
static int _testmode = 0;
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-t][-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int testmode(void)
{
return _testmode;
}
int parseargs(int ac, char **av)
{
int opt, part = 1;
while ((opt = getopt(ac, av, "td:p:")) != -1) {
switch (opt) {
case 't':
_testmode = 1;
break;
case 'd':
debug_level_set(atoi(optarg));
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
case 'i':
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
return part;
}

View File

@@ -0,0 +1,14 @@
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
Sensor at x=9, y=16: closest beacon is at x=10, y=16
Sensor at x=13, y=2: closest beacon is at x=15, y=3
Sensor at x=12, y=14: closest beacon is at x=10, y=16
Sensor at x=10, y=20: closest beacon is at x=10, y=16
Sensor at x=14, y=17: closest beacon is at x=10, y=16
Sensor at x=8, y=7: closest beacon is at x=2, y=10
Sensor at x=2, y=0: closest beacon is at x=2, y=10
Sensor at x=0, y=11: closest beacon is at x=2, y=10
Sensor at x=20, y=14: closest beacon is at x=25, y=17
Sensor at x=17, y=20: closest beacon is at x=21, y=22
Sensor at x=16, y=7: closest beacon is at x=15, y=3
Sensor at x=14, y=3: closest beacon is at x=15, y=3
Sensor at x=20, y=1: closest beacon is at x=15, y=3

View File

@@ -0,0 +1,26 @@
Sensor at x=3999724, y=2000469: closest beacon is at x=4281123, y=2282046
Sensor at x=3995530, y=8733: closest beacon is at x=3321979, y=-692911
Sensor at x=3016889, y=2550239: closest beacon is at x=2408038, y=2645605
Sensor at x=3443945, y=3604888: closest beacon is at x=3610223, y=3768674
Sensor at x=168575, y=491461: closest beacon is at x=1053731, y=-142061
Sensor at x=2820722, y=3865596: closest beacon is at x=3191440, y=3801895
Sensor at x=2329102, y=2456329: closest beacon is at x=2408038, y=2645605
Sensor at x=3889469, y=3781572: closest beacon is at x=3610223, y=3768674
Sensor at x=3256726, y=3882107: closest beacon is at x=3191440, y=3801895
Sensor at x=3729564, y=3214899: closest beacon is at x=3610223, y=3768674
Sensor at x=206718, y=2732608: closest beacon is at x=-152842, y=3117903
Sensor at x=2178192, y=2132103: closest beacon is at x=2175035, y=2000000
Sensor at x=1884402, y=214904: closest beacon is at x=1053731, y=-142061
Sensor at x=3060435, y=980430: closest beacon is at x=2175035, y=2000000
Sensor at x=3998355, y=3965954: closest beacon is at x=3610223, y=3768674
Sensor at x=3704399, y=3973731: closest beacon is at x=3610223, y=3768674
Sensor at x=1421672, y=3446889: closest beacon is at x=2408038, y=2645605
Sensor at x=3415633, y=3916020: closest beacon is at x=3191440, y=3801895
Sensor at x=2408019, y=2263990: closest beacon is at x=2408038, y=2645605
Sensor at x=3735247, y=2533767: closest beacon is at x=4281123, y=2282046
Sensor at x=1756494, y=1928662: closest beacon is at x=2175035, y=2000000
Sensor at x=780161, y=1907142: closest beacon is at x=2175035, y=2000000
Sensor at x=3036853, y=3294727: closest beacon is at x=3191440, y=3801895
Sensor at x=53246, y=3908582: closest beacon is at x=-152842, y=3117903
Sensor at x=2110517, y=2243287: closest beacon is at x=2175035, y=2000000
Sensor at x=3149491, y=3998374: closest beacon is at x=3191440, y=3801895

111
2022/day16/Makefile Normal file
View File

@@ -0,0 +1,111 @@
# AOC daily Makefile - GNU make only.
#
# Copyright (C) 2021-2023 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
INPUT := input/input.txt
SHELL := /bin/bash
CC := gcc
BEAR := bear
CCLSFILE:= compile_commands.json
LIB := aoc_$(shell uname -m)
INCDIR := ../include
LIBDIR := ../lib
LDFLAGS := -L$(LIBDIR)
#LDLIB := -l$(LIB) -lm
LDLIB := -l$(LIB)
export LD_LIBRARY_PATH = $(LIBDIR)
CFLAGS += -std=gnu11
CFLAGS += -O2
CFLAGS += -g
# for gprof
# CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
# Next one may be useful for valgrind (some invalid instructions)
# CFLAGS += -mno-tbm
CFLAGS += -Wmissing-declarations
CFLAGS += -Wno-unused-result
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
CFLAGS += -DDEBUG_POOL # memory pools management
VALGRIND := valgrind
VALGRINDFLAGS := --leak-check=full --show-leak-kinds=all --track-origins=yes \
--sigill-diagnostics=yes --quiet --show-error-list=yes
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
export PATH := .:$(PATH)
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 part1 part2 ccls bear org
all: README.org ccls part1 part2
memcheck: memcheck1 memcheck2
memcheck1: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
memcheck2: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
@#@valgrind -s --track-origins=yes aoc-c -p 2 < $(INPUT)
compile: aoc-c
cpp: aoc-c.i
assembly: aoc-c.s
part1: aoc-c
@#$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 1 < $(INPUT)
part2: aoc-c
@#$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html compile_commands.json
aoc-c: aoc-c.c common.c
@echo compiling $<
$(CC) $(CFLAGS) $(LDFLAGS) -I $(INCDIR) $^ $(LDLIB) -o $@
# generate pre-processed file (.i) and assembler (.s)
%.i: %.c
@echo generating $@
@$(CC) -E $(CFLAGS) -I $(INCDIR) $< -o $@
%.s: %.c
@echo generating $@
@$(CC) -S -fverbose-asm $(CFLAGS) -I $(INCDIR) $< -o $@
# generate README.org from README.html (must cleanup !)
org: README.org
%.org: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@touch .ccls-root
@$(BEAR) -- make compile

275
2022/day16/README.org Normal file
View File

@@ -0,0 +1,275 @@
** --- Day 16: Proboscidea Volcanium ---
The sensors have led you to the origin of the distress signal: yet
another handheld device, just like the one the Elves gave you. However,
you don't see any Elves around; instead, the device is surrounded by
elephants! They must have gotten lost in these tunnels, and one of the
elephants apparently figured out how to turn on the distress signal.
The ground rumbles again, much stronger this time. What kind of cave is
this, exactly? You scan the cave with your handheld device; it reports
mostly igneous rock, some ash, pockets of pressurized gas, magma... this
isn't just a cave, it's a volcano!
You need to get the elephants out of here, quickly. Your device
estimates that you have /30 minutes/ before the volcano erupts, so you
don't have time to go back out the way you came in.
You scan the cave for other options and discover a network of pipes and
pressure-release /valves/. You aren't sure how such a system got into a
volcano, but you don't have time to complain; your device produces a
report (your puzzle input) of each valve's /flow rate/ if it were opened
(in pressure per minute) and the tunnels you could use to move between
the valves.
There's even a valve in the room you and the elephants are currently
standing in labeled =AA=. You estimate it will take you one minute to
open a single valve and one minute to follow any tunnel from one valve
to another. What is the most pressure you could release?
For example, suppose you had the following scan output:
#+begin_example
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
Valve BB has flow rate=13; tunnels lead to valves CC, AA
Valve CC has flow rate=2; tunnels lead to valves DD, BB
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
Valve EE has flow rate=3; tunnels lead to valves FF, DD
Valve FF has flow rate=0; tunnels lead to valves EE, GG
Valve GG has flow rate=0; tunnels lead to valves FF, HH
Valve HH has flow rate=22; tunnel leads to valve GG
Valve II has flow rate=0; tunnels lead to valves AA, JJ
Valve JJ has flow rate=21; tunnel leads to valve II
#+end_example
All of the valves begin /closed/. You start at valve =AA=, but it must
be damaged or jammed or something: its flow rate is =0=, so there's no
point in opening it. However, you could spend one minute moving to valve
=BB= and another minute opening it; doing so would release pressure
during the remaining /28 minutes/ at a flow rate of =13=, a total
eventual pressure release of =28 * 13 = 364=. Then, you could spend your
third minute moving to valve =CC= and your fourth minute opening it,
providing an additional /26 minutes/ of eventual pressure release at a
flow rate of =2=, or =52= total pressure released by valve =CC=.
Making your way through the tunnels like this, you could probably open
many or all of the valves by the time 30 minutes have elapsed. However,
you need to release as much pressure as possible, so you'll need to be
methodical. Instead, consider this approach:
#+begin_example
== Minute 1 ==
No valves are open.
You move to valve DD.
== Minute 2 ==
No valves are open.
You open valve DD.
== Minute 3 ==
Valve DD is open, releasing 20 pressure.
You move to valve CC.
== Minute 4 ==
Valve DD is open, releasing 20 pressure.
You move to valve BB.
== Minute 5 ==
Valve DD is open, releasing 20 pressure.
You open valve BB.
== Minute 6 ==
Valves BB and DD are open, releasing 33 pressure.
You move to valve AA.
== Minute 7 ==
Valves BB and DD are open, releasing 33 pressure.
You move to valve II.
== Minute 8 ==
Valves BB and DD are open, releasing 33 pressure.
You move to valve JJ.
== Minute 9 ==
Valves BB and DD are open, releasing 33 pressure.
You open valve JJ.
== Minute 10 ==
Valves BB, DD, and JJ are open, releasing 54 pressure.
You move to valve II.
== Minute 11 ==
Valves BB, DD, and JJ are open, releasing 54 pressure.
You move to valve AA.
== Minute 12 ==
Valves BB, DD, and JJ are open, releasing 54 pressure.
You move to valve DD.
== Minute 13 ==
Valves BB, DD, and JJ are open, releasing 54 pressure.
You move to valve EE.
== Minute 14 ==
Valves BB, DD, and JJ are open, releasing 54 pressure.
You move to valve FF.
== Minute 15 ==
Valves BB, DD, and JJ are open, releasing 54 pressure.
You move to valve GG.
== Minute 16 ==
Valves BB, DD, and JJ are open, releasing 54 pressure.
You move to valve HH.
== Minute 17 ==
Valves BB, DD, and JJ are open, releasing 54 pressure.
You open valve HH.
== Minute 18 ==
Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
You move to valve GG.
== Minute 19 ==
Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
You move to valve FF.
== Minute 20 ==
Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
You move to valve EE.
== Minute 21 ==
Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
You open valve EE.
== Minute 22 ==
Valves BB, DD, EE, HH, and JJ are open, releasing 79 pressure.
You move to valve DD.
== Minute 23 ==
Valves BB, DD, EE, HH, and JJ are open, releasing 79 pressure.
You move to valve CC.
== Minute 24 ==
Valves BB, DD, EE, HH, and JJ are open, releasing 79 pressure.
You open valve CC.
== Minute 25 ==
Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
== Minute 26 ==
Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
== Minute 27 ==
Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
== Minute 28 ==
Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
== Minute 29 ==
Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
== Minute 30 ==
Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
#+end_example
This approach lets you release the most pressure possible in 30 minutes
with this valve layout, =1651=.
Work out the steps to release the most pressure in 30 minutes. /What is
the most pressure you can release?/
Your puzzle answer was =1737=.
** --- Part Two ---
You're worried that even with an optimal approach, the pressure released
won't be enough. What if you got one of the elephants to help you?
It would take you 4 minutes to teach an elephant how to open the right
valves in the right order, leaving you with only /26 minutes/ to
actually execute your plan. Would having two of you working together be
better, even if it means having less time? (Assume that you teach the
elephant before opening any valves yourself, giving you both the same
full 26 minutes.)
In the example above, you could teach the elephant to help you as
follows:
#+begin_example
== Minute 1 ==
No valves are open.
You move to valve II.
The elephant moves to valve DD.
== Minute 2 ==
No valves are open.
You move to valve JJ.
The elephant opens valve DD.
== Minute 3 ==
Valve DD is open, releasing 20 pressure.
You open valve JJ.
The elephant moves to valve EE.
== Minute 4 ==
Valves DD and JJ are open, releasing 41 pressure.
You move to valve II.
The elephant moves to valve FF.
== Minute 5 ==
Valves DD and JJ are open, releasing 41 pressure.
You move to valve AA.
The elephant moves to valve GG.
== Minute 6 ==
Valves DD and JJ are open, releasing 41 pressure.
You move to valve BB.
The elephant moves to valve HH.
== Minute 7 ==
Valves DD and JJ are open, releasing 41 pressure.
You open valve BB.
The elephant opens valve HH.
== Minute 8 ==
Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
You move to valve CC.
The elephant moves to valve GG.
== Minute 9 ==
Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
You open valve CC.
The elephant moves to valve FF.
== Minute 10 ==
Valves BB, CC, DD, HH, and JJ are open, releasing 78 pressure.
The elephant moves to valve EE.
== Minute 11 ==
Valves BB, CC, DD, HH, and JJ are open, releasing 78 pressure.
The elephant opens valve EE.
(At this point, all valves are open.)
== Minute 12 ==
Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
...
== Minute 20 ==
Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
...
== Minute 26 ==
Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
#+end_example
With the elephant helping, after 26 minutes, the best you could do would
release a total of =1707= pressure.
/With you and an elephant working together for 26 minutes, what is the
most pressure you could release?/
Your puzzle answer was =2216=.
Both parts of this puzzle are complete! They provide two gold stars: **

446
2022/day16/aoc-c.c Normal file
View File

@@ -0,0 +1,446 @@
/* aoc-c.c: Advent of Code 2022, day 16
*
* Copyright (C) 2023 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "br.h"
#include "list.h"
#include "pool.h"
#include "debug.h"
#include "bits.h"
#include "aoc.h"
pool_t *pool_valve;
union val {
u32 val;
char str[3];
};
enum state {
CLOSED,
OPENED
};
struct worker {
struct valve *pos;
int depth;
int time;
};
struct valve {
int index; /* -1 for zero flow rate */
union val val;
enum state state;
int rate;
int evalflow, evaltime;
int playedflow, playedtime;
struct hlist_node hlist;
struct list_head index_sorted;
struct list_head flow_sorted;
struct list_head eval;
int worker;
struct list_head played;
int ntunnels, tottunnels;
struct valve **tunnels; /* array */
};
static struct graph {
struct valve *aa; /* head ("AA") */
int npositive; /* only "AA" & working valves */
int nvalves;
u64 opened; /* bitmask of opened valves */
u64 openable; /* bitmask of openable valves */
struct list_head index_sorted; /* TO REMOVE ? */
struct list_head flow_sorted;
struct list_head eval;
struct list_head played[2];
struct valve **indexed_all;
int *dist; /* 2-D array */
} graph = {
.aa = NULL,
.npositive = 0,
.nvalves = 0,
.index_sorted = LIST_HEAD_INIT(graph.index_sorted),
.flow_sorted = LIST_HEAD_INIT(graph.flow_sorted),
.eval = LIST_HEAD_INIT(graph.eval),
.played[0] = LIST_HEAD_INIT(graph.played[0]),
.played[1] = LIST_HEAD_INIT(graph.played[1]),
.indexed_all = NULL,
.dist = NULL
};
#define POS(a, b) ((a)*graph.nvalves + (b))
#define DIST(a, b) (graph.dist[POS((a), (b))])
static void print_valves()
{
struct valve *cur;
printf("**** graph: .head=%p npositive=%d\n", graph.aa, graph.npositive);
printf("index1: ");
list_for_each_entry(cur, &graph.index_sorted, index_sorted) {
printf("%d:%s ", cur->index, cur->val.str);
}
printf("\n");
printf("index2: ");
for (int i = 0; i < graph.nvalves; ++i) {
printf("%d:%s ", graph.indexed_all[i]->index, graph.indexed_all[i]->val.str);
}
printf("\n");
if (testmode()) {
printf("distances:\n ");
for (int i = 0; i < graph.nvalves; ++i) {
printf(" %s", graph.indexed_all[i]->val.str);
}
printf("\n");
for (int i = 0; i < graph.nvalves; ++i) {
printf("%s ", graph.indexed_all[i]->val.str);
for (int j = 0; j < graph.nvalves; ++j) {
printf("%5d ", DIST(i, j));
}
printf("\n");
}
}
printf("flow_sorted: ");
list_for_each_entry(cur, &graph.flow_sorted, flow_sorted) {
printf("%s:%d ", cur->val.str, cur->rate);
}
printf("\n");
printf("openable: %#lx ", graph.openable);
int pos, tmp;
bit_for_each64_2(pos, tmp, graph.openable) {
printf("%d ", pos);
}
printf("\n");
}
#define PAD3 log(3, "%*s", _depth * 2, "")
#define PAD4 log(4, "%*s", _depth * 2, "")
/**
* eval() - eval possible moves from @flow_sorted list.
* @_depth: recursivity depth (for debug only, TODO: remove).
* @nworkers: number of workers.
* @workers: array of workers.
* @pick: max position (in @flow_sorted) to pick moves from (-1 for all).
* @pressure: total pressure per time unit so far.
*
* Find the "best" next move by evaluating only the first @pick elements
* in @flow_sorted list.
*
* @Return: the current position eval.
*/
static struct valve *eval(int _depth, int nworkers, struct worker *worker, int pick, int pressure)
{
struct valve *cur, *best = NULL, *sub;
struct list_head *list_flow, *tmp;
int _pick = pick, val = 0, val1, max = 0, bestworker = -1;
int _nworkers = nworkers;
if (nworkers == 2 && worker[0].pos->index == worker[1].pos->index)
_nworkers = 1;
PAD3; log_f(3, "EVAL _depth=%d w0={ pos=%d[%s] depth=%d time=%d } w1={ pos=%d[%s] depth=%d time=%d } pick=%d pressure=%d \n",
_depth,
worker[0].pos->index, worker[0].pos->val.str,
worker[0].depth, worker[0].time,
worker[1].pos->index, worker[1].pos->val.str,
worker[1].depth, worker[1].time,
pick, pressure);
list_for_each_safe(list_flow, tmp, &graph.flow_sorted) {
cur = list_entry(list_flow, struct valve, flow_sorted);
//int nworkers = worker[0].pos->index == worker[1].pos->index? 1: 2;
if (!--_pick) {
PAD4; log(4, "pick exhausted\n");
break;
}
for (int _w = 0; _w < _nworkers; ++_w) {
struct worker *w = worker + _w;
int d = DIST(w->pos->index, cur->index);
int remain = w->time - (d + 1);
PAD3; log(3, "worker %d/%d ", _w + 1, nworkers );
PAD3; log(3, "dist(%s,%s) = %d ", w->pos->val.str, cur->val.str, d);
if (remain < 1) {
PAD3; log(4, "time exhausted\n");
continue;
}
val = remain * cur->rate;
PAD3; log(3, "--> val=%d\n", val);
if (w->depth > 0) {
struct worker _tmp = *w;
w->pos = cur;
w->depth--;
w->time = remain;
/* do not use list_del() here, to preserve prev/next pointers */
__list_del_entry(list_flow);
sub = eval(_depth + 1, nworkers, worker, pick, pressure + w->pos->rate);
list_flow->prev->next = list_flow;
list_flow->next->prev = list_flow;
*w = _tmp;
} else {
sub = NULL;
}
val1 = sub? sub->evalflow: 0;
PAD3; log(3, "eval3(%s->%s)= %5d = %d + %d", w->pos->val.str, cur->val.str,
val+val1, val, val1);
if (val + val1 > max) {
max = val + val1;
best = cur;
bestworker = _w;
log(3, " NEW MAX !");
}
log(3, "\n");
}
}
if (best) {
best->evalflow = max;
best->worker = bestworker; /* FIXME */
PAD3; log(3, "EVAL returning best [%s] worker=%d eval=%d\n", best->val.str,
best->worker, max);
}
return best;
}
static struct valve *find_valve(union val val, int ntunnels, int rate)
{
struct valve *cur;
log_f(3, "val=%s ntunnels=%d rate=%d\n", val.str, ntunnels, rate);
list_for_each_entry(cur, &graph.index_sorted, index_sorted) {
//log(3, "\tcomparing with found, addr=%p\n", cur);
if (cur->val.val == val.val) {
log(3, "\tfound, addr=%p\n", cur);
if (ntunnels)
goto init;
goto end;
}
}
cur = pool_get(pool_valve);
cur->val.val = val.val;
cur->ntunnels = 0;
cur->state = CLOSED;
cur->worker = -1;
cur->evalflow = cur->playedflow = 0;
cur->evaltime = cur->playedtime = 30;
INIT_LIST_HEAD(&cur->index_sorted);
INIT_LIST_HEAD(&cur->flow_sorted);
INIT_LIST_HEAD(&cur->eval);
INIT_LIST_HEAD(&cur->played);
log(3, "\talloc new, addr=%p\n", cur);
init:
if (ntunnels) {
cur->rate = rate;
cur->tottunnels = ntunnels;
cur->tunnels = calloc(ntunnels, sizeof(struct valve *));
}
end:
return cur;
}
/**
* nthtok - get nth token fron string.
* @buf: buffer to parse.
* @sep: separators string.
* @n: token number (0: first token).
*
* @Return: pointer to token.
*/
static char *nthtok(char *buf, const char *sep, int n)
{
char *ret;
for (; n >= 0; n--) {
ret = strtok(buf, sep);
buf = NULL;
}
return ret;
}
#define SEP " ,;="
static struct graph *parse()
{
int index = 0, ntunnels;
size_t alloc = 0;
ssize_t buflen;
char *buf = NULL, *tok;
int rate;
struct valve *v1, *v2;
union val cur, link;
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
buf[--buflen] = 0;
/* valve name */
strncpy(cur.str, nthtok(buf, SEP, 1), sizeof(cur.str));
//printf("valve=%s ", tok);
rate = atoi(nthtok(NULL, SEP, 3));
//printf("rate=%s ", tok);
tok = nthtok(NULL, SEP, 4);
ntunnels = (buf + buflen - tok) / 4 + 1;
v1 = find_valve(cur, ntunnels, rate);
v1->index = index++;
// TODO: remove this list ?
list_add_tail(&v1->index_sorted, &graph.index_sorted);
graph.nvalves++;
//if (rate || v1->val.val == ('A' << 8 | 'A')) {
if (rate) {
struct valve *cur;
graph.npositive++;
/* keep this list sorted by flow decrasing */
list_for_each_entry(cur, &graph.flow_sorted, flow_sorted) {
if (rate > cur->rate) {
list_add_tail(&v1->flow_sorted, &cur->flow_sorted);
goto inserted;
}
}
list_add_tail(&v1->flow_sorted, &graph.flow_sorted);
inserted: ;
if (rate) {
//printf("adjust openable(%d): %#lx", v1->index, graph.openable);
graph.openable |= (1 << v1->index);
//printf("->%#lx", graph.openable);
}
}
//printf("lead=%s ntunnels=%d ", tok, ntunnels);
do {
link.val = *(u16 *)tok;
v2 = find_valve(link, 0, 0);
*(v1->tunnels + v1->ntunnels++) = v2;
//printf(",%s", tok);
} while ((tok = nthtok(NULL, SEP, 0)));
//printf("\n");
}
graph.aa = find_valve((union val) { .str="AA" }, 0, 0);
/* build array of indexed valves */
graph.indexed_all = calloc(graph.nvalves, sizeof(struct valve *));
list_for_each_entry(v1, &graph.index_sorted, index_sorted) {
graph.indexed_all[v1->index] = v1;
}
return &graph;
}
static int is_neighbour(int i, int j)
{
struct valve *v1 = graph.indexed_all[i], *v2 = graph.indexed_all[j];
for (int i = 0; i < v1->ntunnels; ++i)
if (v1->tunnels[i]->val.val == v2->val.val)
return 1;
return 0;
}
static void build_distances()
{
int i, j, k;
graph.dist = calloc(graph.nvalves * graph.nvalves, sizeof(int));
/* initialize values */
for (i = 0; i < graph.nvalves; ++i) {
for (j = 1; j < graph.nvalves; ++j) {
if (i != j) {
if (is_neighbour(i, j))
DIST(i, j) = DIST(j, i) = 1;
else
DIST(i, j) = DIST(j, i) = 10000;
}
}
}
/* get all distances using Floyd-Warshall
* see https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
*
* Add all vertices one by one to the set of intermediate vertices.
* ---> Before start of an iteration, we have shortest distances between all
* pairs of vertices such that the shortest distances consider only the
* vertices in set {0, 1, 2, .. k-1} as intermediate vertices.
* ----> After the end of an iteration, vertex no. k is added to the set of
* intermediate vertices and the set becomes {0, 1, 2, .. k}
*/
for (k = 0; k < graph.nvalves; k++) {
/* Pick all vertices as source one by one */
for (i = 0; i < graph.nvalves; i++) {
/* Pick all vertices as destination for the above picked source */
for (j = i + 1; j < graph.nvalves; j++)
DIST(i, j) = DIST(j, i) = min(DIST(i, j), DIST(i, k) + DIST(k, j));
}
}
return;
}
static void print_played(int nworkers)
{
struct valve *p;
int total = 0;
for (int w = 0; w < nworkers; ++w) {
int remain = 26, i = 1;
struct valve *prev = graph.aa;
i = 1;
printf("played by %d/%d:\n", w + 1, nworkers);
list_for_each_entry(p, &graph.played[w], played) {
printf("%2d: %s, ", i, p->val.str);
remain -= DIST(p->index, prev->index) + 1;
total += p->rate * remain;
printf("dist=%d remain=%d total=%d", DIST(p->index, prev->index), remain,
total);
printf("\n");
i++;
prev = p;
}
}
}
static int doit(int part)
{
struct worker w[2];
struct valve *best;
int res = 0;
//int topick = part == 1? 7: 12;
int topick = part == 1? 12: 12;
w[0].pos = w[1].pos = graph.aa;
//w[0].depth = w[1].depth = part == 1? 7: 4;
w[0].depth = w[1].depth = part == 1? 4: 4;
w[0].time = w[1].time = part == 1? 30: 26;
while ((best = eval(0, part, w, topick, 0))) {
list_del(&best->flow_sorted);
list_add_tail(&best->played, &graph.played[best->worker]);
w[best->worker].time -= DIST(w[best->worker].pos->index, best->index) + 1;
w[best->worker].pos = best;
res += best->rate * w[best->worker].time;
print_played(part);
}
return res;
}
static ulong part1()
{
return doit(1);
}
static ulong part2()
{
return doit(2);
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
pool_valve = pool_create("valve", 512, sizeof(struct valve));
parse();
build_distances();
print_valves();
printf("%s: res=%lu\n", *av, part == 1? part1(): part2());
exit(0);
}

17
2022/day16/aoc.h Normal file
View File

@@ -0,0 +1,17 @@
/* aoc.c: Advent of Code 2022
*
* Copyright (C) 2022-2023 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#ifndef _AOC_H_
#define _AOC_H_
extern int parseargs(int ac, char**av);
extern int testmode(void);
#endif /* _AOC_H_ */

68
2022/day16/common.bash Normal file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# common.bash: Advent of Code 2022, common bash functions
#
# Copyright (C) 2022-2023 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
# shellcheck disable=2034
export cmdname=${0##*/}
export debug=0
export res
export LANG=C
shopt -s extglob
set -o noglob
usage() {
printf "usage: %s [-d DEBUG] [-p PART]\n" "$cmdname"
exit 1
}
checkargs() {
local part=1
while getopts p:d: todo; do
case "$todo" in
d)
if [[ "$OPTARG" =~ ^[[:digit:]+]$ ]]; then
debug="$OPTARG"
else
printf "%s: illegal [%s] debug level.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
p)
if [[ "$OPTARG" =~ ^[12]$ ]]; then
part="$OPTARG"
else
printf "%s: illegal [%s] part.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
*)
usage
;;
esac
done
# Now check remaining argument (backup directory)
shift $((OPTIND - 1))
(( $# > 1 )) && usage
return "$part"
}
main() {
local -i part
checkargs "$@"
part=$?
parse "$part"
solve "$part"
printf "%s: res=%s\n" "$cmdname" "$res"
}

59
2022/day16/common.c Normal file
View File

@@ -0,0 +1,59 @@
/* common.c: Advent of Code 2022, common functions
*
* Copyright (C) 2022-2023 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "aoc.h"
#include "debug.h"
static int _testmode = 0;
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-t][-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int testmode(void)
{
return _testmode;
}
int parseargs(int ac, char **av)
{
int opt, part = 1;
while ((opt = getopt(ac, av, "td:p:")) != -1) {
switch (opt) {
case 't':
_testmode = 1;
break;
case 'd':
debug_level_set(atoi(optarg));
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
case 'i':
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
return part;
}

View File

@@ -0,0 +1,10 @@
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
Valve BB has flow rate=13; tunnels lead to valves CC, AA
Valve CC has flow rate=2; tunnels lead to valves DD, BB
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
Valve EE has flow rate=3; tunnels lead to valves FF, DD
Valve FF has flow rate=0; tunnels lead to valves EE, GG
Valve GG has flow rate=0; tunnels lead to valves FF, HH
Valve HH has flow rate=22; tunnel leads to valve GG
Valve II has flow rate=0; tunnels lead to valves AA, JJ
Valve JJ has flow rate=21; tunnel leads to valve II

View File

@@ -0,0 +1,54 @@
Valve EJ has flow rate=25; tunnel leads to valve MC
Valve WC has flow rate=0; tunnels lead to valves OW, RU
Valve NP has flow rate=0; tunnels lead to valves VR, KL
Valve AA has flow rate=0; tunnels lead to valves QT, AP, EZ, AK, XV
Valve VO has flow rate=6; tunnels lead to valves KM, RF, HS, LJ, IA
Valve CB has flow rate=0; tunnels lead to valves UI, UP
Valve TE has flow rate=18; tunnel leads to valve JT
Valve CZ has flow rate=0; tunnels lead to valves UP, OW
Valve LJ has flow rate=0; tunnels lead to valves DV, VO
Valve UP has flow rate=7; tunnels lead to valves SK, CB, CZ
Valve FP has flow rate=0; tunnels lead to valves OW, RE
Valve KM has flow rate=0; tunnels lead to valves SE, VO
Valve DV has flow rate=0; tunnels lead to valves LJ, UM
Valve FL has flow rate=0; tunnels lead to valves AH, TS
Valve VR has flow rate=24; tunnels lead to valves DM, TF, NP
Valve IA has flow rate=0; tunnels lead to valves VS, VO
Valve RF has flow rate=0; tunnels lead to valves VO, JF
Valve RT has flow rate=0; tunnels lead to valves UM, SE
Valve RU has flow rate=0; tunnels lead to valves AR, WC
Valve SE has flow rate=4; tunnels lead to valves GU, KM, CX, RT
Valve MC has flow rate=0; tunnels lead to valves EJ, AR
Valve TF has flow rate=0; tunnels lead to valves AH, VR
Valve CX has flow rate=0; tunnels lead to valves SE, TO
Valve GL has flow rate=11; tunnels lead to valves UY, KL, CY
Valve GU has flow rate=0; tunnels lead to valves SE, EZ
Valve VS has flow rate=0; tunnels lead to valves XN, IA
Valve EZ has flow rate=0; tunnels lead to valves AA, GU
Valve GK has flow rate=0; tunnels lead to valves FI, HZ
Valve JT has flow rate=0; tunnels lead to valves TE, XN
Valve DM has flow rate=0; tunnels lead to valves VR, HZ
Valve AR has flow rate=16; tunnels lead to valves UI, RU, MC
Valve XN has flow rate=9; tunnels lead to valves XP, JT, VS, GT, CY
Valve CY has flow rate=0; tunnels lead to valves XN, GL
Valve QT has flow rate=0; tunnels lead to valves UM, AA
Valve KL has flow rate=0; tunnels lead to valves GL, NP
Valve SK has flow rate=0; tunnels lead to valves XV, UP
Valve OW has flow rate=12; tunnels lead to valves CZ, WC, FP
Valve AK has flow rate=0; tunnels lead to valves AA, HS
Valve XV has flow rate=0; tunnels lead to valves AA, SK
Valve GT has flow rate=0; tunnels lead to valves XN, UM
Valve FI has flow rate=0; tunnels lead to valves JF, GK
Valve UY has flow rate=0; tunnels lead to valves JF, GL
Valve UM has flow rate=5; tunnels lead to valves DV, GT, RT, QT
Valve IQ has flow rate=0; tunnels lead to valves HZ, AH
Valve JF has flow rate=10; tunnels lead to valves RF, FI, UY, RE, TS
Valve TS has flow rate=0; tunnels lead to valves JF, FL
Valve AH has flow rate=23; tunnels lead to valves IQ, FL, TF
Valve HS has flow rate=0; tunnels lead to valves AK, VO
Valve HZ has flow rate=20; tunnels lead to valves IQ, DM, GK
Valve TO has flow rate=15; tunnel leads to valve CX
Valve XP has flow rate=0; tunnels lead to valves AP, XN
Valve AP has flow rate=0; tunnels lead to valves XP, AA
Valve RE has flow rate=0; tunnels lead to valves JF, FP
Valve UI has flow rate=0; tunnels lead to valves AR, CB

111
2022/day17/Makefile Normal file
View File

@@ -0,0 +1,111 @@
# AOC daily Makefile - GNU make only.
#
# Copyright (C) 2021-2023 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
INPUT := input/input.txt
SHELL := /bin/bash
CC := gcc
BEAR := bear
CCLSFILE:= compile_commands.json
LIB := aoc_$(shell uname -m)
INCDIR := ../include
LIBDIR := ../lib
LDFLAGS := -L$(LIBDIR)
#LDLIB := -l$(LIB) -lm
LDLIB := -l$(LIB)
export LD_LIBRARY_PATH = $(LIBDIR)
CFLAGS += -std=gnu11
CFLAGS += -O2
CFLAGS += -g
# for gprof
# CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
# Next one may be useful for valgrind (some invalid instructions)
# CFLAGS += -mno-tbm
CFLAGS += -Wmissing-declarations
CFLAGS += -Wno-unused-result
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
CFLAGS += -DDEBUG_POOL # memory pools management
VALGRIND := valgrind
VALGRINDFLAGS := --leak-check=full --show-leak-kinds=all --track-origins=yes \
--sigill-diagnostics=yes --quiet --show-error-list=yes
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
export PATH := .:$(PATH)
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 part1 part2 ccls bear org
all: README.org ccls part1 part2
memcheck: memcheck1 memcheck2
memcheck1: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
memcheck2: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
@#@valgrind -s --track-origins=yes aoc-c -p 2 < $(INPUT)
compile: aoc-c
cpp: aoc-c.i
assembly: aoc-c.s
part1: aoc-c
@#$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 1 < $(INPUT)
part2: aoc-c
@#$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html compile_commands.json
aoc-c: aoc-c.c common.c
@echo compiling $<
$(CC) $(CFLAGS) $(LDFLAGS) -I $(INCDIR) $^ $(LDLIB) -o $@
# generate pre-processed file (.i) and assembler (.s)
%.i: %.c
@echo generating $@
@$(CC) -E $(CFLAGS) -I $(INCDIR) $< -o $@
%.s: %.c
@echo generating $@
@$(CC) -S -fverbose-asm $(CFLAGS) -I $(INCDIR) $< -o $@
# generate README.org from README.html (must cleanup !)
org: README.org
%.org: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@touch .ccls-root
@$(BEAR) -- make compile

374
2022/day17/README.org Normal file
View File

@@ -0,0 +1,374 @@
** --- Day 17: Pyroclastic Flow ---
Your handheld device has located an alternative exit from the cave for
you and the elephants. The ground is rumbling almost continuously now,
but the strange valves bought you some time. It's definitely getting
warmer in here, though.
The tunnels eventually open into a very tall, narrow chamber. Large,
oddly-shaped rocks are falling into the chamber from above, presumably
due to all the rumbling. If you can't work out where the rocks will fall
next, you might be crushed!
The five types of rocks have the following peculiar shapes, where =#= is
rock and =.= is empty space:
#+begin_example
####
.#.
###
.#.
..#
..#
###
#
#
#
#
##
##
#+end_example
The rocks fall in the order shown above: first the =-= shape, then the
=+= shape, and so on. Once the end of the list is reached, the same
order repeats: the =-= shape falls first, sixth, 11th, 16th, etc.
The rocks don't spin, but they do get pushed around by jets of hot gas
coming out of the walls themselves. A quick scan reveals the effect the
jets of hot gas will have on the rocks as they fall (your puzzle input).
For example, suppose this was the jet pattern in your cave:
#+begin_example
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>
#+end_example
In jet patterns, =<= means a push to the left, while =>= means a push to
the right. The pattern above means that the jets will push a falling
rock right, then right, then right, then left, then left, then right,
and so on. If the end of the list is reached, it repeats.
The tall, vertical chamber is exactly /seven units wide/. Each rock
appears so that its left edge is two units away from the left wall and
its bottom edge is three units above the highest rock in the room (or
the floor, if there isn't one).
After a rock appears, it alternates between /being pushed by a jet of
hot gas/ one unit (in the direction indicated by the next symbol in the
jet pattern) and then /falling one unit down/. If any movement would
cause any part of the rock to move into the walls, floor, or a stopped
rock, the movement instead does not occur. If a /downward/ movement
would have caused a falling rock to move into the floor or an
already-fallen rock, the falling rock stops where it is (having landed
on something) and a new rock immediately begins falling.
Drawing falling rocks with =@= and stopped rocks with =#=, the jet
pattern in the example above manifests as follows:
#+begin_example
The first rock begins falling:
|..@@@@.|
|.......|
|.......|
|.......|
+-------+
Jet of gas pushes rock right:
|...@@@@|
|.......|
|.......|
|.......|
+-------+
Rock falls 1 unit:
|...@@@@|
|.......|
|.......|
+-------+
Jet of gas pushes rock right, but nothing happens:
|...@@@@|
|.......|
|.......|
+-------+
Rock falls 1 unit:
|...@@@@|
|.......|
+-------+
Jet of gas pushes rock right, but nothing happens:
|...@@@@|
|.......|
+-------+
Rock falls 1 unit:
|...@@@@|
+-------+
Jet of gas pushes rock left:
|..@@@@.|
+-------+
Rock falls 1 unit, causing it to come to rest:
|..####.|
+-------+
A new rock begins falling:
|...@...|
|..@@@..|
|...@...|
|.......|
|.......|
|.......|
|..####.|
+-------+
Jet of gas pushes rock left:
|..@....|
|.@@@...|
|..@....|
|.......|
|.......|
|.......|
|..####.|
+-------+
Rock falls 1 unit:
|..@....|
|.@@@...|
|..@....|
|.......|
|.......|
|..####.|
+-------+
Jet of gas pushes rock right:
|...@...|
|..@@@..|
|...@...|
|.......|
|.......|
|..####.|
+-------+
Rock falls 1 unit:
|...@...|
|..@@@..|
|...@...|
|.......|
|..####.|
+-------+
Jet of gas pushes rock left:
|..@....|
|.@@@...|
|..@....|
|.......|
|..####.|
+-------+
Rock falls 1 unit:
|..@....|
|.@@@...|
|..@....|
|..####.|
+-------+
Jet of gas pushes rock right:
|...@...|
|..@@@..|
|...@...|
|..####.|
+-------+
Rock falls 1 unit, causing it to come to rest:
|...#...|
|..###..|
|...#...|
|..####.|
+-------+
A new rock begins falling:
|....@..|
|....@..|
|..@@@..|
|.......|
|.......|
|.......|
|...#...|
|..###..|
|...#...|
|..####.|
+-------+
#+end_example
The moment each of the next few rocks begins falling, you would see
this:
#+begin_example
|..@....|
|..@....|
|..@....|
|..@....|
|.......|
|.......|
|.......|
|..#....|
|..#....|
|####...|
|..###..|
|...#...|
|..####.|
+-------+
|..@@...|
|..@@...|
|.......|
|.......|
|.......|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|..@@@@.|
|.......|
|.......|
|.......|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|...@...|
|..@@@..|
|...@...|
|.......|
|.......|
|.......|
|.####..|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|....@..|
|....@..|
|..@@@..|
|.......|
|.......|
|.......|
|..#....|
|.###...|
|..#....|
|.####..|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|..@....|
|..@....|
|..@....|
|..@....|
|.......|
|.......|
|.......|
|.....#.|
|.....#.|
|..####.|
|.###...|
|..#....|
|.####..|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|..@@...|
|..@@...|
|.......|
|.......|
|.......|
|....#..|
|....#..|
|....##.|
|....##.|
|..####.|
|.###...|
|..#....|
|.####..|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|..@@@@.|
|.......|
|.......|
|.......|
|....#..|
|....#..|
|....##.|
|##..##.|
|######.|
|.###...|
|..#....|
|.####..|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
#+end_example
To prove to the elephants your simulation is accurate, they want to know
how tall the tower will get after 2022 rocks have stopped (but before
the 2023rd rock begins falling). In this example, the tower of rocks
will be =3068= units tall.
/How many units tall will the tower of rocks be after 2022 rocks have
stopped falling?/

17
2022/day17/aoc.h Normal file
View File

@@ -0,0 +1,17 @@
/* aoc.c: Advent of Code 2022
*
* Copyright (C) 2022-2023 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#ifndef _AOC_H_
#define _AOC_H_
extern int parseargs(int ac, char**av);
extern int testmode(void);
#endif /* _AOC_H_ */

68
2022/day17/common.bash Normal file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# common.bash: Advent of Code 2022, common bash functions
#
# Copyright (C) 2022-2023 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
# shellcheck disable=2034
export cmdname=${0##*/}
export debug=0
export res
export LANG=C
shopt -s extglob
set -o noglob
usage() {
printf "usage: %s [-d DEBUG] [-p PART]\n" "$cmdname"
exit 1
}
checkargs() {
local part=1
while getopts p:d: todo; do
case "$todo" in
d)
if [[ "$OPTARG" =~ ^[[:digit:]+]$ ]]; then
debug="$OPTARG"
else
printf "%s: illegal [%s] debug level.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
p)
if [[ "$OPTARG" =~ ^[12]$ ]]; then
part="$OPTARG"
else
printf "%s: illegal [%s] part.\n" "$CMD" "$OPTARG"
exit 1
fi
;;
*)
usage
;;
esac
done
# Now check remaining argument (backup directory)
shift $((OPTIND - 1))
(( $# > 1 )) && usage
return "$part"
}
main() {
local -i part
checkargs "$@"
part=$?
parse "$part"
solve "$part"
printf "%s: res=%s\n" "$cmdname" "$res"
}

59
2022/day17/common.c Normal file
View File

@@ -0,0 +1,59 @@
/* common.c: Advent of Code 2022, common functions
*
* Copyright (C) 2022-2023 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "aoc.h"
#include "debug.h"
static int _testmode = 0;
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-t][-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int testmode(void)
{
return _testmode;
}
int parseargs(int ac, char **av)
{
int opt, part = 1;
while ((opt = getopt(ac, av, "td:p:")) != -1) {
switch (opt) {
case 't':
_testmode = 1;
break;
case 'd':
debug_level_set(atoi(optarg));
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
case 'i':
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
return part;
}

View File

@@ -0,0 +1 @@
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>

File diff suppressed because one or more lines are too long

View File

@@ -31,6 +31,17 @@
#define __PASTE(x, y) ___PASTE(x, y)
#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
/* unused/used parameters/functions
* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-unused-function-attribute
* https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-unused-type-attribute
* https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-unused-variable-attribute
* https://gcc.gnu.org/onlinedocs/gcc/Label-Attributes.html#index-unused-label-attribute
* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-used-function-attribute
* https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-used-variable-attribute
*/
#define __unused __attribute__((__unused__))
#define __used __attribute__((__used__))
/* see https://lkml.org/lkml/2018/3/20/845 for explanation of this monster
*/
#define __is_constexpr(x) \

View File

@@ -25,6 +25,7 @@
#ifdef DEBUG_DEBUG
void debug_init(u32 level);
void debug_level_set(u32 level);
u32 debug_level_get(void);
void _printf debug(u32 level, bool timestamp,
u32 indent, const char *src,
u32 line, const char *, ...);

View File

@@ -24,12 +24,23 @@
#define _pjw_inline static inline
#endif
_pjw_inline unsigned int pjwhash(const char* str, uint length)
/**
* unsigned int pjwhash - PJW hash function
* @key: the key address.
* @length: the length of key.
*
* This hash was created by Peter Jay Weinberger (AT&T Bell Labs):
* https://en.wikipedia.org/wiki/PJW_hash_function
*
* Return: the PJW hash.
*/
_pjw_inline uint pjwhash(const void* key, uint length)
{
uint hash = 0, high;
const u8 *k = key;
for (uint i = 0; i < length; ++str, ++i) {
hash = (hash << ONE_EIGHTH) + *str;
for (uint i = 0; i < length; ++k, ++i) {
hash = (hash << ONE_EIGHTH) + *k;
high = hash & HIGH_BITS;
if (high != 0) {
hash ^= high >> THREE_QUARTERS;

View File

@@ -15,6 +15,16 @@
#include "bits.h"
extern unsigned int pjwhash(const char* str, uint length);
/**
* unsigned int pjwhash - PJW hash function
* @key: the key address.
* @length: the length of key.
*
* This hash was created by Peter Jay Weinberger (AT&T Bell Labs):
* https://en.wikipedia.org/wiki/PJW_hash_function
*
* Return: the PJW hash.
*/
extern uint pjwhash (const void* key, uint length);
#endif /* _PJWHASH_H */

88
2022/libsrc/Makefile Normal file
View File

@@ -0,0 +1,88 @@
# AOC Makefile - GNU make only.
#
# Copyright (C) 2021-2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
SHELL := /bin/bash
CC := gcc
BEAR := bear
CCLSFILE:= compile_commands.json
#LIBS = -lreadline -lncurses
CFLAGS += -std=gnu11
CFLAGS += -O2
CFLAGS += -g
# for gprof
#CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
CFLAGS += -DDEBUG_POOL # memory pools management
# Next one may be useful for valgrind (some invalid instructions)
# CFLAGS += -mno-tbm
CFLAGS += -Wmissing-declarations
CFLAGS += -Wno-unused-result
INCDIR := ../include
LIBSRCDIR := .
LIBDIR := ../lib
LIB := libaoc_$(shell uname -m)
SLIB := $(LIBDIR)/$(LIB).a
DLIB := $(LIBDIR)/$(LIB).so
LIBSRC := $(wildcard $(LIBSRCDIR)/*.c)
LIBOBJ := $(patsubst %.c,%.o,$(LIBSRC))
LDFLAGS := -L$(LIBDIR)
LDLIB := -l$(LIB)
.PHONY: clean cleanlib cleanall all redo output lib $(SUBDIRS)
all: lib $(SUBDIRS)
compile: $(LIBOBJ)
clean:
@$(RM) -f *.o *.s *.i $(LIBOBJ)
cleanall: clean
@$(RM) -f $(SLIB) $(DLIB) $(LIBOBJ)
lib: $(DLIB) $(SLIB)
$(SLIB): $(LIBOBJ)
@echo building $@ static library.
@mkdir -p $(LIBDIR)
@$(AR) $(ARFLAGS) -o $@ $^
$(DLIB): CFLAGS += -fPIC
$(DLIB): LDFLAGS += -shared
$(DLIB): $(LIBOBJ)
@echo building $@ shared library.
@mkdir -p $(LIBDIR)
@$(CC) $(LDFLAGS) $^ -o $@
.c.o:
@echo compiling $<.
@$(CC) -c $(CFLAGS) $(LDFLAGS) -I $(INCDIR) -o $@ $<
# generate pre-processed file (.i) and assembler (.s)
%.i: %.c
@echo generating $@
@$(CC) -E $(CFLAGS) -I $(INCDIR) $< -o $@
%.s: %.c
@echo generating $@
@$(CC) -S -fverbose-asm $(CFLAGS) -I $(INCDIR) $< -o $@
bear: clean
@touch .ccls-root
@$(BEAR) -- make compile

View File

@@ -35,6 +35,11 @@ void debug_level_set(u32 level)
log(1, "debug level set to %u\n", level);
}
u32 debug_level_get()
{
return debug_level;
}
void debug_init(u32 level)
{
struct timespec timer;

View File

@@ -13,4 +13,8 @@
#define _pjw_inline extern
//#include "bits.h"
//extern unsigned int pjwhash (const void* key, uint length);
#include "pjwhash.h"
#include "pjwhash-inline.h"

View File

@@ -14,3 +14,7 @@
#### Advent of Code 2021
- `C`: All (days 1-25)
#### Advent of Code 2022
- `Bash`: All (days 1-12)
- `C`: All (days 1-14)