Решение на Питоните хапят! от Илия Ячев

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

Към профила на Илия Ячев

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 12 успешни тест(а)
  • 1 неуспешни тест(а)

Код

from collections import namedtuple, deque
class Vec2D(namedtuple('Vec2D', 'x y')):
def __add__(self, other):
return Vec2D(self.x + other.x, self.y + other.y)
def __neg__(self):
return Vec2D(-self.x, -self.y)
def __sub__(self, other):
return self + -other
def __mul__(self, other):
return Vec2D(self.x * other, self.y * other)
def are_inside_world_with_size(self, size):
return self.x in range(size) and self.y in range(size)
class WorldObject:
pass
class Food(WorldObject):
def __init__(self, energy=0):
self.energy = energy
class Cell():
def __init__(self, contents=None):
if not isinstance(contents, (WorldObject, type(None))):
raise TypeError
self.contents = contents
def is_empty(self):
return self.contents is None
def empty(self):
self.contents = None
def contains(self, type_):
return isinstance(self.contents, type_)
class FixedArray:
def __init__(self, list_):
self.range = range(len(list_))
self.list = list_
def __getitem__(self, key):
if key in self.range:
return self.list[key]
else:
raise IndexError
def __setitem__(self, key, value):
if key in self.range:
self.list[key] = value
else:
raise IndexError
class World():
def __init__(self, width):
self.width = width
self.matrix = FixedArray([FixedArray(
[Cell() for y in range(width)]) for x in range(width)])
def __len__(self):
return self.width
def __getitem__(self, key):
if isinstance(key, Vec2D):
return self.matrix[key.x][key.y]
else:
return self.matrix[key]
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, self.size, self.direction = world, size, direction
self.energy = 0
self.body_coords = deque(
[coords - direction * i for i in range(size + 1)])
for coords in self.body_coords:
self.world[coords].contents = PythonPart(self)
self.head = PythonHead(self)
self.world[self.body_coords[0]].contents = self.head
def eat(self, food):
self.energy += food.energy
self.size += 1
def move(self, direction):
if direction == self.direction * (-1):
raise ValueError("Cannot go in opposite direction")
new_coords = self.body_coords[0] + direction
if not new_coords.are_inside_world_with_size(len(self.world)):
raise Death("You went to another world")
if self.world[new_coords].contains(Food):
self.eat(self.world[new_coords].contents)
elif (self.world[new_coords].is_empty() or
new_coords == self.body_coords[-1]):
self.world[self.body_coords.pop()].empty()
else:
raise Death("You bumped into something")
self.direction = direction
self.body_coords.appendleft(new_coords)
self.world[self.body_coords[0]].contents = self.head
self.world[self.body_coords[1]].contents = PythonPart(self)
class PythonPart(WorldObject):
def __init__(self, owner):
self.owner = owner
class PythonHead(PythonPart):
pass
class Death(Exception):
pass

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

..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-t3a0xo/test.py", line 47, in test_ouroboros_death
    py.move(Python.DOWN)
AssertionError: Death not raised

----------------------------------------------------------------------
Ran 13 tests in 0.058s

FAILED (failures=1)

История (4 версии и 2 коментара)

Илия обнови решението на 11.05.2013 23:22 (преди над 11 години)

+from collections import namedtuple, deque
+
+
+class Vec2D(namedtuple('Vec2D', 'x y')):
+
+ def __add__(self, other):
+ return Vec2D(self.x + other.x, self.y + other.y)
+
+ def __sub__(self, other):
+ return Vec2D(self.x - other.x, self.y - other.y)
+
+ def __mul__(self, other):
+ return Vec2D(self.x * other, self.y * other)
+
+ def are_inside_world_with_size(self, size):
+ return self.x in range(size) and self.y in range(size)
+
+
+class WorldObject:
+ pass
+
+
+class Food(WorldObject):
+
+ def __init__(self, energy=0):
+ self.energy = energy
+
+
+class Cell():
+
+ def __init__(self, contents=None):
+ if not isinstance(contents, (WorldObject, type(None))):
+ raise TypeError
+ self.contents = contents
+
+ def is_empty(self):
+ return self.contents is None
+
+ def empty(self):
+ self.contents = None
+
+ def contains(self, type_):
+ return isinstance(self.contents, type_)
+
+
+class World():
+
+ def __init__(self, width):
+ self.width = width
+ self.matrix = [[Cell() for y in range(width)] for x in range(width)]
+
+ def __len__(self):
+ return self.width
+
+ def __getitem__(self, key):
+ if isinstance(key, Vec2D):
+ return self.matrix[key.y][key.x]
+ return self.matrix[key]
+
+
+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, self.size, self.direction = world, size, direction
+ self.energy = 0
+
+ self.body_coords = deque(
+ [coords - direction * i for i in range(size + 1)])
+ for coords in self.body_coords:
+ self.world[coords].contents = PythonPart(self)
+
+ self.head = PythonHead(self)
+ self.world[self.body_coords[0]].contents = self.head
+
+ def eat(self, food):
+ self.energy += food.energy
+ self.size += 1
+
+ def move(self, direction):
+ if direction == self.direction * (-1):
+ raise ValueError("Cannot go in opposite direction")
+
+ new_coords = self.body_coords[0] + direction
+
+ if not new_coords.are_inside_world_with_size(len(self.world)):
+ raise Death("You went to another world")
+
+ if self.world[new_coords].contains(Food):
+ self.eat(self.world[new_coords].contents)
+ elif self.world[new_coords].is_empty():
+ self.world[self.body_coords.pop()].empty()
+ else:
+ raise Death("You bumped into something")
+
+ self.body_coords.appendleft(new_coords)
+ self.world[self.body_coords[0]].contents = self.head
+ self.world[self.body_coords[1]].contents = PythonPart(self)
+
+
+class PythonPart(WorldObject):
+
+ def __init__(self, owner):
+ self.owner = owner
+
+
+class PythonHead(PythonPart):
+ pass
+
+
+class Death(Exception):
+ pass

Илия обнови решението на 12.05.2013 10:02 (преди над 11 години)

from collections import namedtuple, deque
class Vec2D(namedtuple('Vec2D', 'x y')):
def __add__(self, other):
return Vec2D(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vec2D(self.x - other.x, self.y - other.y)
def __mul__(self, other):
return Vec2D(self.x * other, self.y * other)
def are_inside_world_with_size(self, size):
return self.x in range(size) and self.y in range(size)
class WorldObject:
pass
class Food(WorldObject):
def __init__(self, energy=0):
self.energy = energy
class Cell():
def __init__(self, contents=None):
if not isinstance(contents, (WorldObject, type(None))):
raise TypeError
self.contents = contents
def is_empty(self):
return self.contents is None
def empty(self):
self.contents = None
def contains(self, type_):
return isinstance(self.contents, type_)
class World():
def __init__(self, width):
self.width = width
self.matrix = [[Cell() for y in range(width)] for x in range(width)]
def __len__(self):
return self.width
def __getitem__(self, key):
if isinstance(key, Vec2D):
- return self.matrix[key.y][key.x]
+ return self.matrix[key.x][key.y]
return self.matrix[key]
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, self.size, self.direction = world, size, direction
self.energy = 0
self.body_coords = deque(
[coords - direction * i for i in range(size + 1)])
for coords in self.body_coords:
self.world[coords].contents = PythonPart(self)
self.head = PythonHead(self)
self.world[self.body_coords[0]].contents = self.head
def eat(self, food):
self.energy += food.energy
self.size += 1
def move(self, direction):
if direction == self.direction * (-1):
raise ValueError("Cannot go in opposite direction")
new_coords = self.body_coords[0] + direction
if not new_coords.are_inside_world_with_size(len(self.world)):
raise Death("You went to another world")
if self.world[new_coords].contains(Food):
self.eat(self.world[new_coords].contents)
- elif self.world[new_coords].is_empty():
+ elif (self.world[new_coords].is_empty() or
+ new_coords == self.body_coords[-1]):
self.world[self.body_coords.pop()].empty()
else:
raise Death("You bumped into something")
self.body_coords.appendleft(new_coords)
self.world[self.body_coords[0]].contents = self.head
self.world[self.body_coords[1]].contents = PythonPart(self)
class PythonPart(WorldObject):
def __init__(self, owner):
self.owner = owner
class PythonHead(PythonPart):
pass
class Death(Exception):
pass

Илия обнови решението на 12.05.2013 15:49 (преди над 11 години)

from collections import namedtuple, deque
class Vec2D(namedtuple('Vec2D', 'x y')):
def __add__(self, other):
return Vec2D(self.x + other.x, self.y + other.y)
+ def __neg__(self):
+ return Vec2D(-self.x, -self.y)
+
def __sub__(self, other):
- return Vec2D(self.x - other.x, self.y - other.y)
+ return self + -other
def __mul__(self, other):
return Vec2D(self.x * other, self.y * other)
def are_inside_world_with_size(self, size):
return self.x in range(size) and self.y in range(size)
class WorldObject:
pass
class Food(WorldObject):
def __init__(self, energy=0):
self.energy = energy
class Cell():
def __init__(self, contents=None):
if not isinstance(contents, (WorldObject, type(None))):
raise TypeError
self.contents = contents
def is_empty(self):
return self.contents is None
def empty(self):
self.contents = None
def contains(self, type_):
return isinstance(self.contents, type_)
class World():
def __init__(self, width):
self.width = width
self.matrix = [[Cell() for y in range(width)] for x in range(width)]
def __len__(self):
return self.width
def __getitem__(self, key):
if isinstance(key, Vec2D):
return self.matrix[key.x][key.y]
return self.matrix[key]
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, self.size, self.direction = world, size, direction
self.energy = 0
self.body_coords = deque(
[coords - direction * i for i in range(size + 1)])
for coords in self.body_coords:
self.world[coords].contents = PythonPart(self)
self.head = PythonHead(self)
self.world[self.body_coords[0]].contents = self.head
def eat(self, food):
self.energy += food.energy
self.size += 1
def move(self, direction):
if direction == self.direction * (-1):
raise ValueError("Cannot go in opposite direction")
new_coords = self.body_coords[0] + direction
if not new_coords.are_inside_world_with_size(len(self.world)):
raise Death("You went to another world")
if self.world[new_coords].contains(Food):
self.eat(self.world[new_coords].contents)
elif (self.world[new_coords].is_empty() or
new_coords == self.body_coords[-1]):
self.world[self.body_coords.pop()].empty()
else:
raise Death("You bumped into something")
+ self.direction = direction
self.body_coords.appendleft(new_coords)
self.world[self.body_coords[0]].contents = self.head
self.world[self.body_coords[1]].contents = PythonPart(self)
class PythonPart(WorldObject):
def __init__(self, owner):
self.owner = owner
class PythonHead(PythonPart):
pass
class Death(Exception):
pass

Илия обнови решението на 15.05.2013 01:20 (преди над 11 години)

from collections import namedtuple, deque
class Vec2D(namedtuple('Vec2D', 'x y')):
def __add__(self, other):
return Vec2D(self.x + other.x, self.y + other.y)
def __neg__(self):
return Vec2D(-self.x, -self.y)
def __sub__(self, other):
return self + -other
def __mul__(self, other):
return Vec2D(self.x * other, self.y * other)
def are_inside_world_with_size(self, size):
return self.x in range(size) and self.y in range(size)
class WorldObject:
pass
class Food(WorldObject):
def __init__(self, energy=0):
self.energy = energy
class Cell():
def __init__(self, contents=None):
if not isinstance(contents, (WorldObject, type(None))):
raise TypeError
self.contents = contents
def is_empty(self):
return self.contents is None
def empty(self):
self.contents = None
def contains(self, type_):
return isinstance(self.contents, type_)
+class FixedArray:
+
+ def __init__(self, list_):
+ self.range = range(len(list_))
+ self.list = list_
+
+ def __getitem__(self, key):
+ if key in self.range:
+ return self.list[key]
+ else:
+ raise IndexError
+
+ def __setitem__(self, key, value):
+ if key in self.range:
+ self.list[key] = value
+ else:
+ raise IndexError
+
+
class World():
def __init__(self, width):
self.width = width
- self.matrix = [[Cell() for y in range(width)] for x in range(width)]
+ self.matrix = FixedArray([FixedArray(
+ [Cell() for y in range(width)]) for x in range(width)])
def __len__(self):
return self.width
def __getitem__(self, key):
if isinstance(key, Vec2D):
return self.matrix[key.x][key.y]
- return self.matrix[key]
+ else:
+ return self.matrix[key]
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, self.size, self.direction = world, size, direction
self.energy = 0
self.body_coords = deque(
[coords - direction * i for i in range(size + 1)])
for coords in self.body_coords:
self.world[coords].contents = PythonPart(self)
self.head = PythonHead(self)
self.world[self.body_coords[0]].contents = self.head
def eat(self, food):
self.energy += food.energy
self.size += 1
def move(self, direction):
if direction == self.direction * (-1):
raise ValueError("Cannot go in opposite direction")
new_coords = self.body_coords[0] + direction
if not new_coords.are_inside_world_with_size(len(self.world)):
raise Death("You went to another world")
if self.world[new_coords].contains(Food):
self.eat(self.world[new_coords].contents)
elif (self.world[new_coords].is_empty() or
new_coords == self.body_coords[-1]):
self.world[self.body_coords.pop()].empty()
else:
raise Death("You bumped into something")
self.direction = direction
self.body_coords.appendleft(new_coords)
self.world[self.body_coords[0]].contents = self.head
self.world[self.body_coords[1]].contents = PythonPart(self)
class PythonPart(WorldObject):
def __init__(self, owner):
self.owner = owner
class PythonHead(PythonPart):
pass
class Death(Exception):
pass

Това за самоизяждането ми хареса. Иначе направих и промяна да не се поддържат отрицателни координати, макар че според мен си беше ок и да се поддържат. За останалите случаи самия list си хвърляше IndexError-и, а така според мен имам един излишен клас само заради онова нещо.

Опитах се по някакъв начин да затворя всичко в getitem метода на World, но не знаех дали ще се хареса и затова го направих по класическия начин.

Между другото забавно нещо - Markdown ми разпозна дъндър метода като негов синтаксис и го болдна :smile: