Compare commits

...

2 Commits

Author SHA1 Message Date
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
5 changed files with 424 additions and 2 deletions

View File

@@ -141,3 +141,57 @@ 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=.
The first half of this puzzle is complete! It provides one gold star: *
** --- 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?/

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

@@ -0,0 +1,354 @@
/* aoc-c.c: Advent of Code 2022, day 13
*
* 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 <unistd.h>
#include "br.h"
#include "debug.h"
#include "list.h"
#include "pool.h"
#include "aoc.h"
typedef enum {
NIL,
LIST,
//SUBLIST,
INT
} type_t;
char *types[] = {
"NIL",
"LIST",
//"SUBLIST",
"INT"
};
struct node;
typedef struct cons {
type_t type;
union {
//struct list_head node; /* same level node */
struct node *sub;
int value;
};
} cons_t;
#define CAR 0 /* always NUM or SUBLIST */
#define CDR 1 /* always LIST */
typedef struct node {
type_t car_t;
union {
struct list_head sub;
int value;
} car;
struct list_head cdr;
//cons_t cons[2];
} node_t;
typedef struct line {
int pos; /* position to parse */
char *s;
} line_t;
pool_t *pool_nodes;
static node_t *getnode()
{
node_t *node = pool_get(pool_nodes);
node->car_t = NIL;
INIT_LIST_HEAD(&node->cdr);
log_f(4, "\n");
return node;
}
static void print_tree(struct list_head *head, int level)
{
struct node *cur;
log_f(4, "head=%p lev=%d\n", head, level);
printf("( ");
//if (!list_empty(&node->cdr)) {
list_for_each_entry(cur, head, cdr) {
if (cur->car_t == INT)
printf("%d ", cur->car.value);
else if (cur->car_t == NIL)
printf("ERROR ");
else
print_tree(&cur->car.sub, level + 2);
}
//} else {
//printf("nil ");
//}
printf(") ");
if (!level)
printf("\n");
}
static int compare_tree(struct list_head *h1, struct list_head *h2)
{
struct list_head *cur1, *cur2;
//struct list_head *h1, *h2;
node_t *tmp, *n1, *n2;
int res;
log_f(3, "h1=%p h2=%p\n", h1, h2);
/* check for NIL */
/*
* if (n1->car_t == NIL) {
* log(3, "n1 is NIL\n");
* return n2->car_t == NIL? 0: 1;
* }
* if (n2->car_t == NIL) {
* log(3, "n2 is NIL\n");
* return -1;
* }
*/
//h1 = &n1->cdr;
//h2 = &n2->cdr;
/* get lists first entries */
cur1 = h1->next;
cur2 = h2->next;
//if (!list_empty(h1) && !list_empty(h2)) {
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->car.value < n2->car.value) {
log(3, "car1=%d < car2=%d, returning 1\n", n1->car.value,
n2->car.value);
return 1;
} else if (n1->car.value > n2->car.value) {
log(3, "car1=%d > car2=%d, returning -1\n", n1->car.value,
n2->car.value);
return -1;
}
log(3, "car1 == car2 == %d, skipping\n", n1->car.value);
} else { /* both sublists */
res = compare_tree(&n1->car.sub, &n2->car.sub);
if (res)
return res;
}
} else { /* one number, one list */
tmp = getnode();
//INIT_LIST_HEAD(&tmp->car.sub);
tmp->car_t = INT;
if (n1->car_t == INT) {
log(3, "car1 == INT, adding a node\n");
tmp->car.value = n1->car.value;
n1->car_t = LIST;
INIT_LIST_HEAD(&n1->car.sub);
list_add(&tmp->cdr, &n1->car.sub);
//n1->car.sub = tmp;
//print_tree()
} else {
log(3, "car2 == INT, adding a node\n");
tmp->car.value = n2->car.value;
n2->car_t = LIST;
INIT_LIST_HEAD(&n2->car.sub);
list_add(&tmp->cdr, &n2->car.sub);
//n2->car.sub = tmp;
}
res = compare_tree(&n1->car.sub, &n2->car.sub);
if (res)
return res;
//continue;
}
//next:
cur1 = cur1->next;
cur2 = cur2->next;
}
//} else {
// log(3, "some list empty\n");
//}
/* at least one list came to end */
if (cur1 == h1 && cur2 == h2) { /* both are ending */
log(3, "Both sides Left side ran out of items, undecided\n");
return 0;
} else if (cur1 == h1) { /* first list did end */
log(3, "Left side ran out of items, so inputs are in the right order\n");
return 1;
} else {
log(3, "Right side ran out of items, so inputs are not in the right order\n");
return -1;
}
}
static struct list_head *create_tree(char *s, int *consumed, int level, struct list_head *head)
{
node_t *node = NULL;
LIST_HEAD(sub);
int num = 0, val, depth = 0, subconsumed;
//LIST_HEAD(head);
*consumed = 1;
if (*s != '[') {
printf("error 0\n");
exit(0);
}
INIT_LIST_HEAD(head);
//head = getnode();
log_f(3, "create_tree(%s)\n", s);
for (; *s; s++, (*consumed)++) {
log(4, "L=%d examining %c num=%d depth=%d\n", level, *s, num, depth);
val = 0;
switch (*s) {
case '[':
switch (++depth) {
case 1: /* first level */
break;
case 2: /* second level (nested list) */
node = getnode();
node->car_t = LIST;
INIT_LIST_HEAD(&node->car.sub);
create_tree(s, &subconsumed, level + 1, &node->car.sub);
s += subconsumed - 1;
*consumed += subconsumed - 1;
log(4, "after create_tree: cons=%d s=%s\n", subconsumed, s);
//if (num == 0) {
// head->car_t = SUBLIST;
// head->car.sub = sub;
//} else {
//list_add(&sub, &node->car.sub); /* add sublist to new node */
list_add_tail(&node->cdr, head); /* add node to current level */
puts("ZOBI");
print_tree(&node->car.sub, 0);
puts("ZOBa");
//sleep(1);
print_tree(head, 0);
//}
depth--;
num++;
break;
default: /* should not happen */
printf("error 1\n");
exit(0);
break; /* not reached */
}
//num++;
break;
case ',':
break;
case ']':
if (!--depth)
goto end;
break;
default: /* number */
sscanf(s, "%d%n", &val, &subconsumed);
*consumed += subconsumed - 1;
s += subconsumed - 1;
log(4, "got integer=%d num=%d depth=%d chars=%d\n", val, num, depth, subconsumed);
//if (num == 0) {
// head->car_t = INT;
// head->car.value = val;
//} else {
node = getnode();
node->car_t = INT;
node->car.value = val;
list_add_tail(&node->cdr, head);
//}
//print_tree(head, 0);
num++;
break;
}
}
end:
log(4, "returning from create_tree, consumed=%d head=%p\n", *consumed, head);
return head;
}
static int parse()
{
size_t alloc = 0;
ssize_t buflen;
char *buf = NULL;
int i = 0;
struct list_head head[2];
int consumed;
int group = 1, res = 0, tmp;
//line_t line;
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
buf[--buflen] = 0;
if (!buflen) {
//i = 0;
//printf("++++ node 1 = %p\n", node[1]);
printf("++++ node 0 = %p\n", &head[0]);
print_tree(&head[0], 0);
printf("++++ node 1 = %p\n", &head[1]);
print_tree(&head[1], 0);
tmp = compare_tree(&head[0], &head[1]);
printf("group = %d compare_tree() = %d\n", group, tmp);
if (tmp == 1) {
res += group;
printf("group = %d: right order res:%d -> %d\n", group, res - group, res);
}
group++;
printf("\n\n");
//pool_add(pool_nodes, node[0]);
//pool_add(pool_nodes, node[1]);
//node[0] = node[1] = NULL;
//exit(0);
} else {
//node[i % 2] = getnode();
create_tree(buf, &consumed, 0, &head[i % 2]);
printf("setting node %d\n\n", i%2);
i++;
}
}
printf("++++ node 0 = %p\n", &head[0]);
print_tree(&head[0], 0);
printf("++++ node 1 = %p\n", &head[1]);
print_tree(&head[1], 0);
tmp = compare_tree(&head[0], &head[1]);
printf("group = %d compare_tree() = %d\n", group, tmp);
if (tmp == 1) {
res += group;
printf("group = %d: right order res:%d -> %d\n", group, res - group, res);
}
printf("\n\n");
return 1;
}
static u64 doit()
{
return 1;
}
static u64 part1()
{
return doit();
}
static u64 part2()
{
return doit();
}
int main(int ac, char **av)
{
int part = parseargs(ac, av);
pool_nodes = pool_create("nodes", 512, sizeof(node_t));
//u32 foo=0x12345678;
parse();
printf("%s: res=%lu\n", *av, part == 1? part1(): part2());
pool_destroy(pool_nodes);
exit(0);
}

View File

@@ -34,7 +34,7 @@
*
* Return: the PJW hash.
*/
_pjw_inline unsigned int pjwhash(const void* key, uint length)
_pjw_inline uint pjwhash(const void* key, uint length)
{
uint hash = 0, high;
const u8 *k = key;

View File

@@ -15,6 +15,16 @@
#include "bits.h"
extern unsigned int pjwhash (const void* key, uint length)
/**
* 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.
*/
extern uint pjwhash (const void* key, uint length);
#endif /* _PJWHASH_H */

View File

@@ -13,4 +13,8 @@
#define _pjw_inline extern
//#include "bits.h"
//extern unsigned int pjwhash (const void* key, uint length);
#include "pjwhash.h"
#include "pjwhash-inline.h"