Bir kraliçenin spiral boyunca yürümesi


13

Uzak bir krallıkta, bir satranç kraliçesi spiral yol boyunca günlük bir yürüyüş yapar n, 1'den numaraya, spiralin kendisini takip etmeye özen göstermez, ancak sadece bir satranç tahtasında olduğu gibi kraliçenin hareketlerini yapar. Kraliçe, denekleri tarafından sevilir ve yolunda ziyaret ettiği her kareyi not ederler. Kraliçenin herhangi bir meydanda yürüyüşüne başlayabileceği ve herhangi bir meydanda bitirebileceği göz önüne alındığında, alabileceği en kısa kraliçenin yürüyüşü nedir?

Meydan okuma

Dikdörtgen bir ızgara üzerinde tamsayıların bir sarmalı verildiğinde, bir satranç kraliçesinin hareketlerini kullanarak bu sarmal ızgaradaki iki sayı arasında mümkün olan en kısa yollardan birini (seyahat edilen hücre sayısı ile sayılır) döndüren bir işlev yazın .

Örneğin, gelen 16için 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

Bazı olası yollar 16, 4, 2, 10, 25ve içerir 16, 5, 1, 9, 25.

kurallar

  • Giriş herhangi iki pozitif tamsayı olacaktır.
  • Çıktı, yalnızca dikey ve çapraz hareketler kullanılarak spiral boyunca bir tamsayılar yolu (her iki uç noktası dahil) olacaktır.
  • Bir yolun uzunluğu, seyahat edilen hücre sayısı ile sayılır.
  • Cevabınız bir program veya bir fonksiyon olabilir.
  • Bu kod golf, bu yüzden en az bayt sayısı kazanır.

Her zaman olduğu gibi, sorun net değilse, lütfen bana bildirin. İyi şanslar ve iyi golf!

Test senaryoları

>>> 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
Seyahat edilen hücre sayısına göre en kısa yolu aradığınızı belirtmek isteyebilirsiniz (Öklid mesafesinin aksine).
Martin Ender

1
Bu bir "kralın yürüyüşü" olarak daha anlamlı olmaz mıydı?
Jo King

1
@JoKing Ah, şimdi bahsettiğinize göre, bu bir kral yürüyüşü olmalı. Ancak, başlığı değiştirmek biraz geç olabilir.
Sherlock9

Yanıtlar:


5

APL (Dyalog Unicode) , 59 57 bayt SBCS

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

Çevrimiçi deneyin!

@Ngn sayesinde -2 bayt.

İki uç noktayı sol ve sağ argümanlar olarak kabul eden anonim işlev.

Ungolfed ve nasıl çalışır

Kraliçe önce çapraz olarak hareket eder, bu nedenle her sayının koordinatlarını önceden hesaplamak yeterlidir max(start,end).

Koordinat üreten algoritma, ilgili meydan okumadaki çeşitli cevaplardan esinlenmiştir , ancak mevcut cevapların herhangi birinden biraz farklıdır:

  • Gerekli sınır 10 verildiğinde
  • 1 tabanlı aralığı oluşturun r=1 2 3 4 5 6 7 8 9 10
  • Her sayının yarısının tavanını al n=1 1 2 2 3 3 4 4 5 5
  • Her öğeyi çoğaltırlar rtarafından 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
  • Başlangıç ​​noktası 0 olan hayali birimin kümülatif gücünün toplamını alın (bu bölüm bağlantılı meydan okumaya çeşitli Python çözümleri için ortaktır)

Koordinatların vektör Sonra, bir kez vhazır, kolayca sarmal indeksi ve koordinatlar kullanma arasında dönüştürebilir v[i]ve v⍳coord(ilk indeksi bulmakta coordiçinde 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

Mathematica 615530 bayt

Bu bir sayı ızgarası oluşturur, bir grafiğe dönüştürür ve daha sonra girilen iki sayı arasında en kısa yolu bulur.


UnGolfed

numberSpiralMathworld Prime Spiral'den . Bir n by n Ulam Spiral oluşturur ( asalleri vurgulamadan).

findPathsayı ızgarasını grafiğe dönüştürür. Kenarlar, sayı ızgarasında geçerli kraliçe hareketleridir.


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

Örnekler

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

{4,5}

{13,3,1,7,22}

{16,4,1,9,25}

Kafes


80 ile 1 arasındaki en kısa yol, 6 değil, 5 köşe içerir.

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

{80, 48, 24, 8, 1}

seksen bir ızgara


golfed

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

Karşılıklı dört özyinelemeli işlev kullanarak spirali kare bir 2D dizide oluşturur. Yol listesini oluşturmak için başka bir özyinelemeli arama.

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

Ungolfed

  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

Yakut, 262 218 216 bayt

Bu benim Python cevabımın bir limanı . Golf önerileri hoş geldiniz.

Düzenleme: 45 Ürdün ve onların önerileri sayesinde bayt d=[0]*n=m*m;*e=c=0;*t=a, .rect, 0<=>xve x,y=(e[a]-g=e[b]).rect; t<<d[(g.real+x)*m+g.imag+y]. Bir başka bayt (x+y*1i)için (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}

Ungolfed:

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

Baytlarını saymadığınız q=için yanıtını kaldırmalısınız . c=0;e=[c];t=[a]kısaltılabilir *e=c=0;*t=a. Sen yerini alabilir z=e[a]-e[b];x,y=z.real,z.imagile x,y=(e[a]-e[b]).rectve x+=x<0?1:x>0?-1:0ile x+=0<=>x(aynı y). Bunun 229 bayta düştüğünü düşünüyorum.
Ürdün

1 boyutlu bir diziye geçerseniz 6 bayt daha kaydedebilirsiniz. Başlatılması değiştirin dile d=[0]*m*mdeğiştirin, sonra d[c.real][c.imag]ile d[c.real*m+c.imag]ve d[e[b].real+x][e[b].imag+y]ile d[(e[b].real+x)*m+e[b].imag+y].
Ürdün

Önceki yorumuma göre 2 baytlık bir iyileştirme: t<<d[(e[b].real+x)*m+e[b].imag+y]kısaltılabilir u,v=e[b].rect;t<<d[(u+x)*m+v+y].
Ürdün

Daha iki değiştirerek bayt d=[0]*m*miçin d=[0]*n=m*mve (m*m).timesiçin n.times. 219.
Ürdün

Sen değiştirerek iki ek bayt kaydedebilirsiniz x,y=(e[a]-e[b]).rectiçin x,y=(e[a]-g=e[b]).rect, silme u,v=e[b].rectve değiştirme t<<d[(u+x)*m+v+y]için t<<d[(g.real+x)*g.imag+v+y](temelde benim ikinci-to-son yorumun geri alma).
Ürdün

1

Python 3, 316 bayt

Bu cevap koordinatları bakar ave b(karmaşık sayılar kullanılarak) spiral ve ilk diyagonal hareketler, sonra dik hamle ekler.

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

Ungolfed:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.