Comments (8)
Note:
This dynamic merge sort algorithm saves results for a partial list of an input list if the partial list itself was used as an input in the recursive part of the algorithm. For example, after having ordered [9, 6, 8, 7, 0], the result for the partial list [8, 7, 0] can be retrieved from the dictionary. However, the partial list [6, 8, 7] is not stored in the dictionary and has to be ordered itself. The difference is that the latter was never used as an input of the recursive merge_sort_dp(). Whereas the first partial list was used as an input.
+++ Dynamic Merge Sort with Test Cases +++
# Test Function
def test_merge_sort_dp(input_list, expected):
return expected == merge_sort_dp(input_list)
# Merge Algorithm
def merge_dp(left_list, right_list):
left = left_list.copy()
right = right_list.copy()
result = list()
while len(left) > 0 and len(right) > 0:
left_item = left[0]
right_item = right[0]
if left_item < right_item:
result.append(left_item)
left.remove(left_item)
else:
result.append(right_item)
right.remove(right_item)
result.extend(left)
result.extend(right)
return result
# Merge Sort Algorithm
def merge_sort_dp(input_list, d=dict()):
input_list_len = len(input_list)
key = ''.join(map(str, input_list))
if key not in d:
if len(input_list) <= 1:
d[key] = input_list
else:
mid = input_list_len // 2
left = merge_sort_dp(input_list[0:mid])
right = merge_sort_dp(input_list[mid:input_list_len])
d[key] = merge_dp(left, right)
return d[key]
# Test Cases
print(test_merge_sort_dp([3,4,1,5,2,9,6,8,7,0],[0,1,2,3,4,5,6,7,8,9]))
print(test_merge_sort_dp([9, 6, 8, 7, 0],[0, 6, 7, 8, 9]))
print(test_merge_sort_dp([8, 7, 0],[0, 7, 8]))
print(test_merge_sort_dp([3, 4, 1, 5, 2],[1, 2, 3, 4, 5]))
print(test_merge_sort_dp([3,4,1,5,2,9,6,8,7,0],[0,1,2,3,4,5,6,7,8,9]))
print(test_merge_sort_dp(["B","C","F","A","G","E","H","J","D","I"],["A","B","C","D","E","F","G","H","I","J"]))
print(test_merge_sort_dp(["B","C","A","E","D"],["A","B","C","D","E"]))
from 2018-2019.
from merge import merge
# test for the algorithm
def test_merge_sort(books_list, expected, d=dict()):
result = merge_sort(books_list, d=dict())
if result == expected:
return True
else:
return False
def merge_sort(books_list, d=dict()):
books_list_len = len(books_list) # base case
if len(books_list)<= 1:
return books_list
else:
mid = books_list_len // 2 # divide step
left_books_list = books_list[0:mid]
right_books_list = books_list[mid:books_list_len]
# recursive step
left = merge_sort(books_list[0:mid])
right = merge_sort(books_list[mid:books_list_len])
# dictionary used as input in case the same list of books must be ordered more than one time
# dynamic programming approach
if left_books_list == right_books_list:
d[right] = left
return merge(left, right) # combine
print(test_merge_sort(["Coraline", "American Gods", "Neverwhere", "Neverwhere", "American Gods", "Coraline"], ["American Gods", "American Gods", "Coraline", "Coraline", "Neverwhere", "Neverwhere"], ({})))
print(test_merge_sort(["Heart of Darkness", "Wuthering Heights", "Twelfth Night", "Twelfth Night", "Wuthering Heights", "Heart of Darkness"], ["Heart of Darkness", "Heart of Darkness", "Twelfth Night", "Twelfth Night", "Wuthering Heights", "Wuthering Heights"], ({})))
# True
# True
from 2018-2019.
My approach, based on a mix of Severin's and Eleonora's approaches but with a focus on labelling each of the 5 steps of dynamic programming.
STEP 1: base case - solution already exists
STEP 2: base case - easy-to-solve, approach directly
STEP 3: divide
STEP 4: conquer
STEP 5: combine
STEP 6: memorize
I created an ancillary function list_to_key() to handle the key label creations for each element in the dictionary separately.
# ____________MERGE_________________________
def merge(left_list, right_list):
left = left_list.copy()
right = right_list.copy()
result = list()
while len(left) > 0 and len(right) > 0:
left_item = left[0]
right_item = right[0]
if left_item < right_item:
result.append(left_item)
left.remove(left_item)
else:
result.append(right_item)
right.remove(right_item)
result.extend(left)
result.extend(right)
return result
#_______ANCILLARY FUNCT: LIST_TO_KEY()_______
def list_to_key(input_list):
key_list = list()
for item in input_list:
str_item = str(item)
key_list.append(str_item)
key_name = ""
for i in key_list:
key_name += str(i)
return key_name
#__________TEST_DYNAMIC _MSORT_________________
def test_dynamic_msort(input_list, expected, d=dict()):
result = dynamic_msort(input_list, d=dict())
if result == expected:
return True
else:
return False
#_____________DYNAMIC _MSORT_________________
def dynamic_msort(input_list, d=dict()):
len_input_list = len(input_list)
key = list_to_key(input_list)
if key in d: # STEP 1-base case: solution exists
return d[key]
elif len_input_list <= 1: # STEP 2-base case: address directly
d[key] = input_list
return d[key]
else: #recursive step
mid = len_input_list // 2 # STEP 3- divide
left_list = input_list[0:mid]
right_list = input_list[mid:len_input_list]
left = dynamic_msort(left_list) # STEP 4-conquer
right = dynamic_msort(right_list) # STEP 4conquer
merged_list = merge(left, right) # STEP 5 -combine
d[key] = merged_list # STEP 6- memorize
return d[key]
print(test_dynamic_msort([3,4,1,5,2,9,6,8,7,0],[0,1,2,3,4,5,6,7,8,9]))
print(test_dynamic_msort([9, 6, 8, 7, 0],[0, 6, 7, 8, 9]))
print(test_dynamic_msort([8, 7, 0],[0, 7, 8]))
print(test_dynamic_msort([3, 4, 1, 5, 2],[1, 2, 3, 4, 5]))
print(test_dynamic_msort([3,4,1,5,2,9,6,8,7,0],[0,1,2,3,4,5,6,7,8,9]))
print(test_dynamic_msort(["B","C","F","A","G","E","H","J","D","I"],["A","B","C","D","E","F","G","H","I","J"]))
print(test_dynamic_msort(["B","C","A","E","D"],["A","B","C","D","E"]))
# True
# True
# True
# True
# True
# True
# True
@SeverinJB I figured it out the merge() edit on my own! We need to use copies of the lists, because otherwise our dictionaries are corrupted every time we run the merge() function.
from 2018-2019.
def test_merge_sort(input_list, expected):
result = merge_sort(input_list)
if result == expected:
return True
else:
return False
def merge_sort(input_list):
input_list_len = len(input_list)
if len(input_list) <= 1:
return input_list
else:
mid = input_list_len // 2
l = (merge_sort(input_list[0:mid]))
r = (merge_sort(input_list[mid:input_list_len]))
return merge(l,r)
def merge(l,r):
result = list()
while len(l) > 0 and len(r) > 0:
left_item = l[0]
right_item = r[0]
if left_item < right_item:
result.append(left_item)
l.remove(left_item)
else:
result.append(right_item)
r.remove(right_item)
result.extend(l)
result.extend(r)
return result
input_list = (["Coraline", "American Gods", "Neverwhere", "Neverwhere", "American Gods", "Coraline"])
print(test_merge_sort(["Coraline", "American Gods", "Neverwhere", "Neverwhere", "American Gods", "Coraline"],['American Gods', 'American Gods', 'Coraline', 'Coraline', 'Neverwhere', 'Neverwhere'])) #True
from 2018-2019.
Note:
This dynamic merge sort algorithm saves results for a partial list of an input list if the partial list itself was used as an input in the recursive part of the algorithm. For example, after having ordered [9, 6, 8, 7, 0], the result for the partial list [8, 7, 0] can be retrieved from the dictionary. However, the partial list [6, 8, 7] is not stored in the dictionary and has to be ordered itself. The difference is that the latter was never used as an input of the recursive merge_sort_dp(). Whereas the first partial list was used as an input.+++ Dynamic Merge Sort with Test Cases +++
# Test Function def test_merge_sort_dp(input_list, expected): return expected == merge_sort_dp(input_list) # Merge Algorithm def merge_dp(left_list, right_list): left = left_list.copy() right = right_list.copy() result = list() while len(left) > 0 and len(right) > 0: left_item = left[0] right_item = right[0] if left_item < right_item: result.append(left_item) left.remove(left_item) else: result.append(right_item) right.remove(right_item) result.extend(left) result.extend(right) return result # Merge Sort Algorithm def merge_sort_dp(input_list, d=dict()): input_list_len = len(input_list) key = ''.join(map(str, input_list)) if key not in d: if len(input_list) <= 1: d[key] = input_list else: mid = input_list_len // 2 left = merge_sort_dp(input_list[0:mid]) right = merge_sort_dp(input_list[mid:input_list_len]) d[key] = merge_dp(left, right) return d[key] # Test Cases print(test_merge_sort_dp([3,4,1,5,2,9,6,8,7,0],[0,1,2,3,4,5,6,7,8,9])) print(test_merge_sort_dp([9, 6, 8, 7, 0],[0, 6, 7, 8, 9])) print(test_merge_sort_dp([8, 7, 0],[0, 7, 8])) print(test_merge_sort_dp([3, 4, 1, 5, 2],[1, 2, 3, 4, 5])) print(test_merge_sort_dp([3,4,1,5,2,9,6,8,7,0],[0,1,2,3,4,5,6,7,8,9])) print(test_merge_sort_dp(["B","C","F","A","G","E","H","J","D","I"],["A","B","C","D","E","F","G","H","I","J"])) print(test_merge_sort_dp(["B","C","A","E","D"],["A","B","C","D","E"]))
@SeverinJB Sevi, could you explain your thinking process behind editing the merge() algorithm definition, when you added
left = left_list.copy() right = right_list.copy()
in its definition? I am trying to understand why this is necessary to make your merge_sort_dp() work. As I tried your code without editing merge() in the way you did, and it doesn't work.
Would be awesome if you could explain your thinking process also in general!
from 2018-2019.
@SeverinJB Sevi, could you explain your thinking process behind editing the merge() algorithm definition, when you added
left = left_list.copy() right = right_list.copy()
@SeverinJB I figured it out the merge() edit on my own! We need to use copies of the lists, because otherwise our dictionaries are corrupted every time we run the merge() function.
Hi @delfimpandiani,
Sorry for not coming back to your questions earlier.
For clarification:
With copy_list = main_list only the reference is copied. It's like the computer is storing the list with a generic name "281x829yez", but there are now two human-readable names (copy_list and main_list) which can be used to address the list. Hence, when copy_list is modified main_list is simultaneously modified! The additional "copy()" in copy_list = main_list.copy() creates an actual copy of main_list and stores this copy in copy_list.
Hopefully, this helps.
from 2018-2019.
Hi all,
Here my take on the exercise - source codes available online.
# Import the function 'merge' from the module 'merge' (file 'merge.py')
from merge import merge
# Test case for the algorithm
def test_merge_sort_dp(input_list, expected):
result = merge_sort_dp(input_list)
if expected == result:
return True
else:
return False
# Code of the algorithm
def merge_sort_dp(input_list, prev_l=list()):
result = find_solution(input_list, prev_l)
if result is None:
if len(input_list) <= 1:
result = input_list
store_solution(result, prev_l)
else:
input_list_len = len(input_list)
mid = input_list_len // 2
left = merge_sort_dp(input_list[0:mid], prev_l)
right = merge_sort_dp(input_list[mid:input_list_len], prev_l)
result = merge(left, right)
store_solution(result, prev_l)
return result
def find_solution(input_list, sol_list):
input_dic = create_list_dict(input_list)
for d, sol in sol_list:
if input_dic == d:
return list(sol)
def store_solution(input_list, solution_list):
d = create_list_dict(input_list)
solution_list.append((d, list(input_list)))
def create_list_dict(input_list):
d = {}
for el in input_list:
if el not in d:
d[el] = 0
d[el] = d[el] + 1
return d
print(test_merge_sort_dp([], []))
print(test_merge_sort_dp([1], [1]))
print(test_merge_sort_dp([3, 4, 1, 2, 9, 8, 2], [1, 2, 2, 3, 4, 8, 9]))
print(test_merge_sort_dp(["Coraline", "American Gods", "The Graveyard Book", "Good Omens", "Neverwhere"],
["American Gods", "Coraline", "Good Omens", "Neverwhere", "The Graveyard Book"]))
print(test_merge_sort_dp(["Coraline", "American Gods", "The Graveyard Book", "Good Omens", "Neverwhere", "American Gods",
"American Gods", "Good Omens", "The Graveyard Book", "American Gods", "Neverwhere", "Coraline"],
["American Gods", "American Gods","American Gods", "American Gods", "Coraline", "Coraline",
"Good Omens", "Good Omens", "Neverwhere", "Neverwhere", "The Graveyard Book", "The Graveyard Book"]))
from 2018-2019.
I didn't see the solution of the exercise again. I tried to create an algoritm but I'm not sure of the efficiency, because it returns the result, but maybe it iterates in an unneccessary way. Could it work?
def test_merge(left_list, right_list, expected):
result = merge(left_list, right_list)
if expected == result:
return True
else:
return False
def merge(left_list, right_list):
result = list()
while len(left_list) > 0 and len(right_list) > 0:
left_item = left_list[0]
right_item = right_list[0]
if left_item < right_item:
result.append(left_item)
left_list.remove(left_item)
else:
result.append(right_item)
right_list.remove(right_item)
result.extend(left_list)
result.extend(right_list)
return result
def test_merge_sort(input_list, expected, d):
if merge_sort(input_list, d) == expected:
return True
else:
return False
def merge_sort(input_list, d):
input_list_len = len(input_list)
for item in input_list:
if item not in d:
if input_list_len <= 1:
d[merge] = input_list
else:
mid = input_list_len // 2
left = merge_sort(input_list[0:mid], d)
right = merge_sort(input_list[mid:input_list_len], d)
d[merge] = merge(left, right)
return d[merge]
print(test_merge_sort(["Coraline", "American Gods", "Neverwhere", "Neverwhere", "American Gods", "Coraline"],
['American Gods', 'American Gods', 'Coraline', 'Coraline', 'Neverwhere', 'Neverwhere'], ({})))
from 2018-2019.
Related Issues (20)
- Lecture "Brute-force algorithms", exercise 3 HOT 13
- Lecture "Brute-force algorithms", exercise 4 HOT 16
- Lecture "Brute-force algorithms", exercise 5 HOT 12
- Lecture "Organising information: unordered structures", exercise 1 HOT 21
- Lecture "Organising information: unordered structures", exercise 2 HOT 19
- Lecture "Organising information: unordered structures", exercise 3 HOT 17
- Lecture "Recursion", exercise 1 HOT 18
- Lecture "Recursion", exercise 2 HOT 20
- Lecture "Divide and conquer algorithm", exercise 1 HOT 12
- Lecture "Divide and conquer algorithm", exercise 2 HOT 5
- Lecture "Dynamic programming algorithms", exercise 1 HOT 15
- Lecture "Organising information: trees", exercise 1 HOT 4
- Lecture "Organising information: trees", exercise 2 HOT 4
- Lecture "Organising information: graphs", exercise 1 HOT 14
- Lecture "Organising information: graphs", exercise 2 HOT 12
- Christmas present game + bonus Python exercise
- Lecture "Backtracking algorithms", exercise 1 HOT 3
- Lecture "Greedy algorithms", exercise 1 HOT 2
- Question about an exercise from last year
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from 2018-2019.