From d0376f21c3b46df6180223e13f66ccfcfd0e862b Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Sat, 24 Dec 2022 21:06:10 +0100 Subject: [PATCH] 2022 day 12 (C, parts 1 & 2) --- 2022/RESULTS.txt | 12 +++- 2022/day12/aoc-c.c | 172 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 2022/day12/aoc-c.c diff --git a/2022/RESULTS.txt b/2022/RESULTS.txt index 6a936ab..99ea4db 100644 --- a/2022/RESULTS.txt +++ b/2022/RESULTS.txt @@ -261,7 +261,15 @@ 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.57 real, 0.56 user, 0.00 sys - context-switch: 35+1, page-faults: 0+459 + 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 diff --git a/2022/day12/aoc-c.c b/2022/day12/aoc-c.c new file mode 100644 index 0000000..9c5bd5a --- /dev/null +++ b/2022/day12/aoc-c.c @@ -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 . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include +#include +#include + +#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); +}