Решение на Питоните хапят! от Мартин Маринов

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

Към профила на Мартин Маринов

Резултати

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

Код

from collections import deque
import operator
class Death(Exception):
pass
class MyValidatingList(list):
def __getitem__(self, key):
if not key in range(len(self)):
raise IndexError()
return super(MyValidatingList, self).__getitem__(key)
def __setitem__(self, key, value):
if not key in range(len(self)):
raise IndexError()
return super(MyValidatingList, self).__setitem__(key, value)
class World:
def __init__(self, width):
self.width = width
self.__init_board()
def __init_board(self):
self.__board = MyValidatingList()
for i in range(self.width):
column = MyValidatingList()
for j in range(self.width):
column.append(Cell())
self.__board.append(column)
def __len__(self):
return self.width
def __str__(self):
s = ''
for row in reversed(tuple(zip(*self.__board))):
s += ''.join(str(cell) for cell in row) + '\n'
return s
def __getitem__(self, key):
return self.__board[key]
class Cell:
EMPTY_CELL = '..'
def __init__(self, contents=None):
if not isinstance(contents, WorldObject) and not contents is None:
self.contents = None
raise TypeError("Invalid cell contents type")
self.contents = contents
def is_empty(self):
return self.contents is None
def __str__(self):
if self.is_empty():
return self.EMPTY_CELL
else:
return str(self.contents)
class WorldObject:
def __str__(self):
return self.CHARS
def __repr__(self):
return '%s at v(%d, %d)' % (self.__class__.__name__,
self.coords.x,
self.coords.y)
class Food(WorldObject):
CHARS = ':3'
def __init__(self, energy=0):
self.__energy = energy
@property
def energy(self):
return self.__energy
class Vec2D(tuple):
x = property(operator.itemgetter(0))
y = property(operator.itemgetter(1))
def __new__(cls, x, y):
return super(Vec2D, cls).__new__(Vec2D, (x, y))
def __add__(self, other):
return Vec2D(self.x+other.x, self.y+other.y)
def __mul__(self, scalar):
if not isinstance(scalar, int):
raise TypeError("Can't multiply Vec2D with a non-int type object")
return Vec2D(self.x*scalar, self.y*scalar)
def fits_in_world(self, world):
valid_coords = range(len(world))
return self.x in valid_coords and self.y in valid_coords
class PythonPart(WorldObject):
CHARS = '##'
def __init__(self, coords):
super(PythonPart, self).__init__()
self.coords = coords
class PythonHead(PythonPart):
CHARS = '@@'
class Python:
LEFT = Vec2D(-1, 0)
RIGHT = Vec2D(1, 0)
UP = Vec2D(0, 1)
DOWN = Vec2D(0, -1)
OPPOSITE_DIRECTION = {LEFT: RIGHT,
RIGHT: LEFT,
UP: DOWN,
DOWN: UP}
def __init__(self, world, coords, size, direction, energy=0):
self.world = world
self.coords = coords
self.size = size
self.direction = direction
self.energy = energy
## Init the head
self.head = PythonHead(coords)
self.world[coords.x][coords.y] = Cell(self.head)
## Init the body
self.__init_body(self.OPPOSITE_DIRECTION[direction])
def move(self, direction):
self.__validate_move(direction)
self.direction = direction
self.__move_head(direction)
self.__move_body(direction)
def __init_body(self, direction):
self.body = deque()
for i in range(1, self.size + 1):
part_coords = self.coords+direction*i
part = PythonPart(part_coords)
self.body.append(part)
self.world[part_coords.x][part_coords.y] = Cell(part)
def __move_head(self, direction):
self.head.coords = self.coords = self.coords + direction
self.world[self.coords.x][self.coords.y] = Cell(self.head)
def __move_body(self, direction):
old_coords = self.head.coords + self.OPPOSITE_DIRECTION[direction]
if self.size != len(self.body): # Body has increased
part = PythonPart(old_coords)
self.world[old_coords.x][old_coords.y] = Cell(part)
else:
last_part = self.body[-1]
self.world[last_part.coords.x][last_part.coords.y] = Cell()
last_part.coords = old_coords
self.body.appendleft(last_part)
self.body.pop()
def __validate_move(self, direction):
new_coords = self.coords + direction
if not new_coords.fits_in_world(self.world):
raise Death()
new_cell = self.world[new_coords.x][new_coords.y]
if isinstance(new_cell.contents, PythonPart):
raise Death()
elif isinstance(new_cell.contents, Food):
self.size += 1
self.energy += new_cell.contents.energy

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

.E.EE........
======================================================================
ERROR: test_move_backwards (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-14b8zr/test.py", line 105, in test_move_backwards
    py.move(-direction)
TypeError: bad operand type for unary -: 'Vec2D'

======================================================================
ERROR: 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-14b8zr/test.py", line 34, in test_python_movement_basic
    x, y = Vec2D(10, 10) - direction * part_no
TypeError: unsupported operand type(s) for -: 'Vec2D' and 'Vec2D'

======================================================================
ERROR: test_python_placement (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-14b8zr/test.py", line 18, in test_python_placement
    x, y = position - direction
TypeError: unsupported operand type(s) for -: 'Vec2D' and 'Vec2D'

----------------------------------------------------------------------
Ran 13 tests in 0.050s

FAILED (errors=3)

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

Мартин обнови решението на 15.05.2013 02:26 (преди почти 11 години)

+from collections import deque
+import operator
+
+
+class Death(Exception):
+ pass
+
+
+class MyValidatingList(list):
+ def __getitem__(self, key):
+ if not key in range(len(self)):
+ raise IndexError()
+ return super(MyValidatingList, self).__getitem__(key)
+
+ def __setitem__(self, key, value):
+ if not key in range(len(self)):
+ raise IndexError()
+ return super(MyValidatingList, self).__setitem__(key, value)
+
+
+class World:
+ def __init__(self, width):
+ self.width = width
+ self.__init_board()
+
+ def __init_board(self):
+ self.__board = MyValidatingList()
+ for i in range(self.width):
+ column = MyValidatingList()
+ for j in range(self.width):
+ column.append(Cell())
+ self.__board.append(column)
+
+ def __len__(self):
+ return self.width
+
+ def __str__(self):
+ s = ''
+ for row in reversed(tuple(zip(*self.__board))):
+ s += ''.join(str(cell) for cell in row) + '\n'
+ return s
+
+ def __getitem__(self, key):
+ return self.__board[key]
+
+
+class Cell:
+ EMPTY_CELL = '..'
+
+ def __init__(self, contents=None):
+ if not isinstance(contents, WorldObject) and not contents is None:
+ self.contents = None
+ raise TypeError("Invalid cell contents type")
+ self.contents = contents
+
+ def is_empty(self):
+ return self.contents is None
+
+ def __str__(self):
+ if self.is_empty():
+ return self.EMPTY_CELL
+ else:
+ return str(self.contents)
+
+
+class WorldObject:
+
+ def __str__(self):
+ return self.CHARS
+
+ def __repr__(self):
+ return '%s at v(%d, %d)' % (self.__class__.__name__,
+ self.coords.x,
+ self.coords.y)
+
+
+class Food(WorldObject):
+ CHARS = ':3'
+
+ def __init__(self, energy=0):
+ self.__energy = energy
+
+ @property
+ def energy(self):
+ return self.__energy
+
+
+class Vec2D(tuple):
+ x = property(operator.itemgetter(0))
+ y = property(operator.itemgetter(1))
+
+ def __new__(cls, x, y):
+ return super(Vec2D, cls).__new__(Vec2D, (x, y))
+
+ def __add__(self, other):
+ return Vec2D(self.x+other.x, self.y+other.y)
+
+ def __mul__(self, scalar):
+ if not isinstance(scalar, int):
+ raise TypeError("Can't multiply Vec2D with a non-int type object")
+ return Vec2D(self.x*scalar, self.y*scalar)
+
+ def fits_in_world(self, world):
+ valid_coords = range(len(world))
+ return self.x in valid_coords and self.y in valid_coords
+
+
+class PythonPart(WorldObject):
+ CHARS = '##'
+
+ def __init__(self, coords):
+ super(PythonPart, self).__init__()
+ self.coords = coords
+
+
+class PythonHead(PythonPart):
+ CHARS = '@@'
+
+
+class Python:
+ LEFT = Vec2D(-1, 0)
+ RIGHT = Vec2D(1, 0)
+ UP = Vec2D(0, 1)
+ DOWN = Vec2D(0, -1)
+
+ OPPOSITE_DIRECTION = {LEFT: RIGHT,
+ RIGHT: LEFT,
+ UP: DOWN,
+ DOWN: UP}
+
+ def __init__(self, world, coords, size, direction, energy=0):
+ self.world = world
+ self.coords = coords
+ self.size = size
+ self.direction = direction
+ self.energy = energy
+ ## Init the head
+ self.head = PythonHead(coords)
+ self.world[coords.x][coords.y] = Cell(self.head)
+ ## Init the body
+ self.__init_body(self.OPPOSITE_DIRECTION[direction])
+
+ def move(self, direction):
+ self.__validate_move(direction)
+ self.__move_head(direction)
+ self.__move_body(direction)
+
+ def __init_body(self, direction):
+ self.body = deque()
+ for i in range(1, self.size + 1):
+ part_coords = self.coords+direction*i
+ part = PythonPart(part_coords)
+ self.body.append(part)
+ self.world[part_coords.x][part_coords.y] = Cell(part)
+
+ def __move_head(self, direction):
+ self.head.coords = self.coords = self.coords + direction
+ self.world[self.coords.x][self.coords.y] = Cell(self.head)
+
+ def __move_body(self, direction):
+ old_coords = self.head.coords + self.OPPOSITE_DIRECTION[direction]
+ if self.size != len(self.body): # Body has increased
+ part = PythonPart(old_coords)
+ self.world[old_coords.x][old_coords.y] = Cell(part)
+ else:
+ last_part = self.body[-1]
+ self.world[last_part.coords.x][last_part.coords.y] = Cell()
+ last_part.coords = old_coords
+ self.body.appendleft(last_part)
+ self.body.pop()
+
+ def __validate_move(self, direction):
+ new_coords = self.coords + direction
+ if not new_coords.fits_in_world(self.world):
+ raise Death()
+ new_cell = self.world[new_coords.x][new_coords.y]
+ if isinstance(new_cell.contents, PythonPart):
+ raise Death()
+ elif isinstance(new_cell.contents, Food):
+ self.size += 1
+ self.energy += new_cell.contents.energy

Мартин обнови решението на 15.05.2013 15:38 (преди почти 11 години)

from collections import deque
import operator
class Death(Exception):
pass
class MyValidatingList(list):
def __getitem__(self, key):
if not key in range(len(self)):
raise IndexError()
return super(MyValidatingList, self).__getitem__(key)
def __setitem__(self, key, value):
if not key in range(len(self)):
raise IndexError()
return super(MyValidatingList, self).__setitem__(key, value)
class World:
def __init__(self, width):
self.width = width
self.__init_board()
def __init_board(self):
self.__board = MyValidatingList()
for i in range(self.width):
column = MyValidatingList()
for j in range(self.width):
column.append(Cell())
self.__board.append(column)
def __len__(self):
return self.width
def __str__(self):
s = ''
for row in reversed(tuple(zip(*self.__board))):
s += ''.join(str(cell) for cell in row) + '\n'
return s
def __getitem__(self, key):
return self.__board[key]
class Cell:
EMPTY_CELL = '..'
def __init__(self, contents=None):
if not isinstance(contents, WorldObject) and not contents is None:
self.contents = None
raise TypeError("Invalid cell contents type")
self.contents = contents
def is_empty(self):
return self.contents is None
def __str__(self):
if self.is_empty():
return self.EMPTY_CELL
else:
return str(self.contents)
class WorldObject:
def __str__(self):
return self.CHARS
def __repr__(self):
return '%s at v(%d, %d)' % (self.__class__.__name__,
self.coords.x,
self.coords.y)
class Food(WorldObject):
CHARS = ':3'
def __init__(self, energy=0):
self.__energy = energy
@property
def energy(self):
return self.__energy
class Vec2D(tuple):
x = property(operator.itemgetter(0))
y = property(operator.itemgetter(1))
def __new__(cls, x, y):
return super(Vec2D, cls).__new__(Vec2D, (x, y))
def __add__(self, other):
return Vec2D(self.x+other.x, self.y+other.y)
def __mul__(self, scalar):
if not isinstance(scalar, int):
raise TypeError("Can't multiply Vec2D with a non-int type object")
return Vec2D(self.x*scalar, self.y*scalar)
def fits_in_world(self, world):
valid_coords = range(len(world))
return self.x in valid_coords and self.y in valid_coords
class PythonPart(WorldObject):
CHARS = '##'
def __init__(self, coords):
super(PythonPart, self).__init__()
self.coords = coords
class PythonHead(PythonPart):
CHARS = '@@'
class Python:
LEFT = Vec2D(-1, 0)
RIGHT = Vec2D(1, 0)
UP = Vec2D(0, 1)
DOWN = Vec2D(0, -1)
OPPOSITE_DIRECTION = {LEFT: RIGHT,
RIGHT: LEFT,
UP: DOWN,
DOWN: UP}
def __init__(self, world, coords, size, direction, energy=0):
self.world = world
self.coords = coords
self.size = size
self.direction = direction
self.energy = energy
## Init the head
self.head = PythonHead(coords)
self.world[coords.x][coords.y] = Cell(self.head)
## Init the body
self.__init_body(self.OPPOSITE_DIRECTION[direction])
def move(self, direction):
self.__validate_move(direction)
+ self.direction = direction
self.__move_head(direction)
self.__move_body(direction)
def __init_body(self, direction):
self.body = deque()
for i in range(1, self.size + 1):
part_coords = self.coords+direction*i
part = PythonPart(part_coords)
self.body.append(part)
self.world[part_coords.x][part_coords.y] = Cell(part)
def __move_head(self, direction):
self.head.coords = self.coords = self.coords + direction
self.world[self.coords.x][self.coords.y] = Cell(self.head)
def __move_body(self, direction):
old_coords = self.head.coords + self.OPPOSITE_DIRECTION[direction]
if self.size != len(self.body): # Body has increased
part = PythonPart(old_coords)
self.world[old_coords.x][old_coords.y] = Cell(part)
else:
last_part = self.body[-1]
self.world[last_part.coords.x][last_part.coords.y] = Cell()
last_part.coords = old_coords
self.body.appendleft(last_part)
self.body.pop()
def __validate_move(self, direction):
new_coords = self.coords + direction
if not new_coords.fits_in_world(self.world):
raise Death()
new_cell = self.world[new_coords.x][new_coords.y]
if isinstance(new_cell.contents, PythonPart):
raise Death()
elif isinstance(new_cell.contents, Food):
self.size += 1
self.energy += new_cell.contents.energy