Compare commits
2 Commits
d0376f21c3
...
f54479189b
Author | SHA1 | Date | |
---|---|---|---|
f54479189b | |||
8e00fec33c |
@@ -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
354
2022/day13/aoc-c.c
Normal 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);
|
||||
}
|
@@ -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;
|
||||
|
@@ -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 */
|
||||
|
@@ -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"
|
||||
|
Reference in New Issue
Block a user