Problem: 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.

Examples

Input

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


Output

3


Input

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


Output

3


Input

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


Output

870

Solution (in CPP):

Solution:
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <bitset>
#include <set>
#include <cmath>
#include <cassert>
using namespace std;

int cumsum[666][666];
int cumsum2[666][666];

int main(){
    int H, W;
    cin >> H >> W;
    vector<string> s(H);
    for(int i=0; i<H; i++)
        cin >> s[i];

    vector<vector<int>> coins(H+W+1);
    vector<vector<int>> coins2(H+W+1);
    for(int i=1; i<=H; i++){
        for(int j=1; j<=W; j++){
            if(s[i-1][j-1] == '#'){
                cumsum[i+j][W+i-j] = 1;
                cumsum2[W+i-j][i+j] = 1;
                coins[i+j].push_back(W+i-j);
                coins2[W+i-j].push_back(i+j);
            }
        }
    }
    for(int i=0; i<=H+W; i++)
        for(int j=1; j<=H+W; j++)
            cumsum[i][j] += cumsum[i][j-1];

    for(int i=0; i<=H+W; i++)
        for(int j=1; j<=H+W; j++)
            cumsum2[i][j] += cumsum2[i][j-1];

    long long ans = 0;
    for(int i=0; i<=H+W; i++){
        int sz = coins[i].size();
        for(int j=0; j<sz; j++){
            for(int k=j+1; k<sz; k++){
                int bot = coins[i][j];
                int top = coins[i][k];
                int dist = top - bot;
                int lef = i - dist;
                if(lef >= 0){
                    ans += cumsum[lef][top] - cumsum[lef][bot-1];
                }
                int rig = i + dist;
                if(rig <= H+W){
                    ans += cumsum[rig][top] - cumsum[rig][bot-1];
                }
            }
        }
    }

    for(int i=0; i<=H+W; i++){
        int sz = coins2[i].size();
        for(int j=0; j<sz; j++){
            for(int k=j+1; k<sz; k++){
                int bot = coins2[i][j];
                int top = coins2[i][k];
                int dist = top - bot;
                int lef = i - dist;
                if(lef >= 0){
                    ans += cumsum2[lef][top-1] - cumsum2[lef][bot];
                }
                int rig = i + dist;
                if(rig <= H+W){
                    ans += cumsum2[rig][top-1] - cumsum2[rig][bot];
                }
            }
        }
    }

    cout << ans << endl;

    return 0;
}