From a753acf1deddf28bb6a83a77a60dc8597398f67d Mon Sep 17 00:00:00 2001 From: Daniel Ingram Date: Tue, 20 Mar 2018 15:23:09 -0400 Subject: [PATCH] Computes minimum cost for converting one string into another --- strings/min-cost-string-conversion.py | 124 ++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 strings/min-cost-string-conversion.py diff --git a/strings/min-cost-string-conversion.py b/strings/min-cost-string-conversion.py new file mode 100644 index 000000000..1798e81cd --- /dev/null +++ b/strings/min-cost-string-conversion.py @@ -0,0 +1,124 @@ +from __future__ import print_function + +try: + xrange #Python 2 +except NameError: + xrange = range #Python 3 + +def compute_transform_tables(X, Y, cC, cR, cD, cI): +''' +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 +''' + X = list(X) + Y = list(Y) + m = len(X) + n = len(Y) + + costs = [[0 for _ in xrange(n+1)] for _ in xrange(m+1)] + ops = [[0 for _ in xrange(n+1)] for _ in xrange(m+1)] + + for i in xrange(1, m+1): + costs[i][0] = i*cD + ops[i][0] = 'D%c' % X[i-1] + + for i in xrange(1, n+1): + costs[0][i] = i*cI + ops[0][i] = 'I%c' % Y[i-1] + + for i in xrange(1, m+1): + for j in xrange(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__': + from time import sleep + _, 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) + + file = open('min_cost.txt', 'w') + + string = list('Python') + i = 0 + cost = 0 + 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') + + i += 1 + 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') + + i += 1 + 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') + + i += 1 + 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') + + i += 1 + cost += 2 + + print ''.join(string) + print 'Cost: ', cost + + file.write('\r\nMinimum cost: ' + str(cost)) + file.close() \ No newline at end of file