AI算法测试题spiral memory

 

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:

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

这道题目是参加培训的一道入门测试题, 同时也来源于2017 edition of Advent of Code的day 3.

大概说明下题目的意图,spiral memory 螺旋存储,以1开始,以逆时针螺旋式递增数字。输入一个数,算出这个数离1有多少步(只能上下左右移动步数),比如12离1有3步(下,左,左),以此类推。

先说结论:目标数字的坐标绝对值的和就是离中心1的步数

首先这道题可以以1为中心作直角坐标系,如下图

首先将每个正方形按照层级划分,1属于第零层,9属于第一层正方形,25属于第二层正方形。所以输入的数字只要知道在第几层就可以算出该数字的坐标(x, y)。

第一步确定目标数字属于第几层

  1. 第一层的最后一位数是9=(2*1+1)^2
  2. 第二层的最后一位数是25=(2*2+1)^2
  3. 第i层的最后一位数是(2*i+1)^2

每一层的最后一个数字都是奇数的平方,所以对目标数字开方来计算判断属于第几层,具体算法看下面python代码:

def getI(number):
    i = 0
    num = int(math.sqrt(number))
    print("num: " + str(num))
    if num % 2 != 0:
        # odd
        i = int((num - 1) / 2)
    else:
        # even
        i = int(num / 2)
    min = int(math.pow(2 * (i - 1) + 1, 2))
    max1 = int(math.pow(2 * i + 1, 2))
    max2 = int(math.pow(2 * (i + 1) + 1, 2))
    if min < number <= max1:
        print("%d<%d<=%d" % (min, number, max1))
        print("i: " + str(i))
        i = i
    elif max1 < number < max2:
        print("%d<%d<=%d" % (max1, number, max2))
        print("i+1: " + str(i + 1))
        i = i + 1
    return i

第二步就要算出y坐标

对于计算y坐标,需要对每一层的数字找到相对应的规律,因为都是正方形,就是每边的数字个数是相同的(8*i/4),每条边对应的坐标规律不一样,比如以x轴水平的边,y坐标不变,x坐标增减。

主要规律如下

  • 每层数字个数(i表示层数):8*i
  • 每边的数字个数:2*i
  • 每层最后一个数字:(2*i+1)^2

以此类推可以算出每条边的数字范围以及坐标:

def getY(i, number):
    n = 2 * i + 1
    nsuq = int(math.pow(n, 2))
    firstN = int(nsuq - 8 * i + 1)
    secondN = int(nsuq - 6 * i)
    thirdN = int(secondN + 1)
    fourN = int(nsuq - 4 * i)
    fiveN = int(fourN + 1)
    sixN = int(nsuq - 2 * i)
    seventN = int(sixN + 1)
    eightN = int(nsuq)
    x = 0
    y = 0
    if firstN <= number <= secondN:
        x = i
        y = i - secondN + number
    elif thirdN <= number <= fourN:
        x = -i + fourN - number
        y = i
    elif fiveN <= number <= sixN:
        x = -i
        y = -i + sixN - number
    elif seventN <= number <= eightN:
        x = i - eightN + number
        y = -i
    return x, y

第i层最后一个数是(2*i+1)^2, 坐标(i,-i)

最后测试结果:

input a number: 1
num: 1
1 needs 0 steps to the center
(x, y): (0, 0)
input a number: 12
num: 3
9<12<=25
i+1: 2
12 needs 3 steps to the center
(x, y): (2, 1)
input a number: 100000
num: 316
99225<100000<=100489
i: 158
100000 needs 173 steps to the center
(x, y): (-158, 15)
input a number: 2345678
num: 1531
2343961<2345678<=2350089
i+1: 766
2345678 needs 1347 steps to the center
(x, y): (581, 766)

耗时测试:

input a number: 1234567890
num: 35136
1234468225<1234567890<=1234608769
i: 17568
1234567890 needs 29393 steps to the center
(x, y): (-17568, -11825)
Consuming Time: 0:00:00.000089


input a number: 2345678
num: 1531
2343961<2345678<=2350089
i+1: 766
2345678 needs 1347 steps to the center
(x, y): (581, 766)
Consuming Time: 0:00:00.000055

代码传送门spiral memory

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值