Другу был нужен алгоритм, который позволял бы ему проходить по элементам матрицы NxM (N и M нечетные). Я придумал решение, но я хотел посмотреть, смогут ли мои коллеги-SO предложить лучшее решение.
Я публикую свое решение в качестве ответа на этот вопрос.
Пример вывода:
Для матрицы 3х3 вывод должен быть:
(0, 0) (1, 0) (1, 1) (0, 1) (-1, 1) (-1, 0) (-1, -1) (0, -1) (1, -1 )
Кроме того, алгоритм должен поддерживать неквадратные матрицы, поэтому, например, для матрицы 5x3 выходные данные должны быть:
(0, 0) (1, 0) (1, 1) (0, 1) (-1, 1) (-1, 0) (-1, -1) (0, -1) (1, -1 ) (2, -1) (2, 0) (2, 1) (-2, 1) (-2, 0) (-2, -1)
Ответы:
Вот мое решение (на Python):
источник
C ++ кто-нибудь? Быстрый перевод с питона, выложен для полноты
источник
Было предложено много решений этой проблемы, написанных на разных языках программирования, однако, похоже, что все они основаны на одном и том же замысловатом подходе. Я собираюсь рассмотреть более общую проблему вычисления спирали, которую можно выразить кратко, используя индукцию.
Базовый случай: начать с (0, 0), двигаться вперед на 1 клетку, повернуть налево, двигаться вперед на 1 клетку, повернуть налево. Шаг индукции: двигаться вперед n + 1 на квадраты, повернуть налево, двигаться вперед на n + 1 квадрат, повернуть налево.
Математическая элегантность выражения этой проблемы настоятельно предполагает, что должен быть простой алгоритм для вычисления решения. Имея в виду абстракцию, я выбрал не реализацию алгоритма на конкретном языке программирования, а псевдокод.
Сначала рассмотрим алгоритм для вычисления всего 2 итераций спирали с использованием 4 пар циклов while. Структура каждой пары похожа, но сама по себе отлична. Поначалу это может показаться сумасшедшим (некоторые циклы выполняются только один раз), но шаг за шагом я буду выполнять преобразования, пока мы не получим 4 пары циклов, которые идентичны и, следовательно, могут быть заменены одной парой, размещенной внутри другого цикла. Это даст нам общее решение для вычисления n итераций без использования каких-либо условий.
Первое преобразование, которое мы сделаем, - это введение новой переменной d для direction, которая содержит значение +1 или -1. Направление переключается после каждой пары петель. Поскольку мы знаем значение d во всех точках, мы можем умножить на него каждую сторону каждого неравенства, соответствующим образом скорректировать направление неравенства и упростить любые умножения d на постоянную до другой постоянной. Это оставляет нас со следующим.
Теперь отметим, что и x * d, и RHS являются целыми числами, поэтому мы можем вычесть из RHS любое действительное значение в диапазоне от 0 до 1, не влияя на результат неравенства. Мы выбираем вычитать 0.5 из неравенств любой другой пары циклов while, чтобы получить больше паттернов.
Теперь мы можем ввести другую переменную m для количества шагов, которые мы предпринимаем в каждой паре циклов while.
Наконец, мы видим, что структура каждой пары циклов while идентична и может быть сведена к одному циклу, помещенному внутри другого цикла. Кроме того, чтобы избежать использования вещественных чисел, я умножил начальное значение m; значение m увеличивается на; и обе стороны каждого неравенства по 2.
Это приводит к решению, показанному в начале этого ответа.
источник
Вот решение O (1), чтобы найти положение в квадрате спирали: Скрипка
источник
if (n === 0) return [0, 0, r]; --n;
См. Fiddle: jsfiddle.net/Wishmesh/nwd9gt1s/2Я люблю генераторы питона.
Тестирование с:
Ты получаешь:
источник
Спираль Java "Код гольф" попытка, основанная на варианте C ++.
источник
Вот решение C ++, которое показывает, что вы можете легко и просто рассчитать следующие (x, y) координаты из предыдущих - не нужно отслеживать текущее направление, радиус или что-либо еще:
Если все, что вы пытаетесь сделать, это сгенерировать первые N точек на спирали (без ограничения маскирования исходной задачи на область N x M), код становится очень простым:
Хитрость в том, что вы можете сравнить x и y, чтобы определить, на какой стороне квадрата вы находитесь, и это говорит вам, в каком направлении двигаться.
источник
TDD, на Java.
SpiralTest.java:
Spiral.java:
источник
Вот мое решение (в рубине)
источник
Хаскелл, сделай свой выбор:
источник
Это в с.
Я случайно выбрал плохие имена переменных. В именах T == вверху, L == слева, B == внизу, R == справа. Итак, tli это верхний левый угол i, а brj нижний правый угол j.
источник
У меня есть библиотека с открытым исходным кодом, pixelscan , которая представляет собой библиотеку python, которая предоставляет функции для сканирования пикселей на сетке в различных пространственных структурах. Пространственные модели включают в себя круговые, кольца, сетки, змей и случайные прогулки. Существуют также различные преобразования (например, клип, своп, вращение, перевод). Исходная проблема ОП может быть решена следующим образом
который дает очки
Генераторы библиотек и преобразования могут быть объединены в цепочку для изменения точек в широком диапазоне порядков и пространственных структур.
источник
Вот решение в Python 3 для печати последовательных целых чисел по спирали по часовой стрелке и против часовой стрелки.
объяснение
Спираль состоит из концентрических квадратов, например квадрат 5х5 с вращением по часовой стрелке выглядит следующим образом:
(
>>>>>
означает «перейти в 5 раз вправо» или увеличить индекс столбца в 5 раз,v
означает уменьшить или увеличить индекс строки и т. д.)Все квадраты одинаковы по своим размерам, я перебрал концентрические квадраты.
Для каждого квадрата в коде есть четыре цикла (по одному для каждой стороны), в каждом цикле мы увеличиваем или уменьшаем столбцы или индекс строки. Если
i
это индекс строки и индексj
столбца, то квадрат 5x5 можно построить следующим образом: - увеличиваяj
от 0 до 4 (5 раз) - увеличиваяi
от 1 до 4 (4 раза) - уменьшаяj
с 3 до 0 (4 раза) - уменьшаяi
от 3 до 1 (3 раза)Для следующих квадратов (3x3 и 1x1) мы делаем то же самое, но смещаем начальный и конечный индексы соответствующим образом. Я использовал индекс
k
для каждого концентрического квадрата, есть n // 2 + 1 концентрических квадратов.Наконец, немного математики для красивой печати.
Чтобы распечатать индексы:
источник
Вот c #, linq'ish.
Первый пример вопроса (3x3) будет:
Второй пример вопроса (5x3):
источник
Это немного другая версия - пытаюсь использовать
recursion
иiterators
в LUA. На каждом шаге программа опускается дальше внутрь матрицы и зацикливается. Я также добавил дополнительный флаг в спиральclockwise
илиanticlockwise
. Вывод начинается с правого нижнего угла и рекурсивно зацикливается по направлению к центру.источник
// реализация PHP
источник
Вот итеративное решение этой проблемы с помощью JavaScript (ES6):
Вот как это использовать:
spiralMatrix(0, 0, 1, 100);
Это создаст внешнюю спираль, начинающуюся с координат (x = 0, y = 0) с шагом 1 и общим количеством элементов, равным 100. Реализация всегда начинает движение в следующем порядке - вверх, вправо, вниз, осталось.
Обратите внимание, что эта реализация создает квадратные матрицы.
источник
Вот ответ Джулии: мой подход заключается в назначении точек в концентрических квадратах («спиралях») вокруг начала координат
(0,0)
, где каждый квадрат имеет длину стороныm = 2n + 1
, для создания упорядоченного словаря с номерами местоположений (начиная с 1 для начала координат) в качестве ключей и соответствующая координата в качестве значения.Поскольку максимальное положение на спираль составляет
(n,-n)
, остальные точки можно найти, просто работая в обратном направлении от этой точки, то есть от нижнего правого угла наm-1
единицы, а затем повторяя для перпендикулярных 3 сегментовm-1
единиц.Этот процесс записан в обратном порядке ниже, в соответствии с тем, как протекает спираль, а не с процессом обратного подсчета, то есть
ra
[правый возрастающий] сегмент уменьшается3(m+1)
, затемla
[левый восходящий]2(m+1)
и т. Д. - надеюсь, это самоочевидно ,Итак, для вашего первого примера, включение
m = 3
в уравнение для поиска n даетn = (5-1)/2 = 2
иwalk(2)
дает упорядоченный словарь местоположений для координат, который вы можете превратить в просто массив координат, обратившись кvals
полю словаря :Обратите внимание, что для некоторых функций [например
norm
] может быть предпочтительнее оставить координаты в массивах, чемTuple{Int,Int}
, но здесь я изменяю их в кортежи -(x,y)
- по запросу, используя понимание списка.Контекст «поддержка» не-квадратная матрица не указана (обратите внимание , что это решение все еще вычисляет значения вне сетки), но если вы хотите , чтобы фильтр только в диапазон
x
отy
(здесьx=5
,y=3
) после вычисления полной спирали тогдаintersect
эта матрица против значений изwalk
.источник
Ваш вопрос выглядит как вопрос, называемый спиральной памятью. В этой задаче каждый квадрат на сетке размещается в виде спирали, начиная с номера 1, который находится в начале координат. А затем подсчитывать, двигаясь по спирали наружу. Например:
Мое решение для вычисления координат каждого числа по этой спиральной схеме опубликовано ниже:
источник
Это основано на вашем собственном решении, но мы можем быть умнее в поиске углов. Это облегчает понимание того, как можно пропустить области снаружи, если M и N сильно различаются.
и решение на основе генератора, которое лучше, чем O (max (n, m) ^ 2). Это O (nm + abs (nm) ^ 2), потому что оно пропускает целые полосы, если они не являются частью решения.
источник
источник
Это моё очень плохое решение, основанное на минимальных знаниях Java. Здесь я должен разместить юниты на поле по спирали. Юниты нельзя размещать поверх других юнитов, в горах или в океане.
Чтобы было ясно. Это не хорошее решение. Это очень плохое решение, добавленное для того, чтобы другие люди смеялись над тем, как плохо это можно сделать.
Слава всем, кто действительно может прочитать это
Бонусный вопрос: каково время работы этого «алгоритма»? :П
источник
Решение для AutoIt
источник
Недавно у меня была похожая проблема, когда мне пришлось создать двумерный массив и использовать алгоритм спиральной матрицы для сортировки и печати результатов. Этот код C # будет работать с N, N 2D массивом. Это является подробным для ясности и, вероятно, может быть переработано, чтобы соответствовать вашим потребностям.
источник
Я сделал это с другом, который настраивает соотношение сторон спирали и холста в Javascript. Лучшее решение, которое я получил для эволюции изображения пиксель за пикселем, заполняя все изображение.
Надеюсь, это кому-нибудь поможет.
Вы можете видеть, как это работает на http://jsfiddle.net/hitbyatruck/c4Kd6/ . Просто убедитесь, что изменили ширину и высоту холста в javascript vars и в атрибутах HTML.
источник
Просто для удовольствия в Javascript:
источник
Версия C #, также обрабатывает неквадратные размеры.
источник
Я делюсь этим кодом, который я разработал для другой цели; речь идет о поиске номера столбца «X» и номера строки «Y» элемента массива @ спирального индекса «index». Эта функция принимает ширину «w» и высоту «h» матрицы, а также необходимый «индекс». Конечно, эту функцию можно использовать для получения того же требуемого результата. Я думаю, что это самый быстрый из возможных методов (поскольку он перепрыгивает через ячейки, а не сканирует их).
источник
Python зацикливает спиральный код по часовой стрелке, используя ответ Can Berk Güder .
источник
Отличное решение Davidont в VB.Net
источник