Longest consecutive path in a matrix of letters - arrays

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.

Related

Given two arrays and an upper limit, what is the most efficient way to get the index pair for which the sum is maximum and below the upper limit?

Given two arrays A and B and an upper limit k, what will the most efficient way to compute the index pair (i, j) such that given,
s = A[i] + B[j]
s = max(A[a] + B[b]) for a = 0, 1, 2, .. , len(A)-1 and b = 0, 1, 2, .. , len(B)-1
and
s < k
For example,
Given,
A = [9,2,5]
B = [2,1,6]
k = 5
we get,
s = 2 + 2 = 4 < 5
and hence,
i = 1 and j = 0
So the output should be (1,0)
A straight-forward approach would be looping through all the elements of A and B but that would make the worst case time complexity O(nm) where n = len(A) and m = len(B).
Is there a better way to solve this problem?
This type of problems can be solved by sorting one of the array.
One Approach could be this ::
make an array temp of tuples such that each tuple will be (value,index) where value is item of B and index is its corresponding index in B.
Now, sort this temp array with respect to first item of tuple i.e, value.
iterate through array A and using Binary Search find the Lower bound of K - A[i] in temp array. let it be at index j.
Now there are two possibilities, either A[ i ] + temp[ j ][ 0 ] > = K or < k.
If it is greater than K, than check if j - 1 exists or not and update currentMaximum if possible because this pair can be max and at the same time less than k because we found lower bound.
If it is less than K, than update currentMaximum if possible.
If you need indices than whenever you update you currentMaximum, store i and j.
In this way you can find maximum sum of pairs such that it is less than K with original index as given in array B
If order of elements does not matter than, just sort B and do same steps on B instead of temp.
Time Complexity
For sorting = O( len(B) * Log(len(B)) )
for traversing A and doing Binary Search on B = O ( len(A) * Log (len(B))) i.e, O ( nlog(n))
You can use sort for A and B. Then you can use an early break once you are >= k. The function below returns indices, s.t. A[i] + B[j] < k and A[p] + B[q] < A[i] + B[j], for all p < i and for all q < j.
def sum_less_than_k(A, B, k):
i_max = -1
j_max = -1
s_max = -np.inf
for i, a in enumerate(A):
if a + B[0] >= k:
break
for j, b in enumerate(B):
if a + b >= k:
break
if a + b > s_max:
s_max = a + b
i_max = i
j_max = j
return i_max, j_max
A.sort()
B.sort()
i, j = sum_less_than_k(A, B, k)
I wrote the code for Saurab's suggestion as well which is way faster for large k relative to what's in the list. However, for rather short lists or small k the two for loops are faster according to some sample runs.
def sum_less_than_k(A, B, k):
i_max = j_max = -1
s_max = -np.inf
for i, a in enumerate(A):
j = bisect(B, k - a - 1)
if len(B) > j > -1 and k > A[i] + B[j] > s_max:
s_max = A[i] + B[j]
i_max = i
j_max = j
return i_max, j_max
B.sort()
i, j = sum_less_than_k(A, B, k)

Find the number of triplets i,j,k in an array such that the xor of elements indexed i to j-1 is equal to the xor of elements indexed j to k

For a given sequence of positive integers A1,A2,…,AN, you are supposed to find the number of triplets (i,j,k) such that Ai^Ai+1^..^Aj-1=Aj^Aj+1^..Ak
where ^ denotes bitwise XOR.
The link to the question is here: https://www.codechef.com/AUG19B/problems/KS1
All I did is try to find all subarrays with xor 0. The solution works but is quadratic time and thus too slow.
This is the solution that I managed to get to.
for (int i = 0; i < arr.length; i++) {
int xor = arr[i];
for (int j = i + 1; j < arr.length; j++) {
xor ^= arr[j];
if (xor == 0) {
ans += (j - i);
}
}
}
finAns.append(ans + "\n");
Here's an O(n) solution based on CiaPan's comment under the question description:
If xor of items at indices I through J-1 equals that from J to K, then xor from I to K equals zero. And for any such subarray [I .. K] every J between I+1 and K-1 makes a triplet satisfying the requirements. And xor from I to K equals (xor from 0 to K) xor (xor from 0 to I-1). So I suppose you might find xor-s of all possible initial parts of the sequence and look for equal pairs of them.
The function f is the main method. brute_force is used for validation.
Python 2.7 code:
import random
def brute_force(A):
res = 0
for i in xrange(len(A) - 1):
left = A[i]
for j in xrange(i + 1, len(A)):
if j > i + 1:
left ^= A[j - 1]
right = A[j]
for k in xrange(j, len(A)):
if k > j:
right ^= A[k]
if left == right:
res += 1
return res
def f(A):
ps = [A[0]] + [0] * (len(A) - 1)
for i in xrange(1, len(A)):
ps[i] = ps[i- 1] ^ A[i]
res = 0
seen = {0: (-1, 1, 0)}
for i in xrange(len(A)):
if ps[i] in seen:
prev_i, i_count, count = seen[ps[i]]
new_count = count + i_count * (i - prev_i) - 1
res += new_count
seen[ps[i]] = (i, i_count + 1, new_count)
else:
seen[ps[i]] = (i, 1, 0)
return res
for i in xrange(100):
A = [random.randint(1, 10) for x in xrange(200)]
f_A, brute_force_A = f(A), brute_force(A)
assert f_A == brute_force_A
print "Done"

Combination (mathematical) of structs [duplicate]

I want to write a function that takes an array of letters as an argument and a number of those letters to select.
Say you provide an array of 8 letters and want to select 3 letters from that. Then you should get:
8! / ((8 - 3)! * 3!) = 56
Arrays (or words) in return consisting of 3 letters each.
Art of Computer Programming Volume 4: Fascicle 3 has a ton of these that might fit your particular situation better than how I describe.
Gray Codes
An issue that you will come across is of course memory and pretty quickly, you'll have problems by 20 elements in your set -- 20C3 = 1140. And if you want to iterate over the set it's best to use a modified gray code algorithm so you aren't holding all of them in memory. These generate the next combination from the previous and avoid repetitions. There are many of these for different uses. Do we want to maximize the differences between successive combinations? minimize? et cetera.
Some of the original papers describing gray codes:
Some Hamilton Paths and a Minimal Change Algorithm
Adjacent Interchange Combination Generation Algorithm
Here are some other papers covering the topic:
An Efficient Implementation of the Eades, Hickey, Read Adjacent Interchange Combination Generation Algorithm (PDF, with code in Pascal)
Combination Generators
Survey of Combinatorial Gray Codes (PostScript)
An Algorithm for Gray Codes
Chase's Twiddle (algorithm)
Phillip J Chase, `Algorithm 382: Combinations of M out of N Objects' (1970)
The algorithm in C...
Index of Combinations in Lexicographical Order (Buckles Algorithm 515)
You can also reference a combination by its index (in lexicographical order). Realizing that the index should be some amount of change from right to left based on the index we can construct something that should recover a combination.
So, we have a set {1,2,3,4,5,6}... and we want three elements. Let's say {1,2,3} we can say that the difference between the elements is one and in order and minimal. {1,2,4} has one change and is lexicographically number 2. So the number of 'changes' in the last place accounts for one change in the lexicographical ordering. The second place, with one change {1,3,4} has one change but accounts for more change since it's in the second place (proportional to the number of elements in the original set).
The method I've described is a deconstruction, as it seems, from set to the index, we need to do the reverse – which is much trickier. This is how Buckles solves the problem. I wrote some C to compute them, with minor changes – I used the index of the sets rather than a number range to represent the set, so we are always working from 0...n.
Note:
Since combinations are unordered, {1,3,2} = {1,2,3} --we order them to be lexicographical.
This method has an implicit 0 to start the set for the first difference.
Index of Combinations in Lexicographical Order (McCaffrey)
There is another way:, its concept is easier to grasp and program but it's without the optimizations of Buckles. Fortunately, it also does not produce duplicate combinations:
The set that maximizes , where .
For an example: 27 = C(6,4) + C(5,3) + C(2,2) + C(1,1). So, the 27th lexicographical combination of four things is: {1,2,5,6}, those are the indexes of whatever set you want to look at. Example below (OCaml), requires choose function, left to reader:
(* this will find the [x] combination of a [set] list when taking [k] elements *)
let combination_maccaffery set k x =
(* maximize function -- maximize a that is aCb *)
(* return largest c where c < i and choose(c,i) <= z *)
let rec maximize a b x =
if (choose a b ) <= x then a else maximize (a-1) b x
in
let rec iterate n x i = match i with
| 0 -> []
| i ->
let max = maximize n i x in
max :: iterate n (x - (choose max i)) (i-1)
in
if x < 0 then failwith "errors" else
let idxs = iterate (List.length set) x k in
List.map (List.nth set) (List.sort (-) idxs)
A small and simple combinations iterator
The following two algorithms are provided for didactic purposes. They implement an iterator and (a more general) folder overall combinations.
They are as fast as possible, having the complexity O(nCk). The memory consumption is bound by k.
We will start with the iterator, which will call a user provided function for each combination
let iter_combs n k f =
let rec iter v s j =
if j = k then f v
else for i = s to n - 1 do iter (i::v) (i+1) (j+1) done in
iter [] 0 0
A more general version will call the user provided function along with the state variable, starting from the initial state. Since we need to pass the state between different states we won't use the for-loop, but instead, use recursion,
let fold_combs n k f x =
let rec loop i s c x =
if i < n then
loop (i+1) s c ##
let c = i::c and s = s + 1 and i = i + 1 in
if s < k then loop i s c x else f c x
else x in
loop 0 0 [] x
In C#:
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] {e}).Concat(c)));
}
Usage:
var result = Combinations(new[] { 1, 2, 3, 4, 5 }, 3);
Result:
123
124
125
134
135
145
234
235
245
345
Short java solution:
import java.util.Arrays;
public class Combination {
public static void main(String[] args){
String[] arr = {"A","B","C","D","E","F"};
combinations2(arr, 3, 0, new String[3]);
}
static void combinations2(String[] arr, int len, int startPosition, String[] result){
if (len == 0){
System.out.println(Arrays.toString(result));
return;
}
for (int i = startPosition; i <= arr.length-len; i++){
result[result.length - len] = arr[i];
combinations2(arr, len-1, i+1, result);
}
}
}
Result will be
[A, B, C]
[A, B, D]
[A, B, E]
[A, B, F]
[A, C, D]
[A, C, E]
[A, C, F]
[A, D, E]
[A, D, F]
[A, E, F]
[B, C, D]
[B, C, E]
[B, C, F]
[B, D, E]
[B, D, F]
[B, E, F]
[C, D, E]
[C, D, F]
[C, E, F]
[D, E, F]
May I present my recursive Python solution to this problem?
def choose_iter(elements, length):
for i in xrange(len(elements)):
if length == 1:
yield (elements[i],)
else:
for next in choose_iter(elements[i+1:], length-1):
yield (elements[i],) + next
def choose(l, k):
return list(choose_iter(l, k))
Example usage:
>>> len(list(choose_iter("abcdefgh",3)))
56
I like it for its simplicity.
Lets say your array of letters looks like this: "ABCDEFGH". You have three indices (i, j, k) indicating which letters you are going to use for the current word, You start with:
A B C D E F G H
^ ^ ^
i j k
First you vary k, so the next step looks like that:
A B C D E F G H
^ ^ ^
i j k
If you reached the end you go on and vary j and then k again.
A B C D E F G H
^ ^ ^
i j k
A B C D E F G H
^ ^ ^
i j k
Once you j reached G you start also to vary i.
A B C D E F G H
^ ^ ^
i j k
A B C D E F G H
^ ^ ^
i j k
...
Written in code this look something like that
void print_combinations(const char *string)
{
int i, j, k;
int len = strlen(string);
for (i = 0; i < len - 2; i++)
{
for (j = i + 1; j < len - 1; j++)
{
for (k = j + 1; k < len; k++)
printf("%c%c%c\n", string[i], string[j], string[k]);
}
}
}
The following recursive algorithm picks all of the k-element combinations from an ordered set:
choose the first element i of your combination
combine i with each of the combinations of k-1 elements chosen recursively from the set of elements larger than i.
Iterate the above for each i in the set.
It is essential that you pick the rest of the elements as larger than i, to avoid repetition. This way [3,5] will be picked only once, as [3] combined with [5], instead of twice (the condition eliminates [5] + [3]). Without this condition you get variations instead of combinations.
Short example in Python:
def comb(sofar, rest, n):
if n == 0:
print sofar
else:
for i in range(len(rest)):
comb(sofar + rest[i], rest[i+1:], n-1)
>>> comb("", "abcde", 3)
abc
abd
abe
acd
ace
ade
bcd
bce
bde
cde
For explanation, the recursive method is described with the following example:
Example: A B C D E
All combinations of 3 would be:
A with all combinations of 2 from the rest (B C D E)
B with all combinations of 2 from the rest (C D E)
C with all combinations of 2 from the rest (D E)
I found this thread useful and thought I would add a Javascript solution that you can pop into Firebug. Depending on your JS engine, it could take a little time if the starting string is large.
function string_recurse(active, rest) {
if (rest.length == 0) {
console.log(active);
} else {
string_recurse(active + rest.charAt(0), rest.substring(1, rest.length));
string_recurse(active, rest.substring(1, rest.length));
}
}
string_recurse("", "abc");
The output should be as follows:
abc
ab
ac
a
bc
b
c
In C++ the following routine will produce all combinations of length distance(first,k) between the range [first,last):
#include <algorithm>
template <typename Iterator>
bool next_combination(const Iterator first, Iterator k, const Iterator last)
{
/* Credits: Mark Nelson http://marknelson.us */
if ((first == last) || (first == k) || (last == k))
return false;
Iterator i1 = first;
Iterator i2 = last;
++i1;
if (last == i1)
return false;
i1 = last;
--i1;
i1 = k;
--i2;
while (first != i1)
{
if (*--i1 < *i2)
{
Iterator j = k;
while (!(*i1 < *j)) ++j;
std::iter_swap(i1,j);
++i1;
++j;
i2 = k;
std::rotate(i1,j,last);
while (last != j)
{
++j;
++i2;
}
std::rotate(k,i2,last);
return true;
}
}
std::rotate(first,k,last);
return false;
}
It can be used like this:
#include <string>
#include <iostream>
int main()
{
std::string s = "12345";
std::size_t comb_size = 3;
do
{
std::cout << std::string(s.begin(), s.begin() + comb_size) << std::endl;
} while (next_combination(s.begin(), s.begin() + comb_size, s.end()));
return 0;
}
This will print the following:
123
124
125
134
135
145
234
235
245
345
static IEnumerable<string> Combinations(List<string> characters, int length)
{
for (int i = 0; i < characters.Count; i++)
{
// only want 1 character, just return this one
if (length == 1)
yield return characters[i];
// want more than one character, return this one plus all combinations one shorter
// only use characters after the current one for the rest of the combinations
else
foreach (string next in Combinations(characters.GetRange(i + 1, characters.Count - (i + 1)), length - 1))
yield return characters[i] + next;
}
}
Simple recursive algorithm in Haskell
import Data.List
combinations 0 lst = [[]]
combinations n lst = do
(x:xs) <- tails lst
rest <- combinations (n-1) xs
return $ x : rest
We first define the special case, i.e. selecting zero elements. It produces a single result, which is an empty list (i.e. a list that contains an empty list).
For n > 0, x goes through every element of the list and xs is every element after x.
rest picks n - 1 elements from xs using a recursive call to combinations. The final result of the function is a list where each element is x : rest (i.e. a list which has x as head and rest as tail) for every different value of x and rest.
> combinations 3 "abcde"
["abc","abd","abe","acd","ace","ade","bcd","bce","bde","cde"]
And of course, since Haskell is lazy, the list is gradually generated as needed, so you can partially evaluate exponentially large combinations.
> let c = combinations 8 "abcdefghijklmnopqrstuvwxyz"
> take 10 c
["abcdefgh","abcdefgi","abcdefgj","abcdefgk","abcdefgl","abcdefgm","abcdefgn",
"abcdefgo","abcdefgp","abcdefgq"]
And here comes granddaddy COBOL, the much maligned language.
Let's assume an array of 34 elements of 8 bytes each (purely arbitrary selection.) The idea is to enumerate all possible 4-element combinations and load them into an array.
We use 4 indices, one each for each position in the group of 4
The array is processed like this:
idx1 = 1
idx2 = 2
idx3 = 3
idx4 = 4
We vary idx4 from 4 to the end. For each idx4 we get a unique combination
of groups of four. When idx4 comes to the end of the array, we increment idx3 by 1 and set idx4 to idx3+1. Then we run idx4 to the end again. We proceed in this manner, augmenting idx3,idx2, and idx1 respectively until the position of idx1 is less than 4 from the end of the array. That finishes the algorithm.
1 --- pos.1
2 --- pos 2
3 --- pos 3
4 --- pos 4
5
6
7
etc.
First iterations:
1234
1235
1236
1237
1245
1246
1247
1256
1257
1267
etc.
A COBOL example:
01 DATA_ARAY.
05 FILLER PIC X(8) VALUE "VALUE_01".
05 FILLER PIC X(8) VALUE "VALUE_02".
etc.
01 ARAY_DATA OCCURS 34.
05 ARAY_ITEM PIC X(8).
01 OUTPUT_ARAY OCCURS 50000 PIC X(32).
01 MAX_NUM PIC 99 COMP VALUE 34.
01 INDEXXES COMP.
05 IDX1 PIC 99.
05 IDX2 PIC 99.
05 IDX3 PIC 99.
05 IDX4 PIC 99.
05 OUT_IDX PIC 9(9).
01 WHERE_TO_STOP_SEARCH PIC 99 COMP.
* Stop the search when IDX1 is on the third last array element:
COMPUTE WHERE_TO_STOP_SEARCH = MAX_VALUE - 3
MOVE 1 TO IDX1
PERFORM UNTIL IDX1 > WHERE_TO_STOP_SEARCH
COMPUTE IDX2 = IDX1 + 1
PERFORM UNTIL IDX2 > MAX_NUM
COMPUTE IDX3 = IDX2 + 1
PERFORM UNTIL IDX3 > MAX_NUM
COMPUTE IDX4 = IDX3 + 1
PERFORM UNTIL IDX4 > MAX_NUM
ADD 1 TO OUT_IDX
STRING ARAY_ITEM(IDX1)
ARAY_ITEM(IDX2)
ARAY_ITEM(IDX3)
ARAY_ITEM(IDX4)
INTO OUTPUT_ARAY(OUT_IDX)
ADD 1 TO IDX4
END-PERFORM
ADD 1 TO IDX3
END-PERFORM
ADD 1 TO IDX2
END_PERFORM
ADD 1 TO IDX1
END-PERFORM.
Another C# version with lazy generation of the combination indices. This version maintains a single array of indices to define a mapping between the list of all values and the values for the current combination, i.e. constantly uses O(k) additional space during the entire runtime. The code generates individual combinations, including the first one, in O(k) time.
public static IEnumerable<T[]> Combinations<T>(this T[] values, int k)
{
if (k < 0 || values.Length < k)
yield break; // invalid parameters, no combinations possible
// generate the initial combination indices
var combIndices = new int[k];
for (var i = 0; i < k; i++)
{
combIndices[i] = i;
}
while (true)
{
// return next combination
var combination = new T[k];
for (var i = 0; i < k; i++)
{
combination[i] = values[combIndices[i]];
}
yield return combination;
// find first index to update
var indexToUpdate = k - 1;
while (indexToUpdate >= 0 && combIndices[indexToUpdate] >= values.Length - k + indexToUpdate)
{
indexToUpdate--;
}
if (indexToUpdate < 0)
yield break; // done
// update combination indices
for (var combIndex = combIndices[indexToUpdate] + 1; indexToUpdate < k; indexToUpdate++, combIndex++)
{
combIndices[indexToUpdate] = combIndex;
}
}
}
Test code:
foreach (var combination in new[] {'a', 'b', 'c', 'd', 'e'}.Combinations(3))
{
System.Console.WriteLine(String.Join(" ", combination));
}
Output:
a b c
a b d
a b e
a c d
a c e
a d e
b c d
b c e
b d e
c d e
Here is an elegant, generic implementation in Scala, as described on 99 Scala Problems.
object P26 {
def flatMapSublists[A,B](ls: List[A])(f: (List[A]) => List[B]): List[B] =
ls match {
case Nil => Nil
case sublist#(_ :: tail) => f(sublist) ::: flatMapSublists(tail)(f)
}
def combinations[A](n: Int, ls: List[A]): List[List[A]] =
if (n == 0) List(Nil)
else flatMapSublists(ls) { sl =>
combinations(n - 1, sl.tail) map {sl.head :: _}
}
}
If you can use SQL syntax - say, if you're using LINQ to access fields of an structure or array, or directly accessing a database that has a table called "Alphabet" with just one char field "Letter", you can adapt following code:
SELECT A.Letter, B.Letter, C.Letter
FROM Alphabet AS A, Alphabet AS B, Alphabet AS C
WHERE A.Letter<>B.Letter AND A.Letter<>C.Letter AND B.Letter<>C.Letter
AND A.Letter<B.Letter AND B.Letter<C.Letter
This will return all combinations of 3 letters, notwithstanding how many letters you have in table "Alphabet" (it can be 3, 8, 10, 27, etc.).
If what you want is all permutations, rather than combinations (i.e. you want "ACB" and "ABC" to count as different, rather than appear just once) just delete the last line (the AND one) and it's done.
Post-Edit: After re-reading the question, I realise what's needed is the general algorithm, not just a specific one for the case of selecting 3 items. Adam Hughes' answer is the complete one, unfortunately I cannot vote it up (yet). This answer's simple but works only for when you want exactly 3 items.
I had a permutation algorithm I used for project euler, in python:
def missing(miss,src):
"Returns the list of items in src not present in miss"
return [i for i in src if i not in miss]
def permutation_gen(n,l):
"Generates all the permutations of n items of the l list"
for i in l:
if n<=1: yield [i]
r = [i]
for j in permutation_gen(n-1,missing([i],l)): yield r+j
If
n<len(l)
you should have all combination you need without repetition, do you need it?
It is a generator, so you use it in something like this:
for comb in permutation_gen(3,list("ABCDEFGH")):
print comb
https://gist.github.com/3118596
There is an implementation for JavaScript. It has functions to get k-combinations and all combinations of an array of any objects. Examples:
k_combinations([1,2,3], 2)
-> [[1,2], [1,3], [2,3]]
combinations([1,2,3])
-> [[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
Lets say your array of letters looks like this: "ABCDEFGH". You have three indices (i, j, k) indicating which letters you are going to use for the current word, You start with:
A B C D E F G H
^ ^ ^
i j k
First you vary k, so the next step looks like that:
A B C D E F G H
^ ^ ^
i j k
If you reached the end you go on and vary j and then k again.
A B C D E F G H
^ ^ ^
i j k
A B C D E F G H
^ ^ ^
i j k
Once you j reached G you start also to vary i.
A B C D E F G H
^ ^ ^
i j k
A B C D E F G H
^ ^ ^
i j k
...
function initializePointers($cnt) {
$pointers = [];
for($i=0; $i<$cnt; $i++) {
$pointers[] = $i;
}
return $pointers;
}
function incrementPointers(&$pointers, &$arrLength) {
for($i=0; $i<count($pointers); $i++) {
$currentPointerIndex = count($pointers) - $i - 1;
$currentPointer = $pointers[$currentPointerIndex];
if($currentPointer < $arrLength - $i - 1) {
++$pointers[$currentPointerIndex];
for($j=1; ($currentPointerIndex+$j)<count($pointers); $j++) {
$pointers[$currentPointerIndex+$j] = $pointers[$currentPointerIndex]+$j;
}
return true;
}
}
return false;
}
function getDataByPointers(&$arr, &$pointers) {
$data = [];
for($i=0; $i<count($pointers); $i++) {
$data[] = $arr[$pointers[$i]];
}
return $data;
}
function getCombinations($arr, $cnt)
{
$len = count($arr);
$result = [];
$pointers = initializePointers($cnt);
do {
$result[] = getDataByPointers($arr, $pointers);
} while(incrementPointers($pointers, count($arr)));
return $result;
}
$result = getCombinations([0, 1, 2, 3, 4, 5], 3);
print_r($result);
Based on https://stackoverflow.com/a/127898/2628125, but more abstract, for any size of pointers.
Here you have a lazy evaluated version of that algorithm coded in C#:
static bool nextCombination(int[] num, int n, int k)
{
bool finished, changed;
changed = finished = false;
if (k > 0)
{
for (int i = k - 1; !finished && !changed; i--)
{
if (num[i] < (n - 1) - (k - 1) + i)
{
num[i]++;
if (i < k - 1)
{
for (int j = i + 1; j < k; j++)
{
num[j] = num[j - 1] + 1;
}
}
changed = true;
}
finished = (i == 0);
}
}
return changed;
}
static IEnumerable Combinations<T>(IEnumerable<T> elements, int k)
{
T[] elem = elements.ToArray();
int size = elem.Length;
if (k <= size)
{
int[] numbers = new int[k];
for (int i = 0; i < k; i++)
{
numbers[i] = i;
}
do
{
yield return numbers.Select(n => elem[n]);
}
while (nextCombination(numbers, size, k));
}
}
And test part:
static void Main(string[] args)
{
int k = 3;
var t = new[] { "dog", "cat", "mouse", "zebra"};
foreach (IEnumerable<string> i in Combinations(t, k))
{
Console.WriteLine(string.Join(",", i));
}
}
Hope this help you!
Another version, that forces all the first k to appear firstly, then all the first k+1 combinations, then all the first k+2 etc.. It means that if you have sorted array, the most important on the top, it would take them and expand gradually to the next ones - only when it is must do so.
private static bool NextCombinationFirstsAlwaysFirst(int[] num, int n, int k)
{
if (k > 1 && NextCombinationFirstsAlwaysFirst(num, num[k - 1], k - 1))
return true;
if (num[k - 1] + 1 == n)
return false;
++num[k - 1];
for (int i = 0; i < k - 1; ++i)
num[i] = i;
return true;
}
For instance, if you run the first method ("nextCombination") on k=3, n=5 you'll get:
0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4
2 3 4
But if you'll run
int[] nums = new int[k];
for (int i = 0; i < k; ++i)
nums[i] = i;
do
{
Console.WriteLine(string.Join(" ", nums));
}
while (NextCombinationFirstsAlwaysFirst(nums, n, k));
You'll get this (I added empty lines for clarity):
0 1 2
0 1 3
0 2 3
1 2 3
0 1 4
0 2 4
1 2 4
0 3 4
1 3 4
2 3 4
It's adding "4" only when must to, and also after "4" was added it adds "3" again only when it must to (after doing 01, 02, 12).
Array.prototype.combs = function(num) {
var str = this,
length = str.length,
of = Math.pow(2, length) - 1,
out, combinations = [];
while(of) {
out = [];
for(var i = 0, y; i < length; i++) {
y = (1 << i);
if(y & of && (y !== of))
out.push(str[i]);
}
if (out.length >= num) {
combinations.push(out);
}
of--;
}
return combinations;
}
Clojure version:
(defn comb [k l]
(if (= 1 k) (map vector l)
(apply concat
(map-indexed
#(map (fn [x] (conj x %2))
(comb (dec k) (drop (inc %1) l)))
l))))
Algorithm:
Count from 1 to 2^n.
Convert each digit to its binary representation.
Translate each 'on' bit to elements of your set, based on position.
In C#:
void Main()
{
var set = new [] {"A", "B", "C", "D" }; //, "E", "F", "G", "H", "I", "J" };
var kElement = 2;
for(var i = 1; i < Math.Pow(2, set.Length); i++) {
var result = Convert.ToString(i, 2).PadLeft(set.Length, '0');
var cnt = Regex.Matches(Regex.Escape(result), "1").Count;
if (cnt == kElement) {
for(int j = 0; j < set.Length; j++)
if ( Char.GetNumericValue(result[j]) == 1)
Console.Write(set[j]);
Console.WriteLine();
}
}
}
Why does it work?
There is a bijection between the subsets of an n-element set and n-bit sequences.
That means we can figure out how many subsets there are by counting sequences.
e.g., the four element set below can be represented by {0,1} X {0, 1} X {0, 1} X {0, 1} (or 2^4) different sequences.
So - all we have to do is count from 1 to 2^n to find all the combinations. (We ignore the empty set.) Next, translate the digits to their binary representation. Then substitute elements of your set for 'on' bits.
If you want only k element results, only print when k bits are 'on'.
(If you want all subsets instead of k length subsets, remove the cnt/kElement part.)
(For proof, see MIT free courseware Mathematics for Computer Science, Lehman et al, section 11.2.2. https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-042j-mathematics-for-computer-science-fall-2010/readings/ )
short python code, yielding index positions
def yield_combos(n,k):
# n is set size, k is combo size
i = 0
a = [0]*k
while i > -1:
for j in range(i+1, k):
a[j] = a[j-1]+1
i=j
yield a
while a[i] == i + n - k:
i -= 1
a[i] += 1
All said and and done here comes the O'caml code for that.
Algorithm is evident from the code..
let combi n lst =
let rec comb l c =
if( List.length c = n) then [c] else
match l with
[] -> []
| (h::t) -> (combi t (h::c))#(combi t c)
in
combi lst []
;;
Here is a method which gives you all combinations of specified size from a random length string. Similar to quinmars' solution, but works for varied input and k.
The code can be changed to wrap around, ie 'dab' from input 'abcd' w k=3.
public void run(String data, int howMany){
choose(data, howMany, new StringBuffer(), 0);
}
//n choose k
private void choose(String data, int k, StringBuffer result, int startIndex){
if (result.length()==k){
System.out.println(result.toString());
return;
}
for (int i=startIndex; i<data.length(); i++){
result.append(data.charAt(i));
choose(data,k,result, i+1);
result.setLength(result.length()-1);
}
}
Output for "abcde":
abc abd abe acd ace ade bcd bce bde cde
Short javascript version (ES 5)
let combine = (list, n) =>
n == 0 ?
[[]] :
list.flatMap((e, i) =>
combine(
list.slice(i + 1),
n - 1
).map(c => [e].concat(c))
);
let res = combine([1,2,3,4], 3);
res.forEach(e => console.log(e.join()));
Another python recusive solution.
def combination_indicies(n, k, j = 0, stack = []):
if len(stack) == k:
yield list(stack)
return
for i in range(j, n):
stack.append(i)
for x in combination_indicies(n, k, i + 1, stack):
yield x
stack.pop()
list(combination_indicies(5, 3))
Output:
[[0, 1, 2],
[0, 1, 3],
[0, 1, 4],
[0, 2, 3],
[0, 2, 4],
[0, 3, 4],
[1, 2, 3],
[1, 2, 4],
[1, 3, 4],
[2, 3, 4]]
I created a solution in SQL Server 2005 for this, and posted it on my website: http://www.jessemclain.com/downloads/code/sql/fn_GetMChooseNCombos.sql.htm
Here is an example to show usage:
SELECT * FROM dbo.fn_GetMChooseNCombos('ABCD', 2, '')
results:
Word
----
AB
AC
AD
BC
BD
CD
(6 row(s) affected)
Here is my proposition in C++
I tried to impose as little restriction on the iterator type as i could so this solution assumes just forward iterator, and it can be a const_iterator. This should work with any standard container. In cases where arguments don't make sense it throws std::invalid_argumnent
#include <vector>
#include <stdexcept>
template <typename Fci> // Fci - forward const iterator
std::vector<std::vector<Fci> >
enumerate_combinations(Fci begin, Fci end, unsigned int combination_size)
{
if(begin == end && combination_size > 0u)
throw std::invalid_argument("empty set and positive combination size!");
std::vector<std::vector<Fci> > result; // empty set of combinations
if(combination_size == 0u) return result; // there is exactly one combination of
// size 0 - emty set
std::vector<Fci> current_combination;
current_combination.reserve(combination_size + 1u); // I reserve one aditional slot
// in my vector to store
// the end sentinel there.
// The code is cleaner thanks to that
for(unsigned int i = 0u; i < combination_size && begin != end; ++i, ++begin)
{
current_combination.push_back(begin); // Construction of the first combination
}
// Since I assume the itarators support only incrementing, I have to iterate over
// the set to get its size, which is expensive. Here I had to itrate anyway to
// produce the first cobination, so I use the loop to also check the size.
if(current_combination.size() < combination_size)
throw std::invalid_argument("combination size > set size!");
result.push_back(current_combination); // Store the first combination in the results set
current_combination.push_back(end); // Here I add mentioned earlier sentinel to
// simplyfy rest of the code. If I did it
// earlier, previous statement would get ugly.
while(true)
{
unsigned int i = combination_size;
Fci tmp; // Thanks to the sentinel I can find first
do // iterator to change, simply by scaning
{ // from right to left and looking for the
tmp = current_combination[--i]; // first "bubble". The fact, that it's
++tmp; // a forward iterator makes it ugly but I
} // can't help it.
while(i > 0u && tmp == current_combination[i + 1u]);
// Here is probably my most obfuscated expression.
// Loop above looks for a "bubble". If there is no "bubble", that means, that
// current_combination is the last combination, Expression in the if statement
// below evaluates to true and the function exits returning result.
// If the "bubble" is found however, the ststement below has a sideeffect of
// incrementing the first iterator to the left of the "bubble".
if(++current_combination[i] == current_combination[i + 1u])
return result;
// Rest of the code sets posiotons of the rest of the iterstors
// (if there are any), that are to the right of the incremented one,
// to form next combination
while(++i < combination_size)
{
current_combination[i] = current_combination[i - 1u];
++current_combination[i];
}
// Below is the ugly side of using the sentinel. Well it had to haave some
// disadvantage. Try without it.
result.push_back(std::vector<Fci>(current_combination.begin(),
current_combination.end() - 1));
}
}
Here is a code I recently wrote in Java, which calculates and returns all the combination of "num" elements from "outOf" elements.
// author: Sourabh Bhat (heySourabh#gmail.com)
public class Testing
{
public static void main(String[] args)
{
// Test case num = 5, outOf = 8.
int num = 5;
int outOf = 8;
int[][] combinations = getCombinations(num, outOf);
for (int i = 0; i < combinations.length; i++)
{
for (int j = 0; j < combinations[i].length; j++)
{
System.out.print(combinations[i][j] + " ");
}
System.out.println();
}
}
private static int[][] getCombinations(int num, int outOf)
{
int possibilities = get_nCr(outOf, num);
int[][] combinations = new int[possibilities][num];
int arrayPointer = 0;
int[] counter = new int[num];
for (int i = 0; i < num; i++)
{
counter[i] = i;
}
breakLoop: while (true)
{
// Initializing part
for (int i = 1; i < num; i++)
{
if (counter[i] >= outOf - (num - 1 - i))
counter[i] = counter[i - 1] + 1;
}
// Testing part
for (int i = 0; i < num; i++)
{
if (counter[i] < outOf)
{
continue;
} else
{
break breakLoop;
}
}
// Innermost part
combinations[arrayPointer] = counter.clone();
arrayPointer++;
// Incrementing part
counter[num - 1]++;
for (int i = num - 1; i >= 1; i--)
{
if (counter[i] >= outOf - (num - 1 - i))
counter[i - 1]++;
}
}
return combinations;
}
private static int get_nCr(int n, int r)
{
if(r > n)
{
throw new ArithmeticException("r is greater then n");
}
long numerator = 1;
long denominator = 1;
for (int i = n; i >= r + 1; i--)
{
numerator *= i;
}
for (int i = 2; i <= n - r; i++)
{
denominator *= i;
}
return (int) (numerator / denominator);
}
}

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)

Finding neighbours in a two-dimensional array

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.

Resources