Вы должны написать программу или функцию, которая принимает неотрицательное целое число в N
качестве входных данных и выводит или возвращает два целых числа (отрицательное, нулевое или положительное) X
и Y
.
Целые числа подразумеваются в математическом смысле, поскольку их бесконечно много.
Реализованная функция должна быть биективной . Это означает, что для каждого N
он должен вывести отдельную X
Y
пару, и каждая X
Y
пара должна быть выведена для некоторого ввода, N
то есть все следующие пары должны быть выведены для некоторого N
:
...
┌─────┬─────┬────┬────┬────┐
│-2 -2│-2 -1│-2 0│-2 1│-2 2│
├─────┼─────┼────┼────┼────┤
│-1 -2│-1 -1│-1 0│-1 1│-1 2│
├─────┼─────┼────┼────┼────┤
... │0 -2 │0 -1 │0 0 │0 1 │0 2 │ ...
├─────┼─────┼────┼────┼────┤
│1 -2 │1 -1 │1 0 │1 1 │1 2 │
├─────┼─────┼────┼────┼────┤
│2 -2 │2 -1 │2 0 │2 1 │2 2 │
└─────┴─────┴────┴────┴────┘
...
Обратите внимание, что U V
и V U
разные пары, если U!=V
.
Детали
- Если ваш язык не поддерживает произвольно большие целые числа, это нормально, но ваш алгоритм должен работать с произвольно большим целочисленным типом данных. Ваш код должен по-прежнему поддерживать входные значения по крайней мере
2^31-1
. - Если вы решите напечатать или вернуть вывод в виде строки, начальные
0
символы или+
знаки не допускаются. В противном случае стандартное целочисленное представление вашего языка в порядке.
пример
Если задача состоит в том, чтобы сделать биективную функцию с неотрицательным целым числом N
и вывести одно целое число, X
решением может быть функция
if (input mod 2 == 0) return N/2 else return -(N+1)/2
,
реализовано на каком-то языке. Эта функция возвращает X = 0 -1 1 -2 2...
для N = 0 1 2 3 4...
.
10=>11 12, 9=>10 11
, это неверно, потому что 11 повторяется?Ответы:
Пиф, 15
Попробуйте онлайн.
Перевод Python:
или итеративно:
где
binlist
преобразует число в список цифр, какbinlist(4) = [1,0,0]
.Так как же это работает? Он интерпретирует двоичные цифры числа как два перемеженных числа в базе отрицательных двух, как в моем решении Python .N
Двоичное число соответствует паре ( x , y ) = ( b 0 - 2 b 2 + 4 b 4 - 8 b 6 + ⋯ , b 1 - 2 б 3 + 4 б 5 - 8 б 7 + ⋯ )
Если бы мы еще не обработали последнюю цифру из n , все индексы были бы выше на $ 1 $, n ′ = … b 5 b 4 b 3 b 2 b 1, соответствующих паре ( x ′ , y ′ ) = ( b 1 - 2 b 3 + 4 b 5 - 8 b 7 + ⋯ , b 2 - 2 b 4б0 N
источник
CJam,
242221 байтМой мозг не может понять математику, которую используют другие решения. Но мой мозг определенно понимает бинарный код, так что вот вам подсказка, основанная на битовых манипуляциях!
Попробуйте онлайн.
объяснение
Этот подход обрабатывает входные данные как два чередующихся двоичных значения, по одному для каждого выходного числа. Все, кроме младшего значащего бита каждого, кодируют величину, а младший значащий бит сигнализирует, следует ли принимать побитовое дополнение этой величины. В этой реализации биты с нечетным позиционированием соответствуют первому выходному номеру (а биты с нечетным позиционированием соответствуют второму) и младшему разряду
0
сигналов для принятия дополнения.Например, при заданном входе
73
, чередование его двоичного представления1001001b
производит0 1|0
(биты с нечетным позиционированием) и1 0 0|1
(биты с четным позиционированием). Первое значение имеет величину01b = 1
и должно быть дополнено до конечного значения~1 = -2
, а второе значение имеет величину100b = 4
и не должно дополняться.Неформальная демонстрация правильности
Я сделал тестовую программу, которая помещает каждый вход от нуля до указанного пользователем числа минус один в своем месте вывода на 2D-сетке. Вы можете попробовать это онлайн также. Вот выходные данные этой программы, показывающие, как алгоритм отображает
0-99
:Шаблон заливки выглядит немного странно, но на самом деле это биективно! С каждой последовательной степенью 4 он заполняет квадрат с удвоенной длиной предыдущей стороны. Например, вот как алгоритм отображает
0-15
:Это составляет квадрат 4x4 в середине квадрата 8x8
0-63
:Что составляет квадрат 8x8 в середине квадрата 16x16 из
0-255
:источник
li4b2fmd2/
вместо0li2b+W%2/W%
. Это дает те же самые целые числа, но в обратном порядке.Python 2, 49
Изменить: Улучшено до 49 с использованием лучшей одношаговой рекурсии для базы -2.
Вот версия Pyth с использованием
reduce
.Изменить: Улучшено до 52 путем переключения на базу -2 из сбалансированной троичной .
Python 2, 52
Python 2, 54
При этом используется чередование цифр, как в решении Runer112 , но с сбалансированным троичным, а не двоичным знаком . Python не имеет встроенного базового преобразования, поэтому код реализует его рекурсивно.
Вспомогательная функция
h
(с3
вместо9
) берет натуральное число и преобразует его из троичного в сбалансированный троичный с заменой цифрТак, например, 19, который равен 201 в основании, становится (-1) (0) (+ 1) в сбалансированной троичной, что составляет (-1) * 3 ^ 2 + (0) * 3 ^ 1 + (+ 1) * 3 ^ 0 = -8.
Сбалансированный троичный код достаточен для кодирования каждого целого числа, и поэтому дает отображение из натуральных чисел в целые числа.
Чтобы отобразить пары целых чисел, мы чередуем цифры в
n
. Чтобы сделать это, мы должныh
смотреть на каждую другую цифру, выполняяn/9
рекурсивный шаг, а неn/3
. Затем, для одной координаты, мы сдвигаемсяn
на пол-деление на3
.Вот первые 81 выход, которые охватывают область [-4,4] ^ 2.
Альтернативный код с четверть-мнимым получился длиннее, хотя он очень симпатичный.
Python 2, 63
В языке с менее сложной обработкой сложных преобразований это, вероятно, будет лучшим подходом. Если бы мы могли выводить комплексные числа, мы могли бы сделать:
Python 2, 38
источник
L&b-%b2*2y/b4,yQy/Q2
длиной всего 20 байтов.Python 2, 98 байт
Давайте начнем с простого подхода:
Он просто формирует прямоугольные спиральные
N
единицы длиной на двумерной сетке, начиная с начала координат, и возвращает координаты последней точки.Функция является биективной, поскольку:
Спираль выглядит примерно так (за исключением того, что начинается с 0, а не с 1):
источник
0**0 == 1
в Python, так что это так же, какif a == 0: a = b/2
a=a or b/2
короче0^0=1
во всей математике, а не только на питоне.0**0
- фактически неопределенная форма в математикеDC, 49
Это начинается с размещения неотрицательных целых чисел в сетке таким образом:
Обратите внимание на то, как позиции сетки заполняются по диагонали с увеличением N. Обратите внимание, что строка Y = 0 содержит треугольную последовательность чисел, заданную как
N = X(X+1)/2
. Это квадратное уравнение, которое решается с помощью нормальной формулы, используя только корень + ve, так что мы можем определить X из N, когда Y = 0. Далее следует простое арифметическое перемешивание, чтобы дать уникальный {X, Y} для каждого N.Это обеспечивает требуемое биективное качество, но X и Y только неотрицательны, но вопрос требует всех возможных целых чисел. Таким образом, X и Y отображаются с использованием
((t+1)/2)*((t+1)~2*2-1)
всех возможных целых чисел.dc
имеет произвольные числа точности, поэтому входной диапазон для2^31-1
не проблема. Также обратите внимание, что точность по умолчанию равна 0 десятичных цифр,sqrt()
а/
округление и округление - это поведение, которое необходимо здесь.Выход:
источник
Matlab, 54 байта
Ключевым моментом здесь является то
spiral
, что это создает спиральную матрицу произвольного размера.возвращается
spiral
источник
Haskell,
7874 байтаТестовый забег:
Как это работает: перечислите все пары в первом квадранте в следующем порядке
зеркалируйте каждую точку в другие квадранты, чтобы составить список из 4 списков элементов. Объединить все в один список и взять
n
элемент th.Редактировать: функция не нуждается в имени, переупорядочена математика. выражения.
источник
do
-notation: Попробуйте онлайн!Haskell , 50 байтов
Попробуйте онлайн или попробуйте с обратным!
Ungolfed
объяснение
(!)
l
xCounter
y
Обратите внимание, что фактическая функция
f
(ntoN2
) увеличивает вход перед началом процедуры.источник
05AB1E , 35 байт
Попробуйте онлайн! или как тестовый набор
объяснение
Рассмотреть возможность
источник
Математика, 46
Сортируйте векторы по их норме, а затем по
n
одному.источник
JavaScript, 166
168байт / символовНовый подход с использованием прямоугольной спирали, как и другие.
Я использовал этот ответ на Math.SE, перевел его на JS и сжал его с помощью UglifyJS .
Этот подход не использует петли и не создает спираль в любом случае.
Обновление: сохранены 2 символа путем сохранения
Math
вb
.t-=1
t+=4
источник