Вращение 2D-матрицы


30

Допустим, у меня есть следующая (2D) матрица:

[[1,  2,  3,  4 ],
 [5,  6,  7,  8 ],
 [9,  10, 11, 12],
 [13, 14, 15, 16]]

Поверните матрицу против часовой стрелки R (не с шагом 90 градусов, просто на 1 число каждый раз),

1  2  3  4             2 3   4  8         3   4   8  12
5  6  7  8    -->      1 7  11 12   -->   2  11  10  16 
9  10 11 12            5 6  10 16         1   7   6  15 
13 14 15 16            9 13 14 15         5   9  13  14

Завершенный пример:

Входные данные:

2
[[1,  2,  3,  4 ],
 [5,  6,  7,  8 ],
 [9,  10, 11, 12],
 [13, 14, 15, 16]]

Выход:

[[3,  4,  8, 12],
 [2, 11, 10, 16],
 [1,  7,  6, 15],
 [5,  9, 13, 14]]

(странные пробелы для выравнивания чисел в хороших столбцах)

Внешнее «кольцо» матрицы вращается на 2 против часовой стрелки, а внутреннее правое вращается также на 2. В этой матрице есть только два кольца.

Пример с 1 «кольцом»:

2
[[1, 2],
 [3, 4],
 [5, 6]]

Должен вывести:

[[4, 6],
 [2, 5],
 [1, 3]]

Ваша задача - взять матрицу и целое число Rи вывести переведенную версию после Rповоротов.

Вращение матрицы 4x5 представлено на следующем рисунке: введите описание изображения здесь

Ограничения:

  • 2 ≤ M, N ≤ 100где М и N - размеры матрицы. Гарантируется, что минимум M и N будет четным.
  • 1 ≤ R ≤ 80где r - число оборотов.
  • Матрица будет содержать только положительные целые числа.
  • Ценности не всегда различны.
  • Входные данные всегда должны быть в виде двумерного массива (если вы не можете использовать входные данные во время выполнения в качестве двумерного массива, вам просто нужно найти другой способ получения ввода).

Еще один тестовый пример с нечеткими значениями:

1
[[1, 1],
 [2, 2],
 [3, 3]]

Выходы:

[[1, 2],
 [1, 3],
 [2, 3]]

Это , поэтому выигрывает самый короткий ответ!





4
@ceasedtoturncounterclockwis Ваше имя очень иронично для этой задачи ...
HyperNeutrino

1
[[3, 4, 8, 12], [2, 11, 10, 16], [1, 7, 6, 16], [5, 9, 13, 14]]16 внезапно дублируется я предполагаю , что это должно быть: [[3, 4, 8, 12], [2, 11, 10, 16], [1, 7, 6, 15], [5, 9, 13, 14]]?
Кристоф

Ответы:



5

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

function M=F(M,R);f=@(z)[-z/2:-1 !eye(!!mod(z,2)) 1:z/2];t=angle(f([x y]=size(M))'+f(y)*i);B=!!M;B(2:x-1,2:y-1)=0;d=bwdist(B,'ch');[~,I]=sortrows([d(:) t(:)]);for k=0:max(d(:));M(h)=shift(M(h=I(d(I)==k)),R);end

Попробуйте это на Octave Online!

Безголовая версия:

function M=F(M,R)
    [x y]=size(M);
    f=@(z)[-z/2:-1 !eye(!!mod(z,2)) 1:z/2];
    t=angle(f(x)'+f(y)*i);
    B=!!M;
    B(2:x-1,2:y-1)=0;
    d=bwdist(B,'chessboard');
    [~,I]=sortrows([d(:) t(:)]);
    for k=0:max(d(:))
        M(h)=shift(M(h=I(d(I)==k)),R);
    end
end
R=2;
M=randi(10,4,7)
F(M,R)

Объяснение:

f=@(z)[-z/2:-1 !eye(!!mod(z,2)) 1:z/2]; 

Функция, которая получает число и генерирует диапазон, который упорядочен и центрирован для ввода 4 (четный), генерирует -2 -1 1 2
для ввода 5 (нечетный) генерирует -2.5 -1.5 0 1 2
только его следует упорядочить и центрировать

f(x)'+f(y)*i    

сложная матрица, сгенерированная из диапазонов

(-2,-2.5) (-2,-1.5) (-2,0) (-2,1) (-2,2)
(-1,-2.5) (-1,-1.5) (-1,0) (-1,1) (-1,2)
(1,-2.5)  (1,-1.5)  (1,0)  (1,1)  (1,2)
(2,-2.5)  (2,-1.5)  (2,0)  (2,1)  (2,2)

t=angle(f(x)'+f(y)*i);                    

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

-2.25  -2.50  3.14  2.68  2.36
-1.95  -2.16  3.14  2.36  2.03
-1.19  -0.98  0.00  0.79  1.11
-0.90  -0.64  0.00  0.46  0.79


B=!!M;
B(2:x-1,2:y-1)=0;

Следующая матрица сгенерирована

1   1   1   1   1
1   0   0   0   1
1   0   0   0   1
1   1   1   1   1

d=bwdist(B,'chessboard');

Вычисляет преобразование расстояния B с использованием расстояния шахматной доски для генерации индексов кольца

0   0   0   0   0
0   1   1   1   0
0   1   1   1   0
0   0   0   0   0               

для матрицы 6 * 7 мы будем иметь следующую матрицу

0   0   0   0   0   0   0
0   1   1   1   1   1   0
0   1   2   2   2   1   0
0   1   2   2   2   1   0
0   1   1   1   1   1   0
0   0   0   0   0   0   0   

[~,I]=sortrows([d(:) t(:)]);

лексикографическая сортировка сначала по индексу кольца, а затем по порядку угла (возвращаются индексы отсортированных элементов)

    for k=0:max(d(:))
        M(h)=shift(M(h=I(d(I)==k)),R);
    end

и, наконец, круговое смещение каждого кольца.


4

Python 3, 292 288 байт

_=eval
a=input().split()
b,a=int(a[0]),_("".join(a[1:]))[::-1]
c=len(a)
d=len(a[0])
e=range
f="int((i>=j and i+j<c-1)|2*(i>=c/2and i+d>j+c)|3*(i<c/2and i+j<d))"
l=[-1,1,0,0],[0,0,1,-1]
g=lambda x:[[x[i+l[0][_(f)]][j+l[1][_(f)]]for j in e(d)]for i in e(c)]
print(_("g("*b+"a"+")"*b)[::-1])

Принимает ввод с удаленными символами новой строки, но оставляя пробел после числа приращений, чтобы повернуть его.

Объяснение:

Вместо того, чтобы моделировать матрицу как серию концентрических колец в соответствии с предложением ОП, можно вместо этого разделить ее на четыре области, где элементы перемещаются вверх, вниз, вправо или влево за один оборот. Это цель длинной строки с eval-ed f: определить, в какую область i,jпопадает каждая комбинация. Затем результат этого ищется дважды l, давая элемент, который должен повернуться в позицию i,jна следующем шаге. Функция, gкоторая делает все это и формирует новую матрицу после одного шага, затем вызывается повторно путем оценки сгенерированной строки, содержащей представление вызова вложенной функции.

Когда я сделал это изначально, я случайно заставил матрицу вращаться по часовой стрелке, а не против часовой стрелки. Вместо того, чтобы делать правильное исправление, я добавил две стратегически размещенные копии, [::-1]чтобы повернуть матрицу до и после поворота. Вероятно, они могут быть заполнены до ~ 280 276 байт, но мне лень это делать.

Кроме того, это быстрый непроверенный порт из немного более длинной программы на Python 2, так что простите, если он работает не совсем правильно. Вот код Python 2, в любом случае:

_=eval
a=raw_input().split()
b,a=int(a[0]),_("".join(a[1:]))[::-1]
c=len(a)
d=len(a[0])
e=xrange
f="int((i>=j and i+j<c-1)|2*(i>=c/2and i+d>j+c)|3*(i<c/2and i+j<d))"
l=[-1,1,0,0],[0,0,1,-1]
g=lambda x:[[x[i+l[0][_(f)]][j+l[1][_(f)]]for j in e(d)]for i in e(c)]
print _("g("*b+"a"+")"*b)[::-1]

EDIT: Golfed от 4 байта, заменив orв |два раза. andК сожалению, ничего не поделаешь.


Добро пожаловать в PPCG! Хороший первый пост!
HyperNeutrino

Забавная история на самом деле - в моем оркестре в старшей школе сегодня мы узнали группу, в которой все движутся в концентрических прямоугольных «кольцах», похожих на этот вопрос, и я сразу же подумал об этом ответе.
Эйдан Ф. Пирс

1

Perl 330 328 байт

sub f{($r,$m)=@_;$h=@m=@$m;for$s(0..(($w=$#{$m[0]})<--$h?$w:$h)/2-.5){@_=(@{$m[$s]}[@x=$s..($x=$w-$s)],(map$m[$_][$x],@y=1+$s..($y=$h-$s)-1),reverse(@{$m[$y]}[@x]),(map$m[$h-$_][$s],@y));push@_,shift
for 1..$r;@{$m[$s]}[@x]=map shift,@x;$m[$_][$x]=shift for@y;@{$m[$y]}[@x]=reverse map shift,@x;$m[$h-$_][$s]=shift for@y}@$m=@m}

Попробуйте это на Ideone .

Ungolfed:

sub f {
    my ($r, $m) = @_;

    my @m = @$m;
    my $h = $#m;
    my $w = @{$m[0]} - 1;
    my $c = (($w < $h ? $w : $h) + 1) / 2 - 1;

    for my $s (0 .. $c) {
        my $x = $w - $s;
        my $y = $h - $s;
        my @x = $s .. $x;
        my @y = $s + 1 .. $y - 1;

        # One circle.
        @_ = (@{$m[$s]}[@x],
              (map { $m[$_][$x] } @y),
              reverse(@{$m[$y]}[@x]),
              (map { $m[$h - $_][$s] } @y));

        # Circular shift.
        push(@_, shift(@_)) for 1 .. $r;

        @{$m[$s]}[@x] = map { shift(@_) } @x;
        $m[$_][$x] = shift(@_) for @y;
        @{$m[$y]}[@x] = reverse(map { shift(@_) } @x);
        $m[$h - $_][$s] = shift(@_) for @y;
    }

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