From 4dbcc30dc346854a44c49d73e50916732f91defe Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Tue, 5 Apr 2022 13:20:13 +0200 Subject: [PATCH] first try of A* move sorting --- 2021/day23/aoc-c.c | 222 ++++++++++++++++++++++++--------------------- 1 file changed, 119 insertions(+), 103 deletions(-) diff --git a/2021/day23/aoc-c.c b/2021/day23/aoc-c.c index 40a57d6..5f4895a 100644 --- a/2021/day23/aoc-c.c +++ b/2021/day23/aoc-c.c @@ -60,6 +60,15 @@ typedef struct pos { struct list_head list; } pos_t; +/* All possible moves between hallway and rooms + */ +typedef struct { + uint mask; /* blocking spaces */ + uint dist; +} possible_move_t; + +static possible_move_t moves[24][24]; + typedef struct hash { u64 zobrist; /* zobrist hash */ u32 amp[4]; @@ -145,6 +154,32 @@ static s32 room_exit[4][2][6] = { } }; +static char *int2bin(u32 mask) +{ + static char ret[64]; + + for (int i = 0; i < 32; ++i) { + ret[31-i] = mask & BIT(i)? '1': '0'; + } + ret[32] = 0; + return ret; +} + +static char *int2pos(u32 mask) +{ + static char res[1024]; + char *p = res; + + for (int i = 0; i < 32; ++i) { + if (mask & BIT(i)) { + *p++ = ' '; + strcpy(p, cells[i]); + p += 2; + } + } + return res; +} + static void moves_print(move_t *moves, int nmoves) { for (int i = 0; i < nmoves; ++i) @@ -422,72 +457,77 @@ static u64 hash(pos_t *pos, int amp, u32 from, u32 to) return zobrist; } -/* evaluate current position. - * - * -*/ -static u32 eval(pos_t *pos, int amp, u32 from, u32 to) +/* evaluate current position : + * eval = cost + eval_to_dest + * cost is current cost + * eval is cost to join top of destination room + */ +static int room2room_dist[][4] = { + { 4, 4, 6, 8}, { 4, 4, 4, 6}, { 6, 4, 4, 4}, { 8, 6, 4, 4} +}; + +/* static u64 eval_amp(pos_t *pos, int amp, u32 cell) */ +/* { */ +/* u32 bit = BIT(cell); */ +/* int rows = popcount32(pos->amp[0]); */ +/* int dist; */ +/* int left = rows - popcount32(rooms[amp] & pos->final); */ + +/* if (ROOM(bit)) { /\* in a room *\/ */ +/* int curroom = cell / 4 - 2; */ + +/* dist = cell % 4; /\* distance to top of room *\/ */ +/* dist += room2room_dist[curroom][amp]; */ +/* dist += --left; /\* distance to final room *\/ */ +/* log(1, "eval %c room(%s) = %d\n", amp + 'A', cells[cell], dist); */ +/* } else { /\* in hallway *\/ */ +/* int dest = (amp + 2) * 4; */ +/* dist = moves[cell][dest].dist; */ +/* dist += --left; /\* distance to final room *\/ */ +/* log(1, "eval %c hallway(%s) = %d\n", amp + 'A', cells[cell], dist); */ +/* } */ +/* return cost[amp] * dist; */ +/* } */ + +static u64 eval(pos_t *pos) { - log_f(1, "pos=%p amp=%d from=%u to=%u\n", pos, amp, from, to); - return 1; -} + u32 amp, tmp; + int cell; + int rows = popcount32(pos->amp[0]); + u64 eval = 0; -static char *int2bin(u32 mask) -{ - static char ret[64]; + for (amp = A; amp <= D; ++amp) { + u32 todo = pos->amp[amp] & ~pos->final; /* ignore finished ones */ + int destroom = amp, dist; + int left = rows - popcount32(rooms[destroom] & pos->final); - for (int i = 0; i < 32; ++i) { - ret[31-i] = mask & BIT(i)? '1': '0'; - } - ret[32] = 0; - return ret; -} + printf("amp=%d %u final=%u\n", amp, pos->amp[amp], pos->final); + printf("amp=%c pos=%s\n", amp + 'A', int2bin(pos->amp[amp])); + printf("amp= tod=%s\n", int2bin(todo)); + printf("amp= fin=%s\n", int2bin(pos->final)); + bit_for_each32_2(cell, tmp, todo) { + u32 bit = BIT(cell); + if (ROOM(bit)) { /* in a room */ + int curroom = cell / 4 - 2; -static char *int2pos(u32 mask) -{ - static char res[1024]; - char *p = res; - - for (int i = 0; i < 32; ++i) { - if (mask & BIT(i)) { - *p++ = ' '; - strcpy(p, cells[i]); - p += 2; + dist = cell % 4; /* distance to top of room */ + dist += room2room_dist[curroom][destroom]; + dist += --left; /* distance to final room */ + log(1, "eval %c room(%s) = %d\n", amp + 'A', cells[cell], dist); + } else { /* in hallway */ + int dest = (destroom + 2) * 4; + dist = moves[cell][dest].dist; + dist += --left; /* distance to final room */ + log(1, "eval %c hallway(%s) = %d\n", amp + 'A', cells[cell], dist); + } + //printf("eval = %lu %lu\n", cost[amp] * dist, eval_amp(pos, amp, cell)); + eval += cost[amp] * dist; } } - return res; + //log_f(1, "pos=%p amp=%d from=%u to=%u\n", pos, amp, from, to); + return eval; } -typedef enum { - H1 = BIT(_H1), H2 = BIT(_H2), H3 = (_H3), H4 = (_H4), - H5 = (_H5), H6 = (_H6), H7 = (_H7), - A1 = (_A1), A2 = (_A2), A3 = (_A3), A4 = (_A4), - B1 = (_B1), B2 = (_B2), B3 = (_B3), B4 = (_B4), - C1 = (_C1), C2 = (_C2), C3 = (_C3), C4 = (_C4), - D1 = (_D1), D2 = (_D2), D3 = (_D3), D4 = (_D4), -} space_t; - -/* Steps to move to hallway - */ -typedef enum { - A1H = 1, A2H = 2, A3H = 3, A4H = 4 -} out_t; - -/* Mask which disallow moves to hallway - */ -typedef struct { - uint mask, dist; -} possible_move_t; - -/* Steps to move from space outside room to hallway destination - */ -typedef enum { - AH1 = 2, AH2 = 1, AH3 = 1, AH4 = 3, AH5 = 5, AH6 = 7 , AH7 = 8, - BH1 = 4, BH2 = 3, BH3 = 1, BH4 = 1, BH5 = 3, BH6 = 5 , BH7 = 6, - CH1 = 6, CH2 = 5, CH3 = 3, CH4 = 1, CH5 = 1, CH6 = 3 , CH7 = 4, - DH1 = 8, DH2 = 7, DH3 = 5, DH4 = 3, DH5 = 1, DH6 = 1 , DH7 = 2 -} steps_t; - /* * ############# * #ab.c.d.e.fg# @@ -529,7 +569,6 @@ static pos_t *get_pos(pos_t *from) new->final = new->occupied = new->zobrist = 0; new->cost = new->eval = 0; new->moves = 0; - new->zobrist = 0; } else { *new = *from; } @@ -553,12 +592,26 @@ static void free_pos(pos_t *pos) */ static void push_pos(pos_t *pos) { - if (pos) { - list_add(&pos->list, &pos_queue); - } else { + pos_t *cur; + + if (!pos) { log(1, "Fatal foo\n"); exit(1); } + if (!list_empty(&pos_queue)) { + //list_add_tail(&pos->list, &pos_queue); + //} else { + list_for_each_entry(cur, &pos_queue, list) { + if (cur->eval > pos->eval) { + log(1, "adding %lu before %lu\n", pos->eval, cur->eval); + list_add_tail(&pos->list, &cur->list); + return; + } else { + log(1, "not adding %lu before %lu\n", pos->eval, cur->eval); + } + } + } + list_add_tail(&pos->list, &pos_queue); } /* pop a position from stack @@ -629,10 +682,6 @@ static void mask_print(u32 bits) } -/* generate possible moves between hallway and rooms - */ -static possible_move_t moves[24][24]; - /* calculate distance and move mask for all possible moves * (room -> hallway ans hallway -> room) */ @@ -745,15 +794,6 @@ static pos_t *newmove(pos_t *pos, amphipod_t amp, u32 from, u32 to) } } */ - /* - if ((IN_HALLWAY(from) && !IN_ROOM(to)) || - (IN_ROOM(from) && !IN_HALLWAY(to)) || - (HALLWAY(bit_from) && !ROOM(bit_to)) || - (ROOM(bit_from) && !HALLWAY(bit_to))) { - log(1, "BUG genmove!\n"); - } - */ - zobrist = hash(&pos_tmp, amp, from, to); //if (zobrist != zobrist_1(&pos_tmp)) { // printf("Zobi Fuck1\n"); // exit(1); @@ -763,6 +803,7 @@ static pos_t *newmove(pos_t *pos, amphipod_t amp, u32 from, u32 to) // exit(1); //} //zobrist = hash1(pos); + zobrist = hash(&pos_tmp, amp, from, to); if (ok < rows * 4 - 1) { /* */ if (zobrist == HASH_SEEN) { log(1, "collision, skipping move : "); @@ -770,35 +811,10 @@ static pos_t *newmove(pos_t *pos, amphipod_t amp, u32 from, u32 to) return NULL; } } + pos_tmp.eval = eval(&pos_tmp) + pos_tmp.cost; if (!(newpos = get_pos(&pos_tmp))) return NULL; - //newpos->zobrist = zobrist; - //log(1, "Zobi6 %lu\n", newpos->zobrist); - //newpos->moves_list[newpos->moves].from = from; - //newpos->moves_list[newpos->moves].to = to; - //newpos->moves++; - //newpos->cost = newcost; - - /* - if (HALLWAY(bit_from)) { - newpos->final |= bit_to; - log(1, "Final destination %s, ok=%d, final=%s\n", cells[to], - popcount32(newpos->final), int2pos(newpos->final)); - if (popcount32(newpos->final) == rows * 4) { - log(1, "found solution! cost=%lu\n", newpos->cost); - if (newpos->cost < result) { - result = newpos->cost; - log(1, "New best=%lu moves=%u List:", result, newpos->moves); - log(1, "\n"); - } - free_pos(newpos); - return NULL; - } - - } -*/ - burrow_print_flat(newpos); push_pos(newpos); log(1, "New position: moves=%d cost=%lu\n", newpos->moves, newpos->cost); @@ -1023,6 +1039,6 @@ int main(int ac, char **av) printf("%s : res=%ld\n", *av, part == 1? part1(): part2()); exit(0); - /* for flycheck */ - eval(pos, 1, 1, 1); + /* dummy calls for flycheck */ + eval(pos); }