Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Поворот матрицы (http://www.flasher.ru/forum/showthread.php?t=182375)

FlashRus 21.07.2012 11:15

Поворот матрицы
 
Имеется матрица n * m.
Код:

0 4 0
4 4 4
4 0 4

Требуется, взависимости от полученного значения, в диапозоне [0 ; 4) развернуть матрицу.
то есть:
0
Код:

0 4 0
4 4 4
4 0 4

1
Код:

4 4 0
0 4 4
4 4 0

2
Код:

4 0 4
4 4 4
0 4 0

3
Код:

0 4 4
4 4 0
0 4 4

Решений в данном случае достаточно много, но все, найденые мной, либо громоздкие, либо не производительные. Хотелось бы какое нибудь комплексное, элегантное решение.

З.Ы. матрица может в любой n-ный момент быть любого из перечисленныхь видов.
Размерность матрицы неограничена и не обязательно является равносторонней (квадратом).

wvxvw 21.07.2012 14:02

А как задается матрица изначально? Вложенные массивы? Один массив упакованный каким-нибудь интересным способом например:
Код AS3:

function itemAt(x, y):Object {
    return this._array[y * this._width + x];
}

или
Код AS3:

function itemAt(x, y):Object {
    return this._array[this.cantorDiagonal(x, y)];
}

И их есть еще. В зависимости от подхода, естесственно, могут быть разные решения.

http://stackoverflow.com/questions/4...ensional-array кстати, тут есть интересное решение (в третьем ответе), где задается класс матрицы а при вращении меняется коеффициент в зависимости от которог индексы через которые идет обращение к элементам матрицы преобразуются к нужному виду, что делает вращение O(1) операцией вообще :)

FlashRus 21.07.2012 14:23

Цитата:

А как задается матрица изначально? Вложенные массивы?
да.

Цитата:

displayData = [[0,4,4][4,4,4][4,0,4]]
Касательно кода, можно по подробней...

wvxvw 21.07.2012 15:27

Код AS3:

package
{
        public class Matrix
        {
                public static const DEGREES_0:int = 0;
 
                public static const DEGREES_90:int = 1;
 
                public static const DEGREES_180:int = 2;
 
                public static const DEGREES_270:int = 3;
 
                private const _source:Array = [];
 
                private var _direction:int;
 
                private var _width:int;
 
                private var _height:int;
 
                public function Matrix(width:int, height:int)
                {
                        super();
                        this._width = width;
                        this._height = height;
                        this._source.length = width * height;
                }
 
                public function get(x:int, y:int):Object
                {
                        var result:Object;
                        this.assertOutOfBounds(x, y);
                        switch (this._direction)
                        {
                                case 0:
                                        result = this._source[y * this._width + x];
                                        break;
                                case 1:
                                        result = this._source[(this._width - x - 1) * this._width +
                                                (this._height - y - 1)];
                                        break;
                                case 2:
                                        result = this._source[(this._height - y - 1) * this._width +
                                                (this._width - x - 1)];
                                        break;
                                case 3:
                                        result = this._source[x * this._width + y];
                                        break;
                        }
                        return result;
                }
 
                public function set(x:int, y:int, value:Object):Object
                {
                        var result:Object;
                        this.assertOutOfBounds(x, y);
                        switch (this._direction)
                        {
                                case 0:
                                        result = this._source[y * this._width + x] = value;
                                        break;
                                case 1:
                                        result = this._source[(this._width - x - 1) * this._width +
                                                (this._height - y - 1)] = value;
                                        break;
                                case 2:
                                        result = this._source[(this._height - y - 1) * this._width +
                                                (this._width - x - 1)] = value;
                                        break;
                                case 3:
                                        result = this._source[x * this._width + y] = value;
                                        break;
                        }
                        return value;
                }
 
                public function rotate(rotation:int):void
                {
                        if (rotation < 0 || rotation > 3)
                                throw new ArgumentError("Invalid rotation");
                        this._direction = rotation;
                        if (rotation & 1)
                        {
                                this._width = this._height ^ this._width;
                                this._height = this._height ^ this._width;
                                this._width = this._height ^ this._width;
                        }
                }
 
                public function toString():String
                {
                        var result:String = "[";
                        for (var i:int; i < this._height; i++)
                        {
                                result += "[";
                                for (var j:int = 0; j < this._width; j++)
                                        result += this.get(j, i) + ", ";
                                if (this._width)
                                        result = result.substr(0, result.length - 2) + "],\n";
                        }
                        if (this._height) result = result.substr(0, result.length - 2);
                        return result + "]";
                }
 
                private function assertOutOfBounds(x:int, y:int):void
                {
                        if (this._width < x || this._height < y)
                                throw new ArgumentError("Index out of bounds");
                }
        }
}

Код AS3:

package
{
        import flash.display.Sprite;
 
        public class TestMatrix extends Sprite
        {
                public function TestMatrix()
                {
                        super();
                        this.test();       
                }
 
                private function test():void
                {
                        var matrix:Matrix = new Matrix(3, 3);
                        matrix.set(0, 0, 4);
                        matrix.set(1, 0, 0);
                        matrix.set(2, 0, 4);
                        matrix.set(0, 1, 4);
                        matrix.set(1, 1, 5);
                        matrix.set(2, 1, 6);
                        matrix.set(0, 2, 0);
                        matrix.set(1, 2, 4);
                        matrix.set(2, 2, 0);
                        trace(matrix);
                        matrix.rotate(Matrix.DEGREES_90);
                        trace(matrix);
                        matrix.rotate(Matrix.DEGREES_180);
                        trace(matrix);
                        matrix.rotate(Matrix.DEGREES_270);
                        trace(matrix);
                        matrix.rotate(Matrix.DEGREES_0);
                        trace(matrix);
                }
        }
}

Вроде бы правильно, на первый взгляд :) Но, смотрите, зависит от того, что нужно чаще делать, читать из матрицы или поворачивать. Но если существует возможность, что нужно будет несколько раз поворачивать подряд, не читая, то это как бы вообще крутое решение (опять же, заслуга не моя, а постера с СО).

FlashRus 21.07.2012 15:44

Вложений: 1
спасибо, wvxvw, попробую покурить этот вариант)

Вот моё решение... убого.. жуть вообще... оптимизировать и оптимизировать... но хоть так.

В моём решение много достаточно похожего кода, но свести к чему-то одному неполучается..


Часовой пояс GMT +4, время: 04:03.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.