title: Python: Find the structure of a molecule using previously known bonds
body: <p>I have data that represents atoms in a molecule. In first row and first column I have the atoms in the molecule and the rest of the list contains either distance between pairs of atoms or <code>'BOND'</code> which means that these atoms are bound to each other. Every element on the diagonal is <code>0</code> because <code>ls[0][index]</code> is the same atom as <code>ls[index][0]</code> so the distance between this pair of atoms is <code>0</code>.</p>
  <pre><code>ls = [['', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'N'],
  ['C', 0.0, 'BOND', 2.525, 3.892, 5.08, 6.414, 7.632, 'BOND', 2.124, 2.141, 2.77, 2.732, 4.163, 4.19, 5.208, 5.189, 6.582, 6.598, 8.551, 7.758, 7.745, 1.892, 'BOND'],
  ['C', 'BOND', 0.0, 'BOND', 2.557, 3.928, 5.115, 6.444, 2.205, 'BOND', 'BOND', 2.16, 2.162, 2.78, 2.778, 4.212, 4.214, 5.229, 5.228, 7.288, 6.66, 6.661, 2.577, 2.499],
  ['C', 2.525, 'BOND', 0.0, 'BOND', 2.555, 3.926, 5.107, 2.842, 2.157, 2.174, 'BOND', 'BOND', 2.156, 2.156, 2.78, 2.781, 4.209, 4.208, 6.036, 5.263, 5.264, 3.705, 3.559],
  ['C', 3.892, 2.557, 'BOND', 0.0, 'BOND', 2.558, 3.923, 4.259, 2.769, 2.81, 2.159, 2.157, 'BOND', 'BOND', 2.157, 2.157, 2.781, 2.782, 4.733, 4.243, 4.243, 4.854, 4.897],
  ['C', 5.08, 3.928, 2.555, 'BOND', 0.0, 'BOND', 2.552, 5.284, 4.2, 4.234, 2.785, 2.784, 2.157, 2.157, 'BOND', 'BOND', 2.155, 2.155, 3.503, 2.816, 2.817, 6.095, 6.078],
  ['C', 6.414, 5.115, 3.926, 2.558, 'BOND', 0.0, 'BOND', 6.674, 5.218, 5.26, 4.214, 4.213, 2.786, 2.784, 2.156, 2.156, 'BOND', 'BOND', 2.181, 2.176, 2.176, 7.318, 7.404],
  ['C', 7.632, 6.444, 5.107, 3.923, 2.552, 'BOND', 0.0, 7.794, 6.609, 6.647, 5.226, 5.225, 4.211, 4.21, 2.775, 2.774, 2.159, 2.159, 'BOND', 'BOND', 'BOND', 8.579, 8.614],
  ['H', 'BOND', 2.205, 2.842, 4.259, 5.284, 6.674, 7.794, 0.0, 2.534, 3.093, 3.174, 2.602, 4.428, 4.789, 5.471, 5.161, 6.784, 7.023, 8.751, 7.965, 7.754, 2.873, 2.011],
  ['H', 2.124, 'BOND', 2.157, 2.769, 4.2, 5.218, 6.609, 2.534, 0.0, 1.764, 3.059, 2.51, 2.54, 3.082, 4.728, 4.395, 5.099, 5.39, 7.377, 6.993, 6.77, 3.319, 3.175],
  ['H', 2.141, 'BOND', 2.174, 2.81, 4.234, 5.26, 6.647, 3.093, 1.764, 0.0, 2.512, 3.072, 3.132, 2.584, 4.419, 4.761, 5.437, 5.141, 7.418, 6.802, 7.03, 2.303, 2.666],
  ['H', 2.77, 2.16, 'BOND', 2.159, 2.785, 4.214, 5.226, 3.174, 3.059, 2.512, 0.0, 1.753, 3.061, 2.512, 2.559, 3.102, 4.739, 4.403, 6.204, 5.152, 5.444, 3.591, 3.52],
  ['H', 2.732, 2.162, 'BOND', 2.157, 2.784, 4.213, 5.225, 2.602, 2.51, 3.072, 1.753, 0.0, 2.506, 3.06, 3.102, 2.56, 4.401, 4.737, 6.203, 5.444, 5.152, 4.29, 3.889],
  ['H', 4.163, 2.78, 2.156, 'BOND', 2.157, 2.786, 4.211, 4.428, 2.54, 3.132, 3.061, 2.506, 0.0, 1.753, 3.061, 2.508, 2.559, 3.103, 4.892, 4.769, 4.431, 5.278, 5.266],
  ['H', 4.19, 2.778, 2.156, 'BOND', 2.157, 2.784, 4.21, 4.789, 3.082, 2.584, 2.512, 3.06, 1.753, 0.0, 2.51, 3.06, 3.099, 2.557, 4.89, 4.432, 4.767, 4.73, 5.001],
  ['H', 5.208, 4.212, 2.78, 2.157, 'BOND', 2.156, 2.775, 5.471, 4.728, 4.419, 2.559, 3.102, 3.061, 2.51, 0.0, 1.753, 3.058, 2.506, 3.779, 2.593, 3.134, 6.029, 6.057],
  ['H', 5.189, 4.214, 2.781, 2.157, 'BOND', 2.156, 2.774, 5.161, 4.395, 4.761, 3.102, 2.56, 2.508, 3.06, 1.753, 0.0, 2.507, 3.058, 3.778, 3.132, 2.593, 6.47, 6.279],
  ['H', 6.582, 5.229, 4.209, 2.781, 2.155, 'BOND', 2.159, 6.784, 5.099, 5.437, 4.739, 4.401, 2.559, 3.099, 3.058, 2.507, 0.0, 1.752, 2.503, 3.075, 2.522, 7.606, 7.652],
  ['H', 6.598, 5.228, 4.208, 2.782, 2.155, 'BOND', 2.159, 7.023, 5.39, 5.141, 4.403, 4.737, 3.103, 2.557, 2.506, 3.058, 1.752, 0.0, 2.502, 2.522, 3.075, 7.235, 7.472],
  ['H', 8.551, 7.288, 6.036, 4.733, 3.503, 2.181, 'BOND', 8.751, 7.377, 7.418, 6.204, 6.203, 4.892, 4.89, 3.779, 3.778, 2.503, 2.502, 0.0, 1.766, 1.766, 9.443, 9.532],
  ['H', 7.758, 6.66, 5.263, 4.243, 2.816, 2.176, 'BOND', 7.965, 6.993, 6.802, 5.152, 5.444, 4.769, 4.432, 2.593, 3.132, 3.075, 2.522, 1.766, 0.0, 1.764, 8.571, 8.641],
  ['H', 7.745, 6.661, 5.264, 4.243, 2.817, 2.176, 'BOND', 7.754, 6.77, 7.03, 5.444, 5.152, 4.431, 4.767, 3.134, 2.593, 2.522, 3.075, 1.766, 1.764, 0.0, 8.889, 8.799],
  ['H', 1.892, 2.577, 3.705, 4.854, 6.095, 7.318, 8.579, 2.873, 3.319, 2.303, 3.591, 4.29, 5.278, 4.73, 6.029, 6.47, 7.606, 7.235, 9.443, 8.571, 8.889, 0.0, 'BOND'],
  ['N', 'BOND', 2.499, 3.559, 4.897, 6.078, 7.404, 8.614, 2.011, 3.175, 2.666, 3.52, 3.889, 5.266, 5.001, 6.057, 6.279, 7.652, 7.472, 9.532, 8.641, 8.799, 'BOND', 0.0]]
  </code></pre>
  <p>What I want to do is to find how many bonds away each atom is from an atom defined as &quot;start&quot;. I always define nitrogen or oxygen as &quot;start&quot; (this molecule doesn't contain oxygen). So for example if I have a carbon that is bound to nitrogen (&quot;start&quot;), it is 1 carbon bond away from start. If another carbon is bound to this carbon, it is 2 carbon bond away from the start. Third carbon which is bound to this carbon, is 3 carbon bonds away from start etc.</p>
  <p>My approach to this problem is as follows:</p>
  <ol>
  <li>Find &quot;start&quot; atom and its index</li>
  <li>Find all atoms that have &quot;BOND&quot; to &quot;start&quot; atom, these are 1 bond away from &quot;start&quot;</li>
  <li>Find all atoms that have &quot;BOND&quot; to the atoms that are 1 bond away except the ones that I checked in previous loop. These atoms are 2 bonds away from &quot;start&quot;</li>
  <li>Find all atoms that have &quot;BOND&quot; to atoms that are 2 bonds away, except the ones that I checked in previous loop. These are 3 bonds away from &quot;start&quot;, etc...</li>
  <li>Continue this so long that all atoms are assigned with a distance from &quot;start&quot;</li>
  </ol>
  <p>I want the output to be the same list that I loop through but so that I append the distance from &quot;start&quot; to the end of each row of the array. So the output should look like this:</p>
  <pre><code>output = [['', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'N'],
  ['C', 0.0, 'BOND', 2.525, 3.892, 5.08, 6.414, 7.632, 'BOND', 2.124, 2.141, 2.77, 2.732, 4.163, 4.19, 5.208, 5.189, 6.582, 6.598, 8.551, 7.758, 7.745, 1.892, 'BOND', num],
  ['C', 'BOND', 0.0, 'BOND', 2.557, 3.928, 5.115, 6.444, 2.205, 'BOND', 'BOND', 2.16, 2.162, 2.78, 2.778, 4.212, 4.214, 5.229, 5.228, 7.288, 6.66, 6.661, 2.577, 2.499, num],
  ['C', 2.525, 'BOND', 0.0, 'BOND', 2.555, 3.926, 5.107, 2.842, 2.157, 2.174, 'BOND', 'BOND', 2.156, 2.156, 2.78, 2.781, 4.209, 4.208, 6.036, 5.263, 5.264, 3.705, 3.559, num],
  ['C', 3.892, 2.557, 'BOND', 0.0, 'BOND', 2.558, 3.923, 4.259, 2.769, 2.81, 2.159, 2.157, 'BOND', 'BOND', 2.157, 2.157, 2.781, 2.782, 4.733, 4.243, 4.243, 4.854, 4.897, num],
  ['C', 5.08, 3.928, 2.555, 'BOND', 0.0, 'BOND', 2.552, 5.284, 4.2, 4.234, 2.785, 2.784, 2.157, 2.157, 'BOND', 'BOND', 2.155, 2.155, 3.503, 2.816, 2.817, 6.095, 6.078, num],
  ['C', 6.414, 5.115, 3.926, 2.558, 'BOND', 0.0, 'BOND', 6.674, 5.218, 5.26, 4.214, 4.213, 2.786, 2.784, 2.156, 2.156, 'BOND', 'BOND', 2.181, 2.176, 2.176, 7.318, 7.404, num],
  ['C', 7.632, 6.444, 5.107, 3.923, 2.552, 'BOND', 0.0, 7.794, 6.609, 6.647, 5.226, 5.225, 4.211, 4.21, 2.775, 2.774, 2.159, 2.159, 'BOND', 'BOND', 'BOND', 8.579, 8.614, num],
  ['H', 'BOND', 2.205, 2.842, 4.259, 5.284, 6.674, 7.794, 0.0, 2.534, 3.093, 3.174, 2.602, 4.428, 4.789, 5.471, 5.161, 6.784, 7.023, 8.751, 7.965, 7.754, 2.873, 2.011, num],
  ['H', 2.124, 'BOND', 2.157, 2.769, 4.2, 5.218, 6.609, 2.534, 0.0, 1.764, 3.059, 2.51, 2.54, 3.082, 4.728, 4.395, 5.099, 5.39, 7.377, 6.993, 6.77, 3.319, 3.175, num],
  ['H', 2.141, 'BOND', 2.174, 2.81, 4.234, 5.26, 6.647, 3.093, 1.764, 0.0, 2.512, 3.072, 3.132, 2.584, 4.419, 4.761, 5.437, 5.141, 7.418, 6.802, 7.03, 2.303, 2.666, num],
  ['H', 2.77, 2.16, 'BOND', 2.159, 2.785, 4.214, 5.226, 3.174, 3.059, 2.512, 0.0, 1.753, 3.061, 2.512, 2.559, 3.102, 4.739, 4.403, 6.204, 5.152, 5.444, 3.591, 3.52, num],
  ['H', 2.732, 2.162, 'BOND', 2.157, 2.784, 4.213, 5.225, 2.602, 2.51, 3.072, 1.753, 0.0, 2.506, 3.06, 3.102, 2.56, 4.401, 4.737, 6.203, 5.444, 5.152, 4.29, 3.889, num],
  ['H', 4.163, 2.78, 2.156, 'BOND', 2.157, 2.786, 4.211, 4.428, 2.54, 3.132, 3.061, 2.506, 0.0, 1.753, 3.061, 2.508, 2.559, 3.103, 4.892, 4.769, 4.431, 5.278, 5.266, num],
  ['H', 4.19, 2.778, 2.156, 'BOND', 2.157, 2.784, 4.21, 4.789, 3.082, 2.584, 2.512, 3.06, 1.753, 0.0, 2.51, 3.06, 3.099, 2.557, 4.89, 4.432, 4.767, 4.73, 5.001, num],
  ['H', 5.208, 4.212, 2.78, 2.157, 'BOND', 2.156, 2.775, 5.471, 4.728, 4.419, 2.559, 3.102, 3.061, 2.51, 0.0, 1.753, 3.058, 2.506, 3.779, 2.593, 3.134, 6.029, 6.057, num],
  ['H', 5.189, 4.214, 2.781, 2.157, 'BOND', 2.156, 2.774, 5.161, 4.395, 4.761, 3.102, 2.56, 2.508, 3.06, 1.753, 0.0, 2.507, 3.058, 3.778, 3.132, 2.593, 6.47, 6.279, num],
  ['H', 6.582, 5.229, 4.209, 2.781, 2.155, 'BOND', 2.159, 6.784, 5.099, 5.437, 4.739, 4.401, 2.559, 3.099, 3.058, 2.507, 0.0, 1.752, 2.503, 3.075, 2.522, 7.606, 7.652, num],
  ['H', 6.598, 5.228, 4.208, 2.782, 2.155, 'BOND', 2.159, 7.023, 5.39, 5.141, 4.403, 4.737, 3.103, 2.557, 2.506, 3.058, 1.752, 0.0, 2.502, 2.522, 3.075, 7.235, 7.472, num],
  ['H', 8.551, 7.288, 6.036, 4.733, 3.503, 2.181, 'BOND', 8.751, 7.377, 7.418, 6.204, 6.203, 4.892, 4.89, 3.779, 3.778, 2.503, 2.502, 0.0, 1.766, 1.766, 9.443, 9.532, num],
  ['H', 7.758, 6.66, 5.263, 4.243, 2.816, 2.176, 'BOND', 7.965, 6.993, 6.802, 5.152, 5.444, 4.769, 4.432, 2.593, 3.132, 3.075, 2.522, 1.766, 0.0, 1.764, 8.571, 8.641, num],
  ['H', 7.745, 6.661, 5.264, 4.243, 2.817, 2.176, 'BOND', 7.754, 6.77, 7.03, 5.444, 5.152, 4.431, 4.767, 3.134, 2.593, 2.522, 3.075, 1.766, 1.764, 0.0, 8.889, 8.799, num],
  ['H', 1.892, 2.577, 3.705, 4.854, 6.095, 7.318, 8.579, 2.873, 3.319, 2.303, 3.591, 4.29, 5.278, 4.73, 6.029, 6.47, 7.606, 7.235, 9.443, 8.571, 8.889, 0.0, 'BOND', num],
  ['N', 'BOND', 2.499, 3.559, 4.897, 6.078, 7.404, 8.614, 2.011, 3.175, 2.666, 3.52, 3.889, 5.266, 5.001, 6.057, 6.279, 7.652, 7.472, 9.532, 8.641, 8.799, 'BOND', 0.0, num]]
  </code></pre>
  <p>Where <code>num</code> is the distance from &quot;start&quot;. Obviously in this case <code>num</code> in last row should be <code>0</code> because nitrogen is defined as &quot;start&quot;. And <code>num</code> on the second row should be <code>1</code> since this carbon is bound to the nitrogen etc.</p>
  <p>I tried something like this:</p>
  <pre><code>def find_distance_from_start(data):
      new_data = data
      count = 0 #count is &quot;num&quot; that should be added to the end of each row of new_data (except the first row, obviously)
  
      for i, row1 in enumerate(data):
          if data[i][0] == &quot;N&quot; or data[i][0] == &quot;O&quot;:
              start_index = i
              new_data[i].append(count)
  
              atoms_to_check = [index for index, value in enumerate(data[start_index])
                                if value == &quot;BOND&quot; and data[0][index] != &quot;H&quot;] #this should find atoms that are bound to &quot;start&quot; or whatever atom we are looking at
  
              for atom in atoms_to_check:
                  count += 1
                  new_data[atom].append(count)
                  atoms_to_check = [index for index, value in enumerate(data[atom])
                                    if value == &quot;BOND&quot; and data[0][index] != &quot;H&quot;]
                  continue
  
      return new_data
  
  x = find_distance_from_start(ls)
  for y in x:
      print(y)
  </code></pre>
  <p>But this code doesn't work. This problem seems hard for me and I just can't figure this out. Could anyone help?</p>