Advertisement
Marrin

day06.c

Jan 14th, 2016
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.58 KB | None | 0 0
  1. #include <ctype.h>
  2. #include <stdbool.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include <time.h>
  7.  
  8. #include "switching.h"
  9.  
  10. #define MAX_LINE_LENGTH 80
  11. #define MAX_COMMANDS    500
  12. #define GRID_SIZE       1000
  13.  
  14. typedef enum {TURN_ON, TURN_OFF, TOGGLE} Opcode;
  15.  
  16. typedef struct Command
  17. {
  18.     uint8_t opcode;
  19.     union {
  20.         uint16_t coordinates[4];
  21.         struct {
  22.             uint16_t x1, y1, x2, y2;
  23.         };
  24.     };
  25.     struct Command *next;
  26. } Command;
  27.  
  28. typedef struct
  29. {
  30.     uint16_t length;
  31.     Command items[MAX_COMMANDS];
  32. } Commands;
  33.  
  34. typedef struct
  35. {
  36.     uint16_t length;
  37.     Command *items[MAX_COMMANDS];
  38. } ActiveCommands;
  39.  
  40. #ifdef DEBUG
  41. static const char *opcode2command[] = {"turn on", "turn off", "toggle"};
  42. #endif
  43.  
  44. static Commands commands;
  45. static Command *row2commands_to_start[GRID_SIZE];
  46. static _Bool row2commands_change[GRID_SIZE + 1];
  47. static _Bool row2just_remove_commands[GRID_SIZE];
  48. static ActiveCommands active_commands;
  49. uint16_t row[GRID_SIZE];
  50.  
  51. /* ------------------------------------------------------------------------ */
  52.  
  53. char* parse_int(char *string, uint16_t *result)
  54. {
  55.     uint16_t value;
  56.  
  57.     while (*string && !isdigit(*string)) ++string;
  58.     if (!isdigit(*string)) return NULL;
  59.  
  60.     value = 0;
  61.     while (isdigit(*string)) {
  62.         value = value * 10 + (*string - '0');
  63.         ++string;
  64.     }
  65.     *result = value;
  66.     return string;
  67. }
  68.  
  69. _Bool parse_line(char *line, Command *result)
  70. {
  71.     uint8_t i;
  72.  
  73.     if (strncmp(line, "turn o", 6) == 0) {
  74.         if (line[6] == 'n' && line[7] == ' ') {
  75.             result->opcode = TURN_ON;
  76.         } else if (line[6] == 'f' && line[7] == 'f' && line[8] == ' ') {
  77.             result->opcode = TURN_OFF;
  78.         } else {
  79.             return false;
  80.         }
  81.     } else if (strncmp(line, "toggle ", 7) == 0) {
  82.         result->opcode = TOGGLE;
  83.     } else {
  84.         return false;
  85.     }
  86.     line += 7;
  87.  
  88.     for (i = 0; i < 4; ++i) {
  89.         line = parse_int(line, &result->coordinates[i]);
  90.         if (!line) return false;
  91.     }
  92.  
  93.     result->next = NULL;
  94.  
  95.     return true;
  96. }
  97.  
  98. _Bool parse_file(FILE *file)
  99. {
  100.     char line[MAX_LINE_LENGTH + 1];
  101.  
  102.     commands.length = 0;
  103.     while (fgets(line, MAX_LINE_LENGTH, file)) {
  104.         if (!parse_line(line, &commands.items[commands.length])) return false;
  105.         ++commands.length;
  106.     }
  107.  
  108.     return true;
  109. }
  110.  
  111. #ifdef DEBUG
  112. void debug_dump_commands(void)
  113. {
  114.     uint16_t i;
  115.     Command *command;
  116.  
  117.     for (i = 0; i < commands.length; ++i) {
  118.         command = &commands.items[i];
  119.         printf(
  120.             "%s %u,%u through %u,%u\n",
  121.             opcode2command[command->opcode],
  122.             command->x1,
  123.             command->y1,
  124.             command->x2,
  125.             command->y2
  126.         );
  127.     }
  128. }
  129. #endif
  130.  
  131. void init_row_lookup_tables(void)
  132. {
  133.     int16_t i;
  134.     uint16_t j;
  135.     Command *command;
  136.  
  137.     memset(row2commands_to_start, 0, sizeof(row2commands_to_start));
  138.     memset(row2commands_change, false, sizeof(row2commands_change));
  139.     memset(row2just_remove_commands, false, sizeof(row2just_remove_commands));
  140.     for (i = commands.length - 1; i > 0; --i) {
  141.         command = &commands.items[i];
  142.         command->next = row2commands_to_start[command->y1];
  143.         row2commands_to_start[command->y1] = command;
  144.         row2commands_change[command->y1] = true;
  145.         row2just_remove_commands[command->y2] = true;
  146.         row2commands_change[command->y2 + 1] = true;
  147.     }
  148.     for (j = 0; j < GRID_SIZE; ++j) {
  149.         row2just_remove_commands[j] = (
  150.             row2just_remove_commands[j] && ! row2commands_change[j]
  151.         );
  152.     }
  153. }
  154.  
  155. /* ------------------------------------------------------------------------ */
  156.  
  157. void ActiveCommands_init(void)
  158. {
  159.     active_commands.length = 0;
  160.     memset(active_commands.items, 0, sizeof(active_commands.items));
  161. }
  162.  
  163. void ActiveCommands_extend(uint16_t row_index)
  164. {
  165.     Command *command;
  166.     uint16_t i;
  167.  
  168.     command = row2commands_to_start[row_index];
  169.     while (command) {
  170.         i = active_commands.length;
  171.         while (i && active_commands.items[i - 1] > command) {
  172.             active_commands.items[i] = active_commands.items[i - 1];
  173.             --i;
  174.         }
  175.         active_commands.items[i] = command;
  176.         ++active_commands.length;
  177.         command = command->next;
  178.     }
  179. }
  180.  
  181. /* ------------------------------------------------------------------------ */
  182.  
  183. #ifndef __CC65__
  184.  
  185. void turn_on(uint16_t i, uint16_t j)
  186. {
  187.     for (; i <= j; ++i) row[i] = 1;
  188. }
  189.  
  190. void turn_off(uint16_t i, uint16_t j)
  191. {
  192.     for (; i <= j; ++i) row[i] = 0;
  193. }
  194.  
  195. void toggle(uint16_t i, uint16_t j)
  196. {
  197.     for (; i <= j; ++i) row[i] = row[i] ^ 1;
  198. }
  199.  
  200. void turn_up(uint16_t i, uint16_t j)
  201. {
  202.     for (; i <= j; ++i) row[i] += 1;
  203. }
  204.  
  205. void turn_double_up(uint16_t i, uint16_t j)
  206. {
  207.     for (; i <= j; ++i) row[i] += 2;
  208. }
  209.  
  210. void turn_down(uint16_t i, uint16_t j)
  211. {
  212.     for (; i <= j; ++i) {
  213.         if (row[i]) row[i] -= 1;
  214.     }
  215. }
  216.  
  217. #endif
  218.  
  219. uint32_t count_lights(CommandFunction *command_functions)
  220. {
  221.     uint16_t row_index, row_result, i, j;
  222.     uint32_t result;
  223.     Command *command;
  224.  
  225.     result = row_result = 0;
  226.     ActiveCommands_init();
  227.     for (row_index = 0; row_index < GRID_SIZE; ++row_index) {
  228.         #ifdef __CC65__
  229.             printf("%u\n%c", row_index, 145);
  230.         #endif
  231.  
  232.         if (row2commands_change[row_index]) {
  233.             ActiveCommands_extend(row_index);
  234.             memset(row, 0, sizeof(row));
  235.             for (i = 0, j = 0; i < active_commands.length; ++i) {
  236.                 command = active_commands.items[i];
  237.                 command_functions[command->opcode](command->x1, command->x2);
  238.                 active_commands.items[j] = command;
  239.                 if (command->y2 != row_index) {
  240.                     ++j;
  241.                 }
  242.             }
  243.             active_commands.length -= i - j;
  244.  
  245.             row_result = 0;
  246.             for (i = 0; i < GRID_SIZE; ++i) {
  247.                 row_result += row[i];
  248.             }
  249.         } else if (row2just_remove_commands[row_index]) {
  250.             for (i = 0, j = 0; i < active_commands.length; ++i) {
  251.                 command = active_commands.items[i];
  252.                 active_commands.items[j] = command;
  253.                 if (command->y2 != row_index) {
  254.                     ++j;
  255.                 }
  256.             }
  257.             active_commands.length -= i - j;            
  258.         }
  259.         result += row_result;
  260.     }
  261.  
  262.     return result;
  263. }
  264.  
  265. int main(void)
  266. {
  267.     clock_t start_time, end_time;
  268.     uint8_t i;
  269.     _Bool ok;
  270.     FILE *file;
  271.     CommandFunction command_functions[][3] = {
  272.         {turn_on, turn_off, toggle},
  273.         {turn_up, turn_down, turn_double_up}
  274.     };
  275.  
  276.     puts("Reading input...");
  277.     start_time = clock();
  278.     file = fopen("input.txt", "r");
  279.     ok = parse_file(file);
  280.     fclose(file);
  281.     init_row_lookup_tables();
  282.     end_time = clock();
  283.     printf(
  284.         "Parsing took %ld seconds.\n", (end_time - start_time) / CLOCKS_PER_SEC
  285.     );
  286.     if (ok) {
  287.         #ifdef DEBUG
  288.         debug_dump_commands();
  289.         #endif
  290.         for (
  291.             i = 0;
  292.             i < (sizeof(command_functions) / sizeof(command_functions[0]));
  293.             ++i
  294.         ) {
  295.             printf("Counting %u...\n", i);
  296.             start_time = end_time;
  297.             printf("\n%lu\n", count_lights(command_functions[i]));
  298.             end_time = clock();
  299.             printf("(%ld seconds)\n", (end_time - start_time) / CLOCKS_PER_SEC);
  300.         }
  301.     } else {
  302.         printf("Parsing error in line %u.\n", commands.length + 1);
  303.     }
  304.  
  305.     return !ok;
  306. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement