parent
fdb9277ad1
commit
7785832673
@ -0,0 +1,41 @@
|
|||||||
|
SRC:= day9.c map.c
|
||||||
|
|
||||||
|
OPT_FLAGS?= -march=native -flto \
|
||||||
|
-march=native -fgraphite -fopenmp -floop-parallelize-all -ftree-parallelize-loops=4 \
|
||||||
|
-floop-interchange -ftree-loop-distribution -floop-strip-mine -floop-block \
|
||||||
|
-fno-stack-check -fno-strict-aliasing
|
||||||
|
|
||||||
|
COMMON_FLAGS?=-pipe -O3 -Wall -pedantic -Wextra -Wstrict-aliasing
|
||||||
|
|
||||||
|
C_OPT_FLAGS=$(OPT_FLAGS)
|
||||||
|
CXX_OPT_FLAGS=$(OPT_FLAGS) -felide-constructors -fno-exceptions
|
||||||
|
LD_OPT_FLAGS?=-O3 -flto
|
||||||
|
|
||||||
|
INCLUDE=../common/include
|
||||||
|
|
||||||
|
CFLAGS?=$(COMMON_FLAGS) $(C_OPT_FLAGS) --std=gnu11
|
||||||
|
CXXFLAGS?=$(COMMON_FLAGS) $(CXX_OPT_FLAGS) --std=gnu++20
|
||||||
|
LDFLAGS?=$(LD_OPT_FLAGS)
|
||||||
|
|
||||||
|
CFLAGS+=-I$(INCLUDE)
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: part1 part2
|
||||||
|
|
||||||
|
inpu%.h: inpu%
|
||||||
|
@rm -f $@
|
||||||
|
while read line; do \
|
||||||
|
echo "$$line," >> $@; \
|
||||||
|
done < $<
|
||||||
|
|
||||||
|
part1: $(SRC) | input.h
|
||||||
|
$(CC) $(SRC) $(CFLAGS) -o $@ $(LDFLAGS)
|
||||||
|
strip $@
|
||||||
|
|
||||||
|
part1-test: $(SRC) | input-test.h
|
||||||
|
$(CC) $(SRC) -DTEST $(CFLAGS) -o $@ $(LDFLAGS)
|
||||||
|
strip $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f part{1,2}{,-test}
|
||||||
|
rm -f input{,-test}.h
|
@ -0,0 +1,92 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "map.h"
|
||||||
|
|
||||||
|
typedef uint64_t u64;
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
#define PREAMBLE 5
|
||||||
|
#else
|
||||||
|
#define PREAMBLE 25
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define input_sz (sizeof(input) / sizeof(u64))
|
||||||
|
const u64 input[] = {
|
||||||
|
#ifdef TEST
|
||||||
|
#include "input-test.h"
|
||||||
|
#else
|
||||||
|
#include "input.h"
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#define box(t) (calloc(sizeof(t), 1))
|
||||||
|
|
||||||
|
struct pair {
|
||||||
|
bool valid;
|
||||||
|
u64 num;
|
||||||
|
u64 sum[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline static void insert_page(map_t* restrict where, u64 key, size_t i)
|
||||||
|
{
|
||||||
|
//if(key > PAGE_SIZE) panic("Data too large, increase page size to fit %lu in a single page", key);
|
||||||
|
map_insert(where, key, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void calculate_deficits(const u64 pre[static PREAMBLE], map_t * restrict output, u64 target)
|
||||||
|
{
|
||||||
|
for(size_t i=0;i<PREAMBLE;i++)
|
||||||
|
if(target > pre[i])
|
||||||
|
insert_page(output, target - pre[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PART2
|
||||||
|
static u64 find_set(u64 target)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
map_t def = map_new();
|
||||||
|
struct pair result[input_sz] = {0};
|
||||||
|
|
||||||
|
for(register size_t i= PREAMBLE;i<input_sz;i++)
|
||||||
|
{
|
||||||
|
calculate_deficits(&input[i-PREAMBLE], &def, input[i]);
|
||||||
|
|
||||||
|
for(register size_t j=0;j<PREAMBLE;j++)
|
||||||
|
{
|
||||||
|
result[i].num = input[i];
|
||||||
|
|
||||||
|
size_t idx;
|
||||||
|
u64 us = input[(i-PREAMBLE)+j];
|
||||||
|
if(!map_get(&def, us, &idx)) continue;
|
||||||
|
u64 other = input[(i-PREAMBLE)+idx];
|
||||||
|
|
||||||
|
// Found pair!
|
||||||
|
result[i] = (struct pair){.valid = other!=us, .num=input[i], .sum = { us, other }};
|
||||||
|
}
|
||||||
|
map_clear(&def);
|
||||||
|
}
|
||||||
|
map_free(def);
|
||||||
|
|
||||||
|
for(register size_t i=PREAMBLE;i<input_sz;i++)
|
||||||
|
{
|
||||||
|
if(!result[i].valid && !(result[i].sum[0] | result[i].sum[1])) {
|
||||||
|
#ifdef PART2
|
||||||
|
return find_set(result[i].num);
|
||||||
|
#else
|
||||||
|
printf("%lu\n", result[i].num);
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Not found\n");
|
||||||
|
return 1;
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "map.h"
|
||||||
|
|
||||||
|
#define box(t) calloc(sizeof(t), 1)
|
||||||
|
|
||||||
|
struct page {
|
||||||
|
struct entry {
|
||||||
|
bool set;
|
||||||
|
map_key_t key;
|
||||||
|
map_value_t value;
|
||||||
|
} p[PAGE_SIZE];
|
||||||
|
|
||||||
|
struct page* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
map_t map_new()
|
||||||
|
{
|
||||||
|
register map_t rval;
|
||||||
|
|
||||||
|
rval.page0 = box(struct page);
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t page_index(map_key_t k)
|
||||||
|
{
|
||||||
|
return (size_t)(k % PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void map_insert(map_t * restrict into, map_key_t k, map_value_t v)
|
||||||
|
{
|
||||||
|
struct page** p = &into->page0;
|
||||||
|
size_t i = page_index(k);
|
||||||
|
|
||||||
|
while(*p) {
|
||||||
|
register struct page* page = *p;
|
||||||
|
if (!page->p[i].set || page->p[i].key == k)
|
||||||
|
{
|
||||||
|
page->p[i] = (struct entry){.set = true, .key = k, .value = v};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p = &page->next;
|
||||||
|
}
|
||||||
|
// p == &<last page>.next == &NULL
|
||||||
|
(*p = box(struct page))->p[i] = (struct entry){.set = true, .key = k, .value = v};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool map_get(const map_t* from, map_key_t k, map_value_t* restrict v)
|
||||||
|
{
|
||||||
|
const struct page* p = from->page0;
|
||||||
|
size_t i = page_index(k);
|
||||||
|
|
||||||
|
while(p) {
|
||||||
|
if (p->p[i].set && p->p[i].key ==k) {
|
||||||
|
*v = p->p[i].value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void map_free(map_t map)
|
||||||
|
{
|
||||||
|
while(map.page0)
|
||||||
|
{
|
||||||
|
struct page* next = map.page0->next;
|
||||||
|
free(map.page0);
|
||||||
|
map.page0 = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _map_walk(map_t* restrict map, void (*cb)(struct page* page))
|
||||||
|
{
|
||||||
|
struct page* page= map->page0;
|
||||||
|
while(page)
|
||||||
|
{
|
||||||
|
cb(page);
|
||||||
|
page = page->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _map_page_clear(struct page* page)
|
||||||
|
{
|
||||||
|
memset(page, 0, sizeof(struct page));
|
||||||
|
}
|
||||||
|
|
||||||
|
void map_clear(map_t* restrict map)
|
||||||
|
{
|
||||||
|
_map_walk(map, &_map_page_clear);
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef _MAP_H
|
||||||
|
#define _MAP_H
|
||||||
|
|
||||||
|
#ifndef KELEMENT
|
||||||
|
#include <stdint.h>
|
||||||
|
# define KELEMENT uint64_t
|
||||||
|
#endif
|
||||||
|
#ifndef VELEMENT
|
||||||
|
#include <stddef.h>
|
||||||
|
# define VELEMENT size_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef KELEMENT map_key_t;
|
||||||
|
typedef VELEMENT map_value_t;
|
||||||
|
|
||||||
|
#define PAGE_SIZE UINT16_MAX
|
||||||
|
|
||||||
|
typedef struct _map {
|
||||||
|
struct page* page0;
|
||||||
|
} map_t;
|
||||||
|
|
||||||
|
map_t map_new();
|
||||||
|
void map_insert(map_t * restrict into, map_key_t k, map_value_t v);
|
||||||
|
bool map_get(const map_t* from, map_key_t k, map_value_t* restrict v);
|
||||||
|
void map_free(map_t map);
|
||||||
|
void map_clear(map_t* restrict map);
|
||||||
|
|
||||||
|
#endif /* _MAP_H */
|
Loading…
Reference in new issue