Một nữ hoàng đi ngang qua một vòng xoắn ốc


13

Ở một vương quốc xa xôi, một nữ hoàng cờ vua đi bộ hàng ngày trên một con đường xoắn ốc, được đánh số từ 1 đến n, không quan tâm đến việc đi theo vòng xoắn ốc, mà chỉ đơn giản là thực hiện các động tác của nữ hoàng như trên bàn cờ. Nữ hoàng được yêu mến bởi các đối tượng của mình, và họ ghi chú lại mọi quảng trường mà cô ghé thăm trên con đường của mình. Cho rằng nữ hoàng có thể bắt đầu đi bộ trên bất kỳ quảng trường nào và kết thúc nó trên bất kỳ quảng trường nào, bước đi ngắn nhất của nữ hoàng mà cô có thể đi là gì?

Các thách thức

Đưa ra một vòng tròn số nguyên trên lưới hình chữ nhật, viết một hàm trả về một trong những đường đi ngắn nhất có thể (tính theo số lượng ô di chuyển) giữa hai số trên lưới xoắn ốc này bằng cách di chuyển của một nữ hoàng cờ vua.

Ví dụ: từ 16đến 25:

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

Một số đường dẫn có thể bao gồm 16, 4, 2, 10, 2516, 5, 1, 9, 25.

Quy tắc

  • Đầu vào sẽ là bất kỳ hai số nguyên dương.
  • Đầu ra sẽ là một đường dẫn của các số nguyên (bao gồm cả hai điểm cuối) trên đường xoắn ốc chỉ sử dụng các chuyển động trực giao và đường chéo.
  • Độ dài của một đường dẫn được tính bằng số lượng ô di chuyển.
  • Câu trả lời của bạn có thể là một chương trình hoặc một chức năng.
  • Đây là mã golf, vì vậy số byte nhỏ nhất sẽ thắng.

Như mọi khi, nếu vấn đề không rõ ràng, xin vui lòng cho tôi biết. Chúc may mắn và chơi golf tốt!

Các trường hợp thử nghiệm

>>> 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
Bạn có thể muốn đề cập rằng bạn đang tìm kiếm con đường ngắn nhất theo số lượng tế bào đã đi (trái ngược với khoảng cách Euclidian, nói).
Martin Ender

1
Điều này sẽ không có ý nghĩa hơn như là một "bước đi của nhà vua"?
Jo King

1
@JoKing Ah, bây giờ bạn đề cập đến nó, nó nên là một cuộc đi bộ của nhà vua. Tuy nhiên, có thể hơi muộn để thay đổi tiêu đề.
Sherlock9

Câu trả lời:


5

APL (Dyalog Unicode) , 59 57 byte SBCS

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

Hãy thử trực tuyến!

-2 byte nhờ @ngn.

Hàm ẩn danh chấp nhận hai điểm cuối là đối số trái và phải.

Ungolfed và cách thức hoạt động

Nữ hoàng di chuyển theo đường chéo trước, do đó, đủ để tính toán trước tọa độ của mỗi số lên đến max(start,end).

Thuật toán tạo tọa độ được lấy cảm hứng từ một số câu trả lời cho thử thách liên quan , nhưng hơi khác so với bất kỳ câu trả lời hiện có nào:

  • Đưa ra giới hạn cần thiết là 10
  • Tạo phạm vi dựa trên 1 r=1 2 3 4 5 6 7 8 9 10
  • Lấy trần của một nửa số n=1 1 2 2 3 3 4 4 5 5
  • Tái tạo từng hạng mục công rbằng 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
  • Lấy tổng công suất tích lũy của đơn vị tưởng tượng, với điểm bắt đầu là 0. (phần này là chung cho các giải pháp Python khác nhau cho thử thách được liên kết)

Sau đó, khi vectơ tọa độ vđã sẵn sàng, chúng ta có thể dễ dàng chuyển đổi giữa chỉ số xoắn ốc và tọa độ bằng cách sử dụng v[i]v⍳coord(tìm chỉ số đầu tiên của coordin 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

Toán học 615 530 byte

Điều này xây dựng một lưới số, chuyển đổi nó thành một biểu đồ và sau đó tìm thấy một con đường ngắn nhất giữa hai số được nhập vào.


Vô duyên

numberSpirallà từ Mathworld Prime xoắn ốc . Nó tạo ra một n bởi n Ulam xoắn ốc (mà không làm nổi bật các số nguyên tố).

findPathchuyển đổi lưới số thành một biểu đồ. Các cạnh là nữ hoàng hợp lệ di chuyển trên lưới số.


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]]

Ví dụ

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

{4,5}

{13,3,1,7,22}

{16,4,1,9,25}

lưới điện


Đường đi ngắn nhất từ ​​80 đến 1 chứa 5, không phải 6, đỉnh.

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

{80, 48, 24, 8, 1}

tám mươi mốt lưới


Chơi gôn

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

Scala (830 byte)

Xây dựng hình xoắn ốc trong một mảng 2D vuông bằng bốn hàm đệ quy lẫn nhau. Một tìm kiếm đệ quy khác để xây dựng danh sách đường dẫn.

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)}}

Ung dung

  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

Ruby, 262 218 216 byte

Đây là một cổng của câu trả lời Python của tôi . Gợi ý chơi golf chào mừng.

Chỉnh sửa: 45 byte nhờ Jordan và gợi ý của họ 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]. Một byte khác từ (x+y*1i)đến (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}

Ung dung:

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

Bạn nên xóa q=câu trả lời vì bạn không đếm byte của nó. c=0;e=[c];t=[a]có thể rút ngắn thành *e=c=0;*t=a. Bạn có thể thay thế z=e[a]-e[b];x,y=z.real,z.imagbằng x,y=(e[a]-e[b]).rectx+=x<0?1:x>0?-1:0với x+=0<=>x(tương tự cho y). Tôi nghĩ rằng nó đã giảm xuống còn 229 byte.
Jordan

Nếu bạn chuyển sang mảng 1 chiều, bạn có thể lưu thêm 6 byte. Thay thế khởi tạo dbằng d=[0]*m*m, sau đó thay thế d[c.real][c.imag]bằng d[c.real*m+c.imag]d[e[b].real+x][e[b].imag+y]bằng d[(e[b].real+x)*m+e[b].imag+y].
Jordan

Một cải tiến 2 byte so với nhận xét trước đây của tôi: t<<d[(e[b].real+x)*m+e[b].imag+y]có thể rút ngắn thành u,v=e[b].rect;t<<d[(u+x)*m+v+y].
Jordan

Thêm hai byte bằng cách thay đổi d=[0]*m*mđể d=[0]*n=m*m(m*m).timesđể n.times. Đó là 219.
Jordan

Bạn có thể lưu hai byte bổ sung bằng cách thay đổi x,y=(e[a]-e[b]).rectđể x,y=(e[a]-g=e[b]).rect, xóa u,v=e[b].rectvà thay đổi t<<d[(u+x)*m+v+y]đến t<<d[(g.real+x)*g.imag+v+y](về cơ bản quay trở lại thứ hai-to-cuối cùng của tôi bình luận).
Jordan

1

Python 3, 316 byte

Câu trả lời này xem xét tọa độ của abtrên hình xoắn ốc (sử dụng số phức) và thêm các bước di chuyển chéo trước, sau đó là các bước di chuyển trực giao.

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

Ung dung:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.