Compare commits

...

59 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
106 changed files with 13462 additions and 0 deletions

View File

@@ -129,3 +129,189 @@ aoc.bash: res=2260
aoc-c: res=2260 aoc-c: res=2260
time: 0:00.00 real, 0.00 user, 0.00 sys time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87 context-switch: 0+1, page-faults: 0+87
=========================================
================= day07 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=1390824
time: 0:00.05 real, 0.03 user, 0.01 sys
context-switch: 7+1, page-faults: 0+307
aoc-c: res=1390824
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+98
+++++++++++++++++ part 2
aoc.bash: res=7490863
time: 0:00.05 real, 0.05 user, 0.00 sys
context-switch: 9+1, page-faults: 0+308
aoc-c: res=7490863
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+98
=========================================
================= day08 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=1698
time: 0:01.10 real, 1.10 user, 0.00 sys
context-switch: 5+1, page-faults: 0+319
aoc-c: res=1698
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+92
+++++++++++++++++ part 2
aoc.bash: res=672280
time: 0:03.54 real, 3.53 user, 0.00 sys
context-switch: 48+1, page-faults: 0+284
aoc-c: res=672280
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+91
=========================================
================= day09 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=5619
time: 0:00.69 real, 0.69 user, 0.00 sys
context-switch: 38+1, page-faults: 0+430
aoc-c: res=5619
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+158
+++++++++++++++++ part 2
aoc.bash: res=2376
time: 0:03.25 real, 3.24 user, 0.00 sys
context-switch: 46+1, page-faults: 0+340
aoc-c: res=2376
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+131
=========================================
================= day10 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=13220
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+260
aoc-c: res=13220
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+88
+++++++++++++++++ part 2
aoc.bash: res=
###..#..#..##..#..#.#..#.###..####.#..##
#..#.#..#.#..#.#.#..#..#.#..#.#....#.#..
#..#.#..#.#..#.##...####.###..###..##..#
###..#..#.####.#.#..#..#.#..#.#....#.#.#
#.#..#..#.#..#.#.#..#..#.#..#.#....#.#..
#..#..##..#..#.#..#.#..#.###..####.#..#.
time: 0:00.01 real, 0.00 user, 0.00 sys
context-switch: 3+1, page-faults: 0+262
###..#..#..##..#..#.#..#.###..####.#..##
#..#.#..#.#..#.#.#..#..#.#..#.#....#.#..
#..#.#..#.#..#.##...####.###..###..##..#
###..#..#.####.#.#..#..#.#..#.#....#.#.#
#.#..#..#.#..#.#.#..#..#.#..#.#....#.#..
#..#..##..#..#.#..#.#..#.###..####.#..#.
aoc-c: res=0
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+88
=========================================
================= day11 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=54253
time: 0:00.05 real, 0.04 user, 0.00 sys
context-switch: 1+1, page-faults: 0+268
aoc-c: res=54253
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+87
+++++++++++++++++ part 2
aoc.bash: res=13119526120
time: 0:16.49 real, 16.48 user, 0.00 sys
context-switch: 106+1, page-faults: 0+270
aoc-c: res=13119526120
time: 0:00.01 real, 0.01 user, 0.00 sys
context-switch: 13+1, page-faults: 0+87
=========================================
================= day12 =================
=========================================
+++++++++++++++++ part 1
aoc.bash: res=408
time: 0:00.81 real, 0.80 user, 0.00 sys
context-switch: 223+1, page-faults: 0+486
aoc-c: res=408
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+170
+++++++++++++++++ part 2
aoc.bash: res=399
time: 0:00.55 real, 0.54 user, 0.01 sys
context-switch: 25+1, page-faults: 0+460
aoc-c: res=399
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+171
=========================================
================= day13 =================
=========================================
+++++++++++++++++ part 1
aoc-c: res=5843
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+192
+++++++++++++++++ part 2
aoc-c: res=26289
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 1+1, page-faults: 0+190
=========================================
================= day14 =================
=========================================
+++++++++++++++++ part 1
aoc-c: res=665
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+109
+++++++++++++++++ part 2
aoc-c: res=25434
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+121
=========================================
================= day15 =================
=========================================
+++++++++++++++++ part 1
aoc-c: res=5176944
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+152
+++++++++++++++++ part 2
aoc-c: res=13350458933732
time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 0+1, page-faults: 0+88

111
2022/day07/Makefile Normal file
View File

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

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

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

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

@@ -0,0 +1,194 @@
/* aoc-c.c: Advent of Code 2022, day 7
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "pool.h"
#include "debug.h"
#include "br.h"
#include "aoc.h"
#include "hashtable.h"
#include "pjwhash-inline.h"
/* we will totally ignore the tree structure here and only keep a hashtable
* to keep directories sizes.
*/
#define HBITS 9 /* 9 bits: size is 512 */
#define DIRNAME_SIZE 128
DEFINE_HASHTABLE(hasht_dir, HBITS);
typedef struct dir {
char name[DIRNAME_SIZE];
uint namelen;
uint hash;
int size;
struct hlist_node hlist;
} dir_t;
static pool_t *pool_dirs;
/**
* find_dir - find entry in an hashtable bucket
*/
static dir_t *find_dir(struct hlist_head *head, uint hash, char *dir, uint len)
{
dir_t *cur;
hlist_for_each_entry(cur, head, hlist)
if (cur->hash == hash && cur->namelen == len && !memcmp(cur->name, dir, len))
return cur;
return NULL;
}
static dir_t *find_dirname(char *name, uint len)
{
uint hash = pjwhash(name, len);
uint bucket = hash_32(hash, HBITS);
return find_dir(&hasht_dir[bucket], hash, name, len);
}
/**
* parent_dir - get new len of parent directory
*/
static int parent_dir(char *dir, uint len)
{
for (--len; len && *(dir + len) != '/'; --len)
;
return len? len: 1;
}
static void adjust_dirsize(dir_t *dir, uint size)
{
dir_t *cur = dir;
uint len = cur->namelen;
while (len > 1) {
cur = find_dirname(dir->name, len);
if (!cur) {
log(1, "FATAL hash issue");
exit(1);
}
cur->size +=size;
len = parent_dir(dir->name, len);
};
cur = find_dirname("/", 1); /* do not forget "/" */
cur->size += size;
}
/**
* add_dir - add an entry in hashtable
*/
static struct dir *add_dir(char *dir, uint len)
{
uint hash = pjwhash(dir, len);
uint bucket = hash_32(hash, HBITS);
dir_t *new = pool_get(pool_dirs);
memcpy(new->name, dir, len);
new->namelen = len;
new->hash = hash;
new->size = 0;
hlist_add_head(&new->hlist, &hasht_dir[bucket]);
return new;
}
/**
* add_dir_maybe - add an entry in hashtable if it does not exist
*/
static struct dir *add_dir_maybe(char *dir, int len)
{
dir_t *new = find_dirname(dir, len);
return new? new: add_dir(dir, len);
}
static struct dir *cd(struct dir *dir, char *to, uint tolen)
{
char *newname = dir->name;
int newlen, add_slash = 0;
if (!dir)
return add_dir_maybe(to, tolen);
if (dir->namelen + tolen + 1 > DIRNAME_SIZE) /* conservative (think / or ..) */
return NULL;
if (*to == '.') { /* .. = parent dir */
newlen = parent_dir(dir->name, dir->namelen);
} else if (*to == '/') { /* root */
newname = to;
newlen = tolen;
} else { /* subdir */
newlen = dir->namelen + tolen;
if (dir->namelen > 1) { /* add '/' separator */
dir->name[dir->namelen] = '/';
add_slash = 1;
newlen++;
}
memcpy(dir->name + dir->namelen + add_slash, to, tolen);
}
return add_dir_maybe(newname, newlen);
}
#define CDLEN (sizeof("$ cd ") - 1)
static void parse()
{
dir_t *curdir = NULL;
size_t alloc = 0;
char *buf = NULL, *tok;
ssize_t buflen;
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
buf[--buflen] = 0;
tok = buf;
if (*tok == '$' &&*(tok+2) == 'c') /* ignore "ls"" */
curdir = cd(curdir, tok + CDLEN, buflen - CDLEN);
else if (isdigit(*tok)) /* ignore "dir" keyword */
adjust_dirsize(curdir, atoi(tok));
}
free(buf);
return;
}
static int solve(int part)
{
ulong bucket;
dir_t *cur;
int res = 0, needed;
if (part == 1) {
hash_for_each(hasht_dir, bucket, cur, hlist)
if (cur->size <= 100000)
res += cur->size;
} else {
res = find_dirname("/", 1)->size;
needed = res - (70000000-30000000);
hash_for_each(hasht_dir, bucket, cur, hlist)
if (cur->size >= needed && cur->size < res)
res = cur->size;
}
return res;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
pool_dirs = pool_create("dirs", 128, sizeof(dir_t));
parse();
printf("%s: res=%d\n", *av, solve(part));
pool_destroy(pool_dirs);
exit(0);
}

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

@@ -0,0 +1,102 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 7
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
. common.bash
declare -A sizes=() # file size
declare -A dirs=() # directories
declare -a lines # shell lines
declare -i curline=0 # current line in shell
declare curdir
do_cd() {
local dir="$1"
case "$dir" in
"..")
curdir=${curdir%/*}
[[ -z $curdir ]] && curdir="/"
;;
"/")
curdir="/"
;;
*)
[[ $curdir != "/" ]] && curdir+="/"
curdir+="$dir"
esac
dirs[$curdir]="$curdir"
}
do_ls() {
local remain
local -i size
((curline++))
while [[ $curline -lt ${#lines[@]} && ${lines[$curline]:0:1} != "\$" ]]; do
if [[ "${lines[$curline]}" != dir* ]]; then
size=${lines[$curline]% *}
remain="$curdir"
while [[ -n $remain ]]; do # recurse up curdir and adjust sizes
((sizes[$remain] += size))
remain=${remain%/*}
done
(( sizes["/"] += size ))
fi
((curline++))
done
((curline--))
}
parse() {
readarray -t lines
curline=0
declare -a line
while ((curline < ${#lines[@]})); do
read -ra line <<< "${lines[$curline]}"
case "${line[1]}" in
"cd")
do_cd "${line[2]}"
;;
"ls")
do_ls
;;
esac
((curline++))
done
}
solve() {
declare -ig res
local part="$1" dir mindir="/"
local -i needed
if ((part == 1)); then
for dir in "${dirs[@]}"; do
((sizes[$dir] <= 100000 )) && ((res+=sizes[$dir]))
done
else
(( res = sizes["/"] ))
(( needed = sizes["/"] - (70000000-30000000) ))
for dir in "${!dirs[@]}"; do
if (( sizes[$dir] >= needed )); then
if (( sizes[$dir] <= res )); then
mindir=$dir
((res = sizes[$mindir]))
fi
fi
done
fi
}
main "$@"
exit 0

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

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

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

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

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

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

View File

@@ -0,0 +1,23 @@
$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k

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

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

111
2022/day08/Makefile Normal file
View File

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

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

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

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

@@ -0,0 +1,159 @@
/* aoc-c.c: Advent of Code 2022, day 8
*
* Copyright (C) 2022 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bits.h"
#include "aoc.h"
typedef struct tree {
u16 size;
char *h; /* heigts */
char *v; /* visible (part 1) */
} tree_t;
#define HEIGHT(t, x, y) (((t)->h[((t)->size * (y)) + (x)]))
#define VISIBLE(t, x, y) (((t)->v[((t)->size * (y)) + (x)]))
static tree_t *parse(tree_t *trees)
{
size_t alloc = 0;
char *buf = NULL;
ssize_t buflen;
buflen = getline(&buf, &alloc, stdin);
buf[--buflen] = 0;
trees->size = buflen;
trees->h = malloc((buflen * buflen) * sizeof(char) + 1);
memcpy(trees->h, buf, buflen); /* store first line */
free(buf);
for (buf = trees->h + buflen; ; buf += buflen) {
if (scanf("%s", buf) <= 0)
break;
}
trees->v = calloc(buflen * buflen, sizeof (char));
return trees;
}
static int visible(tree_t *t, int *max, int x, int y)
{
int h = HEIGHT(t, x, y);
if (h > *max) {
VISIBLE(t, x, y) = 1;
if ((*max = h) == '9') {
return 1;
}
}
return 0;
}
static int check_tree(tree_t *t, int x, int y)
{
int i, h = HEIGHT(t, x, y), res = 1, size = t->size, tmp;
for (tmp = 0, i = x + 1; i < size ; ++i) { /* east */
tmp++;
if (HEIGHT(t, i, y) >= h)
break;
}
res *= tmp;
for (tmp = 0, i = x - 1; i >= 0; --i) { /* west */
tmp++;
if (HEIGHT(t, i, y) >= h)
break;
}
res *= tmp;
for (tmp = 0, i = y + 1; i < size; ++i) { /* south */
tmp++;
if (HEIGHT(t, x, i) >= h)
break;
}
res *= tmp;
for (tmp = 0, i = y - 1; i >= 0; --i) { /* north */
tmp++;
if (HEIGHT(t, x, i) >= h)
break;
}
res *= tmp;
return res;
}
static int part1(tree_t *t)
{
int x, y, max, res = 0, size = t->size;
for (y = 1; y < size -1; ++y) { /* to east */
if ((max = HEIGHT(t, 0, y)) < '9') {
for (x = 1; x < size -1; ++x) {
if (visible (t, &max, x, y))
break;
}
}
}
for (y = 1; y < size -1; ++y) { /* to west */
if ((max = HEIGHT(t, size - 1, y)) < '9') {
for (x = size - 2; x > 0; --x) {
if (visible (t, &max, x, y)) {
break;
}
}
}
}
for (x = 1; x < size -1; ++x) { /* to south */
if ((max = HEIGHT(t, x, 0)) < '9') {
for (y = 1; y < size -1; ++y) {
if (visible (t, &max, x, y))
break;
}
}
}
for (x = 1; x < size -1; ++x) { /* to north */
if ((max = HEIGHT(t, x, size - 1)) < '9') {
for (y = size - 2; y > 0; --y) {
if (visible (t, &max, x, y))
break;
}
}
}
for (y = 0; y < size; ++y)
for (x = 0; x < size; ++x)
if (VISIBLE(t, x, y))
res++;
return res + size * 4 - 4;
}
static int part2(tree_t *t)
{
int res = 0, tmp, size = t->size;
for (int y = 1; y < size - 1; ++y) {
for (int x = 1; x < size - 1; ++x) {
tmp = check_tree(t, x, y);
if (tmp > res)
res = tmp;
}
}
return res;
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
tree_t trees;
parse(&trees);
printf("%s: res=%d\n", *av, part == 1? part1(&trees): part2(&trees));
exit(0);
}

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

@@ -0,0 +1,135 @@
#!/usr/bin/env bash
#
# aoc.bash: Advent of Code 2022, day 8
#
# Copyright (C) 2022 Bruno Raoult ("br")
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
. common.bash
declare -a trees=() # trees height
declare -Ai visible=() # visible if set
declare -i size
parse() {
readarray -t trees
size=${#trees[@]}
}
# height - return height of a tree
# $1: reference of return value
# $2, $3: x, y
# x is column, y is row
height() {
local -n _ret="$1"
_ret=${trees[$3]:$2:1}
}
check_visible() {
local -n _max="$1"
local -i _x="$2" _y="$3" _c
height _c "$x" "y"
if (( _c > _max )); then
(( visible[$x-$y]++, _max=_c ))
(( _max == 9 )) && return 1
fi
return 0
}
part1() {
declare -ig res
local -i x y max
for ((y = 1; y < size -1; ++y)); do # to east
height max 0 "$y"
(( max == 9 )) && continue
for ((x = 1; x < size -1; ++x)); do
check_visible max "$x" "$y" || break
done
done
for ((y = 1; y < size -1; ++y)); do # to west
height max $((size - 1)) "$y"
(( max == 9 )) && continue
for ((x = size - 2; x > 0; --x)); do
check_visible max "$x" "$y" || break
done
done
for ((x = 1; x < size -1; ++x)); do # to south
height max "$x" 0
(( max == 9 )) && continue
for ((y = 1; y < size -1; ++y)); do
check_visible max "$x" "$y" || break
done
done
for ((x = 1; x < size -1; ++x)); do # to north
height max "$x" $((size - 1))
(( max == 9 )) && continue
for ((y = size - 2; y > 0; --y)); do
check_visible max "$x" "$y" || break
done
done
(( res = ${#visible[@]} + size * 4 - 4 ))
}
check_tree() {
local -n res=$1
local -i X="$2" Y="$3" c x y h
local -ai vis=()
height h "$X" "$Y"
for ((x = X + 1; x < size ; ++x)); do # east
height c "$x" "Y"
(( vis[0]++ ))
((c >= h)) && break
done
for ((x = X - 1; x >= 0; --x)); do # west
height c "$x" "Y"
(( vis[1]++ ))
((c >= h)) && break
done
for ((y = Y + 1; y < size; ++y)); do # south
height c "$X" "$y"
(( vis[2]++ ))
((c >= h)) && break
done
for ((y = Y - 1; y >= 0; --y)); do # north
height c "$X" "$y"
(( vis[3]++ ))
((c >= h)) && break
done
# shellcheck disable=1102
res=$(( "${vis[@]/%/ *}" 1))
}
part2() {
local -ig res=0
local -i tmp=1 x y
for ((x = 1; x < size - 1; ++x)); do
for ((y = 1; y < size - 1; ++y)); do
check_tree tmp "$x" "$y"
if ((tmp > res)); then
((res = tmp))
fi
done
done
}
solve() {
if ((part == 1)); then
part1
else
part2
fi
}
main "$@"
exit 0

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

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

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

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

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

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

View File

@@ -0,0 +1,5 @@
30373
25512
65332
33549
35390

View File

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

111
2022/day09/Makefile Normal file
View File

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

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

@@ -0,0 +1,747 @@
** --- Day 9: Rope Bridge ---
This rope bridge creaks as you walk along it. You aren't sure how old it
is, or whether it can even support your weight.
It seems to support the Elves just fine, though. The bridge spans a
gorge which was carved out by the massive river far below you.
You step carefully; as you do, the ropes stretch and twist. You decide
to distract yourself by modeling rope physics; maybe you can even figure
out where /not/ to step.
Consider a rope with a knot at each end; these knots mark the /head/ and
the /tail/ of the rope. If the head moves far enough away from the tail,
the tail is pulled toward the head.
Due to nebulous reasoning involving
[[https://en.wikipedia.org/wiki/Planck_units#Planck_length][Planck
lengths]], you should be able to model the positions of the knots on a
two-dimensional grid. Then, by following a hypothetical /series of
motions/ (your puzzle input) for the head, you can determine how the
tail will move.
Due to the aforementioned Planck lengths, the rope must be quite short;
in fact, the head (=H=) and tail (=T=) must /always be touching/
(diagonally adjacent and even overlapping both count as touching):
#+begin_example
....
.TH.
....
....
.H..
..T.
....
...
.H. (H covers T)
...
#+end_example
If the head is ever two steps directly up, down, left, or right from the
tail, the tail must also move one step in that direction so it remains
close enough:
#+begin_example
..... ..... .....
.TH.. -> .T.H. -> ..TH.
..... ..... .....
... ... ...
.T. .T. ...
.H. -> ... -> .T.
... .H. .H.
... ... ...
#+end_example
Otherwise, if the head and tail aren't touching and aren't in the same
row or column, the tail always moves one step diagonally to keep up:
#+begin_example
..... ..... .....
..... ..H.. ..H..
..H.. -> ..... -> ..T..
.T... .T... .....
..... ..... .....
..... ..... .....
..... ..... .....
..H.. -> ...H. -> ..TH.
.T... .T... .....
..... ..... .....
#+end_example
You just need to work out where the tail goes as the head follows a
series of motions. Assume the head and the tail both start at the same
position, overlapping.
For example:
#+begin_example
R 4
U 4
L 3
D 1
R 4
D 1
L 5
R 2
#+end_example
This series of motions moves the head /right/ four steps, then /up/ four
steps, then /left/ three steps, then /down/ one step, and so on. After
each step, you'll need to update the position of the tail if the step
means the head is no longer adjacent to the tail. Visually, these
motions occur as follows (=s= marks the starting position as a reference
point):
#+begin_example
== Initial State ==
......
......
......
......
H..... (H covers T, s)
== R 4 ==
......
......
......
......
TH.... (T covers s)
......
......
......
......
sTH...
......
......
......
......
s.TH..
......
......
......
......
s..TH.
== U 4 ==
......
......
......
....H.
s..T..
......
......
....H.
....T.
s.....
......
....H.
....T.
......
s.....
....H.
....T.
......
......
s.....
== L 3 ==
...H..
....T.
......
......
s.....
..HT..
......
......
......
s.....
.HT...
......
......
......
s.....
== D 1 ==
..T...
.H....
......
......
s.....
== R 4 ==
..T...
..H...
......
......
s.....
..T...
...H..
......
......
s.....
......
...TH.
......
......
s.....
......
....TH
......
......
s.....
== D 1 ==
......
....T.
.....H
......
s.....
== L 5 ==
......
....T.
....H.
......
s.....
......
....T.
...H..
......
s.....
......
......
..HT..
......
s.....
......
......
.HT...
......
s.....
......
......
HT....
......
s.....
== R 2 ==
......
......
.H.... (H covers T)
......
s.....
......
......
.TH...
......
s.....
#+end_example
After simulating the rope, you can count up all of the positions the
/tail visited at least once/. In this diagram, =s= again marks the
starting position (which the tail also visited) and =#= marks other
positions the tail visited:
#+begin_example
..##..
...##.
.####.
....#.
s###..
#+end_example
So, there are =13= positions the tail visited at least once.
Simulate your complete hypothetical series of motions. /How many
positions does the tail of the rope visit at least once?/
Your puzzle answer was =5619=.
** --- Part Two ---
A rope snaps! Suddenly, the river is getting a lot closer than you
remember. The bridge is still there, but some of the ropes that broke
are now whipping toward you as you fall through the air!
The ropes are moving too quickly to grab; you only have a few seconds to
choose how to arch your body to avoid being hit. Fortunately, your
simulation can be extended to support longer ropes.
Rather than two knots, you now must simulate a rope consisting of /ten/
knots. One knot is still the head of the rope and moves according to the
series of motions. Each knot further down the rope follows the knot in
front of it using the same rules as before.
Using the same series of motions as the above example, but with the
knots marked =H=, =1=, =2=, ..., =9=, the motions now occur as follows:
#+begin_example
== Initial State ==
......
......
......
......
H..... (H covers 1, 2, 3, 4, 5, 6, 7, 8, 9, s)
== R 4 ==
......
......
......
......
1H.... (1 covers 2, 3, 4, 5, 6, 7, 8, 9, s)
......
......
......
......
21H... (2 covers 3, 4, 5, 6, 7, 8, 9, s)
......
......
......
......
321H.. (3 covers 4, 5, 6, 7, 8, 9, s)
......
......
......
......
4321H. (4 covers 5, 6, 7, 8, 9, s)
== U 4 ==
......
......
......
....H.
4321.. (4 covers 5, 6, 7, 8, 9, s)
......
......
....H.
.4321.
5..... (5 covers 6, 7, 8, 9, s)
......
....H.
....1.
.432..
5..... (5 covers 6, 7, 8, 9, s)
....H.
....1.
..432.
.5....
6..... (6 covers 7, 8, 9, s)
== L 3 ==
...H..
....1.
..432.
.5....
6..... (6 covers 7, 8, 9, s)
..H1..
...2..
..43..
.5....
6..... (6 covers 7, 8, 9, s)
.H1...
...2..
..43..
.5....
6..... (6 covers 7, 8, 9, s)
== D 1 ==
..1...
.H.2..
..43..
.5....
6..... (6 covers 7, 8, 9, s)
== R 4 ==
..1...
..H2..
..43..
.5....
6..... (6 covers 7, 8, 9, s)
..1...
...H.. (H covers 2)
..43..
.5....
6..... (6 covers 7, 8, 9, s)
......
...1H. (1 covers 2)
..43..
.5....
6..... (6 covers 7, 8, 9, s)
......
...21H
..43..
.5....
6..... (6 covers 7, 8, 9, s)
== D 1 ==
......
...21.
..43.H
.5....
6..... (6 covers 7, 8, 9, s)
== L 5 ==
......
...21.
..43H.
.5....
6..... (6 covers 7, 8, 9, s)
......
...21.
..4H.. (H covers 3)
.5....
6..... (6 covers 7, 8, 9, s)
......
...2..
..H1.. (H covers 4; 1 covers 3)
.5....
6..... (6 covers 7, 8, 9, s)
......
...2..
.H13.. (1 covers 4)
.5....
6..... (6 covers 7, 8, 9, s)
......
......
H123.. (2 covers 4)
.5....
6..... (6 covers 7, 8, 9, s)
== R 2 ==
......
......
.H23.. (H covers 1; 2 covers 4)
.5....
6..... (6 covers 7, 8, 9, s)
......
......
.1H3.. (H covers 2, 4)
.5....
6..... (6 covers 7, 8, 9, s)
#+end_example
Now, you need to keep track of the positions the new tail, =9=, visits.
In this example, the tail never moves, and so it only visits =1=
position. However, /be careful/: more types of motion are possible than
before, so you might want to visually compare your simulated rope to the
one above.
Here's a larger example:
#+begin_example
R 5
U 8
L 8
D 3
R 17
D 10
L 25
U 20
#+end_example
These motions occur as follows (individual steps are not shown):
#+begin_example
== Initial State ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
...........H.............. (H covers 1, 2, 3, 4, 5, 6, 7, 8, 9, s)
..........................
..........................
..........................
..........................
..........................
== R 5 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
...........54321H......... (5 covers 6, 7, 8, 9, s)
..........................
..........................
..........................
..........................
..........................
== U 8 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
................H.........
................1.........
................2.........
................3.........
...............54.........
..............6...........
.............7............
............8.............
...........9.............. (9 covers s)
..........................
..........................
..........................
..........................
..........................
== L 8 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
........H1234.............
............5.............
............6.............
............7.............
............8.............
............9.............
..........................
..........................
...........s..............
..........................
..........................
..........................
..........................
..........................
== D 3 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
.........2345.............
........1...6.............
........H...7.............
............8.............
............9.............
..........................
..........................
...........s..............
..........................
..........................
..........................
..........................
..........................
== R 17 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
................987654321H
..........................
..........................
..........................
..........................
...........s..............
..........................
..........................
..........................
..........................
..........................
== D 10 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
...........s.........98765
.........................4
.........................3
.........................2
.........................1
.........................H
== L 25 ==
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
...........s..............
..........................
..........................
..........................
..........................
H123456789................
== U 20 ==
H.........................
1.........................
2.........................
3.........................
4.........................
5.........................
6.........................
7.........................
8.........................
9.........................
..........................
..........................
..........................
..........................
..........................
...........s..............
..........................
..........................
..........................
..........................
..........................
#+end_example
Now, the tail (=9=) visits =36= positions (including =s=) at least once:
#+begin_example
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
#.........................
#.............###.........
#............#...#........
.#..........#.....#.......
..#..........#.....#......
...#........#.......#.....
....#......s.........#....
.....#..............#.....
......#............#......
.......#..........#.......
........#........#........
.........########.........
#+end_example
Simulate your complete series of motions on a larger rope with ten
knots. /How many positions does the tail of the rope visit at least
once?/
Your puzzle answer was =2376=.
Both parts of this puzzle are complete! They provide two gold stars: **

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

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

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

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

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

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

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

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

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

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

View File

@@ -0,0 +1,8 @@
R 4
U 4
L 3
D 1
R 4
D 1
L 5
R 2

View File

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

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

File diff suppressed because it is too large Load Diff

111
2022/day10/Makefile Normal file
View File

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

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

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

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

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

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

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

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

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

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

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

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

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

View File

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

View File

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

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

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

111
2022/day11/Makefile Normal file
View File

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

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

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

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

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

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

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

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

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

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

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

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

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

View File

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

View File

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

114
2022/day12/Makefile Normal file
View File

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

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

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

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

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

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

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

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

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

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

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

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

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

View File

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

View File

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

111
2022/day13/Makefile Normal file
View File

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

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

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

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

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

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

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

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

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

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

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

View File

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

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

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

111
2022/day14/Makefile Normal file
View File

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

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

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

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

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

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

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

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

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

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

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

View File

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

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

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

111
2022/day15/Makefile Normal file
View File

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

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

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

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

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

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

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

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

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

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

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

View File

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

View File

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

111
2022/day16/Makefile Normal file
View File

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

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

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

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

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

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

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

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

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

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

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

View File

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

View File

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

111
2022/day17/Makefile Normal file
View File

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

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

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

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

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

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

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

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

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

View File

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

File diff suppressed because one or more lines are too long

View File

@@ -44,11 +44,30 @@ typedef uint8_t u8;
/* convenience types /* convenience types
*/ */
typedef long long int llong;
typedef unsigned long long int ullong;
typedef unsigned long int ulong; typedef unsigned long int ulong;
typedef unsigned int uint; typedef unsigned int uint;
typedef unsigned short ushort; typedef unsigned short ushort;
typedef unsigned char uchar; typedef unsigned char uchar;
/* define common types sizes
*/
#define BITS_PER_CHAR 8
#ifndef BITS_PER_SHORT
#define BITS_PER_SHORT (BITS_PER_CHAR * sizeof (short))
#endif
#ifndef BITS_PER_INT
#define BITS_PER_INT (BITS_PER_CHAR * sizeof (int))
#endif
#ifndef BITS_PER_LONG
#define BITS_PER_LONG (BITS_PER_CHAR * sizeof (long))
#endif
#ifndef BITS_PER_LLONG
#define BITS_PER_LLONG (BITS_PER_CHAR * sizeof (long long))
#endif
/* count set bits: 10101000 -> 3 /* count set bits: 10101000 -> 3
* ^ ^ ^ * ^ ^ ^
*/ */

View File

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

View File

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

View File

@@ -0,0 +1,53 @@
/* pjwhash-inline.h - PJW hash function, inline version.
*
* 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 _PJWHASH_INLINE_H
#define _PJWHASH_INLINE_H
#include "bits.h"
#define THREE_QUARTERS ((int) ((BITS_PER_INT * 3) / 4))
#define ONE_EIGHTH ((int) (BITS_PER_INT / 8))
#define HIGH_BITS ( ~((uint)(~0) >> ONE_EIGHTH ))
#ifndef _pjw_inline
#define _pjw_inline static inline
#endif
/**
* unsigned int pjwhash - PJW hash function
* @key: the key address.
* @length: the length of key.
*
* This hash was created by Peter Jay Weinberger (AT&T Bell Labs):
* https://en.wikipedia.org/wiki/PJW_hash_function
*
* Return: the PJW hash.
*/
_pjw_inline uint pjwhash(const void* key, uint length)
{
uint hash = 0, high;
const u8 *k = key;
for (uint i = 0; i < length; ++k, ++i) {
hash = (hash << ONE_EIGHTH) + *k;
high = hash & HIGH_BITS;
if (high != 0) {
hash ^= high >> THREE_QUARTERS;
hash &= ~high;
}
}
return hash;
}
#endif /* _PJWHASH_INLINE_H */

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