#!/usr/bin/env python3 #Copyright (C) 2025 by john morris beck # #Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is#hereby granted. # #THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL # #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER # #RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF # #THIS SOFTWARE. import sys # Read from stdin until EOF file_content = sys.stdin.read() def parse_s_expression(expression): def tokenize(expr): """Breaks the expression into tokens.""" return expr.replace('(', ' ( ').replace(')', ' ) ').split() def parse_tokens(tokens): """Parses tokens into a tree structure.""" if not tokens: raise ValueError("Unexpected EOF while reading.") token = tokens.pop(0) if token == '(': subtree = [] while tokens[0] != ')': subtree.append(parse_tokens(tokens)) tokens.pop(0) # Remove closing ')' return subtree elif token == ')': raise ValueError("Unexpected ')'.") else: return token tokens = tokenize(expression) return parse_tokens(tokens) def replace_freestanding_vars(tree, env=None, depth=0): """ Recursively replace freestanding variables in the tree with the depth at which they were defined. Args: tree (list or str): The tree representing the lambda structure. env (dict): A mapping of variable names to their defining depths. depth (int): The current depth of lambda nesting. Returns: list or int: A transformed tree with freestanding variables replaced by their defining depth. """ if env is None: env = {} # If the tree is a variable (symbol) if isinstance(tree, str): # Return the depth at which the variable was defined if it exists in env, else keep it as-is if tree in env: return depth - env[tree] # Count the number of lambdas since definition return tree # Freestanding variable with no definition remains unchanged # If the tree is a lambda definition if isinstance(tree, list) and len(tree) >= 3 and tree[0] == 'lambda': var_name = tree[1] # The variable being defined body = tree[2] # The body of the lambda # Create a new environment for the nested scope new_env = env.copy() new_env[var_name] = depth # Record the current depth where the variable is defined # Process the body with the updated environment and increased depth processed_body = replace_freestanding_vars(body, new_env, depth + 1) # Process any additional siblings after the lambda body siblings = tree[3:] if len(tree) > 3 else [] processed_siblings = [replace_freestanding_vars(sibling, env, depth) for sibling in siblings] return ['lambda', var_name, processed_body, *processed_siblings] # Otherwise, it's a generic list - process each element return [replace_freestanding_vars(subtree, env, depth) for subtree in tree] def omit_after_lambda(tree): if not isinstance(tree, list): # Base case: if it's not a list, return it as-is return tree result = [] skip_next = False # Flag to skip the element following "lambda" for elem in tree: if skip_next: skip_next = False continue if elem == "lambda": result.append(elem) # Keep "lambda" skip_next = True else: # Recursively process elements if they are lists result.append(omit_after_lambda(elem)) return result def replace_lambda(data): if isinstance(data, list): # Check if the element is a list return [replace_lambda(item) for item in data] # Recursively process each element in the list elif data == "lambda": # Check if the element is "lambda" return "00" # Replace "lambda" with "00" else: return data # Return the element unchanged if it's not "lambda" def prepend_to_arrays(data, is_outer=False): if isinstance(data, list): # Check if the list is an array of integers if all(isinstance(x, int) for x in data): return ["01"] * len(data) + data result = [] for idx, item in enumerate(data): if idx == 0 and item == "00" and not is_outer: # Add "01" immediately after the first "00" in non-outer lists result.append("00") result.append("01") elif isinstance(item, list): # Recursively process nested lists result.append(prepend_to_arrays(item)) else: result.append(item) return result return data # Return non-list items unchanged def process_outer_list(data): # Prepend "01" to the outermost list while processing its elements if isinstance(data, list): processed = [] for item in data: if isinstance(item, list): processed.append(prepend_to_arrays(item, is_outer=True)) else: processed.append(item) return ["01", processed] return data def replace_integers_with_ones(array): # Iterate over the elements in the array for i in range(len(array)): if isinstance(array[i], list): # If the element is a list, recurse into it replace_integers_with_ones(array[i]) elif isinstance(array[i], int): # If the element is an integer, replace it array[i] = "1" * array[i] def append_zero_to_ones(data): if isinstance(data, list): # Recursively process each item in the list return [append_zero_to_ones(item) for item in data] elif isinstance(data, str) and all(char == '1' for char in data): # Append '0' if the string contains only '1' return data + '0' else: # Return the item as is return data def flatten_and_convert_to_string(nested_array): result = [] def flatten(array): for element in array: if isinstance(element, list): flatten(element) else: result.append(element) flatten(nested_array) return ''.join(result) def replace_integers_with_ones(array): for i in range(len(array)): if isinstance(array[i], list): # If the element is a list, recurse into it array[i] = replace_integers_with_ones(array[i]) elif isinstance(array[i], int): # If the element is an integer, replace it array[i] = "1" * array[i] return array # Return the modified array def remove_comments(tree): if isinstance(tree, list): # If the first element is 'comment', return None (eliminate it) if tree and tree[0] == 'comment': return None # Otherwise, recursively process the sub-elements return [filtered for item in tree if (filtered := remove_comments(item)) is not None] return tree # Return non-list elements as is def parse_s_expression(expression): def tokenize(expr): """Breaks the expression into tokens.""" return expr.replace('(', ' ( ').replace(')', ' ) ').split() def parse_tokens(tokens): """Parses tokens into a tree structure.""" if not tokens: raise ValueError("Unexpected EOF while reading.") token = tokens.pop(0) if token == '(': subtree = [] while tokens[0] != ')': subtree.append(parse_tokens(tokens)) tokens.pop(0) # Remove closing ')' return subtree elif token == ')': raise ValueError("Unexpected ')'.") else: return token tokens = tokenize(expression) result = [] while tokens: result.append(parse_tokens(tokens)) return result def flatten_text_nodes(tree): if isinstance(tree, list): # If the list starts with "text", flatten its contents into a single string if tree[0] == "text": return ["text", " ".join(map(str, tree[1:]))] else: # Otherwise, recursively process each child return [flatten_text_nodes(child) for child in tree] return tree # Return non-list elements as is def string_to_binary(s): """Convert a string to its binary representation.""" return ''.join(format(ord(char), '08b') for char in s) def transform_tree_string_to_binary(tree): """ Recursively traverse the tree and convert strings following 'text' to their binary representation. """ if isinstance(tree, list): if len(tree) == 2 and tree[0] == 'text' and isinstance(tree[1], str): return ['text', string_to_binary(tree[1])] return [transform_tree_string_to_binary(subtree) for subtree in tree] return tree def process_binary(binary_str): result = "" for bit in binary_str: if bit == "0": result += "((lambda x (lambda y (lambda z (z x y)))) (lambda x (lambda y x))" elif bit == "1": result += "((lambda x (lambda y (lambda z (z x y)))) (lambda x (lambda y y))" result += ")" * len(binary_str) # Append the right parentheses return result def transform_tree_binary_to_lambda(tree): if isinstance(tree, list): # Check if the first element is "text" and the second is a binary string if tree[0] == "text" and isinstance(tree[1], str) and all(bit in "01" for bit in tree[1]): transformed_text = process_binary(tree[1]) return [tree[0], transformed_text] # Replace the binary string with the transformed string else: # Recursively process each element of the list return [transform_tree_binary_to_lambda(subtree) for subtree in tree] return tree # If it's not a list, return it as is def unprepend_text(arr): if isinstance(arr, list): # Check if the array begins with "text" if len(arr) > 0 and arr[0] == "text": return arr[1:] # Return the array without "text" else: # Recursively process each element return [unprepend_text(item) for item in arr] return arr # Return non-list elements as-is def transform_tree_parse_s_expression(array): for i, item in enumerate(array): if isinstance(item, list): # Recursively process nested arrays array[i] = transform_tree_parse_s_expression(item) elif isinstance(item, str) and i > 0 and array[i-1] == "text": # Replace the string with the parsed result array[i] = parse_s_expression(item) return array def process_binary2(binary_str): result = "" for bit in binary_str: if bit == "0": result += "((lambda x (lambda y (lambda z (z x y)))) (lambda x (lambda y x))" elif bit == "1": result += "((lambda x (lambda y (lambda z (z x y)))) (lambda x (lambda y y))" result += "(lambda x (lambda y y))" # Append the additional lambda expression result += ")" * (len(binary_str)) # Append the right parentheses return result def transform_tree(tree): if isinstance(tree, list): # Check if the first element is "text" and the second is a binary string if tree[0] == "text" and isinstance(tree[1], str) and all(bit in "01" for bit in tree[1]): transformed_text = process_binary2(tree[1]) # Transform the binary string return [tree[0], transformed_text] # Replace the binary string with the transformed string else: # Recursively process each element of the list return [transform_tree(subtree) for subtree in tree] return tree # If it's not a list, return it as is def insert_01(data): # Check if the input is a list if isinstance(data, list): # Check if the first element is '00' and the list has more than 2 elements if len(data) > 1 and data[0] == '00': # Insert a list of '01' with length len(data) - 2 after the first element data.insert(1, ['01'] * (len(data) - 2)) # Recursively apply the function to each element in the list for i in range(len(data)): insert_01(data[i]) return data def insert_01(data): # Check if the input is a list if isinstance(data, list): # Check if the list starts with '00' and has more than 2 elements if len(data) > 2 and data[0] == '00': # Insert '01' elements directly into the list after the first element num_of_01 = len(data) - 2 data[1:1] = ['01'] * num_of_01 # Splice the '01' elements directly # Recursively process each element in the list for i in range(len(data)): insert_01(data[i]) return data def insert_more_01(tree, depth=0): updated_tree = [] for item in tree: if isinstance(item, list): if len(item) > 0 and item[0] != '00': # Create a list of '01' with length depth + 1 prefix = ['01'] * (depth + 1) # Prepend the prefix to the current list, but do not process further updated_tree.append(prefix + item) else: # Recursively process children if it starts with '00' updated_tree.append([item[0]] + insert_more_01(item[1:], depth + 1)) else: # Keep non-list items as they are updated_tree.append(item) return updated_tree def prepend_01_to_arrays(tree): def process(subtree): # If the subtree is a list of lists if all(isinstance(item, list) for item in subtree): # Calculate the number of '01' to prepend num_01 = len(subtree) - 1 # Prepend '01' elements to the subtree return ['01'] * num_01 + [process(item) for item in subtree] elif isinstance(subtree, list): # Recur for each item in the list return [process(item) for item in subtree] return subtree # Return non-list items as is return process(tree) def insert_more_01(tree, depth=0): updated_tree = [] for item in tree: if isinstance(item, list): prefix = ['01'] * depth updated_tree.append(prefix + insert_more_01(item, depth + 1)) # Corrected recursion else: updated_tree.append(item) return updated_tree def insert_more_01(tree, depth=0): updated_tree = [] for item in tree: if isinstance(item, list): if len(item) > 0 and item[0] == '00': # Only increment depth for lambda abstractions updated_tree.append(['00'] + insert_more_01(item[1:], depth + 1)) # Corrected recursion else: prefix = ['01'] * depth updated_tree.append(prefix + insert_more_01(item, depth)) # Corrected prefixing else: updated_tree.append(item) return updated_tree def insert_more_01(tree, depth=0): """ Inserts '01' prefixes into the tree based on the depth of lambda abstractions. Args: tree: The input tree (list) representing the Fastlisp expression. depth: The current depth of lambda nesting. Returns: The modified tree with '01' prefixes inserted. """ updated_tree = [] for item in tree: if isinstance(item, list): if len(item) > 0 and item[0] == '00': # Only increment depth for lambda abstractions updated_tree.append(['00'] + insert_more_01(item[1:], depth + 1)) else: prefix = ['01'] * depth updated_tree.append(prefix + insert_more_01(item, depth)) else: updated_tree.append(item) return updated_tree def insert_more_01(tree, depth=0): """ Inserts '01' prefixes into the tree based on the depth of lambda abstractions. Args: tree: The input tree (list) representing the Fastlisp expression. depth: The current depth of lambda nesting. Returns: The modified tree with '01' prefixes inserted. """ updated_tree = [] for item in tree: if isinstance(item, list): if len(item) > 0 and item[0] == '00': # Only increment depth for lambda abstractions updated_tree.append(['00'] + insert_more_01(item[1:], depth + 1)) else: prefix = ['01'] * depth updated_tree.append(prefix + insert_more_01(item, depth)) # Corrected prefixing else: updated_tree.append(item) return updated_tree def insert_more_01(tree, depth=0): """ Inserts '01' prefixes into the tree based on the depth of lambda abstractions. Args: tree: The input tree (list) representing the Fastlisp expression. depth: The current depth of lambda nesting. Returns: The modified tree with '01' prefixes inserted. """ updated_tree = [] for item in tree: if isinstance(item, list): if item and item[0] == '00': # Lambda abstraction updated_tree.append(['00'] + insert_more_01(item[1:], depth + 1)) else: # Application prefix = ['01'] * depth updated_tree.append(prefix + insert_more_01(item, depth)) else: updated_tree.append(item) return updated_tree def prepend_01_to_arrays(tree): """ Prepends '01' to arrays within a tree structure based on their length. Args: tree: The input tree (nested lists). Returns: The modified tree with '01' prepended to arrays. """ def process_subtree(subtree): if isinstance(subtree, list): if subtree and subtree[0] == '00': # Skip arrays starting with '00' at this level return ['00'] + [process_subtree(item) for item in subtree[1:]] # recursively process the rest of the list else: num_01 = len(subtree) - 1 if num_01 > 0: return ['01'] * num_01 + [process_subtree(item) for item in subtree] else: return [process_subtree(item) for item in subtree] # Still process nested lists even if num_01 = 0 else: return subtree # Return non-list items as is return process_subtree(tree) def insert_01_after_00(tree): """ Inserts '01' elements after '00' in arrays within a tree structure. Args: tree: The input tree (nested lists). Returns: The modified tree. """ def process_subtree(subtree): if isinstance(subtree, list): if subtree and subtree[0] == '00' and len(subtree) > 2: num_01 = len(subtree) - 2 # Number of elements after '00' minus 1 return ['00'] + ['01'] * num_01 + [process_subtree(item) for item in subtree[1:]] #Insert 01's and process the rest else: return [process_subtree(item) for item in subtree] else: return subtree return process_subtree(tree) def compile(source): temp=source temp=parse_s_expression(temp) temp=remove_comments(temp) temp=flatten_text_nodes(temp) temp=transform_tree_string_to_binary(temp) temp=transform_tree(temp) temp=transform_tree_parse_s_expression(temp) temp=unprepend_text(temp) temp=replace_freestanding_vars(temp) temp=omit_after_lambda(temp) temp=replace_lambda(temp) temp=prepend_01_to_arrays(temp) temp=insert_01_after_00(temp) ## temp=insert_01(temp) ## temp=insert_more_01(temp) temp=replace_integers_with_ones(temp) temp=append_zero_to_ones(temp) ## temp=prepend_01_to_arrays(temp) temp=flatten_and_convert_to_string(temp) return temp print((compile(file_content)))