Магнітний витяг у масиві


20

Фон

У мене є ряд потужних магнітів і купа металевих предметів між ними. Куди їх потягнуть магніти?

Вхідні дані

Ваш вхід - це масив невід’ємних цілих чисел, який буде містити принаймні одне 1. Ви можете використовувати будь-який розумний формат.

В 0s масиву представляє собою порожній простір, і 1s є фіксовані магніти. Всі інші числа - це металеві предмети, які тягнуть магнітами. Кожен предмет витягується до найближчого магніту (якщо є краватка, об’єкт витягується праворуч), і він рухається в тому напрямку, поки не потрапить на магніт або інший об’єкт. Врешті-решт, всі об’єкти зібралися навколо магнітів. Порядок об’єктів зберігається.

Вихідні дані

Ваш вихід - це масив, де кожен об'єкт був витягнутий якнайближче до найближчого магніту. Він повинен мати той самий формат, що і вхідний.

Приклад

Розглянемо масив

[0,0,2,0,1,1,0,2,0,3,0,5,0,1,0]

Найменше лівий 2тягнеться до першої пари магнітів, як і до другої 2. 3Має магніт чотири кроків в обох напрямках, тому він отримує потягнули вправо. 5Також отримує потягнув вправо, і вона йде між 3і магнітом. Правильний вихід

[0,0,0,2,1,1,2,0,0,0,0,3,5,1,0]

Правила та оцінка

Ви можете написати повну програму або функцію. Виграє найменший кількість байтів, а стандартні лазівки заборонені.

Тестові кейси

[0,1,0] -> [0,1,0]
[1,0,2,0,0,1,0] -> [1,2,0,0,0,1,0]
[7,0,5,0,0,1,0] -> [0,0,0,7,5,1,0]
[1,0,3,0,1,0,3,0,1] -> [1,0,0,3,1,0,0,3,1]
[1,0,0,0,0,0,0,7,3] -> [1,7,3,0,0,0,0,0,0]
[1,2,3,4,5,6,7,8,9,10,11,0,0,0,1] -> [1,2,3,4,5,6,7,0,0,0,8,9,10,11,1]
[12,3,0,0,1,0,1,3,0,0,6,12,0,0,0,1] -> [0,0,12,3,1,0,1,3,6,0,0,0,0,0,12,1]

Відповіді:


7

Pyth, 28 20

o@.e?bhaDk_x1QkQ~hZQ

Дякую @ThomasKwa за гольф на 6 байт!

Це зловживає стабільним сортуванням, присвоюючи всім значень 1 або більше в списку індекс найближчого 1 (зв’язки, порушені до правого 1), а потім сортування списку за цими значеннями. Нулі задаються власним індексом як їх сортувальною вартістю.

Тестовий сюїт

Підтвердження люкс

Пояснення:

o@.e?bhaDk_x1QkQ~hZQ  ##  implicit: Q = eval(input())
o                  Q  ##  Sort Q using the values of the lambda below
 @              ~hZ   ##  select the value from the matching index of the enumerate
  .e           Q      ##  enumerate with b = value, k = index
    ?b                ##  ternary on b
      haDk_x1Q        ##  if true, this thing
              k       ##  otherwise use the index as the sort weight
          _x1Q        ##  the indices of 1 in Q, given in reverse order 
                      ##  (the reverse makes it sort to the right because of stable sorts)
       aDk            ##  sort those indices by |index - k|
      h               ##  take the first value

Приклад:

Візьмемо [1,0,3,0,1,0,3,0,1], наприклад, тестовий випадок . Коли ми застосуємо перерахування, всі нулі отримають свій власний індекс як сортове значення, тому я пропускаю їх і виконую один і три.

Для першого, ми отримаємо індекси них: [0, 4, 8]. Потім поверніть її назад і сортуйте за абсолютним значенням показників за мінусом індексу, який тут дорівнює нулю. Тож ми [0, 4, 8]знову повертаємось. Перше значення, 0тому ми використовуємо це.

Для трьох ми отримуємо зворотні індекси та проводимо те саме сортування, але використовуючи два як індекс трьох, тож як 0і 4даємо однакове значення для абсолютної різниці, тому отримуємо: [4, 0, 8]і беремо одиницю 4.

Тоді буде остаточний масив "сортування значень" [0, 1, 4, 3, 4, 5, 8, 7, 8]. Завдяки стабільному сортуванню зв'язки розриваються на порядок того, що значення з'явилися спочатку, тому ми отримуємо потрібний остаточний масив.


Сортування за індексом найближчих 1- хороша ідея!
Згарб

4

Сітківка , 97 72 байти

+`(?<=\b1(,1*)*?)(\B,(11+)|,(11+))\b(?!(?<-1>,1*)*,1\b)|(11+),\B
$3,$4$5

Очікується, що введення буде розділеним комами списком одинарних цілих чисел (провідні та кінцеві роздільники на кшталт [...]роботи справні).

Тут запустіть усі тестові справи. (Для зручності це турбується про перетворення з та в десятковий автоматично.)

Ось зовсім інша ідея, яка дозволяє уникнути дорогих балансуючих груп, використовуючи багатоступеневі. Наразі це на 6 байт довше, але, можливо, буде більш зіграно:

,1\b
>1
\b1,
1<
(T`,`<`<1*,
)T`,`>`,1*>
+`(1+>)>
>$1
+`<(<1+\b)(?!>)
$1<
<|>
,

Щойно я побачив цей виклик, я подумав, що Retina добре підійде (+1)
Michael Klein

@MichaelKlein Дякую, але я не дуже думаю, що це так. Я здивований, що навіть побив JavaScript, але я впевнений, що це не матиме шансів проти жодної з мов для гольфу.
Мартін Ендер

Добре підходить, як у мене, я одразу почав думати, як вирішити проблему в Retina
Michael Klein

3

JavaScript (ES6), 108 байт

a=>a.map(_=>a.map((x,i)=>x>1?a[j=(n=a.indexOf(1,i))<0|n-i>i-p?i-1:i+1]?0:a[a[i]=0,j]=x:x<1?0:p=i,p=-1/0))&&a

Пояснення

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

var solution =

a=>
  a.map(_=>                  // loop a.length times to ensure completeness
    a.map((x,i)=>            // for each cell item x at index i
      x>1?                   // if the cell contains metal
        a[j=                 // j = index of cell to move to
          (n=a.indexOf(1,i)) // n = index of next magnet
          <0|n-i>i-p?i-1:i+1 // set j to previous or next cell based on closest magnet
        ]?0:                 // if cell j is empty
          a[a[i]=0,j]=x      // set it to x and set cell i to 0
      :x<1?0:                // else if the cell contains a magnet
        p=i,                 // set p to the index of this magnet
      p=-1/0                 // p = index of previous magnet, initialise to -Infinity
    )
  )
  &&a                        // return a
<input type="text" id="input" value="1,2,3,4,5,6,7,8,9,10,11,0,0,0,1" />
<button onclick="result.textContent=solution(input.value.split(',').map(n=>+n))">Go</button>
<pre id="result"></pre>


2

PHP, 337 символів

<?$i=explode(",",$argv[1]);$m=$n=[];foreach($i as$k=>$v)if($v>0)eval("array_push(\$".($v<2?"m":"n").",$k);");for($p=0;$p<count($i);$p++)foreach($i as$k=>$v)if($v>1){$i[$k]=0;$r=-1;foreach($m as$_)if($r<0||abs($k-$r)>abs($_-$k))$r=$_;while($i[$r]>0)$r+=($r<$k?1:-1);$i[$r]=$v;}$s="";foreach($i as$v)$s.=$v.",";echo substr($s,0,-1)."\n";?>

Так, це дуже довго, тому що PHP насправді не є мовою для гри в гольф, але він працює, і я мав FUN, щоб це було добре для мене. Звичайно, я відкритий для можливих скорочень.

Також є маленька функція помилок, яка думає, наприклад, ось тут:

root@raspberrypi:~/stack# php magnet.php 12,3,0,0,1,0,1,3,0,0,6,12,0,0,0,1
0,0,3,12,1,0,1,3,6,0,0,0,0,0,12,1

це схоже на те, що 12 магічно потрапили перед 3, але це неправда!

3 поважає більшу кількість і дозволяє наблизитися до maget!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.