Зигзагообразная матрица


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
@ Гарет да, вы можете взять тип матрицы в качестве входных данных.
Мартин Эндер

1
@xnor Хммм, это немного сложнее. Я чувствую, что взятие такого количества избыточной информации идет на предварительную обработку ввода.
Мартин Эндер

Может ли плоский список быть в главном порядке столбцов, если это родной порядок языка?
Луис Мендо

Ответы:


27

J, 31 30 14 12 11 байт

[:;<@|.`</.

Ych . Слишком большой.

Принимает матрицу в качестве ввода.

объяснение

У J здесь есть преимущество. Есть команда с именем oblique ( /.), которая по очереди принимает косые линии и применяет к ним глагол. В этом случае я использую герунду для попеременного применения двух глаголов: <( коробка ) и <@|.( реверс и коробка). Тогда это просто вопрос распаковки всего, используя ;( raze ).


26
J - единственный язык, который заставляет меня чувствовать, что мне нужна высшая степень по английскому языку, чтобы понять это.
Алекс А.

2
@AlexA. Кстати, слово «команда» должно было быть «наречие».
Адам

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является условным приложением, поэтому оно _(переворачивает) все подмассивы, где =!Ttrue. Tпеременная, предварительно инициализированная до десяти (правда), и =!Tозначает (T = !T). Таким образом, он переключает значение переменной, которая начинается с истинного и возвращает новое значение, что означает, что он будет чередоваться с возвращением ложного, правдивого, ложного, правдивого ... (заслуга Якуба за эту идею)

Тестовый набор здесь .


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.

Tsk. Я не уверен, смогу ли я сделать мой короче сейчас. : -S
Гарет

Это не значит, что я не буду пытаться ...
Гарет

Почему Желе еще не унаследовал Oblique? Могу ли я предложить символы APL и ? А может и скандинавские øа ǿ?
Адам

7

MATL , 28 27 байт

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

Адаптировано из моего ответа здесь . Общая идея заключается в создании двумерного массива того же размера, что и входные данные, заполненного значениями, которые увеличиваются в том же порядке, что и зигзагообразный путь. Затем линеаризованная (уплощенная) версия этого массива сортируется, и индексы этой сортировки сохраняются. Это те индексы, которые необходимо применить к входным данным, чтобы получить зигзагообразный путь.

Ввод в форме

[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

Matlab, 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указывает порядок элементов M в зигзагированных результатах. Затем [~,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. Принимает ввод в виде 2D-массива.


3

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

Принимает плоский массив с заданной шириной и высотой. Сортирует соответствующие двухмерные координаты (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]который является xэлементом th [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]))],[])

Принимает массив numpy в качестве входных данных. Выводит список.

Попробуйте онлайн

Объяснение:

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 начинается в 0 ^^
Эрван

Ах, вы говорите о номерах строк, а не о длине строки. Я перепутал те, извините.
16:00

@nwp np, кстати, я изменил его, чтобы избежать путаницы
Эрван
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.