fork download
  1. import math
  2.  
  3. class Point(object):
  4. def __init__(self, *args, **kargs):
  5. self.num_dimensions = kargs.get("num_dimensions", len(args))
  6. self.coords = [0 for i in range(self.num_dimensions)]
  7. for i in range(len(args)):
  8. self.coords[i] = args[i]
  9. def magnitude(self):
  10. return math.sqrt(sum(c*c for c in self.coords))
  11. def angle(self):
  12. assert self.num_dimensions == 2
  13. assert self.x != 0 or self.y != 0
  14. return math.atan2(self.y,self.x)
  15. def tuple(self):
  16. return tuple(self.coords)
  17. def map(self, func):
  18. new_coords = [func(a) for a in self.coords]
  19. return Point(*new_coords)
  20. def _applyVectorFunc(self, other, f):
  21. assert self.num_dimensions == other.num_dimensions
  22. new_coords = [f(a,b) for a,b in zip(self.coords, other.coords)]
  23. return Point(*new_coords)
  24. def _applyScalarFunc(self, val, f):
  25. return self.map(lambda a: f(a,val))
  26. """
  27. new_coords = [f(a, val) for a in self.coords]
  28. return Point(*new_coords)
  29. """
  30.  
  31. def normalized(self):
  32. return self.__div__(self.magnitude())
  33.  
  34. def __add__(self, other):
  35. return self._applyVectorFunc(other, lambda a,b: a+b)
  36. def __sub__(self, other):
  37. return self._applyVectorFunc(other, lambda a,b: a-b)
  38. def __mul__(self, a):
  39. return self._applyScalarFunc(a, lambda b,c: b*c)
  40. def __div__(self, a):
  41. return self._applyScalarFunc(a, lambda b,c: b/c)
  42.  
  43. def __eq__(self, other):
  44. try:
  45. return self.num_dimensions == other.num_dimensions and self.coords == other.coords
  46. except:
  47. return False
  48.  
  49. def __ne__(self, other):
  50. return not(self == other)
  51.  
  52. def __getattr__(self, name):
  53. if name == "x": return self.coords[0]
  54. if name == "y": return self.coords[1]
  55. if name == "z": return self.coords[2]
  56. raise AttributeError(name)
  57. def __setattr__(self, name, value):
  58. if name == "x": self.coords[0] = value
  59. elif name == "y": self.coords[1] = value
  60. elif name == "z": self.coords[2] = value
  61. else: object.__setattr__(self, name, value)
  62. def copy(self):
  63. return Point(*self.coords[:])
  64. def __hash__(self):
  65. return hash(self.tuple())
  66. def __repr__(self):
  67. use_nice_floats = False
  68. if use_nice_floats:
  69. return "Point(" + ", ".join("%.1f" % c for c in self.coords) + ")"
  70. else:
  71. return "Point(" + ", ".join(str(c) for c in self.coords) + ")"
  72.  
  73. def to_radians(x):
  74. return math.pi * 2 * x / 360.0
  75.  
  76. #converts from hex grid coordinates to screen coordinates.
  77. #assumes that the hexagons have a minor radius of 1.
  78. def hex_to_screen(p):
  79. y = 2 * p.y * math.sin(to_radians(60))
  80. x = 2 * ((p.y * math.cos(to_radians(60))) + p.x)
  81. return Point(x,y)
  82.  
  83. #finds the coordinates of the center of each circle of `minor` radius that can fit in a circle of `major` radius.
  84. def get_centers(major, minor):
  85. assert major > minor
  86. extent = int(2 * major / minor)
  87. for i in range(-extent, extent):
  88. for j in range(-extent, extent):
  89. p = hex_to_screen(Point(i,j)) * minor
  90. if p.magnitude() + minor <= major:
  91. yield p
  92.  
  93. mm_per_inch = 25.4
  94. values = [1, 2, 5, 10, 20, 50, 100, 200]
  95. diameters = [20.3, 25.9, 18.0, 24.5, 21.4, 27.3, 22.5, 28.4]
  96. for value, diameter in zip(values, diameters):
  97. for major_diameter in [12, 14]:
  98. major_radius = major_diameter * mm_per_inch / 2
  99. count = len(list(get_centers(major_radius, diameter/2)))
  100. cost = count * value / 100.0
  101. print "{} pence coin on {}\" pizza: {} coins, {} pounds".format(value, major_diameter, count, cost)
Success #stdin #stdout 1.53s 7692KB
stdin
Standard input is empty
stdout
1 pence coin on 12" pizza: 187 coins, 1.87 pounds
1 pence coin on 14" pizza: 253 coins, 2.53 pounds
2 pence coin on 12" pizza: 109 coins, 2.18 pounds
2 pence coin on 14" pizza: 151 coins, 3.02 pounds
5 pence coin on 12" pizza: 235 coins, 11.75 pounds
5 pence coin on 14" pizza: 313 coins, 15.65 pounds
10 pence coin on 12" pizza: 121 coins, 12.1 pounds
10 pence coin on 14" pizza: 163 coins, 16.3 pounds
20 pence coin on 12" pizza: 163 coins, 32.6 pounds
20 pence coin on 14" pizza: 211 coins, 42.2 pounds
50 pence coin on 12" pizza: 91 coins, 45.5 pounds
50 pence coin on 14" pizza: 127 coins, 63.5 pounds
100 pence coin on 12" pizza: 151 coins, 151.0 pounds
100 pence coin on 14" pizza: 199 coins, 199.0 pounds
200 pence coin on 12" pizza: 85 coins, 170.0 pounds
200 pence coin on 14" pizza: 121 coins, 242.0 pounds