Design Neighbor Sum Service
Source: leetcode
Difficulty: Easy
Tags: array, hash-table, design, matrix, simulation

You are given a `n x n` 2D array `grid` containing **distinct** elements in the range `[0, n2 - 1]`.


Implement the `NeighborSum` class:


- `NeighborSum(int [][]grid)` initializes the object.
- `int adjacentSum(int value)` returns the **sum** of elements which are adjacent neighbors of `value`, that is either to the top, left, right, or bottom of `value` in `grid`.
- `int diagonalSum(int value)` returns the **sum** of elements which are diagonal neighbors of `value`, that is either to the top\-left, top\-right, bottom\-left, or bottom\-right of `value` in `grid`.


![](https://assets.leetcode.com/uploads/2024/06/24/design.png)


 


**Example 1:**



**Input:**


\["NeighborSum", "adjacentSum", "adjacentSum", "diagonalSum", "diagonalSum"]


\[\[\[\[0, 1, 2], \[3, 4, 5], \[6, 7, 8]]], \[1], \[4], \[4], \[8]]


**Output:** \[null, 6, 16, 16, 4]


**Explanation:**


**![](https://assets.leetcode.com/uploads/2024/06/24/designexample0.png)**


- The adjacent neighbors of 1 are 0, 2, and 4\.
- The adjacent neighbors of 4 are 1, 3, 5, and 7\.
- The diagonal neighbors of 4 are 0, 2, 6, and 8\.
- The diagonal neighbor of 8 is 4\.



**Example 2:**



**Input:**


\["NeighborSum", "adjacentSum", "diagonalSum"]


\[\[\[\[1, 2, 0, 3], \[4, 7, 15, 6], \[8, 9, 10, 11], \[12, 13, 14, 5]]], \[15], \[9]]


**Output:** \[null, 23, 45]


**Explanation:**


**![](https://assets.leetcode.com/uploads/2024/06/24/designexample2.png)**


- The adjacent neighbors of 15 are 0, 10, 7, and 6\.
- The diagonal neighbors of 9 are 4, 12, 14, and 15\.



 


**Constraints:**


- `3 <= n == grid.length == grid[0].length <= 10`
- `0 <= grid[i][j] <= n2 - 1`
- All `grid[i][j]` are distinct.
- `value` in `adjacentSum` and `diagonalSum` will be in the range `[0, n2 - 1]`.
- At most `2 * n2` calls will be made to `adjacentSum` and `diagonalSum`.




C++ solution:
class neighborSum {
public:
    vector<vector<int>> grida;
    neighborSum(vector<vector<int>>& grid):grida(grid) {
        
    }
    
    int adjacentSum(int value) {
        int sum = 0;
        for(int i = 0;i<grida.size();i++){
            for(int j = 0;j<grida[i].size();j++){
                if(value==grida[i][j]){
                    if(i-1>=0)
                    sum+=grida[i-1][j];
                    if((i+1<grida.size()))
                    sum+=grida[i+1][j];
                    if(j+1<grida[i].size())
                    sum+=grida[i][j+1];
                    if(j-1>=0)
                    sum+=grida[i][j-1];
                    break;
                }
            }
            if(sum!=0) break;
        }
        return sum;

    }
    
    int diagonalSum(int value) {
        int sum = 0;
        for(int i = 0;i<grida.size();i++){
            for(int j = 0;j<grida[i].size();j++){
                if(value==grida[i][j]){
                    if(i-1>=0&&j-1>=0)
                    sum+=grida[i-1][j-1];
                    if((i+1<grida.size()&&j+1<grida[i].size()))
                    sum+=grida[i+1][j+1];
                    if(i-1>=0&&j+1<grida[i].size())
                    sum+=grida[i-1][j+1];

                    if(i+1<grida.size()&&j-1>=0)
                    sum+=grida[i+1][j-1];
                    
                    break;
                }
            }
            if(sum!=0) break;
        }
        return sum;
        
    }
};

/**
 * Your neighborSum object will be instantiated and called as such:
 * neighborSum* obj = new neighborSum(grid);
 * int param_1 = obj->adjacentSum(value);
 * int param_2 = obj->diagonalSum(value);
 */

Go solution:
type NeighborSum struct {
	pGrid *[][]int
	n     int
}

func Constructor(grid [][]int) NeighborSum {
	return NeighborSum{pGrid: &grid, n: len(grid)}
}

func (this *NeighborSum) AdjacentSum(value int) int {
	sum := 0
	for i := 0; i < this.n; i++ {
		for j := 0; j < this.n; j++ {
			if (*this.pGrid)[i][j] == value {
				if i-1 >= 0 {
					sum += (*this.pGrid)[i-1][j]
				}
				if i+1 < this.n {
					sum += (*this.pGrid)[i+1][j]
				}
				if j-1 >= 0 {
					sum += (*this.pGrid)[i][j-1]
				}
				if j+1 < this.n {
					sum += (*this.pGrid)[i][j+1]
				}
			}
		}
	}
	return sum
}

func (this *NeighborSum) DiagonalSum(value int) int {
	sum := 0
	for i := 0; i < this.n; i++ {
		for j := 0; j < this.n; j++ {
			if (*this.pGrid)[i][j] == value {
				if i-1 >= 0 {
					if j - 1 >= 0 {
                        sum += (*this.pGrid)[i-1][j-1] 
                    }
                    if j + 1 < this.n {
                        sum += (*this.pGrid)[i-1][j+1] 
                    }
				}
				if i+1 < this.n {
					if j - 1 >= 0 {
                        sum += (*this.pGrid)[i+1][j-1] 
                    }
                    if j + 1 < this.n {
                        sum += (*this.pGrid)[i+1][j+1] 
                    }
				}
			}
		}
	}
	return sum
}

/**
 * Your NeighborSum object will be instantiated and called as such:
 * obj := Constructor(grid);
 * param_1 := obj.AdjacentSum(value);
 * param_2 := obj.DiagonalSum(value);
 */

Java solution:
class NeighborSum {
    private int[] suma = new int[101];  // Array to store sums of adjacent neighbors
    private int[] sumd = new int[101];  // Array to store sums of diagonal neighbors
    private final int[] adj = {0, 1, 0, -1, 0};  // Direction vectors for adjacent neighbors
    private final int[] dia = {1, 1, -1, -1, 1}; // Direction vectors for diagonal neighbors

    public NeighborSum(int[][] grid) {
        for (int i = 0; i < grid.length; ++i) {
            for (int j = 0; j < grid[i].length; ++j) {
                for (int d = 0; d < 4; ++d) {
                    add(i + adj[d], j + adj[d + 1], grid[i][j], suma, grid);
                    add(i + dia[d], j + dia[d + 1], grid[i][j], sumd, grid);
                }
            }
        }
    }

    private void add(int i, int j, int val, int[] arr, int[][] grid) {
        if (i >= 0 && j >= 0 && i < grid.length && j < grid[0].length) {
            arr[grid[i][j]] += val;
        }
    }

    public int adjacentSum(int value) {
        return suma[value];
    }

    public int diagonalSum(int value) {
        return sumd[value];
    }
}

JavaScript solution:
function findIndexOfHouse(val,grid){
    for(let i = 0 ; i <grid.length ; i++){
        for(let j = 0 ; j < grid[i].length ; j++){
            if(grid[i][j] == val) return [i , j]
        }
    }
}
var NeighborSum = function(grid) {
    this.grid = grid;
};
NeighborSum.prototype.adjacentSum = function(value) {
   let [i , j ] = findIndexOfHouse(value , this.grid);
 
    let sum = 0 ;

    sum += i>0 ?this.grid[i-1][j] : 0;
    sum += i < this.grid.length - 1 ? this.grid[i+1][j] : 0 
    sum += j > 0 ? this.grid[i][j-1] : 0
    sum += j < this.grid[i].length - 1 ? this.grid[i][j+1] : 0;
    return sum
    
}
NeighborSum.prototype.diagonalSum = function(value) {
    let [i , j ] = findIndexOfHouse(value , this.grid);
 
    let sum = 0 ;
    
    if(i > 0 && j > 0) sum += this.grid[i-1][j-1];
    if(i < this.grid.length - 1 && j > 0) sum += this.grid[i+1][j-1] 
    if( i>0 && j < this.grid[i].length - 1) sum += this.grid[i-1][j+1];
    if(i < this.grid.length - 1  && j < this.grid[i].length - 1) sum += this.grid[i+1][j+1];
    return sum 
};

Python solution:
class neighborSum:

    def __init__(self, grid: List[List[int]]):
        self.grid = grid
        self.row_num = len(self.grid)
        self.col_num = len(self.grid[0])
        self.v2p_dict = {}
        for ri in range(self.row_num):
            for ci in range(self.col_num):
                self.v2p_dict[grid[ri][ci]] = (ri, ci) 

    def adjacentSum(self, value: int) -> int:
        val = 0
        vri, vci = self.v2p_dict[value]
        if vri + 1 < self.row_num:
            val += self.grid[vri + 1][vci]
        if vri - 1 >= 0:
            val += self.grid[vri - 1][vci]
        if vci + 1 < self.col_num:
            val += self.grid[vri][vci + 1]
        if vci - 1 >= 0:
            val += self.grid[vri][vci - 1]
        return val
        

    def diagonalSum(self, value: int) -> int:
        val = 0
        vri, vci = self.v2p_dict[value]
        if vri - 1 >= 0 and vci - 1 >= 0:
            val += self.grid[vri - 1][vci - 1]
        if vri - 1 >= 0 and vci + 1 < self.col_num:
            val += self.grid[vri - 1][vci + 1]
        if vri + 1 < self.row_num and vci - 1 >= 0:
            val += self.grid[vri + 1][vci - 1]
        if vri + 1 < self.row_num and vci + 1 < self.col_num:
            val += self.grid[vri + 1][vci + 1]
        return val

# Your neighborSum object will be instantiated and called as such:
# obj = neighborSum(grid)
# param_1 = obj.adjacentSum(value)
# param_2 = obj.diagonalSum(value)

Ruby solution:
class NeighborSum
    attr_accessor :grid

=begin
    :type grid: Integer[][]
=end
    def initialize(grid)
        @grid = grid
    end

=begin
    :type value: Integer
    :rtype: Integer
=end
    def adjacent_sum(value)
        total = 0
        y, x = find_y_and_x value

        if y > 0
            total += @grid[y-1][x]
        end

        if y + 1 < @grid.size 
            total += @grid[y+1][x]
        end

         if x > 0
            total += @grid[y][x-1]
        end

        if x + 1 < @grid[0].size 
            total += @grid[y][x+1]
        end

        total
    end

=begin
    :type value: Integer
    :rtype: Integer
=end
    def diagonal_sum(value)
        total = 0
        y, x = find_y_and_x value

        if y > 0 and x > 0
            total += @grid[y-1][x-1]
        end

        if y > 0 and x + 1 < @grid[0].size 
            total += @grid[y-1][x+1]
        end

        if y + 1 < @grid.size and x > 0
            total += @grid[y+1][x - 1]
        end

        if y + 1 < @grid.size and x + 1 < @grid[0].size 
            total += @grid[y+1][x+1]
        end

        total
    end

    def find_y_and_x value
        y = 0
        x = 0
        i = @grid[y][x]
        while i != value
            if @grid[y][x + 1] == nil
                y += 1
                x = 0
            else
                x += 1
            end

            i = @grid[y][x]
        end

        [y, x]
    end

end

def neighborSum 
  NeighborSum 
end 

# Your neighborSum object will be instantiated and called as such:
# obj = neighborSum.new(grid)
# param_1 = obj.adjacent_sum(value)
# param_2 = obj.diagonal_sum(value)