Biorąc pod uwagę ukierunkowany wykres, generuj najdłuższy cykl.
Zasady
- Dozwolony jest dowolny rozsądny format wejściowy (np. Lista krawędzi, macierz połączeń).
- Etykiety nie są ważne, więc możesz nałożyć ograniczenia na etykiety, których potrzebujesz i / lub pragniesz, o ile nie zawierają one dodatkowych informacji, które nie zostały podane w danych wejściowych (np. Nie możesz wymagać, aby węzły w cyklach były oznaczone liczbami całkowitymi, a inne węzły są oznaczone łańcuchami alfabetycznymi).
- Cykl jest sekwencją połączonych węzłów i żaden węzeł nie jest powtarzany poza węzłem, który jest początkiem i końcem cyklu (
[1, 2, 3, 1]
jest cyklem, ale[1, 2, 3, 2, 1]
nie jest). - Jeśli wykres jest acykliczny, najdłuższy cykl ma długość 0, a zatem powinien dać pusty wynik (np. Pusta lista, brak danych wyjściowych).
- Powtórzenie pierwszego węzła na końcu listy węzłów w cyklu jest opcjonalne (
[1, 2, 3, 1]
i[1, 2, 3]
oznacza ten sam cykl). - Jeśli istnieje wiele cykli o tej samej długości, można wygenerować jeden lub wszystkie z nich.
- Wbudowane są dozwolone, ale jeśli twoje rozwiązanie korzysta z jednego, zachęcamy do dołączenia alternatywnego rozwiązania, które nie wykorzystuje trywialnych wbudowanych (np. Wbudowanego, który generuje wszystkie cykle). Jednak alternatywne rozwiązanie w ogóle nie będzie wliczane do wyniku, więc jest całkowicie opcjonalne.
Przypadki testowe
W tych przypadkach testowych dane wejściowe są podawane jako lista krawędzi (gdzie pierwszy element jest węzłem źródłowym, a drugi element jest węzłem docelowym), a dane wyjściowe to lista węzłów bez powtarzania pierwszego / ostatniego węzła.
[(0, 0), (0, 1)] -> [0]
[(0, 1), (1, 2)] -> []
[(0, 1), (1, 0)] -> [0, 1]
[(0, 1), (1, 2), (1, 3), (2, 4), (4, 5), (5, 1)] -> [1, 2, 4, 5]
[(0, 1), (0, 2), (1, 3), (2, 4), (3, 0), (4, 6), (6, 8), (8, 0)] -> [0, 2, 4, 6, 8]
[(0, 0), (0, 8), (0, 2), (0, 3), (0, 9), (1, 0), (1, 1), (1, 6), (1, 7), (1, 8), (1, 9), (2, 1), (2, 3), (2, 4), (2, 5), (3, 8), (3, 1), (3, 6), (3, 7), (4, 1), (4, 3), (4, 4), (4, 5), (4, 6), (4, 8), (5, 0), (5, 8), (5, 4), (6, 0), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6), (6, 7), (6, 9), (7, 0), (7, 1), (7, 2), (7, 3), (7, 4), (7, 5), (7, 8), (7, 9), (8, 0), (8, 1), (8, 2), (8, 5), (8, 9), (9, 1), (9, 2), (9, 3), (9, 4), (9, 5), (9, 6)] -> [0, 9, 6, 7, 8, 2, 5, 4, 3, 1]
[(0, 0), (0, 2), (0, 4), (0, 5), (0, 7), (0, 9), (0, 11), (1, 2), (1, 4), (1, 5), (1, 8), (1, 9), (1, 10), (2, 0), (2, 1), (2, 3), (2, 4), (2, 5), (2, 6), (3, 0), (3, 1), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (3, 11), (4, 1), (4, 3), (4, 7), (4, 8), (4, 9), (4, 10), (4, 11), (5, 0), (5, 4), (5, 6), (5, 7), (5, 8), (5, 11), (6, 0), (6, 8), (6, 10), (6, 3), (6, 9), (7, 8), (7, 9), (7, 2), (7, 4), (7, 5), (8, 8), (8, 9), (8, 2), (8, 4), (8, 7), (9, 0), (9, 1), (9, 2), (9, 3), (9, 6), (9, 10), (9, 11), (10, 8), (10, 3), (10, 5), (10, 6), (11, 2), (11, 4), (11, 5), (11, 9), (11, 10), (11, 11)] -> [0, 11, 10, 6, 9, 3, 8, 7, 5, 4, 1, 2]
code-golf
graph-theory
Mego
źródło
źródło
Odpowiedzi:
Mathematica,
8058 bajtówZaoszczędzono aż 22 bajty dzięki JungHwan Min
to trzy bajtowy prywatny znakU+F3D5
reprezentujący\[DirectedEdge]
. Czysta funkcja z pierwszym argumentem#
powinna być listą ukierunkowanych krawędzi. ZnajdujeAll
cykle długości co najwyżejInfinity
wGraph@#
, a następnie zastępuje pustą listę z listą samorządów pętli. Cykle są reprezentowane jako listy krawędzi i posortowane według długości, więc bierzemy ostatni taki cykl, a następnie ze wszystkich jego krawędzi bierzemy pierwszy argument, aby uzyskać listę wierzchołków w określonym formacie wyjściowym.Gdyby tylko Mathematica traktował pętle jako cykl długości
1
(AcyclicGraphQ @ CycleGraph[1, DirectedEdges -> True]
dajeTrue
poważnie), moglibyśmy zapisać kolejne26
bajty:źródło
MaximalBy
ponieważ wynikFindCycle
jest już posortowany według długości (ostatni element jest najdłuższy). Pierwszym argumentemFindCycle
może być lista\[DirectedEdge]
(zamiast aGraph
). Ponadto można użyć 2-bajtowego;;
(=1;;-1
) zamiast 3-bajtowegoAll
wPart
celu zapisania bajtu. -22 bajty (58 bajtów):(FindCycle[#,∞,All]/.{}->{Cases[#,v_v_]})[[-1,;;,1]]&
Haskell ,
157 154150 bajtówWypróbuj online!
Dzięki @Laikoni i @Zgrab za uratowanie wielu bajtów!
To bardzo nieefektywny program:
Pierwsza funkcja
#
pobiera listę ścieżekl
(listę list liczb) i próbuje rozszerzyć elementyl
, przygotowując każdą możliwą krawędź (listę długości 2)g
dla każdego elementul
. Dzieje się tak tylko wtedy, gdy elementl
nie jest już cyklem i jeśli nowy węzeł, który byłby poprzedzony, nie jest już zawarty w elemenciel
. Jeśli jest to już cykl, nie przygotowujemy niczego, ale dodajemy go ponownie do nowej listy ścieżek, jeśli możemy go rozszerzyć, dodajemy rozszerzoną ścieżkę do nowej listy, w przeciwnym razie nie dodamy jej do nowej listy .Teraz funkcja
h
wielokrotnie próbuje wydłużyć te ścieżki (zaczynając od samej listy krawędzi), aż dojdziemy do ustalonego punktu, tzn. Nie możemy już przedłużyć żadnej ścieżki. W tym momencie mamy tylko cykle na naszej liście. Zatem wystarczy wybrać najdłuższy cykl. Oczywiście cykle pojawiają się na tej liście wiele razy, ponieważ każdy możliwy cykliczny obrót cyklu jest znowu cyklem.źródło
(p:q)<-l
.<$>
zamiastmap
powinno zapisać kolejny bajt w((,)=<<length)<$>[]:
.d@(p:q)<-l
oszczędza niektóre bajty.d@(p:q)
to naprawdę miłe, dziękuję za pokazanie mi!Pyth, 20 bajtów
Zestaw testowy
Pobiera listę krawędzi, jak w przykładach.
Wyjaśnienie:
źródło
Bash + bsdutils, 129 bajtów
tsort wykonuje wszystkie ciężkie operacje podnoszenia, ale jego format wyjściowy jest raczej unikalny i nie wykrywa cykli długości 1. Zauważ, że nie działa to z GNU tsort.
Weryfikacja
źródło
JavaScript (ES6),
173163156145139 139 bajtówZaoszczędź 5 bajtów dzięki @Neil
Testowy fragment kodu
Pokaż fragment kodu
źródło
map
oszczędza Ci kilka bajtów?.filter().map()
, więc prawie na pewno nie. Przełącznik zaoszczędził mi 10 bajtów (choć nie był tak w pełni golfowy, jak teraz)a.filter(z=>!e).map(z=>d)
możesz użyća.map(z=>e?0:d)
.a+a?
też :-)Haskell ,
109108 bajtówRozwiązanie brutalnej siły: wygeneruj wszystkie listy krawędzi o coraz większej długości aż do długości wejścia, zachowaj te, które są cyklami, zwróć ostatnią. Przyjmuje wykres w formacie
[(1,2),(2,3),(2,4),(4,1)]
. Wypróbuj online!Wyjaśnienie
źródło
MATLAB,
291260 bajtówPobiera macierz adjecencji, w
A
której krawędź(i,j)
jest oznaczona przez1
inA(i,j)
, iA
wynosi zero we wszystkich innych pozycjach. Wynik jest listą najdłuższego cyklu. Lista jest pusta, jeśli w ogóle nie ma cyklu, a lista zawiera początek i punkt końcowy, jeśli istnieje cykl. Korzysta z1
indeksowania na podstawie.To rozwiązanie nie korzysta z żadnych wbudowanych funkcji związanych z wykresami.
Niestety nie działa to w TryItOnline, ponieważ używa funkcji wewnątrz funkcji, która jest rekurencyjna. Odrobina modyfikacji pozwala wypróbować ją na octave-online.net .
W ostatnim przypadku testowym znalazłem alternatywny najdłuższy cykl
[0 2 1 4 3 5 7 8 9 11 10 6 0]
(ta notacja wykorzystuje indeksowanie oparte na 0)Wyjaśnienie
Podstawowe podejście polega na tym, że wykonujemy BFS z każdego węzła i uważamy, aby nie odwiedzać ponownie żadnego z węzłów pośrednich, z wyjątkiem węzła początkowego. Dzięki temu pomysłowi możemy zebrać wszystkie możliwe cykle i łatwo wybrać najdłuższy.
źródło