Compare commits

...

84 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
dfe2207e8e init day 9 2022-12-12 20:47:45 +01:00
31a255a9ac 2020 day 8 (C, both parts. No inspiration here) 2022-12-12 20:46:09 +01:00
25d25b399e 2022 day 8: bash final 2022-12-11 18:44:55 +01:00
f5ebb5c5cc 2022 day 8: Bash parts 1 & 2 2022-12-11 18:36:21 +01:00
c608f6dcde 2022 day 8 init 2022-12-10 16:53:33 +01:00
9e3a875e37 2022 day 7: C final version (parts 1 & 2) 2022-12-10 16:43:34 +01:00
4c0f6e3025 2022 day 7: C, parts 1 & 2 2022-12-10 14:56:46 +01:00
68f200ff65 2022: add PJW hash (lib) 2022-12-10 14:56:31 +01:00
8aff410ff4 2020 / day 7: final Bash cleanup 2022-12-10 07:43:14 +01:00
16da47600c 2022 day 7: clean bash code & remove file size info (50% speed) 2022-12-09 20:34:05 +01:00
8b68bf4449 2022 day 7: Bash parts 1 and 2 (messy, tons of debug) 2022-12-09 20:23:26 +01:00
c86517897e 2022 day 7 init 2022-12-09 16:42:45 +01:00
9c999e9717 2022 day 6: C (parts 1 and 2) 2022-12-09 16:25:56 +01:00
05643127c2 2022 day 6: Bash part 2 (lucky me: part 1 code worked) + optimizations 2022-12-09 14:38:21 +01:00
6a5a0da435 2022 day 6 init + bash part 1 2022-12-09 14:14:58 +01:00
3dd072c53e 2022 day 5 (C) 2022-12-09 11:47:32 +01:00
8f09fcf13f 2022 day 5 bash: simplify code (final ?) 2022-12-08 16:52:58 +01:00
8f444d7341 fix day # in comment 2022-12-08 16:30:55 +01:00
d7fa1c4fb5 Bash: 2022 day 5 (both parts, brute code) 2022-12-08 16:09:32 +01:00
0c787d9a51 2022/bash: move LANG=C to common.bash 2022-12-08 12:52:54 +01:00
64ad068ec8 2022/day 5 init 2022-12-08 12:45:04 +01:00
ab73311d6b 2022 day 4: C, parts 1 & 2 (lazy way: same algo as Bash) 2022-12-08 12:21:12 +01:00
d116b98ae9 Bash 2022/day4: remove nearly everything :-) 2022-12-08 11:45:40 +01:00
325c8254b8 Bash: 2022 day 4 part 2 2022-12-08 09:50:06 +01:00
76ab3d0c5b Bash: 2022/day 4 part 1 2022-12-08 09:43:43 +01:00
bc2b2ac726 C: 2022/Day 3 final cleanup + more comments 2022-12-08 08:19:57 +01:00
b7c0b1fa01 C 2022/Day 4 init 2022-12-08 08:18:27 +01:00
487766c0a2 C: 2022 day 3, remove useless code / variables 2022-12-07 22:21:19 +01:00
a0fddb5f44 2022 day 3 / cleanup some C code, update RESULTS.txt 2022-12-07 21:49:48 +01:00
f68d5b319e 2020 / day 3: C first working version (parts 1 & 2) 2022-12-07 21:38:46 +01:00
9455b99342 bash: 2022 day 3 (final 2 parts) 2022-12-07 19:07:16 +01:00
ea4967bfcd 2022 day 3 (bash, working version before cleanup) 2022-12-07 18:45:52 +01:00
d1026e8f59 2022 day 3 part 1 (bash) 2022-12-07 17:31:29 +01:00
01cdce6608 C: 2022 day 2 2022-12-07 15:37:00 +01:00
b8f6763a3b forgot 2022-12-07 13:40:01 +01:00
81a58c6266 update lib from tools repo (some fixed for 32 bits) 2022-12-07 13:20:48 +01:00
ca06a4a355 typo in printf 2022-12-07 13:20:29 +01:00
155 changed files with 17560 additions and 95 deletions

View File

@@ -12,9 +12,9 @@ declare floor
function adj() {
local -i r="$1" n="$2" c="$3" count=0
local -a prow=(${rows[r-1]})
local -a row=(${rows[r]})
local -a nrow=(${rows[r+1]})
local -a prow=("${rows[r-1]}")
local -a row=("${rows[r]}")
local -a nrow=("${rows[r+1]}")
#echo
#echo p="${prow[*]}"
#echo r="${row[*]}"
@@ -51,7 +51,7 @@ function run() {
changed=0
seated=0
for ((r=1; r<=NROWS; ++r)); do
row=(${rows[r]})
row=("${rows[r]}")
newrow=(0)
for ((c=1; c<=RLENGTH; ++c)); do
newrow+=("${row[c]}")
@@ -61,13 +61,13 @@ function run() {
case ${row[c]} in
0) continue
;;
1) if (( $(adj $r $c 2) == 0 )); then
1) if (( $(adj "$r" "$c" 2) == 0 )); then
((++changed))
newrow[c]=2
fi
#printf "[%d][%d]: %s %s %d\n" $r $c "${row[c]}" "${newrow[c]}" $(adj $r $c 2)
;;
2) if (( $(adj $r $c 2) >= 4 )); then
2) if (( $(adj "$r" "$c" 2) >= 4 )); then
((++changed))
newrow[c]=1
fi

View File

@@ -1,6 +1,6 @@
/* debug.c - debug/log management
*
* Copyright (C) 2021 Bruno Raoult ("br")
* Copyright (C) 2021-2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
@@ -22,8 +22,9 @@
#include "bits.h"
#include "debug.h"
#define NANOSEC 1000000000 /* nano sec in sec */
#define MILLISEC 1000000 /* milli sec in sec */
#define NS_SEC 1000000000 /* nano sec in sec */
#define MS_SEC 1000000 /* microsec in sec */
#define NS_MS 1000 /* nano in micro */
static long long timer_start; /* in nanosecond */
static u32 debug_level=0;
@@ -41,7 +42,7 @@ void debug_init(u32 level)
debug_level_set(level);
if (!clock_gettime(CLOCK_MONOTONIC, &timer)) {
timer_start = timer.tv_sec * NANOSEC + timer.tv_nsec;
timer_start = timer.tv_sec * NS_SEC + timer.tv_nsec;
}
else {
timer_start = 0;
@@ -54,10 +55,9 @@ inline static long long timer_elapsed()
struct timespec timer;
clock_gettime(CLOCK_MONOTONIC, &timer);
return (timer.tv_sec * NANOSEC + timer.tv_nsec) - timer_start;
return (timer.tv_sec * NS_SEC + timer.tv_nsec) - timer_start;
}
/* void debug - log function
* @timestamp : boolean
* @indent : indent level (2 spaces each)
@@ -77,8 +77,8 @@ void debug(u32 level, bool timestamp, u32 indent, const char *src,
if (timestamp) {
long long diff = timer_elapsed();
printf("%lld.%03lld ", diff/NANOSEC, (diff/1000000)%1000);
printf("%010lld ", diff);
printf("%lld.%03lld ", diff / NS_SEC, (diff % NS_SEC) / NS_MS);
printf("%010lldμs ", diff / NS_MS);
}
if (src) {

View File

@@ -5,17 +5,313 @@
+++++++++++++++++ part 1
aoc.bash: res=66719
time: 0:00.03 real, 0.02 user, 0.00 sys
context-switch: 0+1, page-faults: 0+274
context-switch: 0+1, page-faults: 0+257
aoc-c : res=66719
aoc-c: res=66719
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+89
context-switch: 0+1, page-faults: 0+88
+++++++++++++++++ part 2
aoc.bash: res=198551
time: 0:00.03 real, 0.03 user, 0.00 sys
context-switch: 2+1, page-faults: 0+283
context-switch: 2+1, page-faults: 0+259
aoc-c : res=198551
aoc-c: res=198551
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 5+1, page-faults: 0+87
context-switch: 0+1, page-faults: 0+87
=========================================
================= day02 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=11841
time: 0:00.05 real, 0.05 user, 0.00 sys
context-switch: 7+1, page-faults: 0+273
aoc-c: res=11841
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
+++++++++++++++++ part 2
aoc.bash: res=13022
time: 0:00.05 real, 0.03 user, 0.01 sys
context-switch: 9+1, page-faults: 0+272
aoc-c: res=13022
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
=========================================
================= day03 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=7878
time: 0:00.02 real, 0.01 user, 0.00 sys
context-switch: 2+1, page-faults: 0+301
aoc-c: res=7878
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
+++++++++++++++++ part 2
aoc.bash: res=2760
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 1+1, page-faults: 0+282
aoc-c: res=2760
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+88
=========================================
================= day04 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=444
time: 0:00.02 real, 0.01 user, 0.00 sys
context-switch: 0+1, page-faults: 0+258
aoc-c: res=444
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
+++++++++++++++++ part 2
aoc.bash: res=801
time: 0:00.02 real, 0.01 user, 0.00 sys
context-switch: 1+1, page-faults: 0+261
aoc-c: res=801
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
=========================================
================= day05 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=VQZNJMWTR
time: 0:00.08 real, 0.06 user, 0.01 sys
context-switch: 3+1, page-faults: 0+274
aoc-c: res=VQZNJMWTR
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
+++++++++++++++++ part 2
aoc.bash: res=NLCDCLVMQ
time: 0:00.04 real, 0.02 user, 0.01 sys
context-switch: 20+1, page-faults: 0+274
aoc-c: res=NLCDCLVMQ
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+86
=========================================
================= day06 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=1658
time: 0:00.06 real, 0.06 user, 0.00 sys
context-switch: 1+1, page-faults: 0+266
aoc-c: res=1658
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
+++++++++++++++++ part 2
aoc.bash: res=2260
time: 0:00.09 real, 0.09 user, 0.00 sys
context-switch: 1+1, page-faults: 0+265
aoc-c: res=2260
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
=========================================
================= day07 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=1390824
time: 0:00.05 real, 0.03 user, 0.01 sys
context-switch: 7+1, page-faults: 0+307
aoc-c: res=1390824
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+98
+++++++++++++++++ part 2
aoc.bash: res=7490863
time: 0:00.05 real, 0.05 user, 0.00 sys
context-switch: 9+1, page-faults: 0+308
aoc-c: res=7490863
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+98
=========================================
================= day08 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=1698
time: 0:01.10 real, 1.10 user, 0.00 sys
context-switch: 5+1, page-faults: 0+319
aoc-c: res=1698
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+92
+++++++++++++++++ part 2
aoc.bash: res=672280
time: 0:03.54 real, 3.53 user, 0.00 sys
context-switch: 48+1, page-faults: 0+284
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

@@ -71,7 +71,7 @@ int main(int ac, char **av)
pool_t *pool_tot = pool_create("total", 128, sizeof(struct plist_node));
parse(pool_tot);
printf("%s : res=%d\n", *av, calc_top_plist(part == 1? 1: 3));
printf("%s: res=%d\n", *av, calc_top_plist(part == 1? 1: 3));
pool_destroy(pool_tot);
exit(0);
}

View File

@@ -15,6 +15,7 @@
export cmdname=${0##*/}
export debug=0
export res
export LANG=C
shopt -s extglob
set -o noglob
@@ -25,7 +26,7 @@ usage() {
}
checkargs() {
local part
local part=1
while getopts p:d: todo; do
case "$todo" in
d)

View File

@@ -71,11 +71,11 @@ assembly: aoc-c.s
part1: aoc-c
@$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
@#$(TIME) aoc-c -p 1 < $(INPUT)
@$(TIME) aoc-c -p 1 < $(INPUT)
part2: aoc-c
@$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
@#$(TIME) aoc-c -p 2 < $(INPUT)
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)

64
2022/day02/aoc-c.c Normal file
View File

@@ -0,0 +1,64 @@
/* aoc-c.c: Advent of Code 2022, day 2
*
* 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 "plist.h"
#include "debug.h"
#include "pool.h"
#include "aoc.h"
/* we will use the following convention, for input line "a x":
* position in array=(a-'A' * 3) + x - 'X'
*/
enum {
A = 0, B, C,
X = 0, Y, Z
};
#define pos(x, y) ((x) * 3 + (y))
int outcome[2][9] = { /* shape is known */
{
[pos(A, X)] = 3 + 1, [pos(A, Y)] = 6 + 2, [pos(A, Z)] = 0 + 3,
[pos(B, X)] = 0 + 1, [pos(B, Y)] = 3 + 2, [pos(B, Z)] = 6 + 3,
[pos(C, X)] = 6 + 1, [pos(C, Y)] = 0 + 2, [pos(C, Z)] = 3 + 3
},
{ /* result is known */
[pos(A, X)] = 0 + 3, [pos(A, Y)] = 3 + 1, [pos(A, Z)] = 6 + 2,
[pos(B, X)] = 0 + 1, [pos(B, Y)] = 3 + 2, [pos(B, Z)] = 6 + 3,
[pos(C, X)] = 0 + 2, [pos(C, Y)] = 3 + 3, [pos(C, Z)] = 6 + 1
}
};
static int *parse(int *res)
{
size_t alloc = 0;
char *buf = NULL;
ssize_t buflen;
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
for (int i = 0; i < 2; ++i)
res[i] += outcome[i][pos(buf[0] - 'A', buf[2] - 'X')];
}
free(buf);
return res;
}
int main(int ac, char **av)
{
int res[2] = { 0, 0 };
printf("%s: res=%d\n", *av, parse(res)[parseargs(ac, av) - 1]);
exit(0);
}

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 1
# aoc.bash: Advent of Code 2022, day 2
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.

View File

@@ -15,6 +15,7 @@
export cmdname=${0##*/}
export debug=0
export res
export LANG=C
shopt -s extglob
set -o noglob

111
2022/day03/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

114
2022/day03/README.org Normal file
View File

@@ -0,0 +1,114 @@
** --- Day 3: Rucksack Reorganization ---
One Elf has the important job of loading all of the
[[https://en.wikipedia.org/wiki/Rucksack][rucksacks]] with supplies for
the jungle journey. Unfortunately, that Elf didn't quite follow the
packing instructions, and so a few items now need to be rearranged.
Each rucksack has two large /compartments/. All items of a given type
are meant to go into exactly one of the two compartments. The Elf that
did the packing failed to follow this rule for exactly one item type per
rucksack.
The Elves have made a list of all of the items currently in each
rucksack (your puzzle input), but they need your help finding the
errors. Every item type is identified by a single lowercase or uppercase
letter (that is, =a= and =A= refer to different types of items).
The list of items for each rucksack is given as characters all on a
single line. A given rucksack always has the same number of items in
each of its two compartments, so the first half of the characters
represent items in the first compartment, while the second half of the
characters represent items in the second compartment.
For example, suppose you have the following list of contents from six
rucksacks:
#+begin_example
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
#+end_example
- The first rucksack contains the items =vJrwpWtwJgWrhcsFMMfFFhFp=,
which means its first compartment contains the items =vJrwpWtwJgWr=,
while the second compartment contains the items =hcsFMMfFFhFp=. The
only item type that appears in both compartments is lowercase =p=.
- The second rucksack's compartments contain =jqHRNqRjqzjGDLGL= and
=rsFMfFZSrLrFZsSL=. The only item type that appears in both
compartments is uppercase =L=.
- The third rucksack's compartments contain =PmmdzqPrV= and =vPwwTWBwg=;
the only common item type is uppercase =P=.
- The fourth rucksack's compartments only share item type =v=.
- The fifth rucksack's compartments only share item type =t=.
- The sixth rucksack's compartments only share item type =s=.
To help prioritize item rearrangement, every item type can be converted
to a /priority/:
- Lowercase item types =a= through =z= have priorities 1 through 26.
- Uppercase item types =A= through =Z= have priorities 27 through 52.
In the above example, the priority of the item type that appears in both
compartments of each rucksack is 16 (=p=), 38 (=L=), 42 (=P=), 22 (=v=),
20 (=t=), and 19 (=s=); the sum of these is =157=.
Find the item type that appears in both compartments of each rucksack.
/What is the sum of the priorities of those item types?/
Your puzzle answer was =7878=.
** --- Part Two ---
As you finish identifying the misplaced items, the Elves come to you
with another issue.
For safety, the Elves are divided into groups of three. Every Elf
carries a badge that identifies their group. For efficiency, within each
group of three Elves, the badge is the /only item type carried by all
three Elves/. That is, if a group's badge is item type =B=, then all
three Elves will have item type =B= somewhere in their rucksack, and at
most two of the Elves will be carrying any other item type.
The problem is that someone forgot to put this year's updated
authenticity sticker on the badges. All of the badges need to be pulled
out of the rucksacks so the new authenticity stickers can be attached.
Additionally, nobody wrote down which item type corresponds to each
group's badges. The only way to tell which item type is the right one is
by finding the one item type that is /common between all three Elves/ in
each group.
Every set of three lines in your list corresponds to a single group, but
each group can have a different badge item type. So, in the above
example, the first group's rucksacks are the first three lines:
#+begin_example
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
#+end_example
And the second group's rucksacks are the next three lines:
#+begin_example
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
#+end_example
In the first group, the only item type that appears in all three
rucksacks is lowercase =r=; this must be their badges. In the second
group, their badge item type must be =Z=.
Priorities for these items must still be found to organize the sticker
attachment efforts: here, they are 18 (=r=) for the first group and 52
(=Z=) for the second group. The sum of these is =70=.
Find the item type that corresponds to the badges of each three-Elf
group. /What is the sum of the priorities of those item types?/
Your puzzle answer was =2760=.
Both parts of this puzzle are complete! They provide two gold stars: **

97
2022/day03/aoc-c.c Normal file
View File

@@ -0,0 +1,97 @@
/* aoc-c.c: Advent of Code 2022, day 3
*
* 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"
#define NCHARS ('Z' - 'A' + 1 + 'z' - 'a' + 1)
/* convert item to map position, and vice versa */
#define CHAR2POS(c) ((c) > 'Z'? (c) - 'a': (c) - 'A' + 26)
#define POS2CHAR(p) ((p) < 26? (p) + 'a': (p) - 26 + 'A')
/* set a map from char */
#define SET_MAP(ex, c) ((ex)[CHAR2POS(c)] = 1)
static void map_init(char *p)
{
memset(p, 0, NCHARS);
}
static void map_populate(char *ex, char *p, int len)
{
map_init(ex);
for (; len; --len)
SET_MAP(ex, p[len - 1]);
}
/* match map with items list. If dest is NULL, return first match,
* otherwise populate dest with matching chars.
*/
static int map_match(char *dest, char *map, char *items, int ilen)
{
if (dest)
map_init(dest);
for (int i = 0; i < ilen; ++i) {
int pos = CHAR2POS(items[i]);
if (map[pos]) { /* already exists */
if (dest)
dest[pos] = 1; /* fill dest array */
else
return pos + 1; /* one match only: return prio */
}
}
return -1; /* unused if dest != NULL */
}
static int parse(int part)
{
size_t alloc = 0;
char *buf = NULL;
ssize_t buflen;
int line = 0, res = 0;
char map[2][NCHARS];
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
buf[--buflen] = 0;
if (part == 1) {
int half = buflen / 2;
map_populate(*map, buf, half); /* populate and calculate */
res += map_match(NULL, *map, buf + half, half);
continue;
}
/* Part 2 here */
switch (++line % 3) { /* group lines by 3 */
case 1: /* line 1: populate *map */
map_populate(*map, buf, buflen);
break;
case 2: /* line 2: merge #1 into map[1] */
map_match(*(map + 1), *map, buf, buflen);
break;
case 0: /* line 3: final merge & calc */
res += map_match(NULL, *(map + 1), buf, buflen);
break;
}
}
free(buf);
return res;
}
int main(int ac, char **av)
{
printf("%s: res=%d\n", *av, parse(parseargs(ac, av)));
exit(0);
}

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

@@ -0,0 +1,86 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 3
#
# 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 input
# prio - get priority value for an item
# $1: reference of variable for result
# $2: string
prio() {
local -n _val="$1"
local _char="${2:0:1}"
printf -v _val "%d" "'$_char"
if [[ $_char > "Z" ]]; then # a-z
((_val += (1 - 97) ))
else # A-Z
((_val += (27 - 65) ))
fi
}
# common=chars - get common characters in two strings
# $1: reference of variable for result
# $2, $3: The two strings
common_chars() {
local -n _res="$1"
_res="${2//[^$3]}"
}
parse() {
readarray -t input
}
part1() {
local line half1 half2 common
local -i half i prio
declare -ig res=0
for line in "${input[@]}"; do
(( half = ${#line} / 2 ))
half1="${line:0:half}"
half2="${line:half}"
common="${half1//[^${half2}]}"
prio prio "${common}"
(( res += prio ))
done
}
part2() {
local one two three common
local -i i prio
declare -ig res=0
for (( i = ${#input[@]} - 1; i > 1; i -= 3)); do
three=${input[i]}
two=${input[i - 1]}
one=${input[i - 2]}
common_chars common "$three" "$two"
common_chars common "$common" "$one"
prio prio "${common}"
(( res += prio ))
done
}
solve() {
if (($1 == 1)); then
part1
else
part2
fi
}
main "$@"
exit 0

17
2022/day03/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/day03/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/day03/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,6 @@
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw

300
2022/day03/input/input.txt Normal file
View File

@@ -0,0 +1,300 @@
ZNNvFWHqLNPZHHqPTHHnTGBhrrpjvmwfMmpfpjBjwpmw
sbdzQgzgssgbglRtmjlwhjBlfrSrMt
zgsCRzJbsdRVQCDbcgLGWWLnZNGVLLZMNZnq
tvHhRtZGMvMHvfsrBBCTRbwbccRc
qznnlpzzDppWlDpQpCrcrwnBNwTZnBTZrn
PdVZJJqVZdllDPFtMjMgLjGMHvSgMF
csbhhVDDvzlVDcbccGGvfRjDHCjNLRHRCLfmnZfR
dFrStSTTmrrrHVfV
MMgQMMTMVTdgWtwTPwSgWSgGbbppJzlplvhBlPbzhlhbzG
FDJSTtSGhpPFDmFTZDpTFPmCBBrHqsCBhgBlqqrqrlRrHH
dQwMtfdzVwWfwctwnfnQCHllzRrsNzrrgNlCgqsr
fLfQnVjfwQfMdfvfnVvWDvtJPFGDpvZGbZpmbSPP
TzzCrJcDrTDdLDCJDvGNPCFqlZWlvNvWpq
RRHfjsQBFsjgjBQsWqGpNvZQqQlPPQPN
VnHBnRVssnnjsSfBwbMSrrbTwJTcwSDF
HJCgHCCFFFVGJWTlbqDdlqTDDpgl
cZccSmLrfZcrmmzSQftdpDtTHdbQTDMQ
NZZccrrBwZRPNNzmcLSSjJhGhVWCnsFnHBjGChsJ
qwwwJHTHqdFDtZBFPfFBZFzM
gVRcLnnWVgggnnnQgVWWNZtZrBfLBzZzBrMPPrZvPv
GQgQSVRtsVnNRGSCdpmwspmbmDpHmhwd
bhNgNfgwpbLMhCZMGQBmDm
FrcHrSllcqcFFMGLBDQlMDTGlT
FVSddRSJRjLwbjJPJw
wzhhrTwwTrSsdHQjjSHnBjQj
gRDCmVgRgMvtMfVMRBBBhWCHQQHGJHZJQZ
NtgVgttVbMNmvsNlpcrLhLTNPw
MCgjsfnscgjjgnGgJHHqHDgdHbGr
QSSmRFPpRtPFQLQRmPzvBzzzDWqrqWWHJGGNrJJbdtVWHJDV
BdSFdLQzRFlSLmQplffwncfscChhcsMj
GfVmfnmJVnNVFhnhGmbmhpHvqjrzHZBjfvrtBHHZrwBt
ddWQldlMdWMlQsLWTLQgMNwBrvjrZjNrwzZjswHqrv
QQdTRcgTRPDlMQlQPQdhcNNnbJmbGpVnGchFmm
CjjZCCZfvWZRHHhRtwhvPN
mrnqlqMqBlSSLnBTLBwmHPPWhPPHtFRPWzwt
rBVTrrMMSMLQBrndGcddWQbbdZfCZJ
LFtdjHjLjLqHqstLTjFLFqNMnMhhZdDDNMVbWdDDbhnZ
CrBpBGnzrzmczcllrphCZZWJMDWRbbZNMDMR
GwgvzpzvrcmBrnfHjTgqTsgHjF
rMPPZcplCZlZPwtSwhtBwCQQzB
FvDGffLqqmQFwmmhzt
TjJjJfHHVDVnHVgZZlQppcVscP
hVcqHwhgwwwjHjjGWbvrbBGrsWVWGn
CttPRpMmPDTWbWltlLBnGl
pZmDFMmPMfnZwqqwfcqJdHgz
bSJWhWJCbGGWJPStWTgRQwzDjgQQjsDW
nFBBVQVrVBrNFMFZVpBBZFZrDgdTldgsRsslsljsRzTRjzns
rMcZcHcBQPvbbHGP
mSfmwqfmzrfHwFfmrwvPHqPmMFRlMDDZBCVVRCVZVlZpMRRR
TWjdTWhTsssLTGsJNWhTQddjRMDMtNNBSCDBllMMBVtDMVRZ
QhWTQcdhjThsdGbTLGjWHmffnmHwnwHrwqmmfcwS
LmrsMQnnpfmMLllvTvqvFFzvFHNN
WGRFVWdwZWZvCbJzcvJNzw
VjGhDtWGSFRGjVVSFdjjDPBfspPnnMBLPLrrpMMm
qqqCCJjtqtqCtqLZspHWBdSrWWSzzbzHFWBldb
GhwwcwPFVDcNFRRGwwzmlBrBWvllrvSzlrcd
DGGhQNNDhTpZZqqLQFQQ
QfZmgQQZCCMLfNrgprdNvvdrTg
hhttsBmBDcFRBlJshJcRrnjnTvNqpddNNqvndp
JtsGJGtGGJJJHDbctllhZHmMwMQSPVPzHSLMPZmV
DScSjZcNBZqjDDcLLfFtPfCfjfPvfv
pTmRlWhdMwTLGwCf
mRdWCVVglWrCmVHVrVCmdrbSzNcBDBqBZDNHqssscNzqNc
sPMHGFMsrPNCPnNS
ffJzllbzpZBllttBtfglgBTbSCVCmmrNFmmbFNvCFLLb
cpZqpfgZZJtJqJJJfWHWhHdHWHjcdRdFHD
ZZPfppvzMrlNBFcvFB
shJgstJwWLVJwcrFFVFrBVNNqFFB
HwWJdLHWWLcQgssHwwSQSQtQzCnZZMpZCmdzZCzpPzpCPRCj
QCpLRbsCCQQLbQzCBQDQBBfTTffWtTctJVRNVtnfwtWV
GvlqqlGlmMrdsvrhmlcTvwJtwNwTvfJfcWTW
lMhgqGhddjqFFCzBBpbsSQpD
JJwGJwVQQwVSsSMhQMQgHfgfTtrrfVTNgNNfrt
dFDWCDdFppvDFmWWWnJTPllHmHlgrqrgggtH
DzFbWjdRpbdFCjjRbnFbQBGhhQBBJZwMhScwZwJz
HttvHpHmpJWtHmFNvlvdMSVdPMtLVCCMMMfcfL
GjgzhGSGSSdCcRMVjMdc
QshbnghgnGDnqsFrNSJFrsNs
wJpjMwzjzdVbzPPVpbCHnqGnBqnsBrNCwgrC
ftTLLDTQtLTGTGtFrgHrvqgQnrvQsCHH
fTcFFfLSfFFcGFllcFhPJPjWWJSjSWzMWPdS
ZjNdmjVQVZmvNNZNNZHWZmWtsJnwTpJJswpWwGqJhJqGpp
FcRRcDblDMLRcRMLFFMDGsJnqhwpqTTJGwnsfnlp
LRBrcLbbgLFgBbFqDvdHQvCCjNzzzVrZdV
BdbLWrgdvgWvVJgWnDfNhVnqhCCpDpcq
tSQPSTSGPMmlMPtQQPJGtGQRCcnqqfnRhCcChDqnCfRScf
jTssPsjMQMmszPjlTtsJdFBFrJzrbJdHZFHdWH
vCccctvvTTtZcgLGcZTbssbMWnpMpmLWqnNjpfPPfPjMPp
wwBBlRBBwDDVFRhFlRhdRRVWPnnpMpffmmffrpWqVNPm
ddhddRzHlQHFJcGsCztTgbNzST
fJctfpVWcnfRLfrRwP
vmmnvDQDZTNTmGGTqTMTvMqwBdLjBvRzBRrRBRLjjBPzBB
GMnmqSTFFQqttcbcJWgsSt
rHNfmfRsmfRGfDNcRmcmMQlLCGSnQwwPPCSnzQlSCl
bsJTBsVhFsVpqFWFgPCwnQwBZzwQzZLlzn
qggTTqvqgqbbTTFqVqgWqvNmmMMRdffftNfMDMmscR
rFWQFszrwjsjFWvshPTCmLZLSTLwSLlgSP
BQbcqVHNVqVpVpmClJgJJHSmZLJm
qBNNNVdDMGBpDcDWsvdQsFrFnjttfj
qGhmttmzhtMvhbrLdSHbdSHRzb
WCBgQJJpjCQlgdHZrfPRPSRbNg
jBTTDjlnjnJDJTQCVntcwtwMSvqcGFDhcvsh
ZTrnTqMWWWnfrddMGJPgPLlPbw
VvmGRVpBpNNmvNvjVjtpNpCNLLLJHHBdgLPdwsdsbLlwwlwb
GmCVSCRVGmpCRVvttmpDrQZfhnzhzqnDWnrZZTQq
DQBZHHtWHzSvZvDQWchgqsqqhrrhhcqrcZ
jdMfwlFfFlTfndwpjjwGnNrqhPTmPSPTPPhmgrPSrh
jlGbwGMdlnJpGFGjpnFCSJzzDDtWHCBBQBvtVC
RrbBWBRRWSRsBBVvsPHZDwSjjPdnHwtPtH
fTgfzMmNJpmJgfllgpjVQtDDndVQpdnHVtPp
gGmlNclTGmGFhLVcVrvLqrvc
QcpCTVCZVcCwLcCVvHvvVsCcNzNNSbPRzsDRDSBlsNNzDRtb
fggMfJqgrWFpmjWMggmrfMWNSbRSPBDbNtJRtPJzlStBbN
gdnmpWGnZvdQCvdv
tqqcLqqDDqNtDrqHrrPWlTlTWZTMzTFzQlMPSZ
pfnpmmppmppRGjwbjmnjwspWbQQQTMWZbCTSZCSQlCllZF
gmpVnGmmmpjDvVLBFqqvrH
LqBvJHZvbHGBHrBtGGQTmSVprVzhpVPDPQzQ
CRdRgwCfhTVDzSdQ
fRCcjgSMjfNgMMLGbGZtvBbGHv
HgvtDDzDpvwgvvqdHPZWdMssTTddSs
rJFrGNFVQmNFVmRnWhhsrTbhwhZTrdTd
VQGBBBVNQClpcBvBwD
PWlSzZGmdmGmlGmhggBpvMjvMjFgPJ
TtLRDtQQfTVcQQQRtBsJFFccFjWhJJFMBs
HqVCNtWHCDwdnlGwGqSr
RwdRJgCJRGGmdMbcGbdnTnTtttLLnptMtMtMqZ
DWsWPFrPqVPPLVCB
zQWWsslsQHFhDSszDSFQzJJJmvcgblRgmNvCJmvNgw
tpmFrWTtRpRTtggsSlnQpsnnlSHPsn
bZwZjNNZGLSrVsGndPPV
NvrcjCfbvvLBDBWfWFgRRm
WWFMgWmMhhwDcMMMDcmLWLtQwwsjbsQHvZHbRjZfsZzH
PTCplTCdSJJCpvPGNSvsbsfHtbQZzdHjQtjjsj
vNGJPpqJvJvqghgFgWFmLD
RlRpLTZCjWRjRWwpRsjHjbSbqMqMvvnbnGMnGGqQCq
gddfDNczmgPthNcDdgPVnbbzbnJrJJGSSVJJQS
BmDmcDmcmhffdBHlRwjRLpwlWQ
prQlfzlWRPzgQWzlMPMRppssHHsDsHjwnHHbWDwwbwjL
vFBJJtZNShJvZFtdSqtmqjTDVHVGDHbwVHDVsDnThH
vcjBZZdZqvCfpzRfcgRp
cggpqgRlSpNsgNggbjjj
ZZSSJVLVLFDZWNGjCWWbCjsF
vZLvfZQQfQtJVJDQShLrLfMmnldmwqwTqqMcMTMTndrm
bQBMtBPddtMFbJFhRGzMfzvnRGRSvWnW
TmHTqlVHwVpQqjmwGvSgSpnLpzfWGWSn
TTrDQCDrrTmDCCCVHHQZBdZFPdsNdFBtFDhtFB
fjpQvNZcGhGGTtQS
DVJzvbVmHbbtSTSTRStzTM
VDvmqllmJfjWlnplNs
ZmdHZJjvQLdRjpmLJrqqZBhhtCschPfBPcrDfPffCD
MWWSMMwnwlSgzWFFgSwzVwzqcfDCfChCbbtssbfDChcD
NMqFTwGqMwgwwgjHRdHRjdmQmQTm
TTqWPCWRhTWqPNjPJMNtrlbJFttQwwrBrlbwlc
GfpSDGZvpQffSHDgggDZrHctFmrHncnnwwbBtBrt
SQGfLsSLZsqMTRNMPT
HdBdnBZJTZBBmsfwwBlh
MjCVjzwqWrfzplzW
vVbqCjjRgjwMbnbGHJScScZHLL
dwwwtCdznvDDFrMrrw
GmWLQmgQmHgcdGcsTgTDqDbSfFWfMDMfbSNqvr
QhTLmVQHLmdLTjGGVptRnZpZBZVRpPpP
CzjFpzRHdtBFBCqNqSbJZWcQJTSbQjMTWZ
wGwVLlGrdVGwDnwsgfMSZvJMbWJcWlvbbMSc
rDfsgggrGnGngsPwdVLfDnmDtzzFNCPHtzCtFHpBRqhPztzR
mrgWzBcDtVCcQcCCdscf
LRJhjRjPZvqSRGhGjLgMCdHpMNwQCpMHpHMS
GRvGJRJjqPZbvGGhRjnqLJWtgFgtzTzDrFnTWrlTlllW
cbmcddlffvbTfvFflpZzsMVNznNVlnqnzqHMNM
StWJBQRWLRWNPNMCswRVHC
BJQBhSWhjSthJQGGWWggJDDDfbdbbfHbddbrFrddvFvv
jFqvqvWZWDtBJrrlrq
TzGcbHcrmVzMGNSmTcGDtBthJCNtsJDlBCghgP
bTrnTccnLSrrTHbnwfLjfdvRRwZFdwfR
drHVrdVDfsDbVsdVDbVqRwbZZwCRCCCJlJThwRgT
jFPcFpBSvtNPzSFcjcQpcQjpThZCRltGRRRJhwCwGhwgwhRm
SQSzPBjjPPSvLqqssdnqLZLMsM
bQTWlWlvQclNwwWlCCLStCRSSjStpj
zVZZDdBnBmgzVsjsLthSpshdCL
DfBnrmBmgzHBfDHmnGrNFCwQvTPvqCTwqTFGbF
srSWJnrbmlWlbhzsWszSvPGwvgDhcjdjjfvhjvGv
BRRQFLtNfQNMpqpQHDjdDjDcZZcvwZZHPH
NLCNCtRQfRttRFRCTqMBqQQrzrbzrlJmVVbsSWmVrTbSzJ
RHLfLcSRTFSghLRHGbwZmMZddgJswZsbMm
ptqjtCzzQztqCjDlBGpDpbMZdwmMbZsdwNmdJpbs
tttzCVllDCtDQnQBVHGHWvWTLWcLSLHf
FVlNnPqbGTHftghggJqf
zLcZWZpWWrcrZLLZDWrwMcrhBFBttChBmBgptChhtFftmf
LZZLrDrrDDMrcwrDwsWFzdTlnGQPQQVbdbnsvnvsVQ
BbPNMJNbQvDbvPLwHflczlwwzf
pZjWZGZjFGdgpnVgZhghdmcflrlswzzcstlrLwhtwc
WZSdqFjqSqSWdGFjZpdMTTDNTvLCRRLLqRQMCN
FqgFGtbgTvRwrLqhvw
JCCWJWCdJMQNNsSWsMPQRDDLDSDLwTrrvnwfDvnD
HdPJlBBHCCQdBMWdTtVbgHczGVGjmtzG
PLlZDLZDsFCvbDQv
HVcTmVmJqVzqczfzbjvvCFMRfCsWjMvR
cqHzTqJTTTTzzmnmrctrBlLlvSlgLdZvSwSlpw
SbMMNJjmgMnJdSSbjVFZVSQrlQfWVQVWZh
PtqDqPGcLHzHpqLcRzRsfQFfZlfRfZfRFVsl
cTDLcqGCzDTqzzDLDzqPTtJvbBJMnmvjbdlmJNvmdgNC
tDJDlZVqJGbvHNQbNFFsFPmLns
ppczpzpffGwfBNLGmn
WShzgTTpWzhWztJJGJSvtvvtjq
TbZFTFScnCZFQRTCqQdBjdJqjBqjjQDB
rmmLpLLfzrlmslMBHvdRddNDDJDrqD
MWwLPzmWfpsMmmlMPMWLwRTZTZnnTcVCcZFCwSnZ
SqmClqHssNWCqPTcWcGhBTchVV
ZnnnDflRpBVTTVhPBZ
DpgfvnvMfCsqlMtSll
ZzLMRZpLMwwppZqnQGvQgBSvlNVlBFFNFVrg
HcqhTmhmdDTPFTJgTTFBSgJN
mccPdDDHbssbtwZMqpbzCRGM
TgqnTltgWqLRSRnlqddngFfrvHvrBTfCCFrFVTvVCf
cwNJmPzQwNzczzNsJGhhHfhrfvVHGvtvVVfC
jjtbtDswcmPWlbgRnRdMZL
TmpTBBwvspTptRmsmTGLQDGRHGgVGLSQSMHQ
ZlPWqjWrzjPqdrlzbrbrwfrWLHVMLnHDMVDQnLQfQfVngQLS
zNwbrrFWbFJpmpmvvt
RMQQMwHMMzcFsWsDrWfcpJpS
LLhZmGVLhVlTZfWWfWpCrDsGSp
VLVTnqjjZngtQRFjvzDM
gmRBpjrpRvCfRCrBgvjHShnbnngbgSJnNsHMHS
ZDPTwGWtqwHhSnbcMNJw
DWGGqtVVqldWZzMzWmvjrjprLRFjRVvvff
tCzVzsVtDFzssnSsgdqJdCNqJhmgmpqq
PZccPGvQfRLMQwNdhpwhNh
jLrcbRjPZBrcPdjRHFlWnVtBFslSWznW
vvvbJbWrLvFWHzZzZRhB
chtwTmCNlRRZzRPT
hmcCssCswrMDGMSrsr
LStGBsQLlllhzMzs
dzVZDNWRDdZNDTZTPvWVhhphpMlfMccRmfnlMlRn
VFvgTrNPdFWNNFNFTzTFFSjSQBCqrtQwSBGLLBGwGL
qGJSJhWStdSfWvSvtGRRnzRDDggrgvnzsmRP
lTTLpcljjGlLlLNBpjwFQDQmRnrRDPrPscRrDDng
NCNjFlHNCTVjpwGqGSVbJddqZZJM
MbWdgvHFlMvmzTzShvmm
tqjqpLsNsrrsjstNLpQrGVhVBzrhVcfmchDcTPVVmc
RqwjqjqsGjjGGQNjGpQZpqRFJgmMHwdbFWgnHMFdwmmCFW
HHHLcCcVHjTHglsB
wDSRwzzRpMSdNSPSwSpRbqvgBsdqlgTvBFBjgFvvgB
RpbzPssDMWwNRbRNRPDsDhJthLQVGLJcctQCJQfQJCLm
WsZgbNgZVCCWbVVVmgZbCCRPccGnzPBqJjzWJBJPzvBvGz
SpfThHtrHFBPPzJvPntj
QHDhhrhpTQpHhQHnfwnTCNlbZCCDLNllZlVsNCNl
QtzJFRQLMRnZcZsfcphlPQ
qSBbjmWSCNmVldSqqSqmjCSZshfwfrPPZZfcPVZfhgsgPg
HqBbHqBGSlNBbltnLLHFJMtRvRTD
tcGtDdMcttttHNBlMctldlwjwwqqCLCwDwZjFCZhmnwC
VrJgvWWsPvRgVgrJQvfQfzgVzZwCbLZmnmwCwZqmnhjZbnLj
sJpffsRWWRJVWWpHltSpnMHGcMTl
zNqRbqSbfdcTLLfS
ZVPzPnVvdLwLDPfF
VWnzQCVWZVMzQRHgqgqrHGtGMp
PbHpWfWPvRfbzWPFfRpPDtBwSHMwCBgDwBjDtMMM
hTTdZQlcnTcmqVTdcddrDgBSwsjjBgqBtsCgMD
hlldTmdJJmJdZvzfFfNJFJgRzR
PJWvJBbWsfLQWsLvmCqHCcNLHqHLLcwDqV
dQztrZrdwHhptqDH
ZrMGjgMSrdzQGQRJPvGGbm
RmjljZChlDZBCRRvlmNSLSqMNLzwLvppwQSQ
sTnVnPrVGsGTPddJrfgQgqLgGpMNQtgNtNzg
sbbTfTdcJPnHbsJfHsdcmDDmmqBZlClmjBRDCZ
CJmHLmHFFCFbHsbJsJqvqhQqLDhQZvnQDZnn
wGwppTjdWPdgFpGcScBqNnNqNhQlDqnDlZZW
pGcgGgTpGjFdwpSFVgSdpPjrMCMffzJzRzztRfHCRsVmtbsz
CgBClZfCflPflNZRvfQswwmwmwQsQhgppdhm
qbzDGrjLLNLDHDqtJmmhhmQdhwpQhhbp
NLGqVqjDjjGrMFrvFWPBRBZnCvfFnT
tbrrHsgsVmmmbtgwVsQRqjJMmqMjQfJfLFLD
ZvlBGzdvjGfRFJQJ
dBppnnBBhdzZncBPlznpnNdWHSsbWthbSCgHrVfgSSwVgr
VRvMtRVFHQLvMRQFQtBctrthshTTgCmhTrgWhWZsZZ
lzJlGBSPPhzjgZsTCr
wJlpJPfDSpwBnddqJDdpPpcvMFHFMvNbvnNMFHHRVVbR
CPShbbdlGCdQqlRPGPdlDWDFzjtFjggCDJgWczfF
mrHrTrrBMBsmNsrwsBpnfpggDDcjjDDpjzFJzzjtJz
BvsNvBLHrrrNvwBTNNsNGbdQhlPGGfqhhRGqLGdl
PSSlPtlStGhPNMtwPMPJzDddnbnDNTDDnJqjbz
FFVHRwVLvFvVrVHrZcLmRHggjDmdDnDnznnznzQjzdmJddbn
WrvgRgcRcRrrcRvgcVrHVrwCCSfsCsGsllhMSSSSMttlSCpG
hBPJqVZTqqPSlGlfddfddZvl
JWWMJCpnMrmztzdjnzld
RbWsrwMrpbRspbWgpwhLJPccNVqLLPSVgVPV
hcTrWqcfhwGfWrWMjHjGvDHPmJMDzF
ZtlsnZZtLBSbSssnbndjDJJFHFHJPHPsHMTHHM
ntRZtSbtZgZStTqchwQfRwNpcq
GfLqrsqQGgPgjjQGVcNvTpTpNFcWPvPPpT
bRnRLnMZFdCMcpvT
RnRhzRlmlhhHhhmhRsqLrfzrGVSrGBSGrL
fbMffwdZsncrGcfG
qDBjSSLqhLBSmDbjqNhqTLjCGrCHGrvcGWcpWcrGWnCrpm
STLDqbhTLqNTNSRhlwZlJlRQFFRwMdPQ
TVVGNFggcjPPJzwvQlRRwRvSlcSc
frsBbWhtSRzSLfRf
qDCqddbsWrqzhsdNmdJNJHjTggFFVV
NTWTDrSdFTLtPTGf
lZqjHlVRvRltLtRWFMtFLL
qvjWzzvVbZpjqllggscdchwDrCphwsdhrD

111
2022/day04/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

90
2022/day04/README.org Normal file
View File

@@ -0,0 +1,90 @@
** --- Day 4: Camp Cleanup ---
Space needs to be cleared before the last supplies can be unloaded from
the ships, and so several Elves have been assigned the job of cleaning
up sections of the camp. Every section has a unique /ID number/, and
each Elf is assigned a range of section IDs.
However, as some of the Elves compare their section assignments with
each other, they've noticed that many of the assignments /overlap/. To
try to quickly find overlaps and reduce duplicated effort, the Elves
pair up and make a /big list of the section assignments for each pair/
(your puzzle input).
For example, consider the following list of section assignment pairs:
#+begin_example
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
#+end_example
For the first few pairs, this list means:
- Within the first pair of Elves, the first Elf was assigned sections
=2-4= (sections =2=, =3=, and =4=), while the second Elf was assigned
sections =6-8= (sections =6=, =7=, =8=).
- The Elves in the second pair were each assigned two sections.
- The Elves in the third pair were each assigned three sections: one got
sections =5=, =6=, and =7=, while the other also got =7=, plus =8= and
=9=.
This example list uses single-digit section IDs to make it easier to
draw; your actual list might contain larger numbers. Visually, these
pairs of section assignments look like this:
#+begin_example
.234..... 2-4
.....678. 6-8
.23...... 2-3
...45.... 4-5
....567.. 5-7
......789 7-9
.2345678. 2-8
..34567.. 3-7
.....6... 6-6
...456... 4-6
.23456... 2-6
...45678. 4-8
#+end_example
Some of the pairs have noticed that one of their assignments /fully
contains/ the other. For example, =2-8= fully contains =3-7=, and =6-6=
is fully contained by =4-6=. In pairs where one assignment fully
contains the other, one Elf in the pair would be exclusively cleaning
sections their partner will already be cleaning, so these seem like the
most in need of reconsideration. In this example, there are =2= such
pairs.
/In how many assignment pairs does one range fully contain the other?/
Your puzzle answer was =444=.
** --- Part Two ---
It seems like there is still quite a bit of duplicate work planned.
Instead, the Elves would like to know the number of pairs that /overlap
at all/.
In the above example, the first two pairs (=2-4,6-8= and =2-3,4-5=)
don't overlap, while the remaining four pairs (=5-7,7-9=, =2-8,3-7=,
=6-6,4-6=, and =2-6,4-8=) do overlap:
- =5-7,7-9= overlaps in a single section, =7=.
- =2-8,3-7= overlaps all of the sections =3= through =7=.
- =6-6,4-6= overlaps in a single section, =6=.
- =2-6,4-8= overlaps in sections =4=, =5=, and =6=.
So, in this example, the number of overlapping assignment pairs is =4=.
/In how many assignment pairs do the ranges overlap?/
Your puzzle answer was =801=.
Both parts of this puzzle are complete! They provide two gold stars: **

43
2022/day04/aoc-c.c Normal file
View File

@@ -0,0 +1,43 @@
/* aoc-c.c: Advent of Code 2022, day 4
*
* 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"
static int parse(int part)
{
int res = 0, val[4];
while (scanf("%d-%d,%d-%d", val, val+1, val+2, val+3) == 4) {
if (part == 1) {
if ( (val[0] >= val[2] && val[1] <= val[3] ) ||
(val[0] <= val[2] && val[1] >= val[3] ) ) {
res++;
}
} else {
if ( (val[0] >= val[2] && val[0] <= val[3] ) ||
(val[0] <= val[2] && val[1] >= val[2] ) ) {
res++;
}
}
}
return res;
}
int main(int ac, char **av)
{
printf("%s: res=%d\n", *av, parse(parseargs(ac, av)));
exit(0);
}

37
2022/day04/aoc.bash Executable file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 4
#
# 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
parse() {
local -i _part="$1"
local -a _arr
declare -ig res=0
while IFS=-, read -ra _arr; do
# shellcheck disable=2068
set -- ${_arr[@]}
if (( _part == 1 )); then
(( ( ($1 >= $3 && $2 <= $4) || ($1 <= $3 && $2 >= $4) ) && res++ ))
else
(( ( ($1 >= $3 && $1 <= $4) || ($1 <= $3 && $2 >= $3) ) && res++ ))
fi
done
}
solve() {
:
}
main "$@"
exit 0

17
2022/day04/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/day04/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/day04/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,6 @@
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8

1000
2022/day04/input/input.txt Normal file

File diff suppressed because it is too large Load Diff

111
2022/day05/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

169
2022/day05/README.org Normal file
View File

@@ -0,0 +1,169 @@
** --- Day 5: Supply Stacks ---
The expedition can depart as soon as the final supplies have been
unloaded from the ships. Supplies are stored in stacks of marked
/crates/, but because the needed supplies are buried under many other
crates, the crates need to be rearranged.
The ship has a /giant cargo crane/ capable of moving crates between
stacks. To ensure none of the crates get crushed or fall over, the crane
operator will rearrange them in a series of carefully-planned steps.
After the crates are rearranged, the desired crates will be at the top
of each stack.
The Elves don't want to interrupt the crane operator during this
delicate procedure, but they forgot to ask her /which/ crate will end up
where, and they want to be ready to unload them as soon as possible so
they can embark.
They do, however, have a drawing of the starting stacks of crates /and/
the rearrangement procedure (your puzzle input). For example:
#+begin_example
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2
#+end_example
In this example, there are three stacks of crates. Stack 1 contains two
crates: crate =Z= is on the bottom, and crate =N= is on top. Stack 2
contains three crates; from bottom to top, they are crates =M=, =C=, and
=D=. Finally, stack 3 contains a single crate, =P=.
Then, the rearrangement procedure is given. In each step of the
procedure, a quantity of crates is moved from one stack to a different
stack. In the first step of the above rearrangement procedure, one crate
is moved from stack 2 to stack 1, resulting in this configuration:
#+begin_example
[D]
[N] [C]
[Z] [M] [P]
1 2 3
#+end_example
In the second step, three crates are moved from stack 1 to stack 3.
Crates are moved /one at a time/, so the first crate to be moved (=D=)
ends up below the second and third crates:
#+begin_example
[Z]
[N]
[C] [D]
[M] [P]
1 2 3
#+end_example
Then, both crates are moved from stack 2 to stack 1. Again, because
crates are moved /one at a time/, crate =C= ends up below crate =M=:
#+begin_example
[Z]
[N]
[M] [D]
[C] [P]
1 2 3
#+end_example
Finally, one crate is moved from stack 1 to stack 2:
#+begin_example
[Z]
[N]
[D]
[C] [M] [P]
1 2 3
#+end_example
The Elves just need to know /which crate will end up on top of each
stack/; in this example, the top crates are =C= in stack 1, =M= in stack
2, and =Z= in stack 3, so you should combine these together and give the
Elves the message =CMZ=.
/After the rearrangement procedure completes, what crate ends up on top
of each stack?/
Your puzzle answer was =VQZNJMWTR=.
** --- Part Two ---
As you watch the crane operator expertly rearrange the crates, you
notice the process isn't following your prediction.
Some mud was covering the writing on the side of the crane, and you
quickly wipe it away. The crane isn't a CrateMover 9000 - it's a
/CrateMover 9001/.
The CrateMover 9001 is notable for many new and exciting features: air
conditioning, leather seats, an extra cup holder, and /the ability to
pick up and move multiple crates at once/.
Again considering the example above, the crates begin in the same
configuration:
#+begin_example
[D]
[N] [C]
[Z] [M] [P]
1 2 3
#+end_example
Moving a single crate from stack 2 to stack 1 behaves the same as
before:
#+begin_example
[D]
[N] [C]
[Z] [M] [P]
1 2 3
#+end_example
However, the action of moving three crates from stack 1 to stack 3 means
that those three moved crates /stay in the same order/, resulting in
this new configuration:
#+begin_example
[D]
[N]
[C] [Z]
[M] [P]
1 2 3
#+end_example
Next, as both crates are moved from stack 2 to stack 1, they /retain
their order/ as well:
#+begin_example
[D]
[N]
[C] [Z]
[M] [P]
1 2 3
#+end_example
Finally, a single crate is still moved from stack 1 to stack 2, but now
it's crate =C= that gets moved:
#+begin_example
[D]
[N]
[Z]
[M] [C] [P]
1 2 3
#+end_example
In this example, the CrateMover 9001 has put the crates in a totally
different order: =MCD=.
Before the rearrangement process finishes, update your simulation so
that the Elves know where they should stand to be ready to unload the
final supplies. /After the rearrangement procedure completes, what crate
ends up on top of each stack?/
Your puzzle answer was =NLCDCLVMQ=.
Both parts of this puzzle are complete! They provide two gold stars: **

115
2022/day05/aoc-c.c Normal file
View File

@@ -0,0 +1,115 @@
/* aoc-c.c: Advent of Code 2022, day 5
*
* 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 MAXSTACKS 128
typedef struct crate {
int code;
struct list_head list;
} crate_t;
static pool_t *pool_crates;
static void move_stack(struct list_head *stacks, int from, int to, int nb)
{
for (int i = 0; i < nb; ++i)
/* Attention !! we should test if &stacks[from - 1] is not empty here */
list_move(stacks[from - 1].next, &stacks[to - 1]);
}
static void move_bulk(struct list_head *stacks, int from, int to, int nb)
{
struct list_head *tail;
LIST_HEAD(bulk);
int count = 1;
list_for_each(tail, &stacks[from - 1])
if (count++ == nb)
break;
list_cut_position(&bulk, &stacks[from - 1], tail);
list_splice(&bulk, &stacks[to - 1]);
}
static void parse(struct list_head *stacks, int *nstacks, int part)
{
size_t alloc = 0;
char *buf = NULL;
ssize_t buflen;
int state = 0;
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
buf[--buflen] = 0;
if (!buflen || buf[1] == '1') {
state = 1;
continue;
}
if (!state) { /* stacks */
int stack = 0, pos, code;
for(pos = 1; pos < buflen; pos += 4, stack++) {
if ((code = buf[pos]) != ' ') {
crate_t *new = pool_get(pool_crates);
new->code = code;
list_add_tail(&new->list, stacks + stack);
if (stack == *nstacks)
++*nstacks;
}
}
} else { /* moves */
int nb, from, to;
if ((sscanf(buf, "%*s%d%*s%d%*s%d", &nb, &from, &to)) == 3) {
if (part == 1)
move_stack(stacks, from, to, nb);
else
move_bulk(stacks, from, to, nb);
}
}
}
}
static char *build_res(struct list_head *stacks, int nstacks, char *res)
{
int i;
for (i = 0; i < nstacks; ++ i) {
crate_t *cur = list_first_entry(&stacks[i], crate_t, list);
res[i] = cur->code;
}
res[i] = 0;
return res;
}
int main(int ac, char **av)
{
char res[MAXSTACKS + 1];
int part = parseargs(ac, av);
struct list_head stacks[MAXSTACKS];
int nstacks = 0;
for (ulong ul = 0; ul < ARRAY_SIZE(stacks); ++ul)
INIT_LIST_HEAD(&stacks[ul]);
pool_crates = pool_create("crates", 64, sizeof (crate_t));
parse(stacks, &nstacks, part);
printf("%s: res=%s\n", *av, build_res(stacks, nstacks, res));
pool_destroy(pool_crates);
exit(0);
}

62
2022/day05/aoc.bash Executable file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 5
#
# 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 stacks=() rules=()
parse() {
local -i _queue _state=1
local _input
local -a _parse
while IFS= read -r _input; do
if [[ -z ${_input} || ${_input:1:1} == "1" ]]; then
_state=2
continue
fi
if (( _state == 1 )); then # stacks description
for (( i = 0, _queue = 0; i < ${#_input}; i += 4, _queue++ )); do
sub=${_input:i:4}
[[ $sub == " "* ]] || stacks[$_queue]+="${sub:1:1}"
done
else # moves description
rules+=( "${_input//[a-z]/}" )
fi
done
}
solve() {
local -i _part="$1" _i=0 _j=0 _nb _from _to
local -a _rule
for ((; _i < ${#rules[@]}; ++_i )); do
read -ra _rule <<< "${rules[$_i]}"
(( _nb = _rule[0], _from = _rule[1] - 1, _to = _rule[2] - 1 ))
if ((_part == 1)); then
# move elements one by one
for ((_j = 0; _j < _nb; ++_j)); do
stacks[$_to]="${stacks[$_from]:0:1}${stacks[$_to]}"
stacks[$_from]=${stacks[$_from]:1}
done
else
# move elements by block
stacks[$_to]="${stacks[$_from]:0:_nb}${stacks[$_to]}"
stacks[$_from]=${stacks[$_from]:_nb}
fi
done
printf -v res "%c" "${stacks[@]}"
}
main "$@"
exit 0

17
2022/day05/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/day05/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/day05/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,9 @@
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2

511
2022/day05/input/input.txt Normal file
View File

@@ -0,0 +1,511 @@
[L] [M] [M]
[D] [R] [Z] [C] [L]
[C] [S] [T] [G] [V] [M]
[R] [L] [Q] [B] [B] [D] [F]
[H] [B] [G] [D] [Q] [Z] [T] [J]
[M] [J] [H] [M] [P] [S] [V] [L] [N]
[P] [C] [N] [T] [S] [F] [R] [G] [Q]
[Z] [P] [S] [F] [F] [T] [N] [P] [W]
1 2 3 4 5 6 7 8 9
move 7 from 3 to 9
move 5 from 8 to 9
move 3 from 9 to 5
move 6 from 9 to 2
move 9 from 9 to 3
move 3 from 7 to 3
move 8 from 2 to 3
move 9 from 3 to 1
move 11 from 3 to 8
move 5 from 6 to 9
move 1 from 6 to 3
move 1 from 2 to 7
move 1 from 4 to 8
move 1 from 3 to 9
move 4 from 4 to 3
move 6 from 8 to 3
move 2 from 8 to 2
move 4 from 9 to 3
move 3 from 2 to 5
move 2 from 5 to 4
move 5 from 3 to 4
move 11 from 1 to 4
move 1 from 7 to 6
move 1 from 3 to 5
move 2 from 1 to 9
move 1 from 1 to 4
move 7 from 5 to 8
move 21 from 4 to 6
move 6 from 6 to 2
move 6 from 8 to 9
move 5 from 8 to 5
move 2 from 2 to 7
move 4 from 3 to 7
move 1 from 2 to 6
move 1 from 2 to 5
move 2 from 2 to 7
move 4 from 3 to 7
move 1 from 4 to 6
move 9 from 5 to 3
move 7 from 3 to 4
move 7 from 7 to 3
move 7 from 4 to 1
move 8 from 3 to 5
move 1 from 3 to 5
move 3 from 8 to 2
move 2 from 2 to 9
move 13 from 9 to 4
move 5 from 5 to 3
move 4 from 7 to 6
move 1 from 7 to 4
move 2 from 4 to 2
move 3 from 3 to 4
move 2 from 5 to 2
move 6 from 1 to 7
move 1 from 2 to 8
move 1 from 3 to 8
move 1 from 1 to 6
move 1 from 3 to 4
move 1 from 2 to 6
move 24 from 6 to 1
move 3 from 2 to 3
move 3 from 3 to 5
move 2 from 8 to 6
move 2 from 5 to 4
move 3 from 5 to 1
move 7 from 4 to 8
move 3 from 8 to 9
move 2 from 9 to 5
move 2 from 6 to 3
move 1 from 9 to 8
move 5 from 7 to 5
move 2 from 3 to 1
move 1 from 7 to 1
move 7 from 4 to 7
move 2 from 4 to 8
move 6 from 8 to 6
move 3 from 6 to 9
move 10 from 5 to 1
move 7 from 7 to 1
move 1 from 4 to 9
move 1 from 6 to 3
move 2 from 9 to 7
move 1 from 4 to 2
move 1 from 9 to 5
move 1 from 8 to 5
move 39 from 1 to 8
move 1 from 2 to 5
move 2 from 6 to 9
move 3 from 9 to 5
move 3 from 1 to 6
move 1 from 7 to 2
move 1 from 3 to 2
move 2 from 6 to 2
move 3 from 2 to 3
move 1 from 6 to 2
move 1 from 1 to 8
move 3 from 1 to 2
move 3 from 2 to 4
move 2 from 4 to 5
move 2 from 3 to 8
move 8 from 5 to 2
move 8 from 8 to 2
move 15 from 2 to 7
move 1 from 1 to 5
move 25 from 8 to 7
move 2 from 2 to 4
move 2 from 4 to 3
move 1 from 8 to 4
move 2 from 4 to 6
move 1 from 2 to 1
move 26 from 7 to 2
move 15 from 2 to 1
move 7 from 8 to 9
move 10 from 1 to 6
move 10 from 7 to 2
move 1 from 8 to 1
move 5 from 9 to 8
move 1 from 8 to 9
move 2 from 6 to 9
move 3 from 7 to 1
move 1 from 7 to 1
move 5 from 9 to 2
move 1 from 3 to 1
move 9 from 6 to 3
move 1 from 6 to 1
move 4 from 2 to 4
move 3 from 4 to 8
move 1 from 4 to 1
move 9 from 3 to 1
move 1 from 7 to 6
move 9 from 2 to 5
move 14 from 1 to 6
move 1 from 3 to 8
move 5 from 2 to 6
move 8 from 1 to 8
move 6 from 6 to 8
move 14 from 6 to 7
move 1 from 1 to 7
move 10 from 5 to 4
move 11 from 8 to 5
move 15 from 7 to 1
move 4 from 5 to 6
move 4 from 8 to 9
move 6 from 5 to 3
move 1 from 6 to 9
move 1 from 1 to 6
move 1 from 5 to 8
move 2 from 6 to 2
move 6 from 1 to 5
move 1 from 5 to 8
move 2 from 5 to 4
move 9 from 2 to 9
move 13 from 9 to 8
move 1 from 2 to 1
move 1 from 4 to 8
move 3 from 3 to 1
move 2 from 4 to 5
move 2 from 1 to 5
move 1 from 9 to 3
move 17 from 8 to 1
move 3 from 3 to 2
move 4 from 5 to 1
move 2 from 2 to 4
move 1 from 6 to 1
move 1 from 2 to 8
move 4 from 4 to 6
move 1 from 5 to 9
move 5 from 6 to 8
move 1 from 5 to 4
move 1 from 5 to 6
move 3 from 8 to 6
move 8 from 4 to 5
move 32 from 1 to 7
move 11 from 7 to 6
move 8 from 5 to 3
move 3 from 8 to 7
move 6 from 3 to 9
move 4 from 3 to 8
move 5 from 8 to 2
move 1 from 8 to 5
move 11 from 6 to 3
move 1 from 5 to 2
move 2 from 8 to 6
move 12 from 7 to 8
move 2 from 6 to 2
move 2 from 6 to 4
move 5 from 2 to 5
move 8 from 7 to 2
move 2 from 7 to 1
move 2 from 7 to 6
move 5 from 5 to 4
move 5 from 4 to 7
move 5 from 8 to 2
move 2 from 9 to 7
move 5 from 8 to 4
move 2 from 7 to 3
move 2 from 9 to 3
move 3 from 7 to 9
move 1 from 1 to 8
move 2 from 6 to 1
move 2 from 9 to 8
move 1 from 7 to 8
move 1 from 2 to 5
move 1 from 7 to 9
move 7 from 4 to 3
move 3 from 3 to 6
move 5 from 8 to 6
move 3 from 9 to 5
move 16 from 3 to 1
move 2 from 9 to 1
move 7 from 1 to 8
move 1 from 1 to 2
move 5 from 8 to 2
move 12 from 1 to 4
move 1 from 3 to 5
move 1 from 2 to 9
move 1 from 9 to 4
move 4 from 6 to 5
move 5 from 6 to 1
move 1 from 6 to 5
move 1 from 1 to 4
move 1 from 4 to 7
move 1 from 3 to 7
move 9 from 4 to 6
move 2 from 7 to 8
move 1 from 3 to 4
move 2 from 8 to 9
move 4 from 8 to 4
move 4 from 2 to 8
move 2 from 9 to 7
move 2 from 7 to 8
move 10 from 2 to 4
move 1 from 2 to 1
move 5 from 4 to 7
move 1 from 1 to 3
move 3 from 8 to 7
move 6 from 7 to 2
move 3 from 2 to 7
move 1 from 6 to 7
move 5 from 5 to 8
move 4 from 1 to 3
move 4 from 3 to 1
move 8 from 4 to 2
move 1 from 3 to 2
move 2 from 7 to 2
move 2 from 6 to 3
move 4 from 7 to 2
move 4 from 5 to 7
move 14 from 2 to 7
move 3 from 2 to 1
move 3 from 8 to 2
move 1 from 5 to 7
move 6 from 2 to 4
move 2 from 2 to 7
move 2 from 3 to 6
move 6 from 8 to 2
move 4 from 6 to 4
move 2 from 6 to 9
move 4 from 4 to 2
move 2 from 4 to 8
move 10 from 7 to 2
move 18 from 2 to 6
move 2 from 2 to 6
move 2 from 9 to 2
move 2 from 8 to 5
move 1 from 2 to 9
move 1 from 2 to 9
move 1 from 5 to 7
move 1 from 2 to 6
move 2 from 9 to 2
move 6 from 7 to 3
move 7 from 6 to 8
move 5 from 7 to 2
move 1 from 7 to 4
move 1 from 5 to 7
move 4 from 8 to 7
move 5 from 2 to 3
move 1 from 7 to 5
move 2 from 2 to 8
move 9 from 4 to 3
move 13 from 6 to 8
move 10 from 3 to 1
move 1 from 5 to 2
move 3 from 6 to 8
move 5 from 1 to 2
move 1 from 1 to 8
move 2 from 4 to 3
move 17 from 8 to 6
move 5 from 6 to 3
move 3 from 1 to 2
move 9 from 6 to 5
move 2 from 6 to 8
move 5 from 5 to 9
move 3 from 9 to 8
move 3 from 1 to 3
move 3 from 7 to 5
move 6 from 5 to 8
move 7 from 2 to 4
move 1 from 6 to 3
move 1 from 1 to 5
move 4 from 4 to 5
move 2 from 2 to 9
move 3 from 1 to 3
move 4 from 5 to 8
move 1 from 4 to 5
move 6 from 8 to 7
move 1 from 5 to 2
move 4 from 9 to 2
move 2 from 5 to 9
move 2 from 1 to 8
move 2 from 4 to 9
move 6 from 7 to 5
move 3 from 5 to 2
move 3 from 2 to 5
move 10 from 8 to 3
move 2 from 8 to 5
move 3 from 2 to 5
move 6 from 5 to 1
move 4 from 5 to 6
move 1 from 7 to 5
move 23 from 3 to 7
move 2 from 5 to 9
move 2 from 1 to 5
move 2 from 6 to 3
move 6 from 3 to 1
move 1 from 1 to 7
move 4 from 3 to 1
move 1 from 8 to 5
move 2 from 9 to 2
move 3 from 3 to 8
move 2 from 6 to 8
move 12 from 1 to 3
move 1 from 9 to 7
move 3 from 5 to 9
move 9 from 3 to 8
move 1 from 1 to 7
move 1 from 9 to 4
move 3 from 3 to 6
move 3 from 2 to 1
move 3 from 8 to 6
move 1 from 4 to 2
move 1 from 2 to 9
move 1 from 2 to 7
move 20 from 7 to 5
move 3 from 7 to 3
move 3 from 1 to 3
move 5 from 8 to 1
move 5 from 1 to 5
move 4 from 5 to 2
move 3 from 2 to 6
move 3 from 8 to 7
move 1 from 2 to 6
move 2 from 8 to 6
move 2 from 7 to 5
move 2 from 3 to 6
move 12 from 5 to 1
move 6 from 5 to 7
move 12 from 6 to 8
move 4 from 9 to 3
move 4 from 5 to 8
move 3 from 1 to 5
move 4 from 7 to 4
move 3 from 5 to 9
move 7 from 1 to 6
move 1 from 1 to 3
move 6 from 7 to 6
move 1 from 1 to 3
move 10 from 3 to 6
move 10 from 6 to 2
move 2 from 9 to 5
move 4 from 6 to 5
move 9 from 6 to 1
move 16 from 8 to 7
move 3 from 8 to 7
move 1 from 8 to 1
move 7 from 2 to 1
move 1 from 5 to 9
move 1 from 6 to 1
move 2 from 2 to 1
move 3 from 1 to 4
move 1 from 6 to 8
move 7 from 4 to 1
move 1 from 8 to 2
move 22 from 1 to 8
move 18 from 7 to 9
move 6 from 5 to 2
move 2 from 2 to 7
move 2 from 1 to 5
move 4 from 7 to 6
move 1 from 5 to 6
move 2 from 8 to 2
move 3 from 2 to 6
move 1 from 5 to 6
move 15 from 9 to 6
move 6 from 9 to 5
move 1 from 9 to 8
move 1 from 2 to 9
move 5 from 5 to 9
move 9 from 8 to 6
move 3 from 2 to 7
move 12 from 8 to 9
move 1 from 7 to 5
move 1 from 5 to 7
move 3 from 7 to 1
move 17 from 6 to 3
move 1 from 2 to 6
move 2 from 1 to 4
move 16 from 6 to 4
move 7 from 4 to 6
move 1 from 5 to 7
move 8 from 4 to 5
move 9 from 9 to 8
move 16 from 3 to 7
move 1 from 1 to 5
move 3 from 5 to 1
move 5 from 6 to 2
move 3 from 1 to 7
move 3 from 6 to 7
move 3 from 9 to 3
move 5 from 8 to 5
move 11 from 5 to 7
move 2 from 3 to 7
move 1 from 2 to 1
move 1 from 3 to 6
move 17 from 7 to 9
move 1 from 3 to 2
move 3 from 4 to 6
move 1 from 1 to 2
move 1 from 6 to 4
move 14 from 7 to 6
move 15 from 9 to 6
move 4 from 8 to 7
move 1 from 4 to 7
move 7 from 9 to 5
move 5 from 2 to 9
move 7 from 5 to 1
move 3 from 1 to 7
move 29 from 6 to 4
move 1 from 2 to 4
move 18 from 4 to 2
move 3 from 1 to 4
move 1 from 1 to 7
move 18 from 2 to 4
move 3 from 6 to 5
move 15 from 4 to 1
move 1 from 5 to 1
move 1 from 5 to 4
move 9 from 4 to 1
move 5 from 1 to 3
move 9 from 1 to 5
move 2 from 4 to 3
move 5 from 5 to 6
move 3 from 7 to 9
move 7 from 7 to 5
move 6 from 4 to 6
move 2 from 3 to 7
move 6 from 5 to 8
move 2 from 8 to 4
move 1 from 8 to 9
move 9 from 6 to 2
move 3 from 9 to 3
move 1 from 2 to 1
move 6 from 7 to 4
move 2 from 2 to 8
move 3 from 9 to 5
move 5 from 4 to 8
move 1 from 6 to 9
move 1 from 3 to 1
move 1 from 3 to 4
move 1 from 6 to 5
move 1 from 9 to 3
move 10 from 8 to 7
move 3 from 9 to 2
move 7 from 2 to 4
move 6 from 5 to 7
move 4 from 5 to 8
move 7 from 3 to 2
move 3 from 7 to 1
move 9 from 1 to 5
move 5 from 7 to 9
move 7 from 1 to 4
move 11 from 4 to 2
move 4 from 8 to 3
move 5 from 4 to 7
move 4 from 4 to 1
move 1 from 3 to 6
move 12 from 7 to 4
move 2 from 1 to 8
move 5 from 9 to 7
move 7 from 5 to 6
move 1 from 1 to 4
move 1 from 9 to 8
move 1 from 4 to 7
move 1 from 8 to 9
move 5 from 7 to 9
move 2 from 7 to 5
move 2 from 6 to 3
move 5 from 2 to 7
move 1 from 7 to 8
move 1 from 1 to 6
move 3 from 5 to 1

111
2022/day06/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

85
2022/day06/README.org Normal file
View File

@@ -0,0 +1,85 @@
** --- Day 6: Tuning Trouble ---
The preparations are finally complete; you and the Elves leave camp on
foot and begin to make your way toward the /star/ fruit grove.
As you move through the dense undergrowth, one of the Elves gives you a
handheld /device/. He says that it has many fancy features, but the most
important one to set up right now is the /communication system/.
However, because he's heard you have [[/2016/day/6][significant]]
[[/2016/day/25][experience]] [[/2019/day/7][dealing]]
[[/2019/day/9][with]] [[/2019/day/16][signal-based]]
[[/2021/day/25][systems]], he convinced the other Elves that it would be
okay to give you their one malfunctioning device - surely you'll have no
problem fixing it.
As if inspired by comedic timing, the device emits a few colorful
sparks.
To be able to communicate with the Elves, the device needs to /lock on
to their signal/. The signal is a series of seemingly-random characters
that the device receives one at a time.
To fix the communication system, you need to add a subroutine to the
device that detects a /start-of-packet marker/ in the datastream. In the
protocol being used by the Elves, the start of a packet is indicated by
a sequence of /four characters that are all different/.
The device will send your subroutine a datastream buffer (your puzzle
input); your subroutine needs to identify the first position where the
four most recently received characters were all different. Specifically,
it needs to report the number of characters from the beginning of the
buffer to the end of the first such four-character marker.
For example, suppose you receive the following datastream buffer:
#+begin_example
mjqjpqmgbljsphdztnvjfqwrcgsmlb
#+end_example
After the first three characters (=mjq=) have been received, there
haven't been enough characters received yet to find the marker. The
first time a marker could occur is after the fourth character is
received, making the most recent four characters =mjqj=. Because =j= is
repeated, this isn't a marker.
The first time a marker appears is after the /seventh/ character
arrives. Once it does, the last four characters received are =jpqm=,
which are all different. In this case, your subroutine should report the
value =7=, because the first start-of-packet marker is complete after 7
characters have been processed.
Here are a few more examples:
- =bvwbjplbgvbhsrlpgdmjqwftvncz=: first marker after character =5=
- =nppdvjthqldpwncqszvftbrmjlhg=: first marker after character =6=
- =nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg=: first marker after character =10=
- =zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw=: first marker after character =11=
/How many characters need to be processed before the first
start-of-packet marker is detected?/
Your puzzle answer was =1658=.
** --- Part Two ---
Your device's communication system is correctly detecting packets, but
still isn't working. It looks like it also needs to look for /messages/.
A /start-of-message marker/ is just like a start-of-packet marker,
except it consists of /14 distinct characters/ rather than 4.
Here are the first positions of start-of-message markers for all of the
above examples:
- =mjqjpqmgbljsphdztnvjfqwrcgsmlb=: first marker after character =19=
- =bvwbjplbgvbhsrlpgdmjqwftvncz=: first marker after character =23=
- =nppdvjthqldpwncqszvftbrmjlhg=: first marker after character =23=
- =nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg=: first marker after character =29=
- =zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw=: first marker after character =26=
/How many characters need to be processed before the first
start-of-message marker is detected?/
Your puzzle answer was =2260=.
Both parts of this puzzle are complete! They provide two gold stars: **

60
2022/day06/aoc-c.c Normal file
View File

@@ -0,0 +1,60 @@
/* aoc-c.c: Advent of Code 2022, day 6
*
* 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 "aoc.h"
struct msg {
char *data;
size_t len;
};
static struct msg *parse(struct msg *msg)
{
size_t alloc = 0;
msg->data=NULL;
msg->len = getline(&msg->data, &alloc, stdin);
msg->data[--msg->len] = 0;
return msg;
}
static int solve(struct msg *msg, int marklen)
{
char *pcur = msg->data, *pnext = pcur;
int len = msg->len, lmark = 0;
for (; pnext < msg->data + len && lmark < marklen; lmark = ++pnext - pcur) {
for (int j = 0; j < lmark; ++j) { /* compare with prev marker chars */
if (*(pcur+j) == *pnext) { /* check new char with cur marker */
pcur += j + 1; /* move marker to after dup char */
goto nextchar;
}
}
nextchar: ;
}
return pnext - msg->data;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
struct msg msg;
printf("%s: res=%d\n", *av, solve(parse(&msg), part == 1? 4:14));
free(msg.data);
exit(0);
}

46
2022/day06/aoc.bash Executable file
View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 6
#
# 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 input # datastream
declare -i len # len of datastream
parse() {
read -r input
len=${#input}
}
solve() {
declare -ig res
local -i mark=4 lcur=0 part="$1"
local cur next
((part == 2)) && mark=14
for (( i = 0; i < len - mark; ++i )); do # loop on all chars
next=${input:i:1} # next char
for ((j = 0; j < lcur; ++j)); do # compare with previous ones
if [[ $next == "${cur:j:1}" ]]; then # duplicate
cur="${cur:j+1}$next" # keep str after dup + new char
(( lcur -= j ))
continue 2
fi
done
cur+="$next" # add new char
((++lcur == mark)) && break # mark len found
done
((res = i + 1))
}
main "$@"
exit 0

17
2022/day06/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/day06/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/day06/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 @@
mjqjpqmgbljsphdztnvjfqwrcgsmlb

View File

@@ -0,0 +1 @@
bvwbjplbgvbhsrlpgdmjqwftvncz

View File

@@ -0,0 +1 @@
nppdvjthqldpwncqszvftbrmjlhg

View File

@@ -0,0 +1 @@
nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg

View File

@@ -0,0 +1 @@
zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw

View File

@@ -0,0 +1 @@
cbhbmmqnmmqvqfqgqcqmmtvvvdsvscvssmfmhfmhhgdgcclhlnnvmnvmnnwngnqggqlqhhbqbfbvffcpfcfpcpmcppsgssvcvmmdwmwsmwswnwvnvvtgvgfgqqnlltgllpplhpllrnrwrtrzrlrzllpnlpnplnlwnnzfztzcchczctcbbpwpbbfhhqllgrllnnghnnlnznzzlqqmggqbgbjjlnlnjllwlnwnjnbjnnhhcddgmdmqmllfjllddmgmpggtvvqqwmmhcmmjpjdpdqqnhhqbhhscstsvttbwtwdtwwjffvccrwrvvnqqtwwhgwhwthwthhvshsfsjstshthqqdfdhdqhqrqggfffvhffhbbwtbtvtwvvwgvvjjjvtjvvlmlmtmztmthmhttjwwmqqjffhvhqvvrddbsbfbgffmcfffqqfzzgmggzvggbjjmccftcftfnttqqjzjdzdrrgvgsgvvlqvlqqlplnnjccjqcjcgjgfjgjlgjjzhhjbbbfdbfddgccncppsbbjjsttcqtqgqpqllqggtsthhtvvtrttbthtnhhddvnnbggmtggcsgcscmmvmllttjbjggbzbttrfttgsstwtftdthdththbttcggdldtdlttbvvpgpjpwpwvwcwjwsjsttznztzftzzjpzzrtzrztrrtsrrdtrdtdbdhhdgdwwnjnnvjvsjjrwjjvrrzvrvllrgghgbbgbsssslqlrllbjbttzfztzpzzvtvccszsddtqttjllqgqgpqphptpwttwtmtltljjfnnzwzmzlzssghssqhhphbhfftwwqmwmzzqtzqzqrrndrrmrqrzrszzrcrbccglgcgwgrgdggtvtpptgtfgflglgrrnvrvhrrhlrhhfchfhdhzzwggvbbgfgrrpdrdccfllqflfmlfmlmbbhnbbsblbzbgbqqjppcddcvvsddjfjjlnnwbbflfzzmlmddjssjffcqffwdfdqqphpnhppbttjfjzzdvdjvvddnfffmjfmfmpfmmmdlmlrrhqqcpcmclmmbmppzczjjmlltqlqzzqgqcggdmdzznnnnsjjvbjjwbwhbhfhvvtmmsfmmcgmcmwcwhwnhhpccmbmdbmbgbjbggqqccfllfqqmqwwzbblffthhdnncqnccqppldlpldpllzmmsqqdffnggqlqtllwlglnlnhlhflfssvzzrllbtbnbgnnfvfllwslszswsnnpwwppvspsmmnfnpffrmrhmmctttrjrbjrjpjtpjpssdwdtwtmmtgtsgttlwttfrfvvpjpcjccmtthhldhllzslshhnrnvvfddnllltclcrrhnnjwwwpfpddmtmsmfflslrlmlmwmllgfgmfgmmjttpcpspslsjspsqstqsqqpsprphrrpqqfzqqwcwcddsjjpvvfnfvnnnrncnwcwczzcwzwnwmwffbdfbdfdjjhrhvhhvwvsvhshnhwwzlwlnnphhtjjmljjqzjjsjgsjshhwjjmttvgvsgstggrcrmmrqrhrqrzrmzmggqvqtqgtqqqqltqqwggmmzggjccgmgwgqqmnqnrnprptrrvfrvffnmnfmmnnnwzzldlvlgvlvqqpnphpgglhlshlhzzpcptpssblqvdbpbbcrngctqgptccwpdcpbcjwdmcrzmhwffgzqmmqwpqvplwzmjlzmvmzmbtqjnhzrpppnpntvmjbzmvhjvbgflmmjnwssvqvbnbddfcwqdtvpvddctmpptcjmvwszhbsttcbjlfjvwlljhlqlvvsnzphdjhfswltdhzprltzcszrgcmnmfznmbccstjvjngwpbsfqssfwvpdhhmlmzttzlszsgpvvbcfvzrlsttlqpnqhwtbqfjnbztnwfnhlhfltgdtsrrwrfhlssvsgzpffnnrhgcvclqnjgfhhzswllvcjffpngcmtjphwnbdfrrgjfrfqbnvbwgccsjvvmjgcvqvtggnvgvgnnchbblqnvvdgjtvdmfrzvhvhzcbqzdslphjjqtcwjqptstvvpqgdbgbcmmchjpvjhvbwtlmlnqpldfcbmwvrmpqcsfdhmmwnbvmpglcfbnsgjmljcwpzpwffcqfrbdrztzhqzhzpcrjfdmrctttdrzlmzcqwjftngwjmgqscftnpbjwqrcvqwbwbdhbhvrdcvgrvctjgwjtmdgzwgvdbmsrjpsbhwcqlqzjnzmgpctlwqhfnbmgsprjcqtfjjvzljqpfqgnvrgnjjlmpqgnzpmpsvzjmtvnfgslldjtjdwlzrvqrbvcpspzpcdnpdjmhcdhsbmthmgjqchqwwsnfjnwgpctlwcdpqpmzqcrptscngqnmhzwjdcqwvdmlzntsfbstbtmmnlsspjbjjdspnslgcnlbfnbhjlzjhrrmdbbwtswqpbpwtzhcnldbsfrvndzvcgzjprcrclhfwbvzgthcglfzqrshgtvbflvnznhmlzdtfnrsltnnppqgrtndbsfqmftdnzmqfwdpcrmssldmrrnzchnqpflgbqzqjjrzlfnptqdwzdhmctfbztmfcmbqcwjmgnwgqzqjctphrrthgvpvppztvpzgzhdszfhlzlcnwmfrlsnvftfrlfvbnlwzctphhpfvszntqcvnfmvmwwhsjlnpfhcpjvrncgmsbprwwllvnsbjfhtbtmcvvpzcvqrrqdvgzvllvcvnvvbftngqcqcvvbsqfshmnhwptcsbsnjzltqzmflftrhblqszrzsbfcpgzncvwhlqlcbmgjdpfcmlgdfphsfcgqccthmlzjbdwpsbddwwrtwmsvqwbzwhzmghhrspvbptznqsqvhgnhlwqjnhgnzprrtjddwtqfsshjrvlglhdlstghftmllvzmmfglnscnrtgcwwwzjphzhvqlctdwjlqvbsvlgzrdpvjhhcthgjhlwsgfzlschhfprfcrzfrzmnlwvqsnqlllczwfhswchrlggqszwrvpldrffnzrffbhtfbslgcdrqpjcrbqsrgfrhttcptncfndcbsdbjsqjvgbmnmhlnbltdcgbmllpgjmgljvglrwmrvgthhhzrsmzvgwcfgvcsbzpjcqnhrzhznzjcjghhwqvllrmsvlpzlssrdsqwvzvqwsvfsjqvbgrfbmfzlchqsjgncbljtvzsfdnvmfzcbrlnnvvmjbmgjmqzjtdzpljdwqtvwsrlbslwfvlgbtnmlpcwmngncnmdhqctshmjmnhpqcqzhvlbvgptctrvggdgnpnrlnngrfhsqdfthvcnpwjfjnslcqlfrfvhnctmsqgnqmgpwtlzhtdqhqqrcllzjccnszsqvrzhcffvnfnstgdmljdrqrndljdnfbbjvmpqdnqhtdlnzcvnfjlvzmfzrndhtglvngmbrdbpbnhvfmrbcwqzttnjplgrhchjtfjwfbjfbmzlrnllhzccpfhfhnjpfvzlpbqnhwmpssvwtzhdbtnbtllhpfdcqjjnzgbdrfjjbcltnzdrmtmsmvpjtmdnqszgbqncsvhjbgwswhmghpvstrqbglgrtgbchttbznvvdhppzwnttpgcbdjdhlsqhhtlphjjrjncrmfdtjhdwmjgmpngnbptzwgwdztmhtpglnftwpnnmrmcwfhwnhlsbwsrjnlmdlmffbzsnhsvnbldwtrrhdhfsjdrsnzlgtfzcwwqrfhtrmjhmphqndwtbpczvmfgczmdlqjqdlwmvjjzwmqnpvwzmtjwtprlnbvjdhpjgndrwzcfthnwhnhqpwtcjlhrhdplzsncfmszmhjmgljhnlsrrfwplclcvjjqmtpnwbtsbwdnjdlqntvdnfgwbpwspssprbffjdlcvbwcqlttnwnhwdspfsjhppbhspnrvrsfmzvbwwtjfzmnzwgqddbmcjzzqhqlgrglsvgsjdwlnsbtmqgsnfwwqrjsbcgdlmbgqwvgpqllqwbcplfjrgnzsdtdtvqnrbcrqjhdtqqplvszvtlflgbpwnpzczbvhzfjrslcwcswsgfvvsswzzwhtfjfpsrvcfnrs

111
2022/day07/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

156
2022/day07/README.org Normal file
View File

@@ -0,0 +1,156 @@
** --- Day 7: No Space Left On Device ---
You can hear birds chirping and raindrops hitting leaves as the
expedition proceeds. Occasionally, you can even hear much louder sounds
in the distance; how big do the animals get out here, anyway?
The device the Elves gave you has problems with more than just its
communication system. You try to run a system update:
#+begin_example
$ system-update --please --pretty-please-with-sugar-on-top
Error: No space left on device
#+end_example
Perhaps you can delete some files to make space for the update?
You browse around the filesystem to assess the situation and save the
resulting terminal output (your puzzle input). For example:
#+begin_example
$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k
#+end_example
The filesystem consists of a tree of files (plain data) and directories
(which can contain other directories or files). The outermost directory
is called =/=. You can navigate around the filesystem, moving into or
out of directories and listing the contents of the directory you're
currently in.
Within the terminal output, lines that begin with =$= are /commands you
executed/, very much like some modern computers:
- =cd= means /change directory/. This changes which directory is the
current directory, but the specific result depends on the argument:
- =cd x= moves /in/ one level: it looks in the current directory for
the directory named =x= and makes it the current directory.
- =cd ..= moves /out/ one level: it finds the directory that contains
the current directory, then makes that directory the current
directory.
- =cd /= switches the current directory to the outermost directory,
=/=.
- =ls= means /list/. It prints out all of the files and directories
immediately contained by the current directory:
- =123 abc= means that the current directory contains a file named
=abc= with size =123=.
- =dir xyz= means that the current directory contains a directory
named =xyz=.
Given the commands and output in the example above, you can determine
that the filesystem looks visually like this:
#+begin_example
- / (dir)
- a (dir)
- e (dir)
- i (file, size=584)
- f (file, size=29116)
- g (file, size=2557)
- h.lst (file, size=62596)
- b.txt (file, size=14848514)
- c.dat (file, size=8504156)
- d (dir)
- j (file, size=4060174)
- d.log (file, size=8033020)
- d.ext (file, size=5626152)
- k (file, size=7214296)
#+end_example
Here, there are four directories: =/= (the outermost directory), =a= and
=d= (which are in =/=), and =e= (which is in =a=). These directories
also contain files of various sizes.
Since the disk is full, your first step should probably be to find
directories that are good candidates for deletion. To do this, you need
to determine the /total size/ of each directory. The total size of a
directory is the sum of the sizes of the files it contains, directly or
indirectly. (Directories themselves do not count as having any intrinsic
size.)
The total sizes of the directories above can be found as follows:
- The total size of directory =e= is /584/ because it contains a single
file =i= of size 584 and no other directories.
- The directory =a= has total size /94853/ because it contains files =f=
(size 29116), =g= (size 2557), and =h.lst= (size 62596), plus file =i=
indirectly (=a= contains =e= which contains =i=).
- Directory =d= has total size /24933642/.
- As the outermost directory, =/= contains every file. Its total size is
/48381165/, the sum of the size of every file.
To begin, find all of the directories with a total size of /at most
100000/, then calculate the sum of their total sizes. In the example
above, these directories are =a= and =e=; the sum of their total sizes
is =95437= (94853 + 584). (As in this example, this process can count
files more than once!)
Find all of the directories with a total size of at most 100000. /What
is the sum of the total sizes of those directories?/
Your puzzle answer was =1390824=.
** --- Part Two ---
Now, you're ready to choose a directory to delete.
The total disk space available to the filesystem is =70000000=. To run
the update, you need unused space of at least =30000000=. You need to
find a directory you can delete that will /free up enough space/ to run
the update.
In the example above, the total size of the outermost directory (and
thus the total amount of used space) is =48381165=; this means that the
size of the /unused/ space must currently be =21618835=, which isn't
quite the =30000000= required by the update. Therefore, the update still
requires a directory with total size of at least =8381165= to be deleted
before it can run.
To achieve this, you have the following options:
- Delete directory =e=, which would increase unused space by =584=.
- Delete directory =a=, which would increase unused space by =94853=.
- Delete directory =d=, which would increase unused space by =24933642=.
- Delete directory =/=, which would increase unused space by =48381165=.
Directories =e= and =a= are both too small; deleting them would not free
up enough space. However, directories =d= and =/= are both big enough!
Between these, choose the /smallest/: =d=, increasing unused space by
=24933642=.
Find the smallest directory that, if deleted, would free up enough space
on the filesystem to run the update. /What is the total size of that
directory?/
Your puzzle answer was =7490863=.
Both parts of this puzzle are complete! They provide two gold stars: **

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

@@ -0,0 +1,194 @@
/* aoc-c.c: Advent of Code 2022, day 7
*
* 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 <ctype.h>
#include "pool.h"
#include "debug.h"
#include "br.h"
#include "aoc.h"
#include "hashtable.h"
#include "pjwhash-inline.h"
/* we will totally ignore the tree structure here and only keep a hashtable
* to keep directories sizes.
*/
#define HBITS 9 /* 9 bits: size is 512 */
#define DIRNAME_SIZE 128
DEFINE_HASHTABLE(hasht_dir, HBITS);
typedef struct dir {
char name[DIRNAME_SIZE];
uint namelen;
uint hash;
int size;
struct hlist_node hlist;
} dir_t;
static pool_t *pool_dirs;
/**
* find_dir - find entry in an hashtable bucket
*/
static dir_t *find_dir(struct hlist_head *head, uint hash, char *dir, uint len)
{
dir_t *cur;
hlist_for_each_entry(cur, head, hlist)
if (cur->hash == hash && cur->namelen == len && !memcmp(cur->name, dir, len))
return cur;
return NULL;
}
static dir_t *find_dirname(char *name, uint len)
{
uint hash = pjwhash(name, len);
uint bucket = hash_32(hash, HBITS);
return find_dir(&hasht_dir[bucket], hash, name, len);
}
/**
* parent_dir - get new len of parent directory
*/
static int parent_dir(char *dir, uint len)
{
for (--len; len && *(dir + len) != '/'; --len)
;
return len? len: 1;
}
static void adjust_dirsize(dir_t *dir, uint size)
{
dir_t *cur = dir;
uint len = cur->namelen;
while (len > 1) {
cur = find_dirname(dir->name, len);
if (!cur) {
log(1, "FATAL hash issue");
exit(1);
}
cur->size +=size;
len = parent_dir(dir->name, len);
};
cur = find_dirname("/", 1); /* do not forget "/" */
cur->size += size;
}
/**
* add_dir - add an entry in hashtable
*/
static struct dir *add_dir(char *dir, uint len)
{
uint hash = pjwhash(dir, len);
uint bucket = hash_32(hash, HBITS);
dir_t *new = pool_get(pool_dirs);
memcpy(new->name, dir, len);
new->namelen = len;
new->hash = hash;
new->size = 0;
hlist_add_head(&new->hlist, &hasht_dir[bucket]);
return new;
}
/**
* add_dir_maybe - add an entry in hashtable if it does not exist
*/
static struct dir *add_dir_maybe(char *dir, int len)
{
dir_t *new = find_dirname(dir, len);
return new? new: add_dir(dir, len);
}
static struct dir *cd(struct dir *dir, char *to, uint tolen)
{
char *newname = dir->name;
int newlen, add_slash = 0;
if (!dir)
return add_dir_maybe(to, tolen);
if (dir->namelen + tolen + 1 > DIRNAME_SIZE) /* conservative (think / or ..) */
return NULL;
if (*to == '.') { /* .. = parent dir */
newlen = parent_dir(dir->name, dir->namelen);
} else if (*to == '/') { /* root */
newname = to;
newlen = tolen;
} else { /* subdir */
newlen = dir->namelen + tolen;
if (dir->namelen > 1) { /* add '/' separator */
dir->name[dir->namelen] = '/';
add_slash = 1;
newlen++;
}
memcpy(dir->name + dir->namelen + add_slash, to, tolen);
}
return add_dir_maybe(newname, newlen);
}
#define CDLEN (sizeof("$ cd ") - 1)
static void parse()
{
dir_t *curdir = NULL;
size_t alloc = 0;
char *buf = NULL, *tok;
ssize_t buflen;
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
buf[--buflen] = 0;
tok = buf;
if (*tok == '$' &&*(tok+2) == 'c') /* ignore "ls"" */
curdir = cd(curdir, tok + CDLEN, buflen - CDLEN);
else if (isdigit(*tok)) /* ignore "dir" keyword */
adjust_dirsize(curdir, atoi(tok));
}
free(buf);
return;
}
static int solve(int part)
{
ulong bucket;
dir_t *cur;
int res = 0, needed;
if (part == 1) {
hash_for_each(hasht_dir, bucket, cur, hlist)
if (cur->size <= 100000)
res += cur->size;
} else {
res = find_dirname("/", 1)->size;
needed = res - (70000000-30000000);
hash_for_each(hasht_dir, bucket, cur, hlist)
if (cur->size >= needed && cur->size < res)
res = cur->size;
}
return res;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
pool_dirs = pool_create("dirs", 128, sizeof(dir_t));
parse();
printf("%s: res=%d\n", *av, solve(part));
pool_destroy(pool_dirs);
exit(0);
}

102
2022/day07/aoc.bash Executable file
View File

@@ -0,0 +1,102 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 7
#
# 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 sizes=() # file size
declare -A dirs=() # directories
declare -a lines # shell lines
declare -i curline=0 # current line in shell
declare curdir
do_cd() {
local dir="$1"
case "$dir" in
"..")
curdir=${curdir%/*}
[[ -z $curdir ]] && curdir="/"
;;
"/")
curdir="/"
;;
*)
[[ $curdir != "/" ]] && curdir+="/"
curdir+="$dir"
esac
dirs[$curdir]="$curdir"
}
do_ls() {
local remain
local -i size
((curline++))
while [[ $curline -lt ${#lines[@]} && ${lines[$curline]:0:1} != "\$" ]]; do
if [[ "${lines[$curline]}" != dir* ]]; then
size=${lines[$curline]% *}
remain="$curdir"
while [[ -n $remain ]]; do # recurse up curdir and adjust sizes
((sizes[$remain] += size))
remain=${remain%/*}
done
(( sizes["/"] += size ))
fi
((curline++))
done
((curline--))
}
parse() {
readarray -t lines
curline=0
declare -a line
while ((curline < ${#lines[@]})); do
read -ra line <<< "${lines[$curline]}"
case "${line[1]}" in
"cd")
do_cd "${line[2]}"
;;
"ls")
do_ls
;;
esac
((curline++))
done
}
solve() {
declare -ig res
local part="$1" dir mindir="/"
local -i needed
if ((part == 1)); then
for dir in "${dirs[@]}"; do
((sizes[$dir] <= 100000 )) && ((res+=sizes[$dir]))
done
else
(( res = sizes["/"] ))
(( needed = sizes["/"] - (70000000-30000000) ))
for dir in "${!dirs[@]}"; do
if (( sizes[$dir] >= needed )); then
if (( sizes[$dir] <= res )); then
mindir=$dir
((res = sizes[$mindir]))
fi
fi
done
fi
}
main "$@"
exit 0

17
2022/day07/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/day07/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/day07/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 @@
$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k

950
2022/day07/input/input.txt Normal file
View File

@@ -0,0 +1,950 @@
$ cd /
$ ls
dir cvt
4967 hcqbmwc.gts
5512 hsbhwb.clj
dir hvfvt
dir phwgv
277125 pwgswq.fld
42131 qdzr.btl
dir svw
144372 vmbnlzgb.wbd
dir zft
$ cd cvt
$ ls
dir bbgsthsd
146042 bcqrmp.czf
dir chhdjtlw
dir cpcfcc
dir dch
dir djb
dir djfww
dir drdf
dir fgbqtjlj
dir hjsmmj
243293 hvfvt.qtb
245795 lrpb
dir msptbrl
181756 qlqqmndd.zcb
18658 rtfzt.tjp
dir slpc
$ cd bbgsthsd
$ ls
236957 djfww.fcb
112286 hcqbmwc.gts
106102 qggjrzts
$ cd ..
$ cd chhdjtlw
$ ls
226927 cpcfcc
309815 djfww
117933 hcqbmwc.gts
dir mbdrgfzs
dir pbmcnpzf
131558 pwgswq.fld
298691 qlqqmndd.zcb
$ cd mbdrgfzs
$ ls
164331 hvfvt.dvq
$ cd ..
$ cd pbmcnpzf
$ ls
102120 bjgg.cqd
$ cd ..
$ cd ..
$ cd cpcfcc
$ ls
15756 ddc
dir dqc
dir glm
dir jbszm
200345 pwgswq.fld
145508 qlqqmndd.zcb
dir vcptbw
dir zrtm
$ cd dqc
$ ls
dir cpcfcc
92063 mzp
dir qmhnvmh
dir snqqcjlw
8423 zdjwr.blc
$ cd cpcfcc
$ ls
dir hvfvt
$ cd hvfvt
$ ls
289372 pwgswq.fld
307397 qlqqmndd.zcb
$ cd ..
$ cd ..
$ cd qmhnvmh
$ ls
274778 jczjwdl.smd
194322 ngrrfm
$ cd ..
$ cd snqqcjlw
$ ls
182851 nprvrgd.tbb
$ cd ..
$ cd ..
$ cd glm
$ ls
188702 hpq.hgm
$ cd ..
$ cd jbszm
$ ls
187645 pwgswq.fld
$ cd ..
$ cd vcptbw
$ ls
dir mgqd
$ cd mgqd
$ ls
157695 rhldvntj.jzm
268696 rjnngctw
$ cd ..
$ cd ..
$ cd zrtm
$ ls
218820 bcqrmp.czf
172319 czpsl.dnf
180114 hcqbmwc.gts
165216 hvfvt.nnw
dir zft
$ cd zft
$ ls
161245 dtqjg.czv
249888 hpq.hgm
192037 zft
$ cd ..
$ cd ..
$ cd ..
$ cd dch
$ ls
dir djfww
dir fzqgwwnf
dir hqvmq
dir mmcrzqc
42136 qlqqmndd.zcb
dir vdtlh
dir wfltm
271200 zrtm
$ cd djfww
$ ls
37427 dct
204401 hcqbmwc.gts
283140 jmq
dir lbrhbc
154148 pncb.bmp
53366 vzt.cnn
$ cd lbrhbc
$ ls
dir djfww
153648 djfww.pps
308911 mvtjzp.btg
219150 ncmc
253604 wqft.ggb
293759 zft
$ cd djfww
$ ls
24794 hcqbmwc.gts
$ cd ..
$ cd ..
$ cd ..
$ cd fzqgwwnf
$ ls
233720 scdd.pwr
$ cd ..
$ cd hqvmq
$ ls
dir cdld
dir cpcfcc
dir djfww
85564 hpq.hgm
dir qnc
81509 wtnl.crs
$ cd cdld
$ ls
293421 llpltsgn.tqb
$ cd ..
$ cd cpcfcc
$ ls
230813 cglljgv
178203 qlqqmndd.zcb
186410 zrtm.tbt
$ cd ..
$ cd djfww
$ ls
201830 zrtm
$ cd ..
$ cd qnc
$ ls
305356 bdf.jrh
dir zrtm
$ cd zrtm
$ ls
dir bdhdrr
$ cd bdhdrr
$ ls
dir nffdrnb
$ cd nffdrnb
$ ls
301601 nbrjz
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd mmcrzqc
$ ls
dir cpcfcc
264271 hpq.hgm
208744 tzsjrf.zdc
274096 zft
$ cd cpcfcc
$ ls
226054 cpcfcc
$ cd ..
$ cd ..
$ cd vdtlh
$ ls
84229 bzlg.crn
58668 cpcfcc.zqw
141409 hpq.hgm
dir mdgst
37090 pstsh.qwv
40357 qlqqmndd.zcb
dir smr
dir sqbgcsgh
dir trp
$ cd mdgst
$ ls
151033 fsmvbpsl.nqr
$ cd ..
$ cd smr
$ ls
140764 cpcfcc.dpg
$ cd ..
$ cd sqbgcsgh
$ ls
dir djfww
263783 dvm
105219 hpq.hgm
29647 hwcgv.gvg
162537 lwjhgh.wmt
235511 nlw
dir zwddrdfz
$ cd djfww
$ ls
260084 vcgpvpd
$ cd ..
$ cd zwddrdfz
$ ls
225632 bhrzzw
269756 cqq.vrz
$ cd ..
$ cd ..
$ cd trp
$ ls
233192 vqwngcs
$ cd ..
$ cd ..
$ cd wfltm
$ ls
140990 djfww
$ cd ..
$ cd ..
$ cd djb
$ ls
213191 cjwrs.prd
dir dhvpqt
dir gtgftm
dir hvfvt
208325 jwhp
301446 qlqqmndd.zcb
dir qnlbgvf
dir tps
dir zft
dir zrtm
dir zwnlm
$ cd dhvpqt
$ ls
dir sbcj
$ cd sbcj
$ ls
20611 ggt
$ cd ..
$ cd ..
$ cd gtgftm
$ ls
179526 qcqbtmvq
$ cd ..
$ cd hvfvt
$ ls
dir djstcnrt
dir hggpvn
dir hvfvt
63889 hvfvt.tjm
265836 qlqqmndd.zcb
105663 zft
223582 zft.llg
26037 zzwwg.lqh
$ cd djstcnrt
$ ls
201498 hcqbmwc.gts
139156 hpq.hgm
277342 pshgz.rtp
dir rjb
257294 rqrb.lhh
dir tqnbfnt
313308 zft.dvc
$ cd rjb
$ ls
268438 hpq.hgm
dir hvfvt
dir hvwpb
161024 mzbcgqc.nvw
137875 pwgswq.fld
260008 pzzcww
283261 wnvlrg.tmn
$ cd hvfvt
$ ls
dir dvwqqt
163397 hcqbmwc.gts
265154 pwgswq.fld
dir trsh
dir vnf
$ cd dvwqqt
$ ls
315187 hcqbmwc.gts
$ cd ..
$ cd trsh
$ ls
dir ssrdpg
$ cd ssrdpg
$ ls
dir vjdc
$ cd vjdc
$ ls
dir srvdrhdq
$ cd srvdrhdq
$ ls
74145 djfww
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd vnf
$ ls
dir djfww
$ cd djfww
$ ls
184018 pwgswq.fld
$ cd ..
$ cd ..
$ cd ..
$ cd hvwpb
$ ls
dir jwpjrcvs
$ cd jwpjrcvs
$ ls
dir cpcfcc
$ cd cpcfcc
$ ls
52191 sdlv
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd tqnbfnt
$ ls
dir djfww
206341 fmpb.lnp
dir fpsjg
4589 hcqbmwc.gts
dir hvfvt
8796 hvfvt.hdz
238364 tgcdpjc.fjm
dir zrtm
40577 zrtm.fsr
$ cd djfww
$ ls
217182 djfww.rbf
$ cd ..
$ cd fpsjg
$ ls
52456 djfww
$ cd ..
$ cd hvfvt
$ ls
dir rqhzvb
275026 szwgzm.qjd
dir zbmtstj
$ cd rqhzvb
$ ls
8395 gcmzsd.jzf
$ cd ..
$ cd zbmtstj
$ ls
39691 qlqqmndd.zcb
dir qqcdss
180676 rwl.zwr
$ cd qqcdss
$ ls
106297 zrtm.nsl
$ cd ..
$ cd ..
$ cd ..
$ cd zrtm
$ ls
153478 ldhvt
$ cd ..
$ cd ..
$ cd ..
$ cd hggpvn
$ ls
19109 cpcfcc.fbh
249168 fnqjc
207420 qgzsh.pfs
135472 qlqqmndd.zcb
$ cd ..
$ cd hvfvt
$ ls
dir djfww
213659 hcqbmwc.gts
dir jzdwq
204021 nvbgf
185328 qlqqmndd.zcb
dir zrtm
$ cd djfww
$ ls
180713 rwmm.gjt
$ cd ..
$ cd jzdwq
$ ls
57424 djfww.qtm
104960 slq.bfp
174906 svc
$ cd ..
$ cd zrtm
$ ls
dir mrtvhht
$ cd mrtvhht
$ ls
188512 djfww.fvm
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd qnlbgvf
$ ls
dir fjrhtssv
46767 jhbnml.lpq
$ cd fjrhtssv
$ ls
198664 fgcc
245142 tsc.rsd
$ cd ..
$ cd ..
$ cd tps
$ ls
dir fmlwghjv
146731 gwch.ttr
dir jjzmdd
dir rtltrng
191609 wff.mqt
$ cd fmlwghjv
$ ls
189227 zrtm.vgg
$ cd ..
$ cd jjzmdd
$ ls
dir hvfvt
178057 mpdfrrm
49493 pwgswq.fld
220129 sqgfb.flm
231012 zrmsnmr
$ cd hvfvt
$ ls
dir lbndbhc
12602 mnclbss
746 ppw
$ cd lbndbhc
$ ls
49601 cdqvs.gwc
158670 wvjpchjg
$ cd ..
$ cd ..
$ cd ..
$ cd rtltrng
$ ls
dir cpgh
115613 hvfvt
59441 zfs
$ cd cpgh
$ ls
dir djfww
$ cd djfww
$ ls
dir tgt
$ cd tgt
$ ls
dir vqwvqss
$ cd vqwvqss
$ ls
dir bsdrhz
$ cd bsdrhz
$ ls
dir pld
$ cd pld
$ ls
8543 mfs.gsb
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd zft
$ ls
dir fhjgg
$ cd fhjgg
$ ls
114494 pwgswq.fld
$ cd ..
$ cd ..
$ cd zrtm
$ ls
201142 tlhr.rtd
298232 wlcztszv
$ cd ..
$ cd zwnlm
$ ls
240023 hcqbmwc.gts
159126 hpq.hgm
22101 hvfvt.bfw
dir ltzl
dir mtfr
dir sbw
dir sqscdjlj
dir ssf
$ cd ltzl
$ ls
260692 hpq.hgm
204540 hvfvt
$ cd ..
$ cd mtfr
$ ls
15391 pwgswq.fld
$ cd ..
$ cd sbw
$ ls
293226 hcqbmwc.gts
267478 htllcq
176349 nlbhcf.vpn
286577 zft.gds
$ cd ..
$ cd sqscdjlj
$ ls
128776 gnh
dir qbdpvcbt
284505 qlsn.vdq
$ cd qbdpvcbt
$ ls
280709 crv.hgm
$ cd ..
$ cd ..
$ cd ssf
$ ls
13328 djfww.pjn
19971 hvfvt
dir zft
$ cd zft
$ ls
97761 dnmnz
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd djfww
$ ls
109590 bwfnnf.wpd
297297 cmht.ljg
280726 hvfvt
$ cd ..
$ cd drdf
$ ls
56764 pwgswq.fld
300547 wqqm
210698 zrtm.jvq
$ cd ..
$ cd fgbqtjlj
$ ls
22217 vrmgsz.ctg
$ cd ..
$ cd hjsmmj
$ ls
232911 bcqrmp.czf
164656 hcqbmwc.gts
dir jql
dir ntd
dir prgm
dir psfvhh
dir zft
$ cd jql
$ ls
212767 zhnhn.lzm
dir zrtm
$ cd zrtm
$ ls
35950 bcqrmp.czf
$ cd ..
$ cd ..
$ cd ntd
$ ls
dir vml
$ cd vml
$ ls
60833 bcqrmp.czf
$ cd ..
$ cd ..
$ cd prgm
$ ls
316166 pwgswq.fld
$ cd ..
$ cd psfvhh
$ ls
152195 pwgswq.fld
92448 qlqqmndd.zcb
$ cd ..
$ cd zft
$ ls
95808 hpq.hgm
$ cd ..
$ cd ..
$ cd msptbrl
$ ls
256069 hpq.hgm
$ cd ..
$ cd slpc
$ ls
dir djfww
285380 djfww.gcm
169898 hcqbmwc.gts
40914 mnpnhpz
188062 pwgswq.fld
dir zrtm
$ cd djfww
$ ls
94935 pwgswq.fld
70655 qlqqmndd.zcb
48528 zft.qvh
$ cd ..
$ cd zrtm
$ ls
160137 hcqbmwc.gts
$ cd ..
$ cd ..
$ cd ..
$ cd hvfvt
$ ls
dir cslthslv
129407 prwq
dir vrzfbtt
$ cd cslthslv
$ ls
dir cpcfcc
158361 hcqbmwc.gts
$ cd cpcfcc
$ ls
dir zpgnczq
$ cd zpgnczq
$ ls
158414 zft
$ cd ..
$ cd ..
$ cd ..
$ cd vrzfbtt
$ ls
185263 nqvvl
$ cd ..
$ cd ..
$ cd phwgv
$ ls
253690 bzpcj.fcj
dir wtbr
168025 zdsh.tnq
157840 zsdfqb.zbd
$ cd wtbr
$ ls
dir lvgdb
$ cd lvgdb
$ ls
177751 cpcfcc.dzr
$ cd ..
$ cd ..
$ cd ..
$ cd svw
$ ls
dir cpcfcc
189430 hpq.hgm
dir ntzbj
13384 qlqqmndd.zcb
10333 wdvqhwgl.trq
161318 zwzp.jsn
$ cd cpcfcc
$ ls
298999 hcqbmwc.gts
290883 hpq.hgm
dir qlnntp
dir vpshs
5547 wlrmg.bpc
dir zft
$ cd qlnntp
$ ls
168562 nqds.tqn
$ cd ..
$ cd vpshs
$ ls
246400 pwgswq.fld
$ cd ..
$ cd zft
$ ls
235634 hvfvt.hst
$ cd ..
$ cd ..
$ cd ntzbj
$ ls
98777 qlqqmndd.zcb
$ cd ..
$ cd ..
$ cd zft
$ ls
dir dhnzm
299292 hvfvt.pvb
dir ltfb
dir mrvsjgsq
dir ntr
dir swmvhgd
dir zrtm
$ cd dhnzm
$ ls
267041 bbsj
$ cd ..
$ cd ltfb
$ ls
242136 bcqrmp.czf
314862 dgdz
203160 hcqbmwc.gts
80422 hgvz
dir qftjfqfv
180815 sstl.wzg
dir wmhm
dir zft
dir zszp
$ cd qftjfqfv
$ ls
dir bmmw
$ cd bmmw
$ ls
dir hvfvt
318039 hvfvt.whc
17057 pwgswq.fld
$ cd hvfvt
$ ls
170348 brplf.wgv
156783 hcqbmwc.gts
$ cd ..
$ cd ..
$ cd ..
$ cd wmhm
$ ls
178474 bcqrmp.czf
dir cmsgv
dir dcfvrtj
225393 htjflrs.tlm
dir hvfvt
dir nlrs
273173 nsmdd.glc
151259 pwgswq.fld
dir ztqvwjr
$ cd cmsgv
$ ls
dir flgjbjg
$ cd flgjbjg
$ ls
13971 cpcfcc
20601 qlqqmndd.zcb
$ cd ..
$ cd ..
$ cd dcfvrtj
$ ls
141992 djfww.djn
118149 hpq.hgm
dir qrmqslq
$ cd qrmqslq
$ ls
105940 zrtm.vql
$ cd ..
$ cd ..
$ cd hvfvt
$ ls
181962 hpq.hgm
$ cd ..
$ cd nlrs
$ ls
82705 vnfwjf.hhl
$ cd ..
$ cd ztqvwjr
$ ls
98257 pwgswq.fld
83864 scv.pbp
$ cd ..
$ cd ..
$ cd zft
$ ls
183072 rsbfsl.zsj
$ cd ..
$ cd zszp
$ ls
dir hvfvt
$ cd hvfvt
$ ls
dir djfww
dir dqdtgjtg
dir hvfvt
$ cd djfww
$ ls
117037 rnmbsq.zph
259243 zrtm.znf
$ cd ..
$ cd dqdtgjtg
$ ls
dir lrbsvng
59301 zft
$ cd lrbsvng
$ ls
46301 bcqrmp.czf
$ cd ..
$ cd ..
$ cd hvfvt
$ ls
223277 qlqqmndd.zcb
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd mrvsjgsq
$ ls
160189 cpcfcc
dir lzqf
232626 pwgswq.fld
dir rpmfcg
$ cd lzqf
$ ls
135552 bcqrmp.czf
48083 qlqqmndd.zcb
dir rbg
229086 rdswb.cjz
204486 spbwfrwf.cmj
$ cd rbg
$ ls
dir sjdwsbqq
$ cd sjdwsbqq
$ ls
270621 rhv.shw
$ cd ..
$ cd ..
$ cd ..
$ cd rpmfcg
$ ls
227216 bld.jtn
dir zft
$ cd zft
$ ls
43056 vzc
$ cd ..
$ cd ..
$ cd ..
$ cd ntr
$ ls
dir cmtnqb
dir djfww
195371 wffvmql.lrv
$ cd cmtnqb
$ ls
135380 pbng.vhq
$ cd ..
$ cd djfww
$ ls
dir fmvrrrq
dir mbhrbss
dir zrtm
$ cd fmvrrrq
$ ls
dir cpcfcc
79110 djfww
300581 ftcdj.wcc
$ cd cpcfcc
$ ls
234211 zsgsm
$ cd ..
$ cd ..
$ cd mbhrbss
$ ls
149184 djfww.gwh
185815 rhgw.rmj
$ cd ..
$ cd zrtm
$ ls
dir zft
$ cd zft
$ ls
310043 bnwvt.fbg
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd swmvhgd
$ ls
77547 djfww.jwr
318547 drggg
300962 pwgswq.fld
$ cd ..
$ cd zrtm
$ ls
229319 bflnffjj
dir djfww
142526 hvfvt
232722 jprrf
94024 ndmf.hdr
dir vhdhn
$ cd djfww
$ ls
30770 bcqrmp.czf
$ cd ..
$ cd vhdhn
$ ls
dir djfww
48261 djfww.frg
dir gqc
316163 qlqqmndd.zcb
$ cd djfww
$ ls
104095 cvjlthn.cfl
223454 hgqwzh
24715 pwgswq.fld
283499 qlqqmndd.zcb
dir zft
224574 zlnwn
$ cd zft
$ ls
100941 pwgswq.fld
$ cd ..
$ cd ..
$ cd gqc
$ ls
156273 wpgwrdl

111
2022/day08/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

122
2022/day08/README.org Normal file
View File

@@ -0,0 +1,122 @@
** --- Day 8: Treetop Tree House ---
The expedition comes across a peculiar patch of tall trees all planted
carefully in a grid. The Elves explain that a previous expedition
planted these trees as a reforestation effort. Now, they're curious if
this would be a good location for a
[[https://en.wikipedia.org/wiki/Tree_house][tree house]].
First, determine whether there is enough tree cover here to keep a tree
house /hidden/. To do this, you need to count the number of trees that
are /visible from outside the grid/ when looking directly along a row or
column.
The Elves have already launched a
[[https://en.wikipedia.org/wiki/Quadcopter][quadcopter]] to generate a
map with the height of each tree (your puzzle input). For example:
#+begin_example
30373
25512
65332
33549
35390
#+end_example
Each tree is represented as a single digit whose value is its height,
where =0= is the shortest and =9= is the tallest.
A tree is /visible/ if all of the other trees between it and an edge of
the grid are /shorter/ than it. Only consider trees in the same row or
column; that is, only look up, down, left, or right from any given tree.
All of the trees around the edge of the grid are /visible/ - since they
are already on the edge, there are no trees to block the view. In this
example, that only leaves the /interior nine trees/ to consider:
- The top-left =5= is /visible/ from the left and top. (It isn't visible
from the right or bottom since other trees of height =5= are in the
way.)
- The top-middle =5= is /visible/ from the top and right.
- The top-right =1= is not visible from any direction; for it to be
visible, there would need to only be trees of height /0/ between it
and an edge.
- The left-middle =5= is /visible/, but only from the right.
- The center =3= is not visible from any direction; for it to be
visible, there would need to be only trees of at most height =2=
between it and an edge.
- The right-middle =3= is /visible/ from the right.
- In the bottom row, the middle =5= is /visible/, but the =3= and =4=
are not.
With 16 trees visible on the edge and another 5 visible in the interior,
a total of =21= trees are visible in this arrangement.
Consider your map; /how many trees are visible from outside the grid?/
Your puzzle answer was =1698=.
** --- Part Two ---
Content with the amount of tree cover available, the Elves just need to
know the best spot to build their tree house: they would like to be able
to see a lot of /trees/.
To measure the viewing distance from a given tree, look up, down, left,
and right from that tree; stop if you reach an edge or at the first tree
that is the same height or taller than the tree under consideration. (If
a tree is right on the edge, at least one of its viewing distances will
be zero.)
The Elves don't care about distant trees taller than those found by the
rules above; the proposed tree house has large
[[https://en.wikipedia.org/wiki/Eaves][eaves]] to keep it dry, so they
wouldn't be able to see higher than the tree house anyway.
In the example above, consider the middle =5= in the second row:
#+begin_example
30373
25512
65332
33549
35390
#+end_example
- Looking up, its view is not blocked; it can see =1= tree (of height
=3=).
- Looking left, its view is blocked immediately; it can see only =1=
tree (of height =5=, right next to it).
- Looking right, its view is not blocked; it can see =2= trees.
- Looking down, its view is blocked eventually; it can see =2= trees
(one of height =3=, then the tree of height =5= that blocks its view).
A tree's /scenic score/ is found by /multiplying together/ its viewing
distance in each of the four directions. For this tree, this is =4=
(found by multiplying =1 * 1 * 2 * 2=).
However, you can do even better: consider the tree of height =5= in the
middle of the fourth row:
#+begin_example
30373
25512
65332
33549
35390
#+end_example
- Looking up, its view is blocked at =2= trees (by another tree with a
height of =5=).
- Looking left, its view is not blocked; it can see =2= trees.
- Looking down, its view is also not blocked; it can see =1= tree.
- Looking right, its view is blocked at =2= trees (by a massive tree of
height =9=).
This tree's scenic score is =8= (=2 * 2 * 1 * 2=); this is the ideal
spot for the tree house.
Consider each tree on your map. /What is the highest scenic score
possible for any tree?/
Your puzzle answer was =672280=.
Both parts of this puzzle are complete! They provide two gold stars: **

159
2022/day08/aoc-c.c Normal file
View File

@@ -0,0 +1,159 @@
/* aoc-c.c: Advent of Code 2022, day 8
*
* 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 "bits.h"
#include "aoc.h"
typedef struct tree {
u16 size;
char *h; /* heigts */
char *v; /* visible (part 1) */
} tree_t;
#define HEIGHT(t, x, y) (((t)->h[((t)->size * (y)) + (x)]))
#define VISIBLE(t, x, y) (((t)->v[((t)->size * (y)) + (x)]))
static tree_t *parse(tree_t *trees)
{
size_t alloc = 0;
char *buf = NULL;
ssize_t buflen;
buflen = getline(&buf, &alloc, stdin);
buf[--buflen] = 0;
trees->size = buflen;
trees->h = malloc((buflen * buflen) * sizeof(char) + 1);
memcpy(trees->h, buf, buflen); /* store first line */
free(buf);
for (buf = trees->h + buflen; ; buf += buflen) {
if (scanf("%s", buf) <= 0)
break;
}
trees->v = calloc(buflen * buflen, sizeof (char));
return trees;
}
static int visible(tree_t *t, int *max, int x, int y)
{
int h = HEIGHT(t, x, y);
if (h > *max) {
VISIBLE(t, x, y) = 1;
if ((*max = h) == '9') {
return 1;
}
}
return 0;
}
static int check_tree(tree_t *t, int x, int y)
{
int i, h = HEIGHT(t, x, y), res = 1, size = t->size, tmp;
for (tmp = 0, i = x + 1; i < size ; ++i) { /* east */
tmp++;
if (HEIGHT(t, i, y) >= h)
break;
}
res *= tmp;
for (tmp = 0, i = x - 1; i >= 0; --i) { /* west */
tmp++;
if (HEIGHT(t, i, y) >= h)
break;
}
res *= tmp;
for (tmp = 0, i = y + 1; i < size; ++i) { /* south */
tmp++;
if (HEIGHT(t, x, i) >= h)
break;
}
res *= tmp;
for (tmp = 0, i = y - 1; i >= 0; --i) { /* north */
tmp++;
if (HEIGHT(t, x, i) >= h)
break;
}
res *= tmp;
return res;
}
static int part1(tree_t *t)
{
int x, y, max, res = 0, size = t->size;
for (y = 1; y < size -1; ++y) { /* to east */
if ((max = HEIGHT(t, 0, y)) < '9') {
for (x = 1; x < size -1; ++x) {
if (visible (t, &max, x, y))
break;
}
}
}
for (y = 1; y < size -1; ++y) { /* to west */
if ((max = HEIGHT(t, size - 1, y)) < '9') {
for (x = size - 2; x > 0; --x) {
if (visible (t, &max, x, y)) {
break;
}
}
}
}
for (x = 1; x < size -1; ++x) { /* to south */
if ((max = HEIGHT(t, x, 0)) < '9') {
for (y = 1; y < size -1; ++y) {
if (visible (t, &max, x, y))
break;
}
}
}
for (x = 1; x < size -1; ++x) { /* to north */
if ((max = HEIGHT(t, x, size - 1)) < '9') {
for (y = size - 2; y > 0; --y) {
if (visible (t, &max, x, y))
break;
}
}
}
for (y = 0; y < size; ++y)
for (x = 0; x < size; ++x)
if (VISIBLE(t, x, y))
res++;
return res + size * 4 - 4;
}
static int part2(tree_t *t)
{
int res = 0, tmp, size = t->size;
for (int y = 1; y < size - 1; ++y) {
for (int x = 1; x < size - 1; ++x) {
tmp = check_tree(t, x, y);
if (tmp > res)
res = tmp;
}
}
return res;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
tree_t trees;
parse(&trees);
printf("%s: res=%d\n", *av, part == 1? part1(&trees): part2(&trees));
exit(0);
}

135
2022/day08/aoc.bash Executable file
View File

@@ -0,0 +1,135 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 8
#
# 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 trees=() # trees height
declare -Ai visible=() # visible if set
declare -i size
parse() {
readarray -t trees
size=${#trees[@]}
}
# height - return height of a tree
# $1: reference of return value
# $2, $3: x, y
# x is column, y is row
height() {
local -n _ret="$1"
_ret=${trees[$3]:$2:1}
}
check_visible() {
local -n _max="$1"
local -i _x="$2" _y="$3" _c
height _c "$x" "y"
if (( _c > _max )); then
(( visible[$x-$y]++, _max=_c ))
(( _max == 9 )) && return 1
fi
return 0
}
part1() {
declare -ig res
local -i x y max
for ((y = 1; y < size -1; ++y)); do # to east
height max 0 "$y"
(( max == 9 )) && continue
for ((x = 1; x < size -1; ++x)); do
check_visible max "$x" "$y" || break
done
done
for ((y = 1; y < size -1; ++y)); do # to west
height max $((size - 1)) "$y"
(( max == 9 )) && continue
for ((x = size - 2; x > 0; --x)); do
check_visible max "$x" "$y" || break
done
done
for ((x = 1; x < size -1; ++x)); do # to south
height max "$x" 0
(( max == 9 )) && continue
for ((y = 1; y < size -1; ++y)); do
check_visible max "$x" "$y" || break
done
done
for ((x = 1; x < size -1; ++x)); do # to north
height max "$x" $((size - 1))
(( max == 9 )) && continue
for ((y = size - 2; y > 0; --y)); do
check_visible max "$x" "$y" || break
done
done
(( res = ${#visible[@]} + size * 4 - 4 ))
}
check_tree() {
local -n res=$1
local -i X="$2" Y="$3" c x y h
local -ai vis=()
height h "$X" "$Y"
for ((x = X + 1; x < size ; ++x)); do # east
height c "$x" "Y"
(( vis[0]++ ))
((c >= h)) && break
done
for ((x = X - 1; x >= 0; --x)); do # west
height c "$x" "Y"
(( vis[1]++ ))
((c >= h)) && break
done
for ((y = Y + 1; y < size; ++y)); do # south
height c "$X" "$y"
(( vis[2]++ ))
((c >= h)) && break
done
for ((y = Y - 1; y >= 0; --y)); do # north
height c "$X" "$y"
(( vis[3]++ ))
((c >= h)) && break
done
# shellcheck disable=1102
res=$(( "${vis[@]/%/ *}" 1))
}
part2() {
local -ig res=0
local -i tmp=1 x y
for ((x = 1; x < size - 1; ++x)); do
for ((y = 1; y < size - 1; ++y)); do
check_tree tmp "$x" "$y"
if ((tmp > res)); then
((res = tmp))
fi
done
done
}
solve() {
if ((part == 1)); then
part1
else
part2
fi
}
main "$@"
exit 0

17
2022/day08/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/day08/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/day08/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 @@
30373
25512
65332
33549
35390

View File

@@ -0,0 +1,99 @@
002100030222341303232115221524311502200403234452204125251345024423544443305142410110142101223120110
102030322341143330244233013052025453422005415304655426206452251310214055314024034341233110302320003
003012203404011430120134554314552441635001641050211406204621114102021543144514102510421243314102033
330313423002034140035001210441156554545625042262651356556544202500446121455112434243313013430141203
331203121131230002055113430244610062654034520106363462155201210355601153542301323442223310134324300
232201231021003254355411402310326206625011564114125202263504451451212600155351424154310240411213431
033033333301011523544023206136145505304224325606020360006206455564513553512054354124523232201230441
132201032234334044251334220345360402456541662253556375754662323265201641514121105025300453041111234
314322341322104402235020206565044225363527617767574524475421763504341061551154250344125514014234344
101323043023430543342440532324326413655657527215661116623455613664321005134300223542510253102211310
320404242514122111525043444530625417656773117247512712444315767422412130351505513231104322032421303
221204123205133142044056245654205231734371546616753217321556472223654044043612554152141554333102034
340310155225452152216635634352712541366312326272262143522347111166646736001360102010220214000133002
012404003515002416422500163244271366252711531615333437352461454777311142132000140205630042305222013
332434552302203445503543424523327464362526657251687634745536521746523154717531643250132300541053000
020130312425316362611130462217125425435545265467725256332777233137141524314631100051153314314343032
112115124512002346011342433146124542356845483862756322785545283652723747276776403131622540014001524
332354013101003031053022245431274627654677343638672643442563448782737464337546541546630431125021330
220315320142064161406534365262377268373743527784575246325564676238816733767331345114363612344051535
102041153526000601402325625766534543527882476653366727573448727775677146365732431425225562043130034
350054114310533002426654125166575285757827422257872378766383267543484865317252532765440216543555512
222440404353016144747347457368562668586285847553578732435887584463446862116134751240360645225435344
554234546163262630313431762248876668663352436888374587856263343842526635237314231451062036605442520
525531324662660356256614344438373575732699988366775989976447384338336827686445577222030363631240512
055541261042533424177375756738443482846986979788978997559377679255463858237757327464422026230510130
514123221240250442457744728347386637684953574546455344754548333793233865436751231314653541223102202
355454250661114645144551785724753237378345375493453967559796675839837444334776625552412552302431302
202445234333206767744653874724276586973668878949653473947686567565487325864733735677672241416513452
445415223211061633767433865252483574744685974593334963668983745643354885658423263536531213102544202
201405464251164654177385783224666473975674643767946648464678958969336335638578275154116223152222102
401423140356441654745572266848965593553995667644648964747884544439493545472454437715336645303346422
154440323240741427732867467564957336394985859766644495658985963583496399736552632162756445212536404
441663663062661372122867364584655388977474857585778686889578799644949733463423826715534215154065204
422036122016243651174663588693898583374968974778579585977478599643389537573534354622377452555411315
430412403362272513348763673566578945645997454758694486758844958569786758359475575577532661126532300
503653020441267422765353469867998339764449596776968996449777464644846938866332635583727771665263026
006252631541331635768754753357384754988659585857956567666645975599653466655333342485345762600032403
215205542775713732868842389885585646884858449858579777975997584997463698339932263363162431251615251
342224450731115175762626546538955447796468885776778879697695699945446388444478355347827635732006646
045011110226211633623658548365544498466468766878699597655897586488555435934935526883851537736604133
440352212243431376382869634434568447654566895897796875679759667598898849334873844583742271767024403
566632367121414762272448784755746799985759966559657989697977677955455754549393784586875275341562621
004131167135757426882464486773699786789959957795985595559587775554479945637849747667752242212324244
022411031432724262533554794664597446479869568767598899669969588984864457535986725263473577457413134
036415005331162527346577487593798458668976888776888766856699598847776567686579476836656723623111342
504001302331545267684439554776894957999788577876688969865558955547965687556849786463457244355044511
464266074264126575276833864784546697885788878967966988678696686685576789843676844576623242451411411
660130573642326366362654785549676574587876888769689696798799988678648554635745724364273772474666502
413511521313437652422664948645649566979966676679778669968777776786958464356797545247763267365643645
455033174473274564484285387995879595555686569997977698868769855686564847593489668858847744131410225
560316675532344635443349663994499869866598568889798868967976679655597494679336978524332246567265361
121053163342234352453837754569968465557968697766766888969966667796479457384444468264837376474515455
604062313527642634768255846899648545559665886668966887999959659769978495794795825775373713613231451
041031112622754332842439776736966994677888699898679988967779696758849589365579766676242256227420364
630161363126476778455475799658545955598576568877768698668579988799596866465635488284555252726211044
455563641427127283364758796475975894658677688789777769876667978747955677573575525588444241765111511
256420063532645225542863884958844496596759999769769687678888788875449888945958948378756476127155054
523256165217547362636325547686549767698957967985968987897777685866576744344388256886854362647342110
205224606764556763544234874676659474468968576879668558856675855668779847849738247387744421321145610
022651355615653552468486676459694744747575877656886776677858584988944678787576556747724125467333305
526313424324717126486746644643397589664468865599858886996669788566489473798387676766873216657521426
426530404522411762572567697375959747975669667958685679878659587764977658398697353283563215312244014
023510245741131775436864579684699874979976567776557765866775469587757498544476554753722641656303654
211341433442225414565332887899363678699495567888998675657659688744458493387343842346747477252626250
406543152154335614758277748595836896786654948759999978569588555764838686653647362854723163226456101
333640633617315535456525364849458558744656899855554897897568844446533866457545654847562377442214226
040003053246534354438748723933365934878485997458955574785966996653353969666867276761661111124104550
405602516206264365157378627495546935658594587869579958969686766986836687348285865231616336232000100
304131030254233641578272475868953446545577766644956989679964489688554398956223433417637732661500540
131164662225325441733366324345477954639475997658684766465487974699579665344326248136151472051130445
452312154206174654138684277376889449945746954689646875777596486949365968888456226732332263263420000
003010154551246223274282454345355673349967689986885795449989359633496728553885221437611730454554455
131435126460017635544785754344874379695379366384573934357795398633967475353836864461424146264354142
350154544045013352533173566257757787385448697484997454578735937499665628425542376452563635450224022
302420224365163651765264446875287359533637498445639443969586466433384346337722662774436566624454214
415242456321105173655733744886343826548944666338683876383973497998744488687446541256724244661531431
155303206134314124372553618623857237346567857564464797593393675563536467777317174625640132203003240
335521544652523624641575451785635352333587957647598535633948867838652636686573137515062356442045153
235314500244636615342325346277256685653838226755493858683465683736283367654226655456541546644313125
252520511531061305614364671212856473625642477732845278766573642425286572562373137446456005011330433
241525455120116046543737642325543677623243884242534423327827446383376441727657314343125403632434002
301045223551220356167117621755325772252845222546246588464784874685774676163655131632622146412415515
011150133311336614251435416453632383454327534367288242328746537673543714263674263262001132354544412
314104033000306256531666256433553535833538337463847277453476563227672715617272601302551120422305504
104211442013141664402363645617163435245556228235337864656673626354151416721375243323635625100210424
413422313502535362615054171511431775335574748526574728747453724472157632635263350024552502052340024
131225301023304456424150404525765416565572272321835377167235317312551645334432406536160545434122120
342131052232413325301451041516716541737346252413667115612642227312572433104525003114240240141232002
244421101354005430232434420344323273421374225635551363463245561271743411452116466311034334101231020
232404402304311415164151401553463731147111147752141732625152553615361046133341313265525232544143442
201321033520133414312301326330253041267251614477322566645472656414545035321106361434351501123314104
211232034442524242313453325046331353174352335422752364775746537513333534355120322320404054014303124
224032233240430510135541652065052415154147565656231651653327511443424113100543020223335130010141400
004110101133543440511523265424013341433043655022512172622140322434116104552043413352211021312421433
000304433232402410151205333526613043463556021413402141634154404530112303306244402221312522221004042
200204441020135232033032541516232550445221141520665016336536052063115335040344025054213324400312303
300211022440310123055510053251505226452265556365100101014044645236505213550201425252404100302413231
310312413210032422053242024243343060135340422313312403505631104430120233112324204414021331012401232
132020341330304022053503522313342026211133610000020554213662244142551253124302245242110111033101203

111
2022/day09/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

747
2022/day09/README.org Normal file
View File

@@ -0,0 +1,747 @@
** --- Day 9: Rope Bridge ---
This rope bridge creaks as you walk along it. You aren't sure how old it
is, or whether it can even support your weight.
It seems to support the Elves just fine, though. The bridge spans a
gorge which was carved out by the massive river far below you.
You step carefully; as you do, the ropes stretch and twist. You decide
to distract yourself by modeling rope physics; maybe you can even figure
out where /not/ to step.
Consider a rope with a knot at each end; these knots mark the /head/ and
the /tail/ of the rope. If the head moves far enough away from the tail,
the tail is pulled toward the head.
Due to nebulous reasoning involving
[[https://en.wikipedia.org/wiki/Planck_units#Planck_length][Planck
lengths]], you should be able to model the positions of the knots on a
two-dimensional grid. Then, by following a hypothetical /series of
motions/ (your puzzle input) for the head, you can determine how the
tail will move.
Due to the aforementioned Planck lengths, the rope must be quite short;
in fact, the head (=H=) and tail (=T=) must /always be touching/
(diagonally adjacent and even overlapping both count as touching):
#+begin_example
....
.TH.
....
....
.H..
..T.
....
...
.H. (H covers T)
...
#+end_example
If the head is ever two steps directly up, down, left, or right from the
tail, the tail must also move one step in that direction so it remains
close enough:
#+begin_example
..... ..... .....
.TH.. -> .T.H. -> ..TH.
..... ..... .....
... ... ...
.T. .T. ...
.H. -> ... -> .T.
... .H. .H.
... ... ...
#+end_example
Otherwise, if the head and tail aren't touching and aren't in the same
row or column, the tail always moves one step diagonally to keep up:
#+begin_example
..... ..... .....
..... ..H.. ..H..
..H.. -> ..... -> ..T..
.T... .T... .....
..... ..... .....
..... ..... .....
..... ..... .....
..H.. -> ...H. -> ..TH.
.T... .T... .....
..... ..... .....
#+end_example
You just need to work out where the tail goes as the head follows a
series of motions. Assume the head and the tail both start at the same
position, overlapping.
For example:
#+begin_example
R 4
U 4
L 3
D 1
R 4
D 1
L 5
R 2
#+end_example
This series of motions moves the head /right/ four steps, then /up/ four
steps, then /left/ three steps, then /down/ one step, and so on. After
each step, you'll need to update the position of the tail if the step
means the head is no longer adjacent to the tail. Visually, these
motions occur as follows (=s= marks the starting position as a reference
point):
#+begin_example
== Initial State ==
......
......
......
......
H..... (H covers T, s)
== R 4 ==
......
......
......
......
TH.... (T covers s)
......
......
......
......
sTH...
......
......
......
......
s.TH..
......
......
......
......
s..TH.
== U 4 ==
......
......
......
....H.
s..T..
......
......
....H.
....T.
s.....
......
....H.
....T.
......
s.....
....H.
....T.
......
......
s.....
== L 3 ==
...H..
....T.
......
......
s.....
..HT..
......
......
......
s.....
.HT...
......
......
......
s.....
== D 1 ==
..T...
.H....
......
......
s.....
== R 4 ==
..T...
..H...
......
......
s.....
..T...
...H..
......
......
s.....
......
...TH.
......
......
s.....
......
....TH
......
......
s.....
== D 1 ==
......
....T.
.....H
......
s.....
== L 5 ==
......
....T.
....H.
......
s.....
......
....T.
...H..
......
s.....
......
......
..HT..
......
s.....
......
......
.HT...
......
s.....
......
......
HT....
......
s.....
== R 2 ==
......
......
.H.... (H covers T)
......
s.....
......
......
.TH...
......
s.....
#+end_example
After simulating the rope, you can count up all of the positions the
/tail visited at least once/. In this diagram, =s= again marks the
starting position (which the tail also visited) and =#= marks other
positions the tail visited:
#+begin_example
..##..
...##.
.####.
....#.
s###..
#+end_example
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

17
2022/day09/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/day09/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/day09/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,8 @@
R 4
U 4
L 3
D 1
R 4
D 1
L 5
R 2

View File

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

2000
2022/day09/input/input.txt Normal file

File diff suppressed because it is too large Load Diff

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

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