Compare commits
115 Commits
6de646f0d1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| ad6a39e82a | |||
| 3a857e4d53 | |||
| f80a051177 | |||
| 129fa07787 | |||
| 1472082c86 | |||
| e8bed49e13 | |||
| 83d70dcc7a | |||
| 56d2e63fac | |||
| 5c91de5d40 | |||
| 40a9c7b12e | |||
| 34b6cd7b57 | |||
| 5ad5c87fd8 | |||
| 11e7b45676 | |||
| 3f2a5648df | |||
| 0a3b404c4c | |||
| a214d2b70d | |||
| f490c2353e | |||
| 2ed6284bcd | |||
| 5fc204744a | |||
| d1cf8d96b8 | |||
| b285f74997 | |||
| c949c64da2 | |||
| 357e8ce087 | |||
| 5cde9051ec | |||
| 111fde4fbd | |||
| f54479189b | |||
| 8e00fec33c | |||
| d0376f21c3 | |||
| 04a856dc47 | |||
| 0658ffdd7d | |||
| efe0dec8f0 | |||
| 6d4a8dd85b | |||
| 11cb3c5c64 | |||
| 7e0a21704e | |||
| 008599e79c | |||
| fe381ae7f0 | |||
| 4a0749999e | |||
| 18720b9e09 | |||
| 17e140f235 | |||
| a1e436babc | |||
| 02a1dda786 | |||
| ef29ca28a1 | |||
| c1b3e83c68 | |||
| bd2548fca9 | |||
| 3f5b282883 | |||
| 38ef781f0a | |||
| 13d183de79 | |||
| dfe2207e8e | |||
| 31a255a9ac | |||
| 25d25b399e | |||
| f5ebb5c5cc | |||
| c608f6dcde | |||
| 9e3a875e37 | |||
| 4c0f6e3025 | |||
| 68f200ff65 | |||
| 8aff410ff4 | |||
| 16da47600c | |||
| 8b68bf4449 | |||
| c86517897e | |||
| 9c999e9717 | |||
| 05643127c2 | |||
| 6a5a0da435 | |||
| 3dd072c53e | |||
| 8f09fcf13f | |||
| 8f444d7341 | |||
| d7fa1c4fb5 | |||
| 0c787d9a51 | |||
| 64ad068ec8 | |||
| ab73311d6b | |||
| d116b98ae9 | |||
| 325c8254b8 | |||
| 76ab3d0c5b | |||
| bc2b2ac726 | |||
| b7c0b1fa01 | |||
| 487766c0a2 | |||
| a0fddb5f44 | |||
| f68d5b319e | |||
| 9455b99342 | |||
| ea4967bfcd | |||
| d1026e8f59 | |||
| 01cdce6608 | |||
| b8f6763a3b | |||
| 81a58c6266 | |||
| ca06a4a355 | |||
| 9d375aecfc | |||
| d412824317 | |||
| d8e05b0fca | |||
| a49a2ed073 | |||
| 2c14abff21 | |||
| 50919df627 | |||
| 73c9fa8150 | |||
| b949e11314 | |||
| f003511e10 | |||
| 36f763830f | |||
| c7553e7849 | |||
|
|
6012d4d375 | ||
| ce446be296 | |||
| a8cab0c7c3 | |||
| dbff06e5da | |||
| 0fb4219c92 | |||
| 58ba8b4ab8 | |||
| cca3d6fbe5 | |||
| cfba08b197 | |||
| ca8de49d5e | |||
| ea9c144127 | |||
| d4d5af0cb6 | |||
| 5ee230df69 | |||
| 9fe7b64263 | |||
| 8df13f9713 | |||
| 74ab0ba990 | |||
| 46dee29af6 | |||
| ad7c6f3042 | |||
| d485983efc | |||
| 23c33894a5 | |||
| 9bd03e0650 |
@@ -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 =================
|
||||
=========================================
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#! /bin/bash
|
||||
PATH=.:$PATH
|
||||
IN="$1"
|
||||
time { ex1.bash < $IN; ex2.bash < $IN; } 2>&1
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
200
2020/day19/README.org
Normal 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
165
2020/day19/aoc-c.c
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
76
2020/day21/README.org
Normal 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]].
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
452
2020/day22/README.org
Normal 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
315
2020/day22/aoc-c.c
Normal 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);
|
||||
}
|
||||
@@ -16,11 +16,11 @@
|
||||
* calculations
|
||||
*/
|
||||
|
||||
struct list_head *curcup; /* curcup cup */
|
||||
struct list_head *curcup; /* current cup */
|
||||
struct list_head *cups; /* the cups cups */
|
||||
int lastnum; /* last cup number */
|
||||
|
||||
#define CUR_CUP (&*curcup)
|
||||
#define CUR_CUP (&*curcup)
|
||||
#define NUM(pcup) ((pcup) - cups)
|
||||
|
||||
static __always_inline void step()
|
||||
@@ -39,7 +39,6 @@ static __always_inline void step()
|
||||
dest = &cups[lastnum];
|
||||
} while (NUM(dest) == num[0] || NUM(dest) == num[1] || NUM(dest) == num[2]);
|
||||
|
||||
//list_bulk_move_tail(dest->next, first, last);
|
||||
list_bulk_move(dest, first, last);
|
||||
curcup = CUR_CUP->next;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
87
2022/Makefile
Normal 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
317
2022/RESULTS.txt
Normal 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
111
2022/day01/Makefile
Normal 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
89
2022/day01/README.org
Normal 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
77
2022/day01/aoc-c.c
Normal 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
56
2022/day01/aoc.bash
Executable 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
17
2022/day01/aoc.h
Normal 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
68
2022/day01/common.bash
Executable 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
49
2022/day01/common.c
Normal 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;
|
||||
}
|
||||
14
2022/day01/input/example.txt
Normal file
14
2022/day01/input/example.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
1000
|
||||
2000
|
||||
3000
|
||||
|
||||
4000
|
||||
|
||||
5000
|
||||
6000
|
||||
|
||||
7000
|
||||
8000
|
||||
9000
|
||||
|
||||
10000
|
||||
2255
2022/day01/input/input.txt
Normal file
2255
2022/day01/input/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
111
2022/day02/Makefile
Normal file
111
2022/day02/Makefile
Normal 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
89
2022/day02/README.org
Normal 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
64
2022/day02/aoc-c.c
Normal 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
42
2022/day02/aoc.bash
Executable 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
17
2022/day02/aoc.h
Normal 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
68
2022/day02/common.bash
Executable 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
49
2022/day02/common.c
Normal 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;
|
||||
}
|
||||
3
2022/day02/input/example.txt
Normal file
3
2022/day02/input/example.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
A Y
|
||||
B X
|
||||
C Z
|
||||
2500
2022/day02/input/input.txt
Normal file
2500
2022/day02/input/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
111
2022/day03/Makefile
Normal file
111
2022/day03/Makefile
Normal 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
114
2022/day03/README.org
Normal 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
97
2022/day03/aoc-c.c
Normal 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
86
2022/day03/aoc.bash
Executable 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
17
2022/day03/aoc.h
Normal 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
68
2022/day03/common.bash
Executable 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
49
2022/day03/common.c
Normal 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;
|
||||
}
|
||||
6
2022/day03/input/example.txt
Normal file
6
2022/day03/input/example.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
vJrwpWtwJgWrhcsFMMfFFhFp
|
||||
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
|
||||
PmmdzqPrVvPwwTWBwg
|
||||
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
|
||||
ttgJtRGJQctTZtZT
|
||||
CrZsJsPPZsGzwwsLwLmpwMDw
|
||||
300
2022/day03/input/input.txt
Normal file
300
2022/day03/input/input.txt
Normal 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
111
2022/day04/Makefile
Normal 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
90
2022/day04/README.org
Normal 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
43
2022/day04/aoc-c.c
Normal 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
37
2022/day04/aoc.bash
Executable 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
17
2022/day04/aoc.h
Normal 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
68
2022/day04/common.bash
Executable 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
49
2022/day04/common.c
Normal 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;
|
||||
}
|
||||
6
2022/day04/input/example.txt
Normal file
6
2022/day04/input/example.txt
Normal 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
1000
2022/day04/input/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
111
2022/day05/Makefile
Normal file
111
2022/day05/Makefile
Normal 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
169
2022/day05/README.org
Normal 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
115
2022/day05/aoc-c.c
Normal 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
62
2022/day05/aoc.bash
Executable 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
17
2022/day05/aoc.h
Normal 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
68
2022/day05/common.bash
Executable 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
49
2022/day05/common.c
Normal 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;
|
||||
}
|
||||
9
2022/day05/input/example.txt
Normal file
9
2022/day05/input/example.txt
Normal 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
511
2022/day05/input/input.txt
Normal 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
111
2022/day06/Makefile
Normal 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
85
2022/day06/README.org
Normal 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
60
2022/day06/aoc-c.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* aoc-c.c: Advent of Code 2022, day 6
|
||||
*
|
||||
* Copyright (C) 2022 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
||||
* Some rights reserved. See COPYING.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this
|
||||
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "br.h"
|
||||
#include "aoc.h"
|
||||
|
||||
struct msg {
|
||||
char *data;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static struct msg *parse(struct msg *msg)
|
||||
{
|
||||
size_t alloc = 0;
|
||||
|
||||
msg->data=NULL;
|
||||
msg->len = getline(&msg->data, &alloc, stdin);
|
||||
msg->data[--msg->len] = 0;
|
||||
return msg;
|
||||
}
|
||||
|
||||
static int solve(struct msg *msg, int marklen)
|
||||
{
|
||||
char *pcur = msg->data, *pnext = pcur;
|
||||
int len = msg->len, lmark = 0;
|
||||
|
||||
for (; pnext < msg->data + len && lmark < marklen; lmark = ++pnext - pcur) {
|
||||
for (int j = 0; j < lmark; ++j) { /* compare with prev marker chars */
|
||||
if (*(pcur+j) == *pnext) { /* check new char with cur marker */
|
||||
pcur += j + 1; /* move marker to after dup char */
|
||||
goto nextchar;
|
||||
}
|
||||
}
|
||||
nextchar: ;
|
||||
}
|
||||
return pnext - msg->data;
|
||||
}
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int part = parseargs(ac, av);
|
||||
struct msg msg;
|
||||
|
||||
printf("%s: res=%d\n", *av, solve(parse(&msg), part == 1? 4:14));
|
||||
free(msg.data);
|
||||
exit(0);
|
||||
}
|
||||
46
2022/day06/aoc.bash
Executable file
46
2022/day06/aoc.bash
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# aoc.bash: Advent of Code 2022, day 6
|
||||
#
|
||||
# Copyright (C) 2022 Bruno Raoult ("br")
|
||||
# Licensed under the GNU General Public License v3.0 or later.
|
||||
# Some rights reserved. See COPYING.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with this
|
||||
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||
|
||||
. common.bash
|
||||
|
||||
declare input # datastream
|
||||
declare -i len # len of datastream
|
||||
|
||||
parse() {
|
||||
read -r input
|
||||
len=${#input}
|
||||
}
|
||||
|
||||
solve() {
|
||||
declare -ig res
|
||||
local -i mark=4 lcur=0 part="$1"
|
||||
local cur next
|
||||
|
||||
((part == 2)) && mark=14
|
||||
for (( i = 0; i < len - mark; ++i )); do # loop on all chars
|
||||
next=${input:i:1} # next char
|
||||
for ((j = 0; j < lcur; ++j)); do # compare with previous ones
|
||||
if [[ $next == "${cur:j:1}" ]]; then # duplicate
|
||||
cur="${cur:j+1}$next" # keep str after dup + new char
|
||||
(( lcur -= j ))
|
||||
continue 2
|
||||
fi
|
||||
done
|
||||
cur+="$next" # add new char
|
||||
((++lcur == mark)) && break # mark len found
|
||||
done
|
||||
((res = i + 1))
|
||||
}
|
||||
|
||||
main "$@"
|
||||
exit 0
|
||||
17
2022/day06/aoc.h
Normal file
17
2022/day06/aoc.h
Normal 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_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user