~quf/computers-are-fast-2020

computers-are-fast-2020/src/08.c -rw-r--r-- 2.2 KiB
6f56515eLukas Himbert Draw the rest of the fine owl. 1 year, 7 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
#include <string.h>

#define BUFSIZE 10
#define BUFSIZE_S "10"
#define MAX_INS (1<<10)

#define die(...) do { \
    fprintf(stderr, __VA_ARGS__); \
    exit(EXIT_FAILURE); \
  } while (0)

#define die_unless(cond, ...) do { \
    if (!(cond)) { \
      die(__VA_ARGS__); \
    } \
  } while (0)

#define die_if(cond, ...) die_unless(!(cond), __VA_ARGS__)

typedef enum {
  NOP, ACC, JMP,
} op_t;

typedef struct {
  op_t op;
  int arg;
} ins_t;

bool run_until_loop_or_end(const ins_t instructions[], size_t n_instructions, int *acc_ret) {
  size_t ip = 0;
  int acc = 0;
  bool visited[MAX_INS] = { 0, };
  while (ip < n_instructions && !visited[ip]) {
    visited[ip] = true;
    ins_t ins = instructions[ip];
    switch (ins.op) {
      case NOP: ++ip; break;
      case ACC: ++ip; acc += ins.arg; break;
      case JMP: ip += ins.arg; break;
    }
  }
  *acc_ret = acc;
  return (ip >= n_instructions);
}

int main(void) {
  ins_t instructions[1<<10] = { 0, };
  size_t n_ins = 0;

  /* Read input */
  char buf[BUFSIZE+1] = { 0, };
  int ret = 0;
  int n = 0;
  while ((ret = scanf("%"BUFSIZE_S"s %d\n", buf, &n)) > 0) {
    die_if(n_ins + 1 >= sizeof instructions / sizeof *instructions, "Too many instructions.\n");
    if (strcmp(buf, "nop") == 0) {
      instructions[n_ins].op = NOP;
    }
    else if (strcmp(buf, "acc") == 0) {
      instructions[n_ins].op = ACC;
    }
    else if (strcmp(buf, "jmp") == 0) {
      instructions[n_ins].op = JMP;
    }
    else {
      die("Invalid operation: %s.\n", buf);
    }
    instructions[n_ins++].arg = n;
  }
  die_unless(feof(stdin), "Expected_eof.\n");
  die_if(ferror(stdin), "Read error: %s\n", strerror(errno));

  /* Part 1 */
  (void) run_until_loop_or_end(instructions, n_ins, &ret);
  printf("%d\n", ret);

  /* Part 2 */
  for (size_t i = 0; i < n_ins; ++i) {
    ins_t ins = instructions[i];
    if (ins.op == NOP) {
      instructions[i].op = JMP;
    }
    else if (ins.op == JMP) {
      instructions[i].op = NOP;
    }
    else {
      continue;
    }
    if (run_until_loop_or_end(instructions, n_ins, &ret)) {
      printf("%d\n", ret);
      return EXIT_SUCCESS;
    }
    instructions[i].op = ins.op;
  }
  die("No termination.\n");
}