Problem:
Score : 700 points

Problem Statement

There are some coins in the xy-plane.
The positions of the coins are represented by a grid of characters with H rows and W columns.
If the character at the i-th row and j-th column, s_{ij}, is #, there is one coin at point (i,j); if that character is ., there is no coin at point (i,j). There are no other coins in the xy-plane.

There is no coin at point (x,y) where 1\leq i\leq H,1\leq j\leq W does not hold.
There is also no coin at point (x,y) where x or y (or both) is not an integer.
Additionally, two or more coins never exist at the same point.

Find the number of triples of different coins that satisfy the following condition:

Choosing any two of the three coins would result in the same Manhattan distance between the points where they exist.

Here, the Manhattan distance between points (x,y) and (x',y') is |x-x'|+|y-y'|.
Two triples are considered the same if the only difference between them is the order of the coins.

Constraints

1 \leq H,W \leq 300

s_{ij} is # or ..

Input

Input is given from Standard Input in the following format:

H W
s_{11}...s_{1W}
:
s_{H1}...s_{HW}

Output

Print the number of triples that satisfy the condition.

Sample Input 1

5 4
#.##
.##.
#...
..##
...#

Sample Output 1

3

((1,1),(1,3),(2,2)),((1,1),(2,2),(3,1)) and ((1,3),(3,1),(4,4)) satisfy the condition.

Sample Input 2

13 27
......#.........#.......#..
#############...#.....###..
..............#####...##...
...#######......#...#######
...#.....#.....###...#...#.
...#######....#.#.#.#.###.#
..............#.#.#...#.#..
#############.#.#.#...###..
#...........#...#...#######
#..#######..#...#...#.....#
#..#.....#..#...#...#.###.#
#..#######..#...#...#.#.#.#
#..........##...#...#.#####

Sample Output 2

870

Solution in Rust (1.15.1) (judge verdict: Time Limit Exceeded)

use std::collections::BTreeMap;

fn main() {
    let s = std::io::stdin();
    let mut sc = Scanner { reader: s.lock() };
    let h: usize = sc.read();
    let w: usize = sc.read();
    let s: Vec<Vec<char>> = (0..h).map(|_| sc.chars()).collect();
    let mut points = vec![];
    for i in 0..h {
        for j in 0..w {
            if s[i][j] == '#' {
                let x = i as i64;
                let y = j as i64;
                points.push((x, y));
            }
        }
    }

    let mut map: BTreeMap<i64, Vec<(i64, i64)>> = BTreeMap::new();
    for &(x, y) in points.iter() {
        let k = y + x;
        map.entry(k).or_insert(Vec::new()).push((x, y));
    }
    for point in map.values_mut() {
        point.sort();
    }

    let mut ans = 0;
    for t in map.values() {
        let n = t.len();
        for i in 0..n {
            for j in 0..i {
                let (x1, y1) = t[j];
                let (x2, y2) = t[i];
                let d = (x1 - x2).abs();
                assert_eq!(x1 + d, x2);
                assert_eq!(y1 - d, y2, "{:?} {:?}", (x1, y1), (x2, y2));
                let d = (x1 - x2).abs();
                for i in 1..d {
                    // (x1-d)->x1
                    // y2->(y2-d)
                    let x = x1 - d + i;
                    let y = y2 - i;
                    if x < 0 || y < 0 {
                        continue;
                    }
                    assert_eq!((x - x1).abs() + (y - y1).abs(), d * 2);
                    assert_eq!((x - x2).abs() + (y - y2).abs(), d * 2);
                    let x = x as usize;
                    let y = y as usize;
                    if x >= h || y >= w {
                        continue;
                    }
                    if s[x][y] == '#' {
                        ans += 1;
                    }
                }
                for i in 1..d {
                    // x2->x2+d
                    // y1+d->y1
                    let x = x2 + i;
                    let y = y1 + d - i;
                    if x < 0 || y < 0 {
                        continue;
                    }
                    assert_eq!((x - x1).abs() + (y - y1).abs(), d * 2);
                    assert_eq!((x - x2).abs() + (y - y2).abs(), d * 2);
                    let x = x as usize;
                    let y = y as usize;
                    if x >= h || y >= w {
                        continue;
                    }
                    if s[x][y] == '#' {
                        ans += 1;
                    }
                }
            }
        }
    }

    let mut map: BTreeMap<i64, Vec<(i64, i64)>> = BTreeMap::new();
    for &(x, y) in points.iter() {
        let k = y - x;
        map.entry(k).or_insert(Vec::new()).push((x, y));
    }
    for point in map.values_mut() {
        point.sort();
    }
    for t in map.values() {
        let n = t.len();
        for i in 0..n {
            for j in 0..i {
                let (x1, y1) = t[j];
                let (x2, y2) = t[i];
                let d = (x1 - x2).abs();
                assert_eq!(x1 + d, x2);
                assert_eq!(y1 + d, y2, "{:?} {:?}", (x1, y1), (x2, y2));
                let d = (x1 - x2).abs();
                for i in 1..d {
                    // (x1-d)->x1
                    // y2->(y2+d)
                    let x = x1 - d + i;
                    let y = y2 + i;
                    if x < 0 || y < 0 {
                        continue;
                    }
                    assert_eq!((x - x1).abs() + (y - y1).abs(), d * 2);
                    assert_eq!((x - x2).abs() + (y - y2).abs(), d * 2);
                    let x = x as usize;
                    let y = y as usize;
                    if x >= h || y >= w {
                        continue;
                    }
                    if s[x][y] == '#' {
                        ans += 1;
                    }
                }
                for i in 1..d {
                    // x2->x2+d
                    // y1-d->y1
                    let x = x2 + i;
                    let y = y1 - d + i;
                    if x < 0 || y < 0 {
                        continue;
                    }
                    assert_eq!((x - x1).abs() + (y - y1).abs(), d * 2);
                    assert_eq!((x - x2).abs() + (y - y2).abs(), d * 2);
                    let x = x as usize;
                    let y = y as usize;
                    if x >= h || y >= w {
                        continue;
                    }
                    if s[x][y] == '#' {
                        ans += 1;
                    }
                }
            }
        }
    }
    for t in map.values() {
        let n = t.len();
        for i in 0..n {
            for j in 0..i {
                let (x1, y1) = t[j];
                let (x2, y2) = t[i];
                let d = (x1 - x2).abs();
                assert_eq!(x1 + d, x2);
                assert_eq!(y1 + d, y2, "{:?} {:?}", (x1, y1), (x2, y2));
                let d = (x1 - x2).abs();
                let v = vec![(x2, y1 - d), (x2 + d, y1), (x1 - d, y2), (x1, y2 + d)];

                for &(x, y) in v.iter() {
                    if x < 0 || y < 0 {
                        continue;
                    }
                    assert_eq!((x - x1).abs() + (y - y1).abs(), d * 2);
                    assert_eq!((x - x2).abs() + (y - y2).abs(), d * 2);
                    let x = x as usize;
                    let y = y as usize;
                    if x >= h || y >= w {
                        continue;
                    }
                    if s[x][y] == '#' {
                        ans += 1;
                    }
                }
            }
        }
    }
    println!("{}", ans);
}

pub struct Scanner<R> {
    reader: R,
}

impl<R: std::io::Read> Scanner<R> {
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .reader
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n')
            .take_while(|&b| b != b' ' && b != b'\n')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn read_vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}