나선을 가로 지르는 여왕의 산책


13

멀리 떨어진 왕국에서 체스 여왕은 나선 경로를 따라 매일 걸어 n다닙니다. 나선 자체를 따르지 않고 단순히 체스 판에서 여왕의 움직임을 만듭니다. 여왕은 그녀의 주제에 의해 사랑 받고, 그녀가 그녀의 길을 방문하는 모든 광장을 기록합니다. 여왕이 어떤 광장에서든 걷기를 시작하고 어떤 광장에서나 끝낼 수 있다는 것을 감안할 때, 그녀가 취할 수있는 가장 짧은 여왕의 걷기는 무엇입니까?

도전

사각형 격자에 정수의 나선이 주어지면 체스 여왕의 움직임을 사용 하여이 나선형 격자의 두 숫자 사이에서 가능한 가장 짧은 경로 중 하나 (이동 한 셀 수로 계산) 를 반환하는 함수를 작성하십시오 .

예를 들어,에서 1625:

25 10 11 12 13
24  9  2  3 14
23  8  1  4 15
22  7  6  5 16
21 20 19 18 17

가능한 경로는 16, 4, 2, 10, 2516, 5, 1, 9, 25입니다.

규칙

  • 입력은 두 개의 양의 정수입니다.
  • 출력은 직교 및 대각선 이동 만 사용하여 나선에 걸쳐 정수 경로 (두 끝점 포함)가됩니다.
  • 경로의 길이는 이동 한 셀 수로 계산됩니다.
  • 귀하의 답변은 프로그램 또는 기능 일 수 있습니다.
  • 이것은 코드 골프이므로 가장 적은 수의 바이트가 이깁니다.

문제가 명확하지 않은 경우 언제든지 알려주십시오. 행운과 좋은 골프!

테스트 사례

>>> queen_spiral(4, 5)
4, 5
>>> queen_spiral(13, 20)
13, 3, 1, 7, 20
>>> queen_spiral(14, 14)
14
>>> queen_spiral(10, 3)
10, 11, 3
>>> queen_spiral(16, 25)
16, 4, 2, 10, 25
>>> queen_spiral(80, 1)
80, 48, 24, 8, 1


5
이동 한 셀 수 (유클리드 거리와 반대)로 최단 경로 찾고 있다고 언급 할 수 있습니다 .
Martin Ender

1
이것이 "킹 워크"로 이해가되지 않습니까?
조왕

1
@JoKing Ah, 이제 언급 했으니, 왕의 산책로가되어야합니다. 그러나 제목을 변경하는 데 약간 늦을 수 있습니다.
Sherlock9

답변:


5

APL (Dyalog Unicode) , 59 57 바이트 SBCS

{v⍳+\v[⍺],↓⍉↑(|⍴¨×)⊃⍵⍺-.⊃⊂v9 11∘○¨+\0,0j1*{⍵/⍨⌈⍵÷2}⍳⍺⌈⍵}

온라인으로 사용해보십시오!

@ngn 덕분에 -2 바이트

두 개의 엔드 포인트를 왼쪽 및 오른쪽 인수로 허용하는 익명 함수.

언 골프 드 & 작동 방식

여왕은 먼저 대각선으로 움직이므로 각 숫자의 좌표를 최대로 사전 계산하면 충분합니다 max(start,end).

좌표 생성 알고리즘은 관련 과제 에 대한 몇 가지 답변에서 영감을 얻었 지만 기존 답변과 약간 다릅니다.

  • 10의 필요한 경계를 감안할 때
  • 1 기반 범위 생성 r=1 2 3 4 5 6 7 8 9 10
  • 각 숫자의 절반을 상한값으로 n=1 1 2 2 3 3 4 4 5 5
  • 의 각 항목 복제 r에 의해를 n.1 2 3 3 4 4 5 5 5 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 9 10 10 10 10 10
  • 시작점이 0 인 허수 단위의 누적 합을 취하십시오. (이 부분은 연결된 도전에 대한 다양한 Python 솔루션에 공통입니다)

좌표의 벡터에 한 번, v준비, 우리는 쉽게 나선형 지수와 좌표를 사용하여 사이에 변환 할 수 v[i]v⍳coord(의 첫 번째 인덱스 찾는 coord에서를 v).

 Define a function; ⍺=start, ⍵=end
f←{
   Construct a vector of spiral coordinates v
  v9 11∘○¨+\0,0j1*{⍵/⍨⌈⍵÷2}⍳⍺⌈⍵
                             ⍺⌈⍵   max of start, end
                                  range of 1 to that number
                   {⍵/⍨⌈⍵÷2}   for each number n of above, copy itself ceil(n/2) times
               0j1*   raise imaginary unit to the power of above
           +\0,       prepend 0 and cumulative sum
                      (gives vector of coordinates as complex numbers)
    9 11∘○¨   convert each complex number into (real, imag) pair
  v          assign it to v

   Extract start and end coordinates
  a w←(⍺⊃v)(⍵⊃v)

   Compute the path the Queen will take
  v⍳+\(a),↓⍉↑(|⍴¨×)w-a
                    w-a   coordinate difference (end-start)
              (|⍴¨×)      generate abs(x) copies of signum(x) for both x- and y-coords
                          e.g. 4 -> (1 1 1 1), ¯3 -> 1 ¯1 ¯1)
           ↓⍉↑   promote to matrix (with 0 padding), transpose and split again
                 (gives list of steps the Queen will take)
    +\(a),      prepend the starting point and cumulative sum
                 (gives the path as coordinates)
  v   index into the spiral vector (gives the spiral numbers at those coordinates)
}

(⍵⊃v)-⍺⊃v->⊃⍵⍺-.⊃⊂
ngn

(⍺⌷v)->v[⍺]
ngn

3

매스 매 티카 615530 바이트

숫자 격자를 구성하여 그래프로 변환 한 다음 입력 된 두 숫자 사이의 최단 경로를 찾습니다.


언 골프

numberSpiralMathworld Prime Spiral 에서 온 것 입니다. 그것은 프라임을 강조하지 않고 n x n의 Ulam Spiral을 만듭니다 .

findPath숫자 표를 그래프로 변환합니다. 모서리는 숫자 그리드에서 유효한 여왕 이동입니다.


numberSpiral[n_Integer?OddQ]:= 
  Module[{a,i=(n+1)/2,j=(n+1)/2,cnt=1,dir=0,len,parity,vec={{1,0},{0,-1},{-1,0},{0,1}}},a=Table[j+n(i-1),{i,n},{j,n}];Do[Do[Do[a[[j,i]]=cnt++;{i,j}+=vec[[dir+1]],{k,len}];dir=Mod[dir+1,4],{parity,0,1}],{len,n-1}];a];  

findPath[v1_, v2_] := 
  Module[{f, z, k},
    (*f  creates edges between each number and its neighboring squares *)
    f[sp_,n_]:=n<->#&/@(sp[[Sequence@@#]]&/@(Position[sp,n][[1]]/.{r_,c_}:>Cases[{{r-1,c},{r+1,c},{r,c-1},{r,c+1},{r-1,c-1},{r-1,c+1},{r+1,c+1}, {r+1,c-1}},{x_,y_}/; 0<x<k&&0<y<k]));k=If[EvenQ[
     z=\[LeftCeiling]Sqrt[Sort[{v1, v2}][[-1]]]\[RightCeiling]],z+1,z];
    FindShortestPath[Graph[Sort/@Flatten[f[ns=numberSpiral[k],#]&/@Range[k^2]] //Union],v1,v2]]

findPath[4,5]
findPath[13,22]
findPath[16,25]
numberSpiral[5]//Grid

{4,5}

{13,3,1,7,22}

{16,4,1,9,25}

그리드


80에서 1까지의 최단 경로에는 6이 아닌 5 개의 정점이 포함됩니다.

findPath[80,1]
numberSpiral[9]//Grid

{80, 48, 24, 8, 1}

여든 하나의 그리드


골프

u=Module;
w@n_:=u[{a,i=(n+1)/2,j=(n+1)/2,c=1,d=0,l,p,v={{1,0},{0,-1},{-1,0},{0,1}}},
a=Table[j+n(i-1),{i,n},{j,n}];
Do[Do[Do[a[[j,i]]=c++;{i,j}+=v[[d+1]],{k,l}];d=Mod[d+1,4],{p,0,1}],{l,n-1}];a];
h[v1_,v2_]:=u[{f,z},
s_~f~n_:=n<->#&/@(s[[Sequence@@#]]&/@(Position[s,n][[1]]/.{r_,c_}:> 
Cases[{{r-1,c},{r+1,c},{r,c-1},{r,c+1},{r-1,c-1},{r-1,c+1},{r+1,c+1},{r+1,c-1}},{x_,y_}/;0<x<k&&0<y<k]));
k=If[EvenQ[z=\[LeftCeiling]Sqrt[Sort[{v1,v2}][[-1]]]\[RightCeiling]],z+1,z];
FindShortestPath[g=Graph[Sort/@Flatten[f[ns=w@k,#]&/@Union@Range[k^2]]],v1,v2]]

2

스칼라 (830 바이트)

네 개의 상호 재귀 함수를 사용하여 사각형 2D 배열로 나선을 만듭니다. 경로 목록을 작성하기위한 또 다른 재귀 검색

def P(s:Int,e:Int):List[Int]={
import scala.math._
type G=Array[Array[Int]]
type I=Int
type T=(I,I)
def S(z:I)={def U(g:G,x:I,y:I,c:I,r:I):Unit={for(i<-0 to r.min(y)){g(y-i)(x)=c+i}
if(r<=y)R(g,x,y-r,c+r,r)}
def R(g:G,x:I,y:I,c:I,r:I)={for(i<-0 to r){g(y)(x+i)=c+i}
D(g,x+r,y,c+r,r+1)}
def D(g:G,x:I,y:I,c:I,r:I)={for(i<-0 to r){g(y+i)(x)=c+i}
L(g,x,y+r,c+r,r)}
def L(g:G,x:I,y:I,c:I,r:I)={for(i<-0 to r){g(y)(x-i)=c+i}
U(g,x-r,y,c+r,r+1)}
val g=Array.ofDim[I](z,z)
U(g,z/2,z/2,1,1)
g}
def C(n:I,g:G):T={var(x,y)=(0,0)
for(i<-g.indices){val j=g(i).indexOf(n)
if(j>=0){x=j
y=i}}
(x,y)}
def N(n:Int)=if(n==0)0 else if(n<0)-1 else 1
def Q(a:T,b:T):List[T]={val u=N(b._1-a._1)
val v=N(b._2-a._2)
if(u==0&&v==0)b::Nil else a::Q((a._1+u,a._2+v),b)}
val z=ceil(sqrt(max(s,e))).toInt|1
val p=S(z)
Q(C(s,p),C(e,p)).map{case(x,y)=>p(y)(x)}}

언 골프

  import scala.math._
  type Grid=Array[Array[Int]]
  def spiral(size: Int) = {
    def up(grid:Grid, x: Int, y: Int, c: Int, r: Int): Unit = {
      for (i <- 0 to r.min(y)) {
        grid(y-i)(x) = c + i
      }
      if (r <= y)
        right(grid,x,y-r,c+r,r)
    }
    def right(grid:Grid, x: Int, y: Int, c: Int, r: Int) = {
      for (i <- 0 to r) {
        grid(y)(x+i) = c + i
      }
      down(grid,x+r,y,c+r,r+1)
    }
    def down(grid:Grid, x: Int, y: Int, c: Int, r: Int) = {
      for (i <- 0 to r) {
        grid(y+i)(x) = c + i
      }
      left(grid,x,y+r,c+r,r)
    }
    def left(grid:Grid, x: Int, y: Int, c: Int, r: Int) = {
      for (i <- 0 to r) {
        grid(y)(x-i) = c + i
      }
      up(grid,x-r,y,c+r,r+1)
    }
    val grid = Array.ofDim[Int](size,size)
    up(grid,size/2,size/2,1,1)
    grid
  }
  def findPath(start: Int, end: Int): List[Int] = {
    def findCoords(n: Int, grid: Grid): (Int, Int) = {
      var (x,y)=(0,0)
      for (i <- grid.indices) {
        val j = grid(i).indexOf(n)
        if (j >= 0) {
          x = j
          y = i
        }
      }
      (x,y)
    }
    def sign(n: Int) = if (n == 0) 0 else if (n < 0) -1 else 1
    def path(stc: (Int, Int), enc: (Int, Int)) : List[(Int, Int)] = {
      val dx = sign(enc._1 - stc._1)
      val dy = sign(enc._2 - stc._2)
      if (dx == 0 && dy == 0) {
        enc :: Nil
      } else {
        stc :: path((stc._1 + dx, stc._2 + dy), enc)
      }
    }
    val size = ceil(sqrt(max(start, end))).toInt | 1
    val spir = spiral(size)
    path(findCoords(start, spir),findCoords(end, spir)).
      map { case (x, y) => spir(y)(x) }
  }

2

루비, 262 (218) 216 바이트

이것은 내 파이썬 답변 의 포트입니다 . 골프 제안을 환영합니다.

편집 : (45)는 요르단과 자신의 제안에 감사 바이트 d=[0]*n=m*m;*e=c=0;*t=a, .rect, 0<=>xx,y=(e[a]-g=e[b]).rect; t<<d[(g.real+x)*m+g.imag+y]. 또 다른 바이트 (x+y*1i)(x+y.i).

->a,b{m=([a,b].max**0.5).to_i+1;d=[0]*n=m*m;*e=c=0;*t=a
n.times{|k|d[c.real*m+c.imag]=k+1;e<<c;c+=1i**((4*k+1)**0.5-1).to_i}
x,y=(e[a]-g=e[b]).rect
(x+=0<=>x;y+=0<=>y;t<<d[(g.real+x)*m+g.imag+y])while(x+y.i).abs>0
t}

언 골프 드 :

def q(a,b)
  m = ([a,b].max**0.5).to_i+1
  n = m*m
  d = [0]*n
  c = 0
  *e = c   # same as e=[0]
  *t = a   # same as t=[a]

  (1..n).each do |k|
    d[c.real * m + c.imag] = k+1
    e << c
    c += 1i**((4*k+1)**0.5-1).to_i
  end

  x, y = (e[a] - g=e[b]).rect

  while (x+y.i).abs > 0 do
    if x<0
      x += 1
    elsif x>0
      x += -1
    end

    if y<0
      y += 1
    elsif y>0
      y -= 1
    end

    t << d[(g.real+x)*m+g.imag+y]
  end

  return t
end

q=바이트 수를 계산하지 않으므로 답변에서를 제거해야 합니다. c=0;e=[c];t=[a]로 단축 할 수 있습니다 *e=c=0;*t=a. 당신은 대체 할 수 z=e[a]-e[b];x,y=z.real,z.imagx,y=(e[a]-e[b]).rectx+=x<0?1:x>0?-1:0x+=0<=>x(대한 동일 y). 나는 그것이 229 바이트로 줄었다 고 생각한다.
Jordan

1 차원 배열로 전환하면 6 바이트를 더 절약 할 수 있습니다. 의 초기화 교체 d로를 d=[0]*m*m교체 한 후, d[c.real][c.imag]d[c.real*m+c.imag]d[e[b].real+x][e[b].imag+y]함께 d[(e[b].real+x)*m+e[b].imag+y].
Jordan

이전 의견보다 2 바이트 개선 : t<<d[(e[b].real+x)*m+e[b].imag+y]단축 할 수 있습니다 u,v=e[b].rect;t<<d[(u+x)*m+v+y].
Jordan

및 로 변경 d=[0]*m*m하여 2 바이트 더 . d=[0]*n=m*m(m*m).timesn.times
요르단

당신은 변화에 의해 두 개의 추가 바이트를 저장할 수 있습니다 x,y=(e[a]-e[b]).rectx,y=(e[a]-g=e[b]).rect, 삭제 u,v=e[b].rect및 변경 t<<d[(u+x)*m+v+y]t<<d[(g.real+x)*g.imag+v+y](기본적으로 나의 마지막에서 두 번째 주석을 되 돌리는).
Jordan

1

파이썬 3, 316 바이트

이 답변은 나선형 의 좌표 ab나선 의 좌표 (복소수 사용)를보고 대각선 이동을 먼저 추가 한 다음 직교 이동을 추가합니다.

def q(a,b):
 m=int(max(a,b)**.5)+1;d=[];c=0;e=[c];t=[a]
 for i in range(m):d+=[[0]*m]
 for k in range(m*m):d[int(c.real)][int(c.imag)]=k+1;e+=[c];c+=1j**int((4*k+1)**.5-1)
 z=e[a]-e[b];x,y=int(z.real),int(z.imag)
 while abs(x+y*1j):x+=(x<0)^-(x>0);y+=(y<0)^-(y>0);t+=[d[int(e[b].real)+x][int(e[b].imag)+y]]
 return t

언 골프 드 :

def queen_spiral(a,b):
    square_size = int(max(a,b)**.5)+1
    complex_to_spiral = []
    complex = 0
    spiral_to_complex = [c] # add 0 first, so that it's 1-indexed later
    result = [a]

    for i in range(square_size):
        complex_to_spiral.append([0]*square_size) # the rows of the spiral

    for k in range(square_size**2):
        row = int(complex.real)
        column = int(complex.imag)
        complex_to_spiral[row][column] = k+1 # 1-indexing

        spiral_to_complex.append(complex)

        quarter_turns = int((4*k+1)**.5-1)
        complex += 1j**quarter_turns

    z = spiral_to_complex[a] - spiral_to_complex[b]
    v = spiral_to_complex[b]
    x, y = int(z.real), int(z.imag)
    r, s = int(v.real), int(v.imag)

    while abs(x+y*1j):
        if x < 0:
            x += 1
        elif x > 0:
            x += -1
        # else x == 0, do nothing
        if y < 0:
            y += 1
        elif y > 0:
            y += -1

        vertex = complex_to_spiral[r+x][s+y]
        result.append(vertex)
    return result
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.