2020 day 24 part 1: C
This commit is contained in:
@@ -39,26 +39,35 @@ CFLAGS += -march=native
|
|||||||
CFLAGS += -Wmissing-declarations
|
CFLAGS += -Wmissing-declarations
|
||||||
CFLAGS += -Wno-unused-result
|
CFLAGS += -Wno-unused-result
|
||||||
|
|
||||||
#CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
|
CFLAGS += -DDEBUG_DEBUG # activate general debug (debug.c)
|
||||||
#CFLAGS += -DDEBUG_POOL # memory pools management
|
CFLAGS += -DDEBUG_POOL # memory pools management
|
||||||
|
|
||||||
|
VALGRIND := valgrind
|
||||||
|
VALGRINDFLAGS := --leak-check=full --show-leak-kinds=all --track-origins=yes \
|
||||||
|
--sigill-diagnostics=yes --quiet --show-error-list=yes
|
||||||
|
|
||||||
|
|
||||||
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
|
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
|
||||||
export PATH := .:$(PATH)
|
export PATH := .:$(PATH)
|
||||||
|
|
||||||
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 ex1 ex2 bear
|
.PHONY: clean all compile assembly memcheck memcheck1 memcheck2 ex1 ex2 bear org
|
||||||
|
|
||||||
all: ex1 ex2
|
org: README.org
|
||||||
|
|
||||||
|
all: org ex1 ex2
|
||||||
|
|
||||||
memcheck: memcheck1 memcheck2
|
memcheck: memcheck1 memcheck2
|
||||||
|
|
||||||
memcheck1: aoc-c
|
memcheck1: aoc-c
|
||||||
@valgrind -q -s --track-origins=yes aoc-c -p 1 < $(INPUT)
|
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 1 < $(INPUT)
|
||||||
|
|
||||||
memcheck2: aoc-c
|
memcheck2: aoc-c
|
||||||
@valgrind -q -s --track-origins=yes aoc-c -p 2 < $(INPUT)
|
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
|
||||||
|
|
||||||
compile: aoc-c
|
compile: aoc-c
|
||||||
|
|
||||||
|
cpp: aoc-c.i
|
||||||
|
|
||||||
assembly: aoc-c.s
|
assembly: aoc-c.s
|
||||||
|
|
||||||
ex1: aoc-c
|
ex1: aoc-c
|
||||||
@@ -70,7 +79,7 @@ ex2: aoc-c
|
|||||||
@$(TIME) aoc-c -p 2 < $(INPUT) 2>&1
|
@$(TIME) aoc-c -p 2 < $(INPUT) 2>&1
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s compile_commands.json
|
@rm -f aoc-c core* vgcore* gmon.out aoc-c.s aoc-c.i README.html compile_commands.json
|
||||||
|
|
||||||
.c:
|
.c:
|
||||||
@echo compiling $<
|
@echo compiling $<
|
||||||
|
@@ -61,10 +61,11 @@ memcheck1: aoc-c
|
|||||||
|
|
||||||
memcheck2: aoc-c
|
memcheck2: aoc-c
|
||||||
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
|
@$(VALGRIND) $(VALGRINDFLAGS) aoc-c -p 2 < $(INPUT)
|
||||||
@#@valgrind -s --track-origins=yes aoc-c -p 2 < $(INPUT)
|
|
||||||
|
|
||||||
compile: aoc-c
|
compile: aoc-c
|
||||||
|
|
||||||
|
cpp: aoc-c.i
|
||||||
|
|
||||||
assembly: aoc-c.s
|
assembly: aoc-c.s
|
||||||
|
|
||||||
ex1: aoc-c
|
ex1: aoc-c
|
||||||
@@ -99,3 +100,7 @@ clean:
|
|||||||
# generate compile_commands.json
|
# generate compile_commands.json
|
||||||
$(CCLSFILE): aoc-c.c Makefile
|
$(CCLSFILE): aoc-c.c Makefile
|
||||||
$(BEAR) -- make clean compile
|
$(BEAR) -- make clean compile
|
||||||
|
|
||||||
|
bear: clean
|
||||||
|
@$(BEAR) -- make compile
|
||||||
|
@touch .ccls-root
|
||||||
|
@@ -4,40 +4,171 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "bits.h"
|
||||||
|
#include "pool.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "hashtable.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
int main(ac, av)
|
/* In day 24 tasks, we do not care the order of tiles, as we regenerate
|
||||||
int ac;
|
* a new list after each process.
|
||||||
char **av;
|
* So we will rely on a hashtable, which will allow to quickly find a
|
||||||
|
* given point.
|
||||||
|
*/
|
||||||
|
typedef union coord {
|
||||||
|
u64 val;
|
||||||
|
struct {
|
||||||
|
s32 x, y;
|
||||||
|
};
|
||||||
|
} coord_t;
|
||||||
|
|
||||||
|
typedef struct point {
|
||||||
|
coord_t pos;
|
||||||
|
struct hlist_node coll; /* entry in hash table */
|
||||||
|
struct list_head all;
|
||||||
|
} point_t;
|
||||||
|
|
||||||
|
#define HBITS 12 /* in bits: 12 bits = 4096 */
|
||||||
|
#define HSIZE (1 << HBITS)
|
||||||
|
|
||||||
|
DEFINE_HASHTABLE(hash1, HBITS);
|
||||||
|
DEFINE_HASHTABLE(hash2, HBITS);
|
||||||
|
struct hlist_head *cur = hash1, *next = hash2;
|
||||||
|
|
||||||
|
pool_t *pt_pool;
|
||||||
|
|
||||||
|
static __always_inline u32 hash(coord_t p)
|
||||||
|
{
|
||||||
|
return hash_64(p.val, HBITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static point_t *find_point(struct hlist_head *head, coord_t p)
|
||||||
|
{
|
||||||
|
point_t *point;
|
||||||
|
hlist_for_each_entry(point, head, coll) {
|
||||||
|
if (point->pos.val == p.val)
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static point_t *add_point(struct hlist_head *p, coord_t pos)
|
||||||
|
{
|
||||||
|
point_t *new;
|
||||||
|
u32 h;
|
||||||
|
|
||||||
|
h = hash(pos);
|
||||||
|
if (!(new = find_point(p + h, pos))) {
|
||||||
|
new = pool_get(pt_pool);
|
||||||
|
new->pos.val = pos.val;
|
||||||
|
hlist_add_head(&new->coll, p + h);
|
||||||
|
}
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static point_t *flip_point(struct hlist_head *p, coord_t pos)
|
||||||
|
{
|
||||||
|
point_t *new;
|
||||||
|
u32 h;
|
||||||
|
|
||||||
|
log_f(3, "val=%lu x=%d y=%d ", pos.val, pos.x, pos.y);
|
||||||
|
h = hash(pos);
|
||||||
|
log(3, "hash=%d ", h);
|
||||||
|
if ((new = find_point(p + h, pos))) {
|
||||||
|
log(3, "removing tile\n");
|
||||||
|
hlist_del(&new->coll);
|
||||||
|
pool_add(pt_pool, new);
|
||||||
|
new = NULL;
|
||||||
|
} else {
|
||||||
|
log(3, "adding tile\n");
|
||||||
|
new = pool_get(pt_pool);
|
||||||
|
new->pos.val = pos.val;
|
||||||
|
hlist_add_head(&new->coll, p + h);
|
||||||
|
}
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int count_points(struct hlist_head *h)
|
||||||
|
{
|
||||||
|
point_t *cur;
|
||||||
|
int res = 0;
|
||||||
|
for (int bkt = 0; bkt < HSIZE; ++bkt) {
|
||||||
|
hlist_for_each_entry(cur, &h[bkt], coll) {
|
||||||
|
res++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse()
|
||||||
{
|
{
|
||||||
size_t alloc;
|
size_t alloc;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
|
|
||||||
while ((len = getline(&buf, &alloc, stdin))) {
|
while ((len = getline(&buf, &alloc, stdin)) > 0) {
|
||||||
buf[len - 1] = 0;
|
buf[len - 1] = 0;
|
||||||
int x=0, y=0;
|
coord_t p = { .val = 0 };
|
||||||
|
puts(buf);
|
||||||
char *c = buf;
|
char *c = buf;
|
||||||
while (*c) {
|
while (*c) {
|
||||||
switch (*c) {
|
switch (*c) {
|
||||||
case 'e':
|
case 'e':
|
||||||
++x;
|
++p.x;
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
++y;
|
--p.x;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
--y, ++c;
|
--p.y;
|
||||||
|
++c;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
++y, ++c;
|
++p.y;
|
||||||
|
++c;
|
||||||
}
|
}
|
||||||
if (*c == 'e')
|
if (*c == 'e')
|
||||||
++x;
|
++p.x;
|
||||||
else if (*c == 'w')
|
else if (*c == 'w')
|
||||||
++y;
|
--p.x;
|
||||||
|
c++;
|
||||||
|
//printf("pos=%ld x=%d y=%d\n", c - buf, p.x, p.y);
|
||||||
|
}
|
||||||
|
flip_point(cur, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usage(char *prg)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(ac, av)
|
||||||
|
int ac;
|
||||||
|
char **av;
|
||||||
|
{
|
||||||
|
int opt, part = 1;
|
||||||
|
ulong res = 0;
|
||||||
|
|
||||||
|
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)
|
||||||
|
default:
|
||||||
|
return usage(*av);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pt_pool = pool_create("pool_points", 256, sizeof(point_t));
|
||||||
|
|
||||||
|
parse();
|
||||||
|
printf("count=%d\n", count_points(cur));
|
||||||
printf("%s : res=%lu\n", *av, res);
|
printf("%s : res=%lu\n", *av, res);
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user