Зігзагіфікуйте матрицю


43

У рамках свого алгоритму стиснення стандарт JPEG розгортає матрицю у вектор уздовж антидіагоналів змінного напрямку:

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

Ваше завдання - взяти матрицю (не обов'язково квадратну) і повернути її в розкрученому вигляді. Як приклад:

[1 2 3 4
 5 6 7 8
 9 1 2 3]

повинні врожаї

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

Правила

Можна припустити, що елементи матриці мають натуральні цілі, менші ніж 10.

Ви можете написати програму або функцію, взявши введення через STDIN (або найближчу альтернативу), аргумент командного рядка або аргумент функції та вивівши результат через STDOUT (або найближчу альтернативу), значення повернення функції або параметр функції (out).

Матриця введення може бути надана у будь-якому зручному, однозначному, вкладеному списку чи рядковому форматі, або у вигляді плоского списку разом із обома розмірами матриці. (Або, звичайно, як тип матриці, якщо у вас є мова.)

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

Діють стандартні правила .

Випробування

[[1]]                                               => [1]
[[1 2] [3 1]]                                       => [1 2 3 1]
[[1 2 3 1]]                                         => [1 2 3 1]
[[1 2 3] [5 6 4] [9 7 8] [1 2 3]]                   => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1 2 3 4] [5 6 7 8] [9 1 2 3]]                     => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1 2 6 3 1 2] [5 9 4 7 8 3]]                       => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1 2 5 9 6 3 4 7 1 2 8 3]]                         => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1] [2] [5] [9] [6] [3] [4] [7] [1] [2] [8] [3]]   => [1 2 5 9 6 3 4 7 1 2 8 3]

Супутні виклики


1
Чи може вхід бути фактичною матрицею в J? Або потрібно було б перетворити з вкладених списків у матрицю як частину функції?
Гарет

4
Якщо ми візьмемо матрицю як двовимірний масив, чи можемо ми все-таки прийняти розміри як вхідні дані?
xnor

1
@Gareth так, ви можете взяти тип введення матриці.
Мартін Ендер

1
@xnor Хм, це трохи складніше. Я відчуваю, що прийняття такої кількості зайвої інформації трохи переробляє введення.
Мартін Ендер

Чи може плоский список бути в порядку основного стовпця, якщо це рідний порядок мови?
Луїс Мендо

Відповіді:


27

J, 31 30 14 12 11 байт

[:;<@|.`</.

Іч . Занадто великий.

Бере матрицю як вхід.

Пояснення

J має перевагу тут. Існує команда під назвою oblique ( /.), яка бере по черзі косі рядки і застосовує до них дієслово. У цьому випадку я використовую герунду, щоб по черзі застосовувати два дієслова: <( box ) і <@|.( reverse and box). Тоді справа лише в тому, щоб розпакувати все, використовуючи ;( ніде ).


26
J - єдина мова, яка змушує мене відчувати, що мені потрібен ступінь англійської мови, щоб зрозуміти це.
Олексій А.

2
@AlexA. btw, слово "команда" повинно було бути "прислівником".
Адам

11

Pyth, 24 23 21 20 19 18 17 байт

ssm_W=!Td.T+LaYkQ

Чергова 17-байтна версія: ssuL_G=!T.T+LaYkQ

                Q  input
           +L      prepend to each subarray...
             aYk   (Y += ''). Y is initialized to [], so this prepends [''] to
                     the first subarray, ['', ''] to the second, etc.
                   ['' 1  2  3  4
                    '' '' 5  6  7  8
                    '' '' '' 9  1  2  3]
         .T        transpose, giving us
                   ['' '' ''
                    1  '' ''
                    2  5  ''
                    3  6  9
                    4  7  1
                    8  2
                    3]
  m_W=!Td          black magic
 s                 join subarrays together
s                  join *everything* on empty string (which means ''s used for
                     padding disappear)

Дякуємо @FryAmTheEggman за байт, @Jakube за 2 байти та @isaacg за байт!

Пояснення "чорної магії", на яке згадувалося вище: m_W=!Tdпо суті реверсує кожен інший підрив. Це робиться шляхом зіставлення _W=!Tкожного підмасива; Wце умовне застосування, тому воно _(повертає) всі підматриці, де =!Tє правдою. Tє змінною, попередньо ініціалізованою на десять (truthy), і =!Tозначає (T = !T). Таким чином, він перемикає значення змінної, яка починає truthy і повертає нове значення, а це означає, що воно буде чергуватися між поверненнями ложною, truthy, фальшивою, truthy ... (заслуга Якубе за цю ідею)

Тут ви знайдете тестовий набір .


11

Желе, 24 19 15 13 11 байт

pS€żị"¥pỤị⁵

Кількість рядків, кількість стовпців і плоский список приймає як окремі аргументи командного рядка.

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

Як це працює

pS€żị"¥pỤị⁵  Main link. Argument: m (rows), n (columns), A (list, flat)

p            Compute the Cartesian product [1, ..., m] × [1, ..., n]. This yields
             the indices of the matrix M, i.e., [[1, 1], [1, 2], ..., [m, n]].
 S€          Compute the sums of all index pairs.
       p     Yield the Cartesian product.
      ¥      Dyadic chain. Arguments: Sums, Cartesian product.
    ị"       For each index pair in the Cartesian product, retrieve the coordinate
             at the index of its sum, i.e., map [i, j] to i if i + j is odd and to
             j if i + j is even.
   ż         Zip the sums with the retrieved indices.
       Ụ     Sort [1, ..., mn] by the corresponding item in the resulting list.
        ị⁵   Retrieve the corresponding items from A.

Цк. Я не впевнений, чи зможу я тепер зробити своє коротшим. : -S
Гарет

Це не означає, що я не намагатимусь ...
Гарет

Чому ще не успадкував косой? Чи можу я запропонувати гліфи APL і ? А може, скандинавський øі ǿ?
Адам

7

MATL , 28 27 байт

tZyZ}:w:!+-1y^7MGn/*-X:K#S)

Адаптований з моєї відповіді тут . Загальна ідея полягає у створенні 2D масиву такого ж розміру, що і вхідний, наповнений значеннями, що збільшуються в тому ж порядку, що і шлях зигзагу. Потім сортується лінеаризована (згладжена) версія цього масиву і зберігаються індекси цього сортування. Це показники, які потрібно застосувати до вхідних даних, щоб створити зигзагоподібний шлях.

Введіть форму

[1 2 3; 5 6 4; 9 7 8; 1 2 3]

Пояснення

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

t       % input 2D array. Duplicate
ZyZ}    % get size as length-2 vector. Split into two numbers: r, c
:       % range [1,2,...,c] as a row vector
w:!     % swap, range [1;2;...;r] as a column vector
+       % add with broadcast. Gives a 2D array
-1      % push -1
y^      % duplicate previous 2D array. Compute -1 raised to that
7M      % push [1;2;...;r] again
Gn/     % divide by input matrix size, that is, r*c
*       % multiply
-       % subtract
X:      % linearize 2D array into column array
K#S     % sort and push the indices of the sorting. Gives a column vector
)       % index input matrix with that column vector

4

Матлаб, 134 байти

Я просто намагався максимально скоротити свій код у Matlab, як телеграфувати його.

function V=z(M)
[m,n]=size(M);
a=(1:m)'*ones(1,n);
b=ones(m,1)*(1:n);
A=a+b-1;
B=a-b;
C=(A.^2+(-1).^A.*B+1);
[~,I]=sort(C(:));
V=M(:);
V=V(I)';

Примітки:

  1. Mє m×nматрицею.
  2. aі bобидві матриці однакового розміру M, кожен рядок aскладається з чисел, рівних номеру його рядка, в той час як кожен стовпець bдорівнює його номеру стовпця. Таким чином, a+ b- це матриця, елемент якої дорівнює сумі її рядка та номера стовпця, тобто matrix(p,q)=p+q.
  3. Таким чином A(p,q)=p+q-1,; і B(p,q)=p-q.
  4. Cматематично подано як рівняння нижче. Зігзагіфіковано збільшуючи матрицю з рівнянням може бути зроблена зигзагіфікована матриця, що збільшується, як показано нижче.
C =
     1     2     6     7
     3     5     8    14
     4     9    13    18
    10    12    19    25
  1. Cвказує на порядок елементів М у зигзагіфікованих результатах. Потім, [~,I]=sort(C(:));повертає порядок, тобто I, таким чином, V=V(I)'є результатом.

Так, я просто знайшов його, зараз я його оновлюю.
Гоян Цинь

@AlexA. Дякую, Алекс. Тому що я новачок у цьому, я хочу скоротити його якомога коротше, але зробити його фрагментом. Тепер я ще виправив свій код.
Гоян Цинь

Виглядає добре. Гарний перший пост! :)
Олексій А.

3

JavaScript (SpiderMonkey 30+), 99 байт

x=>[for(y of[...x,...x[0]].keys())for(z of Array(y+1).keys())if(a=x[y%2?z:y-z])if(b=a[y%2?y-z:z])b]

Тестовано у Firefox 44. Вводить дані як двовимірний масив.


3

Пітон 2, 84 байти

lambda N,w,h:[N[i*w+s-i]for s in range(w+h+1)for i in range(h)[::s%2*2-1]if-1<s-i<w]

Перенесення відповіді німі . Займає плоский масив із заданою шириною та висотою. xsot збережено байт.


88 байт:

lambda M,w,h:[M[i]for i in sorted(range(w*h),key=lambda i:(i/w+i%w,-i*(-1)**(i/w+i%w)))]

Займає плоский масив із заданою шириною та висотою. Сортуйте відповідні 2D координати (i/w,i%w)в порядку зигзагоподібного порядку збільшення суми, щоб отримати діагоналі, зв'язані або збільшуючи, або зменшуючи значення рядка, виходячи з того, чи є рядка плюс стовпець непарним чи парним.


Що якщо стан можна ще більше скоротити.
xsot

@xsot Хороший улов.
xnor

3

Haskell, 79 78 73 байт

(m#h)w=[m!!(y*w+x-y)|x<-[0..h+w],y<-g!!x$[0..x],y<h,x-y<w]
g=reverse:id:g

Вхід - це плоский список із кількістю рядків та стовпців, наприклад ( [1,2,6,3,1,2,5,9,4,7,8,3] # 2) 6-> [1,2,5,9,6,3,4,7,1,2,8,3].

Як це працює: пройдіть координати матриці x та y ( hрядки, wстовпці) у двох вкладених петлях:

  | 0 1 2 3 4 5 6 7 8    outer loop               Index is y*w+x-y, i.e.
--+------------------    x from 0 to h+w          the elements are accessed
0 | 1 2 6 3 1 2                                   in the following order:
1 | 5 9 4 7 8 3
2 |                                               1 2 4 6  8 10 
3 |                                               3 5 7 9 11 12
4 |
5 |
6 |
7 | inner loop:
8 | y from 0 to x

тобто зверху / праворуч вниз / ліворуч, пропускаючи з обмежених індексів ( yі xповинні задовольняти y<hі x-y<w). Коли xрівне число, порядок внутрішньої петлі змінюється на зворотному рівні: yпереходить від xдо 0. Я роблю це, вибираючи функцію модифікації для y-діапазону, [0..x]який є xth-м елементом [reverse,id,reverse,id,...].

Редагувати: @xnor перевпорядкував цикли і зберег 5 байт. Дякую!


Я думаю, ти можеш зробити g=id:reverse:g.
xnor

В круглих дужках на multication (y-x)*wможна відрізати перестановку проблеми: (m#h)w=[m!!(x*w+y-x)|y<-[0..h+w],x<-g!!y$[0..y],x<h,y-x<w] g=reverse:id:g. Переклад на Python економить 3 символи над тим, що я мав.
xnor

1

Python 2 + NumPy, 122 байти

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

import numpy
def f(m):w=len(m);print sum([list(m[::-1,:].diagonal(i)[::(i+w+1)%2*-2+1])for i in range(-w,w+len(m[0]))],[])

Приймає нумерований масив як вхідний. Виводить список.

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

Пояснення:

def f(m):
    w=len(m)    # the height of the matrix, (at one point I thought it was the width)
    # get the anti-diagonals of the matrix. Reverse them if odd by mapping odd to -1
    d=[list(m[::-1,:].diagonal(i)[::(i+w+1)%2*-2+1])for i in range(-w,w+len(m[0]))]
            # w+len(m[0]) accounts for the width of the matrix. Works if it's too large.
    print sum(d,[]) # join the lists

Лямбда однакової довжини:

import numpy
lambda m:sum([list(m[::-1,:].diagonal(i)[::(i+len(m)+1)%2*-2+1])for i in range(-len(m),len(m)+len(m[0]))],[])

1

Python 3, 131 118 115 107 байт

На підставі того ж Прінсіпі , як мій відповідь на виклик Deusovi в

Я припускаю, що ми не можемо мати нуль у вхідній матриці

e=enumerate
lambda s:[k for j,i in e(zip(*[([0]*n+i+[0]*len(s))for n,i in e(s)]))for k in i[::j%2*2-1]if k]

Пояснення

як це працює :

            pad with 0      transpose    remove 0    reverse line           concatenate 
                                                     with even index
1 2 3       1 2 3 0 0        1 0 0        1            1                
4 5 6   --> 0 4 5 6 0    --> 2 4 0    --> 2 4     -->  2 4              -->  1 2 4 7 5 3 6 8 9
7 8 9       0 0 7 8 9        3 5 7        3 5 7        7 5 3             
                             0 6 8        6 8          6 8               
                             0 0 9        9            9

Результати

>>> [print([i,f(i)]) for i in [[[1]], [[1, 2], [3, 1]], [[1, 2, 3, 1]], [[1, 2, 3], [5, 6, 4], [9, 7, 8], [1, 2, 3]], [[1, 2, 3, 4], [5, 6, 7, 8], [9, 1, 2, 3]], [[1, 2, 6, 3, 1, 2], [5, 9, 4, 7, 8, 3]], [[1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]], [[1], [2], [5], [9], [6], [3], [4], [7], [1], [2], [8], [3]]]]
# [input,                                                          output]
[[[1]],                                                            [1]]
[[[1, 2], [3, 1]],                                                 [1, 2, 3, 1]]
[[[1, 2, 3, 1]],                                                   [1, 2, 3, 1]]
[[[1, 2, 3], [5, 6, 4], [9, 7, 8], [1, 2, 3]],                     [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1, 2, 3, 4], [5, 6, 7, 8], [9, 1, 2, 3]],                       [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1, 2, 6, 3, 1, 2], [5, 9, 4, 7, 8, 3]],                         [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]],                           [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1], [2], [5], [9], [6], [3], [4], [7], [1], [2], [8], [3]],     [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]

Чи reverse even lineслід reverse odd linesзамість цього?
nwp

@nwp індекс починається з 0 ^^
Ерван

Ах, ви говорите про номери рядків, а не про довжину рядка. Я переплутав це, вибачте.
nwp

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