Advertisement
Guest User

Untitled

a guest
Nov 23rd, 2018
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.48 KB | None | 0 0
  1. #!/usr/bin/env python2.7
  2. # -*- coding: utf-8 -*-
  3. '''
  4. Assignment 2: Search String Replacement
  5.  
  6. Team Number:
  7. Student Names:
  8. '''
  9. import unittest
  10. # Sample matrix provided by us:
  11. from collections import defaultdict
  12. from string import ascii_lowercase
  13.  
  14. def equalizeStrings(u, r):
  15. if len(u) == len(r):
  16. return u, r
  17. elif len(u) > len(r):
  18. for i in range(0, abs(len(u)-len(r))):
  19. r = r + '-'
  20. else:
  21. for i in range(0, abs(len(u)-len(r))):
  22. u = u + '-'
  23. while r.endswith('-') and u.endswith('-'):
  24. r = r[:-1]
  25. u = u[:-1]
  26. return u, r
  27.  
  28. def swap(s, i, j):
  29. lst = list(s)
  30. lst[i], lst[j] = lst[j], lst[i]
  31. return ''.join(lst)
  32.  
  33. def reorderString(u, r):
  34. for i in range(0, len(u)-1):
  35. if u[i] in r and u[i] != r[i]:
  36. if u[i+1] == '-' and u[i] in r[i:]:
  37. u = swap(u, i, i+1)
  38. elif u[i] == r[i+1]:
  39. u = u[:i] + '-'+ u[i:]
  40. return u
  41.  
  42.  
  43.  
  44. # Solution to part b:
  45. def min_difference(u, r, R):
  46. """
  47. Sig: string, string, int[0..|A|, 0..|A|] ==> int
  48. Pre:
  49. Post:
  50. Example: Let R be the resemblance matrix where every change and skip costs 1
  51. min_difference("dinamck","dynamic",R) ==> 3
  52. """
  53. # To get the resemblance between two letters, use code like this:
  54. # difference = R['a']['b']
  55. u, r = equalizeStrings(u, r)
  56.  
  57. u = reorderString(u, r)
  58.  
  59. u, r = equalizeStrings(u, r)
  60.  
  61. # Initialize the matrix
  62. matrix = [[None for i in range(len(r) + 1)] for j in range(len(u) + 1)]
  63.  
  64. for i in range(len(r) + 1):
  65. matrix[0][i] = i
  66. for i in range(len(u) + 1):
  67. matrix[i][0] = i
  68. for y in range(1,len(u)+1):
  69. for x in range(1,len(r)+1):
  70.  
  71. if y == x and u[y-1] == r[x-1]:
  72. matrix[y][y] = matrix[y-1][y-1]
  73. else:
  74. surrounding = []
  75. surrounding.append(matrix[x][y-1])
  76. surrounding.append(matrix[x-1][y])
  77. surrounding.append(matrix[x-1][y-1])
  78.  
  79. if min(surrounding) == matrix[x-1][y-1]:
  80. matrix[x][y] = min(surrounding) + R[r[x-1]][u[y-1]]
  81. else:
  82. matrix[x][y] = min(surrounding) + R[r[x - 1]]['-']
  83.  
  84. return matrix[len(r)][len(u)]
  85.  
  86.  
  87. # Solution to part c:
  88. def min_difference_align(u, r, R):
  89. """
  90. Sig: string, string, int[0..|A|, 0..|A|] ==> int, string, string
  91. Pre:
  92. Post:
  93. Example: Let R be the resemblance matrix where every change and skip costs 1
  94. min_difference_align("dinamck","dynamic",R) ==>
  95. 3, "dinam-ck", "dynamic-"
  96. """
  97. matrix = [[None for i in range(len(r) + 1)] for j in range(len(u) + 1)]
  98.  
  99. for i in range(len(r) + 1):
  100. matrix[0][i] = i
  101. for i in range(len(u) + 1):
  102. matrix[i][0] = i
  103. for y in range(1,len(u)+1):
  104. for x in range(1,len(r)+1):
  105. if y == x and u[y-1] == r[x-1]:
  106. matrix[y][y] = matrix[y-1][y-1]
  107.  
  108. else:
  109. surrounding = []
  110. surrounding.append(matrix[x][y-1])
  111. surrounding.append(matrix[x-1][y])
  112. surrounding.append(matrix[x-1][y-1])
  113.  
  114. matrix[x][y] = min(surrounding) + 1
  115.  
  116. return matrix[len(r)][len(u)]
  117.  
  118.  
  119. def qwerty_distance():
  120. """Generates a QWERTY Manhattan distance resemblance matrix
  121.  
  122. Costs for letter pairs are based on the Manhattan distance of the
  123. corresponding keys on a standard QWERTY keyboard.
  124. Costs for skipping a character depends on its placement on the keyboard:
  125. adding a character has a higher cost for keys on the outer edges,
  126. deleting a character has a higher cost for keys near the middle.
  127.  
  128. Usage:
  129. R = qwerty_distance()
  130. R['a']['b'] # result: 5
  131. """
  132. from collections import defaultdict
  133. import math
  134. R = defaultdict(dict)
  135. R['-']['-'] = 0
  136. zones = ["dfghjk", "ertyuislcvbnm", "qwazxpo"]
  137. keyboard = ["qwertyuiop", "asdfghjkl", "zxcvbnm"]
  138. for num, content in enumerate(zones):
  139. for char in content:
  140. R['-'][char] = num + 1
  141. R[char]['-'] = 3 - num
  142. for a in ascii_lowercase:
  143. rowA = None
  144. posA = None
  145. for num, content in enumerate(keyboard):
  146. if a in content:
  147. rowA = num
  148. posA = content.index(a)
  149. for b in ascii_lowercase:
  150. for rowB, contentB in enumerate(keyboard):
  151. if b in contentB:
  152. R[a][b] = int(math.fabs(rowB - rowA) + math.fabs(posA - contentB.index(b)))
  153. return R
  154.  
  155.  
  156. # class MinDifferenceTest(unittest.TestCase):
  157. # """Test Suite for search string replacement problem
  158. #
  159. # Any method named "test_something" will be run when this file is
  160. # executed. Use the sanity check as a template for adding your own test
  161. # cases if you wish.
  162. # (You may delete this class from your submitted solution.)
  163. # """
  164. #
  165. # def test_diff_sanity(self):
  166. # """Difference sanity test
  167. #
  168. # Given a simple resemblance matrix, test that the reported
  169. # difference is the expected minimum. Do NOT assume we will always
  170. # use this resemblance matrix when testing!
  171. # """
  172. # alphabet = ascii_lowercase + '-'
  173. # # The simplest (reasonable) resemblance matrix:
  174. # R = dict([(
  175. # a,
  176. # dict([(b, (0 if a == b else 1)) for b in alphabet])
  177. # ) for a in alphabet])
  178. # # Warning: we may (read: 'will') use another matrix!
  179. # self.assertEqual(min_difference("dinamck", "dynamic", R), 3)
  180. #
  181. # def test_align_sanity(self):
  182. # """Simple alignment
  183. #
  184. # Passes if the returned alignment matches the expected one.
  185. # """
  186. # # QWERTY resemblance matrix:
  187. # R = qwerty_distance()
  188. # diff, u, r = min_difference_align("polynomial", "exponential", R)
  189. # # Warning: we may (read: 'will') use another matrix!
  190. # self.assertEqual(diff, 15)
  191. # # Warning: there may be other optimal matchings!
  192. # self.assertEqual(u, '--polyn-om-ial')
  193. # self.assertEqual(r, 'exp-o-ne-ntial')
  194.  
  195.  
  196. if __name__ == '__main__':
  197. R = defaultdict(type('dict'), {
  198. '-': {'-': 0, 'a': 3, 'c': 2, 'b': 2, 'e': 2, 'd': 1, 'g': 1, 'f': 1, 'i': 2, 'h': 1, 'k': 1, 'j': 1, 'm': 2,
  199. 'l': 2, 'o': 3, 'n': 2, 'q': 3, 'p': 3, 's': 2, 'r': 2, 'u': 2, 't': 2, 'w': 3, 'v': 2, 'y': 2, 'x': 3,
  200. 'z': 3},
  201. 'a': {'-': 1, 'a': 0, 'c': 3, 'b': 5, 'e': 3, 'd': 2, 'g': 4, 'f': 3, 'i': 8, 'h': 5, 'k': 7, 'j': 6, 'm': 7,
  202. 'l': 8, 'o': 9, 'n': 6, 'q': 1, 'p': 10, 's': 1, 'r': 4, 'u': 7, 't': 5, 'w': 2, 'v': 4, 'y': 6, 'x': 2,
  203. 'z': 1},
  204. 'c': {'-': 2, 'a': 3, 'c': 0, 'b': 2, 'e': 2, 'd': 1, 'g': 3, 'f': 2, 'i': 7, 'h': 4, 'k': 6, 'j': 5, 'm': 4,
  205. 'l': 7, 'o': 8, 'n': 3, 'q': 4, 'p': 9, 's': 2, 'r': 3, 'u': 6, 't': 4, 'w': 3, 'v': 1, 'y': 5, 'x': 1,
  206. 'z': 2},
  207. 'b': {'-': 2, 'a': 5, 'c': 2, 'b': 0, 'e': 4, 'd': 3, 'g': 1, 'f': 2, 'i': 5, 'h': 2, 'k': 4, 'j': 3, 'm': 2,
  208. 'l': 5, 'o': 6, 'n': 1, 'q': 6, 'p': 7, 's': 4, 'r': 3, 'u': 4, 't': 2, 'w': 5, 'v': 1, 'y': 3, 'x': 3,
  209. 'z': 4},
  210. 'e': {'-': 2, 'a': 3, 'c': 2, 'b': 4, 'e': 0, 'd': 1, 'g': 3, 'f': 2, 'i': 5, 'h': 4, 'k': 6, 'j': 5, 'm': 6,
  211. 'l': 7, 'o': 6, 'n': 5, 'q': 2, 'p': 7, 's': 2, 'r': 1, 'u': 4, 't': 2, 'w': 1, 'v': 3, 'y': 3, 'x': 3,
  212. 'z': 4},
  213. 'd': {'-': 3, 'a': 2, 'c': 1, 'b': 3, 'e': 1, 'd': 0, 'g': 2, 'f': 1, 'i': 6, 'h': 3, 'k': 5, 'j': 4, 'm': 5,
  214. 'l': 6, 'o': 7, 'n': 4, 'q': 3, 'p': 8, 's': 1, 'r': 2, 'u': 5, 't': 3, 'w': 2, 'v': 2, 'y': 4, 'x': 2,
  215. 'z': 3},
  216. 'g': {'-': 3, 'a': 4, 'c': 3, 'b': 1, 'e': 3, 'd': 2, 'g': 0, 'f': 1, 'i': 4, 'h': 1, 'k': 3, 'j': 2, 'm': 3,
  217. 'l': 4, 'o': 5, 'n': 2, 'q': 5, 'p': 6, 's': 3, 'r': 2, 'u': 3, 't': 1, 'w': 4, 'v': 2, 'y': 2, 'x': 4,
  218. 'z': 5},
  219. 'f': {'-': 3, 'a': 3, 'c': 2, 'b': 2, 'e': 2, 'd': 1, 'g': 1, 'f': 0, 'i': 5, 'h': 2, 'k': 4, 'j': 3, 'm': 4,
  220. 'l': 5, 'o': 6, 'n': 3, 'q': 4, 'p': 7, 's': 2, 'r': 1, 'u': 4, 't': 2, 'w': 3, 'v': 1, 'y': 3, 'x': 3,
  221. 'z': 4},
  222. 'i': {'-': 2, 'a': 8, 'c': 7, 'b': 5, 'e': 5, 'd': 6, 'g': 4, 'f': 5, 'i': 0, 'h': 3, 'k': 1, 'j': 2, 'm': 3,
  223. 'l': 2, 'o': 1, 'n': 4, 'q': 7, 'p': 2, 's': 7, 'r': 4, 'u': 1, 't': 3, 'w': 6, 'v': 6, 'y': 2, 'x': 8,
  224. 'z': 9},
  225. 'h': {'-': 3, 'a': 5, 'c': 4, 'b': 2, 'e': 4, 'd': 3, 'g': 1, 'f': 2, 'i': 3, 'h': 0, 'k': 2, 'j': 1, 'm': 2,
  226. 'l': 3, 'o': 4, 'n': 1, 'q': 6, 'p': 5, 's': 4, 'r': 3, 'u': 2, 't': 2, 'w': 5, 'v': 3, 'y': 1, 'x': 5,
  227. 'z': 6},
  228. 'k': {'-': 3, 'a': 7, 'c': 6, 'b': 4, 'e': 6, 'd': 5, 'g': 3, 'f': 4, 'i': 1, 'h': 2, 'k': 0, 'j': 1, 'm': 2,
  229. 'l': 1, 'o': 2, 'n': 3, 'q': 8, 'p': 3, 's': 6, 'r': 5, 'u': 2, 't': 4, 'w': 7, 'v': 5, 'y': 3, 'x': 7,
  230. 'z': 8},
  231. 'j': {'-': 3, 'a': 6, 'c': 5, 'b': 3, 'e': 5, 'd': 4, 'g': 2, 'f': 3, 'i': 2, 'h': 1, 'k': 1, 'j': 0, 'm': 1,
  232. 'l': 2, 'o': 3, 'n': 2, 'q': 7, 'p': 4, 's': 5, 'r': 4, 'u': 1, 't': 3, 'w': 6, 'v': 4, 'y': 2, 'x': 6,
  233. 'z': 7},
  234. 'm': {'-': 2, 'a': 7, 'c': 4, 'b': 2, 'e': 6, 'd': 5, 'g': 3, 'f': 4, 'i': 3, 'h': 2, 'k': 2, 'j': 1, 'm': 0,
  235. 'l': 3, 'o': 4, 'n': 1, 'q': 8, 'p': 5, 's': 6, 'r': 5, 'u': 2, 't': 4, 'w': 7, 'v': 3, 'y': 3, 'x': 5,
  236. 'z': 6},
  237. 'l': {'-': 2, 'a': 8, 'c': 7, 'b': 5, 'e': 7, 'd': 6, 'g': 4, 'f': 5, 'i': 2, 'h': 3, 'k': 1, 'j': 2, 'm': 3,
  238. 'l': 0, 'o': 1, 'n': 4, 'q': 9, 'p': 2, 's': 7, 'r': 6, 'u': 3, 't': 5, 'w': 8, 'v': 6, 'y': 4, 'x': 8,
  239. 'z': 9},
  240. 'o': {'-': 1, 'a': 9, 'c': 8, 'b': 6, 'e': 6, 'd': 7, 'g': 5, 'f': 6, 'i': 1, 'h': 4, 'k': 2, 'j': 3, 'm': 4,
  241. 'l': 1, 'o': 0, 'n': 5, 'q': 8, 'p': 1, 's': 8, 'r': 5, 'u': 2, 't': 4, 'w': 7, 'v': 7, 'y': 3, 'x': 9,
  242. 'z': 10},
  243. 'n': {'-': 2, 'a': 6, 'c': 3, 'b': 1, 'e': 5, 'd': 4, 'g': 2, 'f': 3, 'i': 4, 'h': 1, 'k': 3, 'j': 2, 'm': 1,
  244. 'l': 4, 'o': 5, 'n': 0, 'q': 7, 'p': 6, 's': 5, 'r': 4, 'u': 3, 't': 3, 'w': 6, 'v': 2, 'y': 2, 'x': 4,
  245. 'z': 5},
  246. 'q': {'-': 1, 'a': 1, 'c': 4, 'b': 6, 'e': 2, 'd': 3, 'g': 5, 'f': 4, 'i': 7, 'h': 6, 'k': 8, 'j': 7, 'm': 8,
  247. 'l': 9, 'o': 8, 'n': 7, 'q': 0, 'p': 9, 's': 2, 'r': 3, 'u': 6, 't': 4, 'w': 1, 'v': 5, 'y': 5, 'x': 3,
  248. 'z': 2},
  249. 'p': {'-': 1, 'a': 10, 'c': 9, 'b': 7, 'e': 7, 'd': 8, 'g': 6, 'f': 7, 'i': 2, 'h': 5, 'k': 3, 'j': 4, 'm': 5,
  250. 'l': 2, 'o': 1, 'n': 6, 'q': 9, 'p': 0, 's': 9, 'r': 6, 'u': 3, 't': 5, 'w': 8, 'v': 8, 'y': 4, 'x': 10,
  251. 'z': 11},
  252. 's': {'-': 2, 'a': 1, 'c': 2, 'b': 4, 'e': 2, 'd': 1, 'g': 3, 'f': 2, 'i': 7, 'h': 4, 'k': 6, 'j': 5, 'm': 6,
  253. 'l': 7, 'o': 8, 'n': 5, 'q': 2, 'p': 9, 's': 0, 'r': 3, 'u': 6, 't': 4, 'w': 1, 'v': 3, 'y': 5, 'x': 1,
  254. 'z': 2},
  255. 'r': {'-': 2, 'a': 4, 'c': 3, 'b': 3, 'e': 1, 'd': 2, 'g': 2, 'f': 1, 'i': 4, 'h': 3, 'k': 5, 'j': 4, 'm': 5,
  256. 'l': 6, 'o': 5, 'n': 4, 'q': 3, 'p': 6, 's': 3, 'r': 0, 'u': 3, 't': 1, 'w': 2, 'v': 2, 'y': 2, 'x': 4,
  257. 'z': 5},
  258. 'u': {'-': 2, 'a': 7, 'c': 6, 'b': 4, 'e': 4, 'd': 5, 'g': 3, 'f': 4, 'i': 1, 'h': 2, 'k': 2, 'j': 1, 'm': 2,
  259. 'l': 3, 'o': 2, 'n': 3, 'q': 6, 'p': 3, 's': 6, 'r': 3, 'u': 0, 't': 2, 'w': 5, 'v': 5, 'y': 1, 'x': 7,
  260. 'z': 8},
  261. 't': {'-': 2, 'a': 5, 'c': 4, 'b': 2, 'e': 2, 'd': 3, 'g': 1, 'f': 2, 'i': 3, 'h': 2, 'k': 4, 'j': 3, 'm': 4,
  262. 'l': 5, 'o': 4, 'n': 3, 'q': 4, 'p': 5, 's': 4, 'r': 1, 'u': 2, 't': 0, 'w': 3, 'v': 3, 'y': 1, 'x': 5,
  263. 'z': 6},
  264. 'w': {'-': 1, 'a': 2, 'c': 3, 'b': 5, 'e': 1, 'd': 2, 'g': 4, 'f': 3, 'i': 6, 'h': 5, 'k': 7, 'j': 6, 'm': 7,
  265. 'l': 8, 'o': 7, 'n': 6, 'q': 1, 'p': 8, 's': 1, 'r': 2, 'u': 5, 't': 3, 'w': 0, 'v': 4, 'y': 4, 'x': 2,
  266. 'z': 3},
  267. 'v': {'-': 2, 'a': 4, 'c': 1, 'b': 1, 'e': 3, 'd': 2, 'g': 2, 'f': 1, 'i': 6, 'h': 3, 'k': 5, 'j': 4, 'm': 3,
  268. 'l': 6, 'o': 7, 'n': 2, 'q': 5, 'p': 8, 's': 3, 'r': 2, 'u': 5, 't': 3, 'w': 4, 'v': 0, 'y': 4, 'x': 2,
  269. 'z': 3},
  270. 'y': {'-': 2, 'a': 6, 'c': 5, 'b': 3, 'e': 3, 'd': 4, 'g': 2, 'f': 3, 'i': 2, 'h': 1, 'k': 3, 'j': 2, 'm': 3,
  271. 'l': 4, 'o': 3, 'n': 2, 'q': 5, 'p': 4, 's': 5, 'r': 2, 'u': 1, 't': 1, 'w': 4, 'v': 4, 'y': 0, 'x': 6,
  272. 'z': 7},
  273. 'x': {'-': 1, 'a': 2, 'c': 1, 'b': 3, 'e': 3, 'd': 2, 'g': 4, 'f': 3, 'i': 8, 'h': 5, 'k': 7, 'j': 6, 'm': 5,
  274. 'l': 8, 'o': 9, 'n': 4, 'q': 3, 'p': 10, 's': 1, 'r': 4, 'u': 7, 't': 5, 'w': 2, 'v': 2, 'y': 6, 'x': 0,
  275. 'z': 1},
  276. 'z': {'-': 1, 'a': 1, 'c': 2, 'b': 4, 'e': 4, 'd': 3, 'g': 5, 'f': 4, 'i': 9, 'h': 6, 'k': 8, 'j': 7, 'm': 6,
  277. 'l': 9, 'o': 10, 'n': 5, 'q': 2, 'p': 11, 's': 2, 'r': 5, 'u': 8, 't': 6, 'w': 3, 'v': 3, 'y': 7, 'x': 1,
  278. 'z': 0}})
  279. print(min_difference('flhvmowi', 'kszavmqboyhcf', R))
  280. # alphabet = ascii_lowercase + '-'
  281. # R = dict([(
  282. # a,
  283. # dict([(b, (0 if a == b else 1)) for b in alphabet])
  284. # ) for a in alphabet])
  285. # print(min_difference("dina", "dynamic", R))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement