解題語(yǔ)言不限Java
謎題還有第二部分办素,不過(guò)是留給大家的撞牢,能解出第一題的宙彪,才能寫(xiě)第二題
- Advent of Code Day 1 逆向驗(yàn)證碼
- Advent of Code Day 2 損壞校驗(yàn)和
- Advent of Code Day 3 螺旋內(nèi)存
- Advent of Code Day 4 高熵密碼
- Advevnt of Code Day 5 曲折的蹦床迷宮
- Advent of Code Day 6 內(nèi)存重分配
- Advent of Code Day 7 遞歸馬戲團(tuán)
- Advent of Code Day 8 注冊(cè)表愛(ài)好者
- Advent of Code Day 9 流處理
- Advent of Code Day 10 結(jié)哈希
- Advent of Code Day 11 六邊形迷宮
題目?jī)?nèi)容
You come across an experimental new kind of memory stored on an infinite two-dimensional grid.
你來(lái)到一個(gè)在無(wú)限大的二維矩陣上建立的實(shí)驗(yàn)性內(nèi)存。
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:
在這個(gè)矩陣上等限,每一個(gè)方格都從一個(gè)標(biāo)著1
的原點(diǎn)格按螺旋狀排列向外展開(kāi)爸吮。比如說(shuō),前幾個(gè)方格的位置如圖望门。
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.
這是一個(gè)空間利用率非常高的內(nèi)存形娇,但是需要的數(shù)據(jù)必須能返回原點(diǎn)1
的方格,數(shù)據(jù)只能前后左右的移動(dòng)筹误。內(nèi)存移動(dòng)總是取最近的路徑:距離原點(diǎn)的曼哈頓距離桐早。
For example:
Data from square 1 is carried 0 steps, since it's at the access port.
在1
格的數(shù)據(jù)需要0步,因?yàn)樗呀?jīng)在原點(diǎn)了。
Data from square 12 is carried 3 steps, such as: down, left, left.
在12
格的數(shù)據(jù)需要3步哄酝,下左左
Data from square 23 is carried only 2 steps: up twice.
在23
格的數(shù)據(jù)需要移動(dòng)2步友存,上上
Data from square 1024 must be carried 31 steps.
在1024
格的數(shù)據(jù)要移動(dòng)31步
How many steps are required to carry the data from the square identified in your puzzle input all the way to the access port?
那么從給定的位置移動(dòng)到原點(diǎn)需要多少步
解題思路
終于有些有難度的題目了
讀題可知,本題的主要難度在生成螺旋的序列陶衅。
觀察這個(gè)序列可以發(fā)現(xiàn)
- 從就方格到新方格的移動(dòng)順序總是左屡立,上,右搀军,下侠驯。
- 每次移動(dòng)的距離是不斷增加的,走一格兩次奕巍,走兩個(gè)兩次吟策,以此類推。
所以把這兩個(gè)規(guī)律疊加在一起的止,我們就可以生成一個(gè)可以預(yù)測(cè)的序列:
- 左 | 上 | 右右 | 下下 | 左左左
然后通過(guò)讀題檩坚,我們一個(gè)找到這個(gè)點(diǎn)到原點(diǎn)的曼哈頓距離。其實(shí)曼哈頓距離是指這個(gè)點(diǎn)X坐標(biāo)的絕對(duì)值加上Y坐標(biāo)的絕對(duì)值:
D=|x|+|y|
以下是本人的方法诅福,解法不唯一
- 首先我創(chuàng)建了一個(gè)移動(dòng)序列
Point displacementList[]={new Point(1,0),new Point(0,1),new Point(-1,0),new Point(0,-1)};
這個(gè)序列儲(chǔ)存的4個(gè)移動(dòng)的方向:左(1,0)匾委,上(0,1),右(-1,0)氓润,下(0,-1)赂乐。 - 接下來(lái)應(yīng)該有一個(gè)值來(lái)記錄步長(zhǎng)
int length=1
,因?yàn)檫@個(gè)序列一開(kāi)始就移動(dòng)咖气,所以步長(zhǎng)應(yīng)該從1開(kāi)始挨措。 - 原點(diǎn)我用
Point pointer=new Point(0,0)
表示. - 我用了一個(gè)
ArrayList<Point> points=new ArrayList<Point>()
設(shè)完變量就應(yīng)該組合邏輯了。在主函數(shù)里:
- 應(yīng)該有一個(gè)for循環(huán)來(lái)使pointer移動(dòng)指定次數(shù)
for(int l=0;l<length;l++)
2.應(yīng)該有另一個(gè)for循環(huán)來(lái)循環(huán)讀取displacementList里的移動(dòng)點(diǎn)坐標(biāo)
for(int dis=0;dis<4;dis++)
- 在每次移位之后,points里應(yīng)該增加新的數(shù)據(jù)崩溪,pointer應(yīng)該指向最新的位置
Point newPoint=new Point(pointer.x+displacementList[dis].x,pointer.y-displacementList[dis].y);
points.add(newPoint);
pointer=newPointer;
- 當(dāng)length的動(dòng)作讀完了之后浅役,length應(yīng)該增加
剩下的就是調(diào)試了。
Github 的源代碼會(huì)在Advent of Code 結(jié)束之后發(fā)布