AI算法测试题spiral memory

本文介绍了一种名为螺旋存储的独特内存布局方式,数据以逆时针螺旋形式递增存储于二维网格上。文章详细解析了如何计算任意数据点到网格中心的距离,即所谓的“曼哈顿距离”,并提供了Python代码实现,帮助理解螺旋存储的数学规律。

 

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

 

 

 

在Matlab中,`spiral` 算法常用于生成螺旋矩阵。螺旋矩阵是指一个呈螺旋状的矩阵,它的元素从矩阵的左上角开始,按照顺时针螺旋顺序依次排列。 ### 实现方法 Matlab 本身提供了 `spiral` 函数来生成螺旋矩阵。该函数的基本语法为: ```matlab A = spiral(n) ``` 其中,`n` 是一个正整数,表示矩阵的阶数,即矩阵的行数和列数;`A` 是生成的 `n` 阶螺旋矩阵。 ### 使用示例 以下是使用 `spiral` 函数生成不同阶数螺旋矩阵的示例代码: ```matlab % 生成 3 阶螺旋矩阵 A = spiral(3) % 生成 4 阶螺旋矩阵 B = spiral(4) % 生成 5 阶螺旋矩阵 C = spiral(5) ``` 在上述代码中,分别生成了 3 阶、4 阶和 5 阶的螺旋矩阵,并将它们存储在变量 `A`、`B` 和 `C` 中。运行代码后,Matlab 命令窗口将显示生成的螺旋矩阵。 ### 手动实现螺旋矩阵生成 除了使用 Matlab 自带的 `spiral` 函数,还可以手动实现螺旋矩阵的生成。以下是一个手动实现的示例代码: ```matlab function A = mySpiral(n) A = zeros(n); num = 1; top = 1; bottom = n; left = 1; right = n; while top <= bottom && left <= right % 从左到右填充顶部行 for col = left:right A(top, col) = num; num = num + 1; end top = top + 1; % 从上到下填充右侧列 for row = top:bottom A(row, right) = num; num = num + 1; end right = right - 1; % 从右到左填充底部行 if top <= bottom for col = right:-1:left A(bottom, col) = num; num = num + 1; end bottom = bottom - 1; end % 从下到上填充左侧列 if left <= right for row = bottom:-1:top A(row, left) = num; num = num + 1; end left = left + 1; end end end % 调用自定义函数生成 4 阶螺旋矩阵 D = mySpiral(4) ``` 在上述代码中,定义了一个名为 `mySpiral` 的函数,用于手动生成螺旋矩阵。该函数通过循环控制矩阵的填充顺序,从矩阵的顶部行开始,按照顺时针螺旋顺序依次填充元素。最后,调用该函数生成一个 4 阶螺旋矩阵,并将其存储在变量 `D` 中。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值