Compare commits

...

379 Commits

Author SHA1 Message Date
ad6a39e82a move env.h -> scripts/ 2023-12-29 18:37:52 +01:00
3a857e4d53 2022 day 16 (C): use same eval() for parts 1 & 2. 2023-04-20 08:31:16 +02:00
f80a051177 2022 day 17 init 2023-04-19 14:09:42 +02:00
129fa07787 2022 day 16: Part 2, sooo slooowww (6m40s) 2023-04-18 17:12:41 +02:00
1472082c86 2022 day 16 part 1 (C) - before cleaning useless permutation code 2023-04-11 09:42:58 +02:00
e8bed49e13 2022 day 16 (C): first parse and helper functions 2023-04-09 12:00:41 +02:00
83d70dcc7a 2022: update (C) notices 2023-04-09 11:59:26 +02:00
56d2e63fac 2022 day 15 (C): remove hash for part 1, simplify code 2023-04-03 18:15:37 +02:00
5c91de5d40 2022 day 15: final version (C) 2023-04-02 20:57:44 +02:00
40a9c7b12e 2022 day 15 part 2: improved solution (20,000 times faster) 2023-04-02 19:50:00 +02:00
34b6cd7b57 2022 day 15 part 2 (C). First version: 18s, ~30,000,000 func calls 2023-04-02 19:45:55 +02:00
5ad5c87fd8 2022: init day 16 2023-04-01 13:54:28 +02:00
11e7b45676 2022 day 15: start part 2 data structure 2023-03-30 10:38:03 +02:00
3f2a5648df debug: add debug_level_get() 2023-03-25 13:32:03 +01:00
0a3b404c4c 2022 day 15: part 2 (C) 2023-03-25 13:31:40 +01:00
a214d2b70d common C code: add "-t" option for test mode. 2023-03-22 08:43:46 +01:00
f490c2353e 2022 day 15 (C) part 1 (dirty and even more) 2023-03-21 11:17:04 +01:00
2ed6284bcd 2022 day 15 init 2023-03-18 17:50:59 +01:00
5fc204744a 2022 day 14 (C): final version. Too hacky for me... 2023-03-18 17:30:26 +01:00
d1cf8d96b8 2022 day 14, parts 1 & 2, before cleaning 2023-03-18 16:35:08 +01:00
b285f74997 2022 day 14: init 2023-01-20 20:25:55 +01:00
c949c64da2 day 22 day 13 (C) simplify/comment code 2023-01-12 10:34:32 +01:00
357e8ce087 fix wrong org conversion (brackets become links in code blocks) 2023-01-11 20:16:51 +01:00
5cde9051ec 2022 day 13 (C) final version - more cleanup needed 2023-01-10 22:14:59 +01:00
111fde4fbd 2022 day 13 (C) before cleaning 2023-01-10 22:00:55 +01:00
f54479189b 2022 day 13 part 1 (C) 2023-01-07 18:17:02 +01:00
8e00fec33c PJW hash: add credits 2023-01-07 18:16:18 +01:00
d0376f21c3 2022 day 12 (C, parts 1 & 2) 2022-12-24 21:06:10 +01:00
04a856dc47 Makefile: clean keeps compile_commands.json 2022-12-24 21:05:33 +01:00
0658ffdd7d 2022 day 13 init 2022-12-23 11:41:30 +01:00
efe0dec8f0 2022 day 12 Bash final version 2022-12-22 21:38:26 +01:00
6d4a8dd85b Bash 2022 day 12 (parts 1 & 2), before cleaning code 2022-12-22 21:33:29 +01:00
11cb3c5c64 2022 day 11 final (C) 2022-12-21 15:46:07 +01:00
7e0a21704e 2022 day 11: C first version (parts 1 and 2) 2022-12-21 13:34:28 +01:00
008599e79c 2022 day 11, Bash speedup (40-50%) 2022-12-20 17:29:47 +01:00
fe381ae7f0 Bash: 2022 day 11. Part 2 is ~29 secs 2022-12-20 15:03:42 +01:00
4a0749999e 2022 day 11: Bash parts 1 & 2, before cleaning 2022-12-20 14:47:29 +01:00
18720b9e09 2022 day 10: C, parts 1 and 2. Should be useful if this "machine"...
... comes back in next days puzzles (my guess is that it will ;-)
2022-12-18 14:33:45 +01:00
17e140f235 br.h: add __unused and __used macros 2022-12-18 14:22:18 +01:00
a1e436babc C: remove dead code in 2022/day 9 2022-12-17 18:50:10 +01:00
02a1dda786 2022 day 10: Bash parts 1 & 2 2022-12-17 16:05:49 +01:00
ef29ca28a1 2022: init day 10 2022-12-17 12:25:11 +01:00
c1b3e83c68 2022 day 9: C parts 1 and 2 2022-12-17 11:28:12 +01:00
bd2548fca9 pjwhash: char* to void* 2022-12-17 11:27:40 +01:00
3f5b282883 2022 day 9 Bash: reduce code by 40%, increase speed by 40% 2022-12-13 19:33:29 +01:00
38ef781f0a 2022 day 9: Bash part 2, same code for both part (slower #1) 2022-12-13 18:38:24 +01:00
13d183de79 2022 day 9, Bash part 1 2022-12-13 16:02:50 +01:00
dfe2207e8e init day 9 2022-12-12 20:47:45 +01:00
31a255a9ac 2020 day 8 (C, both parts. No inspiration here) 2022-12-12 20:46:09 +01:00
25d25b399e 2022 day 8: bash final 2022-12-11 18:44:55 +01:00
f5ebb5c5cc 2022 day 8: Bash parts 1 & 2 2022-12-11 18:36:21 +01:00
c608f6dcde 2022 day 8 init 2022-12-10 16:53:33 +01:00
9e3a875e37 2022 day 7: C final version (parts 1 & 2) 2022-12-10 16:43:34 +01:00
4c0f6e3025 2022 day 7: C, parts 1 & 2 2022-12-10 14:56:46 +01:00
68f200ff65 2022: add PJW hash (lib) 2022-12-10 14:56:31 +01:00
8aff410ff4 2020 / day 7: final Bash cleanup 2022-12-10 07:43:14 +01:00
16da47600c 2022 day 7: clean bash code & remove file size info (50% speed) 2022-12-09 20:34:05 +01:00
8b68bf4449 2022 day 7: Bash parts 1 and 2 (messy, tons of debug) 2022-12-09 20:23:26 +01:00
c86517897e 2022 day 7 init 2022-12-09 16:42:45 +01:00
9c999e9717 2022 day 6: C (parts 1 and 2) 2022-12-09 16:25:56 +01:00
05643127c2 2022 day 6: Bash part 2 (lucky me: part 1 code worked) + optimizations 2022-12-09 14:38:21 +01:00
6a5a0da435 2022 day 6 init + bash part 1 2022-12-09 14:14:58 +01:00
3dd072c53e 2022 day 5 (C) 2022-12-09 11:47:32 +01:00
8f09fcf13f 2022 day 5 bash: simplify code (final ?) 2022-12-08 16:52:58 +01:00
8f444d7341 fix day # in comment 2022-12-08 16:30:55 +01:00
d7fa1c4fb5 Bash: 2022 day 5 (both parts, brute code) 2022-12-08 16:09:32 +01:00
0c787d9a51 2022/bash: move LANG=C to common.bash 2022-12-08 12:52:54 +01:00
64ad068ec8 2022/day 5 init 2022-12-08 12:45:04 +01:00
ab73311d6b 2022 day 4: C, parts 1 & 2 (lazy way: same algo as Bash) 2022-12-08 12:21:12 +01:00
d116b98ae9 Bash 2022/day4: remove nearly everything :-) 2022-12-08 11:45:40 +01:00
325c8254b8 Bash: 2022 day 4 part 2 2022-12-08 09:50:06 +01:00
76ab3d0c5b Bash: 2022/day 4 part 1 2022-12-08 09:43:43 +01:00
bc2b2ac726 C: 2022/Day 3 final cleanup + more comments 2022-12-08 08:19:57 +01:00
b7c0b1fa01 C 2022/Day 4 init 2022-12-08 08:18:27 +01:00
487766c0a2 C: 2022 day 3, remove useless code / variables 2022-12-07 22:21:19 +01:00
a0fddb5f44 2022 day 3 / cleanup some C code, update RESULTS.txt 2022-12-07 21:49:48 +01:00
f68d5b319e 2020 / day 3: C first working version (parts 1 & 2) 2022-12-07 21:38:46 +01:00
9455b99342 bash: 2022 day 3 (final 2 parts) 2022-12-07 19:07:16 +01:00
ea4967bfcd 2022 day 3 (bash, working version before cleanup) 2022-12-07 18:45:52 +01:00
d1026e8f59 2022 day 3 part 1 (bash) 2022-12-07 17:31:29 +01:00
01cdce6608 C: 2022 day 2 2022-12-07 15:37:00 +01:00
b8f6763a3b forgot 2022-12-07 13:40:01 +01:00
81a58c6266 update lib from tools repo (some fixed for 32 bits) 2022-12-07 13:20:48 +01:00
ca06a4a355 typo in printf 2022-12-07 13:20:29 +01:00
9d375aecfc 2022 day 2 (bash) 2022-12-07 13:18:58 +01:00
d412824317 2020 day 10 (C): fix for 32 bits architecture (ooops !) 2022-12-06 17:18:22 +01:00
d8e05b0fca 2020/day2: fix for 32 bits arch 2022-12-06 15:45:00 +01:00
a49a2ed073 debug.h: tentatively build on 32 bits arch 2022-12-06 15:17:04 +01:00
2c14abff21 bits.h: move popcount32() up 2022-12-06 14:43:16 +01:00
50919df627 bits.h: tentatively build on 32 bits arch 2022-12-06 14:41:28 +01:00
73c9fa8150 typo 2022-12-06 14:39:06 +01:00
b949e11314 2020: update lib source files (trying to compile on 32 bits arch) 2022-12-06 14:27:10 +01:00
f003511e10 pool.c: please valgrind 2022-12-03 14:50:37 +01:00
36f763830f 2020: Tentative C & Bash frameworks (common functions) 2022-12-03 14:42:37 +01:00
c7553e7849 plist.h: add some reverse macros 2022-12-03 14:40:35 +01:00
Bruno
6012d4d375 2022/day 1 (C) - save from laptop 2022-12-02 10:32:02 +01:00
ce446be296 cleanup code 2022-12-01 10:48:09 +01:00
a8cab0c7c3 2022 day1: fix global Makefile, RESULTS.txt 2022-12-01 10:31:17 +01:00
dbff06e5da 2022 day 1: prepare bash common code + bash solutions 2022-12-01 10:28:40 +01:00
0fb4219c92 init AoC 2022, cleanup useless files 2022-12-01 07:50:35 +01:00
58ba8b4ab8 2020 day 21: init for C version 2022-11-30 20:24:23 +01:00
cca3d6fbe5 2020 day 22: release memory 2022-11-30 13:17:57 +01:00
cfba08b197 typo 2022-11-29 21:00:11 +01:00
ca8de49d5e 2020 day 22/2 (C) - clean code 2022-11-29 20:53:07 +01:00
ea9c144127 2020 day 22 part 2 (C, 1st version) 2022-11-29 19:14:53 +01:00
d4d5af0cb6 2020 day 22 part 1 (C) 2022-10-28 12:08:59 +02:00
5ee230df69 2020 day 22: init for C version 2022-10-27 20:24:37 +02:00
9fe7b64263 typo 2022-10-27 20:08:38 +02:00
8df13f9713 2020/19 (C): cleanup code 2022-10-27 16:14:48 +02:00
74ab0ba990 2020 part 2 (C). 2022-10-27 15:22:44 +02:00
46dee29af6 cleanup README.org 2022-10-26 19:21:39 +02:00
ad7c6f3042 add len in message (for future CYK implementation) 2022-10-26 19:19:41 +02:00
d485983efc 2020/19, add C results for part 1. 2022-10-24 20:37:02 +02:00
23c33894a5 2020 day 19 part 1 (C) - won't work for part 2 !! 2022-10-24 20:15:25 +02:00
9bd03e0650 day 23: typos 2022-10-24 20:14:53 +02:00
6de646f0d1 C: 2020 day 23, part 1 and 2 2022-10-22 18:37:37 +02:00
a525ab6338 change name 2022-10-22 18:36:50 +02:00
2de0c3c9c8 list.h: add list_bulk_move() 2022-10-22 18:35:37 +02:00
6e4c64db39 2020/23 (C) update Makefile, switch to .org readme 2022-10-20 10:12:09 +02:00
b73db03da9 add env.sh 2022-10-20 10:05:16 +02:00
f6d1fe7b9d 2020/23 bash: unify the 2 parts code 2022-10-20 08:51:10 +02:00
30cdb5e1a4 update repo README 2022-10-19 19:19:05 +02:00
b4a2603c7b C: 2020 day 24 - switch to 32 bits hash, rename some var/fct. 2022-10-19 19:02:03 +02:00
abcc4af572 C: day 24 final version + RESULTS.txt cleanup 2022-10-19 18:14:02 +02:00
94f0d95544 C: 2020 day 24 part 2 (dirty code) 2022-10-19 17:16:20 +02:00
452a912fe5 2020 library 2022-10-18 18:11:53 +02:00
46d6b77596 2020 day 24 part 1: C 2022-10-18 17:52:19 +02:00
65c03075f1 switch README to org-mode / add ccls compile_commands.json generation 2022-10-11 20:47:43 +02:00
4a565af1c2 Copy Makefile from 2019 2022-10-11 20:22:33 +02:00
0a03bc557b git-ignoire compile_commands.json 2022-10-11 18:44:38 +02:00
282d55c3cd 2020 day 25 (C): just copied my (lazy/brute-force) bash solution 2022-10-11 18:37:25 +02:00
920f830fac Re-use 2019 latest Makefile 2022-10-11 17:44:06 +02:00
e3d6b622dc 2020 day 25 (C): just copied my (lazy/brute-force) bash solution 2022-10-11 16:51:06 +02:00
5795d24ab4 2020 day 24: Add hexagon page link, for my future needs ;-) 2022-10-11 15:13:50 +02:00
86a62f0b2d update readme (2020 bash finished) 2022-10-10 19:46:29 +02:00
f3ae028751 2020 day 25 (bash) 2022-10-10 18:29:39 +02:00
d2b5a9dc34 2020 day 24 part 2 (bash) 2022-10-10 16:09:24 +02:00
563798871a 2020 day 24 (bash) part 1: simplify code 2022-10-09 14:34:50 +02:00
cced357154 2020 day 24 (bash) part 1. 2022-10-09 14:28:58 +02:00
4653101623 2020 day 24 init 2022-10-09 10:38:25 +02:00
0fb3d8832f typo 2022-10-08 22:00:22 +02:00
c30ca858e4 update README 2022-10-08 21:59:28 +02:00
cd41685cb5 Day 23 (bash) part 2 (~7mn run) 2022-10-08 21:34:13 +02:00
d2d66dc763 2020 day 23 part 1: re-use part 2 (unfinished) code 2022-10-08 20:56:50 +02:00
284eeb3dea 2020 day 23 part 1 (bash). Ooops. This won't do part 2 :-( 2022-10-06 16:42:30 +02:00
f74a1ffb8a delete .projectile and .dir-locals.el 2022-10-05 16:36:57 +02:00
b001690c95 delete .projectile and .dir-locals.el 2022-10-05 16:31:28 +02:00
0fe04e43dc 2019 day 9: cleanup code (see TODO in commit notes)
TODO:
- rename peek/poke
- remove the costly test on valid instruction in run()
- use array for i/o instead of input and output.
   Then merge prg_{add,get}_{input,output}
- add a pipe function to move one program output to (another) input
- remember in next AoC to use _unused to keep interesting unused functions
2022-10-04 22:49:01 +02:00
bd851b6524 2019 day 09: parts 1 & 2 2022-10-04 22:04:50 +02:00
Bruno
1cfd1c81f0 day 19 day 9: save unfinished work from laptop 2022-10-04 12:12:48 +02:00
Bruno
130f2a4d54 2019 day 9 init from day 7 2022-10-04 07:34:29 +02:00
625966f5b8 2019 day 8: parts 1 & 2 2022-10-03 10:54:54 +02:00
521e6e1bca 2019 day 8 init 2022-10-01 19:52:56 +02:00
bacbc6eded typo 2022-10-01 19:49:43 +02:00
5694883ef5 2019 day 6: remove count of allocated tries/objects 2022-10-01 19:07:05 +02:00
6a43725e30 fix copyright year 2022-10-01 18:34:20 +02:00
4d938b6cd7 2019 day6: simplify code, remove forgotten outputs 2022-10-01 18:31:52 +02:00
0c9b93b42a update copyright 2022-10-01 18:20:02 +02:00
04fcca5829 update copyright 2022-10-01 18:19:19 +02:00
ddfa8cf05b 2019 day 7, final version + update RESULTS.txt 2022-10-01 16:39:34 +02:00
5008963937 2019 day 7 part 2, before cleanup 2022-10-01 15:50:33 +02:00
155e066ed2 2019 day 7, part 1 2022-09-30 19:22:12 +02:00
626bd1df41 init 2019 day 7 with day 5 source, typo in day 6 2022-09-30 16:28:22 +02:00
8ed39e52b7 simplify part 2: use depths difference instead of two parent lists 2022-09-29 20:08:50 +02:00
e83b690822 2019 day 6 : add structure diagrams (Thanks Emacs' artist-mode !) 2022-09-29 19:41:51 +02:00
0004b2091e 2019 day 6: remove dead code, trie contains object ptr instead of object 2022-09-28 18:47:20 +02:00
a201283599 2019 day 6: parts 1 and 2, before cleaning (lots of printf ;-) 2022-09-28 15:25:01 +02:00
d5c37f5d48 cosmetic changes 2022-09-28 15:24:18 +02:00
1c10926cf9 bits.h: add rolXX(), rorXX(), ilog2(), bits_per(), etc... 2022-09-28 15:22:25 +02:00
94c6b2eec5 add attribute(__pure__) 2022-09-28 15:21:11 +02:00
b50f3a7098 switch from gnu99 to gnu11 2022-09-28 15:16:41 +02:00
8783eca22c 2019 day 6 init 2022-09-25 12:28:40 +02:00
3d18e36ff4 2019 day 5: fix wrong link in README, replace struct with typedefs 2022-09-25 12:26:07 +02:00
b6af1f3edb 2019 day 5: Update results & README 2022-09-24 18:48:20 +02:00
Bruno
68d81fd1da 2019 day5: cleaner (final ?) version 2022-09-24 12:13:14 +02:00
Bruno
b206ee5b87 2019 day5: fix run-example.sh reversed results 2022-09-24 12:12:12 +02:00
Bruno
13c977957f 2019 day 5: working version before cleanup 2022-09-24 08:01:57 +02:00
Bruno
d0adb2378a 2019 day 5: set all examples + test script 2022-09-24 07:55:47 +02:00
d1221ab086 2019 day 5: add examples from day 2, add _stringify in br.h 2022-09-22 10:11:24 +02:00
f2b32f236d 2019 day 5 init (with day 2 code) 2022-09-21 09:43:50 +02:00
696273367a 2019: update Makefile from day 4 2022-09-21 09:27:33 +02:00
f7336d6814 when rule 4 is violated, skip to next possible number 2022-09-20 22:01:43 +02:00
a461bf2842 typo 2022-09-20 20:02:23 +02:00
0ce9f9aafa Add --show-error-list=yes to valgrind options. Invalid opcode again!
To run "make memcheck", uncomment Makefile line 36 (-m no-tbm).
Without this, I get :
vex amd64->IR: unhandled instruction bytes: 0x8F 0xEA 0xF8 0x10 0xFF 0x23 0x1D 0x0 0x0 0x89
vex amd64->IR:   REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=NONE
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==888233== valgrind: Unrecognised instruction at address 0x109336.
2022-09-20 19:58:30 +02:00
ea530e7d8d 2019 day 4, minor is_valid() simplification 2022-09-20 19:57:27 +02:00
2694f8d4d0 2019 day 4, parts 1 and 2 2022-09-20 19:22:13 +02:00
f9a80239b4 2019 day 4 init 2022-09-20 13:55:15 +02:00
ffb27a8338 2019 day 3 cleanup 2022-09-20 13:39:08 +02:00
dbfc914efb test newline in org paragraph 2022-09-19 20:15:30 +02:00
c4772bb416 typo in day03 README.org 2022-09-19 20:05:13 +02:00
bc8dac927a fix broken Makefile for valgrind + fix day02 memory leak. 2022-09-19 20:01:11 +02:00
42d1f7bf48 README.org cleanup, update RESULTS.txt, build README.org with Makefile 2022-09-19 19:59:26 +02:00
828d13f967 2019 day 3 + add br.h for some useful stuff (min, max... macros) 2022-09-19 19:35:37 +02:00
b67600957e 2019 day3 init 2022-09-18 18:04:21 +02:00
0d7424d9c6 2019 day 2 2022-09-18 17:30:46 +02:00
d9b0f7b7c4 2019 day 1 2022-09-18 14:04:30 +02:00
378df8cf5b init 2019 2022-09-18 13:35:09 +02:00
c56f9ca769 update day25 Makefile 2022-09-18 13:23:53 +02:00
37a38bdc4a day23: delete dead code, rename structs/macros, use native rand() 2022-09-15 09:42:27 +02:00
e0720bdd0a includes: update from tools repo 2022-09-14 20:05:47 +02:00
2fda973085 day 25: fic Makefile for only one part 2022-09-14 20:04:07 +02:00
79428d6192 day23: final version (could add priority queue to improve further ?) 2022-09-14 20:02:54 +02:00
ebb8a0d738 day 25: memory cleanup, simplify puzzle input read 2022-09-14 19:56:33 +02:00
721f9da54e day 25: code cleanup 2022-09-08 21:08:49 +02:00
5da5adb8bf day 25: simplify code. 2022-09-08 16:11:29 +02:00
adb8fc6b95 day 25, first version (need lots of cleaning) 2022-09-07 22:14:45 +02:00
4dbcc30dc3 first try of A* move sorting 2022-04-05 13:20:13 +02:00
49bbc2372c changes in newmove() & hash() to avoid code duplication 2022-04-04 16:46:51 +02:00
aa0f475b17 messy/bloaty/slow version working for example & input 2022-04-02 17:35:39 +02:00
9a0d7a2ca7 temp save to use on laptop 2022-04-01 06:37:55 +02:00
ea429a99a7 Day 23: zobrist hash, still wrong collisions (works only without hash) 2022-03-30 21:39:16 +02:00
4fa4a5d366 day23: 1st "running" version, which does not work (maybe hash issue) 2022-03-30 13:20:11 +02:00
e25d79e95b bits.c: added 32 bits versions (untested) 2022-03-30 13:19:38 +02:00
4be7c56b88 day 24 parts 1 & 2 (forgot source) 2022-03-30 13:19:02 +02:00
c78a3e7285 Day 23 part 2 README (part 1 done with pen/paper) 2022-03-26 16:49:27 +01:00
f807acc983 day 24 2022-03-25 16:08:54 +01:00
b64bc6c1d5 update library from mainstream, especially {READ,WRITE}_ONCE 2022-03-24 18:42:35 +01:00
6aa605a0de init days{24,25} 2022-03-24 18:41:28 +01:00
1f835c10c5 new list.h with {READ,WRITE}_ONCE 2022-03-18 17:25:39 +01:00
d4ec54ed5b add #error for word size != 64 2022-02-07 18:18:11 +01:00
4ac39e5a69 day 23: early code for bitboard approach. 2022-01-29 21:00:54 +01:00
b8e61bcacb day 22: typo in day # comment 2022-01-29 21:00:31 +01:00
efb25f363f bugfix bit_for_each64_2 2022-01-29 15:47:38 +01:00
1e8556b5d5 day 23 init 2022-01-28 19:37:23 +01:00
5c392199fe Day 22 : clean code, more comments. 2022-01-28 17:07:44 +01:00
6b753e9d6c day 22: working part 2. Two days lost due to int overflow :-( 2022-01-28 16:08:05 +01:00
35053f3c8c day 22: change part1 to match part2 changes in input read. 2022-01-27 19:10:36 +01:00
97411fbb08 day 22 part 1 (basic/stupid algorithm, not suitable for part 2) 2022-01-27 16:24:43 +01:00
ecbeffc3d9 Day 22 init 2022-01-25 13:47:18 +01:00
7082ce3565 day 21: fix memory leaks 2022-01-25 13:46:48 +01:00
58027905b8 day 21 part2, 1st version. Need improvement in queue management (!) 2022-01-24 15:49:02 +01:00
76bd022049 day 21 part 1 2022-01-24 00:12:13 +01:00
cf2bed124e day 21 init 2022-01-23 21:58:17 +01:00
dacefcd5ad day20: final version (more comments, more code cleanup) 2022-01-23 21:48:18 +01:00
db7013309b day20 EXAMPLE2.txt: impossible input 2022-01-23 21:47:46 +01:00
63e737b863 day 20: code cleanup 2022-01-23 20:50:51 +01:00
f1af70e55a Added example file to resolve both parts with initial '#' 2022-01-23 20:45:16 +01:00
ec4684a756 day 20, part 2 (before code cleanup) 2022-01-23 20:44:28 +01:00
897453fb39 day 20: working version for part 1 2022-01-23 20:38:58 +01:00
81cfe12d67 day20, part1: working version for given example (not for input) 2022-01-23 20:27:52 +01:00
640feea875 day 20 init 2022-01-22 20:42:38 +01:00
2692f3f621 day19: cosmetic changes 2022-01-22 20:18:15 +01:00
5346b0e7fa day 19, after optimization (8.5s -> 0.06s) 2022-01-22 19:37:25 +01:00
c84a37874c day 19: clean logs 2022-01-22 15:05:23 +01:00
b11c35be26 day 19 part 2, before cleaning 2022-01-22 14:01:13 +01:00
858258770b day 19 part 1 (ugly, many useless code) 2022-01-22 13:22:39 +01:00
1caa102c23 day19: move beacons/distances from arrays to lists 2022-01-21 16:54:15 +01:00
9fd980c71b day 19: save before reverting scanners's beacons/distances to linked lists 2022-01-19 17:23:26 +01:00
6c3672f8d1 (temp) save not working day19 - likely mismatch in scanners ref array 2022-01-16 21:16:21 +01:00
96c9f7d6e3 pool_create: do not fail if structure is too small to handle list pointers 2022-01-16 21:07:30 +01:00
fe4520da7f list.h: blank line 2022-01-16 21:00:16 +01:00
a03cc1c1c4 day19: tentatively get 3 common beacons between overlapping scanners 2022-01-14 20:26:22 +01:00
f1dc062250 day 18: typos in comments 2022-01-14 18:24:59 +01:00
645188216e day19: find common beacons between two scanners 2022-01-14 15:10:45 +01:00
e3382ef3dd debug.h: fix mistake in debug() printf __attribute__ 2022-01-14 12:47:05 +01:00
8a67ac0321 debug.h: add printf() attribute to debug() function 2022-01-14 12:43:05 +01:00
b255dc5d43 .gitignore: added common dummy files (FOO*, BAR*, etc..) 2022-01-14 11:52:42 +01:00
33bee9500c day 19: first functions (read input, calculate beacons distances...) 2022-01-14 11:50:14 +01:00
46fd8a30bc day 18: improve tree structure explanation 2022-01-14 11:49:23 +01:00
77ef1fa003 Makefile day 19: added memcheck targets 2022-01-14 11:48:47 +01:00
457b3eb9b9 Snailfish data structure diagram + cosmetic changes 2022-01-12 11:02:51 +01:00
a88aa2312b (C): 2021 -> 2022 2022-01-11 19:49:14 +01:00
cd4a21380d day 18: more code cleanup/comments 2022-01-11 19:46:27 +01:00
a0b094aa61 day 19 init 2022-01-07 22:35:38 +01:00
0e333e5cb9 day 18: code cleanup, fixed valgrind errors. 2022-01-07 22:24:26 +01:00
0344a9162f day 18 part 2 (before cleaning) 2022-01-07 21:08:56 +01:00
8d3a064c73 day 18 part 1 (with tons of debug) 2022-01-07 20:33:01 +01:00
2f47bb23ea typo 2021-12-28 11:42:30 +01:00
0f932bca95 day 18 init 2021-12-27 14:22:25 +01:00
95ef1bc864 day 17: more code cleaning 2021-12-27 11:34:09 +01:00
8748eb0f1f day17: code cleaning + results 2021-12-27 11:28:10 +01:00
7b7095b8d7 day 17 parts 1 & 2, before code cleaning. 2021-12-27 11:10:41 +01:00
f3717c906b init day 17 2021-12-21 16:32:10 +01:00
f8720a2129 day 16 part 2 final 2021-12-21 12:18:11 +01:00
bdfad93f4a day 16 part 2 (before code cleanup) 2021-12-21 11:57:04 +01:00
50963c233b day 16 part 1 (with tons of debug printf) 2021-12-20 20:36:23 +01:00
90303eb8b5 pool.c: name becomes char array instead of pointer 2021-12-20 15:10:17 +01:00
118d7f8452 refactor pool_init -> pool_create 2021-12-20 14:44:15 +01:00
93ef9438b8 day 16 init 2021-12-20 12:45:12 +01:00
43378e9366 Makefile: add gmon.out in clean target 2021-12-20 12:44:43 +01:00
9d9b111e2c pool.c: add destroy() to totally free a pool's memory 2021-12-20 11:59:02 +01:00
a84c52fa94 day 15 part 2 final 2021-12-20 09:54:23 +01:00
aace9d72de day 15 part 2 (1st version) 2021-12-19 19:32:09 +01:00
befb71ed22 day 15 part 1 2021-12-19 14:59:52 +01:00
fde80b124b day 15 init 2021-12-17 17:54:54 +01:00
85b4204894 day14: more code cleanup 2021-12-17 16:51:24 +01:00
ca6b612d0d day 14 final (need some comments, will not remember :-) 2021-12-17 16:30:21 +01:00
d0c6c6e4f7 day 4 part 2 (before cleaning code) 2021-12-17 16:19:57 +01:00
33ae1b1751 day 14 part 1 (stupid algorithm) + init part 2 2021-12-15 20:32:21 +01:00
295f032d6a day 14 init 2021-12-15 16:03:01 +01:00
cbbfb507c3 day 13: remove debug 2021-12-15 15:58:13 +01:00
394cfcd2ca Day 13 parts 1 & 2 (with tons of debug, before code cleaning) 2021-12-15 15:43:02 +01:00
81867c5a18 init day 13 2021-12-14 16:52:55 +01:00
9933153c9d typo in source exercise name 2021-12-14 16:43:54 +01:00
94aeedb78b day 2: simplify code
- remove stack
- do not create useless links from/to START & END
- remove logs
2021-12-14 16:39:43 +01:00
2dec566985 day 12 part 2 (C), before code cleaning. 2021-12-14 12:58:40 +01:00
d973d86ec7 day 12 part 1 (using recursive BFS, with tons of debug info) 2021-12-14 12:22:03 +01:00
60a042951b more comments for day 11 2021-12-12 21:13:24 +01:00
b06d784563 simplify day 11 (maybe too much) 2021-12-12 20:31:24 +01:00
cede0eb93f day 12 init 2021-12-12 20:01:12 +01:00
af7543b623 revert to silent Makefile 2021-12-12 19:46:54 +01:00
e07241fd25 RESULTS.txt filename typo 2021-12-12 19:44:08 +01:00
1458315653 rename OUTPUT -> RESULTS.txt 2021-12-12 19:43:36 +01:00
9c5e734ece day 11 final (C) 2021-12-12 19:37:31 +01:00
dbf9b52cb3 day 11 part 1 (plenty of logs) 2021-12-12 19:08:29 +01:00
7fd472c17c day 11 part 1 (plenty of logs) 2021-12-12 19:00:51 +01:00
80c19f9331 debug.[ch]: kernel style #ifdef free C source 2021-12-12 19:00:06 +01:00
37fa19f6be fix aoc C comment header 2021-12-11 18:04:23 +01:00
42addcefad C source header fix 2021-12-11 18:02:34 +01:00
d20651dd50 typos on C sources day comment 2021-12-11 10:35:39 +01:00
0cea717fcb day 11 init 2021-12-11 10:19:09 +01:00
b998ada9d2 fix possible leak if wrong input 2021-12-11 10:04:22 +01:00
171eadf318 day 10 cleanup (C) 2021-12-11 10:01:04 +01:00
fb5be18e18 day 10 part 2 (1st version, need huge cleanup) 2021-12-11 09:24:03 +01:00
34acd4012b day 10 part 1 (with tons of debug information ;-) 2021-12-10 22:12:00 +01:00
395060c266 day 10 init 2021-12-10 21:08:46 +01:00
23c0e33c82 day 9 (C) 2021-12-10 21:06:16 +01:00
b67985003c remove useless include 2021-12-10 21:05:22 +01:00
192545c9a3 complete part 8 (switched to bitmasks). 2021-12-10 17:39:51 +01:00
3235bd3b15 day 8 part 1 (C) + init part 2 2021-12-10 13:24:13 +01:00
e871ccf091 day 7 part 2 (C), day 8 init 2021-12-10 12:06:23 +01:00
6f6a6b286a day 7 part 1 (C) 2021-12-10 11:28:25 +01:00
833732ae58 init day 7 2021-12-10 10:09:07 +01:00
7c981d6633 day 6 part 2 (C). Implies change initial stupid algorithm with simple one 2021-12-08 21:37:25 +01:00
6a0a81aa38 day 6 part 1 (simple algorithm) + part 2 README 2021-12-08 20:30:32 +01:00
b62404686a typo in day 5 source core + adjust day 6 example (1 line only) 2021-12-08 18:31:01 +01:00
3cfe781a08 day 6 init 2021-12-06 09:01:18 +01:00
0ea7a9278a day 5, parts 1 & 2 (C) 2021-12-05 13:57:26 +01:00
736cae886a day 5 init 2021-12-05 09:27:02 +01:00
867eb7fda0 add COPYING & fix typo in GPL URL 2021-12-05 00:06:42 +01:00
cb1e5ed442 more reasonable pool size 2021-12-04 22:18:02 +01:00
68f40df298 debug.c: do not print debug level if level == 0 2021-12-04 22:15:42 +01:00
3e886caf63 enable memory pool debug 2021-12-04 22:13:32 +01:00
a6ccc58636 typo 2021-12-04 20:39:10 +01:00
a46c23235d day 4 (C) 2021-12-04 20:34:00 +01:00
a0cb3e5fd8 We can only run 1 exercise (not both) in a single run 2021-12-04 17:20:54 +01:00
8f2c0f8c2d day 4 init 2021-12-04 16:14:12 +01:00
401b567e20 day 3 part 2 (C) 2021-12-04 16:04:51 +01:00
cbe3616422 delete bits.c 2021-12-03 21:26:18 +01:00
edcafd2a00 day 3 part 1 (C) + remove unused-result warning 2021-12-03 21:01:44 +01:00
9a65775f7a revert default part to 1 2021-12-03 19:18:57 +01:00
f769e9b361 remove useless code copied from day 1 2021-12-03 18:54:55 +01:00
a9c713a5ea day 3 init 2021-12-03 18:48:23 +01:00
e93108d033 update OUTPUT 2021-12-03 18:45:49 +01:00
adcc449bea day 2, parts 1 & 2 (C) 2021-12-03 18:45:24 +01:00
172dac6bfe fix wring flycheck include-path 2021-12-03 18:25:46 +01:00
568bc1c0ac exclude objects files 2021-12-03 18:08:22 +01:00
89c85cc40a remove objects files 2021-12-03 18:07:37 +01:00
2fc8a49cea fix cleanall target (lib object files) 2021-12-03 18:07:06 +01:00
bd0ccdd942 day 2 init 2021-12-03 18:00:41 +01:00
9bd7a0cd85 day1 README: remove useless html headers 2021-12-03 17:58:50 +01:00
58980edfb0 update README 2021-12-03 17:48:04 +01:00
ba89d9cf0c update README 2021-12-03 17:12:24 +01:00
bd0c02fb5f OUTPUT file, silent Makefiles 2021-12-03 17:08:36 +01:00
ad032df481 New Makefile, day 1 solution (C) 2021-12-03 16:58:08 +01:00
7a1a200a73 2021 templates 2021-12-02 16:37:50 +01:00
2d431892da day 23 init 2021-08-01 18:02:31 +02:00
6e9e4be8e3 bash day 22/part 2, final version 2021-08-01 17:57:53 +02:00
12d4bdda61 1st version of Bash for Day22/Part 2 (works on TEST.txt) 2021-08-01 17:33:20 +02:00
9a9742bf26 day 22/part 1: cleanup bash code, remove a loop 2021-08-01 12:38:37 +02:00
92f7ea1b2c update README 2021-07-31 16:56:51 +02:00
1a09c380a2 Day 22 part 1 (bash) 2021-07-31 13:13:30 +02:00
5b0a1d7b53 remove faulty use of sort command (implement qsort in pure bash) 2021-07-30 20:07:45 +02:00
92cc3e90c4 days 11/16: remove faulty use of external command (seq) 2021-07-30 19:21:16 +02:00
9c60bd6d12 removed calls to basename 2021-07-30 18:38:28 +02:00
2646b3fa75 day 22 init 2021-07-30 18:33:29 +02:00
16f4f9f926 forgot the code :) 2021-07-30 18:32:55 +02:00
984c6cc942 day 21 part 2 (bash) 2021-07-30 18:07:32 +02:00
3011ffcb5c shellcheck 2021-07-30 17:44:04 +02:00
16deb0f76b day 27/pert 1: bash optimization (25 sec -> 1.7 sec) 2021-07-30 17:31:06 +02:00
1db46ed0b0 day 21 part 1 (bash) 2021-07-30 17:18:48 +02:00
937c1b434b day 21 init 2021-07-28 17:17:13 +02:00
419376949f remove dead code 2021-07-28 16:53:15 +02:00
fbb553645e day 20 part 2 (bash): final version 2021-07-28 16:43:15 +02:00
44c9d00b85 Working day 20 part 2 en bash (before removing debug code) 2021-07-28 16:17:50 +02:00
ce4bcbe7c5 bug fix on lists element removal. tiles are now correctly assembled. 2021-07-28 12:25:51 +02:00
ba0a6217fd tiles re-assembling (tentative) 2021-07-27 18:32:33 +02:00
f4348d3faf add tools for tile manipulation, first code for part 2 2021-07-27 12:25:43 +02:00
150e4ba2a7 starting code for day 20/part 2 2021-07-25 17:12:36 +02:00
505 changed files with 66180 additions and 776 deletions

14
.gitignore vendored
View File

@@ -1,3 +1,15 @@
ex*-c
core
aoc-c
core*
.ccls*
.projectile
.dir-locals.el
gmon.out
*.o
ex*-cob
lib/
GPATH
GRTAGS
GTAGS
README.html
compile_commands.json

87
2019/Makefile Normal file
View File

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

132
2019/RESULTS.txt Normal file
View File

@@ -0,0 +1,132 @@
=========================================
================= day01 =================
=========================================
+++++++++++++++++ part 1
aoc-c : res=3318604
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
+++++++++++++++++ part 2
aoc-c : res=4975039
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+89
=========================================
================= day02 =================
=========================================
+++++++++++++++++ part 1
aoc-c : res=3790689
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+88
+++++++++++++++++ part 2
aoc-c : res=6533
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+88
=========================================
================= day03 =================
=========================================
+++++++++++++++++ part 1
aoc-c : res=860
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+99
+++++++++++++++++ part 2
aoc-c : res=9238
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+98
=========================================
================= day04 =================
=========================================
+++++++++++++++++ part 1
aoc-c : res=2090
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+90
+++++++++++++++++ part 2
aoc-c : res=1419
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+89
=========================================
================= day05 =================
=========================================
+++++++++++++++++ part 1
aoc-c : res=10987514
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
+++++++++++++++++ part 2
aoc-c : res=14195011
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
=========================================
================= day06 =================
=========================================
+++++++++++++++++ part 1
compiling aoc-c.c
aoc-c : res=453028
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+417
+++++++++++++++++ part 2
aoc-c : res=562
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+417
=========================================
================= day07 =================
=========================================
+++++++++++++++++ part 1
aoc-c : res=65464
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+94
+++++++++++++++++ part 2
aoc-c : res=1518124
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+94
=========================================
================= day08 =================
=========================================
+++++++++++++++++ part 1
aoc-c : res=2250
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+93
+++++++++++++++++ part 2
#### # # ## # # #
# # # # # # #
### #### # # # #
# # # # # # #
# # # # # # # #
# # # ## ## ####
aoc-c : res=0
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+90
=========================================
================= day09 =================
=========================================
+++++++++++++++++ part 1
aoc-c : res=2682107844
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+92
+++++++++++++++++ part 2
aoc-c : res=34738
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 1+1, page-faults: 0+95

100
2019/day01/INPUT.txt Normal file
View File

@@ -0,0 +1,100 @@
123457
98952
65241
62222
144922
111868
71513
74124
140122
133046
65283
107447
144864
136738
118458
91049
71486
100320
143765
88677
62034
139946
81017
128668
126450
56551
136839
64516
91821
139909
52907
78846
102008
58518
128627
71256
133546
90986
50808
139055
88769
94491
128902
55976
103658
123605
113468
128398
61725
100388
96763
101378
139952
138298
87171
51840
64828
58250
88273
136781
120097
127291
143752
117291
100023
147239
71296
100907
127612
122424
62942
95445
74040
118994
81810
146408
98939
71359
112120
100630
139576
98998
92481
53510
76343
125428
73447
62472
91370
73506
126539
50739
73133
81906
100856
52758
142303
107605
77797
124355

93
2019/day01/Makefile Normal file
View File

@@ -0,0 +1,93 @@
# 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
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 ex1 ex2
all: README.org ex1 ex2
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
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) aoc-c -p 2 < $(INPUT)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html
.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 $@

75
2019/day01/README.org Normal file
View File

@@ -0,0 +1,75 @@
** --- Day 1: The Tyranny of the Rocket Equation ---
Santa has become stranded at the edge of the Solar System while
delivering presents to other planets! To accurately calculate his
position in space, safely align his warp drive, and return to Earth in
time to save Christmas, he needs you to bring him measurements from
/fifty stars/.
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 Elves quickly load you into a spacecraft and prepare to launch.
At the first Go / No Go poll, every Elf is Go until the Fuel
Counter-Upper. They haven't determined the amount of fuel required yet.
Fuel required to launch a given /module/ is based on its /mass/.
Specifically, to find the fuel required for a module, take its mass,
divide by three, round down, and subtract 2.
For example:
- For a mass of =12=, divide by 3 and round down to get =4=, then
subtract 2 to get =2=.
- For a mass of =14=, dividing by 3 and rounding down still yields =4=,
so the fuel required is also =2=.
- For a mass of =1969=, the fuel required is =654=.
- For a mass of =100756=, the fuel required is =33583=.
The Fuel Counter-Upper needs to know the total fuel requirement. To find
it, individually calculate the fuel needed for the mass of each module
(your puzzle input), then add together all the fuel values.
/What is the sum of the fuel requirements/ for all of the modules on
your spacecraft?
Your puzzle answer was =3318604=.
** --- Part Two ---
During the second Go / No Go poll, the Elf in charge of the Rocket
Equation Double-Checker stops the launch sequence. Apparently, you
forgot to include additional fuel for the fuel you just added.
Fuel itself requires fuel just like a module - take its mass, divide by
three, round down, and subtract 2. However, that fuel /also/ requires
fuel, and /that/ fuel requires fuel, and so on. Any mass that would
require /negative fuel/ should instead be treated as if it requires
/zero fuel/; the remaining mass, if any, is instead handled by /wishing
really hard/, which has no mass and is outside the scope of this
calculation.
So, for each module mass, calculate its fuel and add it to the total.
Then, treat the fuel amount you just calculated as the input mass and
repeat the process, continuing until a fuel requirement is zero or
negative. For example:
- A module of mass =14= requires =2= fuel. This fuel requires no further
fuel (2 divided by 3 and rounded down is =0=, which would call for a
negative fuel), so the total fuel required is still just =2=.
- At first, a module of mass =1969= requires =654= fuel. Then, this fuel
requires =216= more fuel (=654 / 3 - 2=). =216= then requires =70=
more fuel, which requires =21= fuel, which requires =5= fuel, which
requires no further fuel. So, the total fuel required for a module of
mass =1969= is =654 + 216 + 70 + 21 + 5 = 966=.
- The fuel required by a module of mass =100756= and its fuel is:
=33583 + 11192 + 3728 + 1240 + 411 + 135 + 43 + 12 + 2 = 50346=.
/What is the sum of the fuel requirements/ for all of the modules on
your spacecraft when also taking into account the mass of the added
fuel? (Calculate the fuel requirements for each module separately, then
add them all up at the end.)
Your puzzle answer was =4975039=.
Both parts of this puzzle are complete! They provide two gold stars: **

74
2019/day01/aoc-c.c Normal file
View File

@@ -0,0 +1,74 @@
/* aoc-c.c: Advent of Code 2019, day 1 parts 1 & 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 "debug.h"
#include "pool.h"
#include "list.h"
#include "bits.h"
static u64 part1()
{
u64 res = 0;
int cur;
while (scanf("%d", &cur) != EOF)
res += cur / 3 - 2;
return res;
}
static u64 part2()
{
u64 res = 0;
int cur;
while (scanf("%d", &cur) != EOF)
while ((cur = cur / 3 - 2) > 0)
res += cur;
return res;
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
return 1;
}
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)
return usage(*av);
break;
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
printf("%s : res=%lu\n", *av, part == 1? part1(): part2());
exit (0);
}

1
2019/day02/EXAMPLE.txt Normal file
View File

@@ -0,0 +1 @@
1,9,10,3,2,3,11,0,99,30,40,50

1
2019/day02/EXAMPLE2.txt Normal file
View File

@@ -0,0 +1 @@
1,0,0,0,99

1
2019/day02/EXAMPLE3.txt Normal file
View File

@@ -0,0 +1 @@
2,3,0,3,99

1
2019/day02/EXAMPLE4.txt Normal file
View File

@@ -0,0 +1 @@
2,4,4,5,99,0

1
2019/day02/EXAMPLE5.txt Normal file
View File

@@ -0,0 +1 @@
1,1,1,4,99,5,6,0,99

1
2019/day02/INPUT.txt Normal file
View File

@@ -0,0 +1 @@
1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,13,19,1,9,19,23,2,13,23,27,2,27,13,31,2,31,10,35,1,6,35,39,1,5,39,43,1,10,43,47,1,5,47,51,1,13,51,55,2,55,9,59,1,6,59,63,1,13,63,67,1,6,67,71,1,71,10,75,2,13,75,79,1,5,79,83,2,83,6,87,1,6,87,91,1,91,13,95,1,95,13,99,2,99,13,103,1,103,5,107,2,107,10,111,1,5,111,115,1,2,115,119,1,119,6,0,99,2,0,14,0

93
2019/day02/Makefile Normal file
View File

@@ -0,0 +1,93 @@
# 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
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 ex1 ex2
all: README.org ex1 ex2
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
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) aoc-c -p 2 < $(INPUT)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html
.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 $@

159
2019/day02/README.org Normal file
View File

@@ -0,0 +1,159 @@
** --- Day 2: 1202 Program Alarm ---
On the way to your
[[https://en.wikipedia.org/wiki/Gravity_assist][gravity assist]] around
the Moon, your ship computer beeps angrily about a
"[[https://www.hq.nasa.gov/alsj/a11/a11.landing.html#1023832][1202
program alarm]]". On the radio, an Elf is already explaining how to
handle the situation: "Don't worry, that's perfectly norma--" The ship
computer [[https://en.wikipedia.org/wiki/Halt_and_Catch_Fire][bursts
into flames]].
You notify the Elves that the computer's
[[https://en.wikipedia.org/wiki/Magic_smoke][magic smoke]] seems to have
escaped. "That computer ran /Intcode/ programs like the gravity assist
program it was working on; surely there are enough spare parts up there
to build a new Intcode computer!"
An Intcode program is a list of
[[https://en.wikipedia.org/wiki/Integer][integers]] separated by commas
(like =1,0,0,3,99=). To run one, start by looking at the first integer
(called position =0=). Here, you will find an /opcode/ - either =1=,
=2=, or =99=. The opcode indicates what to do; for example, =99= means
that the program is finished and should immediately halt. Encountering
an unknown opcode means something went wrong.
Opcode =1= /adds/ together numbers read from two positions and stores
the result in a third position. The three integers /immediately after/
the opcode tell you these three positions - the first two indicate the
/positions/ from which you should read the input values, and the third
indicates the /position/ at which the output should be stored.
For example, if your Intcode computer encounters =1,10,20,30=, it should
read the values at positions =10= and =20=, add those values, and then
overwrite the value at position =30= with their sum.
Opcode =2= works exactly like opcode =1=, except it /multiplies/ the two
inputs instead of adding them. Again, the three integers after the
opcode indicate /where/ the inputs and outputs are, not their values.
Once you're done processing an opcode, /move to the next one/ by
stepping forward =4= positions.
For example, suppose you have the following program:
#+BEGIN_EXAMPLE
1,9,10,3,2,3,11,0,99,30,40,50
#+END_EXAMPLE
For the purposes of illustration, here is the same program split into
multiple lines:
#+BEGIN_EXAMPLE
1,9,10,3,
2,3,11,0,
99,
30,40,50
#+END_EXAMPLE
The first four integers, =1,9,10,3=, are at positions =0=, =1=, =2=, and
=3=. Together, they represent the first opcode (=1=, addition), the
positions of the two inputs (=9= and =10=), and the position of the
output (=3=). To handle this opcode, you first need to get the values at
the input positions: position =9= contains =30=, and position =10=
contains =40=. /Add/ these numbers together to get =70=. Then, store
this value at the output position; here, the output position (=3=) is
/at/ position =3=, so it overwrites itself. Afterward, the program looks
like this:
#+BEGIN_EXAMPLE
1,9,10,70,
2,3,11,0,
99,
30,40,50
#+END_EXAMPLE
Step forward =4= positions to reach the next opcode, =2=. This opcode
works just like the previous, but it multiplies instead of adding. The
inputs are at positions =3= and =11=; these positions contain =70= and
=50= respectively. Multiplying these produces =3500=; this is stored at
position =0=:
#+BEGIN_EXAMPLE
3500,9,10,70,
2,3,11,0,
99,
30,40,50
#+END_EXAMPLE
Stepping forward =4= more positions arrives at opcode =99=, halting the
program.
Here are the initial and final states of a few more small programs:
- =1,0,0,0,99= becomes =2,0,0,0,99= (=1 + 1 = 2=).
- =2,3,0,3,99= becomes =2,3,0,6,99= (=3 * 2 = 6=).
- =2,4,4,5,99,0= becomes =2,4,4,5,99,9801= (=99 * 99 = 9801=).
- =1,1,1,4,99,5,6,0,99= becomes =30,1,1,4,2,5,6,0,99=.
Once you have a working computer, the first step is to restore the
gravity assist program (your puzzle input) to the "1202 program alarm"
state it had just before the last computer caught fire. To do this,
/before running the program/, replace position =1= with the value =12=
and replace position =2= with the value =2=. /What value is left at
position =0=/ after the program halts?
Your puzzle answer was =3790689=.
** --- Part Two ---
"Good, the new computer seems to be working correctly! /Keep it nearby/
during this mission - you'll probably use it again. Real Intcode
computers support many more features than your new one, but we'll let
you know what they are as you need them."
"However, your current priority should be to complete your gravity
assist around the Moon. For this mission to succeed, we should settle on
some terminology for the parts you've already built."
Intcode programs are given as a list of integers; these values are used
as the initial state for the computer's /memory/. When you run an
Intcode program, make sure to start by initializing memory to the
program's values. A position in memory is called an /address/ (for
example, the first value in memory is at "address 0").
Opcodes (like =1=, =2=, or =99=) mark the beginning of an /instruction/.
The values used immediately after an opcode, if any, are called the
instruction's /parameters/. For example, in the instruction =1,2,3,4=,
=1= is the opcode; =2=, =3=, and =4= are the parameters. The instruction
=99= contains only an opcode and has no parameters.
The address of the current instruction is called the /instruction
pointer/; it starts at =0=. After an instruction finishes, the
instruction pointer increases by /the number of values in the
instruction/; until you add more instructions to the computer, this is
always =4= (=1= opcode + =3= parameters) for the add and multiply
instructions. (The halt instruction would increase the instruction
pointer by =1=, but it halts the program instead.)
"With terminology out of the way, we're ready to proceed. To complete
the gravity assist, you need to /determine what pair of inputs produces
the output =19690720=/."
The inputs should still be provided to the program by replacing the
values at addresses =1= and =2=, just like before. In this program, the
value placed in address =1= is called the /noun/, and the value placed
in address =2= is called the /verb/. Each of the two input values will
be between =0= and =99=, inclusive.
Once the program has halted, its output is available at address =0=,
also just like before. Each time you try a pair of inputs, make sure you
first /reset the computer's memory to the values in the program/ (your
puzzle input) - in other words, don't reuse memory from a previous
attempt.
Find the input /noun/ and /verb/ that cause the program to produce the
output =19690720=. /What is =100 * noun + verb=?/ (For example, if
=noun=12= and =verb=2=, the answer would be =1202=.)
Your puzzle answer was =6533=.
Both parts of this puzzle are complete! They provide two gold stars: **

150
2019/day02/aoc-c.c Normal file
View File

@@ -0,0 +1,150 @@
/* aoc-c.c: Advent of Code 2019, day 2 parts 1 & 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 <string.h>
#include "debug.h"
typedef enum {
ADD = 1,
MUL = 2,
RET = 99
} opcode_t;
#define MAXOPS 1024
struct program {
int length; /* total program length */
int cur; /* current position */
int ops[MAXOPS]; /* should really be dynamic */
};
#define OP(p) ((p)->ops + (p)->cur)
#define A1(p) ((p)->ops + *((p)->ops + (p)->cur + 1))
#define A2(p) ((p)->ops + *((p)->ops + (p)->cur + 2))
#define A3(p) ((p)->ops + *((p)->ops + (p)->cur + 3))
static int run(struct program *prog)
{
while (1) {
opcode_t opcode = *OP(prog);
switch (opcode) {
case ADD:
*A3(prog) = *A1(prog) + *A2(prog);
break;
case MUL:
*A3(prog) = *A1(prog) * *A2(prog);
break;
case RET:
return prog->ops[0];
default:
fprintf(stderr, "wrong opcode %d at %d.\n", opcode, prog->cur);
exit (1);
}
prog->cur += 4;
}
return -1;
}
static struct program *parse()
{
size_t alloc = 0;
ssize_t buflen;
char *buf = NULL, *token;
int input;
struct program *prog = NULL;
if ((buflen = getline(&buf, &alloc, stdin)) <= 0) {
fprintf(stderr, "error reading file.\n");
goto end;
}
if (!(prog = calloc(1, sizeof(struct program)))) {
fprintf(stderr, "cannot allocate program.\n");
goto freebuf;
}
for (token = strtok(buf, ","); token; token = strtok(NULL, ",")) {
if (prog->length >= MAXOPS - 1) {
fprintf(stderr, "overflow !\n");
free(prog);
prog = NULL;
goto freebuf;
}
input=atoi(token);
prog->ops[prog->length++] = input;
}
freebuf:
free(buf);
end:
return prog;
}
static int part1(struct program *p)
{
p->ops[1] = 12;
p->ops[2] = 2;
return run(p);
}
static int part2(struct program *p)
{
struct program work;
for (int noun = 0; noun < 100; ++noun) {
for (int verb = 0; verb < 100; ++verb) {
work = *p;
work.ops[1] = noun;
work.ops[2] = verb;
if (run(&work) == 19690720)
return noun * 100 + verb;
}
}
return -1;
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
return 1;
}
int main(int ac, char **av)
{
int opt, part = 1;
struct program *p;
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;
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
p = parse();
printf("%s : res=%d\n", *av, part == 1? part1(p): part2(p));
free(p);
exit (0);
}

2
2019/day03/EXAMPLE.txt Normal file
View File

@@ -0,0 +1,2 @@
R8,U5,L5,D3
U7,R6,D4,L4

2
2019/day03/EXAMPLE2.txt Normal file
View File

@@ -0,0 +1,2 @@
R75,D30,R83,U83,L12,D49,R71,U7,L72
U62,R66,U55,R34,D71,R55,D58,R83

2
2019/day03/EXAMPLE3.txt Normal file
View File

@@ -0,0 +1,2 @@
R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51
U98,R91,D20,R16,D67,R40,U7,R15,U6,R7

2
2019/day03/INPUT.txt Normal file
View File

@@ -0,0 +1,2 @@
R1000,D722,L887,D371,R430,D952,R168,D541,L972,D594,R377,U890,R544,U505,L629,U839,L680,D863,L315,D10,L482,U874,L291,U100,R770,D717,L749,U776,L869,D155,R250,U672,L195,D991,L556,D925,R358,U296,R647,D652,L790,D780,L865,U405,L400,D160,L460,U50,R515,D666,R306,U746,R754,U854,L332,U254,R673,U795,R560,U69,L507,U332,L328,U547,L717,U291,R626,U868,L583,D256,R371,U462,R793,U559,L571,U270,R738,U425,L231,U549,L465,U21,L647,U43,R847,U104,L699,U378,L549,D975,R13,D306,R532,D730,L566,U846,L903,D224,R448,D424,L727,D199,L626,D872,L541,D786,L304,U462,R347,U379,R29,D556,L775,D768,L284,D480,R654,D659,R818,D57,L77,U140,R619,D148,R686,D461,L910,U244,R115,D769,R968,U802,L737,U868,R399,D150,L791,U579,L856,D11,R115,U522,L443,D575,L133,U750,R437,U718,L79,D119,L97,U471,R817,U438,R157,U105,L219,U777,L965,U687,L906,D744,L983,D350,R664,D917,R431,D721,L153,U757,L665,U526,L49,U166,L59,D293,R962,D764,R538,U519,L24,U91,R11,U574,L647,U891,R44,D897,L715,U498,L624,D573,R287,U762,L613,D79,R122,U148,L849,D385,R792,D20,L512,D431,R818,U428,L10,D800,R773,D936,L594,D38,R824,D216,L220,U358,L463,U550,R968,D346,L658,U113,R813,U411,L730,D84,R479,U877,L730,D961,L839,D792,R424,U321,L105,D862,L815,D243,L521,D913,L1,D513,L269,U495,L27,U16,R904,D926,R640,U948,R346,D240,L273,U131,L296,U556,R347,D640,L261,D43,R136,U824,R126,U583,R736,U530,L734,U717,L256,U362,L86,U48,R851,U519,L610,D134,L554,D766,L179,U637,R71,D895,L21,D908,R486,D863,R31,U85,R420,D718,R466,D861,R655,D304,L701,D403,L860,D208,L595,U64,R999
L992,D463,R10,D791,R312,D146,R865,D244,L364,D189,R35,U328,R857,D683,L660,D707,L908,D277,R356,U369,R197,D35,R625,D862,L769,U705,L728,U999,R938,U233,L595,U266,L697,U966,L536,D543,L669,D829,R910,U693,R753,D389,L647,U603,L660,D787,L138,D119,L131,D266,R268,D917,R776,U290,R920,U904,L46,D139,L341,D19,R982,U790,L981,U791,L147,U30,L246,U677,R343,D492,R398,D234,R76,D423,L709,D392,R741,U408,R878,U29,R446,U36,R806,U78,L76,D813,R584,U682,L187,U666,L340,D301,L694,U15,R800,U276,L755,U558,R366,D309,R571,U976,L286,D833,R318,U365,L864,U408,L352,D61,R284,D272,R240,D845,L206,U721,R367,D541,R628,U581,L750,D680,R695,D30,R849,U743,L214,U605,R533,U493,R803,D783,R168,U877,L61,D726,L794,D116,R717,U44,R964,U674,L291,D372,L381,D523,L644,U438,R983,D390,R520,D471,R556,D693,L919,D863,R84,D629,L264,D429,R82,U64,R835,D801,R93,U770,R441,D152,L718,D788,L797,U699,L82,U206,L40,U952,R902,U570,L759,D655,L131,D901,L470,D804,L407,U458,L922,D21,L171,U841,L237,D301,R192,D293,R984,U243,R846,U139,L413,U162,R925,D235,L115,U443,L884,D910,R335,U274,L338,U160,R125,D775,R824,D821,R531,D761,L189,U822,L602,D732,R473,U149,L128,U30,R77,D957,R811,D154,L988,D237,R425,D855,R482,D571,R134,D731,L905,U869,R916,D689,L17,U24,R353,D996,R832,U855,L76,U659,R581,D483,R821,D145,R199,D344,R487,D436,L92,U491,R365,D909,L17,D148,R307,U57,R666,U660,R195,D767,R612,D902,L594,D299,R670,D881,L583,D793,R58,U89,L99,D355,R394,D350,R920,U544,R887,U564,L238,U979,L565,D914,L95,U150,R292,U495,R506,U475,R813,D308,L797,D484,R9

93
2019/day03/Makefile Normal file
View File

@@ -0,0 +1,93 @@
# 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
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 ex1 ex2
all: README.org ex1 ex2
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
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) aoc-c -p 2 < $(INPUT)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html
.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 $@

119
2019/day03/README.org Normal file
View File

@@ -0,0 +1,119 @@
** --- Day 3: Crossed Wires ---
The gravity assist was successful, and you're well on your way to the
Venus refuelling station. During the rush back on Earth, the fuel
management system wasn't completely installed, so that's next on the
priority list.
Opening the front panel reveals a jumble of wires. Specifically, /two
wires/ are connected to a central port and extend outward on a grid. You
trace the path each wire takes as it leaves the central port, one wire
per line of text (your puzzle input).
The wires twist and turn, but the two wires occasionally cross paths. To
fix the circuit, you need to /find the intersection point closest to the
central port/. Because the wires are on a grid, use the
[[https://en.wikipedia.org/wiki/Taxicab_geometry][Manhattan distance]]
for this measurement. While the wires do technically cross right at the
central port where they both start, this point does not count, nor does
a wire count as crossing with itself.
For example, if the first wire's path is =R8,U5,L5,D3=, then starting
from the central port (=o=), it goes right =8=, up =5=, left =5=, and
finally down =3=:
#+BEGIN_EXAMPLE
...........
...........
...........
....+----+.
....|....|.
....|....|.
....|....|.
.........|.
.o-------+.
...........
#+END_EXAMPLE
Then, if the second wire's path is =U7,R6,D4,L4=, it goes up =7=, right
=6=, down =4=, and left =4=:
#+BEGIN_EXAMPLE
...........
.+-----+...
.|.....|...
.|..+--X-+.
.|..|..|.|.
.|.-X--+.|.
.|..|....|.
.|.......|.
.o-------+.
...........
#+END_EXAMPLE
These wires cross at two locations (marked =X=), but the lower-left one
is closer to the central port: its distance is =3 + 3 = 6=.
Here are a few more examples:
- =R75,D30,R83,U83,L12,D49,R71,U7,L72= \\
=U62,R66,U55,R34,D71,R55,D58,R83=
= distance =159=
- =R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51= \\
=U98,R91,D20,R16,D67,R40,U7,R15,U6,R7=
= distance =135=
/What is the Manhattan distance/ from the central port to the closest
intersection?
Your puzzle answer was =860=.
** --- Part Two ---
It turns out that this circuit is very timing-sensitive; you actually
need to /minimize the signal delay/.
To do this, calculate the /number of steps/ each wire takes to reach
each intersection; choose the intersection where the /sum of both wires'
steps/ is lowest. If a wire visits a position on the grid multiple
times, use the steps value from the /first/ time it visits that position
when calculating the total value of a specific intersection.
The number of steps a wire takes is the total number of grid squares the
wire has entered to get to that location, including the intersection
being considered. Again consider the example from above:
#+BEGIN_EXAMPLE
...........
.+-----+...
.|.....|...
.|..+--X-+.
.|..|..|.|.
.|.-X--+.|.
.|..|....|.
.|.......|.
.o-------+.
...........
#+END_EXAMPLE
In the above example, the intersection closest to the central port is
reached after =8+5+5+2 = 20= steps by the first wire and =7+6+4+3 = 20=
steps by the second wire for a total of =20+20 = 40= steps.
However, the top-right intersection is better: the first wire takes only
=8+5+2 = 15= and the second wire takes only =7+6+2 = 15=, a total of
=15+15 = 30= steps.
Here are the best steps for the extra examples from above:
- =R75,D30,R83,U83,L12,D49,R71,U7,L72= \\
=U62,R66,U55,R34,D71,R55,D58,R83=
= =610= steps
- =R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51= \\
=U98,R91,D20,R16,D67,R40,U7,R15,U6,R7=
= =410= steps
/What is the fewest combined steps the wires must take to reach an
intersection?/
Your puzzle answer was =9238=.
Both parts of this puzzle are complete! They provide two gold stars: **

168
2019/day03/aoc-c.c Normal file
View File

@@ -0,0 +1,168 @@
/* aoc-c.c: Advent of Code 2019, day 3 parts 1 & 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 <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "br.h"
#include "bits.h"
#include "debug.h"
#include "list.h"
#include "pool.h"
typedef enum { DOWN = 'D', LEFT = 'L', RIGHT = 'R', UP = 'U' } dir_t;
struct point {
int x, y;
};
/**
* struct wire - one segment on wire.
* @dist: total distance from start before the current segment
* @dir: indicates which of ends[0] and ends[1] was the original line end point
* @ends: segment ends, ordered (ends[0].x <= ends[1].x and ends[0].y <= ends[1].y)
* @list: segments list
*/
struct wire {
int dist;
int dir;
struct point ends[2];
struct list_head list;
};
static pool_t *wire_pool;
static struct list_head *parse(struct list_head *wires)
{
size_t alloc = 0;
ssize_t buflen;
char *buf = NULL, *token;
for (int line = 0; line < 2; ++line) {
struct point p0 = {0, 0}, p1 = {0, 0};
int totdist = 0;
if ((buflen = getline(&buf, &alloc, stdin)) <= 0) {
fprintf(stderr, "error %d reading input.\n", errno);
wires = NULL;
goto end;
}
for (token = strtok(buf, ","); token; token = strtok(NULL, ",")) {
dir_t dir = *token;
int dist = atoi(token + 1);
struct wire *new = pool_get(wire_pool);
INIT_LIST_HEAD(&new->list);
new->dist = totdist;
totdist += abs(dist);
new->dir = !!(dir == DOWN || dir == LEFT);
if (dir == DOWN || dir == UP) /* vertical segment */
p1.y = p0.y + (1 - (new->dir * 2)) * dist;
else /* horizontal segment */
p1.x = p0.x + (1 - (new->dir * 2)) * dist;
new->ends[0].x = min(p0.x, p1.x); /* order ends (p0.? <= p1.?) */
new->ends[0].y = min(p0.y, p1.y);
new->ends[1].x = max(p0.x, p1.x);
new->ends[1].y = max(p0.y, p1.y);
list_add_tail(&new->list, &wires[line]);
p0 = p1;
}
}
end:
free(buf);
return wires;
}
static struct point *intersect(struct wire *w0, struct wire *w1, struct point *ret)
{
if (w0->ends[0].x == w0->ends[1].x) { /* w0 vertical */
/* BUG: overlapping wires is not handled */
if (w0->ends[0].x >= w1->ends[0].x && w0->ends[1].x <= w1->ends[1].x &&
w0->ends[0].y <= w1->ends[0].y && w0->ends[1].y >= w1->ends[1].y) {
ret->x = w0->ends[0].x;
ret->y = w1->ends[0].y;
return ret;
}
return NULL;
} else { /* w0 horizontal */
if (w0->ends[0].x <= w1->ends[0].x && w0->ends[1].x >= w1->ends[1].x &&
w0->ends[0].y <= w1->ends[1].y && w0->ends[1].y >= w1->ends[0].y) {
ret->x = w1->ends[0].x;
ret->y = w0->ends[0].y;
return ret;
}
return NULL;
}
}
/* part 1 */
#define manhattan(point) (abs(point.x) + abs(point.y))
/* part 2 */
#define signal(point, w0, w1) \
(w0->dist + w1->dist + \
abs(cross.x - w0->ends[w0->dir].x) + abs(cross.y - w0->ends[w0->dir].y) + \
abs(cross.x - w1->ends[w1->dir].x) + abs(cross.y - w1->ends[w1->dir].y))
static int doit(struct list_head *w, int part)
{
struct wire *w0, *w1;
struct point cross;
s32 res = INT32_MAX;
list_for_each_entry(w0, &w[0], list)
list_for_each_entry(w1, &w[1], list)
if (intersect(w0, w1, &cross))
res = min_not_zero(res, part == 1 ?
manhattan(cross) :
signal(cross, w0, w1));
return res;
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
return 1;
}
int main(int ac, char **av)
{
int opt, part = 1;
struct list_head wires[2] = { LIST_HEAD_INIT(wires[0]), LIST_HEAD_INIT(wires[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);
}
}
if (optind < ac)
return usage(*av);
wire_pool = pool_create("wire", 256, sizeof(struct wire));
if (parse(wires)) {
printf("%s : res=%d\n", *av, doit(wires, part));
pool_destroy(wire_pool);
}
exit (0);
}

1
2019/day04/INPUT.txt Normal file
View File

@@ -0,0 +1 @@
130254-678275

93
2019/day04/Makefile Normal file
View File

@@ -0,0 +1,93 @@
# 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
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 ex1 ex2
all: README.org ex1 ex2
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
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) aoc-c -p 2 < $(INPUT)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html
.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 $@

43
2019/day04/README.org Normal file
View File

@@ -0,0 +1,43 @@
** --- Day 4: Secure Container ---
You arrive at the Venus fuel depot only to discover it's protected by a
password. The Elves had written the password on a sticky note, but
someone threw it out.
However, they do remember a few key facts about the password:
- It is a six-digit number.
- The value is within the range given in your puzzle input.
- Two adjacent digits are the same (like =22= in =122345=).
- Going from left to right, the digits /never decrease/; they only ever
increase or stay the same (like =111123= or =135679=).
Other than the range rule, the following are true:
- =111111= meets these criteria (double =11=, never decreases).
- =223450= does not meet these criteria (decreasing pair of digits
=50=).
- =123789= does not meet these criteria (no double).
/How many different passwords/ within the range given in your puzzle
input meet these criteria?
Your puzzle answer was =2090=.
** --- Part Two ---
An Elf just remembered one more important detail: the two adjacent
matching digits /are not part of a larger group of matching digits/.
Given this additional criterion, but still ignoring the range rule, the
following are now true:
- =112233= meets these criteria because the digits never decrease and
all repeated digits are exactly two digits long.
- =123444= no longer meets the criteria (the repeated =44= is part of a
larger group of =444=).
- =111122= meets the criteria (even though =1= is repeated more than
twice, it still contains a double =22=).
/How many different passwords/ within the range given in your puzzle
input meet all of the criteria?
Your puzzle answer was =1419=.

126
2019/day04/aoc-c.c Normal file
View File

@@ -0,0 +1,126 @@
/* aoc-c.c: Advent of Code 2019, day 4 parts 1 & 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 <malloc.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include "debug.h"
#include "likely.h"
/**
* next_number() - finds next suitable number after a faulty right digit
* @number: the number
* @faulty: the faulty digit position (1, 10, 100, etc...)
* @left: the left digit of faulty one
*
* This function is called when rule 4 is violated:
* "Going from left to right, the digits never decrease."
* Example: 453456
* ^
* Here we will replace the faulty digit and next ones with its left digit
* value (5 here). Returned number will be 455555.
* This function allowed to save 546,495/548,022 calls to is_valid(), which
* is 99.7%.
*/
static int next_number(int number, int faulty, int left)
{
int next = number - number % (faulty * 10);
for (; faulty; faulty /= 10)
next += left * faulty;
return next;
}
static int is_valid(int number, int part, int *next)
{
int valid = 0, dups[10] = { 0 }, work = number;
int digit, dec = number + 1, faulty = 1;
*next = number + 1;
for (digit = number % 10; number > 10; digit = dec, faulty *= 10) {
number /= 10;
dec = number % 10;
if (dec > digit) {
*next = next_number(work, faulty, dec);
return 0;
}
if (dec == digit) {
valid = 1;
dups[digit] += 2;
}
}
if (!valid || part == 1)
return valid;
for (int i = 0; i < 10; ++i)
if (dups[i] == 2)
return 1;
return 0;
}
static int doit(int *nums, int part)
{
int res = 0, next = 0;
for (int i = nums[0]; i < nums[1]; i = next) {
if (unlikely(is_valid(i, part, &next)))
res++;
}
return res;
}
static int *parse(int *res)
{
size_t alloc = 0;
char *buf = NULL;
getline(&buf, &alloc, stdin);
*res = atoi(strtok(buf, "-"));
*(res+1) = atoi(strtok(NULL, "-"));
free(buf);
return res;
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
return 1;
}
int main(int ac, char **av)
{
int opt, part = 1;
int nums[2];
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);
}
}
if (optind < ac)
return usage(*av);
parse(nums);
printf("%s : res=%d\n", *av, doit(nums, part));
exit (0);
}

1
2019/day05/EXAMPLE.txt Normal file
View File

@@ -0,0 +1 @@
3,0,4,0,99

1
2019/day05/EXAMPLE1.txt Normal file
View File

@@ -0,0 +1 @@
1002,4,3,4,33

1
2019/day05/EXAMPLE2.txt Normal file
View File

@@ -0,0 +1 @@
3,9,8,9,10,9,4,9,99,-1,8

1
2019/day05/EXAMPLE3.txt Normal file
View File

@@ -0,0 +1 @@
3,9,7,9,10,9,4,9,99,-1,8

1
2019/day05/EXAMPLE4.txt Normal file
View File

@@ -0,0 +1 @@
3,3,1108,-1,8,3,4,3,99

1
2019/day05/EXAMPLE5.txt Normal file
View File

@@ -0,0 +1 @@
3,3,1107,-1,8,3,4,3,99

1
2019/day05/EXAMPLE6.txt Normal file
View File

@@ -0,0 +1 @@
3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9

1
2019/day05/EXAMPLE7.txt Normal file
View File

@@ -0,0 +1 @@
3,3,1105,-1,9,1101,0,0,12,4,12,99,1

1
2019/day05/EXAMPLE8.txt Normal file
View File

@@ -0,0 +1 @@
3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99

1
2019/day05/INPUT.txt Normal file
View File

@@ -0,0 +1 @@
3,225,1,225,6,6,1100,1,238,225,104,0,1101,86,8,225,1101,82,69,225,101,36,65,224,1001,224,-106,224,4,224,1002,223,8,223,1001,224,5,224,1,223,224,223,102,52,148,224,101,-1144,224,224,4,224,1002,223,8,223,101,1,224,224,1,224,223,223,1102,70,45,225,1002,143,48,224,1001,224,-1344,224,4,224,102,8,223,223,101,7,224,224,1,223,224,223,1101,69,75,225,1001,18,85,224,1001,224,-154,224,4,224,102,8,223,223,101,2,224,224,1,224,223,223,1101,15,59,225,1102,67,42,224,101,-2814,224,224,4,224,1002,223,8,223,101,3,224,224,1,223,224,223,1101,28,63,225,1101,45,22,225,1101,90,16,225,2,152,92,224,1001,224,-1200,224,4,224,102,8,223,223,101,7,224,224,1,223,224,223,1101,45,28,224,1001,224,-73,224,4,224,1002,223,8,223,101,7,224,224,1,224,223,223,1,14,118,224,101,-67,224,224,4,224,1002,223,8,223,1001,224,2,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,7,677,677,224,102,2,223,223,1005,224,329,1001,223,1,223,1008,226,226,224,1002,223,2,223,1005,224,344,1001,223,1,223,1107,677,226,224,1002,223,2,223,1006,224,359,1001,223,1,223,107,677,677,224,102,2,223,223,1005,224,374,101,1,223,223,1108,677,226,224,102,2,223,223,1005,224,389,1001,223,1,223,1007,677,677,224,1002,223,2,223,1005,224,404,101,1,223,223,1008,677,226,224,102,2,223,223,1005,224,419,101,1,223,223,1108,226,677,224,102,2,223,223,1006,224,434,1001,223,1,223,8,677,226,224,1002,223,2,223,1005,224,449,101,1,223,223,1008,677,677,224,1002,223,2,223,1006,224,464,1001,223,1,223,1108,226,226,224,1002,223,2,223,1005,224,479,1001,223,1,223,1007,226,677,224,102,2,223,223,1005,224,494,1001,223,1,223,1007,226,226,224,102,2,223,223,1005,224,509,101,1,223,223,107,677,226,224,1002,223,2,223,1006,224,524,1001,223,1,223,108,677,677,224,102,2,223,223,1006,224,539,101,1,223,223,7,677,226,224,102,2,223,223,1006,224,554,1001,223,1,223,1107,226,677,224,102,2,223,223,1005,224,569,101,1,223,223,108,677,226,224,1002,223,2,223,1006,224,584,101,1,223,223,108,226,226,224,102,2,223,223,1006,224,599,1001,223,1,223,1107,226,226,224,102,2,223,223,1006,224,614,1001,223,1,223,8,226,677,224,102,2,223,223,1006,224,629,1001,223,1,223,107,226,226,224,102,2,223,223,1005,224,644,101,1,223,223,8,226,226,224,102,2,223,223,1006,224,659,101,1,223,223,7,226,677,224,102,2,223,223,1005,224,674,101,1,223,223,4,223,99,226

93
2019/day05/Makefile Normal file
View File

@@ -0,0 +1,93 @@
# 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
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 ex1 ex2
all: README.org ex1 ex2
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
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) aoc-c -p 2 < $(INPUT)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html
.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 $@

184
2019/day05/README.org Normal file
View File

@@ -0,0 +1,184 @@
** --- Day 5: Sunny with a Chance of Asteroids ---
You're starting to sweat as the ship makes its way toward Mercury. The
Elves suggest that you get the air conditioner working by upgrading your
ship computer to support the Thermal Environment Supervision Terminal.
The Thermal Environment Supervision Terminal (TEST) starts by running a
/diagnostic program/ (your puzzle input). The TEST diagnostic program
will run on [[file:~/dev/advent-of-code/2019/day02][your existing Intcode computer]] after a few
modifications:
/First/, you'll need to add /two new instructions/:
- Opcode =3= takes a single integer as /input/ and saves it to the
position given by its only parameter. For example, the instruction
=3,50= would take an input value and store it at address =50=.
- Opcode =4= /outputs/ the value of its only parameter. For example, the
instruction =4,50= would output the value at address =50=.
Programs that use these instructions will come with documentation that
explains what should be connected to the input and output. The program
=3,0,4,0,99= outputs whatever it gets as input, then halts.
/Second/, you'll need to add support for /parameter modes/:
Each parameter of an instruction is handled based on its parameter mode.
Right now, your ship computer already understands parameter mode =0=,
/position mode/, which causes the parameter to be interpreted as a
/position/ - if the parameter is =50=, its value is /the value stored at
address =50= in memory/. Until now, all parameters have been in position
mode.
Now, your ship computer will also need to handle parameters in mode =1=,
/immediate mode/. In immediate mode, a parameter is interpreted as a
/value/ - if the parameter is =50=, its value is simply /=50=/.
Parameter modes are stored in the same value as the instruction's
opcode. The opcode is a two-digit number based only on the ones and tens
digit of the value, that is, the opcode is the rightmost two digits of
the first value in an instruction. Parameter modes are single digits,
one per parameter, read right-to-left from the opcode: the first
parameter's mode is in the hundreds digit, the second parameter's mode
is in the thousands digit, the third parameter's mode is in the
ten-thousands digit, and so on. Any missing modes are =0=.
For example, consider the program =1002,4,3,4,33=.
The first instruction, =1002,4,3,4=, is a /multiply/ instruction - the
rightmost two digits of the first value, =02=, indicate opcode =2=,
multiplication. Then, going right to left, the parameter modes are =0=
(hundreds digit), =1= (thousands digit), and =0= (ten-thousands digit,
not present and therefore zero):
#+BEGIN_EXAMPLE
ABCDE
1002
DE - two-digit opcode, 02 == opcode 2
C - mode of 1st parameter, 0 == position mode
B - mode of 2nd parameter, 1 == immediate mode
A - mode of 3rd parameter, 0 == position mode,
omitted due to being a leading zero
#+END_EXAMPLE
This instruction multiplies its first two parameters. The first
parameter, =4= in position mode, works like it did before - its value is
the value stored at address =4= (=33=). The second parameter, =3= in
immediate mode, simply has value =3=. The result of this operation,
=33 * 3 = 99=, is written according to the third parameter, =4= in
position mode, which also works like it did before - =99= is written to
address =4=.
Parameters that an instruction writes to will /never be in immediate
mode/.
/Finally/, some notes:
- It is important to remember that the instruction pointer should
increase by /the number of values in the instruction/ after the
instruction finishes. Because of the new instructions, this amount is
no longer always =4=.
- Integers can be negative: =1101,100,-1,4,0= is a valid program (find
=100 + -1=, store the result in position =4=).
The TEST diagnostic program will start by requesting from the user the
ID of the system to test by running an /input/ instruction - provide it
=1=, the ID for the ship's air conditioner unit.
It will then perform a series of diagnostic tests confirming that
various parts of the Intcode computer, like parameter modes, function
correctly. For each test, it will run an /output/ instruction indicating
how far the result of the test was from the expected value, where =0=
means the test was successful. Non-zero outputs mean that a function is
not working correctly; check the instructions that were run before the
output instruction to see which one failed.
Finally, the program will output a /diagnostic code/ and immediately
halt. This final output isn't an error; an output followed immediately
by a halt means the program finished. If all outputs were zero except
the diagnostic code, the diagnostic program ran successfully.
After providing =1= to the only input instruction and passing all the
tests, /what diagnostic code does the program produce?/
Your puzzle answer was =10987514=.
** --- Part Two ---
The air conditioner comes online! Its cold air feels good for a while,
but then the TEST alarms start to go off. Since the air conditioner
can't vent its heat anywhere but back into the spacecraft, it's actually
making the air inside the ship /warmer/.
Instead, you'll need to use the TEST to extend the
[[https://en.wikipedia.org/wiki/Spacecraft_thermal_control][thermal
radiators]]. Fortunately, the diagnostic program (your puzzle input) is
already equipped for this. Unfortunately, your Intcode computer is not.
Your computer is only missing a few opcodes:
- Opcode =5= is /jump-if-true/: if the first parameter is /non-zero/, it
sets the instruction pointer to the value from the second parameter.
Otherwise, it does nothing.
- Opcode =6= is /jump-if-false/: if the first parameter /is zero/, it
sets the instruction pointer to the value from the second parameter.
Otherwise, it does nothing.
- Opcode =7= is /less than/: if the first parameter is /less than/ the
second parameter, it stores =1= in the position given by the third
parameter. Otherwise, it stores =0=.
- Opcode =8= is /equals/: if the first parameter is /equal to/ the
second parameter, it stores =1= in the position given by the third
parameter. Otherwise, it stores =0=.
Like all instructions, these instructions need to support /parameter
modes/ as described above.
Normally, after an instruction is finished, the instruction pointer
increases by the number of values in that instruction. /However/, if the
instruction modifies the instruction pointer, that value is used and the
instruction pointer is /not automatically increased/.
For example, here are several programs that take one input, compare it
to the value =8=, and then produce one output:
- =3,9,8,9,10,9,4,9,99,-1,8= - Using /position mode/, consider whether
the input is /equal to/ =8=; output =1= (if it is) or =0= (if it is
not).
- =3,9,7,9,10,9,4,9,99,-1,8= - Using /position mode/, consider whether
the input is /less than/ =8=; output =1= (if it is) or =0= (if it is
not).
- =3,3,1108,-1,8,3,4,3,99= - Using /immediate mode/, consider whether
the input is /equal to/ =8=; output =1= (if it is) or =0= (if it is
not).
- =3,3,1107,-1,8,3,4,3,99= - Using /immediate mode/, consider whether
the input is /less than/ =8=; output =1= (if it is) or =0= (if it is
not).
Here are some jump tests that take an input, then output =0= if the
input was zero or =1= if the input was non-zero:
- =3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9= (using /position mode/)
- =3,3,1105,-1,9,1101,0,0,12,4,12,99,1= (using /immediate mode/)
Here's a larger example:
#+BEGIN_EXAMPLE
3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,
999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99
#+END_EXAMPLE
The above example program uses an input instruction to ask for a single
number. The program will then output =999= if the input value is below
=8=, output =1000= if the input value is equal to =8=, or output =1001=
if the input value is greater than =8=.
This time, when the TEST diagnostic program runs its input instruction
to get the ID of the system to test, /provide it =5=/, the ID for the
ship's thermal radiator controller. This diagnostic test suite only
outputs one number, the /diagnostic code/.
/What is the diagnostic code for system ID =5=?/
Your puzzle answer was =14195011=.
Both parts of this puzzle are complete! They provide two gold stars: **

162
2019/day05/aoc-c.c Normal file
View File

@@ -0,0 +1,162 @@
/* aoc-c.c: Advent of Code 2019, day 5 parts 1 & 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 <string.h>
#include "br.h"
#include "bits.h"
#include "debug.h"
typedef enum {
ADD = 1, MUL = 2,
INP = 3, OUT = 4,
JMP_T = 5, JMP_F = 6,
SET_LT = 7, SET_EQ = 8,
HLT = 99
} opcode_t;
/**
* ops - array of op-codes, mnemo, and number of parameters
* @op: An integer, the opcode
* @nargs: Opcode number of parameters (unused)
* @jump: Next instruction (usually @nargs + 1)
* @mnemo: Opcode mnemo (unused, for debug)
*/
typedef struct {
int op;
u8 nargs;
u8 jump;
char *mnemo;
} ops_t;
#define MAXOPS 1024
typedef struct {
int length; /* total program length */
int cur; /* current position */
int mem [MAXOPS]; /* should really be dynamic */
} program_t;
static ops_t ops[] = {
[ADD] = { ADD, 3, 4, __stringify(ADD) },
[MUL] = { MUL, 3, 4, __stringify(MUL) },
[INP] = { INP, 1, 2, __stringify(INP) },
[OUT] = { OUT, 1, 2, __stringify(OUT) },
[JMP_T] = { JMP_T, 2, 3, __stringify(JMP_T) },
[JMP_F] = { JMP_F, 2, 3, __stringify(JMP_F) },
[SET_LT] = { SET_LT, 3, 4, __stringify({SET_LT) },
[SET_EQ] = { SET_EQ, 3, 4, __stringify(SET_EQ) },
[HLT] = { HLT, 0, 1, __stringify(HLT) }
};
static int _flag_pow10[] = {1, 100, 1000, 10000};
#define OP(p, n) ((p->mem[n]) % 100)
#define ISDIRECT(p, n, i) ((((p->mem[n]) / _flag_pow10[i]) % 10))
#define DIRECT(p, i) ((p)->mem[i])
#define INDIRECT(p, i) (DIRECT(p, DIRECT(p, i)))
#define peek(p, n, i) (ISDIRECT(p, n, i)? DIRECT(p, n + i): INDIRECT(p, n + i))
#define poke(p, n, i, val) do { \
INDIRECT(p, n + i) = val; } \
while (0)
static int run(program_t *p, int in)
{
int out = -1;
while (1) {
int op = OP(p, p->cur), cur = p->cur;
if (!(ops[op].op)) {
fprintf(stderr, "PANIC: illegal instruction %d at %d.\n", op, p->cur);
return -1;
}
switch (op) {
case ADD:
poke(p, p->cur, 3, peek(p, p->cur, 1) + peek(p, p->cur, 2));
break;
case MUL:
poke(p, p->cur, 3, peek(p, p->cur, 1) * peek(p, p->cur, 2));
break;
case INP:
poke(p, p->cur, 1, in);
break;
case OUT:
out = peek(p, p->cur, 1);
break;
case JMP_T:
if (peek(p, p->cur, 1))
p->cur = peek(p, p->cur, 2);
break;
case JMP_F:
if (!peek(p, p->cur, 1))
p->cur = peek(p, p->cur, 2);
break;
case SET_LT:
poke(p, p->cur, 3, peek(p, p->cur, 1) < peek(p, p->cur, 2) ? 1: 0);
break;
case SET_EQ:
poke(p, p->cur, 3, peek(p, p->cur, 1) == peek(p, p->cur, 2) ? 1: 0);
break;
case HLT:
return out;
}
if (p->cur == cur)
p->cur += ops[op].jump;
}
}
static void parse(program_t *prog)
{
while (scanf("%d%*c", &prog->mem[prog->length++]) > 0)
;
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int main(int ac, char **av)
{
int opt, part = 1, in = -1;
program_t p = { 0 };
while ((opt = getopt(ac, av, "d:p:i:")) != -1) {
switch (opt) {
case 'd':
debug_level_set(atoi(optarg));
break;
case 'i':
in = atoi(optarg);
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
if (in == -1)
in = part == 1? 1: 5;
parse(&p);
printf("%s : res=%d\n", *av, run(&p, in));
exit (0);
}

53
2019/day05/run-examples.sh Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
make compile
printf "***** EXAMPLE.txt: input value, then output it\n"
printf "Expected: 1\t"
./aoc-c -i 1 < EXAMPLE.txt
printf "Expected: 5\t"
./aoc-c -i 5 < EXAMPLE.txt
printf "\n***** EXAMPLE2.txt: equal test, position mode\n"
printf "Expected: 1\t"
./aoc-c -i 8 < EXAMPLE2.txt
printf "Expected: 0\t"
./aoc-c -i 0 < EXAMPLE.txt
printf "\n***** EXAMPLE3.txt: less than test, position mode\n"
printf "Expected: 1\t"
./aoc-c -i 7 < EXAMPLE3.txt
printf "Expected: 0\t"
./aoc-c -i 8 < EXAMPLE3.txt
printf "\n***** EXAMPLE4.txt: equal test, immediate mode\n"
printf "Expected: 1\t"
./aoc-c -i 8 < EXAMPLE4.txt
printf "Expected: 0\t"
./aoc-c -i 0 < EXAMPLE4.txt
printf "\n***** EXAMPLE5.txt: less than test, immediate mode\n"
printf "Expected: 1\t"
./aoc-c -i 7 < EXAMPLE5.txt
printf "Expected: 0\t"
./aoc-c -i 8 < EXAMPLE5.txt
printf "\n***** EXAMPLE6.txt: equal/jump test, position mode\n"
printf "Expected: 1\t"
./aoc-c -i 8 < EXAMPLE6.txt
printf "Expected: 0\t"
./aoc-c -i 0 < EXAMPLE6.txt
printf "\n***** EXAMPLE7.txt: equal/jump test, immediate mode\n"
printf "Expected: 1\t"
./aoc-c -i 8 < EXAMPLE7.txt
printf "Expected: 0\t"
./aoc-c -i 0 < EXAMPLE7.txt
printf "\n***** EXAMPLE8.txt: equal/less/jump test, mixed mode\n"
printf "Expected:999\t"
./aoc-c -i 7 < EXAMPLE8.txt
printf "Expected: 1000\t"
./aoc-c -i 8 < EXAMPLE8.txt
printf "Expected: 1001\t"
./aoc-c -i 9 < EXAMPLE8.txt

11
2019/day06/EXAMPLE.txt Normal file
View File

@@ -0,0 +1,11 @@
COM)B
B)C
C)D
D)E
E)F
B)G
G)H
D)I
E)J
J)K
K)L

13
2019/day06/EXAMPLE2.txt Normal file
View File

@@ -0,0 +1,13 @@
COM)B
B)C
C)D
D)E
E)F
B)G
G)H
D)I
E)J
J)K
K)L
K)YOU
I)SAN

2306
2019/day06/INPUT.txt Normal file

File diff suppressed because it is too large Load Diff

93
2019/day06/Makefile Normal file
View File

@@ -0,0 +1,93 @@
# 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
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 ex1 ex2
all: README.org ex1 ex2
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
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) aoc-c -p 2 < $(INPUT)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html
.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 $@

147
2019/day06/README.org Normal file
View File

@@ -0,0 +1,147 @@
** --- Day 6: Universal Orbit Map ---
You've landed at the Universal Orbit Map facility on Mercury. Because
navigation in space often involves transferring between orbits, the
orbit maps here are useful for finding efficient routes between, for
example, you and Santa. You download a map of the local orbits (your
puzzle input).
Except for the universal Center of Mass (=COM=), every object in space
is in orbit around exactly one other object. An
[[https://en.wikipedia.org/wiki/Orbit][orbit]] looks roughly like this:
#+BEGIN_EXAMPLE
\
\
|
|
AAA--> o o <--BBB
|
|
/
/
#+END_EXAMPLE
In this diagram, the object =BBB= is in orbit around =AAA=. The path
that =BBB= takes around =AAA= (drawn with lines) is only partly shown.
In the map data, this orbital relationship is written =AAA)BBB=, which
means "=BBB= is in orbit around =AAA=".
Before you use your map data to plot a course, you need to make sure it
wasn't corrupted during the download. To verify maps, the Universal
Orbit Map facility uses /orbit count checksums/ - the total number of
/direct orbits/ (like the one shown above) and /indirect orbits/.
Whenever =A= orbits =B= and =B= orbits =C=, then =A= /indirectly orbits/
=C=. This chain can be any number of objects long: if =A= orbits =B=,
=B= orbits =C=, and =C= orbits =D=, then =A= indirectly orbits =D=.
For example, suppose you have the following map:
#+BEGIN_EXAMPLE
COM)B
B)C
C)D
D)E
E)F
B)G
G)H
D)I
E)J
J)K
K)L
#+END_EXAMPLE
Visually, the above map of orbits looks like this:
#+BEGIN_EXAMPLE
G - H J - K - L
/ /
COM - B - C - D - E - F
\
I
#+END_EXAMPLE
In this visual representation, when two objects are connected by a line,
the one on the right directly orbits the one on the left.
Here, we can count the total number of orbits as follows:
- =D= directly orbits =C= and indirectly orbits =B= and =COM=, a total
of =3= orbits.
- =L= directly orbits =K= and indirectly orbits =J=, =E=, =D=, =C=, =B=,
and =COM=, a total of =7= orbits.
- =COM= orbits nothing.
The total number of direct and indirect orbits in this example is =42=.
/What is the total number of direct and indirect orbits/ in your map
data?
Your puzzle answer was =453028=.
** --- Part Two ---
Now, you just need to figure out how many /orbital transfers/ you
(=YOU=) need to take to get to Santa (=SAN=).
You start at the object =YOU= are orbiting; your destination is the
object =SAN= is orbiting. An orbital transfer lets you move from any
object to an object orbiting or orbited by that object.
For example, suppose you have the following map:
#+BEGIN_EXAMPLE
COM)B
B)C
C)D
D)E
E)F
B)G
G)H
D)I
E)J
J)K
K)L
K)YOU
I)SAN
#+END_EXAMPLE
Visually, the above map of orbits looks like this:
#+BEGIN_EXAMPLE
YOU
/
G - H J - K - L
/ /
COM - B - C - D - E - F
\
I - SAN
#+END_EXAMPLE
In this example, =YOU= are in orbit around =K=, and =SAN= is in orbit
around =I=. To move from =K= to =I=, a minimum of =4= orbital transfers
are required:
- =K= to =J=
- =J= to =E=
- =E= to =D=
- =D= to =I=
Afterward, the map of orbits looks like this:
#+BEGIN_EXAMPLE
G - H J - K - L
/ /
COM - B - C - D - E - F
\
I - SAN
\
YOU
#+END_EXAMPLE
/What is the minimum number of orbital transfers required/ to move from
the object =YOU= are orbiting to the object =SAN= is orbiting? (Between
the objects they are orbiting - /not/ between =YOU= and =SAN=.)
Your puzzle answer was =562=.
Both parts of this puzzle are complete! They provide two gold stars: **

270
2019/day06/aoc-c.c Normal file
View File

@@ -0,0 +1,270 @@
/* aoc-c.c: Advent of Code 2019, day 6 parts 1 & 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 <stdbool.h>
#include <string.h>
#include <malloc.h>
#include <getopt.h>
#include <stdlib.h>
#include "br.h"
#include "debug.h"
#include "pool.h"
/**
* As the character set is [1-9A-Z], the trie arrays size will be 26 + 9 = 35,
* organized as:
* char: 1 2 ... 8 9 A B ... Y Z
* index: 0 1 ... 7 8 9 10 ... 33 34
*/
#define TRIESIZE ('Z' - 'A' + 1 + '9' - '1' + 1)
#define c2index(c) ((c) >= 'A'? (c) - 'A' + 9: (c) - '1')
#define index2c(c) ((c) >= 9? (c) + 'A' - 9: (c) + '1')
/**
* object_t - object representation
* @parent: a pointer to the object we orbit around
* @sibling: a list of objects orbiting around @parent
* @child: a list of object orbiting around this object
* @name: the object name
*
* Example: if N1 and N2 orbit around O and S orbits around N1, we will
* have :
* +---------+
* +---->| 0 |<---------+
* | |---------| |
* | | parent |--->NIL |
* | |---------| |
* +-------------------+---->| child |<---------+-----------------+
* | | |---------| | |
* | | +-->| sibling |<--+ | |
* | | | +---------+ | | |
* | | | | | |
* | +---------+ | +-----------------+ | +---------+ |
* | | N1 |<---+-----+ | | N2 | |
* | |---------| | | | |---------| |
* | | parent |----+ | +--| parent | |
* | |---------| | |---------| |
* | +->| child |<---------+----+ NIL<---| child | |
* | | |---------| | | |---------| |
* +-+->| sibling |<---------+----+----------------->| sibling |<---+
* | +---------+ | | +---------+
* | | |
* | +---------+ | |
* | | S | | |
* | |---------| | |
* | | parent |----------+ |
* | |---------| |
* | | child |--->NIL |
* | |---------| |
* +->| sibling |<--------------+
* +---------+
*
*/
typedef struct object {
struct object *parent;
struct list_head sibling, child;
char name[8];
} object_t;
/**
* trie_t - trie node
* @child: array of pointers to trie_t children of current node
* @object: pointer to object data (NULL if node only)
*
* For example, if objects N1, N2, and S exist, the structure will be:
*
* Root trie
* +--------+-------------------------------------+
* | object | 0 | 1 | ... | N | ... | S | ... | Z |
* +--------+---------------+---------------------+
* | | | | |
* v v | | v
* NIL NIL | | NIL
* +----------------------------+ +-----+
* | "N" trie | "S" trie
* | +--------+-------------+ | +--------------------------+
* +-->| object | 0 | ... | Z | +->| object | 0 | 1 | 2 | ... |
* +--------+-------------+ +--------------------------+
* | | | | | | |
* | v v v v | |
* | NIL NIL NIL NIL | |
* | +---------------------------------+ |
* | | +-----------+
* | | "S1" trie | "S2" trie
* | | +------------------+ | +------------------+
* | +-->| object | 0 | ... | +-->| object | 0 | ... |
* | +------------------+ +------------------+
* | | | | |
* | | v | v
* v v NIL v NIL
* +-----------+ +-----------+ +-----------+
* | Object N | | Object S1 | | Object S2 |
* +-----------+ +-----------+ +-----------+
*/
typedef struct trie {
struct trie *child[TRIESIZE];
object_t *object;
} trie_t;
static pool_t *pool_tries, *pool_objects;
static trie_t *trie_get(trie_t *parent, char *name, int pos)
{
trie_t *trie;
if ((trie = pool_get(pool_tries))) {
for (int i = 0; i < TRIESIZE; ++i)
trie->child[i] = NULL;
trie->object = NULL;
if (parent)
parent->child[c2index(name[pos])] = trie;
}
return trie;
}
static trie_t *trie_find(trie_t *root, char *name)
{
int len = strlen(name);
for (int i = 0; i < len; ++i) {
int ind = c2index(name[i]);
root = root->child[ind] ? root->child[ind]: trie_get(root, name, i);
}
return root;
}
static object_t *object_find(trie_t *root, char *name)
{
trie_t *trie = trie_find(root, name);
if (!trie->object) {
trie->object = pool_get(pool_objects);
trie->object->parent = NULL;
strcpy(trie->object->name, name);
INIT_LIST_HEAD(&trie->object->child);
INIT_LIST_HEAD(&trie->object->sibling);
}
return trie->object;
}
/**
* get_orbits - get all orbits (direct and indirect) around an object
* @object: object address
* @depth: depth of current object
*/
static int get_orbits(object_t *object, int depth)
{
int ret = depth;
object_t *cur;
if (!list_empty(&object->child))
list_for_each_entry(cur, &object->child, sibling)
ret += get_orbits(cur, depth + 1);
return ret;
}
static int part1(trie_t *root, char *name)
{
object_t *object = object_find(root, name);
return get_orbits(object, 0);
}
/**
* get_depth - get depth of an object in a tree
* @object: object address
* Return: object depth
*/
static int get_depth(object_t *obj)
{
int res = 0;
for (; obj; obj = obj->parent)
res++;
return res;
}
static int part2(trie_t *root, char *name1, char *name2)
{
object_t *obj1 = object_find(root, name1), *obj2 = object_find(root, name2);
int count = 0, depth1, depth2;
depth1 = get_depth(obj1);
depth2 = get_depth(obj2);
/* ensure highest depth is obj1
*/
if (depth1 < depth2) {
swap(obj1, obj2);
swap(depth1, depth2);
}
/* make the 2 depths equal
*/
for (; depth1 > depth2; count++, depth1--)
obj1 = obj1->parent;
/* find common parent
*/
for (; obj1 != obj2; count += 2) {
obj1 = obj1->parent;
obj2 = obj2->parent;
}
return count - 2; /* coz' we want parents objects */
}
static void parse(trie_t *root)
{
char str1[8], str2[8];
while (scanf(" %7[^)])%s", str1, str2) == 2) {
object_t *star = object_find(root, str1);
object_t *planet = object_find(root, str2);
/* link planet to star, add planet to star's planets list
*/
planet->parent = star;
list_add(&planet->sibling, &star->child);
}
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
return 1;
}
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);
}
}
if (optind < ac)
return usage(*av);
pool_tries = pool_create("tries", 1024, sizeof(trie_t));
pool_objects = pool_create("objects", 1024, sizeof(object_t));
trie_t *root = trie_get(NULL, NULL, 0);
parse(root);
printf("%s : res=%d\n", *av,
part == 1 ? part1(root, "COM") : part2(root, "YOU", "SAN"));
pool_destroy(pool_tries);
pool_destroy(pool_objects);
exit (0);
}

1
2019/day07/EXAMPLE.txt Normal file
View File

@@ -0,0 +1 @@
3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0

1
2019/day07/EXAMPLE1.txt Normal file
View File

@@ -0,0 +1 @@
3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0

1
2019/day07/EXAMPLE2.txt Normal file
View File

@@ -0,0 +1 @@
3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0

1
2019/day07/INPUT.txt Normal file
View File

@@ -0,0 +1 @@
3,8,1001,8,10,8,105,1,0,0,21,30,39,64,81,102,183,264,345,426,99999,3,9,1001,9,2,9,4,9,99,3,9,1002,9,4,9,4,9,99,3,9,1002,9,5,9,101,2,9,9,102,3,9,9,1001,9,2,9,1002,9,2,9,4,9,99,3,9,1002,9,3,9,1001,9,5,9,1002,9,3,9,4,9,99,3,9,102,4,9,9,1001,9,3,9,102,4,9,9,1001,9,5,9,4,9,99,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,99,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,99

93
2019/day07/Makefile Normal file
View File

@@ -0,0 +1,93 @@
# 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
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 ex1 ex2
all: README.org ex1 ex2
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
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) aoc-c -p 2 < $(INPUT)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html
.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 $@

167
2019/day07/README.org Normal file
View File

@@ -0,0 +1,167 @@
** --- Day 7: Amplification Circuit ---
Based on the navigational maps, you're going to need to send more power
to your ship's thrusters to reach Santa in time. To do this, you'll need
to configure a series of
[[https://en.wikipedia.org/wiki/Amplifier][amplifiers]] already
installed on the ship.
There are five amplifiers connected in series; each one receives an
input signal and produces an output signal. They are connected such that
the first amplifier's output leads to the second amplifier's input, the
second amplifier's output leads to the third amplifier's input, and so
on. The first amplifier's input value is =0=, and the last amplifier's
output leads to your ship's thrusters.
#+BEGIN_EXAMPLE
O-------O O-------O O-------O O-------O O-------O
0 ->| Amp A |->| Amp B |->| Amp C |->| Amp D |->| Amp E |-> (to thrusters)
O-------O O-------O O-------O O-------O O-------O
#+END_EXAMPLE
The Elves have sent you some /Amplifier Controller Software/ (your
puzzle input), a program that should run on your [[file:5][existing
Intcode computer]]. Each amplifier will need to run a copy of the
program.
When a copy of the program starts running on an amplifier, it will first
use an input instruction to ask the amplifier for its current /phase
setting/ (an integer from =0= to =4=). Each phase setting is used
/exactly once/, but the Elves can't remember which amplifier needs which
phase setting.
The program will then call another input instruction to get the
amplifier's input signal, compute the correct output signal, and supply
it back to the amplifier with an output instruction. (If the amplifier
has not yet received an input signal, it waits until one arrives.)
Your job is to /find the largest output signal that can be sent to the
thrusters/ by trying every possible combination of phase settings on the
amplifiers. Make sure that memory is not shared or reused between copies
of the program.
For example, suppose you want to try the phase setting sequence
=3,1,2,4,0=, which would mean setting amplifier =A= to phase setting
=3=, amplifier =B= to setting =1=, =C= to =2=, =D= to =4=, and =E= to
=0=. Then, you could determine the output signal that gets sent from
amplifier =E= to the thrusters with the following steps:
- Start the copy of the amplifier controller software that will run on
amplifier =A=. At its first input instruction, provide it the
amplifier's phase setting, =3=. At its second input instruction,
provide it the input signal, =0=. After some calculations, it will use
an output instruction to indicate the amplifier's output signal.
- Start the software for amplifier =B=. Provide it the phase setting
(=1=) and then whatever output signal was produced from amplifier =A=.
It will then produce a new output signal destined for amplifier =C=.
- Start the software for amplifier =C=, provide the phase setting (=2=)
and the value from amplifier =B=, then collect its output signal.
- Run amplifier =D='s software, provide the phase setting (=4=) and
input value, and collect its output signal.
- Run amplifier =E='s software, provide the phase setting (=0=) and
input value, and collect its output signal.
The final output signal from amplifier =E= would be sent to the
thrusters. However, this phase setting sequence may not have been the
best one; another sequence might have sent a higher signal to the
thrusters.
Here are some example programs:
- Max thruster signal /=43210=/ (from phase setting sequence
=4,3,2,1,0=):
#+BEGIN_EXAMPLE
3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0
#+END_EXAMPLE
- Max thruster signal /=54321=/ (from phase setting sequence
=0,1,2,3,4=):
#+BEGIN_EXAMPLE
3,23,3,24,1002,24,10,24,1002,23,-1,23,
101,5,23,23,1,24,23,23,4,23,99,0,0
#+END_EXAMPLE
- Max thruster signal /=65210=/ (from phase setting sequence
=1,0,4,3,2=):
#+BEGIN_EXAMPLE
3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,
1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0
#+END_EXAMPLE
Try every combination of phase settings on the amplifiers. /What is the
highest signal that can be sent to the thrusters?/
Your puzzle answer was =65464=.
** --- Part Two ---
It's no good - in this configuration, the amplifiers can't generate a
large enough output signal to produce the thrust you'll need. The Elves
quickly talk you through rewiring the amplifiers into a /feedback loop/:
#+BEGIN_EXAMPLE
O-------O O-------O O-------O O-------O O-------O
0 -+->| Amp A |->| Amp B |->| Amp C |->| Amp D |->| Amp E |-.
| O-------O O-------O O-------O O-------O O-------O |
| |
'--------------------------------------------------------+
|
v
(to thrusters)
#+END_EXAMPLE
Most of the amplifiers are connected as they were before; amplifier
=A='s output is connected to amplifier =B='s input, and so on.
/However,/ the output from amplifier =E= is now connected into amplifier
=A='s input. This creates the feedback loop: the signal will be sent
through the amplifiers /many times/.
In feedback loop mode, the amplifiers need /totally different phase
settings/: integers from =5= to =9=, again each used exactly once. These
settings will cause the Amplifier Controller Software to repeatedly take
input and produce output many times before halting. Provide each
amplifier its phase setting at its first input instruction; all further
input/output instructions are for signals.
Don't restart the Amplifier Controller Software on any amplifier during
this process. Each one should continue receiving and sending signals
until it halts.
All signals sent or received in this process will be between pairs of
amplifiers except the very first signal and the very last signal. To
start the process, a =0= signal is sent to amplifier =A='s input
/exactly once/.
Eventually, the software on the amplifiers will halt after they have
processed the final loop. When this happens, the last output signal from
amplifier =E= is sent to the thrusters. Your job is to /find the largest
output signal that can be sent to the thrusters/ using the new phase
settings and feedback loop arrangement.
Here are some example programs:
- Max thruster signal /=139629729=/ (from phase setting sequence
=9,8,7,6,5=):
#+BEGIN_EXAMPLE
3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,
27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5
#+END_EXAMPLE
- Max thruster signal /=18216=/ (from phase setting sequence
=9,7,8,5,6=):
#+BEGIN_EXAMPLE
3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,
-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,
53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10
#+END_EXAMPLE
Try every combination of the new phase settings on the amplifier
feedback loop. /What is the highest signal that can be sent to the
thrusters?/
Your puzzle answer was =1518124=.
Both parts of this puzzle are complete! They provide two gold stars: **

257
2019/day07/aoc-c.c Normal file
View File

@@ -0,0 +1,257 @@
/* aoc-c.c: Advent of Code 2019, day 7 parts 1 & 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 <string.h>
#include "br.h"
#include "bits.h"
#include "debug.h"
#include "list.h"
#include "pool.h"
/* operators codes
*/
typedef enum {
ADD = 1, MUL = 2, /* CALC: add and mult */
INP = 3, OUT = 4, /* I/O: input and output value */
JMP_T = 5, JMP_F = 6, /* JUMPS: jump if true / if false */
SET_LT = 7, SET_EQ = 8, /* COND SETS: set if true/false */
HLT = 99 /* HALT */
} opcode_t;
/**
* ops - array of op-codes, mnemo, and number of parameters
* @op: An integer, the opcode
* @length: Next instruction offset
*/
typedef struct {
int op;
u8 length;
} ops_t;
typedef struct input {
int val;
struct list_head list;
} input_t;
#define MAXOPS 1024
typedef struct {
int length; /* total program length */
int cur; /* current position */
struct list_head input; /* process input queue */
int mem [MAXOPS]; /* should really be dynamic */
} program_t;
static ops_t ops[] = {
[ADD] = { ADD, 4 }, [MUL] = { MUL, 4 },
[INP] = { INP, 2 }, [OUT] = { OUT, 2 },
[JMP_T] = { JMP_T, 3 }, [JMP_F] = { JMP_F, 3 },
[SET_LT] = { SET_LT, 4 }, [SET_EQ] = { SET_EQ, 4 },
[HLT] = { HLT, 1 }
};
static int _flag_pow10[] = {1, 100, 1000, 10000};
#define OP(p, n) ((p->mem[n]) % 100)
#define ISDIRECT(p, n, i) ((((p->mem[n]) / _flag_pow10[i]) % 10))
#define DIRECT(p, i) ((p)->mem[i])
#define INDIRECT(p, i) (DIRECT(p, DIRECT(p, i)))
#define peek(p, n, i) (ISDIRECT(p, n, i)? DIRECT(p, n + i): INDIRECT(p, n + i))
#define poke(p, n, i, val) do { \
INDIRECT(p, n + i) = val; } \
while (0)
static pool_t *pool_input;
static __always_inline int prg_add_input(program_t *prg, int in)
{
input_t *input = pool_get(pool_input);
input->val = in;
list_add_tail(&input->list, &prg->input);
return in;
}
static __always_inline int prg_get_input(program_t *prg, int *out)
{
input_t *input = list_first_entry_or_null(&prg->input, input_t, list);
if (!input)
return 0;
*out = input->val;
list_del(&input->list);
pool_add(pool_input, input);
return 1;
}
/**
* permute - get next permutation of an array of integers
* @len: length of array
* @array: address of array
*
* Algorithm: lexicographic permutations
* https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
* Before the initial call, the array must be sorted (e.g. 0 2 3 5)
*
* Return: 1 if next permutation was found, 0 if no more permutation.
*
*/
static int permute_next(int len, int *array)
{
int k, l;
/* 1. Find the largest index k such that a[k] < a[k + 1] */
for (k = len - 2; k >= 0 && array[k] >= array[k + 1]; k--)
;
/* No more permutations */
if (k < 0)
return 0;
/* 2. Find the largest index l greater than k such that a[k] < a[l] */
for (l = len - 1; array[l] <= array[k]; l--)
;
/* 3. Swap the value of a[k] with that of a[l] */
swap(array[k], array[l]);
/* 4. Reverse sequence from a[k + 1] up to the final element */
for (l = len - 1, k++; k < l; k++, l--)
swap(array[k], array[l]);
return 1;
}
static int run(program_t *p, int *end)
{
int out = -1;
while (1) {
int op = OP(p, p->cur), cur = p->cur, input;
if (!(ops[op].op)) {
fprintf(stderr, "PANIC: illegal instruction %d at %d.\n", op, p->cur);
return -1;
}
switch (op) {
case ADD:
poke(p, p->cur, 3, peek(p, p->cur, 1) + peek(p, p->cur, 2));
break;
case MUL:
poke(p, p->cur, 3, peek(p, p->cur, 1) * peek(p, p->cur, 2));
break;
case INP:
if (prg_get_input(p, &input))
poke(p, p->cur, 1, input);
else
/* we need an input which is not yet avalaible, so we need
* to put the program in "waiting mode": We stop it (and
* return output value) without setting end flag.
*/
goto sleep;
break;
case OUT:
out = peek(p, p->cur, 1);
break;
case JMP_T:
if (peek(p, p->cur, 1))
p->cur = peek(p, p->cur, 2);
break;
case JMP_F:
if (!peek(p, p->cur, 1))
p->cur = peek(p, p->cur, 2);
break;
case SET_LT:
poke(p, p->cur, 3, peek(p, p->cur, 1) < peek(p, p->cur, 2) ? 1: 0);
break;
case SET_EQ:
poke(p, p->cur, 3, peek(p, p->cur, 1) == peek(p, p->cur, 2) ? 1: 0);
break;
case HLT:
*end = 1;
sleep:
return out;
}
if (p->cur == cur)
p->cur += ops[op].length;
}
}
static void parse(program_t *prog)
{
while (scanf("%d%*c", &prog->mem[prog->length++]) > 0)
;
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int main(int ac, char **av)
{
int phase1[] = {0, 1, 2, 3, 4}, phase2[] = {5, 6, 7, 8, 9}, *phase;
int opt, max = 0, part = 1;
program_t p = { 0 }, prg[5];
while ((opt = getopt(ac, av, "d:p:o:")) != -1) {
switch (opt) {
case 'd':
debug_level_set(atoi(optarg));
break;
case 'o':
for (ulong i = 0; i < strlen(optarg); ++i)
phase1[i] = optarg[i] - '0';
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
default:
return usage(*av);
}
}
pool_input = pool_create("input", 128, sizeof(input_t));
if (optind < ac)
return usage(*av);
phase = part == 1? phase1: phase2;
parse(&p);
do {
int out = 0, end = 0;
/* reset programs initial state, and add phase to their input
*/
for (unsigned i = 0; i < ARRAY_SIZE(prg); ++i) {
prg[i] = p;
INIT_LIST_HEAD(&prg[i].input);
prg_add_input(&prg[i], phase[i]);
}
/* run the 5 processes in order (0, 1, 2, 3, 4, 0, 1, etc...),
* until end flag is set by the process 4 (HLT instruction)
*/
while (!end) {
for (int i = 0; i < 5; ++i) {
/* add last process output in current process input queue
*/
prg_add_input(&prg[i], out);
out = run(&prg[i], &end);
}
}
max = max(max, out);
} while (permute_next(5, phase));
printf("%s : res=%d\n", *av, max);
pool_destroy(pool_input);
exit(0);
}

1
2019/day08/EXAMPLE.txt Normal file
View File

@@ -0,0 +1 @@
0222112222120000

1
2019/day08/INPUT.txt Normal file

File diff suppressed because one or more lines are too long

93
2019/day08/Makefile Normal file
View File

@@ -0,0 +1,93 @@
# 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
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 ex1 ex2
all: README.org ex1 ex2
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
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) aoc-c -p 2 < $(INPUT)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html
.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 $@

99
2019/day08/README.org Normal file
View File

@@ -0,0 +1,99 @@
** --- Day 8: Space Image Format ---
The Elves' spirits are lifted when they realize you have an opportunity
to reboot one of their Mars rovers, and so they are curious if you would
spend a brief sojourn on Mars. You land your ship near the rover.
When you reach the rover, you discover that it's already in the process
of rebooting! It's just waiting for someone to enter a
[[https://en.wikipedia.org/wiki/BIOS][BIOS]] password. The Elf
responsible for the rover takes a picture of the password (your puzzle
input) and sends it to you via the Digital Sending Network.
Unfortunately, images sent via the Digital Sending Network aren't
encoded with any normal encoding; instead, they're encoded in a special
Space Image Format. None of the Elves seem to remember why this is the
case. They send you the instructions to decode it.
Images are sent as a series of digits that each represent the color of a
single pixel. The digits fill each row of the image left-to-right, then
move downward to the next row, filling rows top-to-bottom until every
pixel of the image is filled.
Each image actually consists of a series of identically-sized /layers/
that are filled in this way. So, the first digit corresponds to the
top-left pixel of the first layer, the second digit corresponds to the
pixel to the right of that on the same layer, and so on until the last
digit, which corresponds to the bottom-right pixel of the last layer.
For example, given an image =3= pixels wide and =2= pixels tall, the
image data =123456789012= corresponds to the following image layers:
#+BEGIN_EXAMPLE
Layer 1: 123
456
Layer 2: 789
012
#+END_EXAMPLE
The image you received is /=25= pixels wide and =6= pixels tall/.
To make sure the image wasn't corrupted during transmission, the Elves
would like you to find the layer that contains the /fewest =0= digits/.
On that layer, what is /the number of =1= digits multiplied by the
number of =2= digits?/
Your puzzle answer was =2250=.
** --- Part Two ---
Now you're ready to decode the image. The image is rendered by stacking
the layers and aligning the pixels with the same positions in each
layer. The digits indicate the color of the corresponding pixel: =0= is
black, =1= is white, and =2= is transparent.
The layers are rendered with the first layer in front and the last layer
in back. So, if a given position has a transparent pixel in the first
and second layers, a black pixel in the third layer, and a white pixel
in the fourth layer, the final image would have a /black/ pixel at that
position.
For example, given an image =2= pixels wide and =2= pixels tall, the
image data =0222112222120000= corresponds to the following image layers:
#+BEGIN_EXAMPLE
Layer 1: 02
22
Layer 2: 11
22
Layer 3: 22
12
Layer 4: 00
00
#+END_EXAMPLE
Then, the full image can be found by determining the top visible pixel
in each position:
- The top-left pixel is /black/ because the top layer is =0=.
- The top-right pixel is /white/ because the top layer is =2=
(transparent), but the second layer is =1=.
- The bottom-left pixel is /white/ because the top two layers are =2=,
but the third layer is =1=.
- The bottom-right pixel is /black/ because the only visible pixel in
that position is =0= (from layer 4).
So, the final image looks like this:
#+BEGIN_EXAMPLE
01
10
#+END_EXAMPLE
/What message is produced after decoding your image?/
Your puzzle answer was =FHJUL=.
Both parts of this puzzle are complete! They provide two gold stars: **

120
2019/day08/aoc-c.c Normal file
View File

@@ -0,0 +1,120 @@
/* aoc-c.c: Advent of Code 2019, day 8 parts 1 & 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 <string.h>
#include "br.h"
#include "bits.h"
#include "debug.h"
#include "list.h"
#include "pool.h"
struct input {
int len;
char *buf;
};
static int part1(struct input *input, int width, int height)
{
int depth = input->len / width / height;
int minzero = input->len, n1n2;
for (int i = 0; i < depth; ++i) {
char *layer = input->buf + i * (width * height);
int tmp[10] = {0};
for (int j = 0; j < width*height; ++j) {
tmp[layer[j] - '0'] ++;
}
if (tmp[0] < minzero) {
minzero = tmp[0];
n1n2 = tmp[1] * tmp[2];
}
}
return n1n2;
}
static int part2(struct input *input, int width, int height)
{
for (int line = 0; line < height; line++) {
for (int pixel = 0; pixel < width; ++pixel) {
char *pos = input->buf + line * width + pixel;
while (pos < input->buf + input->len && *pos == '2')
pos += width * height;
putchar(*pos == '0'? ' ': '#');
}
putchar('\n');
}
return 0;
}
static int parse(struct input *input)
{
size_t alloc = 0;
ssize_t buflen;
char *buf = NULL;
if ((buflen = getline(&buf, &alloc, stdin)) <= 0) {
fprintf(stderr, "error reading file.\n");
return 0;
}
buf[buflen--] = 0;
input->buf = buf;
input->len = buflen;
return buflen;
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
int main(int ac, char **av)
{
int opt, part = 1, width = 25, height = 6;
struct input input = { 0 };
while ((opt = getopt(ac, av, "d:p:w:h:")) != -1) {
switch (opt) {
case 'd':
debug_level_set(atoi(optarg));
break;
case 'w':
width = atoi(optarg);
break;
case 'h':
height = atoi(optarg);
break;
case 'p': /* 1 or 2 */
part = atoi(optarg);
if (part < 1 || part > 2)
return usage(*av);
break;
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
parse(&input);
printf("%s : res=%d\n", *av,
part == 1?
part1(&input, width, height) :
part2(&input, width, height));
free(input.buf);
exit(0);
}

1
2019/day09/EXAMPLE.txt Normal file
View File

@@ -0,0 +1 @@
109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99

1
2019/day09/EXAMPLE2.txt Normal file
View File

@@ -0,0 +1 @@
1102,34915192,34915192,7,4,7,99,0

1
2019/day09/EXAMPLE3.txt Normal file
View File

@@ -0,0 +1 @@
104,1125899906842624,99

1
2019/day09/INPUT.txt Normal file
View File

@@ -0,0 +1 @@
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,3,1,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,20,0,1007,1101,0,197,1022,1102,475,1,1028,1102,30,1,1008,1101,25,0,1010,1102,1,23,1009,1101,0,22,1013,1101,470,0,1029,1102,24,1,1014,1102,1,39,1005,1101,31,0,1003,1101,807,0,1026,1101,0,26,1018,1102,1,804,1027,1101,0,0,1020,1102,1,38,1017,1101,0,27,1016,1102,443,1,1024,1101,0,36,1006,1102,21,1,1015,1101,28,0,1001,1102,33,1,1019,1102,1,37,1011,1102,1,190,1023,1101,0,434,1025,1101,34,0,1004,1102,1,1,1021,1101,0,29,1012,1102,1,32,1002,1101,35,0,1000,109,30,2105,1,-7,1001,64,1,64,1105,1,199,4,187,1002,64,2,64,109,-23,2101,0,-5,63,1008,63,32,63,1005,63,225,4,205,1001,64,1,64,1105,1,225,1002,64,2,64,109,7,2102,1,-5,63,1008,63,23,63,1005,63,251,4,231,1001,64,1,64,1106,0,251,1002,64,2,64,109,-16,2101,0,2,63,1008,63,33,63,1005,63,275,1001,64,1,64,1106,0,277,4,257,1002,64,2,64,109,10,21102,40,1,4,1008,1012,40,63,1005,63,299,4,283,1106,0,303,1001,64,1,64,1002,64,2,64,109,7,2102,1,-9,63,1008,63,33,63,1005,63,327,1001,64,1,64,1105,1,329,4,309,1002,64,2,64,109,-17,2107,34,2,63,1005,63,347,4,335,1105,1,351,1001,64,1,64,1002,64,2,64,109,1,1201,8,0,63,1008,63,23,63,1005,63,375,1001,64,1,64,1106,0,377,4,357,1002,64,2,64,109,-4,2108,31,8,63,1005,63,395,4,383,1105,1,399,1001,64,1,64,1002,64,2,64,109,3,1201,8,0,63,1008,63,36,63,1005,63,421,4,405,1105,1,425,1001,64,1,64,1002,64,2,64,109,25,2105,1,1,4,431,1001,64,1,64,1105,1,443,1002,64,2,64,109,-3,1205,0,459,1001,64,1,64,1106,0,461,4,449,1002,64,2,64,109,-2,2106,0,10,4,467,1106,0,479,1001,64,1,64,1002,64,2,64,109,12,1206,-9,495,1001,64,1,64,1106,0,497,4,485,1002,64,2,64,109,-39,1207,9,36,63,1005,63,519,4,503,1001,64,1,64,1105,1,519,1002,64,2,64,109,11,1202,-1,1,63,1008,63,28,63,1005,63,541,4,525,1105,1,545,1001,64,1,64,1002,64,2,64,109,6,2107,24,1,63,1005,63,565,1001,64,1,64,1106,0,567,4,551,1002,64,2,64,109,1,1207,-3,35,63,1005,63,583,1106,0,589,4,573,1001,64,1,64,1002,64,2,64,109,1,21102,41,1,5,1008,1015,40,63,1005,63,613,1001,64,1,64,1105,1,615,4,595,1002,64,2,64,109,-2,2108,22,1,63,1005,63,635,1001,64,1,64,1105,1,637,4,621,1002,64,2,64,109,-10,1208,4,33,63,1005,63,653,1106,0,659,4,643,1001,64,1,64,1002,64,2,64,109,16,1206,6,673,4,665,1106,0,677,1001,64,1,64,1002,64,2,64,109,-4,1202,-8,1,63,1008,63,35,63,1005,63,701,1001,64,1,64,1105,1,703,4,683,1002,64,2,64,109,13,21108,42,42,-8,1005,1015,721,4,709,1105,1,725,1001,64,1,64,1002,64,2,64,109,-18,21107,43,44,5,1005,1010,743,4,731,1106,0,747,1001,64,1,64,1002,64,2,64,109,-11,1208,8,32,63,1005,63,765,4,753,1106,0,769,1001,64,1,64,1002,64,2,64,109,15,21101,44,0,5,1008,1014,47,63,1005,63,789,1105,1,795,4,775,1001,64,1,64,1002,64,2,64,109,13,2106,0,5,1106,0,813,4,801,1001,64,1,64,1002,64,2,64,109,-12,21108,45,43,0,1005,1010,829,1106,0,835,4,819,1001,64,1,64,1002,64,2,64,109,-4,21107,46,45,10,1005,1016,855,1001,64,1,64,1106,0,857,4,841,1002,64,2,64,109,3,21101,47,0,5,1008,1014,47,63,1005,63,883,4,863,1001,64,1,64,1106,0,883,1002,64,2,64,109,10,1205,2,901,4,889,1001,64,1,64,1105,1,901,4,64,99,21102,27,1,1,21102,915,1,0,1106,0,922,21201,1,13433,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,0,942,0,1106,0,922,22102,1,1,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1106,0,968,21202,-2,1,-2,109,-3,2106,0,0

93
2019/day09/Makefile Normal file
View File

@@ -0,0 +1,93 @@
# 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
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 ex1 ex2
all: README.org ex1 ex2
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
assembly: aoc-c.s
ex1: aoc-c
@$(TIME) aoc-c -p 1 < $(INPUT)
ex2: aoc-c
@$(TIME) aoc-c -p 2 < $(INPUT)
clean:
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html
.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 $@

94
2019/day09/README.org Normal file
View File

@@ -0,0 +1,94 @@
** --- Day 9: Sensor Boost ---
You've just said goodbye to the rebooted rover and left Mars when you
receive a faint distress signal coming from the asteroid belt. It must
be the Ceres monitoring station!
In order to lock on to the signal, you'll need to boost your sensors.
The Elves send up the latest /BOOST/ program - Basic Operation Of System
Test.
While BOOST (your puzzle input) is capable of boosting your sensors, for
tenuous safety reasons, it refuses to do so until the computer it runs
on passes some checks to demonstrate it is a /complete Intcode
computer/.
[[file:5][Your existing Intcode computer]] is missing one key feature:
it needs support for parameters in /relative mode/.
Parameters in mode =2=, /relative mode/, behave very similarly to
parameters in /position mode/: the parameter is interpreted as a
position. Like position mode, parameters in relative mode can be read
from or written to.
The important difference is that relative mode parameters don't count
from address =0=. Instead, they count from a value called the /relative
base/. The /relative base/ starts at =0=.
The address a relative mode parameter refers to is itself /plus/ the
current /relative base/. When the relative base is =0=, relative mode
parameters and position mode parameters with the same value refer to the
same address.
For example, given a relative base of =50=, a relative mode parameter of
=-7= refers to memory address =50 + -7 = 43=.
The relative base is modified with the /relative base offset/
instruction:
- Opcode =9= /adjusts the relative base/ by the value of its only
parameter. The relative base increases (or decreases, if the value is
negative) by the value of the parameter.
For example, if the relative base is =2000=, then after the instruction
=109,19=, the relative base would be =2019=. If the next instruction
were =204,-34=, then the value at address =1985= would be output.
Your Intcode computer will also need a few other capabilities:
- The computer's available memory should be much larger than the initial
program. Memory beyond the initial program starts with the value =0=
and can be read or written like any other memory. (It is invalid to
try to access memory at a negative address, though.)
- The computer should have support for large numbers. Some instructions
near the beginning of the BOOST program will verify this capability.
Here are some example programs that use these features:
- =109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99= takes no
input and produces a
[[https://en.wikipedia.org/wiki/Quine_(computing)][copy of itself]] as
output.
- =1102,34915192,34915192,7,4,7,99,0= should output a 16-digit number.
- =104,1125899906842624,99= should output the large number in the
middle.
The BOOST program will ask for a single input; run it in test mode by
providing it the value =1=. It will perform a series of checks on each
opcode, output any opcodes (and the associated parameter modes) that
seem to be functioning incorrectly, and finally output a BOOST keycode.
Once your Intcode computer is fully functional, the BOOST program should
report no malfunctioning opcodes when run in test mode; it should only
output a single value, the BOOST keycode. /What BOOST keycode does it
produce?/
Your puzzle answer was =2682107844=.
** --- Part Two ---
/You now have a complete Intcode computer./
Finally, you can lock on to the Ceres distress signal! You just need to
boost your sensors using the BOOST program.
The program runs in sensor boost mode by providing the input instruction
the value =2=. Once run, it will boost the sensors automatically, but it
might take a few seconds to complete the operation on slower hardware.
In sensor boost mode, the program will output a single value: /the
coordinates of the distress signal/.
Run the BOOST program in sensor boost mode. /What are the coordinates of
the distress signal?/
Your puzzle answer was =34738=.
Both parts of this puzzle are complete! They provide two gold stars: **

258
2019/day09/aoc-c.c Normal file
View File

@@ -0,0 +1,258 @@
/* aoc-c.c: Advent of Code 2019, day 9 parts 1 & 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 <string.h>
#include "br.h"
#include "bits.h"
#include "debug.h"
#include "list.h"
#include "pool.h"
#define _unused __attribute__((unused))
/* operators codes
*/
typedef enum {
ADD = 1, MUL = 2, /* CALC: add and mult */
INP = 3, OUT = 4, /* I/O: input and output value */
JMP_T = 5, JMP_F = 6, /* JUMPS: jump if true / if false */
SET_LT = 7, SET_EQ = 8, /* COND SETS: set if true/false */
ADJ_RL = 9, /* ADDRESSING: adjust relative addr */
HLT = 99 /* HALT */
} opcode_t;
/**
* ops - array of op-codes, mnemo, and number of parameters
* @op: An integer, the opcode
* @length: Next instruction offset
*/
typedef struct {
int op;
u8 length;
} ops_t;
typedef struct io {
s64 val;
struct list_head list;
} io_t;
#define MAXOPS 2048
typedef struct {
s64 length; /* total program length */
s64 cur; /* current instruction */
s64 rel; /* current relative memory */
struct list_head input; /* process input queue */
struct list_head output; /* process output queue */
s64 mem [MAXOPS]; /* should really be dynamic */
} program_t;
static ops_t ops[] = {
[ADD] = { ADD, 4 }, [MUL] = { MUL, 4 },
[INP] = { INP, 2 }, [OUT] = { OUT, 2 },
[JMP_T] = { JMP_T, 3 }, [JMP_F] = { JMP_F, 3 },
[SET_LT] = { SET_LT, 4 }, [SET_EQ] = { SET_EQ, 4 },
[ADJ_RL] = { ADJ_RL, 2 },
[HLT] = { HLT, 1 }
};
typedef enum {
IND = 0,
DIR = 1,
REL = 2
} param_t;
static __always_inline int getop(program_t *prg, int addr)
{
return prg->mem[addr] % 100;
}
static __always_inline param_t paramtype(program_t *prg, int addr, int param)
{
static int _flag_pow10[] = {1, 100, 1000, 10000};
return prg->mem[addr] / _flag_pow10[param] % 10;
}
#define DIRECT(p, i) ((p)->mem[i])
#define INDIRECT(p, i) (DIRECT(p, DIRECT(p, i)))
#define RELATIVE(p, i) (DIRECT(p, DIRECT(p, i) + p->rel))
static __always_inline s64 peek(program_t *prg, s64 cur, s64 param)
{
switch(paramtype(prg, cur, param)) {
case IND:
return INDIRECT(prg, cur + param);
case REL:
return RELATIVE(prg, cur + param);
case DIR:
return DIRECT(prg, cur + param);
}
return 0; /* not reached */
}
static __always_inline void poke(program_t *prg, int cur, int param, s64 val)
{
if (paramtype(prg, cur, param) == REL)
RELATIVE(prg, cur + param) = val;
else
INDIRECT(prg, cur + param) = val;
}
static pool_t *pool_io;
static inline int prg_add_input(program_t *prg, s64 in)
{
io_t *input = pool_get(pool_io);
input->val = in;
list_add_tail(&input->list, &prg->input);
return in;
}
static inline s64 prg_add_output(program_t *prg, s64 out)
{
io_t *output = pool_get(pool_io);
output->val = out;
list_add_tail(&output->list, &prg->output);
return out;
}
static inline int prg_get_input(program_t *prg, s64 *in)
{
io_t *input = list_first_entry_or_null(&prg->input, io_t, list);
if (!input)
return 0;
*in = input->val;
list_del(&input->list);
pool_add(pool_io, input);
return 1;
}
static inline _unused int prg_get_output(program_t *prg, s64 *out)
{
io_t *output = list_first_entry_or_null(&prg->output, io_t, list);
if (!output)
return 0;
*out = output->val;
list_del(&output->list);
pool_add(pool_io, output);
return 1;
}
static s64 run(program_t *p, int *end)
{
s64 out = -1, input;
while (1) {
int cur = p->cur;
opcode_t op = getop(p, p->cur);
if (!(ops[op].op)) {
fprintf(stderr, "PANIC: illegal instruction %d at %ld.\n", op, p->cur);
return -1;
}
switch (op) {
case ADD:
poke(p, p->cur, 3, peek(p, p->cur, 1) + peek(p, p->cur, 2));
break;
case MUL:
poke(p, p->cur, 3, peek(p, p->cur, 1) * peek(p, p->cur, 2));
break;
case INP:
if (prg_get_input(p, &input))
poke(p, p->cur, 1, input);
else
/* we need an input which is not yet avalaible, so we need
* to put the program in "waiting mode": We stop it (and
* return output value) without setting end flag.
*/
goto sleep;
break;
case OUT:
prg_add_output(p, out = peek(p, p->cur, 1));
break;
case JMP_T:
if (peek(p, p->cur, 1))
p->cur = peek(p, p->cur, 2);
break;
case JMP_F:
if (!peek(p, p->cur, 1))
p->cur = peek(p, p->cur, 2);
break;
case SET_LT:
poke(p, p->cur, 3, peek(p, p->cur, 1) < peek(p, p->cur, 2) ? 1: 0);
break;
case SET_EQ:
poke(p, p->cur, 3, peek(p, p->cur, 1) == peek(p, p->cur, 2) ? 1: 0);
break;
case ADJ_RL:
p->rel += peek(p, p->cur, 1);
break;
case HLT:
*end = 1;
sleep:
return out;
}
if (p->cur == cur)
p->cur += ops[op].length;
}
}
static void parse(program_t *prog)
{
while (scanf("%ld%*c", &prog->mem[prog->length++]) > 0)
;
}
static int usage(char *prg)
{
fprintf(stderr, "Usage: %s [-d debug_level] [-p part] [-i input]\n", prg);
return 1;
}
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)
return usage(*av);
break;
default:
return usage(*av);
}
}
if (optind < ac)
return usage(*av);
int end = 0;
program_t p = { 0 };
pool_io = pool_create("i/o", 128, sizeof(io_t));
INIT_LIST_HEAD(&p.input);
INIT_LIST_HEAD(&p.output);
prg_add_input(&p, part);
parse(&p);
printf("%s : res=%ld\n", *av, run(&p, &end));
pool_destroy(pool_io);
exit(0);
}

521
2019/include/bits.h Normal file
View File

@@ -0,0 +1,521 @@
/* bits.h - bits functions.
*
* 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>
*
*/
#ifndef BITS_H
#define BITS_H
#include <stdint.h>
#include <stdbool.h>
/* next include will define __WORDSIZE: 32 or 64
*/
#include <bits/wordsize.h>
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
/* no plan to support 32bits for now...
*/
#if __WORDSIZE != 64
#error "Only 64 bits word size supported."
#endif
/* fixed-size types
*/
typedef int64_t s64;
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
/* convenience types
*/
typedef unsigned long int ulong;
typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned char uchar;
/* char is a special case, as it can be signed or unsigned
*/
typedef signed char schar;
/* count trailing zeroes : 00101000 -> 3
* ^^^
*/
static __always_inline int ctz64(u64 n)
{
# if __has_builtin(__builtin_ctzl)
# ifdef DEBUG_BITS
log_f(1, "builtin ctzl.\n");
# endif
return __builtin_ctzl(n);
# elif __has_builtin(__builtin_clzl)
# ifdef DEBUG_BITS
log_f(1, "builtin clzl.\n");
# endif
return __WORDSIZE - (__builtin_clzl(n & -n) + 1);
# else
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
return popcount64((n & n) 1);
# endif
}
static __always_inline int ctz32(u32 n)
{
# if __has_builtin(__builtin_ctz)
# ifdef DEBUG_BITS
log_f(1, "builtin ctz.\n");
# endif
return __builtin_ctzl(n);
# elif __has_builtin(__builtin_clz)
# ifdef DEBUG_BITS
log_f(1, "builtin clz.\n");
# endif
return __WORDSIZE - (__builtin_clz(n & -n) + 1);
# else
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
return popcount32((n & n) 1);
# endif
}
/* clz - count leading zeroes : 00101000 -> 2
* ^^
*/
static __always_inline int clz64(u64 n)
{
# if __has_builtin(__builtin_clzl)
# ifdef DEBUG_BITS
log_f(1, "builtin.\n");
# endif
return __builtin_clzl(n);
# else
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
u64 r, q;
r = (n > 0xFFFFFFFF) << 5; n >>= r;
q = (n > 0xFFFF) << 4; n >>= q; r |= q;
q = (n > 0xFF ) << 3; n >>= q; r |= q;
q = (n > 0xF ) << 2; n >>= q; r |= q;
q = (n > 0x3 ) << 1; n >>= q; r |= q;
r |= (n >> 1);
return 64 - r - 1;
# endif
}
static __always_inline int clz32(u32 n)
{
# if __has_builtin(__builtin_clz)
# ifdef DEBUG_BITS
log_f(1, "builtin.\n");
# endif
return __builtin_clz(n);
# else
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
u32 r, q;
r = (n > 0xFFFF) << 4; n >>= r;
q = (n > 0xFF ) << 3; n >>= q; r |= q;
q = (n > 0xF ) << 2; n >>= q; r |= q;
q = (n > 0x3 ) << 1; n >>= q; r |= q;
r |= (n >> 1);
return 32 - r - 1;
# endif
}
/* fls - find last set : 00101000 -> 6
* ^
*/
static __always_inline int fls64(u64 n)
{
if (!n)
return 0;
return 64 - clz64(n);
}
static __always_inline int fls32(u32 n)
{
if (!n)
return 0;
return 32 - clz32(n);
}
/* find first set : 00101000 -> 4
* ^
*/
static __always_inline uint ffs64(u64 n)
{
# if __has_builtin(__builtin_ffsl)
# ifdef DEBUG_BITS
log_f(1, "builtin ffsl.\n");
# endif
return __builtin_ffsl(n);
# elif __has_builtin(__builtin_ctzl)
# ifdef DEBUG_BITS
log_f(1, "builtin ctzl.\n");
# endif
if (n == 0)
return (0);
return __builtin_ctzl(n) + 1;
# else
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
return popcount64(n ^ ~-n);
# endif
}
static __always_inline uint ffs32(u32 n)
{
# if __has_builtin(__builtin_ffs)
# ifdef DEBUG_BITS
log_f(1, "builtin ffs.\n");
# endif
return __builtin_ffs(n);
# elif __has_builtin(__builtin_ctz)
# ifdef DEBUG_BITS
log_f(1, "builtin ctz.\n");
# endif
if (n == 0)
return (0);
return __builtin_ctz(n) + 1;
# else
# ifdef DEBUG_BITS
log_f(1, "emulated.\n");
# endif
return popcount32(n ^ ~-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
*/
/**
* rol64 - rotate a 64-bit value left
* @word: value to rotate
* @shift: bits to roll
*/
static inline u64 rol64(u64 word, unsigned int shift)
{
return (word << (shift & 63)) | (word >> ((-shift) & 63));
}
/**
* ror64 - rotate a 64-bit value right
* @word: value to rotate
* @shift: bits to roll
*/
static inline u64 ror64(u64 word, unsigned int shift)
{
return (word >> (shift & 63)) | (word << ((-shift) & 63));
}
/**
* rol32 - rotate a 32-bit value left
* @word: value to rotate
* @shift: bits to roll
*/
static inline u32 rol32(u32 word, unsigned int shift)
{
return (word << (shift & 31)) | (word >> ((-shift) & 31));
}
/**
* ror32 - rotate a 32-bit value right
* @word: value to rotate
* @shift: bits to roll
*/
static inline u32 ror32(u32 word, unsigned int shift)
{
return (word >> (shift & 31)) | (word << ((-shift) & 31));
}
/**
* rol16 - rotate a 16-bit value left
* @word: value to rotate
* @shift: bits to roll
*/
static inline u16 rol16(u16 word, unsigned int shift)
{
return (word << (shift & 15)) | (word >> ((-shift) & 15));
}
/**
* ror16 - rotate a 16-bit value right
* @word: value to rotate
* @shift: bits to roll
*/
static inline u16 ror16(u16 word, unsigned int shift)
{
return (word >> (shift & 15)) | (word << ((-shift) & 15));
}
/**
* rol8 - rotate an 8-bit value left
* @word: value to rotate
* @shift: bits to roll
*/
static inline u8 rol8(u8 word, unsigned int shift)
{
return (word << (shift & 7)) | (word >> ((-shift) & 7));
}
/**
* ror8 - rotate an 8-bit value right
* @word: value to rotate
* @shift: bits to roll
*/
static inline u8 ror8(u8 word, unsigned int shift)
{
return (word >> (shift & 7)) | (word << ((-shift) & 7));
}
/**
* ilog2 -
*/
static __always_inline __attribute__((const))
int __ilog2_u32(u32 n)
{
return fls32(n) - 1;
}
static __always_inline __attribute__((const))
int __ilog2_u64(u64 n)
{
return fls64(n) - 1;
}
/**
* is_power_of_2() - check if a value is a power of two
* @n: the value to check
*
* Determine whether some value is a power of two, where zero is
* *not* considered a power of two.
* Return: true if @n is a power of 2, otherwise false.
*/
static inline __attribute__((const))
bool is_power_of_2(unsigned long n)
{
return (n != 0 && ((n & (n - 1)) == 0));
}
/**
* ilog2 - log base 2 of 32-bit or a 64-bit unsigned value
* @n: parameter
*
* constant-capable log of base 2 calculation
* - this can be used to initialise global variables from constant data, hence
* the massive ternary operator construction
*
* selects the appropriately-sized optimised version depending on sizeof(n)
*/
#define ilog2(n) \
( \
__builtin_constant_p(n) ? \
((n) < 2 ? 0 : \
63 - __builtin_clzll(n)) : \
(sizeof(n) <= 4) ? \
__ilog2_u32(n) : \
__ilog2_u64(n) \
)
/**
* roundup_pow_of_two - round the given value up to nearest power of two
* @n: parameter
*
* round the given value up to the nearest power of two
* - the result is undefined when n == 0
* - this can be used to initialise global variables from constant data
*/
#define roundup_pow_of_two(n) \
( \
__builtin_constant_p(n) ? ( \
((n) == 1) ? 1 : \
(1UL << (ilog2((n) - 1) + 1)) \
) : \
__roundup_pow_of_two(n) \
)
/**
* rounddown_pow_of_two - round the given value down to nearest power of two
* @n: parameter
*
* round the given value down to the nearest power of two
* - the result is undefined when n == 0
* - this can be used to initialise global variables from constant data
*/
#define rounddown_pow_of_two(n) \
( \
__builtin_constant_p(n) ? ( \
(1UL << ilog2(n))) : \
__rounddown_pow_of_two(n) \
)
static inline __attribute_const__
int __order_base_2(unsigned long n)
{
return n > 1 ? ilog2(n - 1) + 1 : 0;
}
/**
* order_base_2 - calculate the (rounded up) base 2 order of the argument
* @n: parameter
*
* The first few values calculated by this routine:
* ob2(0) = 0
* ob2(1) = 0
* ob2(2) = 1
* ob2(3) = 2
* ob2(4) = 2
* ob2(5) = 3
* ... and so on.
*/
#define order_base_2(n) \
( \
__builtin_constant_p(n) ? ( \
((n) == 0 || (n) == 1) ? 0 : \
ilog2((n) - 1) + 1) : \
__order_base_2(n) \
)
static inline __attribute__((const))
int __bits_per(unsigned long n)
{
if (n < 2)
return 1;
if (is_power_of_2(n))
return order_base_2(n) + 1;
return order_base_2(n);
}
/**
* bits_per - calculate the number of bits required for the argument
* @n: parameter
*
* This is constant-capable and can be used for compile time
* initializations, e.g bitfields.
*
* The first few values calculated by this routine:
* bf(0) = 1
* bf(1) = 1
* bf(2) = 2
* bf(3) = 2
* bf(4) = 3
* ... and so on.
*/
#define bits_per(n) \
( \
__builtin_constant_p(n) ? ( \
((n) == 0 || (n) == 1) \
? 1 : ilog2(n) + 1 \
) : \
__bits_per(n) \
)
/** bit_for_each - iterate over an u64/u32 bits
* @pos: an int used as current bit
* @tmp: a temp u64/u32 used as temporary storage
* @ul: the u64/u32 to loop over
*
* Usage:
* u64 u=139, _t; // u=b10001011
* int cur;
* bit_for_each64(cur, _t, u) {
* printf("%d\n", cur);
* }
* This will display the position of each bit set in ul: 1, 2, 4, 8
*
* I should probably re-think the implementation...
*/
#define bit_for_each64(pos, tmp, ul) \
for (tmp = ul, pos = ffs64(tmp); tmp; tmp &= (tmp - 1), pos = ffs64(tmp))
#define bit_for_each32(pos, tmp, ul) \
for (tmp = ul, pos = ffs32(tmp); tmp; tmp &= (tmp - 1), pos = ffs32(tmp))
/** or would it be more useful (counting bits from zero instead of 1) ?
*/
#define bit_for_each64_2(pos, tmp, ul) \
for (tmp = ul, pos = ctz64(tmp); tmp; tmp ^= 1UL << pos, pos = ctz64(tmp))
#define bit_for_each32_2(pos, tmp, ul) \
for (tmp = ul, pos = ctz32(tmp); tmp; tmp ^= 1U << pos, pos = ctz32(tmp))
#endif /* BITS_H */

211
2019/include/br.h Normal file
View File

@@ -0,0 +1,211 @@
/* bits.h - bits functions.
*
* 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>
*
* Some parts are taken from Linux's kernel <linux/kernel.h> and others, and are :
* SPDX-License-Identifier: GPL-2.0
*
* This header contains generic stuff.
*/
#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__)
/* see https://lkml.org/lkml/2018/3/20/845 for explanation of this monster
*/
#define __is_constexpr(x) \
(sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
/*
* min()/max()/clamp() macros must accomplish three things:
*
* - avoid multiple evaluations of the arguments (so side-effects like
* "x++" happen only once) when non-constant.
* - perform strict type-checking (to generate warnings instead of
* nasty runtime surprises). See the "unnecessary" pointer comparison
* in __typecheck().
* - retain result as a constant expressions when called with only
* constant expressions (to avoid tripping VLA warnings in stack
* allocation usage).
*/
#define __typecheck(x, y) \
(!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
#define __no_side_effects(x, y) \
(__is_constexpr(x) && __is_constexpr(y))
#define __safe_cmp(x, y) \
(__typecheck(x, y) && __no_side_effects(x, y))
#define __cmp(x, y, op) ((x) op (y) ? (x) : (y))
#define __cmp_once(x, y, unique_x, unique_y, op) ({ \
typeof(x) unique_x = (x); \
typeof(y) unique_y = (y); \
__cmp(unique_x, unique_y, op); })
#define __careful_cmp(x, y, op) \
__builtin_choose_expr(__safe_cmp(x, y), \
__cmp(x, y, op), \
__cmp_once(x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y), op))
#define __pure __attribute__((__pure__))
/**
* min - return minimum of two values of the same or compatible types
* @x: first value
* @y: second value
*/
#define min(x, y) __careful_cmp(x, y, <)
/**
* max - return maximum of two values of the same or compatible types
* @x: first value
* @y: second value
*/
#define max(x, y) __careful_cmp(x, y, >)
/**
* min3 - return minimum of three values
* @x: first value
* @y: second value
* @z: third value
*/
#define min3(x, y, z) min((typeof(x))min(x, y), z)
/**
* max3 - return maximum of three values
* @x: first value
* @y: second value
* @z: third value
*/
#define max3(x, y, z) max((typeof(x))max(x, y), z)
/**
* min_not_zero - return the minimum that is _not_ zero, unless both are zero
* @x: value1
* @y: value2
*/
#define min_not_zero(x, y) ({ \
typeof(x) __x = (x); \
typeof(y) __y = (y); \
__x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); })
/**
* clamp - return a value clamped to a given range with strict typechecking
* @val: current value
* @lo: lowest allowable value
* @hi: highest allowable value
*
* This macro does strict typechecking of @lo/@hi to make sure they are of the
* same type as @val. See the unnecessary pointer comparisons.
*/
#define clamp(val, lo, hi) min((typeof(val))max(val, lo), hi)
/*
* ..and if you can't take the strict
* types, you can specify one yourself.
*
* Or not use min/max/clamp at all, of course.
*/
/**
* min_t - return minimum of two values, using the specified type
* @type: data type to use
* @x: first value
* @y: second value
*/
#define min_t(type, x, y) __careful_cmp((type)(x), (type)(y), <)
/**
* max_t - return maximum of two values, using the specified type
* @type: data type to use
* @x: first value
* @y: second value
*/
#define max_t(type, x, y) __careful_cmp((type)(x), (type)(y), >)
/**
* clamp_t - return a value clamped to a given range using a given type
* @type: the type of variable to use
* @val: current value
* @lo: minimum allowable value
* @hi: maximum allowable value
*
* This macro does no typechecking and uses temporary variables of type
* @type to make all the comparisons.
*/
#define clamp_t(type, val, lo, hi) min_t(type, max_t(type, val, lo), hi)
/**
* clamp_val - return a value clamped to a given range using val's type
* @val: current value
* @lo: minimum allowable value
* @hi: maximum allowable value
*
* This macro does no typechecking and uses temporary variables of whatever
* type the input argument @val is. This is useful when @val is an unsigned
* type and @lo and @hi are literals that will otherwise be assigned a signed
* integer type.
*/
#define clamp_val(val, lo, hi) clamp_t(typeof(val), val, lo, hi)
/**
* swap - swap values of @a and @b
* @a: first value
* @b: second value
*/
#define swap(a, b) \
do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
/**
* ARRAY_SIZE - get the number of elements in array @arr
* @arr: array to be sized
*/
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
/**
* abs - return absolute value of an argument
* @x: the value. If it is unsigned type, it is converted to signed type first.
* char is treated as if it was signed (regardless of whether it really is)
* but the macro's return type is preserved as char.
*
* Return: an absolute value of x.
*/
#define abs(x) __abs_choose_expr(x, long long, \
__abs_choose_expr(x, long, \
__abs_choose_expr(x, int, \
__abs_choose_expr(x, short, \
__abs_choose_expr(x, char, \
__builtin_choose_expr( \
__builtin_types_compatible_p(typeof(x), char), \
(char)({ signed char __x = (x); __x<0?-__x:__x; }), \
((void)0)))))))
#define __abs_choose_expr(x, type, other) __builtin_choose_expr( \
__builtin_types_compatible_p(typeof(x), signed type) || \
__builtin_types_compatible_p(typeof(x), unsigned type), \
({ signed type __x = (x); __x < 0 ? -__x : __x; }), other)
#endif /* _BR_H */

71
2019/include/bug.h Normal file
View File

@@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BR_BUG_H
#define _BR_BUG_H
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "likely.h"
#include "debug.h"
/* BUG functions inspired by Linux kernel's <asm/bug.h>
*/
#define panic() exit(0xff)
/*
* Don't use BUG() or BUG_ON() unless there's really no way out; one
* example might be detecting data structure corruption in the middle
* of an operation that can't be backed out of. If the (sub)system
* can somehow continue operating, perhaps with reduced functionality,
* it's probably not BUG-worthy.
*
* If you're tempted to BUG(), think again: is completely giving up
* really the *only* solution? There are usually better options, where
* users don't need to reboot ASAP and can mostly shut down cleanly.
*/
#define BUG() do { \
fprintf(stderr, "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
panic(); \
} while (0)
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
/*
* WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report
* significant kernel issues that need prompt attention if they should ever
* appear at runtime.
*
* Do not use these macros when checking for invalid external inputs
* (e.g. invalid system call arguments, or invalid data coming from
* network/devices), and on transient conditions like ENOMEM or EAGAIN.
* These macros should be used for recoverable kernel issues only.
* For invalid external inputs, transient conditions, etc use
* pr_err[_once/_ratelimited]() followed by dump_stack(), if necessary.
* Do not include "BUG"/"WARNING" in format strings manually to make these
* conditions distinguishable from kernel issues.
*
* Use the versions with printk format strings to provide better diagnostics.
*/
#define __WARN() do { \
fprintf(stderr, "WARNING: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
} while (0)
#define __WARN_printf(arg...) do { \
vfprintf(stderr, arg); \
} while (0)
#define WARN_ON(condition) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN(); \
unlikely(__ret_warn_on); \
})
#define WARN(condition, format...) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN_printf(format); \
unlikely(__ret_warn_on); \
})
#endif /* _BR_BUG_H */

View File

@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* adaptation of Linux kernel's <linux/container_of.h>
*/
#ifndef _BR_CONTAINER_OF_H
#define _BR_CONTAINER_OF_H
/* Are two types/vars the same type (ignoring qualifiers)? */
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
/**
* typeof_member -
*/
#define typeof_member(T, m) typeof(((T*)0)->m)
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
void *__mptr = (void *)(ptr); \
_Static_assert(__same_type(*(ptr), ((type *)0)->member) || \
__same_type(*(ptr), void), \
"pointer type mismatch in container_of()"); \
((type *)(__mptr - offsetof(type, member))); })
#endif /* BR_CONTAINER_OF_H */

98
2019/include/debug.h Normal file
View File

@@ -0,0 +1,98 @@
/* debug.h - debug/log management.
*
* 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>
*
*/
#ifndef DEBUG_H
#define DEBUG_H
#include <stdbool.h>
#include <stdint.h>
#include "bits.h"
#define _unused __attribute__((__unused__))
#define _printf __attribute__ ((format (printf, 6, 7)))
#ifdef DEBUG_DEBUG
void debug_init(u32 level);
void debug_level_set(u32 level);
void _printf debug(u32 level, bool timestamp,
u32 indent, const char *src,
u32 line, const char *, ...);
#else /* DEBUG_DEBUG */
static inline void debug_init(_unused u32 level) {}
static inline void debug_level_set(_unused u32 level) {}
static inline void _printf debug(_unused u32 level, _unused bool timestamp,
_unused u32 indent, _unused const char *src,
_unused u32 line, const char *, ...) {}
#endif /* DEBUG_DEBUG */
#undef _unused
#undef _printf
/**
* log - simple log (no function name, no indent, no timestamp)
* @level: log level
* @fmt: printf format string
* @args: subsequent arguments to printf
*/
#define log(level, fmt, args...) \
debug((level), false, 0, NULL, 0, fmt, ##args)
/**
* log_i - log with indent (no function name, no timestamp)
* @level: log level
* @fmt: printf format string
* @args: subsequent arguments to printf
*
* Output example:
* >>>>val=2
*/
#define log_i(level, fmt, args...) \
debug((level), false, (level), NULL, 0, fmt, ##args)
/**
* log_f - log with function name (no indent name, no timestamp)
* @level: log level
* @fmt: printf format string
* @args: subsequent arguments to printf
*
* Output example:
* [function] val=2
*/
#define log_f(level, fmt, args...) \
debug((level), false, 0, __func__, 0, fmt, ##args)
/**
* log_if - log with function name and line number (no indent name, no timestamp)
* @level: log level
* @fmt: printf format string
* @args: subsequent arguments to printf
*
* Output example:
* >>>> [function:15] val=2
*/
#define log_if(level, fmt, args...) \
debug((level), false, (level), __func__, __LINE__, fmt, ##args)
/**
* log_it - log with function name, line number, indent, and timestamp
* @level: log level
* @fmt: printf format string
* @args: subsequent arguments to printf
*
* Output example:
* >>>> [function:15] val=2
*/
#define log_it(level, fmt, args...) \
debug((level), true, (level), __func__, __LINE__, fmt, ##args)
#endif /* DEBUG_H */

173
2019/include/hash.h Normal file
View File

@@ -0,0 +1,173 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BR_HASH_H
#define _BR_HASH_H
/* adaptation of Linux kernel's <linux/hash.h> and <linux/stringhash.h>
*/
/* Fast hashing routine for ints, longs and pointers.
(C) 2002 Nadia Yvette Chambers, IBM */
#include <asm/types.h>
#include <asm/bitsperlong.h>
#include "bits.h"
#include "br.h"
/*
* The "GOLDEN_RATIO_PRIME" is used in ifs/btrfs/brtfs_inode.h and
* fs/inode.c. It's not actually prime any more (the previous primes
* were actively bad for hashing), but the name remains.
*/
#if __BITS_PER_LONG == 32
#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_32
#define hash_long(val, bits) hash_32(val, bits)
#elif __BITS_PER_LONG == 64
#define hash_long(val, bits) hash_64(val, bits)
#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_64
#else
#error Wordsize not 32 or 64
#endif
/*
* This hash multiplies the input by a large odd number and takes the
* high bits. Since multiplication propagates changes to the most
* significant end only, it is essential that the high bits of the
* product be used for the hash value.
*
* Chuck Lever verified the effectiveness of this technique:
* http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf
*
* Although a random odd number will do, it turns out that the golden
* ratio phi = (sqrt(5)-1)/2, or its negative, has particularly nice
* properties. (See Knuth vol 3, section 6.4, exercise 9.)
*
* These are the negative, (1 - phi) = phi**2 = (3 - sqrt(5))/2,
* which is very slightly easier to multiply by and makes no
* difference to the hash distribution.
*/
#define GOLDEN_RATIO_32 0x61C88647
#define GOLDEN_RATIO_64 0x61C8864680B583EBull
/*
* The _generic versions exist only so lib/test_hash.c can compare
* the arch-optimized versions with the generic.
*
* Note that if you change these, any <asm/hash.h> that aren't updated
* to match need to have their HAVE_ARCH_* define values updated so the
* self-test will not false-positive.
*/
#ifndef HAVE_ARCH__HASH_32
#define __hash_32 __hash_32_generic
#endif
static inline u32 __hash_32_generic(u32 val)
{
return val * GOLDEN_RATIO_32;
}
static inline u32 hash_32(u32 val, unsigned int bits)
{
/* High bits are more random, so use them. */
return __hash_32(val) >> (32 - bits);
}
#ifndef HAVE_ARCH_HASH_64
#define hash_64 hash_64_generic
#endif
static __always_inline u32 hash_64_generic(u64 val, unsigned int bits)
{
#if __BITS_PER_LONG == 64
/* 64x64-bit multiply is efficient on all 64-bit processors */
return val * GOLDEN_RATIO_64 >> (64 - bits);
#else
/* Hash 64 bits using only 32x32-bit multiply. */
return hash_32((u32)val ^ __hash_32(val >> 32), bits);
#endif
}
static inline u32 hash_ptr(const void *ptr, unsigned int bits)
{
return hash_long((unsigned long)ptr, bits);
}
/* This really should be called fold32_ptr; it does no hashing to speak of. */
static inline u32 hash32_ptr(const void *ptr)
{
unsigned long val = (unsigned long)ptr;
#if __BITS_PER_LONG == 64
val ^= (val >> 32);
#endif
return (u32)val;
}
/*
* Routines for hashing strings of bytes to a 32-bit hash value.
*
* These hash functions are NOT GUARANTEED STABLE between kernel
* versions, architectures, or even repeated boots of the same kernel.
* (E.g. they may depend on boot-time hardware detection or be
* deliberately randomized.)
*
* They are also not intended to be secure against collisions caused by
* malicious inputs; much slower hash functions are required for that.
*
* They are optimized for pathname components, meaning short strings.
* Even if a majority of files have longer names, the dynamic profile of
* pathname components skews short due to short directory names.
* (E.g. /usr/lib/libsesquipedalianism.so.3.141.)
*/
/*
* Version 1: one byte at a time. Example of use:
*
* unsigned long hash = init_name_hash;
* while (*p)
* hash = partial_name_hash(tolower(*p++), hash);
* hash = end_name_hash(hash);
*
* Although this is designed for bytes, fs/hfsplus/unicode.c
* abuses it to hash 16-bit values.
*/
/* Hash courtesy of the R5 hash in reiserfs modulo sign bits */
#define init_name_hash(salt) (unsigned long)(salt)
/* partial hash update function. Assume roughly 4 bits per character */
static inline unsigned long
partial_name_hash(unsigned long c, unsigned long prevhash)
{
return (prevhash + (c << 4) + (c >> 4)) * 11;
}
/*
* Finally: cut down the number of bits to a int value (and try to avoid
* losing bits). This also has the property (wanted by the dcache)
* that the msbits make a good hash table index.
*/
static inline unsigned int end_name_hash(unsigned long hash)
{
return hash_long(hash, 32);
}
/*
* Version 2: One word (32 or 64 bits) at a time.
* If CONFIG_DCACHE_WORD_ACCESS is defined (meaning <asm/word-at-a-time.h>
* exists, which describes major Linux platforms like x86 and ARM), then
* this computes a different hash function much faster.
*
* If not set, this falls back to a wrapper around the preceding.
*/
extern unsigned int __pure hash_string(const void *salt, const char *, unsigned int);
/*
* A hash_len is a u64 with the hash of a string in the low
* half and the length in the high half.
*/
#define hashlen_hash(hashlen) ((u32)(hashlen))
#define hashlen_len(hashlen) ((u32)((hashlen) >> 32))
#define hashlen_create(hash, len) ((u64)(len)<<32 | (u32)(hash))
/* Return the "hash_len" (hash and length) of a null-terminated string */
extern u64 __pure hashlen_string(const void *salt, const char *name);
#endif /* _BR_HASH_H */

204
2019/include/hashtable.h Normal file
View File

@@ -0,0 +1,204 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* adaptation of Linux kernel's <linux/hashtable.h>
*/
/*
* Statically sized hash table implementation
* (C) 2012 Sasha Levin <levinsasha928@gmail.com>
*/
#ifndef _LINUX_HASHTABLE_H
#define _LINUX_HASHTABLE_H
#include "list.h"
#include <linux/types.h>
#include <linux/kernel.h>
#include "hash.h"
//#include <linux/rculist.h>
#define DEFINE_HASHTABLE(name, bits) \
struct hlist_head name[1 << (bits)] = \
{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
#define DEFINE_READ_MOSTLY_HASHTABLE(name, bits) \
struct hlist_head name[1 << (bits)] __read_mostly = \
{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
#define DECLARE_HASHTABLE(name, bits) \
struct hlist_head name[1 << (bits)]
#define HASH_SIZE(name) (ARRAY_SIZE(name))
#define HASH_BITS(name) ilog2(HASH_SIZE(name))
/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
#define hash_min(val, bits) \
(sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
{
unsigned int i;
for (i = 0; i < sz; i++)
INIT_HLIST_HEAD(&ht[i]);
}
/**
* hash_init - initialize a hash table
* @hashtable: hashtable to be initialized
*
* Calculates the size of the hashtable from the given parameter, otherwise
* same as hash_init_size.
*
* This has to be a macro since HASH_BITS() will not work on pointers since
* it calculates the size during preprocessing.
*/
#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
/**
* hash_add - add an object to a hashtable
* @hashtable: hashtable to add to
* @node: the &struct hlist_node of the object to be added
* @key: the key of the object to be added
*/
#define hash_add(hashtable, node, key) \
hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
/**
* hash_add_rcu - add an object to a rcu enabled hashtable
* @hashtable: hashtable to add to
* @node: the &struct hlist_node of the object to be added
* @key: the key of the object to be added
*/
#define hash_add_rcu(hashtable, node, key) \
hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
/**
* hash_hashed - check whether an object is in any hashtable
* @node: the &struct hlist_node of the object to be checked
*/
static inline bool hash_hashed(struct hlist_node *node)
{
return !hlist_unhashed(node);
}
static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz)
{
unsigned int i;
for (i = 0; i < sz; i++)
if (!hlist_empty(&ht[i]))
return false;
return true;
}
/**
* hash_empty - check whether a hashtable is empty
* @hashtable: hashtable to check
*
* This has to be a macro since HASH_BITS() will not work on pointers since
* it calculates the size during preprocessing.
*/
#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
/**
* hash_del - remove an object from a hashtable
* @node: &struct hlist_node of the object to remove
*/
static inline void hash_del(struct hlist_node *node)
{
hlist_del_init(node);
}
/**
* hash_for_each - iterate over a hashtable
* @name: hashtable to iterate
* @bkt: integer to use as bucket loop cursor
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
*/
#define hash_for_each(name, bkt, obj, member) \
for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
(bkt)++)\
hlist_for_each_entry(obj, &name[bkt], member)
/**
* hash_for_each_rcu - iterate over a rcu enabled hashtable
* @name: hashtable to iterate
* @bkt: integer to use as bucket loop cursor
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
*/
#define hash_for_each_rcu(name, bkt, obj, member) \
for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
(bkt)++)\
hlist_for_each_entry_rcu(obj, &name[bkt], member)
/**
* hash_for_each_safe - iterate over a hashtable safe against removal of
* hash entry
* @name: hashtable to iterate
* @bkt: integer to use as bucket loop cursor
* @tmp: a &struct hlist_node used for temporary storage
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
*/
#define hash_for_each_safe(name, bkt, tmp, obj, member) \
for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
(bkt)++)\
hlist_for_each_entry_safe(obj, tmp, &name[bkt], member)
/**
* hash_for_each_possible - iterate over all possible objects hashing to the
* same bucket
* @name: hashtable to iterate
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
* @key: the key of the objects to iterate over
*/
#define hash_for_each_possible(name, obj, member, key) \
hlist_for_each_entry(obj, &name[hash_min(key, HASH_BITS(name))], member)
/**
* hash_for_each_possible_rcu - iterate over all possible objects hashing to the
* same bucket in an rcu enabled hashtable
* @name: hashtable to iterate
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
* @key: the key of the objects to iterate over
*/
#define hash_for_each_possible_rcu(name, obj, member, key, cond...) \
hlist_for_each_entry_rcu(obj, &name[hash_min(key, HASH_BITS(name))],\
member, ## cond)
/**
* hash_for_each_possible_rcu_notrace - iterate over all possible objects hashing
* to the same bucket in an rcu enabled hashtable in a rcu enabled hashtable
* @name: hashtable to iterate
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
* @key: the key of the objects to iterate over
*
* This is the same as hash_for_each_possible_rcu() except that it does
* not do any RCU debugging or tracing.
*/
#define hash_for_each_possible_rcu_notrace(name, obj, member, key) \
hlist_for_each_entry_rcu_notrace(obj, \
&name[hash_min(key, HASH_BITS(name))], member)
/**
* hash_for_each_possible_safe - iterate over all possible objects hashing to the
* same bucket safe against removals
* @name: hashtable to iterate
* @obj: the type * to use as a loop cursor for each entry
* @tmp: a &struct hlist_node used for temporary storage
* @member: the name of the hlist_node within the struct
* @key: the key of the objects to iterate over
*/
#define hash_for_each_possible_safe(name, obj, tmp, member, key) \
hlist_for_each_entry_safe(obj, tmp,\
&name[hash_min(key, HASH_BITS(name))], member)
#endif

18
2019/include/likely.h Normal file
View File

@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* taken from Kernel's <linux/compiler.h
*/
#ifndef __LIKELY_H
#define __LIKELY_H
/* See https://kernelnewbies.org/FAQ/LikelyUnlikely
*
* In 2 words:
* "You should use it [likely() and unlikely()] only in cases when the likeliest
* branch is very very very likely, or when the unlikeliest branch is very very
* very unlikely."
*/
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#endif /* __LIKELY_H */

992
2019/include/list.h Normal file
View File

@@ -0,0 +1,992 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* adaptation of kernel's <linux/list.h>
*
*/
#ifndef __BR_LIST_H
#define __BR_LIST_H
#include <stddef.h>
#include <stdbool.h>
#include "rwonce.h"
#include "container-of.h"
/************ originally in <include/linux/types.h> */
struct list_head {
struct list_head *next, *prev;
};
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
/************ originally in <include/linux/poison.h> */
# define POISON_POINTER_DELTA 0
/* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
*/
#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA)
#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA)
/*
* Circular doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
/**
* INIT_LIST_HEAD - Initialize a list_head structure
* @list: list_head structure to be initialized.
*
* Initializes the list_head to point to itself. If it is a list header,
* the result is an empty list.
*/
static inline void INIT_LIST_HEAD(struct list_head *list)
{
WRITE_ONCE(list->next, list);
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
WRITE_ONCE(prev->next, new);
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
WRITE_ONCE(prev->next, next);
}
/*
* Delete a list entry and clear the 'prev' pointer.
*
* This is a special-purpose list clearing method used in the networking code
* for lists allocated as per-cpu, where we don't want to incur the extra
* WRITE_ONCE() overhead of a regular list_del_init(). The code that uses this
* needs to check the node 'prev' pointer instead of calling list_empty().
*/
static inline void __list_del_clearprev(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->prev = NULL;
}
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del_entry(entry);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
/**
* list_replace - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
/**
* list_replace_init - replace old entry by new one and initialize the old one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace_init(struct list_head *old,
struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
/**
* list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position
* @entry1: the location to place entry2
* @entry2: the location to place entry1
*/
static inline void list_swap(struct list_head *entry1,
struct list_head *entry2)
{
struct list_head *pos = entry2->prev;
list_del(entry2);
list_replace(entry1, entry2);
if (pos == entry1)
pos = entry2;
list_add(entry1, pos);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del_entry(entry);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del_entry(list);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del_entry(list);
list_add_tail(list, head);
}
/**
* list_bulk_move_tail - move a subsection of a list to its tail
* @head: the head that will follow our entry
* @first: first entry to move
* @last: last entry to move, can be the same as first
*
* Move all entries between @first and including @last before @head.
* All three entries must belong to the same linked list.
*/
static inline void list_bulk_move_tail(struct list_head *head,
struct list_head *first,
struct list_head *last)
{
first->prev->next = last->next;
last->next->prev = first->prev;
head->prev->next = first;
first->prev = head->prev;
last->next = head;
head->prev = last;
}
/**
* list_is_first -- tests whether @list is the first entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_first(const struct list_head *list,
const struct list_head *head)
{
return list->prev == head;
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return READ_ONCE(head->next) == head;
}
/**
* list_rotate_left - rotate the list to the left
* @head: the head of the list
*/
static inline void list_rotate_left(struct list_head *head)
{
struct list_head *first;
if (!list_empty(head)) {
first = head->next;
list_move_tail(first, head);
}
}
/**
* list_rotate_to_front() - Rotate list to specific item.
* @list: The desired new front of the list.
* @head: The head of the list.
*
* Rotates list so that @list becomes the new front of the list.
*/
static inline void list_rotate_to_front(struct list_head *list,
struct list_head *head)
{
/*
* Deletes the list head from the list denoted by @head and
* places it as the tail of @list, this effectively rotates the
* list so that @list is at the front.
*/
list_move_tail(head, list);
}
/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
static inline int list_is_singular(const struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
}
static inline void __list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
struct list_head *new_first = entry->next;
list->next = head->next;
list->next->prev = list;
list->prev = entry;
entry->next = list;
head->next = new_first;
new_first->prev = head;
}
/**
* list_cut_position - cut a list into two
* @list: a new list to add all removed entries
* @head: a list with entries
* @entry: an entry within head, could be the head itself
* and if so we won't cut the list
*
* This helper moves the initial part of @head, up to and
* including @entry, from @head to @list. You should
* pass on @entry an element you know is on @head. @list
* should be an empty list or a list you do not care about
* losing its data.
*
*/
static inline void list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
if (list_empty(head))
return;
if (list_is_singular(head) &&
(head->next != entry && head != entry))
return;
if (entry == head)
INIT_LIST_HEAD(list);
else
__list_cut_position(list, head, entry);
}
/**
* list_cut_before - cut a list into two, before given entry
* @list: a new list to add all removed entries
* @head: a list with entries
* @entry: an entry within head, could be the head itself
*
* This helper moves the initial part of @head, up to but
* excluding @entry, from @head to @list. You should pass
* in @entry an element you know is on @head. @list should
* be an empty list or a list you do not care about losing
* its data.
* If @entry == @head, all entries on @head are moved to
* @list.
*/
static inline void list_cut_before(struct list_head *list,
struct list_head *head,
struct list_head *entry)
{
if (head->next == entry) {
INIT_LIST_HEAD(list);
return;
}
list->next = head->next;
list->next->prev = list;
list->prev = entry->prev;
list->prev->next = list;
head->next = entry;
entry->prev = head;
}
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
/**
* list_splice - join two lists, this is designed for stacks
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(const struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head, head->next);
}
/**
* list_splice_tail - join two lists, each list being a queue
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice_tail(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head->prev, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head, head->next);
INIT_LIST_HEAD(list);
}
}
/**
* list_splice_tail_init - join two lists and reinitialise the emptied list
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* Each of the lists is a queue.
* The list at @list is reinitialised
*/
static inline void list_splice_tail_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head->prev, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_last_entry - get the last element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_last_entry(ptr, type, member) \
list_entry((ptr)->prev, type, member)
/**
* list_first_entry_or_null - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note that if the list is empty, it returns NULL.
*/
#define list_first_entry_or_null(ptr, type, member) ({ \
struct list_head *head__ = (ptr); \
struct list_head *pos__ = READ_ONCE(head__->next); \
pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
})
/**
* list_next_entry - get the next element in list
* @pos: the type * to cursor
* @member: the name of the list_head within the struct.
*/
#define list_next_entry(pos, member) \
list_entry((pos)->member.next, __typeof__(*(pos)), member)
/**
* list_prev_entry - get the prev element in list
* @pos: the type * to cursor
* @member: the name of the list_head within the struct.
*/
#define list_prev_entry(pos, member) \
list_entry((pos)->member.prev, __typeof__(*(pos)), member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_continue - continue iteration over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*
* Continue to iterate over a list, continuing after the current position.
*/
#define list_for_each_continue(pos, head) \
for (pos = pos->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_prev_safe(pos, n, head) \
for (pos = (head)->prev, n = pos->prev; \
pos != (head); \
pos = n, n = pos->prev)
/**
* list_entry_is_head - test if the entry points to the head of the list
* @pos: the type * to cursor
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_entry_is_head(pos, head, member) \
(&pos->member == (head))
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, __typeof__(*pos), member); \
!list_entry_is_head(pos, head, member); \
pos = list_next_entry(pos, member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_last_entry(head, __typeof__(*pos), member); \
!list_entry_is_head(pos, head, member); \
pos = list_prev_entry(pos, member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_head within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member) \
((pos) ? : list_entry(head, __typeof__(*pos), member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_next_entry(pos, member); \
!list_entry_is_head(pos, head, member); \
pos = list_next_entry(pos, member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define list_for_each_entry_continue_reverse(pos, head, member) \
for (pos = list_prev_entry(pos, member); \
!list_entry_is_head(pos, head, member); \
pos = list_prev_entry(pos, member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member) \
for (; !list_entry_is_head(pos, head, member); \
pos = list_next_entry(pos, member))
/**
* list_for_each_entry_from_reverse - iterate backwards over list of given type
* from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate backwards over list of given type, continuing from current position.
*/
#define list_for_each_entry_from_reverse(pos, head, member) \
for (; !list_entry_is_head(pos, head, member); \
pos = list_prev_entry(pos, member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_first_entry(head, __typeof__(*pos), member), \
n = list_next_entry(pos, member); \
!list_entry_is_head(pos, head, member); \
pos = n, n = list_next_entry(n, member))
/**
* list_for_each_entry_safe_continue - continue list iteration safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = list_next_entry(pos, member), \
n = list_next_entry(pos, member); \
!list_entry_is_head(pos, head, member); \
pos = n, n = list_next_entry(n, member))
/**
* list_for_each_entry_safe_from - iterate over list from current point safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
for (n = list_next_entry(pos, member); \
!list_entry_is_head(pos, head, member); \
pos = n, n = list_next_entry(n, member))
/**
* list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_last_entry(head, __typeof__(*pos), member), \
n = list_prev_entry(pos, member); \
!list_entry_is_head(pos, head, member); \
pos = n, n = list_prev_entry(n, member))
/**
* list_safe_reset_next - reset a stale list_for_each_entry_safe loop
* @pos: the loop cursor used in the list_for_each_entry_safe loop
* @n: temporary storage used in list_for_each_entry_safe
* @member: the name of the list_head within the struct.
*
* list_safe_reset_next is not safe to use in general if the list may be
* modified concurrently (eg. the lock is dropped in the loop body). An
* exception to this is if the cursor element (pos) is pinned in the list,
* and list_safe_reset_next is called after re-taking the lock and before
* completing the current iteration of the loop body.
*/
#define list_safe_reset_next(pos, n, member) \
n = list_next_entry(pos, member)
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
/**
* hlist_unhashed - Has node been removed from list and reinitialized?
* @h: Node to be checked
*
* Not that not all removal functions will leave a node in unhashed
* state. For example, hlist_nulls_del_init_rcu() does leave the
* node in unhashed state, but hlist_nulls_del() does not.
*/
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
/**
* hlist_unhashed_lockless - Version of hlist_unhashed for lockless use
* @h: Node to be checked
*
* This variant of hlist_unhashed() must be used in lockless contexts
* to avoid potential load-tearing. The READ_ONCE() is paired with the
* various WRITE_ONCE() in hlist helpers that are defined below.
*/
static inline int hlist_unhashed_lockless(const struct hlist_node *h)
{
return !READ_ONCE(h->pprev);
}
/**
* hlist_empty - Is the specified hlist_head structure an empty hlist?
* @h: Structure to check.
*/
static inline int hlist_empty(const struct hlist_head *h)
{
return !READ_ONCE(h->first);
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
WRITE_ONCE(*pprev, next);
if (next)
WRITE_ONCE(next->pprev, pprev);
}
/**
* hlist_del - Delete the specified hlist_node from its list
* @n: Node to delete.
*
* Note that this function leaves the node in hashed state. Use
* hlist_del_init() or similar instead to unhash @n.
*/
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
/**
* hlist_del_init - Delete the specified hlist_node from its list and initialize
* @n: Node to delete.
*
* Note that this function leaves the node in unhashed state.
*/
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
/**
* hlist_add_head - add a new entry at the beginning of the hlist
* @n: new entry to be added
* @h: hlist head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
WRITE_ONCE(n->next, first);
if (first)
WRITE_ONCE(first->pprev, &n->next);
WRITE_ONCE(h->first, n);
WRITE_ONCE(n->pprev, &h->first);
}
/**
* hlist_add_before - add a new entry before the one specified
* @n: new entry to be added
* @next: hlist node to add it before, which must be non-NULL
*/
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
WRITE_ONCE(n->pprev, next->pprev);
WRITE_ONCE(n->next, next);
WRITE_ONCE(next->pprev, &n->next);
WRITE_ONCE(*(n->pprev), n);
}
/**
* hlist_add_behind - add a new entry after the one specified
* @n: new entry to be added
* @prev: hlist node to add it after, which must be non-NULL
*/
static inline void hlist_add_behind(struct hlist_node *n,
struct hlist_node *prev)
{
WRITE_ONCE(n->next, prev->next);
WRITE_ONCE(prev->next, n);
WRITE_ONCE(n->pprev, &prev->next);
if (n->next)
WRITE_ONCE(n->next->pprev, &n->next);
}
/**
* hlist_add_fake - create a fake hlist consisting of a single headless node
* @n: Node to make a fake list out of
*
* This makes @n appear to be its own predecessor on a headless hlist.
* The point of this is to allow things like hlist_del() to work correctly
* in cases where there is no list.
*/
static inline void hlist_add_fake(struct hlist_node *n)
{
n->pprev = &n->next;
}
/**
* hlist_fake: Is this node a fake hlist?
* @h: Node to check for being a self-referential fake hlist.
*/
static inline bool hlist_fake(struct hlist_node *h)
{
return h->pprev == &h->next;
}
/**
* hlist_is_singular_node - is node the only element of the specified hlist?
* @n: Node to check for singularity.
* @h: Header for potentially singular list.
*
* Check whether the node is the only node of the head without
* accessing head, thus avoiding unnecessary cache misses.
*/
static inline bool
hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h)
{
return !n->next && n->pprev == &h->first;
}
/**
* hlist_move_list - Move an hlist
* @old: hlist_head for old list.
* @new: hlist_head for new list.
*
* Move a list from one list head to another. Fixup the pprev
* reference of the first entry if it exists.
*/
static inline void hlist_move_list(struct hlist_head *old,
struct hlist_head *new)
{
new->first = old->first;
if (new->first)
new->first->pprev = &new->first;
old->first = NULL;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos ; pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
#define hlist_entry_safe(ptr, type, member) \
({ __typeof__(ptr) ____ptr = (ptr); \
____ptr ? hlist_entry(____ptr, type, member) : NULL; \
})
/**
* hlist_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(pos, head, member) \
for (pos = hlist_entry_safe((head)->first, __typeof__(*(pos)), member); \
pos; \
pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member))
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* @pos: the type * to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(pos, member) \
for (pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member); \
pos; \
pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member))
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* @pos: the type * to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(pos, member) \
for (; pos; \
pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member))
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: a &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(pos, n, head, member) \
for (pos = hlist_entry_safe((head)->first, __typeof__(*pos), member); \
pos && ({ n = pos->member.next; 1; }); \
pos = hlist_entry_safe(n, __typeof__(*pos), member))
#endif /* __BR_LIST_H */

301
2019/include/plist.h Normal file
View File

@@ -0,0 +1,301 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Descending-priority-sorted double-linked list
*
* (C) 2002-2003 Intel Corp
* Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.
*
* 2001-2005 (c) MontaVista Software, Inc.
* Daniel Walker <dwalker@mvista.com>
*
* (C) 2005 Thomas Gleixner <tglx@linutronix.de>
*
* Simplifications of the original code by
* Oleg Nesterov <oleg@tv-sign.ru>
*
* Based on simple lists (include/linux/list.h).
*
* This is a priority-sorted list of nodes; each node has a
* priority from INT_MIN (highest) to INT_MAX (lowest).
*
* Addition is O(K), removal is O(1), change of priority of a node is
* O(K) and K is the number of RT priority levels used in the system.
* (1 <= K <= 99)
*
* This list is really a list of lists:
*
* - The tier 1 list is the prio_list, different priority nodes.
*
* - The tier 2 list is the node_list, serialized nodes.
*
* Simple ASCII art explanation:
*
* pl:prio_list (only for plist_node)
* nl:node_list
* HEAD| NODE(S)
* |
* ||------------------------------------|
* ||->|pl|<->|pl|<--------------->|pl|<-|
* | |10| |21| |21| |21| |40| (prio)
* | | | | | | | | | | |
* | | | | | | | | | | |
* |->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-|
* |-------------------------------------------|
*
* The nodes on the prio_list list are sorted by priority to simplify
* the insertion of new nodes. There are no nodes with duplicate
* priorites on the list.
*
* The nodes on the node_list are ordered by priority and can contain
* entries which have the same priority. Those entries are ordered
* FIFO
*
* Addition means: look for the prio_list node in the prio_list
* for the priority of the node and insert it before the node_list
* entry of the next prio_list node. If it is the first node of
* that priority, add it to the prio_list in the right position and
* insert it into the serialized node_list list
*
* Removal means remove it from the node_list and remove it from
* the prio_list if the node_list list_head is non empty. In case
* of removal from the prio_list it must be checked whether other
* entries of the same priority are on the list or not. If there
* is another entry of the same priority then this entry has to
* replace the removed entry on the prio_list. If the entry which
* is removed is the only entry of this priority then a simple
* remove from both list is sufficient.
*
* INT_MIN is the highest priority, 0 is the medium highest, INT_MAX
* is lowest priority.
*
* No locking is done, up to the caller.
*/
#ifndef _LINUX_PLIST_H_
#define _LINUX_PLIST_H_
#include "container-of.h"
#include "list.h"
//#include <types.h>
// #include <asm/bug.h>
struct plist_head {
struct list_head node_list;
};
struct plist_node {
int prio;
struct list_head prio_list;
struct list_head node_list;
};
/**
* PLIST_HEAD_INIT - static struct plist_head initializer
* @head: struct plist_head variable name
*/
#define PLIST_HEAD_INIT(head) \
{ \
.node_list = LIST_HEAD_INIT((head).node_list) \
}
/**
* PLIST_HEAD - declare and init plist_head
* @head: name for struct plist_head variable
*/
#define PLIST_HEAD(head) \
struct plist_head head = PLIST_HEAD_INIT(head)
/**
* PLIST_NODE_INIT - static struct plist_node initializer
* @node: struct plist_node variable name
* @__prio: initial node priority
*/
#define PLIST_NODE_INIT(node, __prio) \
{ \
.prio = (__prio), \
.prio_list = LIST_HEAD_INIT((node).prio_list), \
.node_list = LIST_HEAD_INIT((node).node_list), \
}
/**
* plist_head_init - dynamic struct plist_head initializer
* @head: &struct plist_head pointer
*/
static inline void
plist_head_init(struct plist_head *head)
{
INIT_LIST_HEAD(&head->node_list);
}
/**
* plist_node_init - Dynamic struct plist_node initializer
* @node: &struct plist_node pointer
* @prio: initial node priority
*/
static inline void plist_node_init(struct plist_node *node, int prio)
{
node->prio = prio;
INIT_LIST_HEAD(&node->prio_list);
INIT_LIST_HEAD(&node->node_list);
}
extern void plist_add(struct plist_node *node, struct plist_head *head);
extern void plist_del(struct plist_node *node, struct plist_head *head);
extern void plist_requeue(struct plist_node *node, struct plist_head *head);
/**
* plist_for_each - iterate over the plist
* @pos: the type * to use as a loop counter
* @head: the head for your list
*/
#define plist_for_each(pos, head) \
list_for_each_entry(pos, &(head)->node_list, node_list)
/**
* plist_for_each_continue - continue iteration over the plist
* @pos: the type * to use as a loop cursor
* @head: the head for your list
*
* Continue to iterate over plist, continuing after the current position.
*/
#define plist_for_each_continue(pos, head) \
list_for_each_entry_continue(pos, &(head)->node_list, node_list)
/**
* plist_for_each_safe - iterate safely over a plist of given type
* @pos: the type * to use as a loop counter
* @n: another type * to use as temporary storage
* @head: the head for your list
*
* Iterate over a plist of given type, safe against removal of list entry.
*/
#define plist_for_each_safe(pos, n, head) \
list_for_each_entry_safe(pos, n, &(head)->node_list, node_list)
/**
* plist_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop counter
* @head: the head for your list
* @mem: the name of the list_head within the struct
*/
#define plist_for_each_entry(pos, head, mem) \
list_for_each_entry(pos, &(head)->node_list, mem.node_list)
/**
* plist_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor
* @head: the head for your list
* @m: the name of the list_head within the struct
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define plist_for_each_entry_continue(pos, head, m) \
list_for_each_entry_continue(pos, &(head)->node_list, m.node_list)
/**
* plist_for_each_entry_safe - iterate safely over list of given type
* @pos: the type * to use as a loop counter
* @n: another type * to use as temporary storage
* @head: the head for your list
* @m: the name of the list_head within the struct
*
* Iterate over list of given type, safe against removal of list entry.
*/
#define plist_for_each_entry_safe(pos, n, head, m) \
list_for_each_entry_safe(pos, n, &(head)->node_list, m.node_list)
/**
* plist_head_empty - return !0 if a plist_head is empty
* @head: &struct plist_head pointer
*/
static inline int plist_head_empty(const struct plist_head *head)
{
return list_empty(&head->node_list);
}
/**
* plist_node_empty - return !0 if plist_node is not on a list
* @node: &struct plist_node pointer
*/
static inline int plist_node_empty(const struct plist_node *node)
{
return list_empty(&node->node_list);
}
/* All functions below assume the plist_head is not empty. */
/**
* plist_first_entry - get the struct for the first entry
* @head: the &struct plist_head pointer
* @type: the type of the struct this is embedded in
* @member: the name of the list_head within the struct
*/
#ifdef CONFIG_DEBUG_PLIST
# define plist_first_entry(head, type, member) \
({ \
WARN_ON(plist_head_empty(head)); \
container_of(plist_first(head), type, member); \
})
#else
# define plist_first_entry(head, type, member) \
container_of(plist_first(head), type, member)
#endif
/**
* plist_last_entry - get the struct for the last entry
* @head: the &struct plist_head pointer
* @type: the type of the struct this is embedded in
* @member: the name of the list_head within the struct
*/
#ifdef CONFIG_DEBUG_PLIST
# define plist_last_entry(head, type, member) \
({ \
WARN_ON(plist_head_empty(head)); \
container_of(plist_last(head), type, member); \
})
#else
# define plist_last_entry(head, type, member) \
container_of(plist_last(head), type, member)
#endif
/**
* plist_next - get the next entry in list
* @pos: the type * to cursor
*/
#define plist_next(pos) \
list_next_entry(pos, node_list)
/**
* plist_prev - get the prev entry in list
* @pos: the type * to cursor
*/
#define plist_prev(pos) \
list_prev_entry(pos, node_list)
/**
* plist_first - return the first node (and thus, highest priority)
* @head: the &struct plist_head pointer
*
* Assumes the plist is _not_ empty.
*/
static inline struct plist_node *plist_first(const struct plist_head *head)
{
return list_entry(head->node_list.next,
struct plist_node, node_list);
}
/**
* plist_last - return the last node (and thus, lowest priority)
* @head: the &struct plist_head pointer
*
* Assumes the plist is _not_ empty.
*/
static inline struct plist_node *plist_last(const struct plist_head *head)
{
return list_entry(head->node_list.prev,
struct plist_node, node_list);
}
#endif

90
2019/include/pool.h Normal file
View File

@@ -0,0 +1,90 @@
/* pool.h - A simple memory pool manager.
*
* 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>
*
*/
#ifndef POOL_H
#define POOL_H
#include <stdint.h>
#include <stddef.h>
#include "list.h"
#include "bits.h"
#define POOL_NAME_LENGTH (16) /* max name length including trailing \0 */
typedef struct {
struct list_head list_blocks; /* list of allocated blocks in pool */
char data[]; /* objects block */
} block_t;
typedef struct {
char name[POOL_NAME_LENGTH]; /* pool name */
size_t eltsize; /* object size */
u32 available; /* current available elements */
u32 allocated; /* total objects allocated */
u32 growsize; /* number of objects per block allocated */
u32 nblocks; /* number of blocks allocated */
struct list_head list_available; /* available nodes */
struct list_head list_blocks; /* allocated blocks */
} pool_t;
/**
* pool_stats - display some pool statistics
* @pool: the pool address.
*/
void pool_stats(pool_t *pool);
/**
* pool_create - create a new memory pool
* @name: the name to give to the pool.
* @grow: the number of elements to add when no more available.
* @size: the size of an element in pool.
*
* The name will be truncated to 16 characters (including the final '\0').
*
* Return: The address of the created pool, or NULL if error.
*/
pool_t *pool_create(const char *name, u32 grow, size_t size);
/**
* pool_get() - Get an element from a pool.
* @pool: The pool address.
*
* Get an object from the pool.
*
* Return: The address of the object, or NULL if error.
*/
void *pool_get(pool_t *pool);
/**
* pool_add() - Add (free) an element to a pool.
* @pool: The pool address.
* @elt: The address of the object to add to the pool.
*
* The object will be available for further pool_get().
*
* Return: The current number of available elements in pool (including
* @elt).
*/
u32 pool_add(pool_t *pool, void *elt);
/**
* pool_destroy() - destroy a pool.
* @pool: The pool address.
*
* Attention: All memory is freed, but no check is done whether all pool
* elements have been released. Referencing any pool object after this call
* will likely imply some memory corruption.
*/
void pool_destroy(pool_t *pool);
#endif

128
2019/include/rwonce.h Normal file
View File

@@ -0,0 +1,128 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* adaptation of kernel's <asm-generic/rwonce.h>
* See https://www.kernel.org/doc/Documentation/memory-barriers.txt
*/
/*
* Prevent the compiler from merging or refetching reads or writes. The
* compiler is also forbidden from reordering successive instances of
* READ_ONCE and WRITE_ONCE, but only when the compiler is aware of some
* particular ordering. One way to make the compiler aware of ordering is to
* put the two invocations of READ_ONCE or WRITE_ONCE in different C
* statements.
*
* These two macros will also work on aggregate data types like structs or
* unions.
*
* Their two major use cases are: (1) Mediating communication between
* process-level code and irq/NMI handlers, all running on the same CPU,
* and (2) Ensuring that the compiler does not fold, spindle, or otherwise
* mutilate accesses that either do not require ordering or that interact
* with an explicit memory barrier or atomic instruction that provides the
* required ordering.
*/
#ifndef __BR_RWONCE_H
#define __BR_RWONCE_H
/************ originally in <include/linux/compiler_attributes.h> */
#if __has_attribute(__error__)
# define __compiletime_error(msg) __attribute__((__error__(msg)))
#else
# define __compiletime_error(msg)
#endif
/************ originally in <include/linux/compiler_types.h> */
/*
* __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
* non-scalar types unchanged.
*/
/*
* Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
* is not type-compatible with 'signed char', and we define a separate case.
*/
#define __scalar_type_to_expr_cases(type) \
unsigned type: (unsigned type)0, \
signed type: (signed type)0
#define __unqual_scalar_typeof(x) \
typeof(_Generic((x), \
char: (char)0, \
__scalar_type_to_expr_cases(char), \
__scalar_type_to_expr_cases(short), \
__scalar_type_to_expr_cases(int), \
__scalar_type_to_expr_cases(long), \
__scalar_type_to_expr_cases(long long), \
default: (x)))
/* Is this type a native word size -- useful for atomic operations */
#define __native_word(t) \
(sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
#ifdef __OPTIMIZE__
# define __compiletime_assert(condition, msg, prefix, suffix) \
do { \
extern void prefix ## suffix(void) __compiletime_error(msg); \
if (!(condition)) \
prefix ## suffix(); \
} while (0)
#else
# define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0)
#endif
#define _compiletime_assert(condition, msg, prefix, suffix) \
__compiletime_assert(condition, msg, prefix, suffix)
/**
* compiletime_assert - break build and emit msg if condition is false
* @condition: a compile-time constant condition to check
* @msg: a message to emit if condition is false
*
* In tradition of POSIX assert, this macro will break the build if the
* supplied condition is *false*, emitting the supplied error message if the
* compiler has support to do so.
*/
#define compiletime_assert(condition, msg) \
_compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
#define compiletime_assert_atomic_type(t) \
compiletime_assert(__native_word(t), \
"Need native word sized stores/loads for atomicity.")
/************ originally in <asm-generic/rwonce.h> */
/*
* Yes, this permits 64-bit accesses on 32-bit architectures. These will
* actually be atomic in some cases (namely Armv7 + LPAE), but for others we
* rely on the access being split into 2x32-bit accesses for a 32-bit quantity
* (e.g. a virtual address) and a strong prevailing wind.
*/
#define compiletime_assert_rwonce_type(t) \
compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
"Unsupported access size for {READ,WRITE}_ONCE().")
/*
* Use __READ_ONCE() instead of READ_ONCE() if you do not require any
* atomicity. Note that this may result in tears!
*/
#ifndef __READ_ONCE
#define __READ_ONCE(x) (*(const volatile __unqual_scalar_typeof(x) *)&(x))
#endif
#define READ_ONCE(x) \
({ \
compiletime_assert_rwonce_type(x); \
__READ_ONCE(x); \
})
#define __WRITE_ONCE(x, val) \
do { \
*(volatile typeof(x) *)&(x) = (val); \
} while (0)
#define WRITE_ONCE(x, val) \
do { \
compiletime_assert_rwonce_type(x); \
__WRITE_ONCE(x, val); \
} while (0)
#endif /* __BR_RWONCE_H */

111
2019/libsrc/debug.c Normal file
View File

@@ -0,0 +1,111 @@
/* debug.c - debug/log management
*
* 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>
*
*/
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#ifndef DEBUG_DEBUG
#define DEBUG_DEBUG
#endif
#include "debug.h"
#define NANOSEC 1000000000 /* nano sec in sec */
#define MILLISEC 1000000 /* milli sec in sec */
static s64 timer_start; /* in nanosecond */
static u32 debug_level=0;
void debug_level_set(u32 level)
{
debug_level = level;
log(1, "debug level set to %u\n", level);
}
void debug_init(u32 level)
{
struct timespec timer;
debug_level_set(level);
if (!clock_gettime(CLOCK_MONOTONIC, &timer)) {
timer_start = timer.tv_sec * NANOSEC + timer.tv_nsec;
}
else {
timer_start = 0;
}
log(0, "timer started.\n");
}
inline static s64 timer_elapsed()
{
struct timespec timer;
clock_gettime(CLOCK_MONOTONIC, &timer);
return (timer.tv_sec * NANOSEC + timer.tv_nsec) - timer_start;
}
/* void debug - log function
* @timestamp : boolean
* @indent : indent level (2 spaces each)
* @src : source file/func name (or NULL)
* @line : line number
*/
void debug(u32 level, bool timestamp, u32 indent, const char *src,
u32 line, const char *fmt, ...)
{
if (level > debug_level)
return;
va_list ap;
if (indent)
printf("%*s", 2*(indent-1), "");
if (timestamp) {
s64 diff = timer_elapsed();
printf("%ld.%03ld ", diff/NANOSEC, (diff/1000000)%1000);
printf("%010ld ", diff);
}
if (src) {
if (line)
printf("[%s:%u] ", src, line);
else
printf("[%s] ", src);
}
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
#ifdef BIN_debug
#include <unistd.h>
int main()
{
int foo=1;
debug_init(5);
log(0, "log0=%d\n", foo++);
log(1, "log1=%d\n", foo++);
log(2, "log2=%d\n", foo++);
log_i(2, "log_i 2=%d\n", foo++);
log_i(5, "log_i 5=%d\n", foo++);
log_i(6, "log_i 6=%d\n", foo++);
log_it(4, "log_it 4=%d\n", foo++);
log_f(1, "log_f 5=%d\n", foo++);
}
#endif

173
2019/libsrc/plist.c Normal file
View File

@@ -0,0 +1,173 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* adapted from Linux kernel lib/plist.c
*
* Descending-priority-sorted double-linked list
*
* (C) 2002-2003 Intel Corp
* Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.
*
* 2001-2005 (c) MontaVista Software, Inc.
* Daniel Walker <dwalker@mvista.com>
*
* (C) 2005 Thomas Gleixner <tglx@linutronix.de>
*
* Simplifications of the original code by
* Oleg Nesterov <oleg@tv-sign.ru>
*
* Based on simple lists (include/linux/list.h).
*
* This file contains the add / del functions which are considered to
* be too large to inline. See include/linux/plist.h for further
* information.
*/
#include "plist.h"
#include "bug.h"
#ifdef DEBUG_PLIST
static struct plist_head test_head;
static void plist_check_prev_next(struct list_head *t, struct list_head *p,
struct list_head *n)
{
WARN(n->prev != p || p->next != n,
"top: %p, n: %p, p: %p\n"
"prev: %p, n: %p, p: %p\n"
"next: %p, n: %p, p: %p\n",
t, t->next, t->prev,
p, p->next, p->prev,
n, n->next, n->prev);
}
static void plist_check_list(struct list_head *top)
{
struct list_head *prev = top, *next = top->next;
plist_check_prev_next(top, prev, next);
while (next != top) {
prev = next;
next = prev->next;
plist_check_prev_next(top, prev, next);
}
}
static void plist_check_head(struct plist_head *head)
{
if (!plist_head_empty(head))
plist_check_list(&plist_first(head)->prio_list);
plist_check_list(&head->node_list);
}
#else
# define plist_check_head(h) do { } while (0)
#endif
/**
* plist_add - add @node to @head
*
* @node: &struct plist_node pointer
* @head: &struct plist_head pointer
*/
void plist_add(struct plist_node *node, struct plist_head *head)
{
struct plist_node *first, *iter, *prev = NULL;
struct list_head *node_next = &head->node_list;
plist_check_head(head);
WARN_ON(!plist_node_empty(node));
WARN_ON(!list_empty(&node->prio_list));
if (plist_head_empty(head))
goto ins_node;
first = iter = plist_first(head);
do {
if (node->prio < iter->prio) {
node_next = &iter->node_list;
break;
}
prev = iter;
iter = list_entry(iter->prio_list.next,
struct plist_node, prio_list);
} while (iter != first);
if (!prev || prev->prio != node->prio)
list_add_tail(&node->prio_list, &iter->prio_list);
ins_node:
list_add_tail(&node->node_list, node_next);
plist_check_head(head);
}
/**
* plist_del - Remove a @node from plist.
*
* @node: &struct plist_node pointer - entry to be removed
* @head: &struct plist_head pointer - list head
*/
void plist_del(struct plist_node *node, struct plist_head *head)
{
plist_check_head(head);
if (!list_empty(&node->prio_list)) {
if (node->node_list.next != &head->node_list) {
struct plist_node *next;
next = list_entry(node->node_list.next,
struct plist_node, node_list);
/* add the next plist_node into prio_list */
if (list_empty(&next->prio_list))
list_add(&next->prio_list, &node->prio_list);
}
list_del_init(&node->prio_list);
}
list_del_init(&node->node_list);
plist_check_head(head);
}
/**
* plist_requeue - Requeue @node at end of same-prio entries.
*
* This is essentially an optimized plist_del() followed by
* plist_add(). It moves an entry already in the plist to
* after any other same-priority entries.
*
* @node: &struct plist_node pointer - entry to be moved
* @head: &struct plist_head pointer - list head
*/
void plist_requeue(struct plist_node *node, struct plist_head *head)
{
struct plist_node *iter;
struct list_head *node_next = &head->node_list;
plist_check_head(head);
BUG_ON(plist_head_empty(head));
BUG_ON(plist_node_empty(node));
if (node == plist_last(head))
return;
iter = plist_next(node);
if (node->prio != iter->prio)
return;
plist_del(node, head);
plist_for_each_continue(iter, head) {
if (node->prio != iter->prio) {
node_next = &iter->node_list;
break;
}
}
list_add_tail(&node->node_list, node_next);
plist_check_head(head);
}

222
2019/libsrc/pool.c Normal file
View File

@@ -0,0 +1,222 @@
/* pool.c - A simple pool manager.
*
* 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>
*
*/
#include <stddef.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "list.h"
#include "pool.h"
#include "debug.h"
#include "bits.h"
void pool_stats(pool_t *pool)
{
if (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(5, "\tblocks: ");
list_for_each_entry(block, &pool->list_blocks, list_blocks) {
log(5, "%p ", block);
}
log(5, "\n");
}
}
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);
# 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",
name, eltsize, sizeof(struct list_head), sizeof(struct list_head));
# endif
eltsize = sizeof(struct list_head);
}
if ((pool = malloc(sizeof (*pool)))) {
strncpy(pool->name, name, POOL_NAME_LENGTH - 1);
pool->name[POOL_NAME_LENGTH - 1] = 0;
pool->growsize = growsize;
pool->eltsize = eltsize;
pool->available = 0;
pool->allocated = 0;
pool->nblocks = 0;
INIT_LIST_HEAD(&pool->list_available);
INIT_LIST_HEAD(&pool->list_blocks);
} else {
errno = ENOMEM;
}
return pool;
}
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,
offsetof(pool_t, list_available));
# endif
list_add(elt, &pool->list_available);
return ++pool->available;
}
u32 pool_add(pool_t *pool, void *elt)
{
return _pool_add(pool, elt);
}
static struct list_head *_pool_get(pool_t *pool)
{
struct list_head *res = pool->list_available.next;
pool->available--;
list_del(res);
return res;
}
void *pool_get(pool_t *pool)
{
if (!pool)
return NULL;
if (!pool->available) {
block_t *block = malloc(sizeof(block_t) + pool->eltsize * pool->growsize);
if (!block) {
# ifdef DEBUG_POOL
log_f(1, "[%s]: failed block allocation\n", pool->name);
# endif
errno = ENOMEM;
return NULL;
}
/* maintain list of allocated blocks
*/
list_add(&block->list_blocks, &pool->list_blocks);
pool->nblocks++;
# ifdef DEBUG_POOL
log_f(1, "[%s]: growing pool from %u to %u elements. block=%p nblocks=%u\n",
pool->name,
pool->allocated,
pool->allocated + pool->growsize,
block,
pool->nblocks);
# endif
pool->allocated += pool->growsize;
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);
}
}
/* this is the effective address of the object (and also the
* pool list_head address)
*/
return _pool_get(pool);
}
void pool_destroy(pool_t *pool)
{
block_t *block, *tmp;
if (!pool)
return;
/* release memory blocks */
# ifdef DEBUG_POOL
log_f(1, "[%s]: releasing %d blocks and main structure\n", pool->name, pool->nblocks);
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
}
# ifdef DEBUG_POOL
log(5, "\n");
# endif
free(pool);
}
#ifdef BIN_pool
struct d {
u16 data1;
char c;
struct list_head list;
};
static LIST_HEAD (head);
int main(int ac, char**av)
{
pool_t *pool;
int total;
int action=0;
u16 icur=0;
char ccur='z';
struct d *elt;
debug_init(3);
log_f(1, "%s: sizeof(d)=%lu sizeof(*d)=%lu off=%lu\n", *av, sizeof(elt),
sizeof(*elt), offsetof(struct d, list));
if ((pool = pool_create("dummy", 3, sizeof(*elt)))) {
pool_stats(pool);
for (int cur=1; cur<ac; ++cur) {
total = atoi(av[cur]);
if (action == 0) { /* add elt to list */
log_f(2, "adding %d elements\n", total);
for (int i = 0; i < total; ++i) {
elt = pool_get(pool);
elt->data1 = icur++;
elt->c = ccur--;
list_add(&elt->list, &head);
}
pool_stats(pool);
action = 1;
} else { /* remove one elt from list */
log_f(2, "deleting %d elements\n", total);
for (int i = 0; i < total; ++i) {
if (!list_empty(&head)) {
elt = list_last_entry(&head, struct d, list);
printf("elt=[%d, %c]\n", elt->data1, elt->c);
list_del(&elt->list);
pool_add(pool, elt);
}
}
pool_stats(pool);
action = 0;
}
}
}
pool_stats(pool);
pool_destroy(pool);
}
#endif

View File

@@ -1,25 +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??)
EXCLUDE := --exclude 'cob-01/'
CC = gcc
.PHONY: clean $(SUBDIRS)
#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 -C $$dir clean ; \
@for dir in $(SUBDIRS) ; do \
$(MAKE) --no-print-directory -C $$dir clean ; \
done
all: $(SUBDIRS)
cleanlib: clean
@$(RM) -f $(SLIB) $(DLIB) $(LIBOBJ)
cleanall: clean cleanlib
redo: cleanall all
$(SUBDIRS):
@echo "========================================="
@echo "================= $@ ================="
@echo "========================================="
@echo
@echo "+++++++++++++++++ ex1"
@$(MAKE) --no-print-directory -C $@ ex1 2>&1
@echo "+++++++++++++++++ ex2"
@$(MAKE) --no-print-directory -C $@ ex2 2>&1
@echo "+++++++++++++++++ part 1"
+@$(MAKE) --no-print-directory -C $@ ex1 2>&1
@echo "+++++++++++++++++ part 2"
+@$(MAKE) --no-print-directory -C $@ ex2 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 $@ $<

View File

@@ -256,21 +256,21 @@ ex2-c : size=99 res=113387824750592
+++++++++++++++++ ex1
ex1.bash : res=2386
time: 0:40.81 real, 40.25 user, 0.07 sys
context-switch: 6828+17, page-faults: 0+1317
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.03 real, 0.00 user, 0.00 sys
context-switch: 1+2, page-faults: 0+91
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+90
+++++++++++++++++ ex2
ex2.bash : res=2091
time: 1:19.37 real, 78.72 user, 0.08 sys
context-switch: 9445+14, page-faults: 0+1717
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.04 real, 0.02 user, 0.00 sys
context-switch: 2+2, page-faults: 0+91
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 6+1, page-faults: 0+90
=========================================
================= day12 =================
@@ -366,21 +366,21 @@ ex1-c : res[30000000]=548531
+++++++++++++++++ ex1
ex1.bash : res=21996
time: 0:00.23 real, 0.16 user, 0.03 sys
context-switch: 19+99, page-faults: 0+9381
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+71
context-switch: 0+1, page-faults: 0+76
+++++++++++++++++ ex2
ex2.bash : res=650080463519
time: 0:06.58 real, 6.54 user, 0.04 sys
context-switch: 662+95, page-faults: 0+10210
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+71
context-switch: 0+1, page-faults: 0+74
=========================================
================= day17 =================
@@ -439,15 +439,123 @@ 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 =================
=========================================
+++++++++++++++++ ex1
ex1.bash : res=5966506063747
time: 0:00.54 real, 0.53 user, 0.00 sys
context-switch: 1+1, page-faults: 0+223
time: 0:00.56 real, 0.56 user, 0.00 sys
context-switch: 4+1, page-faults: 0+224
+++++++++++++++++ ex2
ex2.bash res=1714
time: 0:02.14 real, 2.05 user, 0.02 sys
context-switch: 1146+1, page-faults: 0+605
=========================================
================= day21 =================
=========================================
+++++++++++++++++ ex1
ex1.bash: res=2211
time: 0:01.72 real, 1.71 user, 0.00 sys
context-switch: 9+1, page-faults: 0+1090
+++++++++++++++++ ex2
ex2.bash: res=vv,nlxsmb,rnbhjk,bvnkk,ttxvphb,qmkz,trmzkcfg,jpvz
time: 0:01.75 real, 1.74 user, 0.00 sys
context-switch: 36+4, page-faults: 0+1388
=========================================
================= day22 =================
=========================================
+++++++++++++++++ ex1
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 =================
=========================================
+++++++++++++++++ ex1
ex1.bash: res=75893264
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 0+1, page-faults: 0+166
aoc-c : res=75893264
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+83
+++++++++++++++++ ex2
ex2.bash: res=38162588308
time: 6:52.50 real, 412.30 user, 0.14 sys
context-switch: 2219+1, page-faults: 0+30233
aoc-c : res=38162588308
time: 0:01.33 real, 1.32 user, 0.01 sys
context-switch: 3+1, page-faults: 0+3992
=========================================
================= day24 =================
=========================================
+++++++++++++++++ ex1
ex1.bash: res=450
time: 0:00.17 real, 0.16 user, 0.00 sys
context-switch: 1+1, page-faults: 0+177
aoc-c : res=450
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+100
+++++++++++++++++ ex2
ex2.bash: res=4059
time: 0:22.35 real, 22.22 user, 0.07 sys
context-switch: 1102+1, page-faults: 0+858
aoc-c : res=4059
time: 0:00.04 real, 0.04 user, 0.00 sys
context-switch: 16+1, page-faults: 0+215
=========================================
================= day25 =================
=========================================
+++++++++++++++++ ex1
ex1.bash: res=9620012
time: 2:42.30 real, 162.05 user, 0.08 sys
context-switch: 3634+1, page-faults: 0+163
ex1-c : res=9620012
time: 0:00.08 real, 0.08 user, 0.00 sys
context-switch: 2+1, page-faults: 0+79

View File

@@ -28,7 +28,7 @@ ex2: ex2-c ex2-sort-cob ex2-pure-sort-cob
@$(TIME) ex2-c < $(INPUT)
clean:
@rm -f ex1-c ex2-c core ex2-galoisgirl-cob ex2-cob
@rm -f ex1-c ex2-c core ex*-cob
output:
$(MAKE) --no-print-directory all >OUTPUT 2>&1

View File

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

View File

@@ -2,7 +2,7 @@
#
# ex1.bash: Advent2020 game, day 1/game 1
CMD=$(basename "$0")
CMD=${0##*/}
readarray -t numbers

View File

@@ -2,7 +2,7 @@
#
# ex2-sort.bash: Advent2020 game, day 1/game 2, with sort.
CMD=$(basename "$0")
CMD=${0##*/}
readarray -t numbers <<< "$(sort -n)"

View File

@@ -2,7 +2,7 @@
#
# ex2.bash: Advent2020 game, day 1/game 2
CMD=$(basename "$0")
CMD=${0##*/}
readarray -t numbers

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,18 +0,0 @@
cc -w ex1-c.c -o ex1-c
ex1.bash : diff1=71 diff2=27 res=1917
time: 0:00.01 real, 0.00 user, 0.00 sys
context-switch: 1+4, page-faults: 0+331
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
cc -w ex2-c.c -o ex2-c
ex2.bash : size=99 res=113387824750592
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 2+4, page-faults: 0+329
ex2-c : size=99 res=113387824750592
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+73

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