• + 1 comment

    Perl:

    sub rotate_matrix {
        my ($matrix, $r) = @_;
        my $rows = scalar @$matrix;
        my $cols = scalar @{$matrix->[0]};
        
        my $num_layers = int(min($rows, $cols) / 2);
        
        for my $layer (0 .. $num_layers - 1) {
            my @ring = extract_ring($matrix, $layer, $rows, $cols);
            my $perimeter = scalar @ring;
    
            my $effective_r = $r % $perimeter;
            @ring = (@ring[$effective_r .. $#ring], @ring[0 .. $effective_r - 1]);
            
            place_ring($matrix, \@ring, $layer, $rows, $cols);
        }
    }
    
    sub extract_ring {
        my ($matrix, $layer, $rows, $cols) = @_;
        my @ring;
    
        for my $i ($layer .. $cols - $layer - 1) {
            push @ring, $matrix->[$layer][$i];
        }
    
        for my $i ($layer + 1 .. $rows - $layer - 1) {
            push @ring, $matrix->[$i][$cols - $layer - 1];
        }
    
        for my $i (reverse $layer .. $cols - $layer - 2) {
            push @ring, $matrix->[$rows - $layer - 1][$i];
        }
    
        for my $i (reverse $layer + 1 .. $rows - $layer - 2) {
            push @ring, $matrix->[$i][$layer];
        }
    
        return @ring;
    }
    
    sub place_ring {
        my ($matrix, $ring_ref, $layer, $rows, $cols) = @_;
        my @ring = @$ring_ref;
        my $index = 0;
    
        for my $i ($layer .. $cols - $layer - 1) {
            $matrix->[$layer][$i] = $ring[$index++];
        }
    
        for my $i ($layer + 1 .. $rows - $layer - 1) {
            $matrix->[$i][$cols - $layer - 1] = $ring[$index++];
        }
    
        for my $i (reverse $layer .. $cols - $layer - 2) {
            $matrix->[$rows - $layer - 1][$i] = $ring[$index++];
        }
    
        for my $i (reverse $layer + 1 .. $rows - $layer - 2) {
            $matrix->[$i][$layer] = $ring[$index++];
        }
    }
    
    sub matrixRotation {
        my ($matrix, $r) = @_;
        
        rotate_matrix($matrix, $r);    
        foreach my $row (@$matrix) {
            print "@$row\n";
        }
    }
    
    sub min {
        return $_[0] < $_[1] ? $_[0] : $_[1];
    }