Finding neighbours in a two-dimensional array - arrays

Is there an easy way of finding the neighbours (that is, the eight elements around an element) of an element in a two-dimensional array? Short of just subtracting and adding to the index in different combinations, like this:
array[i-1][i]
array[i-1][i-1]
array[i][i-1]
array[i+1][i]
... And so on.

(pseudo-code)
row_limit = count(array);
if(row_limit > 0){
column_limit = count(array[0]);
for(x = max(0, i-1); x <= min(i+1, row_limit); x++){
for(y = max(0, j-1); y <= min(j+1, column_limit); y++){
if(x != i || y != j){
print array[x][y];
}
}
}
}
Of course, that takes almost as many lines as the original hard-coded solution, but with this one you can extend the "neighborhood" as much as you can (2-3 or more cells away)

I think Ben is correct in his approach, though I might reorder it, to possibly improve locality.
array[i-1][j-1]
array[i-1][j]
array[i-1][j+1]
array[i][j-1]
array[i][j+1]
array[i+1][j-1]
array[i+1][j]
array[i+1][j+1]
One trick to avoid bounds checking issues, is to make the array dimensions 2 larger than needed. So, a little matrix like this
3 1 4
1 5 9
2 6 5
is actually implemented as
0 0 0 0 0
0 3 1 4 0
0 1 5 9 0
0 2 6 5 0
0 0 0 0 0
then while summing, I can subscript from 1 to 3 in both dimensions, and the array references above are guaranteed to be valid, and have no effect on the final sum.
I am assuming c, and zero based subscripts for the example

Here is a working Javascript example from #seb original pseudo code:
function findingNeighbors(myArray, i, j) {
var rowLimit = myArray.length-1;
var columnLimit = myArray[0].length-1;
for(var x = Math.max(0, i-1); x <= Math.min(i+1, rowLimit); x++) {
for(var y = Math.max(0, j-1); y <= Math.min(j+1, columnLimit); y++) {
if(x !== i || y !== j) {
console.log(myArray[x][y]);
}
}
}
}

an alternative to #SebaGR, if your language supports this:
var deltas = { {x=-1, y=-1}, {x=0, y=-1}, {x=1, y=-1},
{x=-1, y=0}, {x=1, y=0},
{x=-1, y=1}, {x=0, y=1}, {x=1, y=1} };
foreach (var delta in deltas)
{
if (x+delta.x < 0 || x + delta.x >= array.GetLength(0) ||
y+delta.y < 0 || y + delta.y >= array.GetLength(1))
continue;
Console.WriteLine("{0}", array[x + delta.x, y + delta.y]);
}
Slight advantage in readability, possible performance if you can statically allocate the deltas.

To print the neighbors of L[row][column]:
print(L[row-1][column-1], L[row-1][column], L[row-1][column+1])
print(L[row][column-1], L[row][column], L[row][column+1])
print(L[row+1][column-1], L[row+1][column], L[row+1][column+1])
That's probably the fastest/easiest way is to just print possible neighbors. Make sure to do index out of bound checking though.
Some languages might offer a shortcut way of doing this, but I don't know of any.

This is an implementation of #Seb's answer in python3+ that is concise and uses generators for max performance:
def neighbours(pos, matrix):
rows = len(matrix)
cols = len(matrix[0]) if rows else 0
for i in range(max(0, pos[0] - 1), min(rows, pos[0] + 2)):
for j in range(max(0, pos[1] - 1), min(cols, pos[1] + 2)):
if (i, j) != pos:
yield matrix[i][j]

Grid (vector 2D or one dimension... not the problem here)
X & Y, coordinate of your element (or just pass your vector element by ref...)
int neighbour(const Grid & g, const size_t & x, const size_t & y) {
for (int i = -1; i < 2; ++i)
for (int j = -1; j < 2; ++j)
if (x + i >= 0 && x + i < g.row && y + j >= 0 && y + j < g.col)
//Do some stuff
return 0;
}

// My approach in JS
let size = 10
//or some arbitrary number for the size of your grid.
const neighbors = [
[-1, -1],
[-1, 0],
[-1, 1],
[0, -1],
[0, 1],
[1, -1],
[1, 0],
[1, 1]
]
for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
neighbors.forEach(([x, y]) => {
const newI = i + x;
const newJ = j + y;
if (
newI >= 0 &&
newI < size &&
newJ >= 0 &&
newJ < size
) {
// you can access your grid neighbors here ----> grid[newI][newJ];
}
```
I've found this approach helpful because it defines all of the array coordinates as transformations of the existing i and j indexes in your for loops.

Here is a convenient method in Python:
def neighbors(array,pos):
n = []
string = "array[pos.y+%s][pos.x+%s]"
for i in range(-1,2):
for j in range(-1,2):
n.append(eval(string % (i,j)))
return n
Assuming pos is some 2D Point object and array is a 2D array.

Since in a matrix around an element there are only 8 elements, you can use array to store different index values.For e.g.,
int iarr[8] = {-1,-1,-1,0,0,+1,+1,+1};
int jarr[8] = {-1,0,+1,-1,+1,-1,0,+1};
for(int i = 0 ; i < 8 ; i++)
{
if(arr[x-iarr[i]][y-jarr[i]] == 1)
{
//statements
}
}
/* x and y are the position of elements from where you want to reach out its neighbour */
since both array contains just 8 values , then space might not be a problem.

The approach I usually take is described on the bottom of this blog:
https://royvanrijn.com/blog/2019/01/longest-path/
Instead of hardcoding the directions or having two nested loops I like to use a single integer loop for the 8 ‘directions’ and use (i % 3)-1 and (i / 3)-1; do check out the blog with images.
It doesn’t nest as deep and is easily written, not a lot of code needed!

JS sample :
function findingNeighbors(myArray, i, j){
return myArray.reduce(function(a, b, c){
if(Math.max(0, i-1) <= c && c <= Math.min(i+1, myArray.length-1)){
a = a.concat(
b.reduce(function(d, e, f){
if(f == j && c == i)
return d;
if(Math.max(0, j-1) <= f && f <= Math.min(j+1, myArray.length-1))
d.push(e)
return d;
},[])
);
}
return a;
},[]);
}

A lot depends on what your data is. For example, if your 2D array is a logical matrix, you could convert rows to integers and use bitwise operations to find the ones you want.
For a more general-purpose solution I think you're stuck with indexing, like SebaGR's solution.

Rows and Cols are total number of rows and cols
Define a CellIndex struct or class. Or you can just return the actual values instead of the indexes.
public List<CellIndex> GetNeighbors(int rowIndex, int colIndex)
{
var rowIndexes = (new int[] { rowIndex - 1, rowIndex, rowIndex + 1 }).Where(n => n >= 0 && n < Rows);
var colIndexes = (new int[] { colIndex - 1, colIndex, colIndex + 1 }).Where(n => n >= 0 && n < Cols);
return (from row in rowIndexes from col in colIndexes where row != rowIndex || col != colIndex select new CellIndex { Row = row, Col = col }).ToList();
}

private ArrayList<Element> getNeighbors(Element p) {
ArrayList<Element> n = new ArrayList<Element>();
for (int dr = -1; dr <= +1; dr++) {
for (int dc = -1; dc <= +1; dc++) {
int r = p.row + dr;
int c = p.col + dc;
if ((r >= 0) && (r < ROWS) && (c >= 0) && (c < COLS)) {
// skip p
if ((dr != 0) || (dc != 0))
n.add(new Element(r, c));
}
}
}
return n;
}

although nested for loops in list comprehensions is a bit ugly this is shorter:
def neighbours(m, i, j):
return [m[x][y] for x in [i-1,i,i+1] for y in [j-1,j,j+1] if x in range(0,len(m)) and y in range(0,len(m[x])) and (x,y) != (i,j)]

here is some code for C#:
public Cell[,] MeetNeigbours(Cell[,] Grid)
{
for (int X = 0; X < Grid.GetLength(0); X++)
{
for (int Y = 0; Y < Grid.GetLength(1); Y++)
{
int NeighbourCount = 0;
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
if (CellExists(Grid, (X + i)), (Y + j) && (i != 0 && j != 0))
{
Grid[X, Y].Neighbours[NeighbourCount] = Grid[(X + i), (Y + j)];
}
if(!(i == 0 && j == 0))
{
NeighbourCount++;
}
}
}
}
}
return Grid;
}
public bool CellExists(Cell[,] Grid, int X, int Y)
{
bool returnValue = false;
if (X >= 0 && Y >= 0)
{
if (X < Grid.GetLength(0) && Y < Grid.GetLength(1))
{
returnValue = true;
}
}
return returnValue;
}
with the "Cell" class looking like this:
public class Cell
{
public Cell()
{
Neighbours = new Cell[8];
}
/// <summary>
/// 0 3 5
/// 1 X 6
/// 2 4 7
/// </summary>
public Cell[] Neighbours;
}

This was really helpful to me in a recent project, so here's #Seb 's pseudo-code implementation in swift. This is assuming that the two-dimensional array is square:
func adjacentIndexPaths(to indexPath: IndexPath) -> [IndexPath] {
var neighboringSquareIndexes: [IndexPath] = []
// gridSquareCount is the size of the 2D array. For example, in an 8 x 8 [[Array]], gridSquareCount is 8
let maxIndex = gridSquareCount - 1
var neighborRowIndex = max(0, indexPath.section - 1)
var neighborColumnIndex = max(0, indexPath.row - 1)
while neighborRowIndex <= min(indexPath.section + 1, maxIndex) {
while neighborColumnIndex <= min(indexPath.row + 1, maxIndex) {
if neighborRowIndex != indexPath.section || neighborColumnIndex != indexPath.row {
neighboringSquareIndexes.append(IndexPath(row: neighborColumnIndex, section: neighborRowIndex))
}
neighborColumnIndex += 1
}
neighborRowIndex += 1
neighborColumnIndex = max(0, indexPath.row - 1)
}
return neighboringSquareIndexes }

In javascript
let arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
function getNeighborsNumbersAtIthJth(i, j) {
let allPosibleIndexes = [
[i - 1, j],
[i, j - 1],
[i - 1, j - 1],
[i + 1, j],
[i, j + 1],
[i + 1, j + 1],
[i + 1, j - 1],
[i - 1, j + 1]
];
let allPosibleValues = []
allPosibleIndexes.forEach(([i, j]) => {
try {
allPosibleValues.push(arr[i][j])
} catch (err) {
}
})
return allPosibleValues.filter(v => v != undefined);
}
console.log(getNeighborsNumbersAtIthJth(1, 1));//[2, 4, 1, 8, 6, 9, 7, 3]
console.log(getNeighborsNumbersAtIthJth(0, 1));//[1, 5, 3, 6, 4]
console.log(getNeighborsNumbersAtIthJth(0, 0));//[4, 2, 5]

I use a directions array and run a loop to get appropriate directions. Something like this (code is in JS)
function getAdjacent(matrix, i, j, k) {
const directions = [
[i - 1, j - 1],
[i - 1, j],
[i - 1, j + 1],
[i, j - 1],
[i, j + 1],
[i + 1, j - 1],
[i + 1, j],
[i + 1, j + 1],
];
const [row, col] = directions[k];
// Check for last rows and columns
if (row < 0 || row >= matrix.length || col < 0 || col >= matrix[i].length) {
return undefined;
}
return matrix[row][col];
}
function run(){
const hello = 'hello';
const matrix = [
[1, 2, 1],
[2, 1, 1],
[1, 1, 1]
];
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
let sum = 0;
for (let k = 0; k < 8; k++) {
const res = getAdjacent(matrix, i, j, k);
console.log(i, j, k, res); // Do whatever you want here
}
}
}
}
run();

This example in Python might also shed some light:
from itertools import product
def neighbors(coord: tuple, grid=(10, 10), diagonal=True):
"""Retrieve all the neighbors of a coordinate in a fixed 2d grid (boundary).
:param diagonal: True if you also want the diagonal neighbors, False if not
:param coord: Tuple with x, y coordinate
:param grid: the boundary of the grid in layman's terms
:return: the adjacent coordinates
"""
width = grid[0] - 1
height = grid[1] - 1
retx, rety = coord
adjacent = []
nb = [x for x in product([-1, 0, 1], repeat=2) if x != (0, 0)]
if not diagonal:
nb = [x for x in nb if x not in product([-1, 1], repeat=2)]
for x, y in nb:
xx = retx + x
yy = rety + y
if xx < 0 or xx > width or yy < 0 or yy > height:
# not within its boundaries
continue
adjacent.append((xx, yy))
return adjacent
the first product line (nb = [x for x in product([-1, 0, 1], repeat=2) if x != (0, 0)]) will produce all the coordinates of its neibors including the diagonal ones. The (0,0) is removed because that is ourselves so not a neighbor :-)
[(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
If you do not want the diagonal neighbors you can tell it to remove those (product([-1, 1], repeat=2)) then the boundaries of the grid are checked and the resulting list of coordinates will be produced.

Ruby => Returns an array of neighbours.
array = [
[1, 2, 5, 6],
[8, 89, 44, 0],
[8, 7, 23, 0],
[6, 9, 3, 0]
]
def neighbours(array, (i , j))
[
[i, j - 1],
[i, j + 1],
[i - 1, j - 1],
[i - 1, j],
[i - 1, j + 1],
[i + 1, j - 1],
[i + 1, j],
[i + 1, j + 1],
].select { |h, w|
h.between?(0, array.length - 1) && w.between?(0, array.first.length - 1)
}.map do |row, col|
array[row][col]
end
end
array.each_with_index do |row, i|
row.each_with_index do |col, j|
p(array[i][j], neighbours(array, [i, j]))
end
end

I know this is an older question. However, I want to post a solution that I wrote based on Shubh Tripathi's answer
If we're looking for the same neighbors every time and want efficient bounds checking, there is a simple way to achieve this by just storing the indexes we want in an array without re-generating them in each iteration.
I wrote this for a simulation, where I wanted to check all directions surrounding an entity.
def get_surroundings(self, position):
"""
For a given grid location, it returns the surrounding 8x8 grid.
Indexed from the top left to the bottom right. (row-wise)
Args:
position (tuple): The position of the grid location.
Returns:
list: The surrounding 8x8 grid.
"""
# set the x and y coordinates
x = position[0]
y = position[1]
# list out the relative locations of the neighbors
surroundings = [
(-1, -1), (-1, 0), (-1, 1),
(0, -1), (0, 1),
(1, -1), (1, 0), (1, 1)
]
return_list = []
# go through the relative neighbours list, and check if any of the
# bounds condition fail. if they do, append none.
for neighbour in surroundings:
if (
x + neighbour[0] < 0 or
x + neighbour[0] >= self.grid_size or
y + neighbour[1] < 0 or
y + neighbour[1] >= self.grid_size
):
return_list.append(None)
else:
return_list.append(self.grid[x + neighbour[0]][y + neighbour[1]])
self.grid is your 2x2 grid.

Related

Search unsorted array for 3 elements which sum to a value

I am trying to make an algorithm, of Θ( n² ).
It accepts an unsorted array of n elements, and an integer z,
and has to return 3 indices of 3 different elements a,b,c ; so a+b+c = z.
(return NILL if no such integers were found)
I tried to sort the array first, in two ways, and then to search the sorted array.
but since I need a specific running time for the rest of the algorithm, I am getting lost.
Is there any way to do it without sorting? (I guess it does have to be sorted) either with or without sorting would be good.
example:
for this array : 1, 3, 4, 2, 6, 7, 9 and the integer 6
It has to return: 0, 1, 3
because ( 1+3+2 = 6)
Algorithm
Sort - O(nlogn)
for i=0... n-1 - O(1) assigning value to i
new_z = z-array[i] this value is updated each iteration. Now, search for new_z using two pointers, at begin (index 0) and end (index n-1) If sum (array[ptr_begin] + array[ptr_ens]) is greater then new_z, subtract 1 from the pointer at top. If smaller, add 1 to begin pointer. Otherwise return i, current positions of end and begin. - O(n)
jump to step 2 - O(1)
Steps 2, 3 and 4 cost O(n^2). Overall, O(n^2)
C++ code
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> vec = {3, 1, 4, 2, 9, 7, 6};
std::sort(vec.begin(), vec.end());
int z = 6;
int no_success = 1;
//std::for_each(vec.begin(), vec.end(), [](auto const &it) { std::cout << it << std::endl;});
for (int i = 0; i < vec.size() && no_success; i++)
{
int begin_ptr = 0;
int end_ptr = vec.size()-1;
int new_z = z-vec[i];
while (end_ptr > begin_ptr)
{
if(begin_ptr == i)
begin_ptr++;
if (end_ptr == i)
end_ptr--;
if ((vec[begin_ptr] + vec[end_ptr]) > new_z)
end_ptr--;
else if ((vec[begin_ptr] + vec[end_ptr]) < new_z)
begin_ptr++;
else {
std::cout << "indices are: " << end_ptr << ", " << begin_ptr << ", " << i << std::endl;
no_success = 0;
break;
}
}
}
return 0;
}
Beware, result is the sorted indices. You can maintain the original array, and then search for the values corresponding to the sorted array. (3 times O(n))
The solution for the 3 elements which sum to a value (say v) can be done in O(n^2), where n is the length of the array, as follows:
Sort the given array. [ O(nlogn) ]
Fix the first element , say e1. (iterating from i = 0 to n - 1)
Now we have to find the sum of 2 elements sum to a value (v - e1) in range from i + 1 to n - 1. We can solve this sub-problem in O(n) time complexity using two pointers where left pointer will be pointing at i + 1 and right pointer will be pointing at n - 1 at the beginning. Now we will move our pointers either from left or right depending upon the total current sum is greater than or less than required sum.
So, overall time complexity of the solution will be O(n ^ 2).
Update:
I attached solution in c++ for the reference: (also, added comments to explain time complexity).
vector<int> sumOfthreeElements(vector<int>& ar, int v) {
sort(ar.begin(), ar.end());
int n = ar.size();
for(int i = 0; i < n - 2 ; ++i){ //outer loop runs `n` times
//for every outer loop inner loops runs upto `n` times
//therefore, overall time complexity is O(n^2).
int lo = i + 1;
int hi = n - 1;
int required_sum = v - ar[i];
while(lo < hi) {
int current_sum = ar[lo] + ar[hi];
if(current_sum == required_sum) {
return {i, lo, hi};
} else if(current_sum > required_sum){
hi--;
}else lo++;
}
}
return {};
}
I guess this is similar to LeetCode 15 and 16:
LeetCode 16
Python
class Solution:
def threeSumClosest(self, nums, target):
nums.sort()
closest = nums[0] + nums[1] + nums[2]
for i in range(len(nums) - 2):
j = -~i
k = len(nums) - 1
while j < k:
summation = nums[i] + nums[j] + nums[k]
if summation == target:
return summation
if abs(summation - target) < abs(closest - target):
closest = summation
if summation < target:
j += 1
elif summation > target:
k -= 1
return closest
Java
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int closest = nums[0] + nums[nums.length >> 1] + nums[nums.length - 1];
for (int first = 0; first < nums.length - 2; first++) {
int second = -~first;
int third = nums.length - 1;
while (second < third) {
int sum = nums[first] + nums[second] + nums[third];
if (sum > target)
third--;
else
second++;
if (Math.abs(sum - target) < Math.abs(closest - target))
closest = sum;
}
}
return closest;
}
}
LeetCode 15
Python
class Solution:
def threeSum(self, nums):
res = []
nums.sort()
for i in range(len(nums) - 2):
if i > 0 and nums[i] == nums[i - 1]:
continue
lo, hi = -~i, len(nums) - 1
while lo < hi:
tsum = nums[i] + nums[lo] + nums[hi]
if tsum < 0:
lo += 1
if tsum > 0:
hi -= 1
if tsum == 0:
res.append((nums[i], nums[lo], nums[hi]))
while lo < hi and nums[lo] == nums[-~lo]:
lo += 1
while lo < hi and nums[hi] == nums[hi - 1]:
hi -= 1
lo += 1
hi -= 1
return res
Java
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> res = new LinkedList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i == 0 || (i > 0 && nums[i] != nums[i - 1])) {
int lo = -~i, hi = nums.length - 1, sum = 0 - nums[i];
while (lo < hi) {
if (nums[lo] + nums[hi] == sum) {
res.add(Arrays.asList(nums[i], nums[lo], nums[hi]));
while (lo < hi && nums[lo] == nums[-~lo])
lo++;
while (lo < hi && nums[hi] == nums[hi - 1])
hi--;
lo++;
hi--;
} else if (nums[lo] + nums[hi] < sum) {
lo++;
} else {
hi--;
}
}
}
}
return res;
}
}
Reference
You can see the explanations in the following links:
LeetCode 15 - Discussion Board
LeetCode 16 - Discussion Board
LeetCode 15 - Solution
You can use something like:
def find_3sum_restr(items, z):
# : find possible items to consider -- O(n)
candidates = []
min_item = items[0]
for i, item in enumerate(items):
if item < z:
candidates.append(i)
if item < min_item:
min_item = item
# : find possible couples to consider -- O(n²)
candidates2 = []
for k, i in enumerate(candidates):
for j in candidates[k:]:
if items[i] + items[j] <= z - min_item:
candidates2.append([i, j])
# : find the matching items -- O(n³)
for i, j in candidates2:
for k in candidates:
if items[i] + items[j] + items[k] == z:
return i, j, k
This O(n + n² + n³), hence O(n³).
While this is reasonably fast for randomly distributed inputs (perhaps O(n²)?), unfortunately, in the worst case (e.g. for an array of all ones, with a z > 3), this is no better than the naive approach:
def find_3sum_naive(items, z):
n = len(items)
for i in range(n):
for j in range(i, n):
for k in range(j, n):
if items[i] + items[j] + items[k] == z:
return i, j, k

Given an array A of size N, find all combination of four elements in the array whose sum is equal to a given value K

Given an array A of size N, find all combinations of four elements in the array whose sum is equal to a given value K. For example, if the given array is {10, 2, 3, 4, 5, 9, 7, 8} and K = 23, one of the quadruple is “3 5 7 8” (3 + 5 + 7 + 8 = 23).
The output should contain only unique quadruple For example, if the input array is {1, 1, 1, 1, 1, 1} and K = 4, then the output should be only one quadruple {1, 1, 1, 1}
My approach: I tried to solve this problem by storing all the distinct pairs formed from the given array into a hash table (std::unordered_multimap), with their sum as key. Then for each pair sum, I looked for (K - sum) key in the hash table. The problem with this approach is I am getting too many duplicated like (i, j, l, m) and (i, l, j, m) are the same, plus there are duplicates due to the same items in the array. I am not sure what is the optimal way to address that.
The code for the above-mentioned approach is:
#include <iostream>
#include <unordered_map>
#include <tuple>
#include <vector>
int main() {
size_t tc = 0;
std::cin >> tc; //number of test cases
while(tc--) {
size_t n = 0, k = 0;
std::cin >> n >> k;
std::vector<size_t> vec(n);
for (size_t i = 0; i < n; ++i)
std::cin >> vec[i];
std::unordered_multimap<size_t, std::tuple<size_t, size_t>> m;
for (size_t i = 0; i < n - 1; ++i)
for (size_t j = i + 1; j < n; ++j) {
const auto sum = vec[i] + vec[j];
m.emplace(sum, std::make_tuple(i, j));
}
for (size_t i = 0; i < n - 1; ++i)
for (size_t j = i + 1; j < n; ++j) {
const auto sum = vec[i] + vec[j];
auto r = m.equal_range(k - sum);
for (auto it = r.first; it != r.second; ++it) {
if ((i == std::get<0>(it->second))
||(i == std::get<1>(it->second))
||(j == std::get<0>(it->second))
|| (j == std::get<1>(it->second)))
continue;
std::cout << vec[i] << ' ' << vec[j] << ' '
<< vec[std::get<0>(it->second)] << ' '
<< vec[std::get<1>(it->second)] << '$';
}
r = m.equal_range(sum);
for (auto it = r.first; it != r.second; ++it) {
if ((i == std::get<0>(it->second))
&& (j == std::get<1>(it->second))) {
m.erase(it);
break;
}
}
}
std::cout << '\n';
}
return 0;
}
The above code will run as-is in the link mentioned below in the Note.
Note: This problem is taken from https://practice.geeksforgeeks.org/problems/find-all-four-sum-numbers/0
To handle duplicate values in array
Consider [2, 2, 2, 3, 3] with goal 10.
The only solution is the 4-tuple <2,2,3,3>. The main point is to avoid choosing two 2 among three 2.
Let's consider the k-class, the set of tuples in which every tuple contain only k.
e.g: in our array we have the 2-class and 3-class.
The 2-class contains:
<2>
<2,2>
<2,2,2>
while the 3-class contains:
<3>
<3,3>
An idea is to reduce the array of elem (elem being an integer value) to an array of k-class.
idem
[[<2>, <2,2>, <2,2,2>], [<3>, <3,3>]]
We can think of taking the cartesian product between the 2-class set and the 3-class set, and check which result lead to solution.
More concretely, let's take some tuple T, whose last (==rightmost) value is k. (in <2,3,4> rightmost value would be 4).
We can pick any l-class from our array (* l > k) and join the tuples from that l-class to T.
e.g
consider array [2, 9, 9, 3, 3, 4, 6] and tuple <2, 3, 3>
The rightmost value is 3.
The candidate k-class are 4-class, 6-class, 9-class
we can join:
<4>
<6>
<9>
<9,9>
so the next candidates will be:
<2, 3, 3, 4>
<2, 3, 3, 6>
<2, 3, 3, 9>
<2, 3, 3, 9, 9> //that one has too many elem, left for illustration
(* The purpose of l > k is to prevent the permutation. (if <1,2> is solution you don't want <2,1> since addition is commutative))
Algorithm
Foreach tuple, try to create new ones by rightjoining tuples from a "greater" k-class.
discard the resulting ones which have too many elements or whose sum is already too big...
At some point we won't have new candidates, so algorithm will stop
example of cuts:
given array [2,3,7,8,10,11], and tuple <2,3> and S == 13
<2,3,7> is candidate (2+3+7 = 12 < 13)
<2,3,10> is not candidate (2+3+10 = 15 > 13)
<2,3,11> even more so. not
<2,3,8> is not candidate either since the next rightjoin (to reach a 4-tuple) will overflow S
given array [2,3,4,4,4] given tuple <2,3> and candidate <4,4,4>
resulting tuple would be <2,3,4,4,4> which has too many elems, discard it!
Obviously the initialization is
some empty tuple
whose sum is 0
and whose rightmost element is less than any k from the array (you can rightjoin it anybody)
I believe it should not be too hard to translate to C++
class TupleClass {
sum = 0
rightIdx = -1
values = [] // an array of integers (hopefully summing to solution)
//idx is the position of the k-class found in array
add (val, idx) {
const t = new TupleClass()
t.values = this.values.concat(val)
t.sum = this.sum + val
t.rightIdx = idx
return t;
}
toString () {
return `<${this.values.join(',')}>`
}
addTuple (tuple, idx) {
const t = new TupleClass
t.values = this.values.concat(tuple.values)
t.sum = this.sum + tuple.sum
t.rightIdx = idx
return t;
}
get size () {
return this.values.length
}
}
function nodupes (v, S) {
v = v.reduce((acc, klass) => {
acc[klass] = (acc[klass] || {duplicity: 0, klass})
acc[klass].duplicity++
return acc
}, {})
v = Object.values(v).sort((a,b) => a.klass - b.klass).map(({ klass, duplicity }, i) => {
return Array(duplicity).fill(0).reduce((acc, _) => {
const t = acc[acc.length-1].add(klass, i)
acc.push(t)
return acc
}, [new TupleClass()]).slice(1)
})
//v is sorted by k-class asc
//each k-class is an array of tuples with increasing length
//[[<2>, <2,2>, <2,2,2>], [<3>,<3,3>]]
let tuples = [new TupleClass()]
const N = v.length
let nextTuples = []
const solutions = []
while (tuples.length) {
tuples.forEach(tuple => {
//foreach kclass after our rightmost value
for (let j = tuple.rightIdx + 1; j <= N - 1; ++j) {
//foreach tuple of that kclass
for (let tclass of v[j]) {
const nextTuple = tuple.addTuple(tclass, j)
if (nextTuple.sum > S || nextTuple.size > 4) {
break
}
//candidate to solution
if (nextTuple.size == 4) {
if (nextTuple.sum === S) {
solutions.push(nextTuple)
}
//invalid sum so adding more elem won't help, do not push
} else {
nextTuples.push(nextTuple)
}
}
}
})
tuples = nextTuples
nextTuples = []
}
return solutions;
}
const v = [1,1,1,1,1,2,2,2,3,3,3,4,0,0]
const S = 7
console.log('v:', v.join(','), 'and S:',S)
console.log(nodupes(v, 7).map(t=>t.toString()).join('\n'))

Longest consecutive path in a matrix of letters

I'm trying to solve this problem:
Given a matrix of n * m, with letters(characters), find the longest consecutive path of letters in the matrix and output the string. For example:
m = [[a,c,d],[i,b,e],[h,g,f]]
result = e,f,g,h
You can only move up, down, left, right inside the matrix. This is what I have come up so far following some information online, but I'm not all the way there.
I would also like to make the solution efficient, my current code might have too many loops and is probably slow for a large matrix. Any help would be really appreciated!
R = len(matrix)
C = len(matrix[0])
x = [0, 1, 0, -1]
y = [1, 0, -1, 0]
dp=[[0 for i in range(C)]for i in range(R)]
def isvalid( i, j):
if (i < 0 or j < 0 or i >= R or j >= C):
return False
return True
def getLenUtil(matrix, i, j, prev):
if (isvalid(i, j)==False or isadjacent(prev, mat[i][j])==False):
return 0
if (dp[i][j] != -1):
return dp[i][j]
ans = 0
for k in range(4):
ans = max(ans, 1 + getLenUtil(mat, i + x[k],j + y[k], mat[i][j]))
dp[i][j] = ans
return dp[i][j]
def isadjacent(prev, curr):
if (ord(curr) -ord(prev)) == 1:
return True
return False
def findLongestSequence(matrix):
for i in range(R):
for j in range(C):
dp[i][j]=-1
ans = 0
for i in range(R):
for j in range(C):
if (mat[i][j] == s):
for k in range(4):
ans = max(ans, 1 + getLenUtil(matrix, i + x[k], j + y[k], s));
return ans
Several issues in your code:
mat and matrix spelling should be unified.
s is never initialised
In R = len(matrix) and several other references to mat or matrix, that variable is not defined. findLongestSequence is called with the actual value of matrix, so it is there there R should be defined, ...etc
Also,
it is easier if you don't pass prev, but the actual expected character (that is already "incremented").
Why first initialise dp with zeroes, when then you re-initialise with -1? Just use -1 immediately.
Here is how it could work:
def findLongestSequence(mat):
R = len(mat)
C = len(mat[0])
x = [0, 1, 0, -1]
y = [1, 0, -1, 0]
dp = [[-1 for i in range(C)] for i in range(R)]
def isvalid( i, j):
return (0 <= i < R) and (0 <= j < C)
def getLenUtil(mat, i, j, expected):
if not isvalid(i, j) or mat[i][j] != expected:
return 0
if dp[i][j] == -1:
ans = 0
expected = chr(ord(mat[i][j])+1)
for k in range(4):
ans = max(ans, 1 + getLenUtil(mat, i + x[k], j + y[k], expected))
dp[i][j] = ans
return dp[i][j]
ans = 0
for i in range(R):
for j in range(C):
getLenUtil(mat, i, j, mat[i][j])
ans = max(ans, max(dp[i]))
print(dp)
return ans
res = findLongestSequence([["a","c","d"],["i","b","e"],["h","g","f"]])
print(res)
Note that for this example data the returned answer is 8, not 4, as the longest sequence starts with "b" and ends with "i" -- 8 characters in total.

Hourglass Array Submission error

I am trying to solve the hourglass problem on hackerrank.you can find the details of problem here (https://www.hackerrank.com/challenges/2d-array).
On my machine code works fine and give correct results even for the testcase that gives error on hackerrank.
Here is the code:
maxSum = -70
#hourglass = []
arr = [[int(input()) for x in range(0,6)] for y in range(0,6)]
for row in range(0,6):
for col in range(0,6):
if (row + 2) < 6 and (col + 2) < 6 :
sum = arr[row][col] + arr[row][col+1] + arr[row][col+2] + arr[row+1][col+1] + arr[row+2][col] + arr[row+2][col+1] + arr[row+2][col+2]
if sum > maxSum:
#hourglass.append(arr[row][col])
#hourglass.append(arr[row][col+1])
#hourglass.append(arr[row][col+2])
#hourglass.append(arr[row+1][col+1])
#hourglass.append(arr[row+2][col])
#hourglass.append(arr[row+2][col+1])
#hourglass.append(arr[row+2][col+2])
maxSum = sum
print(maxSum)
#print(hourglass)
Following error rased while running code:
Traceback (most recent call last):
File "solution.py", line 4, in <module>
arr = [[int(input()) for x in range(0,6)] for y in range(0,6)]
File "solution.py", line 4, in <listcomp>
arr = [[int(input()) for x in range(0,6)] for y in range(0,6)]
File "solution.py", line 4, in <listcomp>
arr = [[int(input()) for x in range(0,6)] for y in range(0,6)]
ValueError: invalid literal for int() with base 10: '1 1 1 0 0 0'
The testcase for which error is raised is:
1 1 1 0 0 0
0 1 0 0 0 0
1 1 1 0 0 0
0 9 2 -4 -4 0
0 0 0 -2 0 0
0 0 -1 -2 -4 0
Solution in Python:
#!/bin/python3
import sys
arr = []
matt = []
v_sum = 0
for arr_i in range(6):
arr_t = [int(arr_temp) for arr_temp in input().strip().split(' ')]
arr.append(arr_t)
for i in range(len(arr)-2):
for j in range(len(arr)-2):
v_sum = arr[i][j]+arr[i][j+1]+arr[i][j+2]+arr[i+1][j+1]+arr[i+2][j]+arr[i+2][j+1] + arr[i+2][j+2]
matt.append(v_sum)
total = max(matt)
print (total)
In C# , I can provide you a very simple solution of famous hourglass problem. Below solution has been tested for 10 test cases.
class Class1
{
static int[][] CreateHourGlassForIndexAndSumIt(int p, int q, int[][] arr)
{
int[][] hourGlass = new int[3][];
int x = 0, y = 0;
for (int i = p; i <= p + 2; i++)
{
hourGlass[x] = new int[3];
int[] temp = new int[3];
int k = 0;
for (int j = q; j <= q + 2; j++)
{
temp[k] = arr[i][j];
k++;
}
hourGlass[x] = temp;
x++;
}
return hourGlass;
}
static int findSumOfEachHourGlass(int[][] arr)
{
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
for (int j = 0; j < arr.Length; j++)
{
if (!((i == 1 && j == 0) || (i == 1 && j == 2)))
sum += arr[i][j];
}
}
return sum;
}
static void Main(string[] args)
{
int[][] arr = new int[6][];
for (int arr_i = 0; arr_i < 6; arr_i++)
{
string[] arr_temp = Console.ReadLine().Split(' ');
arr[arr_i] = Array.ConvertAll(arr_temp, Int32.Parse);
}
int[] sum = new int[16];
int k = 0;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
int[][] hourGlass = CreateHourGlassForIndexAndSumIt(i, j, arr);
sum[k] = findSumOfEachHourGlass(hourGlass);
k++;
}
}
//max in sum array
Console.WriteLine(sum.Max());
}
}
Thanks,
Ankit Bajpai
Consider the Array of dimension NxN
indexarr = [x for x in xrange(N-2)]
summ=0
for i in indexarr:
for j in indexarr:
for iter_j in xrange(3):
summ += arr[i][j+iter_j] + arr[i+2][j+iter_j]
summ += arr[i+1][j+1]
if i == 0 and j==0:
maxm=summ
if summ > maxm:
maxm = summ
summ = 0
print maxm
This is how I tacked it.
def gethourglass(matrix, row, col):
sum = 0
sum+= matrix[row-1][col-1]
sum+= matrix[row-1][col]
sum+= matrix[row-1][col+1]
sum+= matrix[row][col]
sum+= matrix[row+1][col-1]
sum+= matrix[row+1][col]
sum+= matrix[row+1][col+1]
return sum
def hourglassSum(arr):
maxTotal = -63
for i in range(1, 5):
for j in range(1, 5):
total = gethourglass(arr, i, j)
if total > maxTotal:
maxTotal = total
return maxTotal
Few test cases get failed as we ignore the constraints given for the given problem.
For example,
Constraints
1. -9<=arr[i][j]<=9, it means element of the given array will always between -9 to 9, it can not be 10 or anything else.
2. 0<=i,j<=5
So the max sum will be on range (-63 to 63).
Keep the maxSumValue according to the constraints given or you may use list, append all the sum values, then return the max list value.
Hope this helps in passing your all test cases.
The attractiveness of this algorithm bears a resemblance to CNN (Convolutional Neural Networks); with minor exceptions, such as: 3x3 Kernel size has fixed sparse points (i.e. the [size(3,1), size(1,1), size(3,1)] the second row was delimited by the corners/edges), striding/sliding is always 1 (but, in practice you might change to >=1 (e.g. deep CNN reduces number of filters of a NN, as a heuristic regularization approach to avoid overfitting), and padding was not taken into considerations (i.e. if a list meets its end, instead of continue to next rows(lists), it moves the next ranges to the being of the list, e.g. [0,1,2,3]:
[0,1,2] -> [1,2,3] -> [2,3,0] -> [3,0,1]).
def hourglassSum(arr):
Kernel_size = (3, 3)
stride = 1
memory = []
for i in range(0,Kernel_size[0]+1, stride):
for j in range(0, Kernel_size[1]+1, stride):
hour_glass_sum = sum(arr[i][j:3+j]) + arr[i+1][1+j] + sum(arr[i+2][j:3+j])
memory.append(hour_glass_sum)
return max(memory)

Algorithm to find added/removed elements in an array

I am looking for the most efficent way of solving the following
Problem:
given an array Before = { 8, 7, 2, 1} and an array After ={1, 3, 8, 8}
find the added and the removed elements
the solution is:
added = 3, 8
removed = 7, 2
My idea so far is:
for i = 0 .. B.Lenghtt-1
{
for j= 0 .. A.Lenght-1
{
if A[j] == B[i]
A[j] = 0;
B[i] = 0;
break;
}
}
// B elemnts different from 0 are the Removed elements
// A elemnts different from 0 are the Added elemnts
Does anyone know a better solution perhaps more efficent and that doesn't overwrite the original arrays
Sorting is your friend.
Sort the two arrays (a and b), and then walk them (using x and y as counters). Move down both 1 at a time. You can derive all your tests from there:
if a[x] < b[y], then a[x] was removed (and only increment x)
if a[x] > b[y], then b[y] was added (and only increment y)
(I may have missed an edge case, but you get the general idea.)
(edit: the primary edge case that isn't covered here is handling when you reach the end of one of the arrays before the other, but it's not hard to figure out. :)
You could also use a Dictionary<int, int> and a algorithm similar to this:
foreach i in source_list: dictionary[i]++;
foreach i in dest_list: dictionary[i]--;
The final dictionary tells you which elements were inserted/removed (and how often). This solution should be quite fast even for bigger lists - faster than sorting.
if your language as multiset available (set with count of elements) your question is a standard operation.
B = multiset(Before)
A = multiset(After)
result is A.symdiff(B) (symdiff is union minus intersection and that is exactly what you are looking for to have removed and added).
Obviously you can also get removed only or added only using classical difference between sets.
It can trivially be implemented using hashes and it's O(n) (using sort is slightly less efficient as it is O(n.log(n)) because of the sort itself).
In some sort of C++ pseudo code:
Before.sort();
After.sort();
int i = 0;
int j = 0;
for (; i < Before.size() && j < After.size(); ) {
if (Before[i] < After[j]) {
Removed.add(Before[i]);
++i;
continue;
}
if (Before[i] > After[j]) {
Added.add(After[j]);
++j;
continue;
}
++i;
++j;
}
for (; i < Before.size(); ++i) {
Removed.add(Before[i]);
}
for (; j < After.size(); ++j) {
Added.add(After[j]);
}
This can be solved in linear time.
Create a map for calculating the number of repetitions of each element.
Go through the before array and fill the map.
Go through the after array and decrease the value in the map for each element.
At the end, go through the map and if you find a negative value, that element was added - if positive, that element was removed.
Here is some Java code for this (not tested, just written right now):
Map<Integer, Integer> repetitionMap = new HashMap<Integer, Integer>();
for (int i = 0; i < before.length; i++) {
Integer number = repetitionMap.get(before[i]);
if (number == null) {
repetitionMap.put(before[i], 1);
} else {
repetitionMap.put(before[i], number + 1);
}
}
for (int i = 0; i < after.length; i++) {
Integer number = repetitionMap.get(after[i]);
if (number == null) {
repetitionMap.put(after[i], -1);
} else {
repetitionMap.put(after[i], number - 1);
}
}
Set<Integer> keySet = repetitionMap.keySet();
for (Integer i : keySet) {
Integer number = repetitionMap.get(i);
if (number > 0) {
System.out.println("removed " + number + "times value " + i);
}
if (number < 0) {
System.out.println("added " + number + "times value " + i);
}
}
perl:
#a = ( 8, 7, 2, 2, 1 );
#b = ( 1, 3, 8, 8, 8 );
$d{$_}++ for(#a);
$d{$_}-- for(#b);
print"added = ";
for(keys %d){print "$_ " x (-$d{$_}) if($d{$_}<0)}
print"\n";
print"removed = ";
for(keys %d){print "$_ " x ($d{$_}) if($d{$_}>0)}
print"\n";
result:
$ ./inout.pl
added = 8 8 3
removed = 7 2 2
In Groovy:
def before = [8, 7, 2, 1, 1, 1], after = [1, 3, 8, 8, 8]
def added = before.countBy{it}
def result = after.inject(added){map, a -> map[a] ? map << [(a):map[a] - 1]: map << [(a):-1]}
.inject([:]){m, k, v -> v == 0 ? (m << [:]) : (v < 0 ? m << [(k):"added ${v.abs()} times"] : m << [(k):"removed ${v.abs()} times"])}
println "before $before\nafter $after"
println "result: $result"
Result:
before [8, 7, 2, 1, 1, 1]
after [1, 3, 8, 8, 8]
result: [8:added 2 times, 7:removed 1 times, 2:removed 1 times, 1:removed 2 times, 3:added 1 times]
For countBy I got insipred from Some groovy magic post
In groovy inject is like reduce in other functional languages.
I also refer Groovy collection api slides from Trygve Amundsen with really good table with functional methods
Second solution:
def before = [8, 7, 2, 1, 1, 1], after = [1, 3, 8, 8, 8]
def sb = before.countBy{it}
def sa = after.countBy{it}
def result = sa.inject(sb){m, k, v -> m[k] ? m << [(k): m[k] - v] : m << [(k): -v]}
.inject([:]){m, k, v -> v == 0 ? (m << [:]) : (v < 0 ? m << [(k):"added ${v.abs()} times"] : m << [(k):"removed ${v.abs()} times"])}

Resources