Зсипте пісок


12

(Є пов’язані питання щодо нескінченних пісковиків та пошуку елементів ідентичності пісковиків .)

Давши матрицю невід'ємних цілих чисел, поверніть матрицю таких самих розмірів, але пересипану :

  1. Якщо матриця не містить значень більше 4, поверніть її.
  2. Кожна "комірка", що перевищує 3, зменшується на 4, а всі безпосередньо сусідні комірки (вгорі, внизу, зліва та справа) збільшуються, якщо вони існують.
  3. ГОТО 1.

Приклади:

0 1 0        0 2 0
2 4 0   ->   3 0 1
0 0 3        0 1 3

1 2 3    2 3 4    2 5 1    4 1 2    0 3 3    0 3 3    0 3 3
4 5 6 -> 2 4 4 -> 4 2 3 -> 0 5 4 -> 3 2 1 -> 3 3 1 -> 3 3 2
7 8 9    5 7 7    2 6 5    4 3 2    0 5 3    1 1 4    1 2 0

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

Більш глибоке пояснення та певна мотивація дивіться у цьому відео "Numberphile" чи статті у Вікіпедії про абелеву модель пісочника .

Правила:

  • Ви можете приймати введення та вихід будь-яким із стандартних способів
  • Лазівки заборонені
  • Вхід і вихід можуть бути:
    • вкладений список: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    • простий список: [1, 2, 3, 4, 5, 6, 7, 8, 9]і форма
    • якийсь рідний тип матриці
    • рядок, наприклад 1 2 3\n4 5 6\n7 8 9
    • або що б там не було на вашій мові.
  • Вхід і вихід повинні бути в одній формі
  • Вхід може містити більші числа, ніж наведені тут, але розмір може бути обмежений межами вашої мови (MAXINT еквіваленти, якщо це застосовується)
  • Матриця може мати будь-яку форму (наприклад, 1x1, 2x2, 3x3, 4x4, 2x7, 11x3, ...)
  • Вам не потрібно обробляти випадок, коли форма дорівнює 0xN або Nx0.

Тестові шафи

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

Це , найкоротший код (на кожну мову).


Чи добре відображати всі проміжні результати?
feersum

@feersum Я думаю, що так, поки зрозуміло, який кінцевий результат.
L3viathan

Відповіді:


8

MATL , 17 байт

tss:"t3>t1Y6Z+w4*-+

Спробуйте в MATL Online! Або перевірити всі тестові випадки .

Пояснення

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

Для кожної ітерації 3виявляються записи, що перевищують матрицю пісковика , даючи матрицю 1та 0, яка поєднана з 4-сусідською маскою. Записи, що перевищують 3в матриці пісковика, зменшуються 4, а результат згортки додається.

Для останніх ітерацій, в яких матриця пісковика не має чисельних чисел 3, нулі віднімаються і додаються до неї, тому це не впливає.

t       % Implicit input (matrix). Duplicate
ss      % Sum of matrix entries
:"      % Repeat that many times
  t     %   Duplicate
  3>    %   True for matrix entries that exceed 3
  t     %   Duplicate
  1Y6   %   Push predefined literal [0, 1, 0; 1, 0, 1; 0, 1, 0]
  Z+    %   2D convolution, keeping size
  w     %   Swap
  4*    %   Multiply by 4
  -     %   Subtract
  +     %   Add
        % Implicit end. Implicit display

3
Свиток високої п'ятірки.
Мартін Ендер

@MartinEnder Ах, ти також це використовував :-) Приємно бачити колега-переворота! Я впевнений, що недолік приєднається до нас найближчим часом
Луїс Мендо

2
@LuisMendo Convolutionista
Suever

4

Математика, 65 байт

#//.s_:>s+ListConvolve[{v={0,1,0},1-v,v},x=UnitStep[s-4],2,0]-4x&

Пояснення

#//.s_:>...&

Неодноразово трансформуйте вхід, перебиваючи всі палі більше 3. Цей процес зупиняється автоматично, коли перетворення не змінює матрицю (тобто коли більше великих паль не існує). У наступному виразі матриця називається s.

...x=UnitStep[s-4]...

Створіть матрицю, яка має кожен 1раз, коли поточна матриця має a 4або більше, а нуль інакше. По суті це маска, яка вказує, які палі потрібно скинути. Викликайте маску x.

ListConvolve[{v={0,1,0},1-v,v},x=UnitStep[s-4],2,0]

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

0 1 0
1 0 1
0 1 0

По суті, він додає по одній до поточної комірки для кожного з сусідів фон-Неймана в масці.

s+...-4x

Додаємо попередній результат, sа потім віднімаємо від нього чотири рази маску, щоб зменшити перевалені палі.


3

Октава, 65 байт

Це здається не дуже гарним, я мушу пропустити деякі хитрощі ...

m=input(0);do;m+=conv2(m>3,[0 1 0;1 -4 1;0 1 0],"same")
until m<4

Яку версію Octave ви використовуєте, що дозволяє input(0)?
Suever

@Suever>> version ans = 4.0.1
feersum

2

JavaScript (ES6), 101 95 байт

Бере ширину матриці wта масив значень aу синтаксисі currying (w)(a). Повертає масив значень.

w=>g=a=>(b=a.map((n,i)=>n%4+(F=d=>~m|i%w&&a[i+d]>>2)(m=w)+F(-w)+F(m=-1)+F(!++i)))+0==a+0?a:g(b)

Відформатовано та прокоментовано

w =>                      // main function: takes w as input, returns g
  g = a =>                // recursive function g: takes a as input
    (                     //
      b = a.map((n, i) => // for each element n at position i in a:
        n % 4 + (         //   keep only n MOD 4
          F = d =>        //   define F(): function that takes d as input
            ~m |          //     if m is not equal to -1
            i % w &&      //     or i MOD w is not null:
            a[i + d] >> 2 //       return a fourth of the value of the cell at i + d
        )(m = w) +        //   test the cell below the current cell
        F(-w) +           //   test the cell above
        F(m = -1) +       //   test the cell on the left
        F(!++i)           //   test the cell on the right
      )                   // end of map(): assign the result to b
    ) + 0 == a + 0 ?      // if b is equal to a:
      a                   //   stop recursion and return a
    :                     // else:
      g(b)                //   do a recursive call with b

Тестові справи


1

JavaScript (ES6), 118 114 104 байт

Збережено 2 байти завдяки @Neil

f=a=>a.find(b=>++y&&b.find(c=>++x&&c>3,x=0),y=0)?f(a.map(b=>b.map(c=>c+=--i|y?i*i+y*y==1:-4,i=x,--y))):a

Чи (i-=x)|y-j?i*i+допомагає?
Ніл

@Neil Це дійсно, дякую!
ETHproductions

... Я був по телефону, але я теж розглядав a.find(...b.find(...c>3&&a.map(...)))&&f(a).
Ніл

@Neil Я не думаю, що це спрацює, оскільки .mapне мутує ...
ETHproductions

Здається, що його мутація коштує трохи менше, ніж переміщення карти всередині знахідки економить:f=a=>a.find((b,x)=>b.find((c,y)=>c>3&&a.map(b=>b.map((_,j)=>b[j]+=x|(j-=y)?x*x+j*j==1:-4)&x--)))&&f(a)
Ніл

1

C ++, 261 258 250 байт

#import<vector>
#define S size()
void f(std::vector<std::vector<int>>&m){s:int i,j,r;for(i=r=0;i<m.S;++i)for(j=0;j<m[i].S;++j){if(m[i][j]>3){r=1;m[i][j]-=4;j>0&&m[i][j-1]++;i>0&&m[i-1][j]++;j<m[i].S-1&&m[i][j+1]++;i<m.S-1&&m[i+1][j]++;}}if(r)goto s;}

Приймає введення як посилання на вектор векторів і безпосередньо його модифікує.

Спробуйте в Інтернеті!

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