re_loop.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import random
  2. def cross_product(p1, p2, p3):
  3. """
  4. 计算向量 p1p2 和 p1p3 的叉积。
  5. 如果结果为正,则 p1p3 在 p1p2 的顺时针方向;
  6. 如果结果为负,则 p1p3 在 p1p2 的逆时针方向;
  7. 如果结果为零,则 p1、p2 和 p3 共线。
  8. """
  9. return (p2[0] - p1[0]) * (p3[1] - p1[1]) - (p2[1] - p1[1]) * (p3[0] - p1[0])
  10. def do_segments_intersect(s1, s2):
  11. """
  12. 判断两条线段 s1 和 s2 是否相交。
  13. 每条线段由两个点的元组表示,例如:s1 = ((x1, y1), (x2, y2))。
  14. """
  15. p1, p2 = s1
  16. p3, p4 = s2
  17. if max(p1[0], p2[0]) <= min(p3[0], p4[0]):
  18. return False # 线段1在线段2的左侧
  19. if max(p3[0], p4[0]) <= min(p1[0], p2[0]):
  20. return False # 线段1在线段2的右侧
  21. if max(p1[1], p2[1]) <= min(p3[1], p4[1]):
  22. return False # 线段1在线段2的下方
  23. if max(p3[1], p4[1]) <= min(p1[1], p2[1]):
  24. return False # 线段1在线段2的上方
  25. if cross_product(p1, p2, p3) * cross_product(p1, p2, p4) >= 0:
  26. return False # 线段2的两个端点在线段1的同侧
  27. if cross_product(p3, p4, p1) * cross_product(p3, p4, p2) >= 0:
  28. return False # 线段1的两个端点在线段2的同侧
  29. return True # 两条线段相交
  30. def is_over_k_line(combination, triangle_index):
  31. bottom_length = combination[triangle_index]
  32. if bottom_length == 0:
  33. return False
  34. left_b_x = K_COUNT - sum(combination[triangle_index:])
  35. left_b_y = lowest
  36. left_t_x = middle = left_b_x + int(bottom_length / 2)
  37. left_t_y = low[left_t_x]
  38. right_b_x = left_b_x + bottom_length - 1
  39. right_b_y = lowest
  40. right_t_x = middle
  41. right_t_y = left_t_y
  42. line_left = [[left_b_x, left_b_y], [left_t_x, left_t_y]]
  43. line_right = [[right_b_x, right_b_y], [right_t_x, right_t_y]]
  44. k_index = left_b_x
  45. while k_index <= right_b_x:
  46. k = [[k_index, low[k_index]], [k_index, high[k_index]]]
  47. # 在垂线左侧的K只用考虑三角形的左边;右侧只考虑右边,并且垂线不做判断
  48. if k_index < middle and do_segments_intersect(line_left, k):
  49. return True
  50. if k_index > middle and do_segments_intersect(line_right, k):
  51. return True
  52. k_index = k_index + 1
  53. return False
  54. def generate_combinations(n, k_count, step, min_length, init_value):
  55. # Initialize the combination
  56. combination = []
  57. space_step = 4
  58. space_max = 12
  59. c_index = 0
  60. # 初始间隔
  61. combination.append(0)
  62. while c_index < n:
  63. # 三角形
  64. combination.append(init_value)
  65. # 间隔
  66. combination.append(0)
  67. c_index = c_index + 1
  68. # Generate all combinations
  69. count = 0
  70. while True:
  71. # Print the current combination
  72. # print(combination)
  73. count += 1
  74. # Increment the combination
  75. i = len(combination) - 1
  76. while i >= 0:
  77. # 如果下标是偶数,则该位置是空位,是三角形之间的距离
  78. # 如果下标是奇数,则该位置表达的是三角形
  79. is_triangle = (i % 2 == 1)
  80. # 用大致比例分割三角形数量
  81. # cut_off_index = int(lowest_index / k_count)
  82. # if i > cut_off_index:
  83. # max_length = (k_count - lowest_index)
  84. # else:
  85. # max_length = lowest_index
  86. if is_triangle:
  87. # 单个长度判断
  88. if combination[i] + step > k_count:
  89. combination[i] = init_value
  90. i -= 1
  91. continue
  92. # 三角形长度只能是0或初始值
  93. if combination[i] == 0:
  94. combination[i] = min_length
  95. else:
  96. combination[i] += step
  97. # 总长剪枝
  98. # if i > cut_off_index:
  99. # is_over_max = sum(combination[i:]) > max_length
  100. # else:
  101. # is_over_max = sum(combination[:i]) > max_length
  102. is_over_max = sum(combination) > k_count
  103. # 各种剪枝逻辑
  104. is_intersect = is_over_k_line(combination, i) # 相交剪枝
  105. if is_over_max or is_intersect:
  106. combination[i] = init_value
  107. i -= 1
  108. else:
  109. break
  110. else:
  111. # 单个长度判断
  112. if combination[i] + space_step > space_max:
  113. combination[i] = 0
  114. i -= 1
  115. continue
  116. combination[i] += space_step
  117. # 总长剪枝
  118. # if i > cut_off_index:
  119. # is_over_max = sum(combination[i:]) > max_length
  120. # else:
  121. # is_over_max = sum(combination[:i]) > max_length
  122. # is_over_max = is_over_max or sum(combination) > k_count
  123. is_over_max = sum(combination) > k_count
  124. if is_over_max:
  125. combination[i] = 0
  126. i -= 1
  127. else:
  128. break
  129. # If i < 0, we've exhausted all combinations
  130. if i < 0:
  131. break
  132. return count
  133. if __name__ == '__main__':
  134. # Generate all 8-digit combinations
  135. MAX_TRIANGLE_COUNT = 5
  136. K_COUNT = 100
  137. STEP = 10
  138. MIN_TRIANGLE_BOTTOM_LENGTH = 13
  139. # 生成high
  140. high = [800]
  141. highest = high[0]
  142. highest_index = 0
  143. for i1 in range(K_COUNT - 1):
  144. # 生成一个[-10, 10]之间的随机数
  145. distance = random.randint(-30, 30)
  146. num = high[-1] + distance
  147. # 添加新的元素到数组中
  148. if highest < num:
  149. highest_index = i1 + 1
  150. highest = num
  151. high.append(num)
  152. # 生成low
  153. low = []
  154. lowest = 999999999
  155. lowest_index = -1
  156. for i2 in range(K_COUNT):
  157. # 生成一个[-10, -1]之间的随机数
  158. distance = random.randint(-20, -1)
  159. num = high[i2] + distance
  160. if lowest > num:
  161. lowest_index = i2
  162. lowest = num
  163. # 添加新的元素到数组中
  164. low.append(num)
  165. # print(high)
  166. # print(low)
  167. print(generate_combinations(MAX_TRIANGLE_COUNT, K_COUNT, STEP, MIN_TRIANGLE_BOTTOM_LENGTH, 0))
  168. print('lowest=', lowest, 'lowest_index=', lowest_index)
  169. # print(is_over_k_line([2, 23, 0, 33, 4, 5, 4], 5))