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

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)
Arnauld
источник
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.

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

TFeld
источник
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), опционально сдвигая массив до и после сортировки.

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

Barodus
источник
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 не позволяет. Таким образом, это ответ, который я решил опубликовать для легкой проверки.

Barodus
источник
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];}

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

X1M4L
источник
Я еще не рассматривал реальный алгоритм, но вы можете сэкономить 35 байт, удалив все скобки и поместив все в циклы (включая внутренний оператор if). Попробуйте онлайн: 291 байт. РЕДАКТИРОВАТЬ: Здесь с пробелами, чтобы вы могли более четко увидеть изменения, которые я сделал.
Кевин Круйссен,
@KevinCruijssen Я знал, что что-то упустил
X1M4L
Кроме того, вы можете сделать это вводом карри a->b->вместо (a,b)->и удалить return-statement, так как вы изменяете массив ввода. 281 байт. Тем не менее, хороший ответ. +1 от меня. Я выполнил задание в 05AB1E, но на этот раз даже не попробовал бы его на Java. ;)
Кевин Круйссен
270 байт
floorcat
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
seadoggie01
источник
Если вы предполагаете, что активным листом является 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 $!
nwellnhof
источник
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.
Мистер Xcoder
источник
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.

NikoNyrh
источник