Trouver le nœud le plus profond d'un arbre binaire

9

Écrivez un programme qui prend un arbre binaire en entrée et génère le nœud le plus profond et sa profondeur. S'il y a une égalité, imprimez tous les nœuds impliqués ainsi que leurs profondeurs. Chaque nœud est représenté comme:

T(x,x)

T(x)

T

Test l'identifiant d'un ou plusieurs caractères alphanumériques et chacun xest un autre nœud.

Voici une définition simple d'un arbre binaire:

  • À la tête d'un arbre binaire se trouve un nœud.
  • Un nœud dans un arbre binaire a au plus deux enfants.

Par exemple, l'entrée A(B(C,D(E)))(ci-dessous) sortira 3:E.

Arbre 1

Alors que l'arbre suivant est un lien à trois entre 5, 11 et 4, et leur profondeur est également de 3 (à partir de 0):

L'entrée 2(7(2,6(5,11)),5(9(4)))(ci-dessous) sortirait 3:5,11,4.

Arbre 2

Il s'agit du code golf, donc le code le plus court mesuré en octets gagne.

Jwosty
la source
@ close-voter: de quoi n'êtes-vous pas sûr?
Jwosty
3
Peut-être le fait qu'il n'y a pas de spécification d'entrée ou de sortie, ni de cas de test pour ces entrées et sorties.
Poignée de porte
J'essaye de le réparer mais mon téléphone craint ...: P c'est mieux donc pour quand même.
Jwosty
3
Le premier arbre ne devrait-il pas être A (B (C, D (E))?
bakerg
1
@bakerg à droite, mon erreur. Fixé.
Jwosty

Réponses:

6

CJam, 49 47

0q')/{'(/):U;,+:TW>{T:W];}*TW={U]',*}*T(}/;W':@

 

0                 " Push 0 ";
q                 " Read the whole input ";
')/               " Split the input by ')' ";
{                 " For each item ";
  '(/             " Split by '(' ";
  )               " Extract the last item of the array ";
  :U;             " Assign the result to U, and discard it ";
  ,               " Get the array length ";
  +               " Add the top two items of the stack, which are the array length and the number initialized to 0 ";
  :T              " Assign the result to T ";
  W>{             " If T>W, while W is always initialized to -1 ";
    T:W];         " Set T to W, and empty the stack ";
  }*
  TW={            " If T==W ";
    U]',*         " Push U and add a ',' between everything in the stack, if there were more than one ";
  }*
  T(              " Push T and decrease by one ";
}/
;                 " Discard the top item, which should be now -1 ";
W                 " Push W ";
':                " Push ':' ";
@                 " Rotate the 3rd item to the top ";
jimmy23013
la source
J'ai apporté une légère modification au format de sortie pour le rendre cohérent et moins ambigu, mais cela ne devrait pas trop gêner.
Jwosty
@Jwosty Ce ne devrait pas être le cas, s'il ne s'agit pas de code-golf.
jimmy23013
Eh bien, c'est du code-golf ... Mais de toute façon, belle soumission :)
Jwosty
Pouvez-vous expliquer comment cela fonctionne?
Jerry Jeremiah
@JerryJeremiah Edited.
jimmy23013
5

Haskell, 186 octets

p@(n,s)%(c:z)=maybe((n,s++[c])%z)(\i->p:(n+i,"")%z)$lookup c$zip"),("[-1..1];p%_=[p]
(n,w)&(i,s)|i>n=(i,show i++':':s)|i==n=(n,w++',':s);p&_=p
main=interact$snd.foldl(&)(0,"").((0,"")%)

Programme complet, prend l'arborescence stdin, produit le format de sortie spécifié sur stdout:

& echo '2(7(2,6(5,11)),5(9(4)))' | runhaskell 32557-Deepest.hs 
3:5,11,4

& echo 'A(B(C,D(E)))' | runhaskell 32557-Deepest.hs 
3:E

Guide du code golf (ajouté de meilleurs noms, signatures de type, commentaires et certaines sous-expressions extraites et nommées - mais sinon le même code; une version non golfée ne confondrait pas la rupture en nœuds avec la numérotation, ni la recherche la plus profonde avec formatage de sortie.) :

type Label = String         -- the label on a node
type Node = (Int, Label)    -- the depth of a node, and its label

-- | Break a string into nodes, counting the depth as we go
number :: Node -> String -> [Node]
number node@(n, label) (c:cs) =
    maybe addCharToNode startNewNode $ lookup c adjustTable
  where
    addCharToNode = number (n, label ++ [c]) cs
        -- ^ append current character onto label, and keep numbering rest

    startNewNode adjust = node : number (n + adjust, "") cs
        -- ^ return current node, and the number the rest, adjusting the depth

    adjustTable = zip "),(" [-1..1]
        -- ^ map characters that end node labels onto depth adjustments
        -- Equivalent to [ (')',-1), (',',0), ('(',1) ]

number node _ = [node]      -- default case when there is no more input

-- | Accumulate into the set of deepest nodes, building the formatted output
deepest :: (Int, String) -> Node -> (Int, String)
deepest (m, output) (n, label)
    | n > m     = (n, show n ++ ':' : label)    -- n is deeper tham what we have
    | n == m    = (m, output ++ ',' : label)    -- n is as deep, so add on label
deepest best _ = best                           -- otherwise, not as deep

main' :: IO ()
main' = interact $ getOutput . findDeepest . numberNodes
  where
    numberNodes :: String -> [Node]
    numberNodes = number (0, "")

    findDeepest :: [Node] -> (Int, String)
    findDeepest = foldl deepest (0, "")

    getOutput :: (Int, String) -> String
    getOutput = snd
MtnViewMark
la source
1
Ce code me terrifie.
seequ
Code explicatif étendu ajouté! Laissez la terreur vous rendre plus fort !!
MtnViewMark
Vous méritez un +1 pour cela.
seequ
Oh mon dieu, et je me bats avec les listes: P
Artur Trapp
4

GolfScript (75 caractères)

Pas particulièrement compétitif, mais suffisamment tordu pour qu'il présente un certain intérêt:

{.48<{"'^"\39}*}%','-)](+0.{;.@.@>-\}:^;@:Z~{2$2$={@@.}*;}:^;Z~\-])':'@','*

Le code comporte trois phases. Premièrement, nous prétraitons la chaîne d'entrée:

# In regex terms, this is s/([ -\/])/'^\1'/g
{.48<{"'^"\39}*}%
# Remove all commas
','-
# Rotate the ' which was added after the closing ) to the start
)](+

Nous nous sommes par exemple transformés A(B(C,D(E)))en 'A'^('B'^('C'^'D'^('E'^)''^)''^). Si nous affectons un bloc approprié à ^nous pouvons effectuer un traitement utile en utilisant ~pour évaluer la chaîne.

Deuxièmement, nous trouvons la profondeur maximale:

0.
# The block we assign to ^ assumes that the stack is
#   max-depth current-depth string
# It discards the string and updates max-depth
{;.@.@>-\}:^;
@:Z~

Enfin, nous sélectionnons les nœuds les plus profonds et construisons la sortie:

# The block we assign to ^ assumes that the stack is
#   max-depth current-depth string
# If max-depth == current-depth it pushes the string under them on the stack
# Otherwise it discards the string
{2$2$={@@.}*;}:^;
# Eval
Z~
# The stack now contains
#   value1 ... valuen max-depth 0
# Get a positive value for the depth, collect everything into an array, and pop the depth
\-])
# Final rearranging for the desired output
':'@','*
Peter Taylor
la source
1

Perl 5 - 85

N'hésitez pas à modifier ce message pour corriger le nombre de caractères. J'utilise la sayfonctionnalité, mais je ne connais pas les indicateurs pour la faire fonctionner correctement sans déclarer use 5.010;.

$_=$t=<>,$i=0;$t=$_,$i++while s/\w+(\((?R)(,(?R))?\))?/$1/g,/\w/;@x=$t=~/\w+/gs;say"$i:@x"

Démo sur ideone

La sortie est séparée par des espaces au lieu de séparée par des virgules.

Le code utilise simplement l'expression régulière récursive pour supprimer la racine des arbres dans la forêt, jusqu'à ce qu'il ne soit pas possible de le faire. Ensuite, la chaîne avant le dernier contiendra tous les nœuds feuilles au niveau le plus profond.

Exemples de cycles

2
0:2

2(3(4(5)),6(7))
3:5

2(7(2,6(5,11)),5(9(4)))
3:5 11 4

1(2(3(4,5),6(7,8)),9(10(11,12),13(14,15)))
3:4 5 7 8 11 12 14 15
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
la source
1

VB.net

Function FindDeepest(t$) As String
  Dim f As New List(Of String)
  Dim m = 0
  Dim d = 0
  Dim x = ""
  For Each c In t
    Select Case c
      Case ","
        If d = m Then f.Add(x)
        x = ""
      Case "("
        d += 1
        If d > m Then f.Clear() :
        m = d
        x = ""
      Case ")"
        If d = m Then f.Add(x) : x = ""
        d -= 1
      Case Else
        x += c
    End Select
  Next
  Return m & ":" & String.Join(",", f)
End Function

Hypothèse: valeurs de nœud ne peut pas contenir ,, (,)

Adam Speight
la source
1
Cela ne semble pas du tout être joué au golf. Ne pouvez-vous pas supprimer la plupart de ces espaces (je ne connais pas VB)?
seequ
Cela dépend une partie de l'espace est important.
Adam Speight
1

Javascript (E6) 120

Version itérative

m=d=0,n=[''];
prompt().split(/,|(\(|\))/).map(e=>e&&(e=='('?m<++d&&(n[m=d]=''):e==')'?d--:n[d]+=' '+e));
alert(m+':'+n[m])

Non golfé et testable

F= a=> (
    m=d=0,n=[''],
    a.split(/,|(\(|\))/)
    .map(e=>e && (e=='(' ? m < ++d && (n[m=d]='') : e==')' ? d-- : n[d]+=' '+e)),
    m+':'+n[m]
)

Testez dans la console Firefox:

['A', '2(7(2,6(5,11)),5(9(4)))', 'A(B(C,D(E)))']
.map(x => x + ' --> ' + F(x)).join('\n')

Production

"A -> 0: A

2 (7 (2,6 (5,11)), 5 (9 (4))) -> 3: 5 11 4

A (B (C, D (E))) -> 3: E "

edc65
la source