import re

# Assuming sign_degrees is in string format


def find_letters_sequence(line):
    result = ""
    x = 0
    found_string_a = ""  # Initialize a string to store all found strings
    
    while x < len(line):
        if line[x].isalpha():
            found_string_a += line[x]
            result += "_"
        else:
            # If the current character is not a letter, simply append it
            result += line[x]

        x += 1

    return result, found_string_a

def replace_letters_with_words2(line):
    result = ""
    i = 0

    while i < len(line):
        if line[i].isalpha():
            # When a letter is encountered, append ' found '
            result += 'found'
        else:
            # If the current character is not a letter, simply append it
            if line[i].isdigit() and (i == 0 or not line[i - 1].isdigit()) and (i + 1 == len(line) or not line[i + 1].isdigit()):
                result += '0' + line[i]  # Add leading '0' for single-digit numbers
            else:
                result += line[i]

        i += 1

    return result

def generate_table_string(data, header, header_widths):
    # Format the headers with appropriate width
    headers_formatted = ["{:<{width}}".format(column, width=width) for column, width in zip(header, header_widths)]

    # Initialize the table string with the formatted header
    table_string ="_" * 122 + "\n" + "|".join(headers_formatted) + "\n" + "_" * 122 + "\n"

    # Concatenate each row
    for row in data:
        # Format each row entry with appropriate width
        row_formatted = ["{:<{width}}".format(entry, width=width) for entry, width in zip(row, header_widths)]
        table_string += "|".join(row_formatted) + "\n"

    return table_string

#----->Don't use this use prevy program table string for data
ephemeris_data_list = [
    "S 18 9 49 51 28°48'49 15°27 20°42 1°39 3°39 9°25 8°27 19°18 26°19 0°53 16°54 18°20 15°19 16°40 S 18",
    "M 19 9 53 48 29°49'22 28°12 22°25 2°53 4°25 9°33 8°34 19°19 26°21 0°55 16°50 18°17 15°25 16°43 M 19",
    "T 20 9 57 44 0l49'52 10d44 24° 9 4° 7 5°11 9°42 8°42 19°20 26°23 0°56 16°45 18°14 15°32 16°46 T 20",
    "W 21 10 1 41 1°50'21 23° 3 25°54 5°21 5°58 9°51 8°49 19°21 26°25 0°58 16°37 18°11 15°39 16°48 W 21",
    "T 22 10 5 37 2°50'48 5e13 27°40 6°36 6°44 10° 1 8°56 19°23 26°27 1° 0 16°29 18° 7 15°45 16°51 T 22",
    "F 23 10 9 34 3°51'13 17°15 29°27 7°50 7°30 10°10 9° 4 19°24 26°29 1° 1 16°20 18° 4 15°52 16°54 F 23",
    "S 24 10 13 30 4°51'36 29°12 1l14 9° 4 8°17 10°20 9°11 19°25 26°31 1° 3 16°12 18° 1 15°59 16°57 S 24",
    "S 25 10 17 27 5°51'58 11f 3 3° 3 10°18 9° 3 10°29 9°18 19°27 26°34 1° 5 16° 6 17°58 16° 5 16°59 S 25",
    "M 26 10 21 23 6°52'18 22°52 4°52 11°33 9°49 10°39 9°25 19°28 26°36 1° 7 16° 1 17°55 16°12 17° 2 M 26",
    "T 27 10 25 20 7°52'36 4g41 6°43 12°47 10°36 10°49 9°33 19°30 26°38 1° 8 15°D59 17°52 16°19 17° 5 T 27",
    "W 28 10 29 17 8°52'53 16°31 8°34 14° 1 11°22 10°59 9°40 19°31 26°40 1°10 15°58 17°48 16°25 17° 8 W 28",
    "T 29 10 33 13 9l53'08 28g26 10l26 15k15 12k 9 11b 9 9l47 19b33 26l42 1k11 15a59 17a45 16f32 17a11 T 29"
]


# Define the header
header = ["Day", "Sid Time", "A", "B", "C", "D", "E", "F", "G", "O", "I", "J", "L", "K", "M", "N", "Day"]

# Define the widths for each header column
header_widths = [5, 9, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5]

# Initialize the data table
data_table_from_here = []

# Loop through each line in the ephemeris data list
for line in ephemeris_data_list:
    # Get Part A and Part B
    result_sequence, found_string_a = find_letters_sequence(line)

    # Use a simple split to separate Part B into individual elements
    b_sequence = replace_letters_with_words2(line)

    pattern = re.compile(r'(\d{2}found \d{2})')
    pattern2 = re.compile(r'(\d{2}\s*\°\s*\d{2})')

    # Find all matches for the first pattern
    matches1 = pattern.findall(b_sequence)

    # Find all matches for the second pattern
    matches2 = pattern2.findall(b_sequence)

    # Replace the 'word 'found' zones' with an empty string in the matched patterns for the first pattern
    for match in matches1:
        b_sequence = b_sequence.replace(match, match.replace(' ', ''))

    # Replace the spaces created by the '°' zones of the type nnletterspacezeronumber with an empty string in the matched patterns for the second pattern
    for match in matches2:
        b_sequence = b_sequence.replace(match, match.replace(' ', ''))

    # Use Part A and Part B as needed
    Part_A = found_string_a
    Part_B = b_sequence

    new_string_stage_two = str(Part_B)

    # Check for single-digit numbers and add a tens column as zero
    i = 0
    while i < len(new_string_stage_two):
        if new_string_stage_two[i].isdigit() and (i == 0 or not new_string_stage_two[i - 1].isdigit()) and (
                i + 1 == len(new_string_stage_two) or not new_string_stage_two[i + 1].isdigit()):
            new_string_stage_two = new_string_stage_two[:i] + '0' + new_string_stage_two[i:]
            i += 1  # Skip the added '0'
        else:
            i += 1

    Part_B = new_string_stage_two

    # Initialize modified_line with Part_B
    modified_line = Part_B

    # Iterate over each letter in Part_A and replace "found" in modified_line
    for letter in Part_A:
        modified_line = modified_line.replace("found", letter, 1)
    
    # Do moon's true node delete R
    modified_line = re.sub(r'(\d{1,2}°R\d{1,2})', lambda match: match.group(0).replace('R', ''), modified_line)

# Do moon's true node delete D
    modified_line = re.sub(r'(\d{1,2}°D\d{1,2})', lambda match: match.group(0).replace('D', ''), modified_line)

    # Entry for the table
    entry = [modified_line[:5], modified_line[5:13], modified_line[13:22], modified_line[22:28], modified_line[28:34],
             modified_line[34:40], modified_line[40:46], modified_line[46:52], modified_line[52:58],
             modified_line[58:64], modified_line[64:70], modified_line[70:76], modified_line[76:82],
             modified_line[82:88], modified_line[88:94], modified_line[94:100], modified_line[100:106]]

    data_table_from_here.append(entry)

# Generate table string
    table_string2 = generate_table_string(data_table_from_here, header, header_widths)

# Print the table string or save it to a file
print ("table_string2")
print(table_string2)

# ---->okay this part look here...
# these are needed to substitute the name for the letters
zodiac_mapping = {'a': 'Aries', 'b': 'Taurus', 'c': 'Gemini', 'd': 'Cancer', 'e': 'Leo', 'f': 'Virgo', 'g': 'Libra', 'h': 'Scorpio', 'i': 'Sag', 'j': 'Capricorn', 'k': 'Aquarius', 'l': 'Pisces'}

#sign_degrees = {'Aries': 0, 'Taurus': 30, 'Gemini': 60, 'Cancer': 90, 'Leo': 120, 'Virgo': 150, 'Libra': 180, 'Scorpio': 210, 'Sag': 240, 'Capricorn': 270, 'Aquarius': 300, 'Pisces': 330}
sign_degrees = {'Aries': 0, 'Taurus': 30, 'Gemini': 60, 'Cancer': 90, 'Leo': 120, 'Virgo': 150, 'Libra': 180, 'Scorpio': 210, 'Sagittarius': 240, 'Capricorn**': 270, 'Aquarius***': 300, 'Pisces*****': 330}
    
#table part
#temporary_store_B = {}

output_string = "" # last table needs this defined which prints correct true Longitude correct
# Define the header
header = ["Day", "Sid Time", "A", "B", "C", "D", "E", "F", "G", "O", "I", "J", "L", "K", "M", "N", "Day"]

# Define the widths for each header column
header_widths = [5, 9, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5]

def generate_table_output_string(header, header_widths):
    # Format the headers with appropriate width
    headers_formatted = ["{:<{width}}".format(column, width=width) for column, width in zip(header, header_widths)]

#Initialize the table string with the formatted header
    line_string ="|".join(headers_formatted) 
    # 
    #line_string ="_" * 122 + "\n" + "|".join(headers_formatted) + "\n" + "_" * 122 
    # these column widths need to be passed to the header widths so that they may be updated
    header_widths = [max(len(str(output_string)) + 2 for i in column) for column in zip(*output_string)]
    
    print ("header widths", header_widths)
    
    print (line_string)

    return line_string
    
line_string = generate_table_output_string(header, header_widths)

#print ("line_string", line_string)

#table_thingamob = line_string + output_string

# two 
def calculate_true_longitude(line, B, C, D, zodiac_sign, sign_degrees):
    #if been_there_done_that == 0:
    
    output_string = ""

    # to calculate the true Longitude
    sign_degrees = {'Aries': 0, 'Taurus': 30, 'Gemini': 60, 'Cancer': 90, 'Leo': 120, 'Virgo': 150, 'Libra': 180, 'Scorpio': 210, 'Sagittarius': 240, 'Capricorn': 270, 'Aquarius': 300, 'Pisces': 330}

    zodiac_mapping = {'a': 'Aries', 'b': 'Taurus', 'c': 'Gemini', 'd': 'Cancer', 'e': 'Leo', 'f': 'Virgo******', 'g': 'Libra', 'h': 'Scorpio', 'i': 'Sag', 'j': 'Capricorn', 'k': 'Aquarius', 'l': 'Pisces'}

    # Process B to extract degrees and minutes
    BtoNtype_processed = re.sub(r' (\d)(\d)° (\d) ', lambda match: f'|0{match.group(1)}°0{match.group(2)}|0{match.group(3)}°0{match.group(4)}|', B) #name hones the data of columns

    BtoNtype_str = str(BtoNtype_processed)

    degrees_first_phase = ''.join(char if char.isnumeric() else '' for char in BtoNtype_str)
    #degrees = int(degrees_first_phase[:-2])  # Convert degrees to integer
    
    if degrees_first_phase:
        degrees = int(degrees_first_phase[:-2])  # Convert degrees to integer
    else:
        degrees = 0
      
    minutes_first_phase = ''.join(char if char.isnumeric() else '' for char in BtoNtype_str)
   # minutes = int(minutes_first_phase[-2:])  # Convert minutes to integer
   
    if minutes_first_phase:
        minutes = int(minutes_first_phase[:-2])  # Convert degrees to integer
    else:
        minutes = 0
   
    B = line

    B = re.sub(r' (\d)(\d)° (\d) ', lambda match: f'|0{match.group(1)}°0{match.group(2)}|0{match.group(3)}°0{match.group(4)}|', line[0:8]) # relative to span (cell sun)
    zodiac_key_pattern_sun = re.compile(r'[a-zA-Z]')
    zodiac_key_match_sun = zodiac_key_pattern_sun.search(line[22:27])
    
    A_pattern_sun = re.compile(r'(\d+°\d+\'\d+)')
    A_match_sun = A_pattern_sun.search(line)
    sun = A_match_sun.group() if (A_match_sun and 'a' not in A_match_sun.group()) else line[15:22]
    # the newly generated line from the ephemeris contains zeros and bars so character position changes
    
    # With Pisces sun specifically
    if 'l' in sun:
            zodiac_key = line[19]
            zodiac_sign_sun = zodiac_mapping.get(zodiac_key, "Unknown")
            sun = f'{line[17]}{line[18]}{zodiac_sign_sun}{line[20:25]}'
            sun_location = zodiac_sign_sun
            print (sun_location)
    #print ("sun")
    #print (sun)
    #lines = line.split('\n')
       
    line = line[:16] + " " + sun + line[25:]
    
    lines = line.split('\n')
    
    output_string += f"{line}"
   
    print (output_string)
    # output_string is modified here and contains difference in column widths
    # these column widths need to be passed to the header widths so that they may be updated
    header_widths = [max(len(str(output_string)) + 2 for i in column) for column in zip(*output_string)]
    
    print ("two_the whole row is being examined")
    #print (headers_formatted)
    print ("two_the whole row", header_widths)
    
# Initialize a list to store the widths of each column
    column_widths = []

# Iterate over each row
    for row in output_string.split('\n'):
    # Initialize a list to store the width of each column in the current row
        row_column_widths = []
    # Iterate over each column in the row
        for column in row.split('|'):
        # Calculate the width of the current column and append it to the list
            column_width = len(column.strip())  # Remove leading/trailing whitespaces
            row_column_widths.append(column_width)
    # Update the maximum width of each column encountered so far
        if not column_widths:
            column_widths = row_column_widths
        else:
            for i in range(len(column_widths)):
                column_widths[i] = max(column_widths[i], row_column_widths[i])

# Print the widths of each column
    #print("Widths of each column in each row:")
    for i, width in enumerate(column_widths, start=1):
        pass
# Print the widths of each column
    print("two_Widths of each column:")
    for i, width in enumerate(column_widths, start=1):
        pass
        #print(f"Column {i}: {width}")

# Find the maximum width among all columns
    max_width = max(column_widths)
    print("two_Maximum width:", max_width)

   # print (f"Column {i}: {width}")
    print ("two_output_string", output_string) # last table
    #table_string2 = output_string
    #print (table_string2)
    
    max_column_widths_list = []  # Initialize a list to store the maximum width counts for each set of outputs

# Iterate over each row in the set of outputs
    for row in output_string.split('\n'):
    # Initialize a dictionary to store the maximum width count for each column position in the current row
        max_column_width_counts = {}
    
    # Iterate over each column in the row
        for i, column in enumerate(row.split('|')):
        # Calculate the width of the current column
            column_width = len(column.strip())  # Remove leading/trailing whitespaces
        
        # Update the maximum count for the current column position in the dictionary
            if i not in max_column_width_counts:
                max_column_width_counts[i] = column_width
            else:
                max_column_width_counts[i] = max(max_column_width_counts[i], column_width)
    
    # Append the dictionary containing maximum width counts for the current row to the list
        max_column_widths_list.append(max_column_width_counts)

        print(max_column_widths_list)
# Convert the maximum column width counts to plain ASCII characters
        #plain_ascii_widths = [chr(width) for width in max_column_width_counts.values()]
        #print (max_column_widths_list)

    column_widths = []

# Iterate over each row
    for row in output_string.split('\n'):
    # Initialize a list to store the width of each column in the current row
        row_column_widths = []
    # Iterate over each column in the row
    for column in row.split('|'):
        # Calculate the width of the current column and append it to the list
        column_width = len(column.strip())  # Remove leading/trailing whitespaces
        row_column_widths.append(column_width)
    # Update the maximum width of each column encountered so far
    if not column_widths:
        column_widths = row_column_widths
    else:
        for i in range(len(column_widths)):
            column_widths[i] = max(column_widths[i], row_column_widths[i])

# Print the widths of each column
    print("two_Widths of each column list:")
   
    for i, width in enumerate(column_widths, start=1):
        #print(f"Column {i}: {width}")
        pass
# Initialize a dictionary to store the maximum counts for each column position
    max_column_width_counts = {}
    
    arbitrary_widths = [5, 9, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5]
    
# Iterate over each row in the first set of outputs
    for row in output_string.split('\n'):
    # Iterate over each column in the row
        for i, column in enumerate(row.split('|')):
        # Calculate the width of the current column
            column_width = len(column.strip())  # Remove leading/trailing whitespaces
        # Update the maximum count for the current column position in the dictionary
            if i not in max_column_width_counts:
                max_column_width_counts[i] = column_width
            else:
                max_column_width_counts[i] = max(max_column_width_counts[i], column_width)

# Convert the dictionary values to a list
    max_counts = list(max_column_width_counts.values())

    to_compare_with = max_counts
 
   # max_column_width_counts = {}
    #print (max_column_width_counts)
# Print the to_compare_with array
    print("two_to_compare_with:", to_compare_with)

    sign_degree_value = sign_degrees.get(zodiac_sign, 0)

    # Convert sign_degree_value to float
    sign_degree_value = float(sign_degree_value)
    
    true_longitude = sign_degree_value + degrees + (minutes / 60)
    #print ("this is the correct True Longitude:")
    print ("two_True Longitude:", true_longitude)

    return (true_longitude, degrees, minutes)

#Calculate the maximum width for each column
table_thingamob = ""

print ("after two_here")

# these are necessary to trigger data later on
moon = ""
C = ""
D = ""
E = ""
F = ""
G = ""
O = ""
I = ""
J = ""
L = ""
K = ""
M = ""
N = ""


zodiac_sign = ""
sign_degrees = {'Aries': 0, 'Taurus': 30, 'Gemini': 60, 'Cancer': 90, 'Leo': 120, 'Virgo': 150, 'Libra': 180, 'Scorpio': 210, 'Sagittarius': 240, 'Capricorn': 270, 'Aquarius': 300, 'Pisces': 330}
        #      ees = json.loads(sign_degrees)

result_tuple = calculate_true_longitude(line, moon, C, D, zodiac_sign, sign_degrees)
true_longitude = result_tuple[0]
degrees = result_tuple[1]
minutes = result_tuple[2]

    
def parse_table_string2(table_string2):
    data = []
    header = None
    zodiac_sign = None  # Default 
    
    # split the table string into lines and process each line
    for line in table_string2.split('\n'):
        if '|' in line:
            if not header:
                header = [cell.strip() for cell in line.split('|') if cell.strip()]
                continue

            cells = [cell.strip() for cell in line.split('|') if cell.strip()]
            Day = cells[0]
            sid_t = cells[1]
            sun = cells[2]
            moon = cells[3]
            C = cells[4]
            D = cells[5]
            E = cells[6]
            F = cells[7]
            G = cells[8]
            O = cells[9]
            I = cells[10]
            J = cells[11]
            L = cells[12]
            K = cells[13]
            M = cells[14]
            N = cells[15]
            
            zodiac_key_pattern = re.compile(r'[a-zA-Z]')
            zodiac_key_match = zodiac_key_pattern.search(line[22:27])
            zodiac_key_match = zodiac_key_pattern.search(cells[3])  # Search within cell B
            
            if zodiac_key_match:
                zodiac_key = zodiac_key_match.group()
                zodiac_sign = zodiac_mapping.get(zodiac_key, "Unknown")
                line = line.replace(zodiac_key, f'{zodiac_sign}')
                sign_degree_value = sign_degrees.get(zodiac_sign, 0)

            #true_longitude, degrees, minutes = calculate_true_longitude(line, B, C, D, zodiac_sign, sign_degrees)
            true_longitude, _, _ = calculate_true_longitude(line, moon, C, D, zodiac_sign, sign_degrees)

            # Append data tuple to the list
            data.append((Day, sun, moon, C, D, E, F, G, O, I, J, K, L, M, N, true_longitude, header))
           # print (data, "\n")
           
            header_widths = [max(len(str(line_string)) + 2 for i in column) for column in zip(*line_string)]
    
           # print ("header widths", header_widths)
    
    
            
    
    return data
# data is read from table_string2
data = parse_table_string2(table_string2) #table string2 updated
# Convert data to a string with newline characters between elements



# Print each element of data on a new line
for row in data:
    print(row)
    print()  # Print an empty line between rows

# Iterate over each element of data
for row in data:
    # Iterate over indices from 0 to 18
    for x in range(17):
        # Access the string at index x in the tuple
        string_row = row[x]
    
        # Print the string
        print(string_row)
    # Print an empty line between rows
    print()

#     print (moon_data_string)
    # Print the square brackets on a new line
#Print selected row on separate lines
for row in data:
    # Access the string element within the tuple
    moon_row = row[2] # is also cell 3 - the moon
    # Split the row at '['
    parts = moon_row.split('[')
    
    moon_data_string = str(parts[0].strip())

    # Print the part before the square brackets
    #print(parts[0].strip())
    print (moon_data_string)
    # Print the square brackets

# Define the suffix mapping
suffix_map = {
    'a': 'a', 
    'b': 'b',
    'c': 'c',
    'd': 'd',
    'e': 'e',
    'f': 'f',
    'g': 'g',
    'h': 'h',
    'i': 'i', 
    'j': 'j', 
    'k': 'k', 
    'l': 'l'
}

#suffix_map = {
    #'a': 'Aries', 
    #'b': 'Taurus',
    #'c': 'Cancer',
    #'d': 'Gemini',
    #'e': 'Leo',
    #'f': 'Virgo',
    #'g': 'Libra',
    #'h': 'Scorpio',
    #'i': 'Sag', 
    #'j': 'Capricorn', 
    #'k': 'Aquarius', 
    #'l': 'Pisces'
#}

previous_suffix = ''  # Initialize previous suffix

# Reverse the data list
data.reverse()
modified_data = []
for row_index, row in enumerate(data):
    # Access the string element within the tuple
    moon_row = row[2]  # is also cell 3 - the moon
    print("Moon Row:", moon_row)  # Print the moon_row for debugging
    # Split the row at '['
    parts = moon_row.split('[')

    moon_data_string = str(parts[0].strip())

    # Split the moon_data_string by line breaks
    moon_data_parts = moon_data_string.split('\n')
    
    # Replace the degree symbol with the appropriate suffix
    for part in moon_data_parts:
        modified_part = ''
        for char in part:
            if char == '°':
                modified_part += previous_suffix
            else:
                modified_part += char
                if char in suffix_map:  # Check if the character is in the suffix map
                    previous_suffix = suffix_map[char]  # Update previous_suffix
        
# Reverse the output list
        modified_data.append(modified_part)

# Reverse the modified data list
modified_data.reverse()

# Print the modified moon data
for entry in modified_data:
    print(entry)
print ()
print ()
suffix_map = {
    'a': 'a', 
    'b': 'b',
    'c': 'c',
    'd': 'd',
    'e': 'e',
    'f': 'f',
    'g': 'g',
    'h': 'h',
    'i': 'i', 
    'j': 'j', 
    'k': 'k', 
    'l': 'l'
}

suffix_map = {
    'a': 'Aries', 
    'b': 'Taurus',
    'c': 'Cancer',
    'd': 'Gemini',
    'e': 'Leo',
    'f': 'Virgo',
    'g': 'Libra',
    'h': 'Scorpio',
    'i': 'Sag', 
    'j': 'Capricorn', 
    'k': 'Aquarius', 
    'l': 'Pisces'
}
default_suffix = '°'
marker_suffix = default_suffix
previous_degrees = None
modified_data = []
sign_change = ''
degrees_start_reference = ''
data.reverse()
zodiac_mapping = {'a': 'Aries', 'b': 'Taurus', 'c': 'Cancer', 'd': 'Gemini', 'e': 'Leo', 'f': 'Virgo', 'g': 'Libra', 'h': 'Scorpio', 'i': 'Sag', 'j': 'Capricorn', 'k': 'Aquarius', 'l': 'Pisces'}
for row_index, row in enumerate(data):
    # Access the string element within the tuple
    moon_row = row[2]  # is also cell 3 - the moon
    print ()
    print("Moon Row:", moon_row)  # Print the moon_row for debugging
    # Split the row at '['
    parts = moon_row.split('[')

    moon_data_string = str(parts[0].strip())

    # Split the moon_data_string by line breaks
    moon_data_parts = moon_data_string.split('\n')
    
    # Replace the degree symbol with the appropriate suffix
    for part in moon_data_parts:
        zodiac_key_match = re.search(r'[a-zA-Z]', part)
        print (part)
        if zodiac_key_match:
            zodiac_key = zodiac_key_match.group().lower()  # Convert to lowercase for consistency
            zodiac_sign = zodiac_mapping.get(zodiac_key, "Unknown")
        # Replace zodiac key with sign name in the modified part
            modified_part = modified_part.replace(zodiac_key, zodiac_sign)

        numeric_part = ''.join(filter(str.isdigit, part))
        #print (numeric_part)
        
        degrees_minutes = ''.join(filter(str.isdigit, part))
        
        if len(degrees_minutes) >= 4:  # Check if numeric part contains both degrees and minutes
            degrees = int(degrees_minutes[:-2])  # Extract degrees
            minutes = int(degrees_minutes[-2:])  # Extract minutes
            degrees += minutes / 60 
       
       # print (degrees)
       # print (previous_degrees)
        
        if previous_degrees is None:
            value = 0
            #print (value)
        else:   
            value = degrees - previous_degrees
           # print (value)
      
        if value < 0:
            sign_change =+ 1
            print ("assignation one means zodiac sign changed", sign_change)
           
        modified_part = ''
        

        if sign_change == 1:
            for char in part:
            # Update previous_suffix
        
                if value > 0:
                    modified_part += char # updateddate previous_suffix
                else:
                    modified_part += char # Up
                    if char in suffix_map:  # Check if the character is in the suffix map
                        marker_suffix = suffix_map[char]  # Update previous_suffix
         
        else:
            for char in part:
            # Update previous_suffix
           
           
                if char == '°':
                    modified_part += previous_suffix
                  

                else:
                    modified_part = marker_suffix
                    if char in suffix_map:  # Check if the character is in the suffix map
                        previous_suffix = suffix_map[char]  # Update previous_suffix
    
                if  char == '°' and sign_change == 0:
                    modified_part == marker_suffix
                    print (marker_suffix)
                    degrees_start_reference = modified_part
              
                    print ("calculate suffix of assignation", degrees_start_reference)
                    
        
        sign_change = 0       
        previous_degrees = degrees
# Reverse the output list
        modified_data.append(modified_part)

# Reverse the modified data list
modified_data.reverse()

# Print the modified moon data
for entry in modified_data:
    print(entry)


modified_data = []
previous_degrees = 0
zodiac_mapping = {'a': 'Aries', 'b': 'Taurus', 'c': 'Cancer', 'd': 'Gemini', 'e': 'Leo', 'f': 'Virgo', 'g': 'Libra', 'h': 'Scorpio', 'i': 'Sag', 'j': 'Capricorn', 'k': 'Aquarius', 'l': 'Pisces'}

for row_index, row in enumerate(data):
    # Access the string element within the tuple
    moon_row = row[2]  # is also cell 3 - the moon
    print()
    print("Moon Row:", moon_row)
    
    # Reset modified_part for each moon row
    modified_part = moon_row
    
    zodiac_key_match = re.search(r'[a-zA-Z]', moon_row)
        
    if zodiac_key_match:
        zodiac_key = zodiac_key_match.group().lower()  # Convert to lowercase for consistency
        zodiac_sign = zodiac_mapping.get(zodiac_key, "Unknown")
        # Replace zodiac key with sign name in the modified part
        modified_part = modified_part.replace(zodiac_key, zodiac_sign)
        print(modified_part)
    parts = moon_row.split('[')

    moon_data_string = str(parts[0].strip())

    # Split the moon_data_string by line breaks
    moon_data_parts = moon_data_string.split('\n')
    
    # Replace the degree symbol with the appropriate suffix
    for part in moon_data_parts:
        
        numeric_part = ''.join(filter(str.isdigit, part))
         
        degrees_minutes = ''.join(filter(str.isdigit, part))
        
        if len(degrees_minutes) >= 4:  # Check if numeric part contains both degrees and minutes
            degrees = int(degrees_minutes[:-2])  # Extract degrees
            minutes = int(degrees_minutes[-2:])  # Extract minutes
            degrees += minutes / 60 
       
        print (degrees)
        print (previous_degrees)
        previous_degrees = degrees
    # Append the modified_part to modified_data
    modified_data.append(modified_part)

# Print the modified moon data
for entry in modified_data:
    print ()
    print(entry)
modified_data = []
previous_degrees = 0
zodiac_mapping = {'a': 'Aries', 'b': 'Taurus', 'c': 'Cancer', 'd': 'Gemini', 'e': 'Leo', 'f': 'Virgo', 'g': 'Libra', 'h': 'Scorpio', 'i': 'Sag', 'j': 'Capricorn', 'k': 'Aquarius', 'l': 'Pisces'}
subtraction_results = []

for row_index, row in enumerate(data):
    # Access the string element within the tuple
    moon_row = row[2]  # is also cell 3 - the moon
    print()
    print("Moon Row:", moon_row)
    
    # Reset modified_part for each moon row
    modified_part = moon_row
    
    zodiac_key_match = re.search(r'[a-zA-Z]', moon_row)
        
    if zodiac_key_match:
        zodiac_key = zodiac_key_match.group().lower()  # Convert to lowercase for consistency
        zodiac_sign = zodiac_mapping.get(zodiac_key, "Unknown")
        # Replace zodiac key with sign name in the modified part
        modified_part = modified_part.replace(zodiac_key, zodiac_sign)
        print(modified_part)
    parts = moon_row.split('[')

    moon_data_string = str(parts[0].strip())

    # Split the moon_data_string by line breaks
    moon_data_parts = moon_data_string.split('\n')
    
    # Replace the degree symbol with the appropriate suffix
    for part in moon_data_parts:
        
        numeric_part = ''.join(filter(str.isdigit, part))
         
        degrees_minutes = ''.join(filter(str.isdigit, part))
        sign_change_indices = []
        if len(degrees_minutes) >= 4:  # Check if numeric part contains both degrees and minutes
            degrees = int(degrees_minutes[:-2])  # Extract degrees
            minutes = int(degrees_minutes[-2:])  # Extract minutes
            degrees += minutes / 60 
       
            # Perform subtraction and store result in list
            subtraction_result = degrees - previous_degrees
            subtraction_results.append(subtraction_result)
            print (subtraction_results)
            print("this Subtraction result:", subtraction_result)


# 
        print (degrees)
        print (previous_degrees)
        previous_degrees = degrees
    # Append the modified_part to modified_data
    modified_data.append(modified_part)

# Print the modified moon data
for entry in modified_data:
    print ()
    print(entry)

# Print the list of subtraction results
print("\nSubtraction Results:", subtraction_results)
number_of_results = len(subtraction_results)
print("Number of results:", number_of_results)

rounded_results = []
for result in subtraction_results:
    abs_result = abs(result)
    if 12 <= abs_result <= 17:
        rounded_results.append(int(result))
    else:
        rounded_results.append(round(abs_result))

print("Rounded results:", rounded_results)


#rounded_results = ["X" if result == 12 else result for result in rounded_results]
#print("Modified rounded results:", rounded_results)
rounded_results = ['X' if result == 12 else 'Y' for result in rounded_results]
#print("Modified rounded results:", rounded_results)
#print("Modified rounded results:", [str(x).lower() for x in rounded_results])
print("\n".join(rounded_results))

# Calculate absolute values and round up
absolute_values = [abs(result) for result in subtraction_results]
rounded_values = [round(value) for value in absolute_values]

# Find values between 12 and 18
values_between_12_and_18 = [value for value in rounded_values if 12 <= value <= 18]

# Calculate average between 12 and 18:", average)

 
# Dictionary mapping astrological signs to their degree ranges
astrological_signs = {
    'Aries': (0, 30),
    'Taurus': (30, 60),
    'Gemini': (60, 90),
    'Cancer': (90, 120),
    'Leo': (120, 150),
    'Virgo': (150, 180),
    'Libra': (180, 210),
    'Scorpio': (210, 240),
    'Sagittarius': (240, 270),
    'Capricorn': (270, 300),
    'Aquarius': (300, 330),
    'Pisces': (330, 360)
}

# Get the last entry from the actual data
last_entry = modified_data[-1]
last_sign = "unknown"
last_degree = None
# Extract the degree value from the last entry
if '°' in last_entry:
    last_degree = None  # Mark as unknown
    current_sign = None  # Mark as unknown
elif last_entry.isalpha():  # If the last entry is a word (e.g., Libra)
    last_sign = last_entry
else:  # If the last entry is a combination of letters and numbers (e.g., 10Gemini44)
    last_sign = ''.join(filter(str.isalpha, last_entry))

# Find the appropriate astrological sign for the last entry
if last_degree is not None:
    for sign, (lower, upper) in astrological_signs.items():
        if lower <= last_degree < upper:
            current_sign = sign
            break
else:
    current_sign = last_sign

print(f"The initial sign is inferred as {current_sign}")


# List to store indices where sign change occurs
sign_change_indices = []
# Get the last entry from the actual data
last_entry = modified_data[-1]

# Loop through the data to calculate the subtraction results
for index in range(len(modified_data)):
    #part = [index]
   # print ("index",part)
    degrees_minutes = ''.join(filter(str.isdigit, part))
    
    # Check if numeric part contains both degrees and minutes
    if len(degrees_minutes) >= 4:
        # Extract degrees and minutes
        degrees = int(degrees_minutes[:-2])
        minutes = int(degrees_minutes[-2:])
        degrees += minutes / 60 
        
        # Calculate subtraction and store result in list
        
        #subtraction_result = degrees - previous_degrees
        #subtraction_results.append(subtraction_result)
        
        # Update previous_degrees for the next iteration
        previous_degrees = degrees
print("Display Subtraction result:", subtraction_results)
for index, value in enumerate(modified_data):
    print("Index:", index)

# Loop through the subtraction results to find sign change indices
for i in range(len(subtraction_results)):
    if subtraction_results[i] < 0:
        sign_change_indices.append(i)

print("Indices where sign change occurs:", sign_change_indices)

# Extract the degree value from the last entry
if '°' in last_entry:
    last_degree = None  # Mark as unknown
    current_sign = None  # Mark as unknown
elif last_entry.isalpha():  # If the last entry is a word (e.g., Libra)
    last_sign = last_entry
else:  # If the last entry is a combination of letters and numbers (e.g., 10Gemini44)
    last_sign = ''.join(filter(str.isalpha, last_entry))
    last_degree = int(''.join(filter(str.isdigit, last_entry.split('°')[0])))

# Find the appropriate astrological sign for the last entry
if last_degree is not None:
    for sign, (lower, upper) in astrological_signs.items():
        if lower <= last_degree < upper:
            current_sign = sign
            break
else:
    current_sign = last_sign

print(f"The initial sign is inferred as {current_sign}")

last_entry_number = modified_data.index(modified_data[-1])
print("Entry number of the last item:", last_entry_number)
# Append the last entry number to the sign change indices
sign_change_indices.append(last_entry_number)

# Assign the updated list to pattern_indices
pattern_indices = sign_change_indices

print("Indices pattern:", pattern_indices)


# List to store assigned signs
assigned_signs = []

pattern_indices = [index for index, value in enumerate(modified_data)]
print(pattern_indices)


#pattern_indices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
# Infer astrological signs based on pattern
for index in pattern_indices:
    # Extract the sign from the data
    sign_data = modified_data[index]
    sign_name = ''.join(filter(str.isalpha, sign_data))
    
    # Append the inferred sign
    assigned_signs.append(sign_name)

print("missingAssigned signs based on pattern:\n", assigned_signs)

# List to store indices where sign change occurs
sign_change_indices = []

# Identify sign change indices based on subtraction results
for i in range(len(subtraction_results)):
    if subtraction_results[i] < 0:
        sign_change_indices.append(i)

print("Indices where sign change occurs:", sign_change_indices)



zodiac_signs_order = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpio', 'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces']
matched_indices = []
sign_index = 0
zodiac_signs_missing = ['', '', 'Gemini', '', 'Leo', '', '', 'Virgo', '', 'Libra', '', 'Libra']
def find_previous_sign(sign_name):
    try:
        sign_index = zodiac_signs_order.index(sign_name)
        print (sign_name)
        
        if sign_index > 0:
            #previous_index = matched_indices.index(sign_index) - 1
            #if previous_index >= 0:
                #return zodiac_signs_order[matched_indices[previous_index]]
                
            print(sign_index, "over here:", zodiac_signs_order[sign_index])

    except ValueError: #pisces reset
        sign_index = zodiac_signs_order.index(sign_name)
        print(sign_index, "this:", zodiac_signs_order[sign_index-1])
    return sign

print(find_previous_sign('Aries'))     # Output: Cancer

#print(sign_index, ":", zodiac_signs_order[sign_index-1])
#print(find_previous_sign('Aquariu

print(sign_index, ":", zodiac_signs_order[sign_index-1])
#print(find_previous_sign('Aquariu

zodiac_signs_order = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpio', 'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces']
matched_indices = []

zodiac_signs_missing = ['', '', 'Gemini', '', 'Leo', '', '', 'Virgo', '', 'Libra', '', 'Libra']
#zodiac_signs_order = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpio', 'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces']
matched_indices = []
sign_index = 0
zodiac_signs_missing = ['', '', 'Gemini', '', 'Leo', '', '', 'Virgo', '', 'Libra', '', 'Libra']
def find_previous_sign(sign_name):
    try:
        sign_index = zodiac_signs_order.index(sign_name)
        print (sign_name)
        
        if sign_index > 0:

            print(sign_name, "over here:", zodiac_signs_order[sign_index])
            this_thing = zodiac_signs_order[sign_index - 1]
            print ("this_thing", this_thing)
            return zodiac_signs_order[sign_index - 1]  # Return the name of the previous sign

    except ValueError: #pisces reset
        sign_index = zodiac_signs_order.index(sign_name)
       
    return None

print(find_previous_sign('Gemini'))  # Output: Taurus
print(find_previous_sign('Leo')) 
print(find_previous_sign('Virgo'))  # Output: Taurus: Gemini
print(find_previous_sign('Libra'))   # Output: Leo

zodiac_signs_missing = ['', '', 'Gemini', '', 'Leo', '', '', 'Virgo', '', 'Libra', '', 'Libra']
matched_indices = [2, 4, 7, 9]
i = 0  # Initialize i as a global variable

def find_previous_sign(sign_name):
    global i  # Declare i as a global variable

    try:
        sign_index = zodiac_signs_order.index(sign_name)
       # print(sign_name)
        
        if sign_index > 0:
            #print(sign_name, "over here:", zodiac_signs_order[sign_index])
            this_thing = zodiac_signs_order[sign_index - 1]
            char = chr(ord('A') + i)  # Generate character 'A', 'B', 'C', 'D' corresponding to the indices 0, 1, 2, 3
            i += 1  # Increment i for the next iteration
            print("this_thing", char, this_thing)
    except ValueError:
        sign_index = zodiac_signs_order.index(sign_name)

    return sign_name
    
def find_previous_sign3(sign_name):
    global i  # Declare i as a global variable

    try:
        sign_index = zodiac_signs_order.index(sign_name)
       # print(sign_name)
        
        if sign_index > 0:
            #print(sign_name, "over here:", zodiac_signs_order[sign_index])
            this_thing = zodiac_signs_order[sign_index - 1]
            char = chr(ord('A') + i)  # Generate character 'A', 'B', 'C', 'D' corresponding to the indices 0, 1, 2, 3
            i += 1  # Increment i for the next iteration
            print("data append : this_thing", char, this_thing)
    except ValueError:
        sign_index = zodiac_signs_order.index(sign_name)

    return sign_name

data_set_one = []

def find_previous_sign2(sign_name):
    global i  # Declare i as a global variable
    global data_set_one
    #data_set_one = []  # Initialize an empty list to store the results

    try:
        sign_index = zodiac_signs_order.index(sign_name)
       # print(sign_name)
        
        if sign_index > 0:
            #print(sign_name, "over here:", zodiac_signs_order[sign_index])
            this_thing = zodiac_signs_order[sign_index - 1]
            char = chr(ord('A') + i)  # Generate character 'A', 'B', 'C', 'D' corresponding to the indices 0, 1, 2, 3
            i += 1  # Increment i for the next iteration
            result = "this_thing {} {}".format(char, this_thing)  # Format the result string
            #print("", result)
            
            data_set_one.append(result)  # Append the result to the list
            #print ('data_set_one', data_set_one) 
    except ValueError:
        sign_index = zodiac_signs_order.index(sign_name)
    
    return data_set_one  # Return the list containing the results

print()
print(find_previous_sign('Gemini'))  # Output: Taurus
print(find_previous_sign('Leo')) 
print(find_previous_sign('Virgo'))  # Output: Taurus: Gemini
print(find_previous_sign('Libra'))   # Output: Leo

sign_change_indices = [2, 4, 7, 9]
sign_change_count = len(sign_change_indices)

#print (sign_change_count)

data_set_one = []

def extract_zodiac_sign(data):
    zodiac_signs = []
    for item in data:
        match = re.search(r'[A-Za-z]+', item)  # Find alphabetical characters (zodiac signs)
        if match:
            zodiac_signs.append(match.group())
    return zodiac_signs

# Example usage:
#modified_data = ['15°27', '28°12', '10Gemini44', '23°03', '05Leo13', '17°15', '29°12', '11Virgo03', '22°52', '04Libra41', '16°31', '28Libra26']
zodiac_signs = extract_zodiac_sign(modified_data)

if index - 1 < len(zodiac_signs_missing):
   zodiac_signs_missing[index - 1] = 'here'

print(zodiac_signs_missing)
print ()
print ()
for i in range(sign_change_count):
    sign = zodiac_signs.pop(0) 
   # print (sign)
    
    #sign = zodiac_signs.pop(0)
    #print("Current sign:", sign)
    result = find_previous_sign2(sign)
    print ('data_set_one =', data_set_one) 
    for item in data_set_one:
        print(item)
  #  print("Result:", result)
    # Pop off the first element of the list
    #print('sign', find_previous_sign(sign))
    #pass
print (data_set_one)
zodiac_signs_missing = ['', '', 'Gemini', '', 'Leo', '', '', 'Virgo', '', 'Libra', '', 'Libra']
matched_indices = [2, 4, 7, 9]

for i, index in enumerate(matched_indices):
    if index - 1 < len(zodiac_signs_missing):
        char = chr(ord('A') + i)  # Assigning characters sequentially starting from 'A'
        zodiac_signs_missing[index - 1] = f'this_thing {char}{zodiac_signs_missing[index - 1]}'

print(zodiac_signs_missing)

# Data set two
data_set_two = [
    '',
    'this_thing A ',
    'Gemini',
    'this_thing B ',
    'Leo',
    '',
    'this_thing C ',
    'Virgo',
    'this_thing D ',
    'Libra',
    '',
    'Libra'
]

# Iterate through data_set_two
for i, string in enumerate(data_set_two):
    # Check if the string starts with 'this_thing'
    if string.startswith('this_thing'):
        # Extract the index from the string
        index = string.split()[1]
        # Find the corresponding string from data_set_one
        for item in data_set_one:
            if f'this_thing {index}' in item:
                # Replace the empty string with the found string
                data_set_two[i] = item.split(' ', 1)[1]
                break

print(data_set_two)

# Data set two

# Data set two
data_set_two = [
    '',
    'this_thing A ',
    'Gemini',
    'this_thing B ',
    'Leo',
    '',
    'this_thing C ',
    'Virgo',
    'this_thing D ',
    'Libra',
    '',
    'Libra'
]
# Iterate through data_set_two
for i, string in enumerate(data_set_two):
    # Check if the string starts with 'this_thing'
    if string.startswith('this_thing'):
        # Extract the index from the string
        index = string.split()[1]
        # Find the corresponding string from data_set_one
        for item in data_set_one:
            if f'this_thing {index}' in item:
                # Replace the empty string with the found string (remove the letter)
                data_set_two[i] = item.split(' ', 2)[2]  # Split by space and keep only the second part
                break

print(data_set_two)

# Iterate through data_set_two backwards
for i in range(len(data_set_two) - 1, -1, -1):
    # Check if the string is not empty
    if data_set_two[i]:
        # If it's a name, update the last_name
        last_name = re.search(r'[A-Z][a-z]*', data_set_two[i])
    elif last_name:
        # If it's empty and there's a last_name, fill it with the last_name
        data_set_two[i] = last_name.group()

print(data_set_two)



 
by

Python Online Compiler

Write, Run & Share Python code online using OneCompiler's Python online compiler for free. It's one of the robust, feature-rich online compilers for python language, supporting both the versions which are Python 3 and Python 2.7. Getting started with the OneCompiler's Python editor is easy and fast. The editor shows sample boilerplate code when you choose language as Python or Python2 and start coding.

Taking inputs (stdin)

OneCompiler's python online editor supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample python program which takes name as input and print your name with hello.

import sys
name = sys.stdin.readline()
print("Hello "+ name)

About Python

Python is a very popular general-purpose programming language which was created by Guido van Rossum, and released in 1991. It is very popular for web development and you can build almost anything like mobile apps, web apps, tools, data analytics, machine learning etc. It is designed to be simple and easy like english language. It's is highly productive and efficient making it a very popular language.

Tutorial & Syntax help

Loops

1. If-Else:

When ever you want to perform a set of operations based on a condition IF-ELSE is used.

if conditional-expression
    #code
elif conditional-expression
    #code
else:
    #code

Note:

Indentation is very important in Python, make sure the indentation is followed correctly

2. For:

For loop is used to iterate over arrays(list, tuple, set, dictionary) or strings.

Example:

mylist=("Iphone","Pixel","Samsung")
for i in mylist:
    print(i)

3. While:

While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.

while condition  
    #code 

Collections

There are four types of collections in Python.

1. List:

List is a collection which is ordered and can be changed. Lists are specified in square brackets.

Example:

mylist=["iPhone","Pixel","Samsung"]
print(mylist)

2. Tuple:

Tuple is a collection which is ordered and can not be changed. Tuples are specified in round brackets.

Example:

myTuple=("iPhone","Pixel","Samsung")
print(myTuple)

Below throws an error if you assign another value to tuple again.

myTuple=("iPhone","Pixel","Samsung")
print(myTuple)
myTuple[1]="onePlus"
print(myTuple)

3. Set:

Set is a collection which is unordered and unindexed. Sets are specified in curly brackets.

Example:

myset = {"iPhone","Pixel","Samsung"}
print(myset)

4. Dictionary:

Dictionary is a collection of key value pairs which is unordered, can be changed, and indexed. They are written in curly brackets with key - value pairs.

Example:

mydict = {
    "brand" :"iPhone",
    "model": "iPhone 11"
}
print(mydict)

Supported Libraries

Following are the libraries supported by OneCompiler's Python compiler

NameDescription
NumPyNumPy python library helps users to work on arrays with ease
SciPySciPy is a scientific computation library which depends on NumPy for convenient and fast N-dimensional array manipulation
SKLearn/Scikit-learnScikit-learn or Scikit-learn is the most useful library for machine learning in Python
PandasPandas is the most efficient Python library for data manipulation and analysis
DOcplexDOcplex is IBM Decision Optimization CPLEX Modeling for Python, is a library composed of Mathematical Programming Modeling and Constraint Programming Modeling