part2.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <assert.h>
  6. #include "vec.h"
  7. #include "str.h"
  8. #include "map.h"
  9. void* read_input() {
  10. FILE* fp = fopen("./input", "r");
  11. void *vec = new_vec();
  12. while(1) {
  13. char *line = fgetline(fp);
  14. if (line == NULL) break;
  15. char *stripped = str_strip(line);
  16. if (strlen(stripped) == 0) break;
  17. vec_push_back(vec, stripped);
  18. }
  19. return vec;
  20. }
  21. typedef struct {
  22. int line;
  23. int column;
  24. int value;
  25. int length;
  26. } num_t;
  27. char *compose_key(int x, int y) {
  28. void* ss = new_ss();
  29. ss_add(ss, "%d,%d", x, y);
  30. return ss_cstr(ss);
  31. }
  32. void *parse_nums(void *schema) {
  33. void *nums = new_vec();
  34. int j = 0;
  35. const int IN_NUM = 0, IDLE = 1;
  36. int state = IDLE;
  37. for (int i = 0; i < vec_size(schema); i++) {
  38. char *line = vec_get(schema, i);
  39. int line_len = strlen(line);
  40. int value = 0;
  41. int length = 0;
  42. state = IDLE;
  43. j = 0;
  44. while (1) {
  45. char c = '.';
  46. if (j < line_len) c = line[j];
  47. if (state == IDLE) {
  48. if (isdigit(c)) {
  49. state = IN_NUM;
  50. continue;
  51. } else {
  52. j++;
  53. if (j >= line_len) break;
  54. continue;
  55. }
  56. } else if (state == IN_NUM) {
  57. if (isdigit(c)) {
  58. value = value * 10 + (c - '0');
  59. length++;
  60. j++;
  61. continue;
  62. } else {
  63. num_t *n = malloc(sizeof(num_t));
  64. *n = (num_t){
  65. .line = i,
  66. .column = j - length,
  67. .value = value,
  68. .length = length
  69. };
  70. vec_push_back(nums, n);
  71. value = 0;
  72. length = 0;
  73. state = IDLE;
  74. if (j >= line_len) break;
  75. continue;
  76. }
  77. }
  78. }
  79. }
  80. return nums;
  81. }
  82. char char_at(void *schema, int line, int column) {
  83. char *buf = vec_get(schema, line);
  84. return buf[column];
  85. }
  86. void mark_asterisks(void *asterisks, num_t *num, int x, int y) {
  87. const char *key = compose_key(x, y);
  88. void *num_list = dict_get(asterisks, key);
  89. if (num_list == NULL) {
  90. num_list = new_vec();
  91. dict_set(asterisks, key, num_list);
  92. }
  93. vec_push_back(num_list, num);
  94. }
  95. void find_asterisks(void *schema, void *asterisks, num_t *num) {
  96. int line_len = vec_size(schema);
  97. int col_len = strlen(vec_get(schema, 0));
  98. for (int i = num->column - 1; i < num->column + num->length + 1; i++) {
  99. if (num->line - 1 < 0) continue;
  100. if (i < 0 || i >= col_len) continue;
  101. char c = char_at(schema, num->line - 1, i);
  102. if (c == '*') mark_asterisks(asterisks, num, num->line - 1, i);
  103. }
  104. for (int i = num->column - 1; i < num->column + num->length + 1; i++) {
  105. if (num->line + 1 >= line_len) continue;
  106. if (i < 0 || i >= col_len) continue;
  107. char c = char_at(schema, num->line + 1, i);
  108. if (c == '*') mark_asterisks(asterisks, num, num->line + 1, i);
  109. }
  110. if (num->column - 1 >= 0) {
  111. char c = char_at(schema, num->line, num->column - 1);
  112. if (c == '*') mark_asterisks(asterisks, num, num->line, num->column - 1);
  113. }
  114. if (num->column + num->length < col_len) {
  115. char c = char_at(schema, num->line, num->column + num->length);
  116. if (c == '*') mark_asterisks(asterisks, num, num->line, num->column + num->length);
  117. }
  118. }
  119. int main() {
  120. void *schema = read_input();
  121. void *nums = parse_nums(schema);
  122. int sum = 0;
  123. void *asterisks = new_dict();
  124. for (int i = 0; i < vec_size(nums); i++) {
  125. num_t *num = vec_get(nums, i);
  126. find_asterisks(schema, asterisks, num);
  127. }
  128. for (void *iter = dict_begin(asterisks);
  129. iter != NULL;
  130. iter = dict_next(asterisks, iter)) {
  131. void *list = dict_iter_value(iter);
  132. if (vec_size(list) == 2) {
  133. num_t* n1 = vec_get(list, 0);
  134. num_t* n2 = vec_get(list, 1);
  135. sum += n1->value * n2->value;
  136. }
  137. }
  138. printf("%d\n", sum);
  139. return 0;
  140. }