2.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <htable.h>
  4. #include <crc32.h>
  5. typedef struct {
  6. int x;
  7. int y;
  8. } Point;
  9. uint32_t point_hash(void *point) {
  10. return crc32(0, point, sizeof(Point));
  11. }
  12. bool point_eq(void *x, void *y) {
  13. Point *a = x, *b = y;
  14. return (a->x == b->x) && (a->y == b->y);
  15. }
  16. typedef struct {
  17. Point knots[10];
  18. } State;
  19. bool is_adjacent(Point p1, Point p2) {
  20. if (abs(p1.x - p2.x) <= 1 && abs(p2.y - p1.y) <= 1) {
  21. return true;
  22. }
  23. return false;
  24. }
  25. Point catchup(Point prev, Point new) {
  26. int dx = new.x - prev.x;
  27. int dy = new.y - prev.y;
  28. int cx = 0, cy = 0;
  29. if (dx > 0) cx = 1;
  30. if (dx < 0) cx = -1;
  31. if (dy > 0) cy = 1;
  32. if (dy < 0) cy = -1;
  33. return (Point){prev.x + cx, prev.y + cy};
  34. }
  35. void run_impl(State *s, HTable *record, int dx, int dy) {
  36. s->knots[0].x += dx;
  37. s->knots[0].y += dy;
  38. for (int i = 1; i < 10; i++) {
  39. if (is_adjacent(s->knots[i], s->knots[i-1])) {
  40. continue;
  41. }
  42. s->knots[i] = catchup(s->knots[i], s->knots[i-1]);
  43. if (i == 9) {
  44. htable_insert(record , &(s->knots[i]));
  45. }
  46. }
  47. }
  48. void run(State *s, HTable *record, char direction, int step) {
  49. int dx, dy;
  50. switch (direction) {
  51. case 'U':
  52. dx = 0; dy = 1;
  53. break;
  54. case 'D':
  55. dx = 0; dy = -1;
  56. break;
  57. case 'L':
  58. dx = -1; dy = 0;
  59. break;
  60. case 'R':
  61. dx = 1; dy = 0;
  62. break;
  63. default:
  64. return;
  65. }
  66. for (int i = 0; i < step; i++) {
  67. run_impl(s, record, dx, dy);
  68. }
  69. }
  70. int count_htable(HTable *ht) {
  71. int count = 0;
  72. for (void *iter = htable_begin(ht);
  73. iter != NULL;
  74. iter = htable_next(ht, iter)) {
  75. Point *p = iter;
  76. count++;
  77. }
  78. return count;
  79. }
  80. int main() {
  81. FILE *fp = fopen("input", "r");
  82. State state = {0};
  83. char direction;
  84. int step;
  85. HTable record;
  86. htable_init(&record, sizeof(Point), -1, point_hash, point_eq);
  87. htable_insert(&record, &state.knots[9]);
  88. while (fscanf(fp, "%c %d", &direction, &step) != EOF) {
  89. run(&state, &record, direction, step);
  90. }
  91. int count = count_htable(&record);
  92. printf("%d\n", count);
  93. return 0;
  94. }