Powinieneś napisać program lub funkcję, która przyjmuje nieujemną liczbę całkowitą N
jako dane wejściowe i wyjściowe lub zwraca dwie liczby całkowite (ujemną, zerową lub dodatnią) X
i Y
.
Liczby całkowite są rozumiane w sensie matematycznym, ponieważ jest ich nieskończenie wiele.
Zaimplementowana funkcja musi być bijectywna . Oznacza to, że dla każdego N
musi wyprowadzać inną X
Y
parę i każda X
Y
para powinna być wyprowadzana dla niektórych danych wejściowych, N
tzn. Dla niektórych z nich powinny być wyprowadzane wszystkie następujące pary 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 │
└─────┴─────┴────┴────┴────┘
...
Zauważ, że U V
i V U
są różnymi parami jeśli U!=V
.
Detale
- Jeśli twój język nie obsługuje dowolnie dużych liczb całkowitych, to dobrze, ale twój algorytm powinien działać z dowolnie dużym typem danych. Twój kod powinien nadal obsługiwać wartości wejściowe przynajmniej
2^31-1
. - Jeśli zdecydujesz się wydrukować lub zwrócić wynik jako ciąg znaków, nie będą dozwolone żadne znaki wiodące
0
ani+
znaki. W przeciwnym razie standardowa reprezentacja liczb całkowitych w twoim języku jest w porządku.
Przykład
Jeśli zadaniem byłoby utworzenie funkcji bijectywnej przyjmującej nieujemną liczbę całkowitą N
i wyprowadzenie jednej liczby całkowitej, X
rozwiązaniem może być funkcja
if (input mod 2 == 0) return N/2 else return -(N+1)/2
,
zaimplementowane w jakimś języku. Ta funkcja zwraca wartość X = 0 -1 1 -2 2...
dla N = 0 1 2 3 4...
.
10=>11 12, 9=>10 11
jest to nieprawidłowe, ponieważ 11 jest powtarzane?Odpowiedzi:
Pyth, 15 lat
Wypróbuj online.
Tłumaczenie Python:
lub iteracyjnie:
gdzie
binlist
konwertuje liczbę na listę cyfr takich jakbinlist(4) = [1,0,0]
.Jak to działa? Interpretuje binarne cyfry liczby jako dwie przeplecione liczby w podstawowych ujemnych dwóch, jak w moim rozwiązaniu Python .n
Liczba binarna
Jeśli nie został jeszcze przetworzony ostatnią cyfrę o N , to mamy wszystkie współczynniki wyższa o 1 $ $, n " = ... b 5 b 4 b 3 b 2 b 1 odpowiadającej pary ( x ' , y ' ) = ( b 1 - 2 b 3 + 4 b 5 - 8 b 7 + ⋯ , b 2 - 2 b 4b0 n
Następnie możemy wyrazić nowe wartości po odczytaniu w odniesieniu do starych wartościb0
źródło
CJam,
242221 bajtówMój mózg ma problem ze zrozumieniem matematyki używanej przez inne rozwiązania. Ale mój mózg zdecydowanie rozumie binarny, więc oto dusza oparta na manipulacji bitami!
Wypróbuj online.
Wyjaśnienie
Takie podejście traktuje dane wejściowe jako dwie przeplecione wartości binarne, po jednej dla każdej liczby wyjściowej. Wszystkie z wyjątkiem najmniej znaczącego bitu każdego z nich kodują wielkość, a najmniej znaczący bit sygnalizuje, czy przyjąć bitowe uzupełnienie tej wielkości. W tej implementacji bity o nieparzystej pozycji odpowiadają pierwszej liczbie wyjściowej (a bity o parzystej pozycji odpowiadają drugiej) i LSB
0
sygnałów w celu uzupełnienia.Na przykład, biorąc pod uwagę wejście
73
, przeplatanie jego binarnej reprezentacji1001001b
produkcji0 1|0
(bity o nieparzystej pozycji) i1 0 0|1
(bity o parzystej pozycji). Pierwsza wartość ma wielkość01b = 1
i powinna być uzupełniona do wartości końcowej~1 = -2
, a druga wartość ma wielkość100b = 4
i nie powinna być uzupełniana.Nieformalne wykazanie poprawności
Zrobiłem program testowy, który umieszcza każde wejście od zera do określonej przez użytkownika liczby minus jeden w swoim miejscu wyjściowym na siatce 2D. Możesz spróbować również online . Oto wynik tego programu pokazujący, w jaki sposób algorytm mapuje
0-99
:Wzór wypełnienia wygląda trochę dziwnie, ale w rzeczywistości jest bolesny! Z każdą kolejną siłą 4, wypełnia kwadrat podwójną poprzednią długością boku. Na przykład oto sposób mapowania algorytmu
0-15
:To tworzy kwadrat 4x4 pośrodku kwadratu 8x8
0-63
:Co stanowi kwadrat 8x8 w środku kwadratu 16x16
0-255
:źródło
li4b2fmd2/
zamiast0li2b+W%2/W%
. Daje to te same liczby całkowite, ale w odwrotnej kolejności.Python 2, 49
Edycja: poprawiono do 49, stosując lepszą jednokrokową rekurencję dla bazy -2
Oto wersja Pyth używająca
reduce
.Edycja: Poprawiono do 52 poprzez przejście do bazy -2 ze zbalansowanego trójskładnika .
Python 2, 52
Python 2, 54
Wykorzystuje to przeplatanie cyfr jak rozwiązanie Runer112 , ale ze zrównoważonym trójskładnikiem zamiast ze znakiem binarnym. Python nie ma wbudowanej konwersji podstawowej, więc kod implementuje go rekurencyjnie.
Funkcja pomocnika
h
(z3
zamiast9
) przyjmuje liczbę naturalną i konwertuje ją z trójskładnikowej na zrównoważoną trójskładnikową z podstawieniem cyfrNa przykład 19, który ma 201 w podstawie, staje się (-1) (0) (+ 1) w zrównoważonej trójce, czyli (-1) * 3 ^ 2 + (0) * 3 ^ 1 + (+ 1) * 3 ^ 0 = -8.
Zrównoważone trójskładnikowe wystarcza do zakodowania każdej liczby całkowitej, a zatem daje odwzorowanie liczb naturalnych na liczby całkowite.
Aby odwzorować na pary liczb całkowitych, przeplatamy cyfry
n
. Aby to zrobić,h
patrzymy na każdą inną cyfrę, wykonującn/9
raczej krok rekurencyjny niżn/3
. Następnie, dla jednej współrzędnej, przesuwamyn
przez podział podłogi przez3
.Oto pierwsze 81 wyników, które obejmują region [-4,4] ^ 2.
Alternatywne kodowanie z ćwiartką urojoną okazało się dłuższe, choć jest bardzo ładne.
Python 2, 63
W języku z mniej niezręczną obsługą skomplikowanych konwersji byłoby to prawdopodobnie lepsze podejście. Gdybyśmy mogli wyprowadzić liczby zespolone, moglibyśmy:
Python 2, 38
źródło
L&b-%b2*2y/b4,yQy/Q2
ma tylko 20 bajtów.Python 2, 98 bajtów
Zacznijmy od prostego podejścia:
Po prostu tworzy prostokątne
N
jednostki spiralne długie na siatce 2d, zaczynając od początku i zwraca współrzędne ostatniego punktu.Ta funkcja jest dwuskładnikowa, ponieważ:
Spirala wygląda mniej więcej tak (z wyjątkiem tego, że zaczyna się od 0 zamiast 1):
źródło
0**0 == 1
w pythonie, więc jest to tak samo jakif a == 0: a = b/2
a=a or b/2
jest krótszy0^0=1
we wszystkich aspektach matematycznych, nie tylko python.0**0
jest w rzeczywistości nieokreśloną formą matematykidc, 49
Zaczyna się to od ustawienia liczb całkowitych nieujemnych na siatce w następujący sposób:
Zauważ, że sposób wypełnienia pozycji siatki po przekątnej rosnącym N. Zauważ, że linia Y = 0 zawiera trójkątną sekwencję liczb, podaną przez
N = X(X+1)/2
. Jest to równanie kwadratowe, które rozwiązuje się za pomocą normalnego wzoru, używając tylko + ve pierwiastka, abyśmy mogli określić X z N, gdy Y = 0. Następnie jest kilka prostych tasowań arytmetycznych, które dają unikalne {X, Y} dla każdego N.Zapewnia to wymaganą jakość podwójną, ale X i Y są tylko nieujemne, ale pytanie wymaga wszystkich możliwych liczb całkowitych. Więc X i Y są mapowane za pomocą,
((t+1)/2)*((t+1)~2*2-1)
aby dać wszystkie możliwe liczby całkowite.dc
ma dowolne liczby precyzji, więc zakres wejściowy do2^31-1
nie stanowi problemu. Zauważ też, że domyślna precyzja to 0 cyfr dziesiętnychsqrt()
oraz/
zaokrąglenie w dół, co jest wymaganym zachowaniem.Wydajność:
źródło
Matlab, 54 bajty
Kluczem jest to
spiral
, że tworzy to macierz spiralną o dowolnym rozmiarze.zwraca
spiral
źródło
Haskell,
7874 bajtówTestowe uruchomienie:
Jak to działa: wypisz wszystkie pary w pierwszej ćwiartce w następującej kolejności
odbij każdy punkt w pozostałych ćwiartkach, aby utworzyć listę 4 elementów. Połącz wszystkie w jedną listę i weź
n
element th.Edycja: funkcja nie potrzebuje nazwy, zmieniona matematyka. wyrażenia.
źródło
do
-notacji: Wypróbuj online!Haskell , 50 bajtów
Wypróbuj online lub wypróbuj odwrotnie!
Nie golfił
Wyjaśnienie
Wykorzystuje to fakt, że każdy(x,y)∈N2 2x⋅(2⋅y+1)−1∈N x
(!)
l
xCounter
y
Zauważ, że faktyczna funkcja
f
(ntoN2
) zwiększa dane wejściowe przed rozpoczęciem procedury.źródło
05AB1E , 35 bajtów
Wypróbuj online! lub jako pakiet testowy
Wyjaśnienie
Rozważać
źródło
Mathematica, 46
Posortuj wektory według ich normy, a następnie weź tę
n
.źródło
JavaScript, 166
168bajtów / znakówNowe podejście z wykorzystaniem prostokątnej spirali, podobnie jak inni.
Użyłem tego odpowiedzi na Math.SE, przetłumaczyłem ją na JS i skompresowałem za pomocą UglifyJS .
To podejście nie wykorzystuje żadnych pętli ani nie tworzy spirali w żaden sposób.
Aktualizacja: Saved 2 znaków, przechowując
Math
wb
.t-=1
t+=4
źródło