|
| 1 | +#!/bin/python3 |
| 2 | + |
| 3 | +def _print_list_states(addition_start_index_marks: dict[int, int], size) -> None: |
| 4 | + """Useful for visualizing. |
| 5 | +
|
| 6 | + Args: |
| 7 | + dict[int: index, int: value]: operation application markings |
| 8 | + size (int): number of elements in the array. |
| 9 | + Returns: None |
| 10 | +
|
| 11 | + NB: at the large input values of size_of_list and addition_start_index_marks, it will be slow, because it is |
| 12 | +
|
| 13 | + O(M*N), where |
| 14 | + M = size_of_list - addition_start_index_marks.start : i.e. longest range |
| 15 | + N = size_of_list |
| 16 | + """ |
| 17 | + print(f"{addition_start_index_marks=}\n") |
| 18 | + list_values = [0] * size |
| 19 | + print(f"{list_values=}") |
| 20 | + for i in sorted(addition_start_index_marks.keys()): |
| 21 | + n_inclusive_end_index = n+1 |
| 22 | + for j in range(i, n_inclusive_end_index): |
| 23 | + if j < n_inclusive_end_index: |
| 24 | + # values[j-1], because the list_values is 0 index, but the operations(e.g. {1: 100}) encoded in the addition_start_index_marks are 1 indexed. |
| 25 | + list_values[j-1] += addition_start_index_marks[i] |
| 26 | + print(list_values) |
| 27 | + |
| 28 | + |
| 29 | +def construct_manipulation_instructions(operation_requests): |
| 30 | + """Constructs the operation_start_index_marks data structure |
| 31 | +
|
| 32 | + Steps to construct operation_start_index_marks: |
| 33 | + 1. mark adding 'value' from index 'start_index' to the end of the array. |
| 34 | + 2. mark adding '-value' from index ('stop_index' + 1) to the end of the array, because you only need to add 'value' until index 'stop_index'(as per the query('stop_index') parameter). |
| 35 | + You are actually subtracting the unnecessary 'value' you added, to reset the array values to their previous state from index 'stop_index'+1 until the end. |
| 36 | +
|
| 37 | + Args: |
| 38 | + operation_requests ([start_index: int, stop_index: int, value: int]): operation to apply to array. Defaulted to addition. |
| 39 | +
|
| 40 | + Returns: |
| 41 | + dict[int: index, int: value]: operation application markings. |
| 42 | +
|
| 43 | + Detailed Explanation: |
| 44 | + operation_start_index_marks data structure: |
| 45 | + - data structure meaning: |
| 46 | + This data structure encodes marking an index(𝑥) from which to add some value(𝑘) until the end of the array. |
| 47 | + - data structure usage: |
| 48 | + Example: |
| 49 | + given: |
| 50 | + n = 5, therefore, values = [0, 0, 0, 0, 0] |
| 51 | + queries = [[1, 2, 100], [2, 5, 100], [3, 4, 100]] |
| 52 | + addition_start_index_marks = {1: 100, 2: 100, 3: 0, 5: -100, 6: -100} |
| 53 | + then: |
| 54 | + apply query/operation: [1, 2, 100] |
| 55 | + NB: we subtract -1 from the indices when applying them to an actual array, because the commands {𝑥 = 2: 100} are 1 indexed. |
| 56 | + because lists are zero index. |
| 57 | + 1. {𝑥 = 1: 100} = add 100 from index 1-1 until the end of the array |
| 58 | + ∴ values = [100, 100, 100, 100, 100] |
| 59 | + 2. {𝑥 = 2: 100} = add 100 from index 2-1 until the end of the array |
| 60 | + ∴ values = [100, 100+100, 100+100, 100+100, 100+100] |
| 61 | + ∴ values = [100, 200, 200, 200, 200] |
| 62 | + 3. {𝑥 = 3: 0} = add 0 from index 3-1 until the end of the array |
| 63 | + ∴ values = [100, 200, 200+0, 200+0, 200+0] |
| 64 | + ∴ values = [100, 200, 200, 200, 200] |
| 65 | + 4. {𝑥 = 5: -100} add -100 from index 5-1 until the end of the array |
| 66 | + ∴ values = [100, 200, 200, 200, 200-100] |
| 67 | + ∴ values = [100, 200, 200, 200, 100] |
| 68 | + 5. {𝑥 = 6: -100} add -100 from index 6-1 until the end of the array |
| 69 | + ∴ values = [100, 200, 200, 200, 100] |
| 70 | + NB: Nothing is done, because index 6 is out of bounds of our array, which has length 5. |
| 71 | + """ |
| 72 | + |
| 73 | + operation_start_index_marks = {} |
| 74 | + for start_index, stop_index, value in operation_requests: |
| 75 | + addition_index = start_index |
| 76 | + if start_index not in operation_start_index_marks: |
| 77 | + operation_start_index_marks[addition_index] = value |
| 78 | + else: |
| 79 | + # Increase the value to add to the array values, starting from index a |
| 80 | + operation_start_index_marks[addition_index] += value |
| 81 | + subtraction_index = stop_index + 1 |
| 82 | + if subtraction_index not in operation_start_index_marks: |
| 83 | + operation_start_index_marks[subtraction_index] = -value |
| 84 | + else: |
| 85 | + # Increase the value to subtract from the array values, starting from index a |
| 86 | + operation_start_index_marks[subtraction_index] -= value |
| 87 | + return operation_start_index_marks |
| 88 | + |
| 89 | + |
| 90 | +def arrayManipulation(n, queries): |
| 91 | + """ Calculate maximum value in array after applications of queries |
| 92 | +
|
| 93 | + Args: |
| 94 | + n (int): size of the 1-index array |
| 95 | + queries ([start_index: int, stop_index: int, value: int]): operation to apply to array. |
| 96 | +
|
| 97 | + Returns: |
| 98 | + int: maximum value |
| 99 | + """ |
| 100 | + operation_start_index_marks = construct_manipulation_instructions(queries) |
| 101 | + total_value_added_to_some_list_indices = 0 |
| 102 | + highest_total_value_reached_in_some_list_indices = 0 |
| 103 | + |
| 104 | + """ debugging visualization |
| 105 | + _print_list_states(operation_start_index_marks, n) |
| 106 | + """ |
| 107 | + for i in sorted(operation_start_index_marks.keys()): |
| 108 | + total_value_added_to_some_list_indices += operation_start_index_marks[i] |
| 109 | + highest_total_value_reached_in_some_list_indices = max( |
| 110 | + highest_total_value_reached_in_some_list_indices, total_value_added_to_some_list_indices) |
| 111 | + |
| 112 | + return highest_total_value_reached_in_some_list_indices |
| 113 | + |
| 114 | + |
| 115 | +if __name__ == '__main__': |
| 116 | + with open("array_manipulation_data_10000000_100000.txt", 'r') as file: |
| 117 | + all_lines = file.readline() |
| 118 | + nm = all_lines.split() |
| 119 | + |
| 120 | + n = int(nm[0]) |
| 121 | + m = int(nm[1]) |
| 122 | + |
| 123 | + queries = [] |
| 124 | + for i in range(m): |
| 125 | + queries.append(list(map(int, file.readline().rsplit()))) |
| 126 | + result = arrayManipulation(n, queries) |
| 127 | + |
| 128 | + print(result) |
| 129 | + assert result == 2497169732 |
| 130 | + |
| 131 | +""" |
| 132 | +References: |
| 133 | + - Roy, A. 2023. https://www.techrbun.com/array-manipulation-hackerrank-solution/ |
| 134 | + - Basumatary, V. 2020. https://www.thepoorcoder.com/hackerrank-array-manipulation-solution/ |
| 135 | +""" |
0 commit comments