# 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: introductory

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 "←↑→↓↖↗↘↙")

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):
    dPipper, dNext = (hypot(*(a-b for a,b in zip(pipper,pos))) for pos in ((x,y),(x+dx,y+dy)))
    return dPipper < dNext

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