Блочная сортировка строк и столбцов в двумерном массиве


15

Учитывая двумерный массив целых чисел, давайте отсортируем его строки и столбцы по блокам. Это означает, что вам нужно только отсортировать заданную строку или столбец, но применить преобразования, необходимые для сортировки, для каждой другой строки или столбца в двумерном массиве.

правила

  • Входными данными будут двумерный массив целых чисел и целое число с 1 индексом. Это целое число будет представлять строку, подлежащую сортировке, если число положительное, или столбец, подлежащий сортировке, если число отрицательное (или наоборот, если вы хотите). Пример: учитывая 4x3массив (строки х столбцов), вы можете отсортировать второй столбец с помощью-2 аргументом или третью строку с 3аргументом. Этот второй аргумент никогда не будет нулевым, и его абсолютное значение никогда не будет больше соответствующего измерения массива.
  • Выходными данными будет также двумерный массив целых чисел с необходимыми преобразованиями, примененными для сортировки заданной строки или столбца. В качестве альтернативы вы можете просто записать массив в STDOUT.
  • В выходном массиве указанная строка или столбец будут отсортированы в порядке возрастания. Просто обратите внимание, что когда вам нужно поменять местами два числа, будут поменяны все столбцы, в которых лежат числа. И когда вам нужно поменять местами два числа в столбце, все строки, где лежат числа, будут поменяны местами.
  • В случае, когда одно и то же число появляется в сортируемой строке / столбце несколько раз, будет возможно несколько решений в зависимости от того, как вы меняете значения, просто сделайте это с остальными строками / столбцами, которые нужно поменять местами.

Примеры

Positive indices for rows and negative indices for columns

[5  8  7  6                                  [1  3  2  4
 1  3  2  4   order by -3 (3rd column)  -->   9  6  3  0
 9  6  3  0]                                  5  8  7  6]

[5  8  7  6                                  [9  6  3  0
 1  3  2  4   order by -4 (4th column)  -->   1  3  2  4
 9  6  3  0]                                  5  8  7  6]

[5  8  7  6                                  [5  7  8  6
 1  3  2  4     order by 2 (2nd row)  -->     1  2  3  4
 9  6  3  0]                                  9  3  6  0]

[5  8  7  6                                  [6  7  8  5
 1  3  2  4     order by 3 (3rd row)  -->     4  2  3  1
 9  6  3  0]                                  0  3  6  9]

[1  2                                    [1  2     [3  2
 3  2]   order by -2 (2nd column)  -->    3  2] or  1  2]  (both are valid)

[7  5  9  7                                  [5  7  7  9     [5  7  7  9
 1  3  2  4     order by 1 (1st row)  -->     3  1  4  2  or  3  4  1  2
 9  6  3  0]                                  6  9  0  3]     6  0  9  3]

Это , поэтому может выиграть самый короткий код для каждого языка!


Это происходит из песочницы .
Чарли

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

1
@ LuisfelipeDejesusMunoz да, это указано в вопросе.
Чарли

Может ли строка / столбец содержать повторяющиеся числа?
Кевин Круйссен,

@KevinCruijssen да, посмотрите последние примеры и последний пункт правил.
Чарли

Ответы:


7

R , 55 байт

function(x,n)`if`(n>0,x[,+x[n,]],x[+x[,-n],])
`+`=order

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

Переназначает +оператор (фактически функцию в R) на orderфункцию, которая возвращает индексы вектора от наименьшего к наибольшему. Тогда это просто манипулирование массивом.





4

Japt , 18 17 байт

отрицательный для строк и положительный для столбцов

>0?VñgUÉ:ßUa Vy)y

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


Это терпит неудачу, когда Uотрицательно - предыдущая 17-байтовая версия работает, хотя.
лохматый

@ Shaggy Мой плохой, я думал, что все равно будет работать, совсем не проверял
Луис Фелипе Де Иисус Муньос,

Неплохая идея, однако, передача функции в качестве первого аргумента ßэтого автоматически применяется к U. Это может создать проблемы с попыткой передать буквальные строки, но в любом случае опубликовать предложение в репозитории GitHub для дальнейшего изучения.
Лохматый

4

05AB1E , 25 24 14 байтов

diø}Σ¹Ä<è}¹diø

Колоссальные 10 байт благодаря @Emigna .

Использует положительный целочисленный ввод для сортировки строк, отрицательный для столбцов.

Попробуйте онлайн или проверьте все контрольные примеры .

Объяснение:

di }      # If the (implicit) integer input is positive:
  ø       #  Swap the rows and columns of the (implicit) matrix input
          #   i.e. 3 and [[5,8,7,6],[1,3,2,4],[9,6,3,0]]
          #    → [[5,1,9],[8,3,6],[7,2,3],[6,4,0]]
Σ    }    # Sort the rows of this matrix by:
 ¹Ä       #  Take the absolute value of the input
          #   i.e. -3 → 3
   <      #  Decreased by 1 to make it 0-indexed
          #   i.e. 3 → 2
    è     #  And index it into the current row
          #   i.e. [5,8,7,6] and 2 → 7
          #   i.e. [5,1,9] and 2 → 9
          #  i.e. [[5,1,9],[8,3,6],[7,2,3],[6,4,0]] sorted by [9,6,3,0]
          #   → [[6,4,0],[7,2,3],[8,3,6],[5,1,9]]
          #  i.e. [[5,8,7,6],[1,3,2,4],[9,6,3,0]] sorted by [7,2,3]
          #   → [[1,3,2,4],[9,6,3,0],[5,8,7,6]]
¹di       # And if the integer input was positive:
   ø      #  Swap the rows and columns back again now that we've sorted them
          #   i.e. 3 and [[6,4,0],[7,2,3],[8,3,6],[5,1,9]]
          #    → [[6,7,8,5],[4,2,3,1],[0,3,6,9]]
          # (And implicitly output the now sorted matrix)

1
Я получил, diø}Σ¹Ä<è]¹diøчто является подмножеством вашего, поэтому я не публикую отдельный ответ.
Emigna

@ Emigna Данг, ты так легко выглядишь ... Теперь, когда я это вижу, я не могу поверить, что сама об этом не думала, но в то же время это гениально ... Спасибо! Огромные 10 байтов сохранены благодаря вам.
Кевин Круйссен

4

JavaScript (ES6), 90 байт

t=m=>m[0].map((_,x)=>m.map(r=>r[x]))
f=(m,k)=>k<0?m.sort((a,b)=>a[~k]-b[~k]):t(f(t(m),-k))

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

Как?

У JS нет собственного метода транспонирования, поэтому нам нужно определить его:

t = m =>              // given a matrix m[]
  m[0].map((_, x) =>  // for each column at position x in m[]:
    m.map(r =>        //   for each row r in m[]:
      r[x]            //     map this cell to r[x]
    )                 //   end of map() over rows
  )                   // end of map() over columns

Основная функция:

f = (m, k) =>         // given a matrix m[] and an integer k
  k < 0 ?             // if k is negative:
    m.sort((a, b) =>  //   given a pair (a, b) of matrix rows, sort them:
      a[~k] - b[~k]   //     by comparing a[-k - 1] with b[-k - 1]
    )                 //   end of sort
  :                   // else:
    t(f(t(m), -k))    //   transpose m, call f() with -k and transpose the result

Пример с :Кзнак равно2

Mзнак равно(587613249630)T(M)знак равно(519836723640)е(T(M),-2)знак равно(519723836640)е(M,2)знак равноT(е(T(M),-2))знак равно(578612349360)

3

MATL , 17 байт

y0>XH?!]w|2$XSH?!

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

Или проверьте все тестовые случаи

объяснение

y       % Implicit inputs: number n, matrix M. Duplicate from below: pushes n, M, n
0>      % Greater than 0?
XH      % Copy into clipboard H
?       % If true
  !     %   Transpose matrix. This way, when we sort the rows it will correspond
        %   to sorting the columns of the original M
]       % End
w       % Swap: moves n to top
|       % Absolute value
2$XS    % Two-input sortrows function: sorts rows by specified column
H       % Push contents from clipboard H
?       % If true
  !     %   Transpose again, to convert rows back to columns
        % Implicit end
        % Implicit display


2

Python 2 , 71 70 байт

f=lambda m,n:n<0and sorted(m,key=lambda l:l[~n])or zip(*f(zip(*m),-n))

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


Если n отрицательное, строки сортируются по столбцу n.

В противном случае матрица транспонируется, сортируется таким же образом и транспонируется обратно.



1

C # (.NET Core) , 186 байт

(x,y)=>{Func<int[][],int[][]>shift=a=> a[0].Select((r,i)=>a.Select(c=>c[i]).ToArray()).ToArray();return y>0?shift(shift(x).OrderBy(e=>e[y-1]).ToArray()):x.OrderBy(e=>e[-y-1]).ToArray();}

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

Ungolfed:

    private static int[][] Blocksort0a(int[][] array, int sortingInstruction)
    {
        Func<int[][], int[][]> shift = a => a[0].Select((r, i) => a.Select(c => c[i]).ToArray()).ToArray();

        sortingInstruction++;

        array = sortingInstruction < 0 ? 
        shift(shift(array).OrderBy(e => e[-sortingInstruction]).ToArray()) 
             : 
        array.OrderBy(e => e[sortingInstruction]).ToArray();

        return null;
    }

Функция сдвига мы будем использовать дважды, поэтому переменная функции сэкономит место. Функция выполняет итерацию по горизонтальному измерению массива по индексу и добавляет каждый элемент по этому индексу каждого горизонтального массива в новый выходной массив (по горизонтали) - почти так же, как в решении JS от Arnoud.

Теперь упорядочение простое, упорядочить горизонтальный массив по номеру при индексе (аргумент -1), опционально сдвигая массив до и после сортировки.

Если посмотреть, как конкретно вопрос говорит о массивах, мы конвертируем в массив несколько раз (очень, очень расточительно). Чувствовать себя немного глупо, чтобы использовать такой многословный язык в коде гольф хе-хе.


1

C # (.NET Core) , 142/139 138/135 байт (и еще один -1 Кевина)

(a,s)=>s<0?a.OrderBy(e=>e[~s]).ToArray():a.Select(f=>a[s-1].Select((v,j)=>new{v,j}).OrderBy(e=>e.v).Select(e=>f[e.j]).ToArray()).ToArray()

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

Ungolfed:

    private static int[][] Blocksort0b(int[][] array, int sortingInstruction)
    {
        if (sortingInstruction < 0) { return array.OrderBy(e => e[-sortingInstruction - 1]).ToArray(); }
        var rowIndices = array[sortingInstruction - 1].Select((value, index) => (value, index)).OrderBy(e => e.value);
        var newRow = new int[array[0].Length];
        for (var i = 0; i < array.Length; i++)
        {
            int horizontalIndexer = 0;
            foreach (var e in rowIndices)
            {
                newRow[horizontalIndexer++] = array[i][e.index];
            }
            array[i] = newRow.ToArray();
        }
        return array;
    }

Новый всесторонний подход; отрицательный ответ по-прежнему упорядочивает массивы по элементам по индексу. В противном случае создается коллекция пара-значение-индекс из массива-по-индексу и сортируется по значению. Это эффективно создает коллекцию индексов в порядке необходимости добавления. Затем для каждого массива выбираются элементы в заранее определенных позициях. Немного подрезания кода и безобразного, безобразного, безобразного ** тихого рыдания ** повторного использования входных параметров, и вот, пожалуйста, 142 байта.

Опять же, аргумент массива строго соблюдается, добавляя довольно много накладных расходов для вызовов .ToArray ().

135 байтов утверждают, а ?! Подсказанные значения-кортежи C # 7.2 обрезали бы дополнительные три байта, но tio.run не позволяет. Таким образом, это ответ, который я решил опубликовать для легкой проверки.


1
Хороший ответ. Есть несколько мелочей для игры в гольф. (a,s)=>может быть карри a=>s=>. (s<0)?не нуждается в скобках, и -s-1может быть ~s. Попробуйте онлайн: 137 байтов
Кевин Круйссен,

Сладкий! Я никогда не позволил бы функции возвращать еще одну функцию для сохранения символа, я приятно удивлен. Благодарность! Также веский случай вопиющего упущения не операторов и скобок. Я обновил not и скобки, но оставлю вам всю честь для функции-returning-function.
Бародус

1

Java (OpenJDK 8) , 326 байт

(a,b)->{int l=a.length,w=a[0].length,k,m,t,i;if(b>0){for(i=0;i<w;i++){for(k=1;k<(w-i);k++){if(a[b-1][k-1]>a[b-1][k]){for(m=0;m<l;m++){t=a[m][k];a[m][k]=a[m][k-1];a[m][k-1]=t;}}}}}else{b*=-1;for(i=0;i<l;i++){for(k=1;k<(l-i);k++){if(a[k-1][b-1]>a[k][b-1]){for(m=0;m<w;m++){t=a[k][m];a[k][m]=a[k-1][m];a[k-1][m]=t;}}}}}return a;}

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

Ну, ребята, этот вопрос был очень расстраивающим для меня, и я отправил свой ответ, Зная, что я что-то забыл, к счастью, у нас есть легенды, такие как Кевин Круйссен , чтобы помочь нам :)

Java (OpenJDK 8) , 281 байт

a->b->{int l=a.length,w=a[0].length,k,m,t,i;if(b>0)for(i=0;i<w;i++)for(k=0;++k<w-i;)for(m=0;a[b-1][k-1]>a[b-1][k]&m<l;a[m][k]=a[m][k-1],a[m++][k-1]=t)t=a[m][k];else for(b*=-1,i=0;i<l;i++)for(k=0;++k<l-i;)for(m=0;a[k-1][b-1]>a[k][b-1]&m<w;a[k][m]=a[k-1][m],a[k-1][m++]=t)t=a[k][m];}

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


Я еще не рассматривал реальный алгоритм, но вы можете сэкономить 35 байт, удалив все скобки и поместив все в циклы (включая внутренний оператор if). Попробуйте онлайн: 291 байт. РЕДАКТИРОВАТЬ: Здесь с пробелами, чтобы вы могли более четко увидеть изменения, которые я сделал.
Кевин Круйссен,

@KevinCruijssen Я знал, что что-то упустил
X1M4L

Кроме того, вы можете сделать это вводом карри a->b->вместо (a,b)->и удалить return-statement, так как вы изменяете массив ввода. 281 байт. Тем не менее, хороший ответ. +1 от меня. Я выполнил задание в 05AB1E, но на этот раз даже не попробовал бы его на Java. ;)
Кевин Круйссен





1

красный , 190 185 байт

func[b n][t: func[a][c: length? a/1 a: to[]form a
d: copy[]loop c[append/only d extract a c take a]d]d: does[if n > 0[b: t b]]d
m: absolute n sort/compare b func[x y][x/(m) < y/(m)]d b]

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

Объяснение:

f: func [ b n ] [
    t: func [ a ] [                            ; helper transpose function 
        c: length? a/1                         ; c is the length of the rows
        a: to-block form a                     ; flatten the list
        d: copy []                             ; an empty block (list)
        loop c [                               ; do as many times as the number of columns  
            append/only d extract a c          ; extract each c-th element (an entire column)
                                               ; and append it as a sublist to d
            take a                             ; drop the first element
        ] 
        d                                      ; return the transposed block (list of lists)
    ]
   d: does [ if n > 0 [ b: t b ] ]             ; a helper function (parameterless) to transpose 
                                               ; the array if positive n
   d                                           ; call the function  
   m: absolute n                               ; absolute n
   sort/compare b func[ x y ] [ x/(m) < y/(m) ]; sort the array according to the chosen column 
   d                                           ; transpose if positive n
   b                                           ; return the array  
]

Мое реальное решение имеет длину 175 байт, но оно не работает в TIO. Вот он, работает нормал в красной консоли:

Красный , 175 байт

func[b n][d: does[if n > 0[c: length? b/1 a: to-block form b
t: copy[]loop c[append/only t extract a c take a]b: t]]d
m: absolute n sort/compare b func[x y][x/(m) < y/(m)]d b]

0

VBA (Excel), 205 байтов

Ура! 2-й длинный отсчет байтов! Я не совсем проиграл: D

Golfed:

Sub d(a)
With ActiveSheet.Sort
  .SortFields.Clear
  .SortFields.Add Key:=IIf(a<0,ActiveSheet.Columns(Abs(a)),ActiveSheet.Rows(Abs(a)))
  .SetRange ActiveSheet.UsedRange
  .Orientation=IIf(a<0,1,2)
  .Apply
End With
End Sub

Это сортирует все данные на открытом (активном) рабочем листе, используя UsedRange ..., который может содержать ошибки, но должен содержать только отредактированные ячейки.

UnGolfed:

Sub d(a)
  'Clear any Sort preferences that already exists
  ActiveSheet.Sort.SortFields.Clear
  'Use the column if A is negative, the row if A is positive
  ActiveSheet.Sort.SortFields.Add Key:=IIf(a < 0, ActiveSheet.Columns(Abs(a)), ActiveSheet.Rows(Abs(a)))
  'Set the area to sort
  ActiveSheet.Sort.SetRange ActiveSheet.UsedRange
  'Orient sideways if sorting by row, vertical if by column
  ActiveSheet.Sort.Orientation = IIf(a < 0, xlTopToBottom, xlLeftToRight)
  'Actually sort it now
  ActiveSheet.Sort.Apply
End Sub

Если вы предполагаете, что активным листом является sheet1, то вы можете уменьшить его до 169 байт какSub d(a) With Sheet1.Sort .SortFields.Clear .SortFields.Add IIf(a<0,Columns(Abs(a)),Rows(Abs(a))) .SetRange Sheet1.UsedRange .Orientation=(a<0)+2 .Apply End With End Sub
Taylor Scott

Кроме того, я думаю, что вы можете с уверенностью предположить, что не .SortFieldsопределено, поэтому вы также можете удалить .Sortfields.Clearстроку.
Тейлор Скотт

0

Perl 6 , 43 байта

{($!=$_>0??&[Z]!!*[])o*.sort(*[.abs-1])o$!}

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

Функция карри.

объяснение

{                                         } # Block returning function composed of
                                       o$!  # 1. Apply $! (transpose or not)
                     o*.sort(*[.abs-1])     # 2. Sort rows by column abs(i)-1
     $_>0??&[Z]                             # 3. If i > 0 transpose matrix
               !!*[]                        #    Else identity function
 ($!=               )                       #    Store in $!

0

Physica , 45 байт

Очень похоже на ответ Арно .

F=>n;m:n<0&&Sort[->u:u{~n};m]||Zip@F#Zip@m#-n

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

Как это устроено?

Более подробное и наглядное объяснение можно найти в связанном ответе.

F=>n;m:           // Create a function F that takes two arguments, n and m.
       n<0&&      // If n < 0 (i.e. is negative)
Sort[->u{~n};m]   // Sort the rows u of m by the result of the function u[~n].
                  // In short, sort by indexing from the end with n.
||    F#Zip@m#-n  // Else, apply F to Zip[m] and -n. Uses a new feature, binding.
  Zip@            // And transpose the result.


0

Clojure, 91 байт

(fn f[A i](if(< i 0)(sort-by #(nth %(- -1 i))A)(apply map list(f(apply map list A)(- i)))))

Argh, apply map list* 2.

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