Ми спіраль вийшла з-під контролю, докторе!


11

Доктор, намагаючись врятуватися від сил Далека, вирішив посилати їх спіном, мандруючи по різних кишенях простору спіральним рухом.

Залежно від характеру наявного простору-часу, Лікар потребує введення в систему TARDIS контролю висоти та ширини перерізу простору та точки входу, з якої починається спіраль.

Розділ простору можна представити у вигляді сітки h x w, заповненої послідовними цілими числами зліва направо, зверху вниз, починаючи з 1.

Вихідне положення надається у вигляді rc для рядка та стовпця ... З цього програмного забезпечення TARDIS потрібно виплюнути впорядкований список цілих чисел, отриманих шляхом спіралі назовні в напрямку проти годинникової стрілки з рядка r стовпця c , починаючи вгору ...

Ваше завдання, як супутника Доктора, - запрограмувати ТАРДІС, щоб він взяв чотири числа у форматі, height width row columnі він визначив, у якому просторі потрібно подорожувати ТАРДІС, щоб відповідати спіральному руху, описаному нижче ...

Введення 1

5 5 3 3

(5 х 5 сітки, починаючи з положення 3,3)

Вихід 1

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

Пояснення виходу

Оригінальна сітка введіть тут опис зображення

Створена спіраль введіть тут опис зображення

Введення 2

2 4 1 2

(2 х 4 сітка, починаючи з положення 1,2)

Вихід 2

2 1 5 6 7 3 8 4

Пояснення виходу

Трохи інший, як спіраль, тепер повинен кружляти навколо сітки для отримання відповідного виходу ...

Оригінальна сітка введіть тут опис зображення

Створена спіраль введіть тут опис зображення

Правила:

  1. Це код-гольф, тому найкоротша довжина коду отримує галочку схвалення.

  2. Наведені вище приклади повинні бути використані для тестування вашого коду. Якщо він не забезпечує відповідний вихід, щось не так ...

  3. У вашій відповіді повинні бути вказані версії коду для гольфу та для гольфу ...

Удачі!


Дозвольте вказати вам на малюнок.io, де можна швидко зробити досить розумні малюнки (ви маєте відмінну розбірливість за допомогою намальованої рукою версії ... просто я не бачу жодних червоних кіл). Розглянемо i.stack.imgur.com/xbLSA.png як приклад того, що можна зробити. Зауважте, що в ньому вбудований XML, тому якщо ви перейдете до draw.io, ви можете імпортувати з URL.

Я маю це на увазі для моєї наступної потреби в малюнку, @MichaelT, дякую ...
WallyWest

1
Я надсилаю відповідь з функцією, що повертає масив як вихід. Це прийнятно?
edc65

@ edc65 Mate, ми з вами повертаємось назад на CG, я дозволю для цього функцію S (h, w, r, c) тощо) :)
WallyWest

Відповіді:


3

JavaScript (ES6) 124 163 177

Редагувати Зовсім іншим способом, не потрібно масиву для зберігання відвідуваних комірок. Використовуючи той факт, що сторона спіралі збільшується на 1 через кожні 2 обороти.

// New way
f=(h,w,y,x)=>
  (e=>{
    for(o=[],d=i=t=l=0;l<w*h;i<t?i+=2:[i,d,e]=[1,-e,d,++t])
      o[l]=y*w-w+x,l+=x>0&x<=w&y>0&y<=h,x+=d,y-=e
  })(1)||o


// Golfed
g=(h,w,y,x)=>
  (g=>{
    for(e=n=0;n<h*w;)g[[n%w+1,-~(n/w)]]=++n;
    for(o=[g[[x,y]]],l=d=1;l<n;l+=!!(o[l]=g[[x+=d,y+=e]]))
      g[[x,y]]=0,
      g[[x+e,y-d]]!=0&&([d,e]=[e,-d])
  })([])||o



// Not golfed
u=(h,w,y,x)=>{
  var i,j,dx,dy,kx,ky,o,n,
    g={} // simulate a 2dimensional array using a hashtable with keys in the form 'x,y'

  for(n=i=0; i++<h;) // fill grid (probably better done in a single loop)
    for(j=0; j++<w;)
      g[[j,i]] = ++n;
  o=[g[[x,y]]] // starting point in output
  dx=1, dy=0 // start headed right
  
  for(; !o[w*h-1]; ) // loop until all w*h position are put in output
  {
    g[[x, y]] = 0 // mark current position to avoid reusing
    kx=dy, ky=-dx // try turning left
    if(g[[x+kx, y+ky]] != 0) // check if position marked
    { // found a valid position
      dx=kx, dy=ky // change direction
    }
    x+=dx, y+=dy // move
    k=g[[x, y]] // get current value
    if (k) o.push(k) // put in output list if not 'undefined' (outside grid)
  }
  return o
}

// TEST - In FireFox

out=x=>O.innerHTML+=x+'\n';
[
 [[5,5,3,3],'13 8 7 12 17 18 19 14 9 4 3 2 1 6 11 16 21 22 23 24 25 20 15 10 5'],
 [[2,4,1,2],'2 1 5 6 7 3 8 4']
].forEach(t=>out(t[0] + '\n Result: ' + f(...t[0])+'\n Check:  ' + t[1]))

test=()=>
{
  var r, i=I.value.match(/\d+/g), h=i[0]|0, w=i[1]|0, y=i[2]|0, x=i[3]|0
  if (y>h||x>w) r = 'Invalid input'
  else r = f(h,w,y,x)
  out(i+'\n Reault: ' +r)
}
<pre id=O></pre>
Your test:<input id=I><button onclick="test()">-></button>


Дивовижний гольф! З 300 до 163 ... Я знімаю шапку до вас ...
WallyWest

1
@WallyWest з цим коментарем ти підштовхуєш мене до кращого. Thnx
edc65

Приємно! Моє рішення Python було набагато довше, але мені подобалося, все в порядку, ви використовуєте кращий метод. Тепер ви використовуєте те саме, і це ще коротше ... У мене є якась робота. :)
randomra

@randomra Я все-таки хотів би це побачити ...
WallyWest

2

Пітон 3, 191

Можливо, це не чудовий бал, але ось це:

def f(b,a,d,c):
 p,r,l,s,h=c+1j*d,-1j,1,0,0
 for _ in [0]*((a+b)**2):x,y=p.real,p.imag;0<x<a+1and 0<y<b+1and print(int((y-1)*a+x),end=' ');p+=r;s=(s+1)%l;t=s==0;h=(h+t)%2;l+=h<t;r*=(-1j)**t 

Просуваємося по спіралі, збільшуючи довжину сторони після кожного другого повороту. Якщо наше положення знаходиться всередині даної сітки, ми друкуємо її відповідний номер.

Змінні:

  • p - складна позиція
  • x і y - координати положення
  • r напрямок
  • s - положення на поточній стороні
  • l - поточна довжина сторони
  • h - парність порядкової сторони сторони
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.