day10.c (4039B)
1 #include <stdio.h> 2 #include <stdbool.h> 3 #include <stdlib.h> 4 #include <limits.h> 5 #include <inttypes.h> 6 #include <glpk.h> 7 #include "cputime.h" 8 9 #define BUF_SIZE 256 10 #define MAX_TRIES 20 11 12 static int btoi(int bufl, char buf[bufl]) { 13 int num = 0; 14 for (int i=0;i<bufl;++i) num = num*10+(buf[i]-'0'); 15 return num; 16 } 17 18 typedef struct { 19 uint16_t indicators; 20 int buttons_l; 21 uint16_t buttons[16]; 22 int joltages_l; 23 int joltages[16]; 24 } Machine; 25 26 static void m_indicators_add(Machine *m, int bufl, char buf[bufl]) { 27 for (int i=0;i<bufl;++i) 28 if (buf[i]=='#') 29 m->indicators |= 1<<i; 30 } 31 32 static void m_buttons_add(Machine *m, int bufl, char buf[bufl]) { 33 int b = m->buttons_l++; 34 for (int i=0;i<bufl;++i) 35 m->buttons[b] |= 1<<(buf[i]-'0'); 36 } 37 38 static void m_joltage_add(Machine *m, int jolt) { 39 m->joltages[m->joltages_l++] = jolt; 40 } 41 42 static bool try_combination(Machine *m, int comb_l, uint16_t comb[comb_l], int p) { 43 if (p==comb_l) { 44 uint16_t c = 0; 45 for (int i=0;i<comb_l;++i) c ^= comb[i]; 46 return m->indicators==c; 47 } 48 for (int i=0;i<m->buttons_l;++i) { 49 uint16_t btn = m->buttons[i]; 50 if (p>0&&comb[p-1]==btn) continue; // do not press same button twice in a row 51 comb[p] = btn; 52 if (try_combination(m, comb_l, comb, p+1)) return true; 53 } 54 return false; 55 } 56 57 static int64_t solve_glpk(Machine *m) { 58 int btnl = m->buttons_l; 59 int cntl = m->joltages_l; 60 int matbc[btnl][cntl]; // matrix of buttons/counters 61 for (int b=0;b<btnl;++b) { 62 for (int c=0;c<cntl;++c) { 63 uint16_t i = 1<<c; 64 matbc[b][c] = (m->buttons[b]&i)==0 ? 0 : 1; 65 } 66 } 67 68 glp_prob *prob = glp_create_prob(); 69 glp_set_prob_name(prob, "aoc2025_d10p2"); 70 glp_set_obj_dir(prob, GLP_MIN); 71 72 glp_add_rows(prob, cntl); 73 for (int i=0;i<cntl;++i) { 74 glp_set_row_bnds(prob, i+1, GLP_FX, m->joltages[i], 0); 75 } 76 glp_add_cols(prob, btnl); 77 for (int i=0;i<btnl;++i) { 78 glp_set_col_bnds(prob, i+1, GLP_LO, 0.0, 0.0); 79 glp_set_col_kind(prob, i+1, GLP_IV); 80 glp_set_obj_coef(prob, i+1, 1.0); 81 } 82 int ia[btnl*cntl+1]; // GLPK counts arrays from 1 83 int ja[btnl*cntl+1]; 84 double ar[btnl*cntl+1]; 85 int k = 1; 86 for (int i=1;i<=cntl;++i) { 87 for (int j=1;j<=btnl;++j) { 88 ia[k] = i; 89 ja[k] = j; 90 ar[k++] = matbc[j-1][i-1]; 91 } 92 } 93 glp_load_matrix(prob, btnl*cntl, ia, ja, ar); 94 glp_iocp param; 95 glp_init_iocp(¶m); 96 param.msg_lev = GLP_MSG_OFF; 97 param.presolve = GLP_ON; 98 glp_intopt(prob, ¶m); 99 int64_t ret = glp_mip_obj_val(prob); 100 glp_delete_prob(prob); 101 return ret; 102 } 103 104 int main(void) { 105 Machine machines[180] = {0}; 106 int machines_l = 0; 107 char buf[BUF_SIZE] = {0}; 108 int bufl = 0; 109 bool parse_joltages = false; 110 for (int c=getchar();c!=EOF;c=getchar()) { 111 if (c==']') { 112 m_indicators_add(&machines[machines_l], bufl, buf); 113 bufl = 0; 114 } 115 else if (c==')') { 116 m_buttons_add(&machines[machines_l], bufl, buf); 117 bufl = 0; 118 } 119 else if ((c>='0'&&c<='9')||c=='.'||c=='#') { 120 buf[bufl++] = c; 121 } else if (c=='\n') { 122 machines_l++; 123 bufl = 0; 124 parse_joltages = false; 125 } else if (c=='{') { 126 parse_joltages = true; 127 } else if (parse_joltages&&(c==','||c=='}')) { 128 int jolt = btoi(bufl, buf); 129 m_joltage_add(&machines[machines_l], jolt); 130 bufl = 0; 131 } 132 } 133 int64_t part1 = 0; 134 int64_t part2 = 0; 135 for (int i=0;i<machines_l;++i) { 136 for (int j=1;j<=MAX_TRIES;++j) { 137 uint16_t comb[j]; 138 if (try_combination(&machines[i], j, comb, 0)) { 139 part1 += j; 140 break; 141 } 142 } 143 part2 += solve_glpk(&machines[i]); 144 } 145 printf("p1: %"PRIi64"\np2: %"PRIi64"\n", part1, part2); 146 return 0; 147 }