Browse Source

Minor day 11 optimisations

Calculate the power inline so we don't have to repeat the rack ID
etc every time; give in and use 1-based arrays instead of mapping
the 1-base back to 0-base.
master
Chris Smith 5 years ago
parent
commit
d137fdb031
1 changed files with 13 additions and 12 deletions
  1. 13
    12
      day11.nim

+ 13
- 12
day11.nim View File

1
 import math, sequtils, strscans, strutils
1
 import math, sequtils, strscans, strutils
2
 
2
 
3
-func power(serial, x, y: int): int =
4
-    let rackId = x + 10
5
-    (rackId * y + serial) * rackId div 100 mod 10 - 5
6
-
7
 var
3
 var
8
     serial = readFile("data/11.txt").strip.parseInt
4
     serial = readFile("data/11.txt").strip.parseInt
9
-    prefixSum: array[-1..300, array[-1..300, int]]
5
+    prefixSum: array[301, array[301, int]]
10
 
6
 
11
-for x in 0..299:
12
-    for y in 0..299:
7
+for x in 1..300:
8
+    let serialByRack = (x + 10) * serial
9
+    let rackSquared = (x + 10) * (x + 10)
10
+    var tally = serialByRack
11
+    for y in 1..300:
12
+        tally.inc(rackSquared)
13
+        let power = tally div 100 mod 10 - 5
13
         # Construct a prefix sum of the grid: prefixSum[x][y] holds the sum of
14
         # Construct a prefix sum of the grid: prefixSum[x][y] holds the sum of
14
         # all cells in the rectangle from (0,0) to (x,y). We calculate this
15
         # all cells in the rectangle from (0,0) to (x,y). We calculate this
15
         # by adding the current cell to the rectangle above and the rectangle
16
         # by adding the current cell to the rectangle above and the rectangle
16
         # to the left. This results in double-counting the rect between (0,0)
17
         # to the left. This results in double-counting the rect between (0,0)
17
         # and (x-1,y-1), so we subtract that from the result.
18
         # and (x-1,y-1), so we subtract that from the result.
18
-        prefixSum[x][y] = power(serial, x+1, y+1) + prefixSum[x][y-1] +
19
+        prefixSum[x][y] = power + prefixSum[x][y-1] +
19
                             prefixSum[x-1][y] - prefixSum[x-1][y-1]
20
                             prefixSum[x-1][y] - prefixSum[x-1][y-1]
20
 
21
 
21
 var
22
 var
26
 
27
 
27
 for size in 1..300:
28
 for size in 1..300:
28
     let s1 = size - 1
29
     let s1 = size - 1
29
-    for x in 0..300 - size:
30
-        for y in 0..300 - size:
30
+    for x in 1..300 - size:
31
+        for y in 1..300 - size:
31
             # To use the prefix sum to find the value of a rect, we take the
32
             # To use the prefix sum to find the value of a rect, we take the
32
             # value for the lower right corner and subtract the rects to the
33
             # value for the lower right corner and subtract the rects to the
33
             # left and the top. Like when constructing the prefix sum this
34
             # left and the top. Like when constructing the prefix sum this
37
                         prefixSum[x+s1][y-1] + prefixSum[x-1][y-1]
38
                         prefixSum[x+s1][y-1] + prefixSum[x-1][y-1]
38
             if sum > best:
39
             if sum > best:
39
                 best = sum
40
                 best = sum
40
-                bestPos = $(x + 1) & "," & $(y + 1) & "," & $size
41
+                bestPos = $x & "," & $y & "," & $size
41
             if size == 3 and sum > bestThree:
42
             if size == 3 and sum > bestThree:
42
                 bestThree = sum
43
                 bestThree = sum
43
-                bestThreePos = $(x + 1) & "," & $(y + 1)
44
+                bestThreePos = $x & "," & $y
44
 
45
 
45
 echo bestThreePos
46
 echo bestThreePos
46
 echo bestPos
47
 echo bestPos