Created
February 26, 2019 09:15
-
-
Save iphysresearch/9b01fd852469330e070b88785f79cd81 to your computer and use it in GitHub Desktop.
[Spiral Memory]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Spiral Memory | |
# You come across an experimental new kind of memory stored on an infinite two-dimensional grid. | |
# Each square on the grid is allocated in a spiral pattern starting at a location marked 1 and then counting up while spiraling outward. For example, the first few squares are allocated like this: | |
# 17 16 15 14 13 | |
# 18 5 4 3 12 | |
# 19 6 1 2 11 | |
# 20 7 8 9 10 | |
# 21 22 23---> ... | |
# While this is very space-efficient (no squares are skipped), requested data must be carried back to square 1 (the location of the only access port for this memory system) by programs that can only move up, down, left, or right. They always take the shortest path: the Manhattan Distance between the location of the data and square 1. | |
## For example: | |
# Data from square 1 is carried 0 steps, since it's at the access port. Data from square 12 is carried 3 steps, such as: down, left, left. Data from square 23 is carried only 2 steps: up twice. | |
# Data from square 1024 must be carried 31 steps. | |
# How many steps are required to carry the data from the square identified in your puzzle input all the way to the access port? | |
# How to test your answer: | |
# If you input: 100000 Your Answer should be: 173 | |
# If you input: 2345678 Your Answer should be: 1347 | |
# Series | |
def b(n): | |
if n == 1: | |
return 1 | |
else: | |
return b(n-1) +8 | |
# Coordinate | |
def x_plus(n): | |
if n == 1: | |
return 1 | |
else: | |
return x_plus(n-1) + b(n-1) | |
def y_plus(n): | |
if n == 1: | |
return 1 | |
else: | |
return y_plus(n-1) + b(n-1) + 2 | |
def x_minus(n): | |
if n == 1: | |
return 1 | |
else: | |
return x_minus(n-1) + b(n-1) + 4 | |
def y_minus(n): | |
if n == 1: | |
return 1 | |
else: | |
return y_minus(n-1) + b(n-1) + 6 | |
def Q1(x): | |
q = x | |
x = 2000 // 2 # 2000 is the limit for the function x/y_*(n) | |
distanse = x | |
while True: | |
if (q < y_plus(x)) & (q >= x_plus(x)): | |
# print('1st', x, x_plus(x), y_plus(x)) | |
return min(y_plus(x)-q, q-x_plus(x)) + x -1 | |
elif (q < x_minus(x)) & (q >= y_plus(x)): | |
# print('2nd', x, x_minus(x), y_plus(x)) | |
return min(x_minus(x)-q, q-y_plus(x)) + x -1 | |
elif (q < y_minus(x)) & (q >= x_minus(x)): | |
# print('3rd', x, y_minus(x), x_minus(x)) | |
return min(y_minus(x)-q, q-x_minus(x)) + x -1 | |
elif (q < x_plus(x+1)) & (q >= y_minus(x)): | |
# print('4th', x, x_plus(x), y_minus(x+1)) | |
return min(x_plus(x+1)-q, q-y_minus(x)) + x -1 | |
elif q >= x_plus(x+1): | |
# print(x, x_plus(x), y_plus(x), x_minus(x), y_minus(x), x_plus(x+1)) | |
# print('multi') | |
distanse = ( 1 if distanse == 1 else distanse //2 ) | |
x = x + distanse | |
else: | |
# print(x, x_plus(x), y_plus(x), x_minus(x), y_minus(x), x_plus(x+1)) | |
# print('divide') | |
distanse = ( 1 if distanse == 1 else distanse //2 ) | |
x = x - distanse | |
if __name__ == '__main__': | |
print(Q1(1)) | |
print(Q1(12)) | |
print(Q1(23)) | |
print(Q1(1024)) | |
print(Q1(100000)) | |
print(Q1(2345678)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment