<jupyter_start><jupyter_text>Part 1<jupyter_code># We order our big list of numbers into a more structured list, where each node is demarcated by brackets, e.g.:
# [#children, #metadata, [child 1], [child 2], metadata1, metadata2]
# While we structure the list, we add up the metadatas to answer the question

def metacount(numbers):
    """Sums all the metadatas in a list of node information and orders the list in separate brackets for each node"""
    
    i = 0
    nodes = 0
    metas = 0
    
    while len(numbers) != 2 + numbers[0] + numbers[1]:
        # We keep looping until all nodes are demarcated by brackets i.e. until the whole list contains only:
        # - the two first elements (# children, # metadata)
        # - its children (each one in a separated bracket, so counting as 1)
        # - the metadata entries
        
        nbchildren = numbers[i]
        nbmetas = numbers[i+1]
        
        if type(nbchildren) == int and type(nbmetas) == int:
        
            # For nodes with no children
            if nbchildren == 0 and (i - nodes) % 2 == 0:
                metas += sum(numbers[i+2+nbchildren:i+2+nbchildren+nbmetas]) # We sum all the metadata entries
                numbers[i:i+nbmetas+2] = [numbers[i:i+nbmetas+2]]
                nodes += 1
                i = 0

            # For nodes with children, whose children we already structured into separate brackets
            elif all([type(x) == list for x in numbers[i+2:(i+2)+nbchildren]]):
                metas += sum(numbers[i+2+nbchildren:i+2+nbchildren+nbmetas]) # We sum all the metadata entries
                numbers[i:i+1+nbchildren+nbmetas+1] = [numbers[i:i+1+nbchildren+nbmetas+1]]
                i = 0                

            else:
                i += 1
                
        else:
            i += 1
            
    metas += sum(numbers[-numbers[1]:]) # We add at the end the metadata entries of the root node
         
     
    return numbers, metas
nodes, count = metacount(contents)
count<jupyter_output><empty_output><jupyter_text>Part 2<jupyter_code># Recursive function calculating the value of each node based on the rules described in the problem

def rootvalue(numbers):
    """Calculates the root value of an ordered list of node information""" 
    # We give our structured list to the function where each node is separated by brackets
    
    # If no children
    if numbers[0] == 0:
        return sum(numbers[-numbers[1]:]) # Sum of the metadata entries
                   
    # If children
    else:
        children = numbers[2:-numbers[1]] # We slice the children
        values = [rootvalue(child) for child in children] # We calculate their value, calling the function within itself
        value = 0
        metadata = numbers[-numbers[1]:]
        for data in metadata:
            if data <= len(values): # If the value of the metadata entry is smaller than the number of children
                value += values[data-1] 
        return value
        
rootvalue(nodes)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08959632425336396, 'fraction_numerical': 0.014112241549064654, 'mean_word_length': 2.2774193548387096, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '406335', 'license': 'MIT', 'n_tokens_mistral': 905, 'n_tokens_neox': 838, 'n_words': 322, 'path': 'solutions/2018/celine/day8.ipynb', 'repo_name': 'kws/AdventOfCode', 'size': '3047'}