Решение на Питоните хапят! от Йордан Джамбазов

Обратно към всички решения

Към профила на Йордан Джамбазов

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 10 успешни тест(а)
  • 3 неуспешни тест(а)

Код

import copy
import operator
import math
class Vec2D:
"""2d vector class, supports vector and scalar operators."""
__slots__ = ['x', 'y']
def __init__(self, x_or_pair, y=None):
if y is None:
self.x = x_or_pair[0]
self.y = x_or_pair[1]
else:
self.x = x_or_pair
self.y = y
def __len__(self):
return 2
def __getitem__(self, key):
if key == 0:
return self.x
elif key == 1:
return self.y
else:
raise IndexError("Invalid subscript "+str(key)+" to Vec2D")
def __setitem__(self, key, value):
if key == 0:
self.x = value
elif key == 1:
self.y = value
else:
raise IndexError("Invalid subscript "+str(key)+" to Vec2D")
# String representation (for debugging)
def __repr__(self):
return 'Vec2D(%s, %s)' % (self.x, self.y)
# Comparison
def __eq__(self, other):
if hasattr(other, "__getitem__") and len(other) == 2:
return self.x == other[0] and self.y == other[1]
else:
return False
def __ne__(self, other):
if hasattr(other, "__getitem__") and len(other) == 2:
return self.x != other[0] or self.y != other[1]
else:
return True
def __nonzero__(self):
return bool(self.x or self.y)
# Generic operator handlers
def _o2(self, other, f):
"Any two-operator operation where the left operand is a Vec2D"
if isinstance(other, Vec2D):
return Vec2D(f(self.x, other.x),
f(self.y, other.y))
elif (hasattr(other, "__getitem__")):
return Vec2D(f(self.x, other[0]),
f(self.y, other[1]))
else:
return Vec2D(f(self.x, other),
f(self.y, other))
def _r_o2(self, other, f):
"Any two-operator operation where the right operand is a Vec2D"
if (hasattr(other, "__getitem__")):
return Vec2D(f(other[0], self.x),
f(other[1], self.y))
else:
return Vec2D(f(other, self.x),
f(other, self.y))
def _io(self, other, f):
"inplace operator"
if (hasattr(other, "__getitem__")):
self.x = f(self.x, other[0])
self.y = f(self.y, other[1])
else:
self.x = f(self.x, other)
self.y = f(self.y, other)
return self
# Addition
def __add__(self, other):
if isinstance(other, Vec2D):
return Vec2D(self.x + other.x, self.y + other.y)
elif hasattr(other, "__getitem__"):
return Vec2D(self.x + other[0], self.y + other[1])
else:
return Vec2D(self.x + other, self.y + other)
__radd__ = __add__
def __iadd__(self, other):
if isinstance(other, Vec2D):
self.x += other.x
self.y += other.y
elif hasattr(other, "__getitem__"):
self.x += other[0]
self.y += other[1]
else:
self.x += other
self.y += other
return self
# Subtraction
def __sub__(self, other):
if isinstance(other, Vec2D):
return Vec2D(self.x - other.x, self.y - other.y)
elif (hasattr(other, "__getitem__")):
return Vec2D(self.x - other[0], self.y - other[1])
else:
return Vec2D(self.x - other, self.y - other)
def __rsub__(self, other):
if isinstance(other, Vec2D):
return Vec2D(other.x - self.x, other.y - self.y)
if (hasattr(other, "__getitem__")):
return Vec2D(other[0] - self.x, other[1] - self.y)
else:
return Vec2D(other - self.x, other - self.y)
def __isub__(self, other):
if isinstance(other, Vec2D):
self.x -= other.x
self.y -= other.y
elif (hasattr(other, "__getitem__")):
self.x -= other[0]
self.y -= other[1]
else:
self.x -= other
self.y -= other
return self
# Multiplication
def __mul__(self, other):
if isinstance(other, Vec2D):
return Vec2D(self.x*other.x, self.y*other.y)
if (hasattr(other, "__getitem__")):
return Vec2D(self.x*other[0], self.y*other[1])
else:
return Vec2D(self.x*other, self.y*other)
__rmul__ = __mul__
def __imul__(self, other):
if isinstance(other, Vec2D):
self.x *= other.x
self.y *= other.y
elif (hasattr(other, "__getitem__")):
self.x *= other[0]
self.y *= other[1]
else:
self.x *= other
self.y *= other
return self
# Division
def __div__(self, other):
return self._o2(other, operator.truediv)
def __rdiv__(self, other):
return self._r_o2(other, operator.truediv)
def __idiv__(self, other):
return self._io(other, operator.truediv)
def __floordiv__(self, other):
return self._o2(other, operator.floordiv)
def __rfloordiv__(self, other):
return self._r_o2(other, operator.floordiv)
def __ifloordiv__(self, other):
return self._io(other, operator.floordiv)
def __truediv__(self, other):
return self._o2(other, operator.truediv)
def __rtruediv__(self, other):
return self._r_o2(other, operator.truediv)
def __itruediv__(self, other):
return self._io(other, operator.floordiv)
# Modulo
def __mod__(self, other):
return self._o2(other, operator.mod)
def __rmod__(self, other):
return self._r_o2(other, operator.mod)
def __divmod__(self, other):
return self._o2(other, operator.mod)
def __rdivmod__(self, other):
return self._r_o2(other, operator.mod)
# Power
def __pow__(self, other):
return self._o2(other, operator.pow)
def __rpow__(self, other):
return self._r_o2(other, operator.pow)
# Bitwise operators
def __lshift__(self, other):
return self._o2(other, operator.lshift)
def __rlshift__(self, other):
return self._r_o2(other, operator.lshift)
def __rshift__(self, other):
return self._o2(other, operator.rshift)
def __rrshift__(self, other):
return self._r_o2(other, operator.rshift)
def __and__(self, other):
return self._o2(other, operator.and_)
__rand__ = __and__
def __or__(self, other):
return self._o2(other, operator.or_)
__ror__ = __or__
def __xor__(self, other):
return self._o2(other, operator.xor)
__rxor__ = __xor__
# Unary operations
def __neg__(self):
return Vec2D(operator.neg(self.x), operator.neg(self.y))
def __pos__(self):
return Vec2D(operator.pos(self.x), operator.pos(self.y))
def __abs__(self):
return Vec2D(abs(self.x), abs(self.y))
def __invert__(self):
return Vec2D(-self.x, -self.y)
class Death(Exception):
pass
class World:
def __init__(self, width):
self.width = width
self.reset_rows()
def reset_rows(self):
width_range = range(self.width)
self.rows = [[Cell() for _ in width_range] for _ in width_range]
def update(self):
for y, row in enumerate(self.rows):
for x, cell in enumerate(row):
if not isinstance(cell.contents, Food):
self.rows[x][y] = Cell()
def __getitem__(self, key):
return self.rows[key]
def __setitem(self, key, value):
self.rows[key] = value
def __len__(self):
return self.width
class Cell:
def __init__(self, contents=None):
if contents is not None and not isinstance(contents, WorldObject):
raise TypeError
self.contents = contents
def is_empty(self):
return self.contents is None
class WorldObject:
coords = Vec2D(0, 0)
class Food(WorldObject):
def __init__(self, energy=0):
self.energy = energy
class PythonPart(WorldObject):
pass
class PythonHead(PythonPart):
pass
class Python:
LEFT = Vec2D(-1, 0)
RIGHT = Vec2D(1, 0)
UP = Vec2D(0, -1)
DOWN = Vec2D(0, 1)
def __init__(self, world, coords, size, direction):
self.world = world
self.coords = coords
self.size = size
self.direction = direction
self.energy = 0
self.build()
def build(self):
self.parts = []
for index in range(self.size):
if not index:
part = PythonHead()
part.coords = self.coords
else:
last_part = self.parts[-1]
part = PythonPart()
part.coords = last_part.coords - self.direction
self.parts.append(part)
self.update()
def update(self):
self.world.update()
for part in self.parts:
x = part.coords[0]
y = part.coords[1]
self.world[x][y].contents = part
def eat(self, food):
self.size += 1
self.parts.append(PythonPart())
def detect_collision(self):
head = self.parts[0]
new_coords = head.coords + self.direction
x = new_coords.x
y = new_coords.y
width = self.world.width
if x < 0 or y < 0 or x >= width or y >= width:
raise Death("You hit the border of the area!")
world_object = self.world[x][y].contents
if isinstance(world_object, Food):
self.eat(world_object)
if isinstance(world_object, PythonPart):
raise Death("Your Snake moved to another part if it.")
def move(self, direction):
if (direction * -1) == self.direction:
raise ValueError("Trying to move in opposite direction")
self.direction = direction
old_coords = copy.deepcopy([part.coords for part in self.parts])
for index, part in enumerate(self.parts):
if isinstance(part, PythonHead):
self.detect_collision()
self.parts[index].coords += direction
else:
self.parts[index].coords = old_coords[index-1]
self.update()

Лог от изпълнението

..FF.F.......
======================================================================
FAIL: test_ouroboros_death (test.PythonTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lib/language/python/runner.py", line 60, in thread
    raise it.exc_info[1]
  File "lib/language/python/runner.py", line 48, in run
    self.result = func(*args, **kwargs)
  File "/tmp/d20130606-14014-th9afj/test.py", line 47, in test_ouroboros_death
    py.move(Python.DOWN)
AssertionError: Death not raised

======================================================================
FAIL: test_python_movement_basic (test.PythonTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lib/language/python/runner.py", line 60, in thread
    raise it.exc_info[1]
  File "lib/language/python/runner.py", line 48, in run
    self.result = func(*args, **kwargs)
  File "/tmp/d20130606-14014-th9afj/test.py", line 35, in test_python_movement_basic
    self.assertIsInstance(world[x][y].contents, PythonPart)
AssertionError: None is not an instance of <class 'solution.PythonPart'>

======================================================================
FAIL: test_snake_death (test.PythonTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lib/language/python/runner.py", line 60, in thread
    raise it.exc_info[1]
  File "lib/language/python/runner.py", line 48, in run
    self.result = func(*args, **kwargs)
  File "/tmp/d20130606-14014-th9afj/test.py", line 76, in test_snake_death
    self.assertTrue(cartesian_coord or screen_coord)
AssertionError: False is not true

----------------------------------------------------------------------
Ran 13 tests in 0.083s

FAILED (failures=3)

История (1 версия и 0 коментара)

Йордан обнови решението на 15.05.2013 13:59 (преди над 11 години)

+import copy
+import operator
+import math
+
+
+class Vec2D:
+ """2d vector class, supports vector and scalar operators."""
+ __slots__ = ['x', 'y']
+
+ def __init__(self, x_or_pair, y=None):
+ if y is None:
+ self.x = x_or_pair[0]
+ self.y = x_or_pair[1]
+ else:
+ self.x = x_or_pair
+ self.y = y
+
+ def __len__(self):
+ return 2
+
+ def __getitem__(self, key):
+ if key == 0:
+ return self.x
+ elif key == 1:
+ return self.y
+ else:
+ raise IndexError("Invalid subscript "+str(key)+" to Vec2D")
+
+ def __setitem__(self, key, value):
+ if key == 0:
+ self.x = value
+ elif key == 1:
+ self.y = value
+ else:
+ raise IndexError("Invalid subscript "+str(key)+" to Vec2D")
+
+ # String representation (for debugging)
+ def __repr__(self):
+ return 'Vec2D(%s, %s)' % (self.x, self.y)
+
+ # Comparison
+ def __eq__(self, other):
+ if hasattr(other, "__getitem__") and len(other) == 2:
+ return self.x == other[0] and self.y == other[1]
+ else:
+ return False
+
+ def __ne__(self, other):
+ if hasattr(other, "__getitem__") and len(other) == 2:
+ return self.x != other[0] or self.y != other[1]
+ else:
+ return True
+
+ def __nonzero__(self):
+ return bool(self.x or self.y)
+
+ # Generic operator handlers
+ def _o2(self, other, f):
+ "Any two-operator operation where the left operand is a Vec2D"
+ if isinstance(other, Vec2D):
+ return Vec2D(f(self.x, other.x),
+ f(self.y, other.y))
+ elif (hasattr(other, "__getitem__")):
+ return Vec2D(f(self.x, other[0]),
+ f(self.y, other[1]))
+ else:
+ return Vec2D(f(self.x, other),
+ f(self.y, other))
+
+ def _r_o2(self, other, f):
+ "Any two-operator operation where the right operand is a Vec2D"
+ if (hasattr(other, "__getitem__")):
+ return Vec2D(f(other[0], self.x),
+ f(other[1], self.y))
+ else:
+ return Vec2D(f(other, self.x),
+ f(other, self.y))
+
+ def _io(self, other, f):
+ "inplace operator"
+ if (hasattr(other, "__getitem__")):
+ self.x = f(self.x, other[0])
+ self.y = f(self.y, other[1])
+ else:
+ self.x = f(self.x, other)
+ self.y = f(self.y, other)
+ return self
+
+ # Addition
+ def __add__(self, other):
+ if isinstance(other, Vec2D):
+ return Vec2D(self.x + other.x, self.y + other.y)
+ elif hasattr(other, "__getitem__"):
+ return Vec2D(self.x + other[0], self.y + other[1])
+ else:
+ return Vec2D(self.x + other, self.y + other)
+ __radd__ = __add__
+
+ def __iadd__(self, other):
+ if isinstance(other, Vec2D):
+ self.x += other.x
+ self.y += other.y
+ elif hasattr(other, "__getitem__"):
+ self.x += other[0]
+ self.y += other[1]
+ else:
+ self.x += other
+ self.y += other
+ return self
+
+ # Subtraction
+ def __sub__(self, other):
+ if isinstance(other, Vec2D):
+ return Vec2D(self.x - other.x, self.y - other.y)
+ elif (hasattr(other, "__getitem__")):
+ return Vec2D(self.x - other[0], self.y - other[1])
+ else:
+ return Vec2D(self.x - other, self.y - other)
+
+ def __rsub__(self, other):
+ if isinstance(other, Vec2D):
+ return Vec2D(other.x - self.x, other.y - self.y)
+ if (hasattr(other, "__getitem__")):
+ return Vec2D(other[0] - self.x, other[1] - self.y)
+ else:
+ return Vec2D(other - self.x, other - self.y)
+
+ def __isub__(self, other):
+ if isinstance(other, Vec2D):
+ self.x -= other.x
+ self.y -= other.y
+ elif (hasattr(other, "__getitem__")):
+ self.x -= other[0]
+ self.y -= other[1]
+ else:
+ self.x -= other
+ self.y -= other
+ return self
+
+ # Multiplication
+ def __mul__(self, other):
+ if isinstance(other, Vec2D):
+ return Vec2D(self.x*other.x, self.y*other.y)
+ if (hasattr(other, "__getitem__")):
+ return Vec2D(self.x*other[0], self.y*other[1])
+ else:
+ return Vec2D(self.x*other, self.y*other)
+ __rmul__ = __mul__
+
+ def __imul__(self, other):
+ if isinstance(other, Vec2D):
+ self.x *= other.x
+ self.y *= other.y
+ elif (hasattr(other, "__getitem__")):
+ self.x *= other[0]
+ self.y *= other[1]
+ else:
+ self.x *= other
+ self.y *= other
+ return self
+
+ # Division
+ def __div__(self, other):
+ return self._o2(other, operator.truediv)
+
+ def __rdiv__(self, other):
+ return self._r_o2(other, operator.truediv)
+
+ def __idiv__(self, other):
+ return self._io(other, operator.truediv)
+
+ def __floordiv__(self, other):
+ return self._o2(other, operator.floordiv)
+
+ def __rfloordiv__(self, other):
+ return self._r_o2(other, operator.floordiv)
+
+ def __ifloordiv__(self, other):
+ return self._io(other, operator.floordiv)
+
+ def __truediv__(self, other):
+ return self._o2(other, operator.truediv)
+
+ def __rtruediv__(self, other):
+ return self._r_o2(other, operator.truediv)
+
+ def __itruediv__(self, other):
+ return self._io(other, operator.floordiv)
+
+ # Modulo
+ def __mod__(self, other):
+ return self._o2(other, operator.mod)
+
+ def __rmod__(self, other):
+ return self._r_o2(other, operator.mod)
+
+ def __divmod__(self, other):
+ return self._o2(other, operator.mod)
+
+ def __rdivmod__(self, other):
+ return self._r_o2(other, operator.mod)
+
+ # Power
+ def __pow__(self, other):
+ return self._o2(other, operator.pow)
+
+ def __rpow__(self, other):
+ return self._r_o2(other, operator.pow)
+
+ # Bitwise operators
+ def __lshift__(self, other):
+ return self._o2(other, operator.lshift)
+
+ def __rlshift__(self, other):
+ return self._r_o2(other, operator.lshift)
+
+ def __rshift__(self, other):
+ return self._o2(other, operator.rshift)
+
+ def __rrshift__(self, other):
+ return self._r_o2(other, operator.rshift)
+
+ def __and__(self, other):
+ return self._o2(other, operator.and_)
+ __rand__ = __and__
+
+ def __or__(self, other):
+ return self._o2(other, operator.or_)
+ __ror__ = __or__
+
+ def __xor__(self, other):
+ return self._o2(other, operator.xor)
+ __rxor__ = __xor__
+
+ # Unary operations
+ def __neg__(self):
+ return Vec2D(operator.neg(self.x), operator.neg(self.y))
+
+ def __pos__(self):
+ return Vec2D(operator.pos(self.x), operator.pos(self.y))
+
+ def __abs__(self):
+ return Vec2D(abs(self.x), abs(self.y))
+
+ def __invert__(self):
+ return Vec2D(-self.x, -self.y)
+
+
+class Death(Exception):
+ pass
+
+
+class World:
+ def __init__(self, width):
+ self.width = width
+ self.reset_rows()
+
+ def reset_rows(self):
+ width_range = range(self.width)
+ self.rows = [[Cell() for _ in width_range] for _ in width_range]
+
+ def update(self):
+ for y, row in enumerate(self.rows):
+ for x, cell in enumerate(row):
+ if not isinstance(cell.contents, Food):
+ self.rows[x][y] = Cell()
+
+ def __getitem__(self, key):
+ return self.rows[key]
+
+ def __setitem(self, key, value):
+ self.rows[key] = value
+
+ def __len__(self):
+ return self.width
+
+
+class Cell:
+ def __init__(self, contents=None):
+ if contents is not None and not isinstance(contents, WorldObject):
+ raise TypeError
+ self.contents = contents
+
+ def is_empty(self):
+ return self.contents is None
+
+
+class WorldObject:
+ coords = Vec2D(0, 0)
+
+
+class Food(WorldObject):
+ def __init__(self, energy=0):
+ self.energy = energy
+
+
+class PythonPart(WorldObject):
+ pass
+
+
+class PythonHead(PythonPart):
+ pass
+
+
+class Python:
+ LEFT = Vec2D(-1, 0)
+ RIGHT = Vec2D(1, 0)
+ UP = Vec2D(0, -1)
+ DOWN = Vec2D(0, 1)
+
+ def __init__(self, world, coords, size, direction):
+ self.world = world
+ self.coords = coords
+ self.size = size
+ self.direction = direction
+ self.energy = 0
+ self.build()
+
+ def build(self):
+ self.parts = []
+ for index in range(self.size):
+ if not index:
+ part = PythonHead()
+ part.coords = self.coords
+ else:
+ last_part = self.parts[-1]
+ part = PythonPart()
+ part.coords = last_part.coords - self.direction
+ self.parts.append(part)
+ self.update()
+
+ def update(self):
+ self.world.update()
+ for part in self.parts:
+ x = part.coords[0]
+ y = part.coords[1]
+ self.world[x][y].contents = part
+
+ def eat(self, food):
+ self.size += 1
+ self.parts.append(PythonPart())
+
+ def detect_collision(self):
+ head = self.parts[0]
+ new_coords = head.coords + self.direction
+ x = new_coords.x
+ y = new_coords.y
+ width = self.world.width
+ if x < 0 or y < 0 or x >= width or y >= width:
+ raise Death("You hit the border of the area!")
+ world_object = self.world[x][y].contents
+ if isinstance(world_object, Food):
+ self.eat(world_object)
+ if isinstance(world_object, PythonPart):
+ raise Death("Your Snake moved to another part if it.")
+
+ def move(self, direction):
+ if (direction * -1) == self.direction:
+ raise ValueError("Trying to move in opposite direction")
+
+ self.direction = direction
+ old_coords = copy.deepcopy([part.coords for part in self.parts])
+ for index, part in enumerate(self.parts):
+ if isinstance(part, PythonHead):
+ self.detect_collision()
+ self.parts[index].coords += direction
+ else:
+ self.parts[index].coords = old_coords[index-1]
+ self.update()