Compare commits

...

118 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
9d375aecfc 2022 day 2 (bash) 2022-12-07 13:18:58 +01:00
d412824317 2020 day 10 (C): fix for 32 bits architecture (ooops !) 2022-12-06 17:18:22 +01:00
d8e05b0fca 2020/day2: fix for 32 bits arch 2022-12-06 15:45:00 +01:00
a49a2ed073 debug.h: tentatively build on 32 bits arch 2022-12-06 15:17:04 +01:00
2c14abff21 bits.h: move popcount32() up 2022-12-06 14:43:16 +01:00
50919df627 bits.h: tentatively build on 32 bits arch 2022-12-06 14:41:28 +01:00
73c9fa8150 typo 2022-12-06 14:39:06 +01:00
b949e11314 2020: update lib source files (trying to compile on 32 bits arch) 2022-12-06 14:27:10 +01:00
f003511e10 pool.c: please valgrind 2022-12-03 14:50:37 +01:00
36f763830f 2020: Tentative C & Bash frameworks (common functions) 2022-12-03 14:42:37 +01:00
c7553e7849 plist.h: add some reverse macros 2022-12-03 14:40:35 +01:00
Bruno
6012d4d375 2022/day 1 (C) - save from laptop 2022-12-02 10:32:02 +01:00
ce446be296 cleanup code 2022-12-01 10:48:09 +01:00
a8cab0c7c3 2022 day1: fix global Makefile, RESULTS.txt 2022-12-01 10:31:17 +01:00
dbff06e5da 2022 day 1: prepare bash common code + bash solutions 2022-12-01 10:28:40 +01:00
0fb4219c92 init AoC 2022, cleanup useless files 2022-12-01 07:50:35 +01:00
58ba8b4ab8 2020 day 21: init for C version 2022-11-30 20:24:23 +01:00
cca3d6fbe5 2020 day 22: release memory 2022-11-30 13:17:57 +01:00
cfba08b197 typo 2022-11-29 21:00:11 +01:00
ca8de49d5e 2020 day 22/2 (C) - clean code 2022-11-29 20:53:07 +01:00
ea9c144127 2020 day 22 part 2 (C, 1st version) 2022-11-29 19:14:53 +01:00
d4d5af0cb6 2020 day 22 part 1 (C) 2022-10-28 12:08:59 +02:00
5ee230df69 2020 day 22: init for C version 2022-10-27 20:24:37 +02:00
9fe7b64263 typo 2022-10-27 20:08:38 +02:00
8df13f9713 2020/19 (C): cleanup code 2022-10-27 16:14:48 +02:00
74ab0ba990 2020 part 2 (C). 2022-10-27 15:22:44 +02:00
46dee29af6 cleanup README.org 2022-10-26 19:21:39 +02:00
ad7c6f3042 add len in message (for future CYK implementation) 2022-10-26 19:19:41 +02:00
d485983efc 2020/19, add C results for part 1. 2022-10-24 20:37:02 +02:00
23c33894a5 2020 day 19 part 1 (C) - won't work for part 2 !! 2022-10-24 20:15:25 +02:00
9bd03e0650 day 23: typos 2022-10-24 20:14:53 +02:00
6de646f0d1 C: 2020 day 23, part 1 and 2 2022-10-22 18:37:37 +02:00
a525ab6338 change name 2022-10-22 18:36:50 +02:00
2de0c3c9c8 list.h: add list_bulk_move() 2022-10-22 18:35:37 +02:00
226 changed files with 28270 additions and 1636 deletions

View File

@@ -439,11 +439,20 @@ ex1.bash : res=285
time: 0:00.56 real, 0.55 user, 0.00 sys
context-switch: 12+1, page-faults: 0+5967
aoc-c : res=285
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+94
+++++++++++++++++ ex2
ex2.bash : res=412
time: 0:03.37 real, 3.34 user, 0.03 sys
context-switch: 19+1, page-faults: 0+11909
aoc-c : res=412
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+95
=========================================
================= day20 =================
=========================================
@@ -481,11 +490,19 @@ ex1.bash: res=31314
time: 0:00.07 real, 0.06 user, 0.00 sys
context-switch: 2+1, page-faults: 0+168
aoc-c : res=31314
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+89
+++++++++++++++++ ex2
ex2.bash: res=32760
time: 1:21.92 real, 81.89 user, 0.01 sys
context-switch: 462+1, page-faults: 0+5135
aoc-c : res=32760
time: 0:01.11 real, 1.09 user, 0.01 sys
context-switch: 70+1, page-faults: 0+1933
=========================================
================= day23 =================
=========================================
@@ -495,11 +512,19 @@ ex1.bash: res=75893264
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 0+1, page-faults: 0+166
aoc-c : res=75893264
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+83
+++++++++++++++++ ex2
ex2.bash: res=38162588308
time: 6:52.50 real, 412.30 user, 0.14 sys
context-switch: 2219+1, page-faults: 0+30233
aoc-c : res=38162588308
time: 0:01.33 real, 1.32 user, 0.01 sys
context-switch: 3+1, page-faults: 0+3992
=========================================
================= day24 =================
=========================================

View File

@@ -1,36 +0,0 @@
ex1.bash : 33:1701 180:319 sum=2020 mul=542619
time: 0:00.06 real, 0.06 user, 0.00 sys
context-switch: 20+4, page-faults: 0+305
ex1-cob : res= 542619
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+172
ex1-c : 33:1701 180:319 sum=2020 mul=542619
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+73
ex2.bash : 80:1450 94:43 185:527 sum=2020 mul=32858450
time: 0:10.00 real, 10.00 user, 0.00 sys
context-switch: 1005+3, page-faults: 0+302
ex2-sort.bash : 0:43 2:527 81:1450 sum=2020 mul=32858450
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 2+7, page-faults: 0+479
ex2-pure-sort.bash : 0:43 2:527 81:1450 sum=2020 mul=32858450
time: 0:00.50 real, 0.50 user, 0.00 sys
context-switch: 62+4, page-faults: 0+311
ex2-sort-cob : res= 32858450
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 1+1, page-faults: 0+170
ex2-pure-sort-cob : res= 32858450
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 1+1, page-faults: 0+173
ex2-c : 80:1450 94:43 185:527 sum=2020 mul=32858450
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+75

View File

@@ -1,12 +0,0 @@
ex1.bash : lines: 1000 matched:607
time: 0:00.03 real, 0.03 user, 0.00 sys
ex1-c : lines: 1000 matched:607
time: 0:00.00 real, 0.00 user, 0.00 sys
ex2.bash : lines: 1000 matched:321
time: 0:00.03 real, 0.03 user, 0.00 sys
ex2-c : lines: 1000 matched:321
time: 0:00.00 real, 0.00 user, 0.00 sys

View File

@@ -1,12 +0,0 @@
ex1.bash : lines:322 pos=966 found:169
time: 0:00.01 real, 0.01 user, 0.00 sys
ex1-c : lines:322 pos:966 found:169
time: 0:00.00 real, 0.00 user, 0.00 sys
ex2.bash : lines=323 res=6847128288
time: 0:00.04 real, 0.03 user, 0.00 sys
ex2-c : lines=323 res=6847128288
time: 0:00.00 real, 0.00 user, 0.00 sys

View File

@@ -32,7 +32,7 @@ int main(ac, av)
char **av;
{
int line=1, linelen=0, mod=0, i;
unsigned long res=1;
unsigned long long res=1;
char str[80];
scanf("%s", str); /* ignore 1st line */
@@ -51,6 +51,6 @@ int main(ac, av)
}
for (i=0; set[i].dx != -1; ++i)
res*=set[i].count;
printf ("%s : lines=%d res=%lu\n", *av, line, res);
printf ("%s : lines=%d res=%llu\n", *av, line, res);
exit (0);
}

View File

@@ -1,12 +0,0 @@
ex1.bash : valid=182/251
time: 0:00.06 real, 0.06 user, 0.00 sys
ex1-c : valid=182/251
time: 0:00.00 real, 0.00 user, 0.00 sys
ex2.bash : valid=109/251
time: 0:00.16 real, 0.16 user, 0.00 sys
ex2-c : valid=109/251
time: 0:00.00 real, 0.00 user, 0.00 sys

View File

@@ -1,12 +0,0 @@
ex1.bash : lines=743 max=838
time: 0:00.94 real, 0.62 user, 0.41 sys
ex1-c : lines=743 max=838
time: 0:00.00 real, 0.00 user, 0.00 sys
ex2.bash : lines=743 seat=714
time: 0:00.99 real, 0.65 user, 0.43 sys
ex2-c : lines=743 seat=714
time: 0:00.00 real, 0.00 user, 0.00 sys

View File

@@ -1,24 +0,0 @@
ex1.bash : groups=484 count=6585
time: 0:01.42 real, 1.26 user, 0.20 sys
context-switch: 135+1393, page-faults: 0+59578
ex1-bis.bash : groups=484 count=6585
time: 0:01.22 real, 1.09 user, 0.16 sys
context-switch: 145+1311, page-faults: 0+60076
ex1-c : groups=484 count=6585
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+71
ex2.bash : groups=484 count=3276
time: 0:01.35 real, 1.18 user, 0.20 sys
context-switch: 139+1360, page-faults: 0+59397
ex2-bis.bash : groups=484 count=3276
time: 0:01.30 real, 1.11 user, 0.22 sys
context-switch: 112+1356, page-faults: 0+57986
ex2-c : groups=484 count=3276
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+72

View File

@@ -1,4 +0,0 @@
#! /bin/bash
PATH=.:$PATH
IN="$1"
time { ex1.bash < $IN; ex2.bash < $IN; } 2>&1

View File

@@ -1,5 +0,0 @@
#! /bin/bash
PATH=.:$PATH
IN="$1"
echo IN=$IN
time for i in ex1-c ex2-c; do "$i" < "$IN"; done 2>&1

View File

@@ -1,20 +0,0 @@
ex1.bash : target=shinygold nkeys=594 res=287
time: 0:06.99 real, 6.99 user, 0.00 sys
context-switch: 720+1, page-faults: 0+403
ex1-bis.bash : target=shinygold res=287
time: 0:00.12 real, 0.12 user, 0.00 sys
context-switch: 14+1, page-faults: 0+209
ex1-c : target=shinygold nkeys=594 res=287
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+117
ex2.bash : target=shinygold res=48160
time: 0:00.34 real, 0.28 user, 0.06 sys
context-switch: 37+253, page-faults: 0+12039
ex2-c : target=shinygold nkeys=594 res=48160
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+118

View File

@@ -1,16 +0,0 @@
ex1.bash : res=1594
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 0+4, page-faults: 0+303
ex1-c : res=1594
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 1+0, page-faults: 0+79
ex2.bash : res:758
time: 0:02.26 real, 2.12 user, 0.16 sys
context-switch: 212+1084, page-faults: 0+43039
ex2-c : res=758
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 1+1, page-faults: 0+78

View File

@@ -1,16 +0,0 @@
ex1.bash : res=167829540
time: 0:00.42 real, 0.42 user, 0.00 sys
context-switch: 57+1, page-faults: 0+172
ex1-c : res=167829540
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+76
ex2.bash : res=167829540 sum=28045630
time: 0:03.22 real, 3.01 user, 0.21 sys
context-switch: 359+921, page-faults: 0+49208
ex2-c : res=167829540 sum=28045630
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+75

View File

@@ -1,16 +0,0 @@
ex1.bash : diff1=71 diff2=27 res=1917
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 7+1, page-faults: 0+234
ex1-c : diff1=71 diff2=27 res=1917
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+73
ex2.bash : size=99 res=113387824750592
time: 0:00.02 real, 0.02 user, 0.00 sys
context-switch: 10+1, page-faults: 0+236
ex2-c : size=99 res=113387824750592
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+74

View File

@@ -63,7 +63,6 @@ struct list *add_val(list, val)
struct list *list;
unsigned long long val;
{
//int val;
unsigned cur, size;
unsigned long long *ptr;
@@ -80,7 +79,6 @@ struct list *add_val(list, val)
size+=BLOCKSIZE;
list->size=size;
list->list=realloc(list->list, sizeof(unsigned long long)*size);
fprintf(stderr, "realloc buf: cur=%d size=%d ptr=%p\n", cur, size, list->list);
}
ptr=list->list+cur;
@@ -91,10 +89,10 @@ struct list *add_val(list, val)
return list;
}
unsigned *calc(list)
unsigned long long *calc(list)
struct list *list;
{
static unsigned res[4];
static unsigned long long res[4];
unsigned long long *ptr=list->list;
unsigned last=list->last, i;
@@ -113,10 +111,9 @@ int main(ac, av)
{
char line[80];
struct list *list=NULL;
unsigned long long res, last;
unsigned *result;
unsigned long long res, last, *result;
list=add_val(list, 0);
list=add_val(list, 0llu);
while (fgets(line, sizeof line, stdin)) {
sscanf(line, "%llu", &res);
list=add_val(list, res);
@@ -126,7 +123,7 @@ int main(ac, av)
list=add_val(list, last+3);
//print_list(list);
result=calc(list);
printf("%s : diff1=%u diff2=%u res=%u\n", *av, result[1], result[3],
printf("%s : diff1=%llu diff2=%llu res=%llu\n", *av, result[1], result[3],
result[1]*result[3]);
exit (0);
}

View File

@@ -131,7 +131,7 @@ int main(ac, av)
struct list *list=NULL;
unsigned long long res, last;
list=add_val(list, 0);
list=add_val(list, 0ll);
while (fgets(line, sizeof line, stdin)) {
sscanf(line, "%llu", &res);
list=add_val(list, res);

View File

@@ -1,16 +0,0 @@
ex1.bash : res=2386
time: 0:33.55 real, 33.12 user, 0.42 sys
context-switch: 179+18, page-faults: 0+1948
ex1-c : res=2386
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+90
ex2.bash : res=2091
time: 1:08.60 real, 68.56 user, 0.02 sys
context-switch: 530+10, page-faults: 0+1480
ex2-c : res=2091
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 6+1, page-faults: 0+90

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,16 +0,0 @@
ex1.bash : res=1457
time: 0:00.02 real, 0.02 user, 0.00 sys
context-switch: 5+1, page-faults: 0+152
ex1-c : res=1457
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+72
ex2.bash : res=106860
time: 0:00.09 real, 0.08 user, 0.00 sys
context-switch: 10+1, page-faults: 0+153
ex2-c : res=106860
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 1+1, page-faults: 0+75

View File

@@ -1,16 +0,0 @@
ex1.bash : res=410
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 2+1, page-faults: 0+154
ex1-c : res=410
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+76
ex2.bash : res=600691418730595
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 1+1, page-faults: 0+156
ex2-c : res=600691418730595
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 1+1, page-faults: 0+76

View File

@@ -1,16 +0,0 @@
ex1.bash : res=10035335144067
time: 0:00.06 real, 0.04 user, 0.01 sys
context-switch: 5+1, page-faults: 0+200
ex1-c : res=10035335144067
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+80
ex2.bash : res=3817372618036
time: 0:06.69 real, 6.68 user, 0.00 sys
context-switch: 689+1, page-faults: 0+5949
ex2-c : res=3817372618036
time: 0:00.06 real, 0.05 user, 0.00 sys
context-switch: 6+1, page-faults: 0+662

View File

@@ -1,15 +0,0 @@
ex1.bash : res[2020]=1618
time: 0:00.03 real, 0.02 user, 0.00 sys
context-switch: 6+1, page-faults: 0+158
ex1-c : res[2020]=1618
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+77
ex1.bash : res[30000000]=548531
time: 12:22:02 real, 44488.91 user, 2.70 sys
context-switch: 4552388+2, page-faults: 0+98912
ex1-c : res[30000000]=548531
time: 0:00.56 real, 0.49 user, 0.06 sys
context-switch: 55+1, page-faults: 0+29369

View File

@@ -1,8 +0,0 @@
ex1.bash : res=1618
time: 0:00.07 real, 0.07 user, 0.00 sys
context-switch: 7+1, page-faults: 0+172
ex3.bash : res=548531
time: 12:22:02 real, 44488.91 user, 2.70 sys
context-switch: 4552388+2, page-faults: 0+98912

View File

@@ -1,18 +0,0 @@
cc -w -O3 ex1-c.c -o ex1-c
ex1.bash : res=21996
time: 0:00.14 real, 0.11 user, 0.02 sys
context-switch: 12+120, page-faults: 0+7974
ex1-c : res=21996
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+76
cc -w -O3 ex2-c.c -o ex2-c
ex2.bash : res=650080463519
time: 0:06.58 real, 6.54 user, 0.04 sys
context-switch: 201+114, page-faults: 0+8893
ex2-c : res=650080463519
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+74

View File

@@ -1,20 +0,0 @@
ex1-v1.bash : res=263
time: 1:47.86 real, 74.63 user, 39.28 sys
context-switch: 6224+166221, page-faults: 0+7568225
ex1.bash : res=263
time: 0:00.37 real, 0.36 user, 0.00 sys
context-switch: 1+1, page-faults: 0+322
ex1-c : res=263
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+150
ex2.bash : res=1680
time: 0:06.47 real, 6.47 user, 0.00 sys
context-switch: 23+1, page-faults: 0+2852
ex2-c : res=1680
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+1634

View File

@@ -24,7 +24,7 @@ ex2: ex12-c
@$(TIME) ex12-c 2 < $(INPUT) 2>&1
clean:
@rm -f ex1-c ex2-c core
@rm -f ex12-c core
deploy:
@$(MAKE) -C .. deploy

View File

@@ -1,16 +0,0 @@
ex1.bash : res=650217205854
time: 0:01.80 real, 1.78 user, 0.01 sys
context-switch: 28+1, page-faults: 0+190
ex12-c : res=650217205854
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+75
ex2.bash : res=20394514442037
time: 0:01.56 real, 1.55 user, 0.01 sys
context-switch: 16+1, page-faults: 0+196
ex12-c : res=20394514442037
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+74

View File

@@ -1,6 +1,6 @@
# AOC daily Makefile - GNU make only.
#
# Copyright (C) 2022 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.
#
@@ -15,22 +15,22 @@ SHELL := /bin/bash
CC := gcc
BEAR := bear
CCLSFILE:= compile_commands.json
#LIB := aoc_$(shell uname -m)
#INCDIR := ../include
INCDIR := .
#LIBDIR := ../lib
#LDFLAGS := -L$(LIBDIR)
LIB := aoc_$(shell uname -m)
INCDIR := ../include
LIBDIR := ../lib
LDFLAGS := -L$(LIBDIR)
#LDLIB := -l$(LIB) -lm
#LDLIB := -l$(LIB)
LDLIB := -l$(LIB)
#export LD_LIBRARY_PATH = $(LIBDIR)
export LD_LIBRARY_PATH = $(LIBDIR)
CFLAGS += -std=gnu11
CFLAGS += -O2
CFLAGS += -g
# for gprof
#CFLAGS += -pg
# CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
@@ -50,11 +50,9 @@ VALGRINDFLAGS := --leak-check=full --show-leak-kinds=all --track-origins=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 ex1 ex2 bear org
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 ex1 ex2 ccls
org: README.org
all: org ex1 ex2
all: README.org ccls ex1 ex2
memcheck: memcheck1 memcheck2
@@ -71,19 +69,21 @@ cpp: aoc-c.i
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) ex1.bash < $(INPUT) 2>&1
@$(TIME) aoc-c -p 1 < $(INPUT) 2>&1
@$(TIME) ex1.bash -p 1 < $(INPUT)
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) ex2.bash < $(INPUT) 2>&1
@$(TIME) aoc-c -p 2 < $(INPUT) 2>&1
@$(TIME) ex2.bash -p 2 < $(INPUT)
@$(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
.c:
@echo compiling $<
$(CC) $(CFLAGS) $(LDFLAGS) -I $(INCDIR) $< $(LDLIB) -o $@
@$(CC) $(CFLAGS) $(LDFLAGS) -I $(INCDIR) $< $(LDLIB) -o $@
# generate pre-processed file (.i) and assembler (.s)
%.i: %.c
@@ -94,6 +94,15 @@ clean:
@echo generating $@
@$(CC) -S -fverbose-asm $(CFLAGS) -I $(INCDIR) $< -o $@
# generate README.org from README.html (must cleanup !)
%.org: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@$(BEAR) -- make compile
@touch .ccls-root

View File

@@ -1,8 +0,0 @@
ex1.bash : res=285
time: 0:00.56 real, 0.55 user, 0.00 sys
context-switch: 12+1, page-faults: 0+5967
ex2.bash : res=412
time: 0:03.37 real, 3.34 user, 0.03 sys
context-switch: 19+1, page-faults: 0+11909

View File

@@ -1,145 +0,0 @@
--- Day 19: Monster Messages ---
You land in an airport surrounded by dense forest. As you walk to your high-speed train, the Elves at the Mythical Information Bureau contact you again. They think their satellite has collected an image of a sea monster! Unfortunately, the connection to the satellite is having problems, and many of the messages sent back from the satellite have been corrupted.
They sent you a list of the rules valid messages should obey and a list of received messages they've collected so far (your puzzle input).
The rules for valid messages (the top part of your puzzle input) are numbered and build upon each other. For example:
0: 1 2
1: "a"
2: 1 3 | 3 1
3: "b"
Some rules, like 3: "b", simply match a single character (in this case, b).
The remaining rules list the sub-rules that must be followed; for example, the rule 0: 1 2 means that to match rule 0, the text being checked must match rule 1, and the text after the part that matched rule 1 must then match rule 2.
Some of the rules have multiple lists of sub-rules separated by a pipe (|). This means that at least one list of sub-rules must match. (The ones that match might be different each time the rule is encountered.) For example, the rule 2: 1 3 | 3 1 means that to match rule 2, the text being checked must match rule 1 followed by rule 3 or it must match rule 3 followed by rule 1.
Fortunately, there are no loops in the rules, so the list of possible matches will be finite. Since rule 1 matches a and rule 3 matches b, rule 2 matches either ab or ba. Therefore, rule 0 matches aab or aba.
Here's a more interesting example:
0: 4 1 5
1: 2 3 | 3 2
2: 4 4 | 5 5
3: 4 5 | 5 4
4: "a"
5: "b"
Here, because rule 4 matches a and rule 5 matches b, rule 2 matches two letters that are the same (aa or bb), and rule 3 matches two letters that are different (ab or ba).
Since rule 1 matches rules 2 and 3 once each in either order, it must match two pairs of letters, one pair with matching letters and one pair with different letters. This leaves eight possibilities: aaab, aaba, bbab, bbba, abaa, abbb, baaa, or babb.
Rule 0, therefore, matches a (rule 4), then any of the eight options from rule 1, then b (rule 5): aaaabb, aaabab, abbabb, abbbab, aabaab, aabbbb, abaaab, or ababbb.
The received messages (the bottom part of your puzzle input) need to be checked against the rules so you can determine which are valid and which are corrupted. Including the rules and the messages together, this might look like:
0: 4 1 5
1: 2 3 | 3 2
2: 4 4 | 5 5
3: 4 5 | 5 4
4: "a"
5: "b"
ababbb
bababa
abbbab
aaabbb
aaaabbb
Your goal is to determine the number of messages that completely match rule 0. In the above example, ababbb and abbbab match, but bababa, aaabbb, and aaaabbb do not, producing the answer 2. The whole message must match all of rule 0; there can't be extra unmatched characters in the message. (For example, aaaabbb might appear to match rule 0 above, but it has an extra unmatched b on the end.)
How many messages completely match rule 0?
Your puzzle answer was 285.
--- Part Two ---
As you look over the list of messages, you realize your matching rules aren't quite right. To fix them, completely replace rules 8: 42 and 11: 42 31 with the following:
8: 42 | 42 8
11: 42 31 | 42 11 31
This small change has a big impact: now, the rules do contain loops, and the list of messages they could hypothetically match is infinite. You'll need to determine how these changes affect which messages are valid.
Fortunately, many of the rules are unaffected by this change; it might help to start by looking at which rules always match the same set of values and how those rules (especially rules 42 and 31) are used by the new versions of rules 8 and 11.
(Remember, you only need to handle the rules you have; building a solution that could handle any hypothetical combination of rules would be significantly more difficult.)
For example:
42: 9 14 | 10 1
9: 14 27 | 1 26
10: 23 14 | 28 1
1: "a"
11: 42 31
5: 1 14 | 15 1
19: 14 1 | 14 14
12: 24 14 | 19 1
16: 15 1 | 14 14
31: 14 17 | 1 13
6: 14 14 | 1 14
2: 1 24 | 14 4
0: 8 11
13: 14 3 | 1 12
15: 1 | 14
17: 14 2 | 1 7
23: 25 1 | 22 14
28: 16 1
4: 1 1
20: 14 14 | 1 15
3: 5 14 | 16 1
27: 1 6 | 14 18
14: "b"
21: 14 1 | 1 14
25: 1 1 | 1 14
22: 14 14
8: 42
26: 14 22 | 1 20
18: 15 15
7: 14 5 | 1 21
24: 14 1
abbbbbabbbaaaababbaabbbbabababbbabbbbbbabaaaa
bbabbbbaabaabba
babbbbaabbbbbabbbbbbaabaaabaaa
aaabbbbbbaaaabaababaabababbabaaabbababababaaa
bbbbbbbaaaabbbbaaabbabaaa
bbbababbbbaaaaaaaabbababaaababaabab
ababaaaaaabaaab
ababaaaaabbbaba
baabbaaaabbaaaababbaababb
abbbbabbbbaaaababbbbbbaaaababb
aaaaabbaabaaaaababaa
aaaabbaaaabbaaa
aaaabbaabbaaaaaaabbbabbbaaabbaabaaa
babaaabbbaaabaababbaabababaaab
aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba
Without updating rules 8 and 11, these rules only match three messages: bbabbbbaabaabba, ababaaaaaabaaab, and ababaaaaabbbaba.
However, after updating rules 8 and 11, a total of 12 messages match:
bbabbbbaabaabba
babbbbaabbbbbabbbbbbaabaaabaaa
aaabbbbbbaaaabaababaabababbabaaabbababababaaa
bbbbbbbaaaabbbbaaabbabaaa
bbbababbbbaaaaaaaabbababaaababaabab
ababaaaaaabaaab
ababaaaaabbbaba
baabbaaaabbaaaababbaababb
abbbbabbbbaaaababbbbbbaaaababb
aaaaabbaabaaaaababaa
aaaabbaabbaaaaaaabbbabbbaaabbaabaaa
aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba
After updating rules 8 and 11, how many messages completely match rule 0?
Your puzzle answer was 412.
Both parts of this puzzle are complete! They provide two gold stars: **
At this point, you should return to your Advent calendar and try another puzzle.
If you still want to see it, you can get your puzzle input.

200
2020/day19/README.org Normal file
View File

@@ -0,0 +1,200 @@
** --- Day 19: Monster Messages ---
You land in an airport surrounded by dense forest. As you walk to your
high-speed train, the Elves at the Mythical Information Bureau contact
you again. They think their satellite has collected an image of a /sea
monster/! Unfortunately, the connection to the satellite is having
problems, and many of the messages sent back from the satellite have
been corrupted.
They sent you a list of /the rules valid messages should obey/ and a
list of /received messages/ they've collected so far (your puzzle
input).
The /rules for valid messages/ (the top part of your puzzle input) are
numbered and build upon each other. For example:
#+BEGIN_EXAMPLE
0: 1 2
1: "a"
2: 1 3 | 3 1
3: "b"
#+END_EXAMPLE
Some rules, like =3: "b"=, simply match a single character (in this
case, =b=).
The remaining rules list the sub-rules that must be followed; for
example, the rule =0: 1 2= means that to match rule =0=, the text being
checked must match rule =1=, and the text after the part that matched
rule =1= must then match rule =2=.
Some of the rules have multiple lists of sub-rules separated by a pipe
(=|=). This means that /at least one/ list of sub-rules must match. (The
ones that match might be different each time the rule is encountered.)
For example, the rule =2: 1 3 | 3 1= means that to match rule =2=, the
text being checked must match rule =1= followed by rule =3= /or/ it must
match rule =3= followed by rule =1=.
Fortunately, there are no loops in the rules, so the list of possible
matches will be finite. Since rule =1= matches =a= and rule =3= matches
=b=, rule =2= matches either =ab= or =ba=. Therefore, rule =0= matches
=aab= or =aba=.
Here's a more interesting example:
#+BEGIN_EXAMPLE
0: 4 1 5
1: 2 3 | 3 2
2: 4 4 | 5 5
3: 4 5 | 5 4
4: "a"
5: "b"
#+END_EXAMPLE
Here, because rule =4= matches =a= and rule =5= matches =b=, rule =2=
matches two letters that are the same (=aa= or =bb=), and rule =3=
matches two letters that are different (=ab= or =ba=).
Since rule =1= matches rules =2= and =3= once each in either order, it
must match two pairs of letters, one pair with matching letters and one
pair with different letters. This leaves eight possibilities: =aaab=,
=aaba=, =bbab=, =bbba=, =abaa=, =abbb=, =baaa=, or =babb=.
Rule =0=, therefore, matches =a= (rule =4=), then any of the eight
options from rule =1=, then =b= (rule =5=): =aaaabb=, =aaabab=,
=abbabb=, =abbbab=, =aabaab=, =aabbbb=, =abaaab=, or =ababbb=.
The /received messages/ (the bottom part of your puzzle input) need to
be checked against the rules so you can determine which are valid and
which are corrupted. Including the rules and the messages together, this
might look like:
#+BEGIN_EXAMPLE
0: 4 1 5
1: 2 3 | 3 2
2: 4 4 | 5 5
3: 4 5 | 5 4
4: "a"
5: "b"
ababbb
bababa
abbbab
aaabbb
aaaabbb
#+END_EXAMPLE
Your goal is to determine /the number of messages that completely match
rule =0=/. In the above example, =ababbb= and =abbbab= match, but
=bababa=, =aaabbb=, and =aaaabbb= do not, producing the answer /=2=/.
The whole message must match all of rule =0=; there can't be extra
unmatched characters in the message. (For example, =aaaabbb= might
appear to match rule =0= above, but it has an extra unmatched =b= on the
end.)
/How many messages completely match rule =0=?/
Your puzzle answer was =285=.
** --- Part Two ---
As you look over the list of messages, you realize your matching rules
aren't quite right. To fix them, completely replace rules =8: 42= and
=11: 42 31= with the following:
#+BEGIN_EXAMPLE
8: 42 | 42 8
11: 42 31 | 42 11 31
#+END_EXAMPLE
This small change has a big impact: now, the rules /do/ contain loops,
and the list of messages they could hypothetically match is infinite.
You'll need to determine how these changes affect which messages are
valid.
Fortunately, many of the rules are unaffected by this change; it might
help to start by looking at which rules always match the same set of
values and how /those/ rules (especially rules =42= and =31=) are used
by the new versions of rules =8= and =11=.
(Remember, /you only need to handle the rules you have/; building a
solution that could handle any hypothetical combination of rules would
be [[https://en.wikipedia.org/wiki/Formal_grammar][significantly more
difficult]].)
For example:
#+BEGIN_EXAMPLE
42: 9 14 | 10 1
9: 14 27 | 1 26
10: 23 14 | 28 1
1: "a"
11: 42 31
5: 1 14 | 15 1
19: 14 1 | 14 14
12: 24 14 | 19 1
16: 15 1 | 14 14
31: 14 17 | 1 13
6: 14 14 | 1 14
2: 1 24 | 14 4
0: 8 11
13: 14 3 | 1 12
15: 1 | 14
17: 14 2 | 1 7
23: 25 1 | 22 14
28: 16 1
4: 1 1
20: 14 14 | 1 15
3: 5 14 | 16 1
27: 1 6 | 14 18
14: "b"
21: 14 1 | 1 14
25: 1 1 | 1 14
22: 14 14
8: 42
26: 14 22 | 1 20
18: 15 15
7: 14 5 | 1 21
24: 14 1
abbbbbabbbaaaababbaabbbbabababbbabbbbbbabaaaa
bbabbbbaabaabba
babbbbaabbbbbabbbbbbaabaaabaaa
aaabbbbbbaaaabaababaabababbabaaabbababababaaa
bbbbbbbaaaabbbbaaabbabaaa
bbbababbbbaaaaaaaabbababaaababaabab
ababaaaaaabaaab
ababaaaaabbbaba
baabbaaaabbaaaababbaababb
abbbbabbbbaaaababbbbbbaaaababb
aaaaabbaabaaaaababaa
aaaabbaaaabbaaa
aaaabbaabbaaaaaaabbbabbbaaabbaabaaa
babaaabbbaaabaababbaabababaaab
aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba
#+END_EXAMPLE
Without updating rules =8= and =11=, these rules only match three
messages: =bbabbbbaabaabba=, =ababaaaaaabaaab=, and =ababaaaaabbbaba=.
However, after updating rules =8= and =11=, a total of /=12=/ messages
match:
- =bbabbbbaabaabba=
- =babbbbaabbbbbabbbbbbaabaaabaaa=
- =aaabbbbbbaaaabaababaabababbabaaabbababababaaa=
- =bbbbbbbaaaabbbbaaabbabaaa=
- =bbbababbbbaaaaaaaabbababaaababaabab=
- =ababaaaaaabaaab=
- =ababaaaaabbbaba=
- =baabbaaaabbaaaababbaababb=
- =abbbbabbbbaaaababbbbbbaaaababb=
- =aaaaabbaabaaaaababaa=
- =aaaabbaabbaaaaaaabbbabbbaaabbaabaaa=
- =aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba=
/After updating rules =8= and =11=, how many messages completely match
rule =0=?/
Your puzzle answer was =412=.
Both parts of this puzzle are complete! They provide two gold stars: **

165
2020/day19/aoc-c.c Normal file
View File

@@ -0,0 +1,165 @@
/* aoc-c.c: Advent2020, day 19, parts 1 and 2
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "list.h"
#include "debug.h"
#define MAX_RULES 256
#define MAX_MSG 512
/* to simplify code, we consider here that :
* - a rule has no more than 3 sub-rules
* - there are at most 2 possible sub-rules per rule
*/
struct subrule {
int rule[2][3];
};
static struct rule {
enum type {
SUB,
CHR
} type;
struct subrule sub;
int str;
} rules[MAX_RULES] = {
[0 ... (MAX_RULES-1)] = {
.sub.rule = {{-1, -1, -1}, {-1, -1, -1}}
}
};
static struct mesg {
int len;
char *str;
} mesg[MAX_MSG];
static int nrules, nmesg;
static int match(struct mesg *msg, int *pos, int rule)
{
struct rule *r = rules + rule;
int found = 0, postmp, recurse = 0;
if (r->type == CHR)
return rules[rule].str == msg->str[(*pos)++];
for (int side = 0; side < 2; ++side, recurse = 0, found = 0) {
if (r->sub.rule[side][0] == -1)
break;
postmp = *pos;
found = 1;
for (int sub = 0; sub < 3 && r->sub.rule[side][sub] >= 0; ++sub) {
if (*pos == msg->len)
return recurse;
recurse = r->sub.rule[side][sub] == rule;
if (!match(msg, pos, r->sub.rule[side][sub])) {
found = 0;
*pos = postmp; /* roll back */
break;
}
}
if (found)
break;
}
return found;
}
static long part1()
{
int ret = 0;
for (int msg = 0, pos = 0; msg < nmesg; ++msg, pos = 0)
if (match(mesg + msg, &pos, 0))
ret += pos == mesg[msg].len;
return ret;
}
static long part2()
{
static const struct subrule new[2] = {
{{{42, -1, -1}, {42, 8, -1}}},
{{{42, 31, -1}, {42, 11, 31}}}
};
rules[8].sub = new[0];
rules[11].sub = new[1];
return part1();
}
static void parse()
{
size_t alloc;
ssize_t len;
char *buf = NULL, *tok;
int rule;
while ((len = getline(&buf, &alloc, stdin)) > 0) {
int set = 0, sub = 0;
buf[--len] = 0;
if (len == 0)
continue;
if (isalpha(*buf)) { /* message */
mesg[nmesg].len = len;
mesg[nmesg++].str = strdup(buf);
} else { /* rule */
if (!(tok = strtok(buf, ": "))) /* rule number */
continue;
nrules++;
rule = atoi(tok);
while ((tok = strtok(NULL, ":\" "))) {
switch (*tok) {
case 'a': /* final rule */
case 'b':
rules[rule].type = CHR;
rules[rule].str = *tok;
break;
case '|': /* second ruleset */
set++;
sub = 0;
break;
default:
rules[rule].type = SUB;
rules[rule].sub.rule[set][sub] = atoi(tok);
sub++;
break;
}
}
}
}
free(buf);
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
return 1;
}
int main(ac, av)
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)
default:
return usage(*av);
}
}
parse();
printf("%s : res=%ld\n", *av, part == 1? part1(): part2());
exit (0);
}

View File

@@ -1,46 +0,0 @@
/* ex1-c: Advent2020 game, day 19/tasks 1 & 2
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
struct rule {
struct rule *left;
struct rule *right;
};
int main(ac, av)
int ac;
char **av;
{
char line[1024];
long res=0, tmp;
if (ac != 2) {
fprintf(stderr, "usage: %s [1|2]\n", *av);
exit (1);
}
if (**(av+1) == '2')
prio=&prio_2;
while (fgets(line, sizeof line, stdin)) {
//gets(line, sizeof line, stdin);
//NPUSH(10);
//NPUSH(100);
//NPUSH(1000);
//print();
//printf("TOP=%ld\n", NTOP());
//NPOP();
//print();
saveptr=line;
//printf("%s", line);
tmp=eval_expr();
//printf("%s : res=%ld\n", line, tmp);
res+=tmp;
}
printf("%s : res=%ld\n", *av, res);
exit (0);
}

View File

@@ -1,8 +0,0 @@
ex1.bash : res=5966506063747
time: 0:00.56 real, 0.56 user, 0.00 sys
context-switch: 4+1, page-faults: 0+224
ex2.bash res=1714
time: 0:02.14 real, 2.05 user, 0.02 sys
context-switch: 1146+1, page-faults: 0+605

View File

@@ -1,30 +1,108 @@
INPUT := INPUT.txt
SHELL := /bin/bash
CFLAGS := -w -g
#CFLAGS := -w -g -pg
#CFLAGS := -w -O3
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
# 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.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 deploy ex1 ex2
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 ex1 ex2 ccls
all: ex1 ex2
all: README.org ccls ex1 ex2
output:
@$(MAKE) --no-print-directory all 2>&1 > OUTPUT
memcheck: memcheck1 memcheck2
compile: ex1-c ex2-c
memcheck1: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
ex1:
@$(TIME) ex1.bash < $(INPUT) 2>&1
@#$(TIME) ex1-c 2020 < $(INPUT) 2>&1
memcheck2: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
ex2:
@$(TIME) ex2.bash < $(INPUT) 2>&1
@#$(TIME) ex1-c 30000000 < $(INPUT) 2>&1
compile: aoc-c
cpp: aoc-c.i
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) ex1.bash -p 1 < $(INPUT)
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) ex2.bash -p 2 < $(INPUT)
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)
clean:
@rm -f ex1-c ex2-c core
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html compile_commands.json
deploy:
@$(MAKE) -C .. deploy
.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: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@$(BEAR) -- make compile
@touch .ccls-root

View File

@@ -1,45 +0,0 @@
--- Day 21: Allergen Assessment ---
You reach the train's last stop and the closest you can get to your vacation island without getting wet. There aren't even any boats here, but nothing can stop you now: you build a raft. You just need a few days' worth of food for your journey.
You don't speak the local language, so you can't read any ingredients lists. However, sometimes, allergens are listed in a language you do understand. You should be able to use this information to determine which ingredient contains which allergen and work out which foods are safe to take with you on your trip.
You start by compiling a list of foods (your puzzle input), one food per line. Each line includes that food's ingredients list followed by some or all of the allergens the food contains.
Each allergen is found in exactly one ingredient. Each ingredient contains zero or one allergen. Allergens aren't always marked; when they're listed (as in (contains nuts, shellfish) after an ingredients list), the ingredient that contains each listed allergen will be somewhere in the corresponding ingredients list. However, even if an allergen isn't listed, the ingredient that contains that allergen could still be present: maybe they forgot to label it, or maybe it was labeled in a language you don't know.
For example, consider the following list of foods:
mxmxvkd kfcds sqjhc nhms (contains dairy, fish)
trh fvjkl sbzzf mxmxvkd (contains dairy)
sqjhc fvjkl (contains soy)
sqjhc mxmxvkd sbzzf (contains fish)
The first food in the list has four ingredients (written in a language you don't understand): mxmxvkd, kfcds, sqjhc, and nhms. While the food might contain other allergens, a few allergens the food definitely contains are listed afterward: dairy and fish.
The first step is to determine which ingredients can't possibly contain any of the allergens in any food in your list. In the above example, none of the ingredients kfcds, nhms, sbzzf, or trh can contain an allergen. Counting the number of times any of these ingredients appear in any ingredients list produces 5: they all appear once each except sbzzf, which appears twice.
Determine which ingredients cannot possibly contain any of the allergens in your list. How many times do any of those ingredients appear?
Your puzzle answer was 2211.
The first half of this puzzle is complete! It provides one gold star: *
--- Part Two ---
Now that you've isolated the inert ingredients, you should have enough information to figure out which ingredient contains which allergen.
In the above example:
mxmxvkd contains dairy.
sqjhc contains fish.
fvjkl contains soy.
Arrange the ingredients alphabetically by their allergen and separate them by commas to produce your canonical dangerous ingredient list. (There should not be any spaces in your canonical dangerous ingredient list.) In the above example, this would be mxmxvkd,sqjhc,fvjkl.
Time to stock your raft with supplies. What is your canonical dangerous ingredient list?
Answer:
Although it hasn't changed, you can still get your puzzle input.
You can also [Share] this puzzle.

76
2020/day21/README.org Normal file
View File

@@ -0,0 +1,76 @@
** --- Day 21: Allergen Assessment ---
You reach the train's last stop and the closest you can get to your
vacation island without getting wet. There aren't even any boats here,
but nothing can stop you now: you build a raft. You just need a few
days' worth of food for your journey.
You don't speak the local language, so you can't read any ingredients
lists. However, sometimes, allergens are listed in a language you /do/
understand. You should be able to use this information to determine
which ingredient contains which allergen and work out which foods are
safe to take with you on your trip.
You start by compiling a list of foods (your puzzle input), one food per
line. Each line includes that food's /ingredients list/ followed by some
or all of the allergens the food contains.
Each allergen is found in exactly one ingredient. Each ingredient
contains zero or one allergen. /Allergens aren't always marked/; when
they're listed (as in =(contains nuts, shellfish)= after an ingredients
list), the ingredient that contains each listed allergen will be
/somewhere in the corresponding ingredients list/. However, even if an
allergen isn't listed, the ingredient that contains that allergen could
still be present: maybe they forgot to label it, or maybe it was labeled
in a language you don't know.
For example, consider the following list of foods:
#+begin_example
mxmxvkd kfcds sqjhc nhms (contains dairy, fish)
trh fvjkl sbzzf mxmxvkd (contains dairy)
sqjhc fvjkl (contains soy)
sqjhc mxmxvkd sbzzf (contains fish)
#+end_example
The first food in the list has four ingredients (written in a language
you don't understand): =mxmxvkd=, =kfcds=, =sqjhc=, and =nhms=. While
the food might contain other allergens, a few allergens the food
definitely contains are listed afterward: =dairy= and =fish=.
The first step is to determine which ingredients /can't possibly/
contain any of the allergens in any food in your list. In the above
example, none of the ingredients =kfcds=, =nhms=, =sbzzf=, or =trh= can
contain an allergen. Counting the number of times any of these
ingredients appear in any ingredients list produces /=5=/: they all
appear once each except =sbzzf=, which appears twice.
Determine which ingredients cannot possibly contain any of the allergens
in your list. /How many times do any of those ingredients appear?/
Your puzzle answer was =2211=.
** --- Part Two ---
Now that you've isolated the inert ingredients, you should have enough
information to figure out which ingredient contains which allergen.
In the above example:
- =mxmxvkd= contains =dairy=.
- =sqjhc= contains =fish=.
- =fvjkl= contains =soy=.
Arrange the ingredients /alphabetically by their allergen/ and separate
them by commas to produce your /canonical dangerous ingredient list/.
(There should /not be any spaces/ in your canonical dangerous ingredient
list.) In the above example, this would be /=mxmxvkd,sqjhc,fvjkl=/.
Time to stock your raft with supplies. /What is your canonical dangerous
ingredient list?/
Your puzzle answer was
=vv,nlxsmb,rnbhjk,bvnkk,ttxvphb,qmkz,trmzkcfg,jpvz=.
Both parts of this puzzle are complete! They provide two gold stars: **
At this point, all that is left is for you to [[/2020][admire your
Advent calendar]].

View File

@@ -1,30 +1,108 @@
INPUT := INPUT.txt
SHELL := /bin/bash
CFLAGS := -w -g
#CFLAGS := -w -g -pg
#CFLAGS := -w -O3
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
# 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.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 deploy ex1 ex2
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 ex1 ex2 ccls bear
all: ex1 ex2
all: README.org ccls ex1 ex2
output:
@$(MAKE) --no-print-directory all 2>&1 > OUTPUT
memcheck: memcheck1 memcheck2
compile: ex1-c ex2-c
memcheck1: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
ex1:
@$(TIME) ex1.bash < $(INPUT) 2>&1
@#$(TIME) ex1-c 2020 < $(INPUT) 2>&1
memcheck2: aoc-c
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
ex2:
@$(TIME) ex2.bash < $(INPUT) 2>&1
@#$(TIME) ex1-c 30000000 < $(INPUT) 2>&1
compile: aoc-c
cpp: aoc-c.i
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) ex1.bash -p 1 < $(INPUT)
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) ex2.bash -p 2 < $(INPUT)
@$(TIME) aoc-c -p 2 < $(INPUT)
ccls: $(CCLSFILE)
clean:
@rm -f ex1-c ex2-c core
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html compile_commands.json
deploy:
@$(MAKE) -C .. deploy
.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: %.html
@echo generating $@. Cleanup before commit !
@pandoc $< -o $@
# generate compile_commands.json
$(CCLSFILE): aoc-c.c Makefile
$(BEAR) -- make clean compile
bear: clean
@$(BEAR) -- make compile
@touch .ccls-root

View File

@@ -1,8 +0,0 @@
ex1.bash: res=31314
time: 0:00.07 real, 0.06 user, 0.00 sys
context-switch: 2+1, page-faults: 0+168
ex2.bash: res=32760
time: 1:21.92 real, 81.89 user, 0.01 sys
context-switch: 462+1, page-faults: 0+5135

View File

@@ -1,386 +0,0 @@
--- Day 22: Crab Combat ---
It only takes a few hours of sailing the ocean on a raft for boredom to sink in. Fortunately, you brought a small deck of space cards! You'd like to play a game of Combat, and there's even an opponent available: a small crab that climbed aboard your raft before you left.
Fortunately, it doesn't take long to teach the crab the rules.
Before the game starts, split the cards so each player has their own deck (your puzzle input). Then, the game consists of a series of rounds: both players draw their top card, and the player with the higher-valued card wins the round. The winner keeps both cards, placing them on the bottom of their own deck so that the winner's card is above the other card. If this causes a player to have all of the cards, they win, and the game ends.
For example, consider the following starting decks:
Player 1:
9
2
6
3
1
Player 2:
5
8
4
7
10
This arrangement means that player 1's deck contains 5 cards, with 9 on top and 1 on the bottom; player 2's deck also contains 5 cards, with 5 on top and 10 on the bottom.
The first round begins with both players drawing the top card of their decks: 9 and 5. Player 1 has the higher card, so both cards move to the bottom of player 1's deck such that 9 is above 5. In total, it takes 29 rounds before a player has all of the cards:
-- Round 1 --
Player 1's deck: 9, 2, 6, 3, 1
Player 2's deck: 5, 8, 4, 7, 10
Player 1 plays: 9
Player 2 plays: 5
Player 1 wins the round!
-- Round 2 --
Player 1's deck: 2, 6, 3, 1, 9, 5
Player 2's deck: 8, 4, 7, 10
Player 1 plays: 2
Player 2 plays: 8
Player 2 wins the round!
-- Round 3 --
Player 1's deck: 6, 3, 1, 9, 5
Player 2's deck: 4, 7, 10, 8, 2
Player 1 plays: 6
Player 2 plays: 4
Player 1 wins the round!
-- Round 4 --
Player 1's deck: 3, 1, 9, 5, 6, 4
Player 2's deck: 7, 10, 8, 2
Player 1 plays: 3
Player 2 plays: 7
Player 2 wins the round!
-- Round 5 --
Player 1's deck: 1, 9, 5, 6, 4
Player 2's deck: 10, 8, 2, 7, 3
Player 1 plays: 1
Player 2 plays: 10
Player 2 wins the round!
...several more rounds pass...
-- Round 27 --
Player 1's deck: 5, 4, 1
Player 2's deck: 8, 9, 7, 3, 2, 10, 6
Player 1 plays: 5
Player 2 plays: 8
Player 2 wins the round!
-- Round 28 --
Player 1's deck: 4, 1
Player 2's deck: 9, 7, 3, 2, 10, 6, 8, 5
Player 1 plays: 4
Player 2 plays: 9
Player 2 wins the round!
-- Round 29 --
Player 1's deck: 1
Player 2's deck: 7, 3, 2, 10, 6, 8, 5, 9, 4
Player 1 plays: 1
Player 2 plays: 7
Player 2 wins the round!
== Post-game results ==
Player 1's deck:
Player 2's deck: 3, 2, 10, 6, 8, 5, 9, 4, 7, 1
Once the game ends, you can calculate the winning player's score. The bottom card in their deck is worth the value of the card multiplied by 1, the second-from-the-bottom card is worth the value of the card multiplied by 2, and so on. With 10 cards, the top card is worth the value on the card multiplied by 10. In this example, the winning player's score is:
3 * 10
+ 2 * 9
+ 10 * 8
+ 6 * 7
+ 8 * 6
+ 5 * 5
+ 9 * 4
+ 4 * 3
+ 7 * 2
+ 1 * 1
= 306
So, once the game ends, the winning player's score is 306.
Play the small crab in a game of Combat using the two decks you just dealt. What is the winning player's score?
Your puzzle answer was 31314.
The first half of this puzzle is complete! It provides one gold star: *
--- Part Two ---
You lost to the small crab! Fortunately, crabs aren't very good at recursion. To defend your honor as a Raft Captain, you challenge the small crab to a game of Recursive Combat.
Recursive Combat still starts by splitting the cards into two decks (you offer to play with the same starting decks as before - it's only fair). Then, the game consists of a series of rounds with a few changes:
Before either player deals a card, if there was a previous round in this game that had exactly the same cards in the same order in the same players' decks, the game instantly ends in a win for player 1. Previous rounds from other games are not considered. (This prevents infinite games of Recursive Combat, which everyone agrees is a bad idea.)
Otherwise, this round's cards must be in a new configuration; the players begin the round by each drawing the top card of their deck as normal.
If both players have at least as many cards remaining in their deck as the value of the card they just drew, the winner of the round is determined by playing a new game of Recursive Combat (see below).
Otherwise, at least one player must not have enough cards left in their deck to recurse; the winner of the round is the player with the higher-value card.
As in regular Combat, the winner of the round (even if they won the round by winning a sub-game) takes the two cards dealt at the beginning of the round and places them on the bottom of their own deck (again so that the winner's card is above the other card). Note that the winner's card might be the lower-valued of the two cards if they won the round due to winning a sub-game. If collecting cards by winning the round causes a player to have all of the cards, they win, and the game ends.
Here is an example of a small game that would loop forever without the infinite game prevention rule:
Player 1:
43
19
Player 2:
2
29
14
During a round of Recursive Combat, if both players have at least as many cards in their own decks as the number on the card they just dealt, the winner of the round is determined by recursing into a sub-game of Recursive Combat. (For example, if player 1 draws the 3 card, and player 2 draws the 7 card, this would occur if player 1 has at least 3 cards left and player 2 has at least 7 cards left, not counting the 3 and 7 cards that were drawn.)
To play a sub-game of Recursive Combat, each player creates a new deck by making a copy of the next cards in their deck (the quantity of cards copied is equal to the number on the card they drew to trigger the sub-game). During this sub-game, the game that triggered it is on hold and completely unaffected; no cards are removed from players' decks to form the sub-game. (For example, if player 1 drew the 3 card, their deck in the sub-game would be copies of the next three cards in their deck.)
Here is a complete example of gameplay, where Game 1 is the primary game of Recursive Combat:
=== Game 1 ===
-- Round 1 (Game 1) --
Player 1's deck: 9, 2, 6, 3, 1
Player 2's deck: 5, 8, 4, 7, 10
Player 1 plays: 9
Player 2 plays: 5
Player 1 wins round 1 of game 1!
-- Round 2 (Game 1) --
Player 1's deck: 2, 6, 3, 1, 9, 5
Player 2's deck: 8, 4, 7, 10
Player 1 plays: 2
Player 2 plays: 8
Player 2 wins round 2 of game 1!
-- Round 3 (Game 1) --
Player 1's deck: 6, 3, 1, 9, 5
Player 2's deck: 4, 7, 10, 8, 2
Player 1 plays: 6
Player 2 plays: 4
Player 1 wins round 3 of game 1!
-- Round 4 (Game 1) --
Player 1's deck: 3, 1, 9, 5, 6, 4
Player 2's deck: 7, 10, 8, 2
Player 1 plays: 3
Player 2 plays: 7
Player 2 wins round 4 of game 1!
-- Round 5 (Game 1) --
Player 1's deck: 1, 9, 5, 6, 4
Player 2's deck: 10, 8, 2, 7, 3
Player 1 plays: 1
Player 2 plays: 10
Player 2 wins round 5 of game 1!
-- Round 6 (Game 1) --
Player 1's deck: 9, 5, 6, 4
Player 2's deck: 8, 2, 7, 3, 10, 1
Player 1 plays: 9
Player 2 plays: 8
Player 1 wins round 6 of game 1!
-- Round 7 (Game 1) --
Player 1's deck: 5, 6, 4, 9, 8
Player 2's deck: 2, 7, 3, 10, 1
Player 1 plays: 5
Player 2 plays: 2
Player 1 wins round 7 of game 1!
-- Round 8 (Game 1) --
Player 1's deck: 6, 4, 9, 8, 5, 2
Player 2's deck: 7, 3, 10, 1
Player 1 plays: 6
Player 2 plays: 7
Player 2 wins round 8 of game 1!
-- Round 9 (Game 1) --
Player 1's deck: 4, 9, 8, 5, 2
Player 2's deck: 3, 10, 1, 7, 6
Player 1 plays: 4
Player 2 plays: 3
Playing a sub-game to determine the winner...
=== Game 2 ===
-- Round 1 (Game 2) --
Player 1's deck: 9, 8, 5, 2
Player 2's deck: 10, 1, 7
Player 1 plays: 9
Player 2 plays: 10
Player 2 wins round 1 of game 2!
-- Round 2 (Game 2) --
Player 1's deck: 8, 5, 2
Player 2's deck: 1, 7, 10, 9
Player 1 plays: 8
Player 2 plays: 1
Player 1 wins round 2 of game 2!
-- Round 3 (Game 2) --
Player 1's deck: 5, 2, 8, 1
Player 2's deck: 7, 10, 9
Player 1 plays: 5
Player 2 plays: 7
Player 2 wins round 3 of game 2!
-- Round 4 (Game 2) --
Player 1's deck: 2, 8, 1
Player 2's deck: 10, 9, 7, 5
Player 1 plays: 2
Player 2 plays: 10
Player 2 wins round 4 of game 2!
-- Round 5 (Game 2) --
Player 1's deck: 8, 1
Player 2's deck: 9, 7, 5, 10, 2
Player 1 plays: 8
Player 2 plays: 9
Player 2 wins round 5 of game 2!
-- Round 6 (Game 2) --
Player 1's deck: 1
Player 2's deck: 7, 5, 10, 2, 9, 8
Player 1 plays: 1
Player 2 plays: 7
Player 2 wins round 6 of game 2!
The winner of game 2 is player 2!
...anyway, back to game 1.
Player 2 wins round 9 of game 1!
-- Round 10 (Game 1) --
Player 1's deck: 9, 8, 5, 2
Player 2's deck: 10, 1, 7, 6, 3, 4
Player 1 plays: 9
Player 2 plays: 10
Player 2 wins round 10 of game 1!
-- Round 11 (Game 1) --
Player 1's deck: 8, 5, 2
Player 2's deck: 1, 7, 6, 3, 4, 10, 9
Player 1 plays: 8
Player 2 plays: 1
Player 1 wins round 11 of game 1!
-- Round 12 (Game 1) --
Player 1's deck: 5, 2, 8, 1
Player 2's deck: 7, 6, 3, 4, 10, 9
Player 1 plays: 5
Player 2 plays: 7
Player 2 wins round 12 of game 1!
-- Round 13 (Game 1) --
Player 1's deck: 2, 8, 1
Player 2's deck: 6, 3, 4, 10, 9, 7, 5
Player 1 plays: 2
Player 2 plays: 6
Playing a sub-game to determine the winner...
=== Game 3 ===
-- Round 1 (Game 3) --
Player 1's deck: 8, 1
Player 2's deck: 3, 4, 10, 9, 7, 5
Player 1 plays: 8
Player 2 plays: 3
Player 1 wins round 1 of game 3!
-- Round 2 (Game 3) --
Player 1's deck: 1, 8, 3
Player 2's deck: 4, 10, 9, 7, 5
Player 1 plays: 1
Player 2 plays: 4
Playing a sub-game to determine the winner...
=== Game 4 ===
-- Round 1 (Game 4) --
Player 1's deck: 8
Player 2's deck: 10, 9, 7, 5
Player 1 plays: 8
Player 2 plays: 10
Player 2 wins round 1 of game 4!
The winner of game 4 is player 2!
...anyway, back to game 3.
Player 2 wins round 2 of game 3!
-- Round 3 (Game 3) --
Player 1's deck: 8, 3
Player 2's deck: 10, 9, 7, 5, 4, 1
Player 1 plays: 8
Player 2 plays: 10
Player 2 wins round 3 of game 3!
-- Round 4 (Game 3) --
Player 1's deck: 3
Player 2's deck: 9, 7, 5, 4, 1, 10, 8
Player 1 plays: 3
Player 2 plays: 9
Player 2 wins round 4 of game 3!
The winner of game 3 is player 2!
...anyway, back to game 1.
Player 2 wins round 13 of game 1!
-- Round 14 (Game 1) --
Player 1's deck: 8, 1
Player 2's deck: 3, 4, 10, 9, 7, 5, 6, 2
Player 1 plays: 8
Player 2 plays: 3
Player 1 wins round 14 of game 1!
-- Round 15 (Game 1) --
Player 1's deck: 1, 8, 3
Player 2's deck: 4, 10, 9, 7, 5, 6, 2
Player 1 plays: 1
Player 2 plays: 4
Playing a sub-game to determine the winner...
=== Game 5 ===
-- Round 1 (Game 5) --
Player 1's deck: 8
Player 2's deck: 10, 9, 7, 5
Player 1 plays: 8
Player 2 plays: 10
Player 2 wins round 1 of game 5!
The winner of game 5 is player 2!
...anyway, back to game 1.
Player 2 wins round 15 of game 1!
-- Round 16 (Game 1) --
Player 1's deck: 8, 3
Player 2's deck: 10, 9, 7, 5, 6, 2, 4, 1
Player 1 plays: 8
Player 2 plays: 10
Player 2 wins round 16 of game 1!
-- Round 17 (Game 1) --
Player 1's deck: 3
Player 2's deck: 9, 7, 5, 6, 2, 4, 1, 10, 8
Player 1 plays: 3
Player 2 plays: 9
Player 2 wins round 17 of game 1!
The winner of game 1 is player 2!
== Post-game results ==
Player 1's deck:
Player 2's deck: 7, 5, 6, 2, 4, 1, 10, 8, 9, 3
After the game, the winning player's score is calculated from the cards they have in their original deck using the same rules as regular Combat. In the above game, the winning player's score is 291.
Defend your honor as Raft Captain by playing the small crab in a game of Recursive Combat using the same two decks as before. What is the winning player's score?
Answer:
Although it hasn't changed, you can still get your puzzle input.
You can also [Share] this puzzle.

452
2020/day22/README.org Normal file
View File

@@ -0,0 +1,452 @@
** --- Day 22: Crab Combat ---
It only takes a few hours of sailing the ocean on a raft for boredom to
sink in. Fortunately, you brought a small deck of [[/2019/day/22][space
cards]]! You'd like to play a game of /Combat/, and there's even an
opponent available: a small crab that climbed aboard your raft before
you left.
Fortunately, it doesn't take long to teach the crab the rules.
Before the game starts, split the cards so each player has their own
deck (your puzzle input). Then, the game consists of a series of
/rounds/: both players draw their top card, and the player with the
higher-valued card wins the round. The winner keeps both cards, placing
them on the bottom of their own deck so that the winner's card is above
the other card. If this causes a player to have all of the cards, they
win, and the game ends.
For example, consider the following starting decks:
#+BEGIN_EXAMPLE
Player 1:
9
2
6
3
1
Player 2:
5
8
4
7
10
#+END_EXAMPLE
This arrangement means that player 1's deck contains 5 cards, with =9=
on top and =1= on the bottom; player 2's deck also contains 5 cards,
with =5= on top and =10= on the bottom.
The first round begins with both players drawing the top card of their
decks: =9= and =5=. Player 1 has the higher card, so both cards move to
the bottom of player 1's deck such that =9= is above =5=. In total, it
takes 29 rounds before a player has all of the cards:
#+BEGIN_EXAMPLE
-- Round 1 --
Player 1's deck: 9, 2, 6, 3, 1
Player 2's deck: 5, 8, 4, 7, 10
Player 1 plays: 9
Player 2 plays: 5
Player 1 wins the round!
-- Round 2 --
Player 1's deck: 2, 6, 3, 1, 9, 5
Player 2's deck: 8, 4, 7, 10
Player 1 plays: 2
Player 2 plays: 8
Player 2 wins the round!
-- Round 3 --
Player 1's deck: 6, 3, 1, 9, 5
Player 2's deck: 4, 7, 10, 8, 2
Player 1 plays: 6
Player 2 plays: 4
Player 1 wins the round!
-- Round 4 --
Player 1's deck: 3, 1, 9, 5, 6, 4
Player 2's deck: 7, 10, 8, 2
Player 1 plays: 3
Player 2 plays: 7
Player 2 wins the round!
-- Round 5 --
Player 1's deck: 1, 9, 5, 6, 4
Player 2's deck: 10, 8, 2, 7, 3
Player 1 plays: 1
Player 2 plays: 10
Player 2 wins the round!
...several more rounds pass...
-- Round 27 --
Player 1's deck: 5, 4, 1
Player 2's deck: 8, 9, 7, 3, 2, 10, 6
Player 1 plays: 5
Player 2 plays: 8
Player 2 wins the round!
-- Round 28 --
Player 1's deck: 4, 1
Player 2's deck: 9, 7, 3, 2, 10, 6, 8, 5
Player 1 plays: 4
Player 2 plays: 9
Player 2 wins the round!
-- Round 29 --
Player 1's deck: 1
Player 2's deck: 7, 3, 2, 10, 6, 8, 5, 9, 4
Player 1 plays: 1
Player 2 plays: 7
Player 2 wins the round!
== Post-game results ==
Player 1's deck:
Player 2's deck: 3, 2, 10, 6, 8, 5, 9, 4, 7, 1
#+END_EXAMPLE
Once the game ends, you can calculate the winning player's /score/. The
bottom card in their deck is worth the value of the card multiplied by
1, the second-from-the-bottom card is worth the value of the card
multiplied by 2, and so on. With 10 cards, the top card is worth the
value on the card multiplied by 10. In this example, the winning
player's score is:
#+BEGIN_EXAMPLE
3 * 10
+ 2 * 9
+ 10 * 8
+ 6 * 7
+ 8 * 6
+ 5 * 5
+ 9 * 4
+ 4 * 3
+ 7 * 2
+ 1 * 1
= 306
#+END_EXAMPLE
So, once the game ends, the winning player's score is /=306=/.
Play the small crab in a game of Combat using the two decks you just
dealt. /What is the winning player's score?/
Your puzzle answer was =31314=.
** --- Part Two ---
You lost to the small crab! Fortunately, crabs aren't very good at
recursion. To defend your honor as a Raft Captain, you challenge the
small crab to a game of /Recursive Combat/.
Recursive Combat still starts by splitting the cards into two decks (you
offer to play with the same starting decks as before - it's only fair).
Then, the game consists of a series of /rounds/ with a few changes:
- Before either player deals a card, if there was a previous round in
this game that had exactly the same cards in the same order in the
same players' decks, the /game/ instantly ends in a win for player 1.
Previous rounds from other games are not considered. (This prevents
infinite games of Recursive Combat, which everyone agrees is a bad
idea.)
- Otherwise, this round's cards must be in a new configuration; the
players begin the round by each drawing the top card of their deck as
normal.
- If both players have at least as many cards remaining in their deck as
the value of the card they just drew, the winner of the round is
determined by playing a new game of Recursive Combat (see below).
- Otherwise, at least one player must not have enough cards left in
their deck to recurse; the winner of the round is the player with the
higher-value card.
As in regular Combat, the winner of the round (even if they won the
round by winning a sub-game) takes the two cards dealt at the beginning
of the round and places them on the bottom of their own deck (again so
that the winner's card is above the other card). Note that the winner's
card might be /the lower-valued of the two cards/ if they won the round
due to winning a sub-game. If collecting cards by winning the round
causes a player to have all of the cards, they win, and the game ends.
Here is an example of a small game that would loop forever without the
infinite game prevention rule:
#+BEGIN_EXAMPLE
Player 1:
43
19
Player 2:
2
29
14
#+END_EXAMPLE
During a round of Recursive Combat, if both players have at least as
many cards in their own decks as the number on the card they just dealt,
the winner of the round is determined by recursing into a sub-game of
Recursive Combat. (For example, if player 1 draws the =3= card, and
player 2 draws the =7= card, this would occur if player 1 has at least 3
cards left and player 2 has at least 7 cards left, not counting the =3=
and =7= cards that were drawn.)
To play a sub-game of Recursive Combat, each player creates a new deck
by making a /copy/ of the next cards in their deck (the quantity of
cards copied is equal to the number on the card they drew to trigger the
sub-game). During this sub-game, the game that triggered it is on hold
and completely unaffected; no cards are removed from players' decks to
form the sub-game. (For example, if player 1 drew the =3= card, their
deck in the sub-game would be /copies/ of the next three cards in their
deck.)
Here is a complete example of gameplay, where =Game 1= is the primary
game of Recursive Combat:
#+BEGIN_EXAMPLE
=== Game 1 ===
-- Round 1 (Game 1) --
Player 1's deck: 9, 2, 6, 3, 1
Player 2's deck: 5, 8, 4, 7, 10
Player 1 plays: 9
Player 2 plays: 5
Player 1 wins round 1 of game 1!
-- Round 2 (Game 1) --
Player 1's deck: 2, 6, 3, 1, 9, 5
Player 2's deck: 8, 4, 7, 10
Player 1 plays: 2
Player 2 plays: 8
Player 2 wins round 2 of game 1!
-- Round 3 (Game 1) --
Player 1's deck: 6, 3, 1, 9, 5
Player 2's deck: 4, 7, 10, 8, 2
Player 1 plays: 6
Player 2 plays: 4
Player 1 wins round 3 of game 1!
-- Round 4 (Game 1) --
Player 1's deck: 3, 1, 9, 5, 6, 4
Player 2's deck: 7, 10, 8, 2
Player 1 plays: 3
Player 2 plays: 7
Player 2 wins round 4 of game 1!
-- Round 5 (Game 1) --
Player 1's deck: 1, 9, 5, 6, 4
Player 2's deck: 10, 8, 2, 7, 3
Player 1 plays: 1
Player 2 plays: 10
Player 2 wins round 5 of game 1!
-- Round 6 (Game 1) --
Player 1's deck: 9, 5, 6, 4
Player 2's deck: 8, 2, 7, 3, 10, 1
Player 1 plays: 9
Player 2 plays: 8
Player 1 wins round 6 of game 1!
-- Round 7 (Game 1) --
Player 1's deck: 5, 6, 4, 9, 8
Player 2's deck: 2, 7, 3, 10, 1
Player 1 plays: 5
Player 2 plays: 2
Player 1 wins round 7 of game 1!
-- Round 8 (Game 1) --
Player 1's deck: 6, 4, 9, 8, 5, 2
Player 2's deck: 7, 3, 10, 1
Player 1 plays: 6
Player 2 plays: 7
Player 2 wins round 8 of game 1!
-- Round 9 (Game 1) --
Player 1's deck: 4, 9, 8, 5, 2
Player 2's deck: 3, 10, 1, 7, 6
Player 1 plays: 4
Player 2 plays: 3
Playing a sub-game to determine the winner...
=== Game 2 ===
-- Round 1 (Game 2) --
Player 1's deck: 9, 8, 5, 2
Player 2's deck: 10, 1, 7
Player 1 plays: 9
Player 2 plays: 10
Player 2 wins round 1 of game 2!
-- Round 2 (Game 2) --
Player 1's deck: 8, 5, 2
Player 2's deck: 1, 7, 10, 9
Player 1 plays: 8
Player 2 plays: 1
Player 1 wins round 2 of game 2!
-- Round 3 (Game 2) --
Player 1's deck: 5, 2, 8, 1
Player 2's deck: 7, 10, 9
Player 1 plays: 5
Player 2 plays: 7
Player 2 wins round 3 of game 2!
-- Round 4 (Game 2) --
Player 1's deck: 2, 8, 1
Player 2's deck: 10, 9, 7, 5
Player 1 plays: 2
Player 2 plays: 10
Player 2 wins round 4 of game 2!
-- Round 5 (Game 2) --
Player 1's deck: 8, 1
Player 2's deck: 9, 7, 5, 10, 2
Player 1 plays: 8
Player 2 plays: 9
Player 2 wins round 5 of game 2!
-- Round 6 (Game 2) --
Player 1's deck: 1
Player 2's deck: 7, 5, 10, 2, 9, 8
Player 1 plays: 1
Player 2 plays: 7
Player 2 wins round 6 of game 2!
The winner of game 2 is player 2!
...anyway, back to game 1.
Player 2 wins round 9 of game 1!
-- Round 10 (Game 1) --
Player 1's deck: 9, 8, 5, 2
Player 2's deck: 10, 1, 7, 6, 3, 4
Player 1 plays: 9
Player 2 plays: 10
Player 2 wins round 10 of game 1!
-- Round 11 (Game 1) --
Player 1's deck: 8, 5, 2
Player 2's deck: 1, 7, 6, 3, 4, 10, 9
Player 1 plays: 8
Player 2 plays: 1
Player 1 wins round 11 of game 1!
-- Round 12 (Game 1) --
Player 1's deck: 5, 2, 8, 1
Player 2's deck: 7, 6, 3, 4, 10, 9
Player 1 plays: 5
Player 2 plays: 7
Player 2 wins round 12 of game 1!
-- Round 13 (Game 1) --
Player 1's deck: 2, 8, 1
Player 2's deck: 6, 3, 4, 10, 9, 7, 5
Player 1 plays: 2
Player 2 plays: 6
Playing a sub-game to determine the winner...
=== Game 3 ===
-- Round 1 (Game 3) --
Player 1's deck: 8, 1
Player 2's deck: 3, 4, 10, 9, 7, 5
Player 1 plays: 8
Player 2 plays: 3
Player 1 wins round 1 of game 3!
-- Round 2 (Game 3) --
Player 1's deck: 1, 8, 3
Player 2's deck: 4, 10, 9, 7, 5
Player 1 plays: 1
Player 2 plays: 4
Playing a sub-game to determine the winner...
=== Game 4 ===
-- Round 1 (Game 4) --
Player 1's deck: 8
Player 2's deck: 10, 9, 7, 5
Player 1 plays: 8
Player 2 plays: 10
Player 2 wins round 1 of game 4!
The winner of game 4 is player 2!
...anyway, back to game 3.
Player 2 wins round 2 of game 3!
-- Round 3 (Game 3) --
Player 1's deck: 8, 3
Player 2's deck: 10, 9, 7, 5, 4, 1
Player 1 plays: 8
Player 2 plays: 10
Player 2 wins round 3 of game 3!
-- Round 4 (Game 3) --
Player 1's deck: 3
Player 2's deck: 9, 7, 5, 4, 1, 10, 8
Player 1 plays: 3
Player 2 plays: 9
Player 2 wins round 4 of game 3!
The winner of game 3 is player 2!
...anyway, back to game 1.
Player 2 wins round 13 of game 1!
-- Round 14 (Game 1) --
Player 1's deck: 8, 1
Player 2's deck: 3, 4, 10, 9, 7, 5, 6, 2
Player 1 plays: 8
Player 2 plays: 3
Player 1 wins round 14 of game 1!
-- Round 15 (Game 1) --
Player 1's deck: 1, 8, 3
Player 2's deck: 4, 10, 9, 7, 5, 6, 2
Player 1 plays: 1
Player 2 plays: 4
Playing a sub-game to determine the winner...
=== Game 5 ===
-- Round 1 (Game 5) --
Player 1's deck: 8
Player 2's deck: 10, 9, 7, 5
Player 1 plays: 8
Player 2 plays: 10
Player 2 wins round 1 of game 5!
The winner of game 5 is player 2!
...anyway, back to game 1.
Player 2 wins round 15 of game 1!
-- Round 16 (Game 1) --
Player 1's deck: 8, 3
Player 2's deck: 10, 9, 7, 5, 6, 2, 4, 1
Player 1 plays: 8
Player 2 plays: 10
Player 2 wins round 16 of game 1!
-- Round 17 (Game 1) --
Player 1's deck: 3
Player 2's deck: 9, 7, 5, 6, 2, 4, 1, 10, 8
Player 1 plays: 3
Player 2 plays: 9
Player 2 wins round 17 of game 1!
The winner of game 1 is player 2!
== Post-game results ==
Player 1's deck:
Player 2's deck: 7, 5, 6, 2, 4, 1, 10, 8, 9, 3
#+END_EXAMPLE
After the game, the winning player's score is calculated from the cards
they have in their original deck using the same rules as regular Combat.
In the above game, the winning player's score is /=291=/.
Defend your honor as Raft Captain by playing the small crab in a game of
Recursive Combat using the same two decks as before. /What is the
winning player's score?/
Your puzzle answer was =32760=.
Both parts of this puzzle are complete! They provide two gold stars: **

315
2020/day22/aoc-c.c Normal file
View File

@@ -0,0 +1,315 @@
/* aoc-c.c: Advent2020, day 22, parts 1 & 2
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "debug.h"
#include "hashtable.h"
#include "list.h"
#include "pool.h"
typedef struct card {
u8 card; /* card value */
struct list_head list; /* list of cards */
} card_t;
typedef struct player {
int ncards; /* player cards # */
struct list_head head; /* head of cards list */
} player_t;
/* zobrist hash used to find duplicate positions
*/
typedef struct hash {
u32 zobrist;
struct list_head players[2];
struct hlist_node hlist;
} hash_t;
#define HBITS 10 /* 10 bits: hash size is 1024 */
#define CARDS 50
pool_t *pool_cards;
pool_t *pool_hash;
static u32 zobrist_table[2][CARDS][CARDS];
static void zobrist_init()
{
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 50; ++j)
for (int k = 0; k < 50; ++k)
zobrist_table[i][j][k] = rand();
}
static u32 zobrist(player_t *players)
{
u32 zobrist = 0;
card_t *card;
for (int p = 0; p < 2; ++p) {
int pos = 0;
list_for_each_entry(card, &players[p].head, list) {
zobrist ^= zobrist_table[p][pos][card->card - 1];
pos++;
}
}
return zobrist;
}
static __always_inline u32 hash(u32 h)
{
return hash_32(h, HBITS);
}
static int equal_decks(hash_t *hasht, player_t *new)
{
for (int i = 0; i < 2; ++i) {
card_t *c1 = list_first_entry_or_null(&hasht->players[i], card_t, list);
card_t *c2 = list_first_entry_or_null(&new[i].head, card_t, list);
if (!c1 || !c2) /* one list (only) is empty */
return 0;
while (!list_entry_is_head(c1, &hasht->players[i], list) &&
!list_entry_is_head(c2, &new[i].head, list) &&
c1->card == c2->card) {
if (c1->card != c2->card)
return 0;
c1 = list_next_entry(c1, list);
c2 = list_next_entry(c2, list);
}
if (!list_entry_is_head(c1, &hasht->players[i], list) ||
!list_entry_is_head(c2, &new[i].head, list))
return 0;
}
return 1;
}
static hash_t *create_hash(player_t *players, u32 h)
{
struct card *card;
hash_t *hash = pool_get(pool_hash);
INIT_HLIST_NODE(&hash->hlist);
hash->zobrist = h;
for (int i = 0; i < 2; ++i) {
INIT_LIST_HEAD(&hash->players[i]);
list_for_each_entry(card, &players[i].head, list) {
struct card *new = pool_get(pool_cards);
new->card = card->card;
list_add_tail(&new->list, &hash->players[i]);
}
}
return hash;
}
static player_t *create_subgame(player_t *from, player_t *to)
{
struct card *card;
for (int i = 0; i < 2; ++i) {
int n = 0, ncards;
to[i].ncards = from[i].ncards - 1;
INIT_LIST_HEAD(&to[i].head);
list_for_each_entry(card, &from[i].head, list) {
if (!n) {
to[i].ncards = ncards = card->card;
} else {
struct card *new = pool_get(pool_cards);
new->card = card->card;
list_add_tail(&new->list, &to[i].head);
if (!--ncards)
break;
}
n++;
}
}
return to;
}
/**
* find_deck - find deck in an hashtable bucket
*/
static hash_t *find_deck(struct hlist_head *hasht, player_t *players)
{
hash_t *cur;
u32 z = zobrist(players);
u32 h = hash(z);
hlist_for_each_entry(cur, hasht + h, hlist) {
if (cur->zobrist == z && equal_decks(cur, players))
return cur;
}
cur = create_hash(players, z);
hlist_add_head(&cur->hlist, &hasht[h]);
return NULL;
}
static player_t *parse(player_t *players)
{
size_t alloc;
ssize_t len;
char *buf = NULL;
int player = 0;
struct card *card;
INIT_LIST_HEAD(&players[0].head);
INIT_LIST_HEAD(&players[1].head);
players[0].ncards = players[1].ncards = 0;
while ((len = getline(&buf, &alloc, stdin)) > 0) {
buf[--len] = 0;
if (len == 0) {
player++;
continue;
}
if (isdigit(*buf)) { /* card */
card = pool_get(pool_cards);
card->card = atoi(buf);
players[player].ncards++;
list_add_tail(&card->list, &players[player].head);
}
}
free(buf);
return players;
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
return 1;
}
static void winmove(player_t *winner, player_t *loser)
{
card_t *win, *lose;
win = list_first_entry(&winner->head, struct card, list);
lose = list_first_entry(&loser->head, struct card, list);
list_move_tail(&win->list, &winner->head);
list_move_tail(&lose->list, &winner->head);
loser->ncards--;
winner->ncards++;
}
static long calc_result(player_t *players)
{
/* we don't need to check for winner, as one list is empty */
card_t *card;
long res = 0, mult = 1;
list_for_each_entry_reverse(card, &players[0].head, list)
res += card->card * mult++;
list_for_each_entry_reverse(card, &players[1].head, list)
res += card->card * mult++;
return res;
}
static long part1(player_t *players)
{
int round = 0, winner = 0;
while (players[0].ncards > 0 && players[1].ncards > 0) {
int val[2];
/* we can use list_first_entry() macro, as both lists are not empty */
val[0] = list_first_entry(&players[0].head, struct card, list)->card;
val[1] = list_first_entry(&players[1].head, struct card, list)->card;
winner = val[1] > val[0];
winmove(players + winner, players + 1 - winner);
round++;
}
return calc_result(players);
}
static long part2(player_t *players)
{
int round = 1, winner = 0, game;
long res = 0;
static int maxgame = 0;
DEFINE_HASHTABLE(hasht_deck, HBITS); /* htable for dup decks */
game = ++maxgame;
while (players[0].ncards > 0 && players[1].ncards > 0) {
int val[2];
winner = 0;
if (find_deck(hasht_deck, players)) /* duplicate */
goto end;
/* we can use list_first_entry() macro, as both lists are not empty */
val[0] = list_first_entry(&players[0].head, struct card, list)->card;
val[1] = list_first_entry(&players[1].head, struct card, list)->card;
if (players[0].ncards > val[0] && players[1].ncards > val[1]) {
player_t sub[2];
winner = part2(create_subgame(players, sub));
} else {
winner = val[1] > val[0];
}
winmove(players + winner, players + 1 - winner);
round++;
}
end:
if (game == 1)
res = calc_result(players);
/* cleanup decks */
card_t *card, *tmp1;
for (int i = 0; i < 2; ++i) {
list_for_each_entry_safe(card, tmp1, &players[i].head, list) {
list_del(&card->list);
pool_add(pool_cards, card);
}
}
/* cleanup hashtable */
ulong bkt;
struct hlist_node *tmp2;
hash_t *obj;
hash_for_each_safe(hasht_deck, bkt, tmp2, obj, hlist) {
/* cleanup hash decks */
for (int i = 0; i < 2; ++i) {
list_for_each_entry_safe(card, tmp1, &obj->players[i], list) {
list_del(&card->list);
pool_add(pool_cards, card);
}
}
hlist_del(&obj->hlist);
pool_add(pool_hash, obj);
}
return game == 1? res: winner;
}
int main(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)
default:
return usage(*av);
}
}
pool_cards = pool_create("cards", 4096, sizeof(struct card));
pool_hash = pool_create("hash", 128, sizeof(struct hash));
zobrist_init();
player_t players[2];
parse(players);
long res = part == 1 ? part1(players): part2(players);
printf("%s : res=%ld\n", *av, res);
pool_destroy(pool_hash);
pool_destroy(pool_cards);
exit(0);
}

115
2020/day23/aoc-c.c Normal file
View File

@@ -0,0 +1,115 @@
/* aoc-c.c: Advent2020, day 23, part 1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "list.h"
#include "debug.h"
/* Here we will simply use an array for the numbers (as key is the number
* itself). All elements make a next/prev ring.
* Note: we will ignore array[0] to avoid millions of useless "position -1"
* calculations
*/
struct list_head *curcup; /* current cup */
struct list_head *cups; /* the cups cups */
int lastnum; /* last cup number */
#define CUR_CUP (&*curcup)
#define NUM(pcup) ((pcup) - cups)
static __always_inline void step()
{
struct list_head *first, *last, *dest = CUR_CUP;
int num[3] = { 0 };
first = CUR_CUP->next;
last = first->next->next;
num[0] = NUM(first);
num[1] = NUM(first->next);
num[2] = NUM(last);
do {
if (NUM(--dest) <= 0)
dest = &cups[lastnum];
} while (NUM(dest) == num[0] || NUM(dest) == num[1] || NUM(dest) == num[2]);
list_bulk_move(dest, first, last);
curcup = CUR_CUP->next;
}
/**
* parse - initialize cups list.
*/
static void parse(int last)
{
int count = 0, c;
cups = malloc(sizeof(struct list_head) * (last + 1));
if (cups) {
for (c = getchar(); isdigit(c); c = getchar(), ++count) {
struct list_head *next = &cups[c - '0'];
if (!count) /* first cup */
INIT_LIST_HEAD(curcup = next);
else
list_add_tail(&cups[c - '0'], CUR_CUP);
}
for (++count; count <= last; ++count) /* add remaining cups */
list_add_tail(&cups[count], CUR_CUP);
}
}
static long part1()
{
struct list_head *cur;
int res = 0;
list_for_each(cur, &cups[1]) {
res = res * 10 + NUM(cur);
}
return res;
}
static long part2()
{
return NUM((&cups[1])->next) * NUM((&cups[1])->next->next);
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
return 1;
}
int main(ac, av)
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)
default:
return usage(*av);
}
}
lastnum = part == 1? 9: 1000000;
int loops = part == 1? 100: 10000000;
parse(lastnum);
for (int i = 0; i < loops; ++i)
step();
printf("%s : res=%ld\n", *av, part == 1? part1(): part2());
free(cups);
exit (0);
}

View File

@@ -1,4 +1,4 @@
/* ex1-c: Advent2020, day 24/part 1
/* aoc-c.c: Advent2020, day 24, parts 1 and 2
*/
#include <stdio.h>

View File

@@ -10,8 +10,8 @@
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*
*/
#ifndef BITS_H
#define BITS_H
#ifndef _BITS_H
#define _BITS_H
#include <stdint.h>
#include <stdbool.h>
@@ -26,9 +26,11 @@
/* no plan to support 32bits for now...
*/
/*
#if __WORDSIZE != 64
#error "Only 64 bits word size supported."
#endif
*/
/* fixed-size types
*/
@@ -49,6 +51,51 @@ typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned char uchar;
/* count set bits: 10101000 -> 3
* ^ ^ ^
*/
static __always_inline int popcount64(u64 n)
{
# if __has_builtin(__builtin_popcountl)
# ifdef DEBUG_BITS
log_f(1, "builtin.\n");
# endif
return __builtin_popcountl(n);
# else
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
int count = 0;
while (n) {
count++;
n &= (n - 1);
}
return count;
# endif
}
static __always_inline int popcount32(u32 n)
{
# if __has_builtin(__builtin_popcount)
# ifdef DEBUG_BITS
log_f(1, "builtin.\n");
# endif
return __builtin_popcount(n);
# else
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
int count = 0;
while (n) {
count++;
n &= (n - 1);
}
return count;
# endif
}
/* char is a special case, as it can be signed or unsigned
*/
typedef signed char schar;
@@ -74,7 +121,7 @@ static __always_inline int ctz64(u64 n)
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
return popcount64((n & n) 1);
return popcount64((n & -n) - 1);
# endif
}
@@ -96,7 +143,7 @@ static __always_inline int ctz32(u32 n)
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
return popcount32((n & n) 1);
return popcount32((n & -n) - 1);
# endif
}
@@ -218,51 +265,6 @@ static __always_inline uint ffs32(u32 n)
# endif
}
/* count set bits: 10101000 -> 3
* ^ ^ ^
*/
static __always_inline int popcount64(u64 n)
{
# if __has_builtin(__builtin_popcountl)
# ifdef DEBUG_BITS
log_f(1, "builtin.\n");
# endif
return __builtin_popcountl(n);
# else
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
int count = 0;
while (n) {
count++;
n &= (n - 1);
}
return count;
# endif
}
static __always_inline int popcount32(u32 n)
{
# if __has_builtin(__builtin_popcount)
# ifdef DEBUG_BITS
log_f(1, "builtin.\n");
# endif
return __builtin_popcount(n);
# else
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
int count = 0;
while (n) {
count++;
n &= (n - 1);
}
return count;
# endif
}
/* rolXX are taken from kernel's <linux/bitops.h> are are:
* SPDX-License-Identifier: GPL-2.0
*/
@@ -518,4 +520,4 @@ int __bits_per(unsigned long n)
#define bit_for_each32_2(pos, tmp, ul) \
for (tmp = ul, pos = ctz32(tmp); tmp; tmp ^= 1U << pos, pos = ctz32(tmp))
#endif /* BITS_H */
#endif /* _BITS_H */

View File

@@ -1,4 +1,4 @@
/* bits.h - bits functions.
/* br.h - misc macros.
*
* Copyright (C) 2021-2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
@@ -18,12 +18,18 @@
#ifndef _BR_H
#define _BR_H
/* Indirect stringification. Doing two levels allows the parameter to be a
* macro itself. For example, compile with -DFOO=bar, __stringify(FOO)
* converts to "bar".
*/
#define __stringify_1(x...) #x
#define __stringify(x...) __stringify_1(x)
/* generate a (maybe) unique id.
*/
#define ___PASTE(x, y) x##y
#define __PASTE(x, y) ___PASTE(x, y)
#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
//__##prefix##__COUNTER__
/* see https://lkml.org/lkml/2018/3/20/845 for explanation of this monster
*/

View File

@@ -229,6 +229,29 @@ static inline void list_move_tail(struct list_head *list,
list_add_tail(list, head);
}
/**
* list_bulk_move - move a subsection of a list to its head
* @head: the head that our entry will follow
* @first: first entry to move
* @last: last entry to move, can be the same as first
*
* Move all entries between @first and including @last after @head.
* All three entries must belong to the same linked list.
*/
static inline void list_bulk_move(struct list_head *head,
struct list_head *first,
struct list_head *last)
{
first->prev->next = last->next;
last->next->prev = first->prev;
last->next = head->next;
head->next->prev = last;
head->next = first;
first->prev = head;
}
/**
* list_bulk_move_tail - move a subsection of a list to its tail
* @head: the head that will follow our entry

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.
*
@@ -19,12 +19,14 @@
#define DEBUG_DEBUG
#endif
#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 s64 timer_start; /* in nanosecond */
static long long timer_start; /* in nanosecond */
static u32 debug_level=0;
void debug_level_set(u32 level)
@@ -40,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;
@@ -48,15 +50,14 @@ void debug_init(u32 level)
log(0, "timer started.\n");
}
inline static s64 timer_elapsed()
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)
@@ -75,9 +76,9 @@ void debug(u32 level, bool timestamp, u32 indent, const char *src,
printf("%*s", 2*(indent-1), "");
if (timestamp) {
s64 diff = timer_elapsed();
printf("%ld.%03ld ", diff/NANOSEC, (diff/1000000)%1000);
printf("%010ld ", diff);
long long diff = timer_elapsed();
printf("%lld.%03lld ", diff / NS_SEC, (diff % NS_SEC) / NS_MS);
printf("%010lldμs ", diff / NS_MS);
}
if (src) {

View File

@@ -1,6 +1,6 @@
/* pool.c - A simple pool manager.
*
* 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.
*
@@ -25,18 +25,16 @@
void pool_stats(pool_t *pool)
{
if (pool) {
# ifdef DEBUG_POOL
block_t *block;
log_f(1, "[%s] pool [%p]: blocks:%u avail:%u alloc:%u grow:%u eltsize:%lu\n",
pool->name, (void *)pool, pool->nblocks, pool->available, pool->allocated,
pool->growsize, pool->eltsize);
log_f(1, "[%s] pool [%p]: blocks:%u avail:%u alloc:%u grow:%u eltsize:%zu\n",
pool->name, (void *)pool, pool->nblocks, pool->available,
pool->allocated, pool->growsize, pool->eltsize);
log(5, "\tblocks: ");
list_for_each_entry(block, &pool->list_blocks, list_blocks) {
log(5, "%p ", block);
}
log(5, "\n");
# endif
}
}
@@ -45,14 +43,13 @@ pool_t *pool_create(const char *name, u32 growsize, size_t eltsize)
pool_t *pool;
# ifdef DEBUG_POOL
log_f(1, "name=[%s] growsize=%u eltsize=%lu\n",
name, growsize, eltsize);
log_f(1, "name=[%s] growsize=%u eltsize=%zu\n", name, growsize, eltsize);
# endif
/* we need at least sizeof(struct list_head) space in pool elements
*/
if (eltsize < sizeof (struct list_head)) {
# ifdef DEBUG_POOL
log_f(1, "[%s]: structure size too small (%lu < %lu), adjusting to %lu.\n",
log_f(1, "[%s]: structure size too small (%zu < %zu), adjusting to %zu.\n",
name, eltsize, sizeof(struct list_head), sizeof(struct list_head));
# endif
eltsize = sizeof(struct list_head);
@@ -67,6 +64,8 @@ pool_t *pool_create(const char *name, u32 growsize, size_t eltsize)
pool->nblocks = 0;
INIT_LIST_HEAD(&pool->list_available);
INIT_LIST_HEAD(&pool->list_blocks);
} else {
errno = ENOMEM;
}
return pool;
}
@@ -74,11 +73,9 @@ pool_t *pool_create(const char *name, u32 growsize, size_t eltsize)
static u32 _pool_add(pool_t *pool, struct list_head *elt)
{
# ifdef DEBUG_POOL
log_f(6, "pool=%p &head=%p elt=%p off1=%lu off2=%lu\n",
(void *)pool,
(void *)&pool->list_available,
(void *)elt,
(void *)&pool->list_available-(void *)pool,
log_f(6, "pool=%p &head=%p elt=%p off1=%zu off2=%zu\n",
(void *)pool, (void *)&pool->list_available, (void *)elt,
(void *)&pool->list_available - (void *)pool,
offsetof(pool_t, list_available));
# endif
@@ -105,9 +102,6 @@ void *pool_get(pool_t *pool)
return NULL;
if (!pool->available) {
block_t *block = malloc(sizeof(block_t) + pool->eltsize * pool->growsize);
void *cur;
u32 i;
if (!block) {
# ifdef DEBUG_POOL
log_f(1, "[%s]: failed block allocation\n", pool->name);
@@ -131,16 +125,15 @@ void *pool_get(pool_t *pool)
# endif
pool->allocated += pool->growsize;
for (i = 0; i < pool->growsize; ++i) {
cur = block->data + i * pool->eltsize;
for (u32 i = 0; i < pool->growsize; ++i) {
void *cur = block->data + i * pool->eltsize;
# ifdef DEBUG_POOL
log_f(7, "alloc=%p cur=%p\n", block, cur);
# endif
_pool_add(pool, (struct list_head *)cur);
}
//pool_stats(pool);
}
/* this is the effective address if the object (and also the
/* this is the effective address of the object (and also the
* pool list_head address)
*/
return _pool_get(pool);
@@ -157,11 +150,11 @@ void pool_destroy(pool_t *pool)
log(5, "blocks:");
# endif
list_for_each_entry_safe(block, tmp, &pool->list_blocks, list_blocks) {
list_del(&block->list_blocks);
free(block);
# ifdef DEBUG_POOL
log(5, " %p", block);
# endif
list_del(&block->list_blocks);
free(block);
}
# ifdef DEBUG_POOL
log(5, "\n");
@@ -221,5 +214,6 @@ int main(int ac, char**av)
}
}
pool_stats(pool);
pool_destroy(pool);
}
#endif

View File

@@ -1,500 +0,0 @@
/*
* xxHash - Extremely Fast Hash algorithm
* Copyright (C) 2012-2016, Yann Collet.
*
* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation. This program is dual-licensed; you may select
* either version 2 of the GNU General Public License ("GPL") or BSD license
* ("BSD").
*
* You can contact the author at:
* - xxHash homepage: https://cyan4973.github.io/xxHash/
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
#include <asm/unaligned.h>
#include <linux/errno.h>
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/xxhash.h>
/*-*************************************
* Macros
**************************************/
#define xxh_rotl32(x, r) ((x << r) | (x >> (32 - r)))
#define xxh_rotl64(x, r) ((x << r) | (x >> (64 - r)))
#ifdef __LITTLE_ENDIAN
# define XXH_CPU_LITTLE_ENDIAN 1
#else
# define XXH_CPU_LITTLE_ENDIAN 0
#endif
/*-*************************************
* Constants
**************************************/
static const uint32_t PRIME32_1 = 2654435761U;
static const uint32_t PRIME32_2 = 2246822519U;
static const uint32_t PRIME32_3 = 3266489917U;
static const uint32_t PRIME32_4 = 668265263U;
static const uint32_t PRIME32_5 = 374761393U;
static const uint64_t PRIME64_1 = 11400714785074694791ULL;
static const uint64_t PRIME64_2 = 14029467366897019727ULL;
static const uint64_t PRIME64_3 = 1609587929392839161ULL;
static const uint64_t PRIME64_4 = 9650029242287828579ULL;
static const uint64_t PRIME64_5 = 2870177450012600261ULL;
/*-**************************
* Utils
***************************/
void xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src)
{
memcpy(dst, src, sizeof(*dst));
}
EXPORT_SYMBOL(xxh32_copy_state);
void xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src)
{
memcpy(dst, src, sizeof(*dst));
}
EXPORT_SYMBOL(xxh64_copy_state);
/*-***************************
* Simple Hash Functions
****************************/
static uint32_t xxh32_round(uint32_t seed, const uint32_t input)
{
seed += input * PRIME32_2;
seed = xxh_rotl32(seed, 13);
seed *= PRIME32_1;
return seed;
}
uint32_t xxh32(const void *input, const size_t len, const uint32_t seed)
{
const uint8_t *p = (const uint8_t *)input;
const uint8_t *b_end = p + len;
uint32_t h32;
if (len >= 16) {
const uint8_t *const limit = b_end - 16;
uint32_t v1 = seed + PRIME32_1 + PRIME32_2;
uint32_t v2 = seed + PRIME32_2;
uint32_t v3 = seed + 0;
uint32_t v4 = seed - PRIME32_1;
do {
v1 = xxh32_round(v1, get_unaligned_le32(p));
p += 4;
v2 = xxh32_round(v2, get_unaligned_le32(p));
p += 4;
v3 = xxh32_round(v3, get_unaligned_le32(p));
p += 4;
v4 = xxh32_round(v4, get_unaligned_le32(p));
p += 4;
} while (p <= limit);
h32 = xxh_rotl32(v1, 1) + xxh_rotl32(v2, 7) +
xxh_rotl32(v3, 12) + xxh_rotl32(v4, 18);
} else {
h32 = seed + PRIME32_5;
}
h32 += (uint32_t)len;
while (p + 4 <= b_end) {
h32 += get_unaligned_le32(p) * PRIME32_3;
h32 = xxh_rotl32(h32, 17) * PRIME32_4;
p += 4;
}
while (p < b_end) {
h32 += (*p) * PRIME32_5;
h32 = xxh_rotl32(h32, 11) * PRIME32_1;
p++;
}
h32 ^= h32 >> 15;
h32 *= PRIME32_2;
h32 ^= h32 >> 13;
h32 *= PRIME32_3;
h32 ^= h32 >> 16;
return h32;
}
EXPORT_SYMBOL(xxh32);
static uint64_t xxh64_round(uint64_t acc, const uint64_t input)
{
acc += input * PRIME64_2;
acc = xxh_rotl64(acc, 31);
acc *= PRIME64_1;
return acc;
}
static uint64_t xxh64_merge_round(uint64_t acc, uint64_t val)
{
val = xxh64_round(0, val);
acc ^= val;
acc = acc * PRIME64_1 + PRIME64_4;
return acc;
}
uint64_t xxh64(const void *input, const size_t len, const uint64_t seed)
{
const uint8_t *p = (const uint8_t *)input;
const uint8_t *const b_end = p + len;
uint64_t h64;
if (len >= 32) {
const uint8_t *const limit = b_end - 32;
uint64_t v1 = seed + PRIME64_1 + PRIME64_2;
uint64_t v2 = seed + PRIME64_2;
uint64_t v3 = seed + 0;
uint64_t v4 = seed - PRIME64_1;
do {
v1 = xxh64_round(v1, get_unaligned_le64(p));
p += 8;
v2 = xxh64_round(v2, get_unaligned_le64(p));
p += 8;
v3 = xxh64_round(v3, get_unaligned_le64(p));
p += 8;
v4 = xxh64_round(v4, get_unaligned_le64(p));
p += 8;
} while (p <= limit);
h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) +
xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18);
h64 = xxh64_merge_round(h64, v1);
h64 = xxh64_merge_round(h64, v2);
h64 = xxh64_merge_round(h64, v3);
h64 = xxh64_merge_round(h64, v4);
} else {
h64 = seed + PRIME64_5;
}
h64 += (uint64_t)len;
while (p + 8 <= b_end) {
const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p));
h64 ^= k1;
h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4;
p += 8;
}
if (p + 4 <= b_end) {
h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1;
h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
p += 4;
}
while (p < b_end) {
h64 ^= (*p) * PRIME64_5;
h64 = xxh_rotl64(h64, 11) * PRIME64_1;
p++;
}
h64 ^= h64 >> 33;
h64 *= PRIME64_2;
h64 ^= h64 >> 29;
h64 *= PRIME64_3;
h64 ^= h64 >> 32;
return h64;
}
EXPORT_SYMBOL(xxh64);
/*-**************************************************
* Advanced Hash Functions
***************************************************/
void xxh32_reset(struct xxh32_state *statePtr, const uint32_t seed)
{
/* use a local state for memcpy() to avoid strict-aliasing warnings */
struct xxh32_state state;
memset(&state, 0, sizeof(state));
state.v1 = seed + PRIME32_1 + PRIME32_2;
state.v2 = seed + PRIME32_2;
state.v3 = seed + 0;
state.v4 = seed - PRIME32_1;
memcpy(statePtr, &state, sizeof(state));
}
EXPORT_SYMBOL(xxh32_reset);
void xxh64_reset(struct xxh64_state *statePtr, const uint64_t seed)
{
/* use a local state for memcpy() to avoid strict-aliasing warnings */
struct xxh64_state state;
memset(&state, 0, sizeof(state));
state.v1 = seed + PRIME64_1 + PRIME64_2;
state.v2 = seed + PRIME64_2;
state.v3 = seed + 0;
state.v4 = seed - PRIME64_1;
memcpy(statePtr, &state, sizeof(state));
}
EXPORT_SYMBOL(xxh64_reset);
int xxh32_update(struct xxh32_state *state, const void *input, const size_t len)
{
const uint8_t *p = (const uint8_t *)input;
const uint8_t *const b_end = p + len;
if (input == NULL)
return -EINVAL;
state->total_len_32 += (uint32_t)len;
state->large_len |= (len >= 16) | (state->total_len_32 >= 16);
if (state->memsize + len < 16) { /* fill in tmp buffer */
memcpy((uint8_t *)(state->mem32) + state->memsize, input, len);
state->memsize += (uint32_t)len;
return 0;
}
if (state->memsize) { /* some data left from previous update */
const uint32_t *p32 = state->mem32;
memcpy((uint8_t *)(state->mem32) + state->memsize, input,
16 - state->memsize);
state->v1 = xxh32_round(state->v1, get_unaligned_le32(p32));
p32++;
state->v2 = xxh32_round(state->v2, get_unaligned_le32(p32));
p32++;
state->v3 = xxh32_round(state->v3, get_unaligned_le32(p32));
p32++;
state->v4 = xxh32_round(state->v4, get_unaligned_le32(p32));
p32++;
p += 16-state->memsize;
state->memsize = 0;
}
if (p <= b_end - 16) {
const uint8_t *const limit = b_end - 16;
uint32_t v1 = state->v1;
uint32_t v2 = state->v2;
uint32_t v3 = state->v3;
uint32_t v4 = state->v4;
do {
v1 = xxh32_round(v1, get_unaligned_le32(p));
p += 4;
v2 = xxh32_round(v2, get_unaligned_le32(p));
p += 4;
v3 = xxh32_round(v3, get_unaligned_le32(p));
p += 4;
v4 = xxh32_round(v4, get_unaligned_le32(p));
p += 4;
} while (p <= limit);
state->v1 = v1;
state->v2 = v2;
state->v3 = v3;
state->v4 = v4;
}
if (p < b_end) {
memcpy(state->mem32, p, (size_t)(b_end-p));
state->memsize = (uint32_t)(b_end-p);
}
return 0;
}
EXPORT_SYMBOL(xxh32_update);
uint32_t xxh32_digest(const struct xxh32_state *state)
{
const uint8_t *p = (const uint8_t *)state->mem32;
const uint8_t *const b_end = (const uint8_t *)(state->mem32) +
state->memsize;
uint32_t h32;
if (state->large_len) {
h32 = xxh_rotl32(state->v1, 1) + xxh_rotl32(state->v2, 7) +
xxh_rotl32(state->v3, 12) + xxh_rotl32(state->v4, 18);
} else {
h32 = state->v3 /* == seed */ + PRIME32_5;
}
h32 += state->total_len_32;
while (p + 4 <= b_end) {
h32 += get_unaligned_le32(p) * PRIME32_3;
h32 = xxh_rotl32(h32, 17) * PRIME32_4;
p += 4;
}
while (p < b_end) {
h32 += (*p) * PRIME32_5;
h32 = xxh_rotl32(h32, 11) * PRIME32_1;
p++;
}
h32 ^= h32 >> 15;
h32 *= PRIME32_2;
h32 ^= h32 >> 13;
h32 *= PRIME32_3;
h32 ^= h32 >> 16;
return h32;
}
EXPORT_SYMBOL(xxh32_digest);
int xxh64_update(struct xxh64_state *state, const void *input, const size_t len)
{
const uint8_t *p = (const uint8_t *)input;
const uint8_t *const b_end = p + len;
if (input == NULL)
return -EINVAL;
state->total_len += len;
if (state->memsize + len < 32) { /* fill in tmp buffer */
memcpy(((uint8_t *)state->mem64) + state->memsize, input, len);
state->memsize += (uint32_t)len;
return 0;
}
if (state->memsize) { /* tmp buffer is full */
uint64_t *p64 = state->mem64;
memcpy(((uint8_t *)p64) + state->memsize, input,
32 - state->memsize);
state->v1 = xxh64_round(state->v1, get_unaligned_le64(p64));
p64++;
state->v2 = xxh64_round(state->v2, get_unaligned_le64(p64));
p64++;
state->v3 = xxh64_round(state->v3, get_unaligned_le64(p64));
p64++;
state->v4 = xxh64_round(state->v4, get_unaligned_le64(p64));
p += 32 - state->memsize;
state->memsize = 0;
}
if (p + 32 <= b_end) {
const uint8_t *const limit = b_end - 32;
uint64_t v1 = state->v1;
uint64_t v2 = state->v2;
uint64_t v3 = state->v3;
uint64_t v4 = state->v4;
do {
v1 = xxh64_round(v1, get_unaligned_le64(p));
p += 8;
v2 = xxh64_round(v2, get_unaligned_le64(p));
p += 8;
v3 = xxh64_round(v3, get_unaligned_le64(p));
p += 8;
v4 = xxh64_round(v4, get_unaligned_le64(p));
p += 8;
} while (p <= limit);
state->v1 = v1;
state->v2 = v2;
state->v3 = v3;
state->v4 = v4;
}
if (p < b_end) {
memcpy(state->mem64, p, (size_t)(b_end-p));
state->memsize = (uint32_t)(b_end - p);
}
return 0;
}
EXPORT_SYMBOL(xxh64_update);
uint64_t xxh64_digest(const struct xxh64_state *state)
{
const uint8_t *p = (const uint8_t *)state->mem64;
const uint8_t *const b_end = (const uint8_t *)state->mem64 +
state->memsize;
uint64_t h64;
if (state->total_len >= 32) {
const uint64_t v1 = state->v1;
const uint64_t v2 = state->v2;
const uint64_t v3 = state->v3;
const uint64_t v4 = state->v4;
h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) +
xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18);
h64 = xxh64_merge_round(h64, v1);
h64 = xxh64_merge_round(h64, v2);
h64 = xxh64_merge_round(h64, v3);
h64 = xxh64_merge_round(h64, v4);
} else {
h64 = state->v3 + PRIME64_5;
}
h64 += (uint64_t)state->total_len;
while (p + 8 <= b_end) {
const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p));
h64 ^= k1;
h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4;
p += 8;
}
if (p + 4 <= b_end) {
h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1;
h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
p += 4;
}
while (p < b_end) {
h64 ^= (*p) * PRIME64_5;
h64 = xxh_rotl64(h64, 11) * PRIME64_1;
p++;
}
h64 ^= h64 >> 33;
h64 *= PRIME64_2;
h64 ^= h64 >> 29;
h64 *= PRIME64_3;
h64 ^= h64 >> 32;
return h64;
}
EXPORT_SYMBOL(xxh64_digest);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("xxHash");

87
2022/Makefile Normal file
View File

@@ -0,0 +1,87 @@
# AOC Makefile - GNU make only.
#
# Copyright (C) 2021-2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
SUBDIRS := $(shell echo day??)
CC = gcc
#LIBS = -lreadline -lncurses
CFLAGS += -std=gnu11
CFLAGS += -O2
CFLAGS += -g
#CFLAGS += -pg
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -march=native
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
CFLAGS += -DDEBUG_POOL # memory pools management
INCDIR := ./include
LIBSRCDIR := ./libsrc
LIBDIR := ./lib
LIB := libaoc_$(shell uname -m)
SLIB := $(LIBDIR)/$(LIB).a
DLIB := $(LIBDIR)/$(LIB).so
LIBSRC := $(wildcard $(LIBSRCDIR)/*.c)
LIBOBJ := $(patsubst %.c,%.o,$(LIBSRC))
LDFLAGS := -L$(LIBDIR)
LDLIB := -l$(LIB)
.PHONY: clean cleanlib cleanall all redo output lib $(SUBDIRS)
all: lib $(SUBDIRS)
clean:
@for dir in $(SUBDIRS) ; do \
$(MAKE) --no-print-directory -C $$dir clean ; \
done
cleanlib: clean
@$(RM) -f $(SLIB) $(DLIB) $(LIBOBJ)
cleanall: clean cleanlib
redo: cleanall all
$(SUBDIRS):
@echo "========================================="
@echo "================= $@ ================="
@echo "========================================="
@echo
@echo "+++++++++++++++++ part 1"
+@$(MAKE) --no-print-directory -C $@ part1 2>&1
@echo "+++++++++++++++++ part 2"
+@$(MAKE) --no-print-directory -C $@ part2 2>&1
output:
@$(MAKE) --no-print-directory all >OUTPUT 2>&1
lib: $(DLIB) $(SLIB)
$(SLIB): $(LIBOBJ)
@echo building $@ static library.
@mkdir -p $(LIBDIR)
@$(AR) $(ARFLAGS) -o $@ $^
$(DLIB): CFLAGS += -fPIC
$(DLIB): LDFLAGS += -shared
$(DLIB): $(LIBOBJ)
@echo building $@ shared library.
@mkdir -p $(LIBDIR)
@$(CC) $(LDFLAGS) $^ -o $@
.c.o:
@echo compiling $<.
@$(CC) -c $(CFLAGS) $(LDFLAGS) -I $(INCDIR) -o $@ $<

317
2022/RESULTS.txt Normal file
View File

@@ -0,0 +1,317 @@
=========================================
================= day01 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=66719
time: 0:00.03 real, 0.02 user, 0.00 sys
context-switch: 0+1, page-faults: 0+257
aoc-c: res=66719
time: 0:00.00 real, 0.00 user, 0.00 sys
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+259
aoc-c: res=198551
time: 0:00.00 real, 0.00 user, 0.00 sys
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

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

89
2022/day01/README.org Normal file
View File

@@ -0,0 +1,89 @@
** --- Day 1: Calorie Counting ---
Santa's reindeer typically eat regular reindeer food, but they need a
lot of [[/2018/day/25][magical energy]] to deliver presents on
Christmas. For that, their favorite snack is a special type of /star/
fruit that only grows deep in the jungle. The Elves have brought you on
their annual expedition to the grove where the fruit grows.
To supply enough magical energy, the expedition needs to retrieve a
minimum of /fifty stars/ by December 25th. Although the Elves assure you
that the grove has plenty of fruit, you decide to grab any fruit you see
along the way, just in case.
Collect stars by solving puzzles. Two puzzles will be made available on
each day in the Advent calendar; the second puzzle is unlocked when you
complete the first. Each puzzle grants /one star/. Good luck!
The jungle must be too overgrown and difficult to navigate in vehicles
or access from the air; the Elves' expedition traditionally goes on
foot. As your boats approach land, the Elves begin taking inventory of
their supplies. One important consideration is food - in particular, the
number of /Calories/ each Elf is carrying (your puzzle input).
The Elves take turns writing down the number of Calories contained by
the various meals, snacks, rations, etc. that they've brought with them,
one item per line. Each Elf separates their own inventory from the
previous Elf's inventory (if any) by a blank line.
For example, suppose the Elves finish writing their items' Calories and
end up with the following list:
#+begin_example
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
#+end_example
This list represents the Calories of the food carried by five Elves:
- The first Elf is carrying food with =1000=, =2000=, and =3000=
Calories, a total of =6000= Calories.
- The second Elf is carrying one food item with =4000= Calories.
- The third Elf is carrying food with =5000= and =6000= Calories, a
total of =11000= Calories.
- The fourth Elf is carrying food with =7000=, =8000=, and =9000=
Calories, a total of =24000= Calories.
- The fifth Elf is carrying one food item with =10000= Calories.
In case the Elves get hungry and need extra snacks, they need to know
which Elf to ask: they'd like to know how many Calories are being
carried by the Elf carrying the /most/ Calories. In the example above,
this is /=24000=/ (carried by the fourth Elf).
Find the Elf carrying the most Calories. /How many total Calories is
that Elf carrying?/
Your puzzle answer was =66719=.
** --- Part Two ---
By the time you calculate the answer to the Elves' question, they've
already realized that the Elf carrying the most Calories of food might
eventually /run out of snacks/.
To avoid this unacceptable situation, the Elves would instead like to
know the total Calories carried by the /top three/ Elves carrying the
most Calories. That way, even if one of those Elves runs out of snacks,
they still have two backups.
In the example above, the top three Elves are the fourth Elf (with
=24000= Calories), then the third Elf (with =11000= Calories), then the
fifth Elf (with =10000= Calories). The sum of the Calories carried by
these three elves is =45000=.
Find the top three Elves carrying the most Calories. /How many Calories
are those Elves carrying in total?/
Your puzzle answer was =198551=.
Both parts of this puzzle are complete! They provide two gold stars: **

77
2022/day01/aoc-c.c Normal file
View File

@@ -0,0 +1,77 @@
/* aoc-c.c: Advent of Code 2022, day 1
*
* 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"
PLIST_HEAD(plist);
static int calc_top_plist(int n)
{
int res = 0;
struct plist_node *node;
plist_for_each_reverse(node, &plist) {
res += node->prio;
if (!--n)
break;
}
return res;
}
static void parse(pool_t *pool)
{
size_t alloc = 0;
char *buf = NULL;
ssize_t buflen;
int total = 0;
struct plist_node *node;
while (1) {
buflen = getline(&buf, &alloc, stdin);
switch (buflen) {
case 1:
case -1: /* EOF */
node = pool_get(pool);
plist_node_init(node, total);
plist_add(node, &plist);
total = 0;
if (buflen == -1)
goto end;
break;
default:
total += atoi(buf);
}
}
end:
free(buf);
return;
}
int main(int ac, char **av)
{
int part = parseargs(ac, 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));
pool_destroy(pool_tot);
exit(0);
}

56
2022/day01/aoc.bash Executable file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 1
#
# 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 elf
declare -i maxwanted=3
parse() {
local -i tot=0 i res
while true; do
read -r line
res=$?
# number found: sum & continue
[[ -n $line ]] && (( tot += line)) && continue
# first elf: we set it and continue
(( !${#elf[@]} )) && (( elf[0] = tot )) && continue
# find a place to (maybe) insert new high (keep array sorted)
for (( i = 0; i < ${#elf[@]}; ++i )); do
if (( tot > elf[i] )); then # normal insert (tot > old value)
elf=( "${elf[@]:0:i}" "$tot" "${elf[@]:i}" )
break
elif (( i == ${#elf[@]}-1 )); then # insert at end
elf+=( "$tot" )
break
fi
done
# keep array size <= maxwanted
elf=( "${elf[@]:0:maxwanted}" )
(( tot = 0 ))
((res > 0)) && break # EOF
done
}
solve() {
local -i part="$1"
if ((part == 1)); then
(( res = elf[0] ))
else
(( res = elf[0] + elf[1] + elf[2] ))
fi
}
main "$@"
exit 0

17
2022/day01/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/day01/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/day01/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,14 @@
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000

2255
2022/day01/input/input.txt Normal file

File diff suppressed because it is too large Load Diff

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

89
2022/day02/README.org Normal file
View File

@@ -0,0 +1,89 @@
** --- Day 2: Rock Paper Scissors ---
The Elves begin to set up camp on the beach. To decide whose tent gets
to be closest to the snack storage, a giant
[[https://en.wikipedia.org/wiki/Rock_paper_scissors][Rock Paper
Scissors]] tournament is already in progress.
Rock Paper Scissors is a game between two players. Each game contains
many rounds; in each round, the players each simultaneously choose one
of Rock, Paper, or Scissors using a hand shape. Then, a winner for that
round is selected: Rock defeats Scissors, Scissors defeats Paper, and
Paper defeats Rock. If both players choose the same shape, the round
instead ends in a draw.
Appreciative of your help yesterday, one Elf gives you an /encrypted
strategy guide/ (your puzzle input) that they say will be sure to help
you win. "The first column is what your opponent is going to play: =A=
for Rock, =B= for Paper, and =C= for Scissors. The second column--"
Suddenly, the Elf is called away to help with someone's tent.
The second column, you reason, must be what you should play in response:
=X= for Rock, =Y= for Paper, and =Z= for Scissors. Winning every time
would be suspicious, so the responses must have been carefully chosen.
The winner of the whole tournament is the player with the highest score.
Your /total score/ is the sum of your scores for each round. The score
for a single round is the score for the /shape you selected/ (1 for
Rock, 2 for Paper, and 3 for Scissors) plus the score for the /outcome
of the round/ (0 if you lost, 3 if the round was a draw, and 6 if you
won).
Since you can't be sure if the Elf is trying to help you or trick you,
you should calculate the score you would get if you were to follow the
strategy guide.
For example, suppose you were given the following strategy guide:
#+begin_example
A Y
B X
C Z
#+end_example
This strategy guide predicts and recommends the following:
- In the first round, your opponent will choose Rock (=A=), and you
should choose Paper (=Y=). This ends in a win for you with a score of
/8/ (2 because you chose Paper + 6 because you won).
- In the second round, your opponent will choose Paper (=B=), and you
should choose Rock (=X=). This ends in a loss for you with a score of
/1/ (1 + 0).
- The third round is a draw with both players choosing Scissors, giving
you a score of 3 + 3 = /6/.
In this example, if you were to follow the strategy guide, you would get
a total score of =15= (8 + 1 + 6).
/What would your total score be if everything goes exactly according to
your strategy guide?/
Your puzzle answer was =11841=.
** --- Part Two ---
The Elf finishes helping with the tent and sneaks back over to you.
"Anyway, the second column says how the round needs to end: =X= means
you need to lose, =Y= means you need to end the round in a draw, and =Z=
means you need to win. Good luck!"
The total score is still calculated in the same way, but now you need to
figure out what shape to choose so the round ends as indicated. The
example above now goes like this:
- In the first round, your opponent will choose Rock (=A=), and you need
the round to end in a draw (=Y=), so you also choose Rock. This gives
you a score of 1 + 3 = /4/.
- In the second round, your opponent will choose Paper (=B=), and you
choose Rock so you lose (=X=) with a score of 1 + 0 = /1/.
- In the third round, you will defeat your opponent's Scissors with Rock
for a score of 1 + 6 = /7/.
Now that you're correctly decrypting the ultra top secret strategy
guide, you would get a total score of =12=.
Following the Elf's instructions for the second column, /what would your
total score be if everything goes exactly according to your strategy
guide?/
Your puzzle answer was =13022=.
Both parts of this puzzle are complete! They provide two gold stars: **

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);
}

42
2022/day02/aoc.bash Executable file
View File

@@ -0,0 +1,42 @@
#!/usr/bin/env bash
#
# 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.
# 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 outcome=( # shape is known
[A X]=$((3+1)) [A Y]=$((6+2)) [A Z]=$((0+3))
[B X]=$((0+1)) [B Y]=$((3+2)) [B Z]=$((6+3))
[C X]=$((6+1)) [C Y]=$((0+2)) [C Z]=$((3+3))
)
declare -A outcome2=( # result is known
[A X]=$((0+3)) [A Y]=$((3+1)) [A Z]=$((6+2))
[B X]=$((0+1)) [B Y]=$((3+2)) [B Z]=$((6+3))
[C X]=$((0+2)) [C Y]=$((3+3)) [C Z]=$((6+1))
)
declare -a tot
parse() {
local input
while read -r input; do
(( tot[1] += outcome[$input] ))
(( tot[2] += outcome2[$input] ))
done
}
solve() {
res="${tot[$1]}"
}
main "$@"
exit 0

17
2022/day02/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/day02/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/day02/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,3 @@
A Y
B X
C Z

2500
2022/day02/input/input.txt Normal file

File diff suppressed because it is too large Load Diff

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);
}

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