2022 day 15 init

This commit is contained in:
2023-03-18 17:50:59 +01:00
parent 5fc204744a
commit 2ed6284bcd
9 changed files with 619 additions and 0 deletions

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

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

@@ -0,0 +1,139 @@
** --- 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?/

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

@@ -0,0 +1,194 @@
/* aoc-c.c: Advent of Code 2022, day 15
*
* 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 <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/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);
#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"
}

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

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

View File

@@ -0,0 +1,14 @@
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

View File

@@ -16,4 +16,5 @@
- `C`: All (days 1-25)
#### Advent of Code 2022
- `Bash`: All (days 1-12)
- `C`: All (days 1-14)