nodes: 0, module; 1, function_definition; 2, function_name:toposort; 3, parameters; 4, block; 5, identifier:initialAtoms; 6, identifier:initialBonds; 7, expression_statement; 8, expression_statement; 9, expression_statement; 10, expression_statement; 11, expression_statement; 12, comment:# for the atom and bond hashes; 13, comment:# we ignore the first atom since we; 14, comment:# would have deleted it from the hash anyway; 15, expression_statement; 16, expression_statement; 17, for_statement; 18, for_statement; 19, expression_statement; 20, expression_statement; 21, comment:# do until all the atoms are gone; 22, while_statement; 23, assert_statement; 24, assert_statement; 25, expression_statement; 26, assert_statement; 27, expression_statement; 28, return_statement; 29, comment:"""initialAtoms, initialBonds -> atoms, bonds
      Given the list of atoms and bonds in a ring
      return the topologically sorted atoms and bonds.
      That is each atom is connected to the following atom
      and each bond is connected to the following bond in
      the following manner
      a1 - b1 - a2 - b2 - ... """; 30, assignment; 31, assignment; 32, assignment; 33, assignment; 34, assignment; 35, assignment; 36, identifier:atom; 37, subscript; 38, block; 39, identifier:bond; 40, identifier:initialBonds; 41, block; 42, assignment; 43, call; 44, identifier:ahash; 45, comment:# traverse to all the connected atoms; 46, block; 47, comparison_operator:len(initialAtoms) == len(atoms); 48, comparison_operator:len(bonds) == len(atoms) - 1; 49, assignment; 50, identifier:lastBond; 51, call; 52, expression_list; 53, identifier:atoms; 54, list; 55, identifier:a_append; 56, attribute; 57, identifier:bonds; 58, list; 59, identifier:b_append; 60, attribute; 61, identifier:ahash; 62, dictionary; 63, identifier:bhash; 64, dictionary; 65, identifier:initialAtoms; 66, slice; 67, expression_statement; 68, expression_statement; 69, identifier:next; 70, subscript; 71, identifier:a_append; 72, argument_list; 73, for_statement; 74, call; 75, call; 76, call; 77, binary_operator:len(atoms) - 1; 78, identifier:lastBond; 79, call; 80, identifier:b_append; 81, argument_list; 82, identifier:atoms; 83, identifier:bonds; 84, identifier:atoms; 85, identifier:append; 86, identifier:bonds; 87, identifier:append; 88, integer:1; 89, assignment; 90, assignment; 91, identifier:initialAtoms; 92, integer:0; 93, identifier:next; 94, identifier:atom; 95, attribute; 96, comment:# both the bond and the atom have to be; 97, comment:# in our list of atoms and bonds to use; 98, comment:# ugg, nested if's...  There has to be a; 99, comment:# better control structure; 100, block; 101, else_clause; 102, identifier:len; 103, argument_list; 104, identifier:len; 105, argument_list; 106, identifier:len; 107, argument_list; 108, call; 109, integer:1; 110, attribute; 111, argument_list; 112, identifier:lastBond; 113, subscript; 114, integer:1; 115, subscript; 116, identifier:bond; 117, identifier:next; 118, identifier:oatoms; 119, if_statement; 120, block; 121, identifier:initialAtoms; 122, identifier:atoms; 123, identifier:bonds; 124, identifier:len; 125, argument_list; 126, subscript; 127, identifier:findbond; 128, subscript; 129, identifier:ahash; 130, attribute; 131, identifier:bhash; 132, attribute; 133, call; 134, block; 135, raise_statement; 136, identifier:atoms; 137, identifier:atoms; 138, integer:0; 139, identifier:atoms; 140, unary_operator; 141, identifier:atom; 142, identifier:handle; 143, identifier:bond; 144, identifier:handle; 145, attribute; 146, argument_list; 147, expression_statement; 148, assert_statement; 149, comment:# but wait! the bond has to be in our; 150, comment:# list of bonds we can use!; 151, if_statement; 152, call; 153, integer:1; 154, identifier:ahash; 155, identifier:has_key; 156, attribute; 157, assignment; 158, identifier:bond; 159, call; 160, block; 161, identifier:RingException; 162, argument_list; 163, identifier:atom; 164, identifier:handle; 165, identifier:bond; 166, call; 167, attribute; 168, argument_list; 169, expression_statement; 170, expression_statement; 171, delete_statement; 172, expression_statement; 173, break_statement; 174, string:"Atoms are not in ring"; 175, attribute; 176, argument_list; 177, identifier:bhash; 178, identifier:has_key; 179, attribute; 180, call; 181, call; 182, subscript; 183, assignment; 184, identifier:next; 185, identifier:findbond; 186, identifier:atom; 187, identifier:bond; 188, identifier:handle; 189, identifier:a_append; 190, argument_list; 191, identifier:b_append; 192, argument_list; 193, identifier:ahash; 194, attribute; 195, identifier:next; 196, identifier:atom; 197, identifier:atom; 198, identifier:bond; 199, identifier:atom; 200, identifier:handle
code: def toposort(initialAtoms, initialBonds):
      """initialAtoms, initialBonds -> atoms, bonds
      Given the list of atoms and bonds in a ring
      return the topologically sorted atoms and bonds.
      That is each atom is connected to the following atom
      and each bond is connected to the following bond in
      the following manner
      a1 - b1 - a2 - b2 - ... """
      atoms = []
      a_append = atoms.append
      bonds = []
      b_append = bonds.append
  
      # for the atom and bond hashes
      # we ignore the first atom since we
      # would have deleted it from the hash anyway
      ahash = {}
      bhash = {}
      for atom in initialAtoms[1:]:
          ahash[atom.handle] = 1
          
      for bond in initialBonds:
          bhash[bond.handle] = bond
  
      next = initialAtoms[0]
      a_append(next)
  
      # do until all the atoms are gone
      while ahash:
          # traverse to all the connected atoms
          for atom in next.oatoms:
              # both the bond and the atom have to be
              # in our list of atoms and bonds to use
              # ugg, nested if's...  There has to be a
              # better control structure
              if ahash.has_key(atom.handle):
                  bond = next.findbond(atom)
                  assert bond
                  # but wait! the bond has to be in our
                  # list of bonds we can use!
                  if bhash.has_key(bond.handle):
                      a_append(atom)
                      b_append(bond)
                      del ahash[atom.handle]
                      next = atom
                      break
          else:
              raise RingException("Atoms are not in ring")
  
      assert len(initialAtoms) == len(atoms)
      assert len(bonds) == len(atoms) - 1
      lastBond = atoms[0].findbond(atoms[-1])
      assert lastBond
      b_append(lastBond)
      return atoms, bonds