Advertisement
Guest User

Untitled

a guest
Jul 16th, 2019
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.50 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. from functools import reduce
  3.  
  4. def generate_tests():
  5. def test0():
  6. a = [[0, 1, 0, 1],
  7. [0, 0, 0, 0],
  8. [0, 0, 0, 0],
  9. [1, 0, 0, 1]]
  10. return (a, 2, 2)
  11.  
  12. def test1():
  13. a = [[1, 1, 0, 1],
  14. [1, 0, 0, 0],
  15. [0, 0, 0, 1],
  16. [1, 0, 1, 1]]
  17. return (a, 2, 2)
  18.  
  19. def test2():
  20. a = [[1, 1, 1, 1],
  21. [0, 0, 0, 0],
  22. [0, 0, 0, 1],
  23. [1, 0, 1, 1]]
  24. return (a, 2, 2)
  25.  
  26. def test3():
  27. a = [[1, 1, 0, 1],
  28. [0, 0, 0, 0],
  29. [1, 0, 0, 1],
  30. [1, 0, 1, 1]]
  31. return (a, 2, 2)
  32.  
  33. def test4():
  34. a = [[0, 1, 0, 1],
  35. [0, 0, 0, 0],
  36. [0, 0, 0, 0],
  37. [1, 0, 0, 1]]
  38. return (a, 3, 3)
  39.  
  40. def test5():
  41. a = [[1, 1, 0, 0],
  42. [1, 1, 0, 0],
  43. [0, 0, 1, 1],
  44. [0, 0, 1, 1]]
  45. return (a, 2, 2)
  46.  
  47. def test6():
  48. a = [[0, 1, 1, 0],
  49. [0, 0, 0, 0],
  50. [0, 0, 0, 0],
  51. [1, 0, 1, 0]]
  52. return (a, 2, 2)
  53. test_func_prefix = 'test'
  54. test_namespace = locals()
  55.  
  56. return [(x, test_namespace[x]()) for x in \
  57. filter(lambda x: x.startswith(test_func_prefix) \
  58. and callable(test_namespace[x]), test_namespace)]
  59.  
  60. def output(test_name, succeed, log):
  61. print("%s %s %s" % (test_name, "succeeds" if succeed else "fails", log))
  62.  
  63. def cut(sum_matrix, value_per_portion, portion_num, option):
  64. def total_value(last_pos, cur_pos):
  65. if last_pos == -1:
  66. return sum_matrix[cur_pos][-1] if option == 'r' else sum_matrix[-1][cur_pos]
  67.  
  68. return sum_matrix[cur_pos][-1] - sum_matrix[last_pos][-1] if option == 'r' else \
  69. sum_matrix[-1][cur_pos] - sum_matrix[-1][last_pos]
  70.  
  71. cur_pos = 0
  72. last_pos = -1
  73. max_pos = len(sum_matrix) if option == 'r' else len(sum_matrix[0])
  74.  
  75. cur_value = 0
  76.  
  77. strategy = []
  78.  
  79. while cur_pos < max_pos:
  80. while (cur_pos < max_pos) and \
  81. (total_value(last_pos, cur_pos) < value_per_portion):
  82. cur_pos += 1
  83.  
  84. if total_value(last_pos, cur_pos) != value_per_portion:
  85. return None
  86.  
  87. move = [cur_pos]
  88. while (cur_pos + 1 < max_pos) and (total_value(cur_pos, cur_pos + 1) == 0):
  89. cur_pos += 1
  90. move.append(cur_pos)
  91.  
  92. strategy.append(move)
  93. last_pos = cur_pos
  94. cur_pos += 1
  95.  
  96. return strategy
  97.  
  98. def validate(sum_matrix, r_stg, c_stg, value_per_portion):
  99.  
  100. def compute(r_cut_idx, c_cut_idx):
  101. v = sum_matrix[r_stg[r_cut_idx][0]][c_stg[c_cut_idx][0]]
  102. if c_cut_idx != 0:
  103. v -= sum_matrix[r_stg[r_cut_idx][0]][c_stg[c_cut_idx-1][0]]
  104.  
  105. if r_cut_idx != 0:
  106. v -= sum_matrix[r_stg[r_cut_idx-1][0]][c_stg[c_cut_idx][0]]
  107.  
  108. if (c_cut_idx != 0) and (r_cut_idx != 0):
  109. v += sum_matrix[r_stg[r_cut_idx-1][0]][c_stg[c_cut_idx-1][0]]
  110.  
  111. return v
  112.  
  113. r_cut_cnt, c_cut_cnt = len(r_stg), len(c_stg)
  114. values = [compute(i, j) for j in range(c_cut_cnt) for i in range(r_cut_cnt)]
  115. return all(map(lambda v: v == value_per_portion, values))
  116.  
  117. def generate_sum_matrix(m):
  118. r_num, c_num = len(m), len(m[0])
  119. sum_matrix = [[0 for _ in range(c_num)] for _ in range(r_num)]
  120.  
  121. for r in range(r_num):
  122. r_sum = 0
  123. for c in range(c_num):
  124. if r > 0: sum_matrix[r][c] = sum_matrix[r-1][c]
  125. r_sum += m[r][c]
  126. sum_matrix[r][c] += r_sum
  127. return sum_matrix
  128.  
  129. # assumption: input is always valid
  130. def process(m, r_cut, c_cut):
  131. r_num, c_num = len(m), len(m[0])
  132. # empty input
  133. if r_num == 0: return None
  134.  
  135. total_num = reduce(lambda x, y: x + y, [reduce(lambda x, y: x + y, row) for row in m])
  136. if total_num % (c_cut*r_cut) != 0:
  137. return False, "Invalid number of 1s giving the cutting requirement"
  138.  
  139. sum_matrix = generate_sum_matrix(m)
  140.  
  141. r_stg = cut(sum_matrix, total_num / r_cut, r_cut, 'r')
  142. if r_stg is None:
  143. return False, "No valid row cutting strategy"
  144.  
  145. c_stg = cut(sum_matrix, total_num / c_cut, r_cut, 'c')
  146. if c_stg is None:
  147. return False, "No valid column cutting strategy"
  148.  
  149. if not validate(sum_matrix, r_stg, c_stg,
  150. total_num / (c_cut*r_cut)):
  151. return False, "Possible cutting strategies don't work"
  152.  
  153. return True, "row cuts %s, col cuts: %s" % (str(r_stg), str(c_stg))
  154.  
  155. if __name__ == "__main__":
  156. for test_name, inputs in generate_tests():
  157. output(test_name, *process(*inputs))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement