day 15 part 1
This commit is contained in:
@@ -33,3 +33,130 @@ Your goal is to find a path with the lowest total risk. In this example, a path
|
||||
The total risk of this path is 40 (the starting position is never entered, so its risk is not counted).
|
||||
|
||||
What is the lowest total risk of any path from the top left to the bottom right?
|
||||
|
||||
Your puzzle answer was 435.
|
||||
|
||||
The first half of this puzzle is complete! It provides one gold star: *
|
||||
--- Part Two ---
|
||||
|
||||
Now that you know how to find low-risk paths in the cave, you can try to find your way out.
|
||||
|
||||
The entire cave is actually five times larger in both dimensions than you thought; the area you originally scanned is just one tile in a 5x5 tile area that forms the full map. Your original map tile repeats to the right and downward; each time the tile repeats to the right or downward, all of its risk levels are 1 higher than the tile immediately up or left of it. However, risk levels above 9 wrap back around to 1. So, if your original map had some position with a risk level of 8, then that same position on each of the 25 total tiles would be as follows:
|
||||
|
||||
8 9 1 2 3
|
||||
9 1 2 3 4
|
||||
1 2 3 4 5
|
||||
2 3 4 5 6
|
||||
3 4 5 6 7
|
||||
|
||||
Each single digit above corresponds to the example position with a value of 8 on the top-left tile. Because the full map is actually five times larger in both dimensions, that position appears a total of 25 times, once in each duplicated tile, with the values shown above.
|
||||
|
||||
Here is the full five-times-as-large version of the first example above, with the original map in the top left corner highlighted:
|
||||
|
||||
11637517422274862853338597396444961841755517295286
|
||||
13813736722492484783351359589446246169155735727126
|
||||
21365113283247622439435873354154698446526571955763
|
||||
36949315694715142671582625378269373648937148475914
|
||||
74634171118574528222968563933317967414442817852555
|
||||
13191281372421239248353234135946434524615754563572
|
||||
13599124212461123532357223464346833457545794456865
|
||||
31254216394236532741534764385264587549637569865174
|
||||
12931385212314249632342535174345364628545647573965
|
||||
23119445813422155692453326671356443778246755488935
|
||||
22748628533385973964449618417555172952866628316397
|
||||
24924847833513595894462461691557357271266846838237
|
||||
32476224394358733541546984465265719557637682166874
|
||||
47151426715826253782693736489371484759148259586125
|
||||
85745282229685639333179674144428178525553928963666
|
||||
24212392483532341359464345246157545635726865674683
|
||||
24611235323572234643468334575457944568656815567976
|
||||
42365327415347643852645875496375698651748671976285
|
||||
23142496323425351743453646285456475739656758684176
|
||||
34221556924533266713564437782467554889357866599146
|
||||
33859739644496184175551729528666283163977739427418
|
||||
35135958944624616915573572712668468382377957949348
|
||||
43587335415469844652657195576376821668748793277985
|
||||
58262537826937364893714847591482595861259361697236
|
||||
96856393331796741444281785255539289636664139174777
|
||||
35323413594643452461575456357268656746837976785794
|
||||
35722346434683345754579445686568155679767926678187
|
||||
53476438526458754963756986517486719762859782187396
|
||||
34253517434536462854564757396567586841767869795287
|
||||
45332667135644377824675548893578665991468977611257
|
||||
44961841755517295286662831639777394274188841538529
|
||||
46246169155735727126684683823779579493488168151459
|
||||
54698446526571955763768216687487932779859814388196
|
||||
69373648937148475914825958612593616972361472718347
|
||||
17967414442817852555392896366641391747775241285888
|
||||
46434524615754563572686567468379767857948187896815
|
||||
46833457545794456865681556797679266781878137789298
|
||||
64587549637569865174867197628597821873961893298417
|
||||
45364628545647573965675868417678697952878971816398
|
||||
56443778246755488935786659914689776112579188722368
|
||||
55172952866628316397773942741888415385299952649631
|
||||
57357271266846838237795794934881681514599279262561
|
||||
65719557637682166874879327798598143881961925499217
|
||||
71484759148259586125936169723614727183472583829458
|
||||
28178525553928963666413917477752412858886352396999
|
||||
57545635726865674683797678579481878968159298917926
|
||||
57944568656815567976792667818781377892989248891319
|
||||
75698651748671976285978218739618932984172914319528
|
||||
56475739656758684176786979528789718163989182927419
|
||||
67554889357866599146897761125791887223681299833479
|
||||
|
||||
Equipped with the full map, you can now find a path from the top left corner to the bottom right corner with the lowest total risk:
|
||||
|
||||
11637517422274862853338597396444961841755517295286
|
||||
13813736722492484783351359589446246169155735727126
|
||||
21365113283247622439435873354154698446526571955763
|
||||
36949315694715142671582625378269373648937148475914
|
||||
74634171118574528222968563933317967414442817852555
|
||||
13191281372421239248353234135946434524615754563572
|
||||
13599124212461123532357223464346833457545794456865
|
||||
31254216394236532741534764385264587549637569865174
|
||||
12931385212314249632342535174345364628545647573965
|
||||
23119445813422155692453326671356443778246755488935
|
||||
22748628533385973964449618417555172952866628316397
|
||||
24924847833513595894462461691557357271266846838237
|
||||
32476224394358733541546984465265719557637682166874
|
||||
47151426715826253782693736489371484759148259586125
|
||||
85745282229685639333179674144428178525553928963666
|
||||
24212392483532341359464345246157545635726865674683
|
||||
24611235323572234643468334575457944568656815567976
|
||||
42365327415347643852645875496375698651748671976285
|
||||
23142496323425351743453646285456475739656758684176
|
||||
34221556924533266713564437782467554889357866599146
|
||||
33859739644496184175551729528666283163977739427418
|
||||
35135958944624616915573572712668468382377957949348
|
||||
43587335415469844652657195576376821668748793277985
|
||||
58262537826937364893714847591482595861259361697236
|
||||
96856393331796741444281785255539289636664139174777
|
||||
35323413594643452461575456357268656746837976785794
|
||||
35722346434683345754579445686568155679767926678187
|
||||
53476438526458754963756986517486719762859782187396
|
||||
34253517434536462854564757396567586841767869795287
|
||||
45332667135644377824675548893578665991468977611257
|
||||
44961841755517295286662831639777394274188841538529
|
||||
46246169155735727126684683823779579493488168151459
|
||||
54698446526571955763768216687487932779859814388196
|
||||
69373648937148475914825958612593616972361472718347
|
||||
17967414442817852555392896366641391747775241285888
|
||||
46434524615754563572686567468379767857948187896815
|
||||
46833457545794456865681556797679266781878137789298
|
||||
64587549637569865174867197628597821873961893298417
|
||||
45364628545647573965675868417678697952878971816398
|
||||
56443778246755488935786659914689776112579188722368
|
||||
55172952866628316397773942741888415385299952649631
|
||||
57357271266846838237795794934881681514599279262561
|
||||
65719557637682166874879327798598143881961925499217
|
||||
71484759148259586125936169723614727183472583829458
|
||||
28178525553928963666413917477752412858886352396999
|
||||
57545635726865674683797678579481878968159298917926
|
||||
57944568656815567976792667818781377892989248891319
|
||||
75698651748671976285978218739618932984172914319528
|
||||
56475739656758684176786979528789718163989182927419
|
||||
67554889357866599146897761125791887223681299833479
|
||||
|
||||
The total risk of this path is 315 (the starting position is still never entered, so its risk is not counted).
|
||||
|
||||
Using the full map, what is the lowest total risk of any path from the top left to the bottom right?
|
||||
|
219
2021/day15/aoc-c.c
Normal file
219
2021/day15/aoc-c.c
Normal file
@@ -0,0 +1,219 @@
|
||||
/* aoc-c.c: Advent of Code 2021, day 15 parts 1 & 2
|
||||
*
|
||||
* Copyright (C) 2021 Bruno Raoult ("br")
|
||||
* Licensed under the GNU General Public License v3.0 or later.
|
||||
* Some rights reserved. See COPYING.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this
|
||||
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "pool.h"
|
||||
#include "bits.h"
|
||||
#include "list.h"
|
||||
|
||||
#define MAX_SIZE 128
|
||||
|
||||
int a[] = {
|
||||
['a'] = 0,
|
||||
['b'] = 1,
|
||||
['c'] = 2
|
||||
};
|
||||
|
||||
typedef struct square {
|
||||
uchar cost;
|
||||
u32 totcost;;
|
||||
uchar visited;
|
||||
} square_t;
|
||||
|
||||
typedef struct priority_queue {
|
||||
int l;
|
||||
int c;
|
||||
u32 cost;
|
||||
struct list_head list;
|
||||
} pqueue_t;
|
||||
|
||||
static LIST_HEAD(plist_head);
|
||||
static struct square array[MAX_SIZE][MAX_SIZE];
|
||||
static int asize;
|
||||
static pool_t *pool;
|
||||
|
||||
#define VALID(x, y) ((x) >= 0 && (x) < size && (y) >= 0 && (y) < size )
|
||||
|
||||
static void print_array()
|
||||
{
|
||||
log(3, "array (%dx%d):\n", asize, asize);
|
||||
for (int i = 0; i < asize; ++i) {
|
||||
for (int j = 0; j < asize; ++j)
|
||||
log(3, "%1d/%2d ", array[i][j].cost, array[i][j].totcost);
|
||||
log(3, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void print_queue()
|
||||
{
|
||||
log(3, "queue:\n", asize, asize);
|
||||
pqueue_t *tmp;
|
||||
int i = 1;
|
||||
|
||||
list_for_each_entry(tmp, &plist_head, list) {
|
||||
int l = tmp->l, c = tmp->c;
|
||||
u32 cost = array[l][c].cost;
|
||||
u32 acc = array[l][c].totcost;
|
||||
log(3, "%d: (%d,%d): cost=%u acc=%lu\n", i, l, c, cost, acc);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* insert l,c in queue, keeping cost sorted */
|
||||
static pqueue_t *push(int l, int c, u32 parentcost)
|
||||
{
|
||||
pqueue_t *queue;
|
||||
u32 newcost;
|
||||
|
||||
if (l >= asize || c >= asize || array[l][c].visited)
|
||||
return NULL;
|
||||
newcost = parentcost + array[l][c].cost;
|
||||
if (newcost > array[l][c].totcost)
|
||||
return NULL;
|
||||
|
||||
queue = pool_get(pool);
|
||||
queue->l = l;
|
||||
queue->c = c;
|
||||
queue->cost = newcost;
|
||||
array[l][c].totcost = newcost;
|
||||
|
||||
log_f(3, "(%d,%d) pcost=%u\n", l, c, newcost);
|
||||
list_add_tail(&queue->list, &plist_head);
|
||||
return queue;
|
||||
}
|
||||
|
||||
static pqueue_t *pop()
|
||||
{
|
||||
pqueue_t *tmp, *cur;
|
||||
|
||||
list_for_each_entry_safe(cur, tmp, &plist_head, list) {
|
||||
int l = cur->l, c = cur->c;
|
||||
|
||||
list_del(&cur->list);
|
||||
if (array[l][c].visited) {
|
||||
pool_add(pool, cur);
|
||||
continue;
|
||||
}
|
||||
log_f(3, "(%d,%d) cost=%u\n", l, c, array[l][c].totcost);
|
||||
return cur;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read data and create graph.
|
||||
*/
|
||||
static int read_input()
|
||||
{
|
||||
size_t alloc = 0;
|
||||
char *buf;
|
||||
ssize_t len;
|
||||
int l = 0, c;
|
||||
|
||||
/* get points list */
|
||||
while ((len = getline(&buf, &alloc, stdin)) > 0) {
|
||||
buf[--len] = 0;
|
||||
|
||||
//printf("%d: size=%d [%s]\n", l, asize, buf);
|
||||
for (c = 0; buf[c]; ++c) {
|
||||
array[l][c].cost = buf[c] - '0';
|
||||
array[l][c].totcost = UINT32_MAX;
|
||||
array[l][c].visited = 0;
|
||||
}
|
||||
l++;
|
||||
}
|
||||
free(buf);
|
||||
asize = l;
|
||||
//print_array();
|
||||
return asize;
|
||||
}
|
||||
|
||||
|
||||
static u32 part1()
|
||||
{
|
||||
pqueue_t *pqueue;
|
||||
u32 best = UINT32_MAX;
|
||||
|
||||
push(0, 0, 0);
|
||||
|
||||
while ((pqueue = pop())) {
|
||||
int l = pqueue->l, c = pqueue->c;
|
||||
u32 acc = array[l][c].totcost;
|
||||
|
||||
if (l == (asize - 1) && c == (asize - 1)) {
|
||||
if (acc < best) {
|
||||
best = acc;
|
||||
log_f(3, "New best: %u\n", best);
|
||||
}
|
||||
}
|
||||
push(l, c + 1, acc);
|
||||
push(l + 1, c, acc);
|
||||
array[l][c].visited = 1;
|
||||
|
||||
pool_add(pool, pqueue); /* recycle pqueue in memory pool */
|
||||
}
|
||||
|
||||
/* as we accounted [0][0] cost, we must substract it */
|
||||
return best - array[0][0].cost;
|
||||
}
|
||||
|
||||
static u32 part2()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
static u32 doit(int part)
|
||||
{
|
||||
read_input();
|
||||
return part == 1? part1(): part2();
|
||||
}
|
||||
|
||||
static int usage(char *prg)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int opt, part = 1;
|
||||
|
||||
while ((opt = getopt(ac, av, "d:p:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
debug_level_set(atoi(optarg));
|
||||
break;
|
||||
case 'p': /* 1 or 2 */
|
||||
part = atoi(optarg);
|
||||
if (part < 1 || part > 2)
|
||||
return usage(*av);
|
||||
break;
|
||||
default:
|
||||
return usage(*av);
|
||||
}
|
||||
}
|
||||
if (optind < ac)
|
||||
return usage(*av);
|
||||
|
||||
if (!(pool = pool_init("stack", 1024, sizeof (pqueue_t))))
|
||||
return -1;
|
||||
|
||||
printf("%s : res=%d\n", *av, doit(part));
|
||||
exit (0);
|
||||
}
|
Reference in New Issue
Block a user