From 33bee9500c54b3ab60ca56a8e4d0ecce6a254cea Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Fri, 14 Jan 2022 11:50:14 +0100 Subject: [PATCH] day 19: first functions (read input, calculate beacons distances...) --- 2021/day19/aoc-c.c | 278 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 2021/day19/aoc-c.c diff --git a/2021/day19/aoc-c.c b/2021/day19/aoc-c.c new file mode 100644 index 0000000..ae9994e --- /dev/null +++ b/2021/day19/aoc-c.c @@ -0,0 +1,278 @@ +/* aoc-c.c: Advent of Code 2021, day 19 parts 1 & 2 + * + * Copyright (C) 2022 Bruno Raoult ("br") + * Licensed under the GNU General Public License v3.0 or later. + * Some rights reserved. See COPYING. + * + * You should have received a copy of the GNU General Public License along with this + * program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include +#include +#include + +#include "pool.h" +#include "debug.h" +#include "bits.h" +#include "list.h" + +/* + typedef struct beacon { + int x, y, z; + struct list_head list_beacons; + } beacon_t; + + typedef struct scanner { + struct list_head list_beacons; + } scanner_t; +*/ + +#define MAX_SCANNERS 32 /* I know, I know... */ +#define MAX_BEACONS 32 +#define MAX_DISTANCES ((MAX_BEACONS - 1) * MAX_BEACONS) + +typedef struct beacon { + int x, y, z; + struct list_head list_beacons; +} beacon_t; + +typedef struct dist { + u64 dist; + int b1, b2; +} dist_t; + +typedef struct scanner { + //struct list_head list_beacons; + int nbeacons, ndists; + beacon_t beacons[MAX_BEACONS]; + dist_t dists[MAX_DISTANCES]; /* sorted */ +} scanner_t; + +static pool_t *pool_beacon; + +static scanner_t scanners[MAX_SCANNERS]; +static int nscanners; + +static void scanners_print_dists() +{ + dist_t *cur; + + log_f(1, "nscanners: %d\n", nscanners); + for (int i = 0; i < nscanners; ++i) { + log(1, "scanner %d:\n", i); + for (int j = 0; j < scanners[i].ndists; ++j) { + cur = &scanners[i].dists[j]; + log(1, "\t%d : %d,%d\n", cur->dist, cur->b1, cur->b2); + } + log(1, "\n"); + } +} + +static void scanners_print() +{ + beacon_t *cur; + + log_f(1, "nscanners: %d\n", nscanners); + for (int i = 0; i < nscanners; ++i) { + log(1, "scanner %d:\n\t", i); + /* + list_for_each_entry(cur, &scanners[i].list_beacons, list_beacons) { + log(1, " %d/%d/%d", cur->x, cur->y, cur->z); + } + */ + for (int j = 0; j < scanners[i].nbeacons; ++j) { + cur = &scanners[i].beacons[j]; + log(1, " %d/%d/%d", cur->x, cur->y, cur->z); + } + log(1, "\n"); + } +} + +static void merge(array, left, mid, right) + dist_t *array; + int left, mid, right; +{ + dist_t temp[right - left + 1]; + int pos = 0, lpos = left, rpos = mid + 1, iter; + + while(lpos <= mid && rpos <= right) { + if(array[lpos].dist < array[rpos].dist) { + temp[pos++] = array[lpos++]; + } + else { + temp[pos++] = array[rpos++]; + } + } + while(lpos <= mid) + temp[pos++] = array[lpos++]; + while(rpos <= right) + temp[pos++] = array[rpos++]; + for(iter = 0; iter < pos; iter++) { + array[iter+left] = temp[iter]; + } + return; +} + +static void mergesort(array, left, right) + dist_t *array; + int left, right; +{ + int mid = (left + right) / 2; + if(left < right) { + mergesort(array, left, mid); + mergesort(array, mid + 1, right); + merge(array, left, mid, right); + } +} + +static int count_common_distances(scanner_t *s1, scanner_t *s2) +{ + dist_t *d1 = s1->dists, *d2 = s2->dists; + int cur1 = 0, cur2 = 0; + uint count = 0; + + log_f(1, "(%d, %d): ", s1 - scanners, s2 - scanners); + while (cur1 < s1->ndists && cur2 < s2->ndists) { + if (d1[cur1].dist == d2[cur2].dist) { + log_i(3, " %ld", d1[cur1].dist); + ++count; + ++cur1; + ++cur2; + } + else if (d1[cur1].dist < d2[cur2].dist) { + ++cur1; + } else { + ++cur2; + } + } + log_i(3, "\n"); + return count; +} + +static void calc_square_distances() +{ + scanner_t *scanner; + beacon_t *b1, *b2; + uint dist; + + log_f(1, "nscanners: %d\n", nscanners); + for (int i = 0; i < nscanners; ++i) { + scanner = scanners + i; + for (int j = 0; j < scanner->nbeacons; ++j) { + b1 = scanner->beacons + j; + for (int k = j + 1; k < scanner->nbeacons; ++k) { + scanner->dists[scanner->ndists].b1 = j; + scanner->dists[scanner->ndists].b2 = k; + + b2 = scanner->beacons + k; + dist = (b1->x - b2->x) * (b1->x - b2->x) + + (b1->y - b2->y) * (b1->y - b2->y) + + (b1->z - b2->z) * (b1->z - b2->z); + scanner->dists[scanner->ndists].dist = dist; + scanner->ndists++; + log(5, "\tdist(%d/%d) = %lu\n", + j, k, + dist); + } + + } + scanners_print_dists(); + mergesort(scanner->dists, 0, scanner->ndists - 1); + } + scanners_print_dists(); + log(1, "\n"); +} + +/* read input + */ +static int read_lines() +{ + size_t alloc = 0; + ssize_t buflen; + char *buf = NULL; + beacon_t *beacon; + scanner_t *scanner = NULL; + //int nbeacon = 0; + + while ((buflen = getline(&buf, &alloc, stdin)) > 0) { + //buf[--buflen] = 0; + switch (buf[1]) { + case '-': + scanner = scanners + nscanners; + log_f(2, "[%c] nscanners = %d %p/%p\n", *buf, nscanners, + scanner, scanners); + //INIT_LIST_HEAD(&scanner->list_beacons); + nscanners++; + scanner->nbeacons = 0; + break; + case '\0': + log_f(2, "NULL line\n"); + break; + default: + //log_f(2, "[%c] beacon = %d\n", *buf, nscanners); + //beacon = pool_get(pool_beacon); + //list_add_tail(&beacon->list_beacons, &scanner->list_beacons); + beacon = &scanner->beacons[scanner->nbeacons]; + sscanf(buf, "%d,%d,%d", &beacon->x, &beacon->y, &beacon->z); + //log_f(2, "beacon %d = %d/%d/%d\n", nbeacon, beacon->x, beacon->y, beacon->z); + scanner->nbeacons++; + + } + } + free(buf); + scanners_print(); + calc_square_distances(); + for (int i = 0; i < nscanners - 1; ++i) + for (int j = i + 1; j < nscanners; ++j) + log(1, "common(%d, %d) = %d\n", i, j, + count_common_distances(scanners + i, scanners + j)); + return nscanners; +} + +static s64 part1() +{ + return 1; +} + +static s64 part2() +{ + return 2; +} + +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_beacon = pool_create("beacons", 1024, sizeof(beacon_t)))) + exit(1); + read_lines(); + printf("%s : res=%ld\n", *av, part == 1? part1(): part2()); + pool_destroy(pool_beacon); + exit(0); +}