Wprowadzenie
Załóżmy, że masz losową permutację n
obiektów. Permutacja jest zamknięta w pudełku, więc nie masz pojęcia, który z n!
nich jest możliwy. Jeśli udało ci się zastosować permutację do n
różnych obiektów, możesz natychmiast wywnioskować jej tożsamość. Możesz jednak zastosować permutację tylko do n
wektorów binarnych o długości , co oznacza, że będziesz musiał ją zastosować kilka razy, aby ją rozpoznać. Oczywiście, zastosowanie go do n
wektorów za pomocą tylko jednego 1
działa, ale jeśli jesteś sprytny, możesz to zrobić za pomocą log(n)
aplikacji. Kod dla tej metody będzie dłuższy, jednak ...
Jest to wyzwanie eksperymentalne, w którym wynik jest kombinacją długości kodu i złożoności zapytań , co oznacza liczbę wywołań procedury pomocniczej. Specyfikacja jest trochę długa, więc trzymaj się mnie.
Zadanie
Twoim zadaniem jest napisanie nazwanej funkcji (lub najbliższego odpowiednika), f
która przyjmuje jako dane wejściowe dodatnią liczbę całkowitą n
oraz permutację p
pierwszych n
liczb całkowitych, przy użyciu indeksowania 0 lub 1. Jego wynikiem jest permutacja p
. Nie masz jednak p
bezpośredniego dostępu do permutacji . Jedyne, co możesz z tym zrobić, to zastosować go do dowolnego wektora n
bitów. W tym celu należy użyć funkcji pomocniczej, P
która przyjmuje permutację p
i wektor bitów v
i zwraca permutowany wektor, którego p[i]
współrzędna zawiera bit v[i]
. Na przykład:
P([1,2,3,4,0], [1,1,0,0,0]) == [0,1,1,0,0]
Możesz zastąpić „bity” dowolnymi dwiema odrębnymi wartościami, takimi jak 3
i -4
, i 'a'
i 'b'
, i nie trzeba ich naprawiać, więc możesz dzwonić P
zarówno z tym samym, jak [-4,3,3,-4]
i [2,2,2,1]
tym samym f
. Definicja P
nie jest wliczana do wyniku.
Punktacja
Złożoność zapytań od rozwiązania na danym wejściu jest liczba połączeń sprawia, że do funkcji pomocniczych P
. Aby ta miara była jednoznaczna, twoje rozwiązanie musi być deterministyczne. Możesz użyć liczb generowanych pseudolosowo, ale musisz także ustalić początkowe źródło dla generatora.
W tym repozytorium znajdziesz plik o nazwie, permutations.txt
który zawiera 505 permutacji, 5 o każdej długości od 50 do 150 włącznie, z wykorzystaniem indeksowania opartego na 0 (zwiększaj każdą liczbę w przypadku opartym na 1). Każda permutacja ma swoją własną linię, a jej liczby są oddzielone spacjami. Twój wynik to liczba bajtów f
+ średnia złożoność zapytań na tych danych wejściowych . Najniższy wynik wygrywa.
Dodatkowe zasady
Preferowany jest kod z objaśnieniami, a standardowe luki są niedozwolone. W szczególności poszczególne bity są nierozróżnialne (więc nie można podać wektora Integer
obiektów P
i porównać ich tożsamości), a funkcja P
zawsze zwraca nowy wektor zamiast zmiany kolejności danych wejściowych. Możesz dowolnie zmieniać nazwy f
i P
oraz kolejność, w jakiej przyjmują swoje argumenty.
Jeśli jesteś pierwszą osobą, która udzieli odpowiedzi w swoim języku programowania, gorąco zachęca się do włączenia uprzęży testowej, w tym implementacji funkcji, P
która również zlicza liczbę wywołań. Jako przykład, oto uprząż dla Python 3.
def f(n,p):
pass # Your submission goes here
num_calls = 0
def P(permutation, bit_vector):
global num_calls
num_calls += 1
permuted_vector = [0]*len(bit_vector)
for i in range(len(bit_vector)):
permuted_vector[permutation[i]] = bit_vector[i]
return permuted_vector
num_lines = 0
file_stream = open("permutations.txt")
for line in file_stream:
num_lines += 1
perm = [int(n) for n in line.split()]
guess = f(len(perm), perm)
if guess != perm:
print("Wrong output\n %s\n given for input\n %s"%(str(guess), str(perm)))
break
else:
print("Done. Average query complexity: %g"%(num_calls/num_lines,))
file_stream.close()
W niektórych językach nie można napisać takiej uprzęży. Co najważniejsze, Haskell nie pozwala czystej funkcji P
rejestrować liczby wywołań. Z tego powodu możesz ponownie wdrożyć swoje rozwiązanie w taki sposób, aby obliczało ono również złożoność zapytania i używało go w uprzęży.
abaaabababaa
i-4 3 3 3 -4 3
byłby wektorem bitów.