From ca8de49d5ecc1ea54612fbb486a80378aefe05f5 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Tue, 29 Nov 2022 20:53:07 +0100 Subject: [PATCH] 2020 day 22/2 (C) - clean code --- 2020/RESULTS.txt | 4 ++ 2020/day22/aoc-c.c | 155 +++++++++++++++------------------------------ README.md | 2 +- 3 files changed, 57 insertions(+), 104 deletions(-) diff --git a/2020/RESULTS.txt b/2020/RESULTS.txt index 35a6c7e..2592d66 100644 --- a/2020/RESULTS.txt +++ b/2020/RESULTS.txt @@ -499,6 +499,10 @@ ex2.bash: res=32760 time: 1:21.92 real, 81.89 user, 0.01 sys context-switch: 462+1, page-faults: 0+5135 +aoc-c : res=32760 + time: 0:01.11 real, 1.09 user, 0.01 sys + context-switch: 70+1, page-faults: 0+1933 + ========================================= ================= day23 ================= ========================================= diff --git a/2020/day22/aoc-c.c b/2020/day22/aoc-c.c index 880587e..920e0d1 100644 --- a/2020/day22/aoc-c.c +++ b/2020/day22/aoc-c.c @@ -65,58 +65,26 @@ static __always_inline u32 hash(u32 h) return hash_32(h, HBITS); } -static void print_cards(player_t *players) -{ - struct card *card; - - for (int player = 0; player < 2; ++player) { - int c = 0; - log(2, "Player %d's deck: ", player + 1); - list_for_each_entry(card, &players[player].head, list) { - if (c++) - log(2, ","); - log(2, " %d", card->card); - } - log(2, "\n"); - } -} - static int equal_decks(hash_t *hasht, player_t *new) { - //int i = 0; for (int i = 0; i < 2; ++i) { card_t *c1 = list_first_entry_or_null(&hasht->players[i], card_t, list); card_t *c2 = list_first_entry_or_null(&new[i].head, card_t, list); - log_f(3, "p=%d c1=%p c2=%p", i + 1, c1, c2); - if (!c1 || !c2) { - /* one list is empty and one is not */ - //if ((!c1 && c2) || (c1 && !c2)) { - log(3, "NULL\n"); + if (!c1 || !c2) /* one list (only) is empty */ return 0; - } - log_f(3, "\nplayer=%d ", i + 1); while (!list_entry_is_head(c1, &hasht->players[i], list) && !list_entry_is_head(c2, &new[i].head, list) && c1->card == c2->card) { - log(3, "c1=%d c2=%d ", c1->card, c2->card); - if (c1->card != c2->card) { - log(3, "\n"); + if (c1->card != c2->card) return 0; - } c1 = list_next_entry(c1, list); c2 = list_next_entry(c2, list); } - log(3, "\nd1=%p c1=%p/%d\nd2=%p c2=%p/%d ", - &hasht[i], c1, list_entry_is_head(c1, &hasht->players[i], list), - &new[i], c2, list_entry_is_head(c2, &new[i].head, list)); - //log(3, "\nZOBI\n"); if (!list_entry_is_head(c1, &hasht->players[i], list) || !list_entry_is_head(c2, &new[i].head, list)) return 0; - log(3, "\n"); - //log(3, "\nZOBI\n"); } return 1; } @@ -129,24 +97,12 @@ static hash_t *create_hash(player_t *players, u32 h) hash->zobrist = h; for (int i = 0; i < 2; ++i) { - log_f(4, "player %d: ", i + 1); INIT_LIST_HEAD(&hash->players[i]); list_for_each_entry(card, &players[i].head, list) { struct card *new = pool_get(pool_cards); new->card = card->card; list_add_tail(&new->list, &hash->players[i]); - log(4, "%d ", card->card); } - log(4, "\n"); - } - log_f(3, "hash=%p p1-next=%p p2-next=%p\n", hash, - hash->players[0].next, hash->players[1].next); - for (int i = 0; i < 2; ++i) { - log_f(4, "duped player %d: ", i + 1); - list_for_each_entry(card, &hash->players[i], list) { - log(4, "%d ", card->card); - } - log(4, "\n"); } return hash; } @@ -167,7 +123,6 @@ static player_t *create_subgame(player_t *from, player_t *to) struct card *new = pool_get(pool_cards); new->card = card->card; list_add_tail(&new->list, &to[i].head); - log(4, "%d ", card->card); if (!--ncards) break; } @@ -185,16 +140,10 @@ static hash_t *find_deck(struct hlist_head *hasht, player_t *players) hash_t *cur; u32 z = zobrist(players); u32 h = hash(z); - log_f(3, "zobrist = %u/%u ", z, h); hlist_for_each_entry(cur, hasht + h, hlist) { - log(3, "[%u]\n", cur->zobrist); - if (cur->zobrist == z && equal_decks(cur, players)) { - // && equal_decks(&cur->players[1], &players[1].head)) { - log_f(3, "found\n"); + if (cur->zobrist == z && equal_decks(cur, players)) return cur; - } } - log_f(3, "not found\n"); cur = create_hash(players, z); hlist_add_head(&cur->hlist, &hasht[h]); return NULL; @@ -247,78 +196,91 @@ static void winmove(player_t *winner, player_t *loser) winner->ncards++; } +static long calc_result(player_t *players) +{ + /* we don't need to check for winner, as one list is empty */ + card_t *card; + long res = 0, mult = 1; + list_for_each_entry_reverse(card, &players[0].head, list) + res += card->card * mult++; + list_for_each_entry_reverse(card, &players[1].head, list) + res += card->card * mult++; + return res; +} + static long part1(player_t *players) { int round = 0, winner = 0; while (players[0].ncards > 0 && players[1].ncards > 0) { - winner = 0; + int val[2]; /* we can use list_first_entry() macro, as both lists are not empty */ - int val1 = list_first_entry(&players[0].head, struct card, list)->card; - int val2 = list_first_entry(&players[1].head, struct card, list)->card; - if (val2 > val1) - winner = 1; + val[0] = list_first_entry(&players[0].head, struct card, list)->card; + val[1] = list_first_entry(&players[1].head, struct card, list)->card; + winner = val[1] > val[0]; winmove(players + winner, players + 1 - winner); round++; } - - return winner; + return calc_result(players); } static long part2(player_t *players) { int round = 1, winner = 0, game; + long res = 0; static int maxgame = 0; DEFINE_HASHTABLE(hasht_deck, HBITS); /* htable for dup decks */ + game = ++maxgame; - log(2, "=== Game %d ===\n", game = ++maxgame); while (players[0].ncards > 0 && players[1].ncards > 0) { - int val1, val2; + int val[2]; winner = 0; - log(2, "\n-- Round %d (Game %d) --\n", round, game); - print_cards(players); - - if (find_deck(hasht_deck, players)) { - log(3, "dup found\n"); - goto end; // return winner; - } else { - log(3, "dup not found\n"); - } + if (find_deck(hasht_deck, players)) /* duplicate */ + goto end; /* we can use list_first_entry() macro, as both lists are not empty */ - val1 = list_first_entry(&players[0].head, struct card, list)->card; - val2 = list_first_entry(&players[1].head, struct card, list)->card; - log(2, "Player 1 plays: %d\n", val1); - log(2, "Player 2 plays: %d\n", val2); + val[0] = list_first_entry(&players[0].head, struct card, list)->card; + val[1] = list_first_entry(&players[1].head, struct card, list)->card; - if (players[0].ncards > val1 && players[1].ncards > val2) { + if (players[0].ncards > val[0] && players[1].ncards > val[1]) { player_t sub[2]; - log(2, "Playing a sub-game to determine the winner...\n\n"); winner = part2(create_subgame(players, sub)); - log(2, "\n...anyway, back to game %d\n", game); } else { - if (val2 > val1) - winner = 1; + winner = val[1] > val[0]; } winmove(players + winner, players + 1 - winner); - log(2, "Player %d wins round %d of game %d!\n", winner + 1, round, game); - round++; } end: - log(2, "The winner of game %d is player %d!\n", game, winner + 1); + if (game == 1) + res = calc_result(players); + /* cleanup decks */ - card_t *card, *tmp; - if (game != 1) { + card_t *card, *tmp1; + for (int i = 0; i < 2; ++i) { + list_for_each_entry_safe(card, tmp1, &players[i].head, list) { + list_del(&card->list); + pool_add(pool_cards, card); + } + } + + /* cleanup hashtable */ + ulong bkt; + struct hlist_node *tmp2; + hash_t *obj; + hash_for_each_safe(hasht_deck, bkt, tmp2, obj, hlist) { + /* cleanup hash decks */ for (int i = 0; i < 2; ++i) { - list_for_each_entry_safe(card, tmp, &players[i].head, list) { + list_for_each_entry_safe(card, tmp1, &obj->players[i], list) { list_del(&card->list); pool_add(pool_cards, card); } } + hlist_del(&obj->hlist); + pool_add(pool_hash, obj); } - return winner; + return game == 1? res: winner; } int main(int ac, char **av) @@ -338,26 +300,13 @@ int main(int ac, char **av) } } - pool_cards = pool_create("cards", 128, sizeof(struct card)); + pool_cards = pool_create("cards", 4096, sizeof(struct card)); pool_hash = pool_create("hash", 128, sizeof(struct hash)); zobrist_init(); player_t players[2]; parse(players); - if (part == 1) - part1(players); - else - part2(players); - - /* we don't need to check for winner, as one list is empty */ - log(2, "\n== Post-game results ==\n"); - print_cards(players); - card_t *card; - long res = 0, mult = 1; - list_for_each_entry_reverse(card, &players[0].head, list) - res += card->card * mult++; - list_for_each_entry_reverse(card, &players[1].head, list) - res += card->card * mult++; + long res = part == 1 ? part1(players): part2(players); printf("%s : res=%ld\n", *av, res); exit(0); diff --git a/README.md b/README.md index 4bffbf6..3941ba9 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ - `C`: Days 1-9 #### Advent of Code 2020 - - `C`: Days 1-19, 23-25 + - `C`: Days 1-19, 22-25 - `Bash`: All (days 1-25) - `Cobol`: Day 1 (!!)