day 19 part 2, before cleaning
This commit is contained in:
@@ -27,7 +27,6 @@ typedef struct vector {
|
|||||||
} vector_t;
|
} vector_t;
|
||||||
|
|
||||||
typedef struct beacon {
|
typedef struct beacon {
|
||||||
u64 manhattan; /* manhattan distance from scanner */
|
|
||||||
int scanner; /* original scanner for beacon */
|
int scanner; /* original scanner for beacon */
|
||||||
int num; /* original # in original scanner */
|
int num; /* original # in original scanner */
|
||||||
int common; /* has common distance with 1st scanner */
|
int common; /* has common distance with 1st scanner */
|
||||||
@@ -44,6 +43,7 @@ typedef struct dist {
|
|||||||
typedef struct scanner {
|
typedef struct scanner {
|
||||||
int nbeacons, ndists;
|
int nbeacons, ndists;
|
||||||
int adjusted;
|
int adjusted;
|
||||||
|
vector_t rel; /* relative position to scanner 0 */
|
||||||
struct list_head list_beacons;
|
struct list_head list_beacons;
|
||||||
struct list_head list_dists;
|
struct list_head list_dists;
|
||||||
beacon_t *ref[3]; /* reference beacons */
|
beacon_t *ref[3]; /* reference beacons */
|
||||||
@@ -98,8 +98,7 @@ static void scanner_print(scanner_t *s)
|
|||||||
|
|
||||||
log(1, "scanner %ld: %d beacons\n", s - scanners, s->nbeacons);
|
log(1, "scanner %ld: %d beacons\n", s - scanners, s->nbeacons);
|
||||||
list_for_each_entry(cur, &s->list_beacons, list_beacons) {
|
list_for_each_entry(cur, &s->list_beacons, list_beacons) {
|
||||||
log_i(3, " m=%lu %ld/%ld/%ld\n", cur->manhattan,
|
log_i(3, "%ld/%ld/%ld\n", cur->vec.x, cur->vec.y, cur->vec.z);
|
||||||
cur->vec.x, cur->vec.y, cur->vec.z);
|
|
||||||
}
|
}
|
||||||
//log(1, "\n");
|
//log(1, "\n");
|
||||||
}
|
}
|
||||||
@@ -253,15 +252,13 @@ static int add_beacon_dists1(scanner_t *scanner, beacon_t *beacon)
|
|||||||
static inline int compare_beacons(beacon_t *b1, beacon_t *b2)
|
static inline int compare_beacons(beacon_t *b1, beacon_t *b2)
|
||||||
{
|
{
|
||||||
vector_t *v1 = &b1->vec, *v2 = &b2->vec;
|
vector_t *v1 = &b1->vec, *v2 = &b2->vec;
|
||||||
u64 m1 = b1->manhattan, m2 = b2->manhattan;
|
//u64 m1 = b1->manhattan, m2 = b2->manhattan;
|
||||||
|
|
||||||
if (m1 < m2 ||
|
if (v1->x < v2->x ||
|
||||||
(m1 == m2 &&
|
|
||||||
(v1->x < v2->x ||
|
|
||||||
(v1->x == v2->x && v1->y < v2->y) ||
|
(v1->x == v2->x && v1->y < v2->y) ||
|
||||||
((v1->x == v2->x && v1->y == v2->y) && v1->z < v2->z)))) {
|
((v1->x == v2->x && v1->y == v2->y) && v1->z < v2->z)) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (m1 == m2 && v1->x == v2->x && v1->y == v2->y && v1->z == v2->z) {
|
} else if (v1->x == v2->x && v1->y == v2->y && v1->z == v2->z) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -274,13 +271,7 @@ static inline int compare_beacons(beacon_t *b1, beacon_t *b2)
|
|||||||
*/
|
*/
|
||||||
static int insert_unique_beacon(scanner_t *scanner, beacon_t *beacon)
|
static int insert_unique_beacon(scanner_t *scanner, beacon_t *beacon)
|
||||||
{
|
{
|
||||||
vector_t *vec = &beacon->vec;
|
|
||||||
beacon_t *cur;
|
beacon_t *cur;
|
||||||
u64 manhattan = labs(vec->x) + labs(vec->y) + labs(vec->z);
|
|
||||||
|
|
||||||
beacon->manhattan = manhattan;
|
|
||||||
|
|
||||||
log_f(3, "manhattan=%lu\n", manhattan);
|
|
||||||
|
|
||||||
cur = list_first_entry_or_null(&scanner->list_beacons, beacon_t, list_beacons);
|
cur = list_first_entry_or_null(&scanner->list_beacons, beacon_t, list_beacons);
|
||||||
/* special case: first beacon or new beacon lower than first beacon */
|
/* special case: first beacon or new beacon lower than first beacon */
|
||||||
@@ -291,7 +282,6 @@ static int insert_unique_beacon(scanner_t *scanner, beacon_t *beacon)
|
|||||||
}
|
}
|
||||||
/* normal case: insert before current when new dist is lower than current dist */
|
/* normal case: insert before current when new dist is lower than current dist */
|
||||||
list_for_each_entry(cur, &scanner->list_beacons, list_beacons) {
|
list_for_each_entry(cur, &scanner->list_beacons, list_beacons) {
|
||||||
log_i(7, "comp=%lu\n", cur->manhattan);
|
|
||||||
switch (compare_beacons(beacon, cur)) {
|
switch (compare_beacons(beacon, cur)) {
|
||||||
case -1:
|
case -1:
|
||||||
list_add_tail(&beacon->list_beacons, &cur->list_beacons);
|
list_add_tail(&beacon->list_beacons, &cur->list_beacons);
|
||||||
@@ -308,22 +298,6 @@ end:
|
|||||||
return ++scanner->nbeacons;
|
return ++scanner->nbeacons;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return 1 if b exists in s beacons's list, 0 otherwise.
|
|
||||||
*/
|
|
||||||
static int beacon_exists(scanner_t *s, beacon_t *b)
|
|
||||||
{
|
|
||||||
beacon_t *cur;
|
|
||||||
|
|
||||||
list_for_each_entry(cur, &s->list_beacons, list_beacons) {
|
|
||||||
if (b->vec.x == cur->vec.x &&
|
|
||||||
b->vec.y == cur->vec.y &&
|
|
||||||
b->vec.z == cur->vec.z) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* using scanner's reference points, find the correct rotation and translation
|
/* using scanner's reference points, find the correct rotation and translation
|
||||||
*/
|
*/
|
||||||
static int adjust_scanner(scanner_t *ref, scanner_t *s)
|
static int adjust_scanner(scanner_t *ref, scanner_t *s)
|
||||||
@@ -357,6 +331,7 @@ static int adjust_scanner(scanner_t *ref, scanner_t *s)
|
|||||||
goto next_rot;
|
goto next_rot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s->rel = diff[0];
|
||||||
log(2, "Got it: scanner %lu is (%ld,%ld,%ld) from reference\n",
|
log(2, "Got it: scanner %lu is (%ld,%ld,%ld) from reference\n",
|
||||||
s - scanners, diff[0].x, diff[0].y, diff[0].z);
|
s - scanners, diff[0].x, diff[0].y, diff[0].z);
|
||||||
error = 0;
|
error = 0;
|
||||||
@@ -384,33 +359,6 @@ static int adjust_scanner(scanner_t *ref, scanner_t *s)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add distances between b1 and all following beacons in scanner's list
|
|
||||||
*/
|
|
||||||
static int add_beacon_dists(scanner_t *scanner, beacon_t *b1)
|
|
||||||
{
|
|
||||||
beacon_t *b2 = b1;
|
|
||||||
dist_t *dist;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
list_for_each_entry_continue(b2, &scanner->list_beacons, list_beacons) {
|
|
||||||
dist = pool_get(pool_dist);
|
|
||||||
dist->dist =
|
|
||||||
(b1->vec.x - b2->vec.x) * (b1->vec.x - b2->vec.x) +
|
|
||||||
(b1->vec.y - b2->vec.y) * (b1->vec.y - b2->vec.y) +
|
|
||||||
(b1->vec.z - b2->vec.z) * (b1->vec.z - b2->vec.z);
|
|
||||||
dist->beacon1 = b1;
|
|
||||||
dist->beacon2 = b2;
|
|
||||||
log_f(1, "scanner %lu new dist : %lu (%ld,%ld,%ld) / (%ld,%ld,%ld)\n",
|
|
||||||
scanner - scanners,
|
|
||||||
dist->dist,
|
|
||||||
b1->vec.x, b1->vec.y, b1->vec.z,
|
|
||||||
b2->vec.x, b2->vec.y, b2->vec.z);
|
|
||||||
insert_dist(scanner, dist);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* merge scanner s2 (already translated) beacons into scanner s1.
|
/* merge scanner s2 (already translated) beacons into scanner s1.
|
||||||
* - ignore duplicate beacons
|
* - ignore duplicate beacons
|
||||||
@@ -435,25 +383,6 @@ static int merge_scanner(scanner_t *s1, scanner_t *s2)
|
|||||||
if (insert_unique_beacon(s1, beacon) > 0)
|
if (insert_unique_beacon(s1, beacon) > 0)
|
||||||
add_beacon_dists1(s1, beacon);
|
add_beacon_dists1(s1, beacon);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (beacon->common) {
|
|
||||||
if (!beacon_exists(s1, beacon))
|
|
||||||
log(2, "BUG 1\n");
|
|
||||||
log(2, "common beacon ignored (%ld,%ld,%ld) - count=%d\n",
|
|
||||||
beacon->vec.x, beacon->vec.y, beacon->vec.z, beacon->common);
|
|
||||||
pool_add(pool_beacon, beacon);
|
|
||||||
} else {
|
|
||||||
if (beacon_exists(s1, beacon))
|
|
||||||
log(2, "BUG 2\n");
|
|
||||||
log(2, "add new beacon (%ld,%ld,%ld) - count=%d\n",
|
|
||||||
beacon->vec.x, beacon->vec.y, beacon->vec.z, beacon->common);
|
|
||||||
list_add(cur, &s1->list_beacons);
|
|
||||||
s1->nbeacons++;
|
|
||||||
add_beacon_dists(s1, beacon);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/* free all dists */
|
/* free all dists */
|
||||||
list_for_each_safe(cur, tmp, &s2->list_dists) {
|
list_for_each_safe(cur, tmp, &s2->list_dists) {
|
||||||
dist = list_entry(cur, dist_t, list_dists);
|
dist = list_entry(cur, dist_t, list_dists);
|
||||||
@@ -640,28 +569,6 @@ static int count_common_distances(scanner_t *s1, scanner_t *s2)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For each scanner, calculate square distances between every beacon,
|
|
||||||
* and generate corresponding list.
|
|
||||||
* For N beacons, we will get (N) * (N-1) / 2 distances.
|
|
||||||
*
|
|
||||||
* Note: To find 12 matching beacons between scanners later, we will need
|
|
||||||
* 66 matching distances (= 12 * 11 / 2).
|
|
||||||
*/
|
|
||||||
static void calc_square_distances()
|
|
||||||
{
|
|
||||||
scanner_t *scanner;
|
|
||||||
beacon_t *beacon;
|
|
||||||
|
|
||||||
log_f(1, "nscanners: %d\n", nscanners);
|
|
||||||
for (int i = 0; i < nscanners; ++i) {
|
|
||||||
scanner = scanners + i;
|
|
||||||
list_for_each_entry(beacon, &scanner->list_beacons, list_beacons) {
|
|
||||||
add_beacon_dists(scanner, beacon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scanners_print_dists();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* match all scanners
|
/* match all scanners
|
||||||
*/
|
*/
|
||||||
static void match_scanners()
|
static void match_scanners()
|
||||||
@@ -690,38 +597,6 @@ static void match_scanners()
|
|||||||
scanners_print_dists();
|
scanners_print_dists();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void match_scanners1()
|
|
||||||
{
|
|
||||||
int finished = 0;
|
|
||||||
|
|
||||||
scanners[0].adjusted = 1;
|
|
||||||
log_f(1, "nscanners=%d\n", nscanners);
|
|
||||||
while (!finished) {
|
|
||||||
finished = 1;
|
|
||||||
for (int i = 0; i < nscanners - 1; ++i) {
|
|
||||||
if (!scanners[i].adjusted) /* skip un-translated scanners */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (int j = i+1; j < nscanners; ++j) {
|
|
||||||
if (i == j || scanners[j].adjusted) /* already translated */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int count = count_common_distances(scanners + i, scanners + j);
|
|
||||||
log(1, "common(%d, %d) = %d\n", i, j, count);
|
|
||||||
if (count >= 66) {
|
|
||||||
adjust_scanner(scanners + i, scanners + j);
|
|
||||||
scanners_print_refs(scanners + i, scanners + j);
|
|
||||||
|
|
||||||
//merge_scanner(scanners + i, scanners + j);
|
|
||||||
finished = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scanners_print_dists();
|
|
||||||
//scanners_print_dists(scanners + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read input
|
/* read input
|
||||||
*/
|
*/
|
||||||
static int scanners_read()
|
static int scanners_read()
|
||||||
@@ -771,7 +646,30 @@ static s64 part1()
|
|||||||
|
|
||||||
static s64 part2()
|
static s64 part2()
|
||||||
{
|
{
|
||||||
return list_last_entry(&(*scanners).list_beacons, beacon_t, list_beacons)->manhattan;
|
vector_t *v1, *v2;
|
||||||
|
s64 max = 0, cur;
|
||||||
|
|
||||||
|
for (int i = 0; i < nscanners; ++i) {
|
||||||
|
v1 = &scanners[i].rel;
|
||||||
|
for (int j = i + 1; j < nscanners; ++j) {
|
||||||
|
v2 = &scanners[j].rel;
|
||||||
|
cur = labs(v2->x - v1->x)
|
||||||
|
+ labs(v2->y - v1->y)
|
||||||
|
+ labs(v2->z - v1->z);
|
||||||
|
log(3, "dist(%d, %d)=%ld (%ld,%ld,%ld) / (%ld,%ld,%ld)\n",
|
||||||
|
i, j, cur,
|
||||||
|
v1->x, v1->y, v1->z,
|
||||||
|
v2->x, v2->y, v2->z);
|
||||||
|
if (cur > max) {
|
||||||
|
max = cur;
|
||||||
|
log(3, "new max(%d, %d)=%ld (%ld,%ld,%ld) / (%ld,%ld,%ld)\n",
|
||||||
|
i, j, max,
|
||||||
|
v1->x, v1->y, v1->z,
|
||||||
|
v2->x, v2->y, v2->z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage(char *prg)
|
static int usage(char *prg)
|
||||||
|
Reference in New Issue
Block a user