Skip to content

Commit 0faabf9

Browse files
authored
Create Day3.java
1 parent e4c7397 commit 0faabf9

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed

Day3.java

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import java.util.Arrays;
2+
3+
/**
4+
* --- Day 3: Spiral Memory ---
5+
*
6+
* You come across an experimental new kind of memory stored on an infinite
7+
* two-dimensional grid.
8+
*
9+
* Each square on the grid is allocated in a spiral pattern starting at a
10+
* location marked 1 and then counting up while spiraling outward. For example,
11+
* the first few squares are allocated like this:
12+
*
13+
* 17 16 15 14 13
14+
* 18 5 4 3 12
15+
* 19 6 1 2 11
16+
* 20 7 8 9 10
17+
* 21 22 23---> ...
18+
*
19+
* While this is very space-efficient (no squares are skipped), requested data must be
20+
* carried back to square 1 (the location of the only access port for this
21+
* memory system) by programs that can only move up, down, left, or right. They
22+
* always take the shortest path: the Manhattan Distance between the location of
23+
* the data and square 1.
24+
*
25+
* For example:
26+
*
27+
* Data from square 1 is carried 0 steps, since it's at the access port.
28+
* Data from square 12 is carried 3 steps, such as: down, left, left.
29+
* Data from square 23 is carried only 2 steps: up twice.
30+
* Data from square 1024 must be carried 31 steps.
31+
*/
32+
public class Day3 {
33+
34+
public static int part1(int n) {
35+
// closes AxA location to n in grid
36+
int r = (int) Math.ceil(Math.sqrt(n));
37+
int nextFull = r * r;
38+
int distToOne = r - 1;
39+
40+
if (nextFull == n) {
41+
return distToOne;
42+
}
43+
44+
// Will be distToOne or distToOne + 1
45+
int halfway = nextFull - distToOne;
46+
int halfwayDistToOne = distToOne + (r + 1) % 2;
47+
48+
if (halfway == n) {
49+
return halfwayDistToOne;
50+
}
51+
52+
if (halfway > n) {
53+
// bump to same row as square
54+
int diff = halfway - n;
55+
n = halfway + diff;
56+
}
57+
58+
// Same column as square
59+
int i = 0;
60+
while (halfway + i != n && nextFull - i != n) {
61+
i++;
62+
}
63+
return halfwayDistToOne - i;
64+
}
65+
66+
/**
67+
* --- Part Two ---
68+
*
69+
* As a stress test on the system, the programs here clear the grid and then
70+
* store the value 1 in square 1. Then, in the same allocation order as shown
71+
* above, they store the sum of the values in all adjacent squares, including
72+
* diagonals. <br>
73+
* So, the first few squares' values are chosen as follows: <br>
74+
* Square 1 starts with the value 1. <br>
75+
* Square 2 has only one adjacent filled square (with value 1), so it also stores 1. <br>
76+
* Square 3 has both of the above squares as neighbors and stores the sum of their values, 2. <br>
77+
* Square 4 has all three of the aforementioned squares as neighbors and stores the sum of their values, 4. <br>
78+
* Square 5 only has the first and fourth squares as neighbors, so it gets the value 5. <br>
79+
*
80+
* Once a square is written, its value does not change. Therefore, the first
81+
* few squares would receive the following values: <br>
82+
*
83+
* 147 142 133 122 59
84+
* 304 5 4 2 57
85+
* 330 10 1 1 54
86+
* 351 11 23 25 26
87+
* 362 747 806---> ...
88+
*
89+
*/
90+
public static long part2(int n) {
91+
// base case
92+
if(n < 3) {
93+
return 1;
94+
}
95+
96+
long[] grid = new long[n];
97+
Arrays.fill(grid, -1);
98+
99+
// base case
100+
grid[0] = 1;
101+
grid[1] = 1;
102+
103+
long sum = gridSum(n, grid);
104+
System.out.println(n + " : " + sum);
105+
return sum;
106+
}
107+
108+
109+
private static long gridSum(int n, long[] grid) {
110+
if (grid[n-1] != -1) {
111+
return grid[n-1];
112+
}
113+
114+
// Always need this
115+
grid[n-1] = gridSum(n - 1, grid);
116+
117+
// closes AxA location to n in grid
118+
int r = (int) Math.ceil(Math.sqrt(n));
119+
int closestSquareToN = r * r;
120+
121+
// Corner
122+
if (n == closestSquareToN) {
123+
int diagPos = n == 4 ? 1 : (r - 2) * (r - 2);
124+
grid[n-1] += gridSum(diagPos, grid);
125+
grid[n-1] += gridSum(diagPos + 1, grid);
126+
return grid[n-1];
127+
}
128+
129+
int halfwayDiagDistance = (r * r - (r - 2) * (r - 2) - 2);
130+
131+
// Adj square corner
132+
int prevSquare = (r - 1) * (r - 1);
133+
if(n == prevSquare + 1) {
134+
grid[n-1] += gridSum(n - halfwayDiagDistance + 2, grid);
135+
return grid[n-1];
136+
}
137+
138+
// Adj square corner
139+
if(n == prevSquare + 2) {
140+
int adjPos = n - halfwayDiagDistance + 1;
141+
grid[n-1] += gridSum(prevSquare, grid);
142+
grid[n-1] += gridSum(adjPos, grid);
143+
if(n > 6) {
144+
grid[n-1] += gridSum(adjPos + 1, grid);
145+
}
146+
return grid[n-1];
147+
}
148+
149+
// Corner
150+
int halfway = closestSquareToN - (r - 1);
151+
int diagPos = halfway - halfwayDiagDistance;
152+
if (n == halfway) {
153+
grid[n-1] += gridSum(diagPos, grid);
154+
return grid[n-1];
155+
}
156+
157+
// Adj halfway corner
158+
if(n == halfway + 1) {
159+
grid[n-1] += gridSum(diagPos, grid);
160+
grid[n-1] += gridSum(diagPos + 1, grid);
161+
grid[n-1] += gridSum(n - 2, grid);
162+
return grid[n-1];
163+
}
164+
165+
// Adj halfway corner
166+
if(n == halfway - 1) {
167+
grid[n-1] += gridSum(diagPos, grid);
168+
grid[n-1] += gridSum(diagPos - 1, grid);
169+
return grid[n-1];
170+
}
171+
172+
// Middle of an edge
173+
int adj = halfwayDiagDistance;
174+
if (n < halfway) {
175+
adj--;
176+
} else {
177+
adj++;
178+
}
179+
int adjN = n - adj;
180+
grid[n - 1] += gridSum(adjN, grid);
181+
grid[n - 1] += gridSum(adjN + 1, grid);
182+
grid[n - 1] += gridSum(adjN - 1, grid);
183+
184+
return grid[n-1];
185+
}
186+
}

0 commit comments

Comments
 (0)