"""
Algorithm for calculating the most cost-efficient sequence for converting one string
into another.
The only allowed operations are
---Copy character with cost cC
---Replace character with cost cR
---Delete character with cost cD
---Insert character with cost cI
"""


def compute_transform_tables(X, Y, cC, cR, cD, cI):
    X = list(X)
    Y = list(Y)
    m = len(X)
    n = len(Y)

    costs = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
    ops = [[0 for _ in range(n + 1)] for _ in range(m + 1)]

    for i in range(1, m + 1):
        costs[i][0] = i * cD
        ops[i][0] = "D%c" % X[i - 1]

    for i in range(1, n + 1):
        costs[0][i] = i * cI
        ops[0][i] = "I%c" % Y[i - 1]

    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if X[i - 1] == Y[j - 1]:
                costs[i][j] = costs[i - 1][j - 1] + cC
                ops[i][j] = "C%c" % X[i - 1]
            else:
                costs[i][j] = costs[i - 1][j - 1] + cR
                ops[i][j] = "R%c" % X[i - 1] + str(Y[j - 1])

            if costs[i - 1][j] + cD < costs[i][j]:
                costs[i][j] = costs[i - 1][j] + cD
                ops[i][j] = "D%c" % X[i - 1]

            if costs[i][j - 1] + cI < costs[i][j]:
                costs[i][j] = costs[i][j - 1] + cI
                ops[i][j] = "I%c" % Y[j - 1]

    return costs, ops


def assemble_transformation(ops, i, j):
    if i == 0 and j == 0:
        seq = []
        return seq
    else:
        if ops[i][j][0] == "C" or ops[i][j][0] == "R":
            seq = assemble_transformation(ops, i - 1, j - 1)
            seq.append(ops[i][j])
            return seq
        elif ops[i][j][0] == "D":
            seq = assemble_transformation(ops, i - 1, j)
            seq.append(ops[i][j])
            return seq
        else:
            seq = assemble_transformation(ops, i, j - 1)
            seq.append(ops[i][j])
            return seq


if __name__ == "__main__":
    _, operations = compute_transform_tables("Python", "Algorithms", -1, 1, 2, 2)

    m = len(operations)
    n = len(operations[0])
    sequence = assemble_transformation(operations, m - 1, n - 1)

    string = list("Python")
    i = 0
    cost = 0

    with open("min_cost.txt", "w") as file:
        for op in sequence:
            print("".join(string))

            if op[0] == "C":
                file.write("%-16s" % "Copy %c" % op[1])
                file.write("\t\t\t" + "".join(string))
                file.write("\r\n")

                cost -= 1
            elif op[0] == "R":
                string[i] = op[2]

                file.write("%-16s" % ("Replace %c" % op[1] + " with " + str(op[2])))
                file.write("\t\t" + "".join(string))
                file.write("\r\n")

                cost += 1
            elif op[0] == "D":
                string.pop(i)

                file.write("%-16s" % "Delete %c" % op[1])
                file.write("\t\t\t" + "".join(string))
                file.write("\r\n")

                cost += 2
            else:
                string.insert(i, op[1])

                file.write("%-16s" % "Insert %c" % op[1])
                file.write("\t\t\t" + "".join(string))
                file.write("\r\n")

                cost += 2

            i += 1

        print("".join(string))
        print("Cost: ", cost)

        file.write("\r\nMinimum cost: " + str(cost))