Skip to content

Instantly share code, notes, and snippets.

@ihabunek
Last active December 19, 2018 12:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ihabunek/3ce189a597e207ee9f35ad2d5e82bcb6 to your computer and use it in GitHub Desktop.
Save ihabunek/3ce189a597e207ee9f35ad2d5e82bcb6 to your computer and use it in GitHub Desktop.

Advent of code 2019, day19

Annotated assembler code, program translated to python.

Registers

Aliases used in pseudocode & python shown in parenthesis.

r0 (r) - result accumulator
r1 (x) - inner counter
r2     - temporary values
r3 (n) - target value for counters
r4     - instruction pointer
r5 (y) - outer counter

Annotated program

 0  addi 4 16 4  # JMP 17

### Calculate result
 1  seti 1 2 5   # r5 = 1                   | y = 1
 2  seti 1 1 1   # r1 = 1                   | x = 1
 3  mulr 5 1 2   # r2 = r5 * r1             \
 4  eqrr 2 3 2   # r2 = (r2 == r3) ? 1 : 0   | if (y * x) == n:
 5  addr 2 4 4   # JMP +r2                   |   result += y
 6  addi 4 1 4   # JMP +1                    |
 7  addr 5 0 0   # r0 = r5 + r0             /
 8  addi 1 1 1   # r1 = r1 + 1              | x += 1
 9  gtrr 1 3 2   # r2 = (r1 > r3) ? 1 : 0   \
10  addr 4 2 4   # JMP +r2                   | if x <= n: JMP 3
11  seti 2 4 4   # JMP 3                    /
12  addi 5 1 5   # r5 = r5 + 1              | y += 1
13  gtrr 5 3 2   # r2 = (r5 > r3) ? 1 : 0   \
14  addr 2 4 4   # JMP +r2                   | if y <= n: JMP 2
15  seti 1 8 4   # JMP 2                    /
16  mulr 4 4 4   # JMP 256                  | HALT

### Initial setup
17  addi 3 2 3   # r3 = r3 + 2                          \
18  mulr 3 3 3   # r3 = r3 * r3                          | (assuming r2 = r3 = 0)
19  mulr 4 3 3   # r3 = r4 * r3 = 19 * r3                |
20  muli 3 11 3  # r3 = r3 * 11                          | r3 = 11 * 19 * (r3 + 2)^2 + 22 * (r2 + 4) + 6
21  addi 2 4 2   # r2 = r2 + 4                           |    = 11 * 19 * 4 + 22 * 4 + 6
22  mulr 2 4 2   # r2 = r2 * r4 = r2 * 22                |    = 930
23  addi 2 6 2   # r2 = r2 + 6                           |
24  addr 3 2 3   # r3 = r2 + r3                         /
25  addr 4 0 4   # JMP +r0                              | if r0 == 0: (part 1)
26  seti 0 8 4   # JMP 1                                |   JMP 1
27  setr 4 1 2   # r2 = r4 = 27                          \
28  mulr 2 4 2   # r2 = r2 * r4 = 27 * 28 = 756           |
29  addr 4 2 2   # r2 = r4 + r2 = 29 + 756 = 785          |
30  mulr 4 2 2   # r2 = r4 * r2 = 30 * 785 = 23550        | r3 = r3 + 10550400
31  muli 2 14 2  # r2 = r2 * 14 = 23550 * 14 = 329700     |    = 930 + 10550400
32  mulr 2 4 2   # r2 = r2 * r4 = 329700 * 32 = 10550400  |    = 10551330
33  addr 3 2 3   # r3 = r3 + r2 = r3 + 10550400          /
34  seti 0 0 0   # r0 = 0                                | clear r0 (used to store the result)
35  seti 0 0 4   # JMP 1                                 | go to calculation

Logic

The inital setup populates r3 (alias n) to 930 for part 1 and to 10551330 for part 2.

The calculation contains two nested loops where:

  • outer counter y goes 1..(n + 1)
  • inner counter x goes 1..(n + 1)

At any point, if x * y == n, y is added to the result.

Converted to Python

n = 930

if part2:
    n += 10550400

r = 0
for x in range(1, n + 2):
    for y in range(1, n + 2):
        if x * y == n:
            r += y

print(r)

Conclusion

The condition is true if x and y are factors of n. Therefore this program returns a sum of all factors of n.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment