# Story

Those pesky rats have returned and this time they have taken over the Town Square.

The Pied Piper has been enlisted again to play his magical tune and coax all the rats towards him.

But some of the rats are deaf and are going the wrong way!

# Kata Task

How many deaf rats are there?

## Input Notes

* The Town Square is a rectangle of square paving stones (the Square has 1-15 pavers per side)
* The Pied Piper is always present

## Output Notes
* Deaf rats are those that are moving to paving stone **further away** from the Piper than where they are now
* Use Euclidian distance for your calculations

## Legend

* `P` = The Pied Piper
* `←` `↑` `→` `↓` `↖` `↗` `↘` `↙` = Rats going in different directions
* space = Everything else



# Examples

ex1 - has 1 deaf rat


↗ P              
  ↘   ↖
  ↑              
↗        


---

ex2 - has 7 deaf rats


    ↗            
P ↓   ↖ ↑
    ←   ↓
  ↖ ↙   ↙
↓ ↓ ↓

Difficulty: EASY
Tags: Fundamentals

Starter code:
def count_deaf_rats(town_square):
	

Solutions:
from math import hypot
DIRS = {'←': (0, -1), '↑': (-1, 0), '→': (0, 1), '↓': (1, 0), '↖': (-1, -1), '↗': (-1, 1), '↘': (1, 1), '↙': (1, -1)}

def count_deaf_rats(town):
	pipper = next(((x, y) for (x, r) in enumerate(town) for (y, c) in enumerate(r) if c == 'P'))
	return sum((isDeaf(pipper, x, y, *DIRS[c]) for (x, r) in enumerate(town) for (y, c) in enumerate(r) if c in DIRS))

def isDeaf(pipper, x, y, dx, dy):
	(dCurrent, dNext) = (hypot(*(a - b for (a, b) in zip(pipper, pos))) for pos in ((x, y), (x + dx, y + dy)))
	return dCurrent < dNext


from math import copysign
directions = {'←': (0, -1), '↑': (-1, 0), '→': (0, 1), '↓': (1, 0), '↖': (-1, -1), '↗': (-1, 1), '↘': (1, 1), '↙': (1, -1)}

def count_deaf_rats(town_square):
	(pi, pj) = next(((i, j) for (i, row) in enumerate(town_square) for (j, x) in enumerate(row) if x == 'P'))
	result = 0
	for (i, row) in enumerate(town_square):
		for (j, x) in enumerate(row):
			if x not in directions:
				continue
			(di, dj) = directions[x]
			if (i + di - pi) ** 2 + (j + dj - pj) ** 2 > (i - pi) ** 2 + (j - pj) ** 2:
				result += 1
	return result


D = {'↖': -1 - 1j, '↑': -1, '↗': -1 + 1j, '←': -1j, '→': +1j, '↙': +1 - 1j, '↓': +1, '↘': +1 + 1j}

def count_deaf_rats(town_square):
	coords = [(i + j * 1j, x) for (i, row) in enumerate(town_square) for (j, x) in enumerate(row)]
	p = next((c for (c, x) in coords if x == 'P'))
	return sum((abs(c + D.get(x, 0) - p) > abs(c - p) for (c, x) in coords))


from math import hypot
moves = {'↖': (-1, -1), '←': (-1, 0), '↙': (-1, 1), '↑': (0, -1), '↓': (0, 1), '↗': (1, -1), '→': (1, 0), '↘': (1, 1)}

def count_deaf_rats(town_square):
	(deaf, (px, py)) = (0, next(((row.index('P'), y) for (y, row) in enumerate(town_square) if 'P' in row)))
	dist = lambda x, y: hypot(px - x, py - y)
	for (y, row) in enumerate(town_square):
		for (x, c) in enumerate(row):
			if c in moves:
				(mx, my) = moves[c]
				if dist(x, y) < dist(x + mx, y + my):
					deaf += 1
	return deaf


import math

class Position:

	def __init__(self, x, y):
		self.x = x
		self.y = y

	def distance(self, other):
		return math.hypot(self.x - other.x, self.y - other.y)
Direction = {'←': lambda position: Position(position.x - 1, position.y), '↑': lambda position: Position(position.x, position.y - 1), '→': lambda position: Position(position.x + 1, position.y), '↓': lambda position: Position(position.x, position.y + 1), '↖': lambda position: Position(position.x - 1, position.y - 1), '↗': lambda position: Position(position.x + 1, position.y - 1), '↘': lambda position: Position(position.x + 1, position.y + 1), '↙': lambda position: Position(position.x - 1, position.y + 1)}
PIEP_PIPER = 'P'

class Rat:

	def __init__(self, position, move):
		self.position = position
		self.move = move

	def is_deaf(self, piper):
		current_distance = piper.distance(self.position)
		distance_after_one_step = piper.distance(self.move(self.position))
		return current_distance - distance_after_one_step < 0

def count_deaf_rats(town_square):
	rats = []
	piper = None
	for (y, line) in enumerate(town_square):
		for (x, cell) in enumerate(line):
			if cell in Direction:
				rats.append(Rat(Position(x, y), Direction[cell]))
			elif cell == PIEP_PIPER:
				piper = Position(x, y)
	return len([rat for rat in rats if rat.is_deaf(piper)])


def count_deaf_rats(board):
	(o, p) = next(([i, j] for (i, l) in enumerate(board) for (j, k) in enumerate(l) if board[i][j] == 'P'))
	distance = lambda x, y: ((o - x) ** 2 + (p - y) ** 2) ** 0.5
	d = {'←': (0, -1), '↑': (-1, 0), '→': (0, 1), '↓': (1, 0), '↖': (-1, -1), '↗': (-1, 1), '↘': (1, 1), '↙': (1, -1)}
	return sum((distance(i + d[l][0], k + d[l][1]) > distance(i, k) for (i, j) in enumerate(board) for (k, l) in enumerate(j) if l in '←↑→↓↖↗↘↙'))


deltas = dict(zip('←↑→↓↖↗↘↙', (-1, -1j, 1, 1j, -1 - 1j, 1 - 1j, 1 + 1j, -1 + 1j)))

def count_deaf_rats(town_square):
	(ii, jj) = (list(range(len(town_square[0]))), list(range(len(town_square))))
	p = next((complex(i, j) for i in ii for j in jj if town_square[j][i] == 'P'))
	return sum((abs(ij + d - p) > abs(ij - p) for (ij, d) in ((complex(i, j), deltas.get(town_square[j][i], 0)) for j in jj for i in ii)))


rat_dirs = {'←': (-1, 0), '↑': (0, -1), '→': (1, 0), '↓': (0, 1), '↖': (-1, -1), '↗': (1, -1), '↘': (1, 1), '↙': (-1, 1)}

def find_piper(town_square, width, height):
	for y in range(height):
		for x in range(width):
			if town_square[y][x] == 'P':
				return (x, y)
	return (-1, -1)

def is_rat_deaf(rx, ry, px, py, c):
	(dx, dy) = (px - rx, py - ry)
	(cx, cy) = rat_dirs[c]
	return cx * dx + cy * dy <= 0

def count_deaf_rats(town_square):
	(width, height) = (len(town_square[0]), len(town_square))
	(px, py) = find_piper(town_square, width, height)
	num_deaf = 0
	for y in range(height):
		for x in range(width):
			c = town_square[y][x]
			if c in rat_dirs and is_rat_deaf(x, y, px, py, c):
				num_deaf += 1
	return num_deaf


def count_deaf_rats(a):
	d = [(i, j) for i in range(-1, 2) for j in range(-1, 2) if i or j]
	d = {x: d[i] for (i, x) in enumerate('↖↑↗←→↙↓↘')}
	(p, r) = (divmod(''.join(a).index('P'), len(a[0])), 0)
	for (i, x) in enumerate(a):
		for (j, y) in enumerate(x):
			if y not in ' P':
				z = d[y]
				n = abs(i - p[0] + (j - p[1]) * 1j)
				m = abs(i + z[0] - p[0] + (j + z[1] - p[1]) * 1j)
				if n < m:
					r += 1
	return r