import difflib


def num_of_part1(digit):
    num_in = False
    if len(digit) == 2:
        num_in = True
    elif len(digit) == 3:
        num_in = True
    elif len(digit) == 4:
        num_in = True
    elif len(digit) == 7:
        num_in = True
    return num_in


def get_unique_number(number_str):
    num_in = -1
    if len(number_str) == 2:
        num_in = 1
    elif len(number_str) == 3:
        num_in = 7
    elif len(number_str) == 4:
        num_in = 4
    elif len(number_str) == 7:
        num_in = 8
    return num_in


def check_number2(number_str, char_table):
    ret = False
    number_ref_str = char_table[4]
    output_list = [li for li in difflib.ndiff(
        number_str, number_ref_str) if li[0] != ' ']
    if len(output_list) == 5:
        ret = True
    return ret


def check_number3(number_str, char_table):
    ret = False
    number_ref_str = char_table[7]
    output_list = [li for li in difflib.ndiff(
        number_str, number_ref_str) if li[0] != ' ']
    if len(output_list) == 2:
        ret = True
    return ret


def check_number5(number_str, char_table):
    ret = False
    number_ref_str = char_table[4]
    output_list = [li for li in difflib.ndiff(
        number_str, number_ref_str) if li[0] != ' ']
    if len(output_list) == 3:
        ret = True
    return ret


def check_number9(number_str, char_table):
    ret = False
    number_ref_str = char_table[4]
    output_list = [li for li in difflib.ndiff(
        number_str, number_ref_str) if li[0] != ' ']
    if len(output_list) == 2:
        ret = True
    return ret


def check_number0(number_str, char_table):
    ret = False
    number_ref_str = char_table[1]
    output_list = [li for li in difflib.ndiff(
        number_str, number_ref_str) if li[0] != ' ']
    if len(output_list) == 4:
        ret = True
    return ret


def check_number6(number_str, char_table):
    ret = False
    number_ref_str = char_table[1]
    output_list = [li for li in difflib.ndiff(
        number_str, number_ref_str) if li[0] != ' ']
    if len(output_list) == 6:
        ret = True
    return ret


def get_key(val, my_dict):
    for key, value in my_dict.items():
        if val == value:
            return key
    print("Error, not in dict")


def main():
    # Get file in lines and convert to int
    with open("input.txt", "r", encoding="utf-8") as file:
        # strip out the new line
        puzzle_lines = [line.rstrip('\n') for line in file]
        puzzle_line_arr = [line.split() for line in puzzle_lines]

    # Part 1 calculation
    count_nums = 0
    for i, line in enumerate(puzzle_line_arr):
        # extract digtits from rear
        digits = line[-4:]
        for digit in digits:
            num_in = num_of_part1(digit)
            count_nums += 1 if num_in else 0

    # Part 1
    result_p1 = count_nums
    # Output
    print("Part1: " + str(result_p1))

    # Part 2 check which number is which pattern
    char_table = {}  # my dict with sorted characters
    overall_sum = 0  # overall sum of each line

    for i, line in enumerate(puzzle_line_arr):
        # For each line new dictionary required
        char_table.clear()
        # Extract numbers 0 to 9 and sort them
        numbers_str = [''.join(sorted(num)) for num in line[0:10]]
        # check all numbers for the uniqe one
        for number_str in numbers_str:
            number_found = get_unique_number(number_str)
            if number_found != -1:
                char_table[number_found] = number_str
        # Check for 3 and skip existing patterns in value
        for number_str in numbers_str:
            if number_str in char_table.values():
                continue
            if len(number_str) == 5:
                if check_number3(number_str, char_table):
                    char_table[3] = number_str
        # Check 2 and 5 and skip existing patterns in value
        for number_str in numbers_str:
            if number_str in char_table.values():
                continue
            if len(number_str) == 5:
                if check_number2(number_str, char_table):
                    char_table[2] = number_str
                if check_number5(number_str, char_table):
                    char_table[5] = number_str
        # Check for 9 and skip existing patterns in value
        for number_str in numbers_str:
            if number_str in char_table.values():
                continue
            if len(number_str) == 6:
                if check_number9(number_str, char_table):
                    char_table[9] = number_str
        # Check for last group 0 and 6 and skip existing patterns in value
        for number_str in numbers_str:
            if number_str in char_table.values():
                continue
            if len(number_str) == 6:
                if check_number0(number_str, char_table):
                    char_table[0] = number_str
                if check_number6(number_str, char_table):
                    char_table[6] = number_str
        # print(char_table)        
        nums = []
        # extract digtits from rear
        digits = [''.join(sorted(num)) for num in line[-4:]]
        for digit in digits:
            digit_srt = ''.join(sorted(digit))
            nums.append(get_key(digit_srt, char_table))
        number_line = int(''.join(str(num) for num in nums))
        # print(number_line)
        overall_sum += number_line

    # Part 2
    result_p2 = overall_sum
    # Output
    print("Part2: " + str(result_p2))


if __name__ == "__main__":
    main()
