Olimpijscy swingersi wykonują swoje czynności na standardowych drzewach. W szczególności drzewo standardowe n
ma wierzchołki 0
przechodzące w górę n-1
i krawędzie łączące każdy niezerowy wierzchołek a
z wierzchołkiem n % a
poniżej. Na przykład Standardowe drzewo 5 wygląda następująco:
3
|
2 4
\ /
1
|
0
ponieważ reszta, gdy 5 jest podzielona przez 3, wynosi 2, reszta, gdy 5 jest podzielona przez 2 lub przez 4, wynosi 1, a reszta, gdy 5 jest podzielona przez 1, wynosi 0.
W tym roku Tarzan będzie bronił swojego złota za pomocą nowych procedur, z których każda zaczyna się od wierzchołka n - 1
, przechodzi do wierzchołka n - 2
, kontynuuje do wierzchołka n - 3
itp., Aż w końcu zejdzie do wierzchołka 0
.
Wynik dla rutyny jest sumą wyników dla każdego zamachu (w tym zsiadania), a wynikiem dla zamachu jest odległość w drzewie między punktami początkowymi i końcowymi. Zatem procedura Tarzana na Standard Tree 5 ma wynik 6:
- huśtawka od
4
do3
zdobycia trzech punktów (w dół, w górę, w górę), - huśtawka z
3
na2
jeden punkt (w dół), - huśtawka od
2
do1
zdobywa jeden punkt (w dół) i - zejście z z
1
do0
jednego punktu (w dół).
Napisz program lub funkcję, która przy dodatniej liczbie całkowitej n
oblicza wynik rutyny Tarzana na drzewie standardowym n
. Przykładowe dane wejściowe i wyjściowe:
1 -> 0
2 -> 1
3 -> 2
4 -> 6
5 -> 6
6 -> 12
7 -> 12
8 -> 18
9 -> 22
10 -> 32
11 -> 24
12 -> 34
13 -> 34
14 -> 36
15 -> 44
16 -> 58
17 -> 50
18 -> 64
19 -> 60
20 -> 66
21 -> 78
22 -> 88
23 -> 68
24 -> 82
Zasady i punktacja kodu są jak zwykle dla golfa kodu .
źródło
Odpowiedzi:
C,
9897 bajtówOblicza odległość między każdą parą punktów za pomocą następującego wzoru:
Ma to tę zaletę, że po zastosowaniu do wszystkich par jest takie samo jak:
Aby uprościć logikę, zakładamy, że przechodzimy od węzła 0 do węzła n-1, a nie od n-1 do 0, jak stwierdza pytanie. Odległość od węzła głównego do węzła 0 wynosi oczywiście 0 (są takie same). Widzimy, że dla (większości) drzew odległość od ostatniego węzła do korzenia wynosi 2:
Oznacza to, że mamy kilka specjalnych przypadków (n <2), ale możemy je łatwo wyjaśnić.
Awaria:
Dzięki @feersum za 1 bajt zapisany
Bonus: Drzewa!
Napisałem szybki i brudny program, aby zobaczyć, jak wyglądają te drzewa. Oto niektóre wyniki:
19:
źródło
Python 2, 85 bajtów
źródło
Perl,
65595554 bajtówObejmuje +2 za
-ap
Uruchom z rozmiarem drzewa na STDIN:
vines.pl
:Wyjaśnienie
Jeśli przepiszesz drzewo
do jednego, w którym każdy węzeł zawiera zbiór wszystkich swoich przodków i siebie samego:
Następnie możemy opisać np. Wszystkie węzły ścieżki od 4 do 3 jako:
Liczba krawędzi jest o jeden mniejsza niż liczba węzłów, więc możemy użyć tego do zignorowania punktu połączenia, więc liczba krawędzi na ścieżce od 4 do 3 wynosi 3, ponieważ:
Zauważ, że działa to również dla ścieżki, która prowadzi bezpośrednio do celu, np. Dla ścieżki od 3 do 2 liczba krawędzi wynosi 1, ponieważ:
Następnie możemy zsumować wszystkie te kombinacje.
Jeśli zamiast tego spojrzysz tylko na węzeł, np. Węzeł 2 z ustawionym przodkiem
{2,3}
. Ten węzeł przyczyni się jeden raz podczas przetwarzania ścieżki,2 to 1
ponieważ zawiera 2, ale nie 1. Nie wniesie nic do ścieżki,3 to 2
ponieważ ma zarówno 2, jak i 3, ale przyczyni się raz podczas przetwarzania ścieżki,4 to 3
ponieważ ma 3, ale nie 4. Zasadniczo liczba w zestawie przodków węzła przyczyni się do jednego dla każdego sąsiada (jeden niższy z wyższych), którego nie ma w zestawie. Z wyjątkiem elementu maksymalnego (w tym przypadku 4), który przyczynia się tylko do dolnego sąsiada 3, ponieważ nie ma ścieżki5 to 4
. Simular 0 jest jednostronny, ale ponieważ 0 jest zawsze u podstawy drzewa i zawiera wszystkie liczby (jest to łączenie ostateczne i nie liczymy złączeń), nigdy nie ma żadnego wkładu od 0, więc najłatwiej jest po prostu opuścić węzeł 0 całkowicie.Możemy więc również rozwiązać problem, patrząc na zestaw przodków dla każdego węzła, policz wkłady i sumę dla wszystkich węzłów.
Aby łatwo przetwarzać sąsiadów, zamierzam reprezentować zestawy przodków jako ciąg spacji i 1, gdzie każdy 1 w pozycji p oznacza, że n-1-p jest przodkiem. Tak więc np. W naszym przypadku
n=5
1 w pozycji 0 wskazuje, że 4 jest przodkiem. Zostawię końcowe spacje. Rzeczywista reprezentacja drzewa, które zbuduję, to:Zauważ, że pominąłem węzeł 0, który byłby reprezentowany,
"11111"
ponieważ zamierzam zignorować węzeł 0 (nigdy się nie przyczynia).Przodkowie bez dolnego sąsiada są teraz reprezentowani przez koniec sekwencji 1. Przodkowie bez wyższego sąsiada są teraz reprezentowani przez początek sekwencji 1, ale powinniśmy zignorować każdy początek sekwencji na początku łańcucha, ponieważ reprezentowałby ścieżkę,
5 to 4
która nie istnieje. Ta kombinacja jest dokładnie dopasowana przez wyrażenie regularne/.\b/
.Budowanie ciągów przodka odbywa się poprzez przetworzenie wszystkich węzłów w kolejności,
n-1 .. 1
a następnie ustawienie 1 w pozycji dla samego węzła i wykonanie „lub” w potomku.Dzięki temu program jest wystarczająco łatwy do zrozumienia:
Zauważ, że zastąpienie
/.\b/
przez/\b/
rozwiązuje wersję tego problemu w obie strony, w której tarzan również podąża ścieżką0 to n-1
Kilka przykładów wyglądu ciągów przodka (podanych w kolejności
n-1 .. 1
):źródło
Mathematica,
113103102 bajtów-10 bajtów dzięki @feersum; -1 bajt dzięki @MartinEnder
Następujące jest znacznie szybsze (ale niestety dłuższe, przy 158 bajtach ):
źródło
With
. Również wygląda na to, że za każdym razemRange
jest używany,a
jest argument, więc można to rozłożyć na czynniki.r=Range[a=#-1]
zapisuje bajt.J, 37 bajtów
Stosowanie:
Wypróbuj online tutaj.
źródło
JavaScript (ES6),
118116 bajtówBrak funkcji ustawiania różnicy naprawdę boli, ale niektóre kreatywne rekurencje nieco zmniejszają liczbę bajtów. Edycja: Zapisano 2 bajty, usuwając niepotrzebny parametr.
źródło