fork download
  1. # Generate uniform random point inside unit square.
  2.  
  3. import math
  4. import random
  5.  
  6. def randrange(a, b):
  7. return random.random() * (b - a) + a
  8.  
  9. # @brief Generate uniform random point inside unit square.
  10. # @param mindist Minimum axial distance from center.
  11. # @return 2-tuple float type.
  12.  
  13. def randunit2_1(mindist):
  14. assert 0 <= mindist <= 1
  15. while True:
  16. x = randrange(-1, 1)
  17. y = randrange(-1, 1)
  18. if abs(x) >= mindist or abs(y) >= mindist:
  19. break
  20. return x, y
  21.  
  22. def randunit2_2(mindist):
  23. assert 0 <= mindist <= 1
  24.  
  25. # @note Find a random point on the perimeter of a unit square.
  26. # Use distance to select a random point along the vector from
  27. # origin to the perimeter.
  28. #
  29. # The square root will bias result toward the perimeter where
  30. # area is greater; prevents points 'bunching' near the center.
  31.  
  32. dist = math.sqrt(randrange(pow(mindist, 2), 1))
  33. t, s = math.modf(randrange(0, 4))
  34. x = 2*t - 1
  35. y = s%2*2 - 1
  36. if s < 2:
  37. x, y = y, x
  38. return x * dist, y * dist
  39.  
  40. # Main.
  41.  
  42. def unit_to_norm(x):
  43. return x * 0.5 + 0.5
  44.  
  45. def grouper(iterable, n):
  46. return zip(*[iter(iterable)] * n)
  47.  
  48. def show(n, f, d):
  49. h = [0] * 9
  50. for _ in range(n*9):
  51. x, y = map(unit_to_norm, f(d))
  52. i = math.floor(x * 3)
  53. j = math.floor(y * 3)
  54. k = j*3+i
  55. assert 0 <= k < 9
  56. h[k] += 1
  57. print(f.__name__)
  58. for x in grouper((x/n for x in h), 3):
  59. print(' (', ', '.join(f'{y:.2f}' for y in x), ')', sep='')
  60.  
  61. n = 1000
  62. d = 1/3
  63. show(n, randunit2_1, d)
  64. show(n, randunit2_2, d)
Success #stdin #stdout 0.15s 14304KB
stdin
Standard input is empty
stdout
randunit2_1
 (1.14, 1.09, 1.12)
 (1.08, 0.00, 1.14)
 (1.17, 1.14, 1.11)
randunit2_2
 (1.10, 1.13, 1.09)
 (1.14, 0.00, 1.13)
 (1.11, 1.15, 1.15)