Dado um gráfico direcionado, produza o ciclo mais longo.
Regras
- Qualquer formato de entrada razoável é permitido (por exemplo, lista de bordas, matriz de conectividade).
- Os rótulos não são importantes, portanto, você pode impor restrições aos rótulos de que precisa e / ou deseja, desde que não contenham informações adicionais não fornecidas na entrada (por exemplo, você não pode exigir que os nós nos ciclos sejam rotulados com números inteiros e outros nós são rotulados com seqüências alfabéticas).
- Um ciclo é uma sequência de nós que estão todos conectados e nenhum nó é repetido, exceto o nó que é o início e o fim do ciclo (
[1, 2, 3, 1]
é um ciclo, mas[1, 2, 3, 2, 1]
não é). - Se o gráfico for acíclico, o ciclo mais longo terá o comprimento 0 e, portanto, deverá produzir uma saída vazia (por exemplo, lista vazia, nenhuma saída).
- Repetir o primeiro nó no final da lista de nós no ciclo é opcional (
[1, 2, 3, 1]
e[1, 2, 3]
denota o mesmo ciclo). - Se houver vários ciclos do mesmo comprimento, qualquer um ou todos eles poderão ser produzidos.
- Builtins são permitidos, mas se a sua solução usa um, recomendamos que você inclua uma solução alternativa que não use trivializing builtins (por exemplo, um builtin que produz todos os ciclos). No entanto, a solução alternativa não conta para a sua pontuação, portanto é totalmente opcional.
Casos de teste
Nesses casos de teste, a entrada é fornecida como uma lista de arestas (onde o primeiro elemento é o nó de origem e o segundo elemento é o nó de destino) e a saída é uma lista de nós sem repetição do primeiro / último nó.
[(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
fonte
fonte
Respostas:
Mathematica,
8058 bytesEconomizou 22 bytes graças a JungHwan Min
é o caractere de uso privado de três bytes queU+F3D5
representa\[DirectedEdge]
. Função pura com o primeiro argumento#
esperado como uma lista de arestas direcionadas. LocalizaAll
ciclos de duração no máximo ,Infinity
emGraph@#
seguida, substitui a lista vazia pela lista de auto-loops. Os ciclos são representados como listas de arestas e classificados por comprimento; portanto, pegamos o último ciclo desse tipo; depois, de todas as arestas, pegamos o primeiro argumento para obter uma lista de vértices no formato de saída especificado.Se apenas o Mathematica tratasse loops como um ciclo de duração
1
(AcyclicGraphQ @ CycleGraph[1, DirectedEdges -> True]
dáTrue
, sério), poderíamos salvar outros26
bytes:fonte
MaximalBy
porque o resultado deFindCycle
já está classificado por comprimento (o último elemento é o mais longo). Além disso, o primeiro argumento deFindCycle
pode ser uma lista de\[DirectedEdge]
(em vez de aGraph
). Além disso, você pode usar o 2-byte;;
(=1;;-1
) em vez do 3-byteAll
emPart
para salvar um byte. -22 bytes (58 bytes):(FindCycle[#,∞,All]/.{}->{Cases[#,v_v_]})[[-1,;;,1]]&
Haskell ,
157 154150 bytesExperimente online!
Obrigado @Laikoni e @Zgrab por salvar um monte de bytes!
Este é um programa muito ineficiente:
A primeira função
#
pega uma lista de caminhosl
(uma lista de listas de números) e tenta estender os elementosl
anexando todas as arestas possíveis (uma lista de comprimento 2)g
a cada elemento del
. Isso acontece apenas se o elemento del
já não for um ciclo e se o novo nó que seria acrescentado ainda não estiver contido no elemento del
. Se já é um ciclo, não acrescentamos nada antes, mas o adicionamos novamente à nova lista de caminhos. Se pudermos estendê-lo, adicionamos o caminho estendido à nova lista, caso contrário, não o adicionamos à nova lista. .Agora, a função
h
tenta repetidamente estender esses caminhos (começando pela própria lista de arestas) até chegarmos a um ponto fixo, ou seja, não podemos mais estender nenhum caminho. Neste ponto, temos apenas ciclos em nossa lista. Então é apenas uma questão de escolher o ciclo mais longo. Obviamente, os ciclos aparecem várias vezes nesta lista, pois toda rotação cíclica possível de um ciclo é novamente um ciclo.fonte
(p:q)<-l
.<$>
vez demap
deve salvar outro byte no((,)=<<length)<$>[]:
.d@(p:q)<-l
salva alguns bytes.d@(p:q)
é muito bom, obrigado por me mostrar!Pitão, 20 bytes
Suíte de teste
Leva uma lista de arestas, como nos exemplos.
Explicação:
fonte
Bash + bsdutils, 129 bytes
O tsort faz todo o trabalho pesado, mas seu formato de saída é bastante único e não detecta ciclos de comprimento 1. Observe que isso não funciona com o GNU tsort.
Verificação
fonte
JavaScript (ES6),
173163156 156145139 bytesGuardado 5 bytes graças a @Neil
Snippet de teste
Mostrar snippet de código
fonte
map
economiza alguns bytes?.filter().map()
, então quase certamente não. O switch me salvou 10 bytes (apesar de não ter sido tão completo quanto agora)a.filter(z=>!e).map(z=>d)
você pode usara.map(z=>e?0:d)
.a+a?
:-)Haskell ,
109108 bytesUma solução de força bruta: gere todas as listas de arestas de comprimentos crescentes até o comprimento da entrada, mantenha as que são ciclos, retorne a última. Pega o gráfico no formato
[(1,2),(2,3),(2,4),(4,1)]
. Experimente online!Explicação
fonte
MATLAB,
291260 bytesToma uma matriz de adjecência
A
onde uma aresta(i,j)
é denotada por um1
inA(i,j)
eA
é zero em todas as outras entradas. A saída é uma lista do ciclo mais longo. A lista está vazia, se não houver ciclo, e a lista inclui o ponto inicial e final, se houver um ciclo. Ele usa1
indexação baseada em.Esta solução não usa funções internas relacionadas a gráficos.
Infelizmente, isso não é executado no TryItOnline, pois usa uma função dentro de uma função, que é recursiva. Um pouco de modificação permite que você experimente no octave-online.net .
No último caso de teste, encontrei um ciclo mais longo alternativo
[0 2 1 4 3 5 7 8 9 11 10 6 0]
(essa notação usa indexação baseada em 0)Explicação
A abordagem básica aqui é que executamos um BFS de todos os nós e cuidamos para não visitar nenhum dos nós intermediários novamente, exceto o nó inicial. Com essa idéia, podemos coletar todos os ciclos possíveis e escolher facilmente o mais longo.
fonte