From 5a1e5c35e4bb4593d0e647fabd7c758db4ac131d Mon Sep 17 00:00:00 2001 From: Elliot Brainerd Date: Fri, 28 May 2021 15:09:03 -0700 Subject: [PATCH 1/7] first commit - compression done --- input1.txt | 14 ++++++++++ input2.txt | 7 +++++ ontraport_test.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 input1.txt create mode 100644 input2.txt create mode 100644 ontraport_test.py diff --git a/input1.txt b/input1.txt new file mode 100644 index 0000000..7bbe83c --- /dev/null +++ b/input1.txt @@ -0,0 +1,14 @@ +{ + 'one': + { + 'two': 3, + 'four': [ 5,6,7] + }, + 'eight': + { + 'nine': + { + 'ten':11 + } + } +} \ No newline at end of file diff --git a/input2.txt b/input2.txt new file mode 100644 index 0000000..e632f25 --- /dev/null +++ b/input2.txt @@ -0,0 +1,7 @@ +{ + 'one/two':3, + 'one/four/0':5, + 'one/four/1':6, + 'one/four/2':7, + 'eight/nine/ten':11 +} \ No newline at end of file diff --git a/ontraport_test.py b/ontraport_test.py new file mode 100644 index 0000000..79d7f8e --- /dev/null +++ b/ontraport_test.py @@ -0,0 +1,68 @@ +import sys +import ast + + +def compress_helper(data, result, cur_path): + for key in data: + if type(data[key]) is dict: + cur_path += key + "/" + compress_helper(data[key], result, cur_path) + cur_path = "" + elif type(data[key]) is list: + cur_path += key + "/" + cur_path_copy = cur_path + for i in range(len(data[key])): + cur_path_copy += str(i) + result[cur_path_copy] = data[key][i] + cur_path_copy = cur_path + else: + result[cur_path + key] = data[key] + + return result + + +def compress(data): + data = ast.literal_eval(data) + if type(data) is dict: + return compress_helper(data, {}, "") + + +def expand_helper(result, cur_path_list): + top = cur_path_list.pop(0) + if top not in result.keys() and not top.isnumeric(): + result[top] = expand_helper({}, cur_path_list) + elif top in result.keys(): + expand_helper(result[top], cur_path_list[1:]) + elif top.isnumeric(): + pass + + +def expand(data): + data = ast.literal_eval(data) + if type(data) is dict: + result = {} + for key in data: + spl = key.split("/") + expand_helper(result, spl) + return result + + +for every line: + for every node in line: + if key/node doesnt exist: + create key with value None + continue + if key/node does exist: + continue + + +def main(): + filename = sys.argv[1] + file = open(filename, 'r') + data = file.read() + # print(compress(data)) + expand(data) + + +if __name__ == '__main__': + main() From cdb0d7ae453fb4475f95284d8a12c7a8dfaf665a Mon Sep 17 00:00:00 2001 From: Elliot Brainerd Date: Fri, 28 May 2021 17:42:36 -0700 Subject: [PATCH 2/7] some stuff --- ontraport_test.py | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/ontraport_test.py b/ontraport_test.py index 79d7f8e..2119264 100644 --- a/ontraport_test.py +++ b/ontraport_test.py @@ -27,14 +27,20 @@ def compress(data): return compress_helper(data, {}, "") -def expand_helper(result, cur_path_list): - top = cur_path_list.pop(0) - if top not in result.keys() and not top.isnumeric(): - result[top] = expand_helper({}, cur_path_list) - elif top in result.keys(): - expand_helper(result[top], cur_path_list[1:]) - elif top.isnumeric(): - pass +def expand_helper(nodes, result, value, prev_node): + for node in nodes: + + if node.isnumeric(): + if int(node) == 0: + result[prev_node] = [value] + else: + result[prev_node].append(value) + + if node == nodes[-1]: + result[node] = value + + elif node not in result.keys(): + result[node] = expand_helper(nodes[1:], {}, value, node) def expand(data): @@ -42,18 +48,18 @@ def expand(data): if type(data) is dict: result = {} for key in data: - spl = key.split("/") - expand_helper(result, spl) - return result + nodes = key.split('/') + expand_helper(nodes, result, data[key], None) + return result -for every line: - for every node in line: - if key/node doesnt exist: - create key with value None - continue - if key/node does exist: - continue +# for every line: +# for every node in line: +# if key/node doesnt exist: +# create key with value None +# continue +# if key/node does exist: +# continue def main(): @@ -61,7 +67,7 @@ def main(): file = open(filename, 'r') data = file.read() # print(compress(data)) - expand(data) + print(expand(data)) if __name__ == '__main__': From 2e6d6668d7b84c3eacf85b38372ba112f7714db5 Mon Sep 17 00:00:00 2001 From: Elliot Brainerd Date: Fri, 28 May 2021 19:36:42 -0700 Subject: [PATCH 3/7] both functions working --- ontraport_test.py | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/ontraport_test.py b/ontraport_test.py index 2119264..10e1b8a 100644 --- a/ontraport_test.py +++ b/ontraport_test.py @@ -28,20 +28,37 @@ def compress(data): def expand_helper(nodes, result, value, prev_node): - for node in nodes: + node = nodes[0] - if node.isnumeric(): - if int(node) == 0: - result[prev_node] = [value] - else: - result[prev_node].append(value) + # integer nodes (lists) + if node.isnumeric(): + if int(node) == 0: + result[prev_node] = [value] + else: + result[prev_node].append(value) - if node == nodes[-1]: - result[node] = value + # last non-numeric node + elif node == nodes[-1]: + result[node] = value - elif node not in result.keys(): + # new dict + elif node not in result.keys(): + # if the next node is a number, create a list + if nodes[nodes.index(node) + 1].isnumeric(): + result[node] = [value] + else: result[node] = expand_helper(nodes[1:], {}, value, node) + # node already exists in result + else: + # if node is equal to list, append to list + if type(result[node]) == list: + result[node].append(value) + else: + expand_helper(nodes[1:], result[node], value, node) + + return result + def expand(data): data = ast.literal_eval(data) @@ -53,21 +70,12 @@ def expand(data): return result -# for every line: -# for every node in line: -# if key/node doesnt exist: -# create key with value None -# continue -# if key/node does exist: -# continue - - def main(): filename = sys.argv[1] file = open(filename, 'r') data = file.read() # print(compress(data)) - print(expand(data)) + # print(expand(data)) if __name__ == '__main__': From 3a937caa91a732215411021ec6b17715d7a84348 Mon Sep 17 00:00:00 2001 From: Elliot Brainerd Date: Sat, 29 May 2021 12:11:25 -0700 Subject: [PATCH 4/7] formatting and comments --- ontraport_test.py | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/ontraport_test.py b/ontraport_test.py index 10e1b8a..8b89583 100644 --- a/ontraport_test.py +++ b/ontraport_test.py @@ -1,13 +1,20 @@ +# Elliot Brainerd +# Ontraport Backend Test 5/29 + +# Usage: python .\ontraport_test.py + import sys import ast def compress_helper(data, result, cur_path): for key in data: + if type(data[key]) is dict: cur_path += key + "/" compress_helper(data[key], result, cur_path) cur_path = "" + elif type(data[key]) is list: cur_path += key + "/" cur_path_copy = cur_path @@ -15,12 +22,16 @@ def compress_helper(data, result, cur_path): cur_path_copy += str(i) result[cur_path_copy] = data[key][i] cur_path_copy = cur_path + else: result[cur_path + key] = data[key] return result +# Accepts a multi-dimensional container of any size and converts it into a +# one dimensional associative array whose keys are strings representing +# their value's path in the original container def compress(data): data = ast.literal_eval(data) if type(data) is dict: @@ -30,28 +41,25 @@ def compress(data): def expand_helper(nodes, result, value, prev_node): node = nodes[0] - # integer nodes (lists) + # integer nodes (for lists) if node.isnumeric(): - if int(node) == 0: - result[prev_node] = [value] - else: - result[prev_node].append(value) + if type(result[prev_node] != list): + result[prev_node] = [] + result[prev_node].insert(int(node), value) - # last non-numeric node + # last node, non-numeric elif node == nodes[-1]: result[node] = value - # new dict + # new node, new dict elif node not in result.keys(): - # if the next node is a number, create a list if nodes[nodes.index(node) + 1].isnumeric(): result[node] = [value] else: result[node] = expand_helper(nodes[1:], {}, value, node) - # node already exists in result + # node already seen else: - # if node is equal to list, append to list if type(result[node]) == list: result[node].append(value) else: @@ -60,6 +68,8 @@ def expand_helper(nodes, result, value, prev_node): return result +# Accepts one dimensional associative array whose keys are strings representing +# their value's path and creates a multi-dimensional container def expand(data): data = ast.literal_eval(data) if type(data) is dict: @@ -74,8 +84,8 @@ def main(): filename = sys.argv[1] file = open(filename, 'r') data = file.read() - # print(compress(data)) - # print(expand(data)) + # compressed = compress(data) + # expanded = expand(data) if __name__ == '__main__': From 69ce4ac0a462df0ae1f350a5f29aea3ab5d63be1 Mon Sep 17 00:00:00 2001 From: Elliot Brainerd Date: Sun, 30 May 2021 02:15:43 -0700 Subject: [PATCH 5/7] updated logic for list appending, error checking, better comments --- ontraport_test.py | 54 +++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/ontraport_test.py b/ontraport_test.py index 8b89583..ef9600d 100644 --- a/ontraport_test.py +++ b/ontraport_test.py @@ -1,7 +1,9 @@ # Elliot Brainerd # Ontraport Backend Test 5/29 -# Usage: python .\ontraport_test.py +# usage: +# update main method according to input file format +# run python .\ontraport_test.py import sys import ast @@ -18,57 +20,62 @@ def compress_helper(data, result, cur_path): elif type(data[key]) is list: cur_path += key + "/" cur_path_copy = cur_path + for i in range(len(data[key])): cur_path_copy += str(i) result[cur_path_copy] = data[key][i] cur_path_copy = cur_path + #integers else: result[cur_path + key] = data[key] return result -# Accepts a multi-dimensional container of any size and converts it into a +# accepts a multi-dimensional container of any size and converts it into a # one dimensional associative array whose keys are strings representing # their value's path in the original container def compress(data): data = ast.literal_eval(data) if type(data) is dict: return compress_helper(data, {}, "") + else: + print("Error with input file.") + exit def expand_helper(nodes, result, value, prev_node): - node = nodes[0] + cur_node = nodes[0] # nodes represent the keys in a given path - # integer nodes (for lists) - if node.isnumeric(): + # integer nodes + if cur_node.isnumeric(): if type(result[prev_node] != list): result[prev_node] = [] - result[prev_node].insert(int(node), value) + result[prev_node].insert(int(cur_node), value) # last node, non-numeric - elif node == nodes[-1]: - result[node] = value + elif cur_node == nodes[-1]: + result[cur_node] = value - # new node, new dict - elif node not in result.keys(): - if nodes[nodes.index(node) + 1].isnumeric(): - result[node] = [value] + # new node + elif cur_node not in result.keys(): + if nodes[nodes.index(cur_node) + 1].isnumeric(): + result[cur_node] = [value] else: - result[node] = expand_helper(nodes[1:], {}, value, node) + result[cur_node] = expand_helper(nodes[1:], {}, value, cur_node) # node already seen else: - if type(result[node]) == list: - result[node].append(value) + if type(result[cur_node]) == list: + result[cur_node].insert(int(nodes[nodes.index(cur_node) + 1]), value) else: - expand_helper(nodes[1:], result[node], value, node) + expand_helper(nodes[1:], result[cur_node], value, cur_node) return result -# Accepts one dimensional associative array whose keys are strings representing +# accepts one dimensional associative array whose keys are strings representing # their value's path and creates a multi-dimensional container def expand(data): data = ast.literal_eval(data) @@ -77,15 +84,22 @@ def expand(data): for key in data: nodes = key.split('/') expand_helper(nodes, result, data[key], None) - return result + return result + else: + print("Error with input file.") + exit def main(): filename = sys.argv[1] file = open(filename, 'r') data = file.read() - # compressed = compress(data) - # expanded = expand(data) + + # input1.txt + print(compress(data)) + + # input2.txt + # print(expand(data)) if __name__ == '__main__': From 666e9e6af6b22eed880c7ebafb5f2bcaf73416ef Mon Sep 17 00:00:00 2001 From: Elliot Brainerd Date: Tue, 1 Jun 2021 12:00:34 -0700 Subject: [PATCH 6/7] removed unnecessary check for list type in integer branch inside expand_helper --- ontraport_test.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/ontraport_test.py b/ontraport_test.py index ef9600d..ac9a9e7 100644 --- a/ontraport_test.py +++ b/ontraport_test.py @@ -1,7 +1,7 @@ # Elliot Brainerd # Ontraport Backend Test 5/29 -# usage: +# usage: # update main method according to input file format # run python .\ontraport_test.py @@ -26,7 +26,7 @@ def compress_helper(data, result, cur_path): result[cur_path_copy] = data[key][i] cur_path_copy = cur_path - #integers + # integers else: result[cur_path + key] = data[key] @@ -46,12 +46,10 @@ def compress(data): def expand_helper(nodes, result, value, prev_node): - cur_node = nodes[0] # nodes represent the keys in a given path + cur_node = nodes[0] # nodes represent the keys in a given path # integer nodes if cur_node.isnumeric(): - if type(result[prev_node] != list): - result[prev_node] = [] result[prev_node].insert(int(cur_node), value) # last node, non-numeric @@ -68,7 +66,8 @@ def expand_helper(nodes, result, value, prev_node): # node already seen else: if type(result[cur_node]) == list: - result[cur_node].insert(int(nodes[nodes.index(cur_node) + 1]), value) + result[cur_node].insert( + int(nodes[nodes.index(cur_node) + 1]), value) else: expand_helper(nodes[1:], result[cur_node], value, cur_node) @@ -96,10 +95,10 @@ def main(): data = file.read() # input1.txt - print(compress(data)) + # print(compress(data)) # input2.txt - # print(expand(data)) + print(expand(data)) if __name__ == '__main__': From e5ec402ce8b0061063d9143ae4cfc23665f85298 Mon Sep 17 00:00:00 2001 From: Elliot Brainerd <32251510+ebrainerd@users.noreply.github.com> Date: Tue, 1 Jun 2021 12:03:48 -0700 Subject: [PATCH 7/7] Update header comments --- ontraport_test.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ontraport_test.py b/ontraport_test.py index ac9a9e7..b8df5e3 100644 --- a/ontraport_test.py +++ b/ontraport_test.py @@ -5,6 +5,12 @@ # update main method according to input file format # run python .\ontraport_test.py +# eg. +# uncomment line in main "print(expand(data))" +# python ./ontraport_test.py input2.txt + +# solution assumes that list values are final/do not contain nested data structures + import sys import ast