Skip to content

Algorithm for transforming one string into another in the most cost-efficient way #273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Project Euler/Problem 22/p022_names.txt

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions Project Euler/Problem 22/sol1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: latin-1 -*-
from __future__ import print_function
'''
Name scores
Problem 22

Using names.txt (right click and 'Save Link/Target As...'), a 46K text file containing over five-thousand first names, begin by sorting it
into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list
to obtain a name score.

For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list.
So, COLIN would obtain a score of 938 × 53 = 49714.

What is the total of all the name scores in the file?
'''
try:
xrange #Python 2
except NameError:
xrange = range #Python 3

with open('p022_names.txt') as file:
names = str(file.readlines()[0])
names = names.replace('"', '').split(',')

names.sort()

name_score = 0
total_score = 0

for i, name in enumerate(names):
for letter in name:
name_score += ord(letter) - 64

total_score += (i+1)*name_score
name_score = 0

print(total_score)
123 changes: 123 additions & 0 deletions strings/min-cost-string-conversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
from __future__ import print_function

try:
xrange #Python 2
except NameError:
xrange = range #Python 3

'''
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 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')

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))
file.close()