Min value of adjacent array - java

I need help with this problem, I need an array 3x5 and then when the user selects a position the output will show the min value of the adjacents numbers. Like this:
3 5 6 7 8
6 7 8 2 3
0 9 2 1 1
And the user selects the position 1,1. // Diagonals count it too.
Output: The min value around is 0.
This is the code that I have, the problem is I´m asking if there is a better way than spamming if and elses everywhere.
private static int checkAdjacentField(int p1, int p2, int[][] ae) {
int min = Integer.MAX_VALUE;
if (p1 == 0) {
if (p2 == 0) {
if (ae[p1][p2+1] < min) {
min = ae[p1][p2+1];
} else if (ae[p1+1][p2+1] < min) {
min = ae[p1+1][p2+1];
} else if (ae[p1+1][p2] < min) {
min = ae[p1+1][p2];
}
} else if (p2 == 1) {
if (ae[p1][p2+1] < min){
min = ae[p1][p2+1];
} else if (ae[p1+1][p2+1] < min) {
min = ae[p1+1][p2+1];
} else if (ae[p1+1][p2] < min) {
min = ae[p1+1][p2];
} else if (ae[p1+1][p2-1] < min) {
min = ae[p1+1][p2-1];
} else if (ae[p1][p2-1] < min) {
min = ae[p1][p2-1];
}
}
}
return min;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Random r = new Random();
int [][] ar = new int[3][5];
for (int i = 0; i < ar.length; i++) {
System.out.println();
for (int j = 0; j < 5; j++) {
int rand = r.nextInt(9) + 1;
ar[i][j]=rand;
System.out.printf("%3d",ar[i][j]);
}
}
System.out.println();
System.out.println("Select a position [][]: ");
int pos1 = Integer.parseInt(br.readLine());
int pos2 = Integer.parseInt(br.readLine());
System.out.println("The min value around is " + checkAdjacentField(pos1,pos2,ar));
}
}
In the code the 0,0 and 0,1 works and yes, I could spend time doing the spamming method of if else but I want to know if there is a better way so I can improve. Thanks for helping, any idea or answer is welcome.

I think the best way to do that is using the following algo:
List of all the adjacent positions (regardless of if they are in the array or not)
Filter out the ones that are not in the array
Map the remaining positions to their values in the array
Lookup the smallest one (as we are dealing with integers, you can sort them and take the first one)
this way :
private static int checkAdjacentField(int col, int row, int[][] ae) {
int nbRows = ae.length;
int nbCols = ae[0].length;
// Stream all the 8 positions around your position
Stream<Point> positions = Stream.of(
new Point(col-1, row-1), new Point(col-1, row), new Point(col-1, row+1),
new Point(col, row-1), new Point(col, row+1),
new Point(col+1, row-1), new Point(col+1, row), new Point(col+1, row+1));
return positions
.filter(p -> p.x>=0 && p.y>=0 && p.x<nbCols && p.y<nbRows) // keep those inbound
.mapToInt(p -> ae[p.y][p.x]) // replace positions by their values in the array
.sorted() // sort the values
.findFirst().orElse(-1); // take the first one (smallest)
}
You could even generate the list of points, instead of hard coding them
private static int checkAdjacentField(int col, int row, int[][] ae) {
int nbRows = ae.length;
int nbCols = ae[0].length;
// Stream all the 8 positions around your position
Stream<Point> positions = IntStream.rangeClosed(-1, 1).boxed() // -1, 0, 1
.map(c -> IntStream.rangeClosed(-1, 1).boxed() // -1, 0, 1
.map(r -> new Point(col+c, row+r)))
.flatMap(p -> p) // to a list
.filter(p -> !(p.x == col && p.y==row)); // remove center point
// then same as first example
return positions
.filter(p -> p.x>=0 && p.y>=0 && p.x<nbCols && p.y<nbRows)
.mapToInt(p -> ae[p.y][p.x])
.sorted()
.findFirst().orElse(-1);
}
I prefer hard coding them like in the first example though, it is clearer.

How about this?
private static int checkAdjacentField(int p1, int p2, int[][] ae) {
int[] tmp = new int[8];
int left = (p2-1) % ae[0].length;
int right = (p2+1) % ae[0].length;
int up = (p1-1) % ae.length;
int down = (p1+1) % ae.length;
tmp[0] = ae[up][left];
tmp[1] = ae[up][p2];
tmp[2] = ae[up][right];
tmp[3] = ae[p1][left];
tmp[4] = ae[p1][right];
tmp[5] = ae[down][left];
tmp[6] = ae[down][p2];
tmp[7] = ae[down][right];
List<Integer> tmpList = Arrays.stream(tmp).boxed().collect(Collectors.toList());
return tmpList.stream().mapToInt(i -> i).min().orElse(0);
}
Granted, this doesn't account for edges. If you care about edges, you can use Math.min or Math.max to cover these cases:
private static int checkAdjacentField(int p1, int p2, int[][] ae) {
int[] tmp = new int[8];
int left = (Math.max((p2-1),0)) % ae[0].length;
int right = (Math.min((p2+1), ae[0].length-1)) % ae[0].length;
int up = (Math.max((p1-1),0)) % ae.length;
int down = (Math.min((p1+1), ae.length-1)) % ae.length;
tmp[0] = ae[up][left];
tmp[1] = ae[up][p2];
tmp[2] = ae[up][right];
tmp[3] = ae[p1][left];
tmp[4] = ae[p1][right];
tmp[5] = ae[down][left];
tmp[6] = ae[down][p2];
tmp[7] = ae[down][right];
List<Integer> tmpList = Arrays.stream(tmp).boxed().collect(Collectors.toList());
return tmpList.stream().mapToInt(i -> i).min().orElse(0);
}

At any time, we have 8 possible locations for an adjacent number. N, NW, W, SW, S, SE, E, NE. So, we can add them all to an ArrayList<> to iterate over and check for the minimum number, if we're sure doing so won't get us out of bounds.
This looks verbose, but will handle any case, edge or not, for any size 2d array and works with the code you provided:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Random;
public class Test {
char[] array;
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Random r = new Random();
int [][] ar = new int[3][5];
for (int i = 0; i < ar.length; i++) {
System.out.println();
for (int j = 0; j < 5; j++) {
int rand = r.nextInt(9) + 1;
ar[i][j]=rand;
System.out.printf("%3d",ar[i][j]);
}
}
System.out.println();
System.out.println("Select a position [][]: ");
int pos1 = Integer.parseInt(br.readLine());
int pos2 = Integer.parseInt(br.readLine());
System.out.println("The min value around is " + checkAdjacentField(pos1,pos2,ar));
}
private static int checkAdjacentField(int y, int x, int[][] ae) {
int height = ae.length;
int width = ae[0].length;
int min = Integer.MAX_VALUE;
ArrayList<Integer> adj = new ArrayList<Integer>();
// CHECK NORTH, only out of bounds if we're at the NORTH (y == 0)
if (y != 0) { adj.add(ae[y-1][x]); }
// CHECK NORTHWEST, only out of bounds if we're at the NORTHWEST (y == 0 & x == 0)
if (y != 0 && x != 0) { adj.add(ae[y-1][x-1]); }
// CHECK WEST, only out of bounds if we're at the WEST (x == 0)
if (x != 0) { adj.add(ae[y][x-1]); }
// CHECK SOUTHWEST, only out of bounds if we're at the SOUTHWEST (y == (height-1) & x == 0)
if (y != (height-1) && x != 0) { adj.add(ae[y+1][x-1]); }
// CHECK SOUTH, only out of bounds if we're at the SOUTH (y == (height-1))
if (y != (height-1)) { adj.add(ae[y+1][x]); }
// CHECK SOUTHEAST, only out of bounds if we're at the SOUTHEAST (y == (height-1) & x == (width-1))
if (y != (height-1) && x != (width-1)) { adj.add(ae[y+1][x+1]); }
// CHECK EAST, only out of bounds if we're at the EAST (x == (width-1))
if (x != (width-1)) { adj.add(ae[y][x+1]); }
// CHECK NORTHEAST, only out of bounds if we're at the NORTHEAST (y == 0 & x == (width-1))
if (y != 0 && x != (width-1)) { adj.add(ae[y-1][x+1]); }
// Now, we check our min using our list that contains 3-8 entries
for (Integer num : adj) {
if (num < min) { min = num; }
}
return min;
}
}

You can use a for loop like this to parse all adjacents cells , put them in a list and then you can easly calculate the min of that list.
This way , you can reduce the use of If branchs.
adjRow == 0 && adjCol == 0 ==> Middle Cell
int matrix[][]={{3, 5, 6, 7, 8},
{6, 7, 8, 2, 3} ,
{ 0,9,2,1,1}};
List adjacents = new ArrayList<>(8);
int row= 0 ; int col=1 ;
for (int adjRow = -1; adjRow <= 1; ++adjRow) {
for (int adjCol = -1; adjCol <= 1; ++adjCol) {
if ( (adjRow != 0 || adjCol != 0)
// Avoid IndexOutOfBoundsException
&& ( row + adjRow >= 0 && row + adjRow < 3 )
&& ( col + adjCol >= 0 && col + adjCol < 5 )
){
adjacents.add(matrix[row + adjRow][col + adjCol]);
}
}
}
System.out.println(Collections.min(adjacents));
For (0,1) ==> Min = 3. Hope it helps ^^
Used imports :
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;

You can iterate only adjacent values of your matrix. For this you need to determine edges of array and skip your element:
private static int checkAdjacentField(int p1, int p2, int[][] ae) {
int minColIdx = p2 == 0 ? p2 : p2 - 1;
int minRowIdx = p1 == 0 ? p1 : p1 - 1;
int maxRowIdx = p1 == ae.length - 1 ? p1 : p1 + 1;
int result = Integer.MAX_VALUE;
for (int i = minRowIdx; i <= maxRowIdx; i++) {
int[] row = ae[i];
int maxColIdx = p2 == row.length - 1 ? p2 : p2 + 1;
for (int k = minColIdx; k <= maxColIdx; k++) {
if (!(p1 == i && p2 == k) && ae[i][k] < result) {
result = ae[i][k];
}
}
}
return result;
}

Simple Program for 3x5 matrix:
private static int checkAdjacentField(int p1, int p2, int[][] ae) {
int min = Integer.MAX_VALUE;
for (int i = p1 - 1; i <= p1 + 1; i++) {
for (int j = p2 - 1; j <= p2 + 1; j++) {
if ((i < 0 || j < 0) || (i > 2 || j > 4) || (i == p1 && j == p2)) {
continue;
}
if (ae[i][j] < min) {
min = ae[i][j];
}
}
}
return min;
}

Related

Count the minimum number of jumps required for a frog to get to the other side of a river

I work with a Codility problem provided below,
The Fibonacci sequence is defined using the following recursive formula:
F(0) = 0
F(1) = 1
F(M) = F(M - 1) + F(M - 2) if M >= 2
A small frog wants to get to the other side of a river. The frog is initially located at one bank of the river (position −1) and wants to get to the other bank (position N). The frog can jump over any distance F(K), where F(K) is the K-th Fibonacci number. Luckily, there are many leaves on the river, and the frog can jump between the leaves, but only in the direction of the bank at position N.
The leaves on the river are represented in an array A consisting of N integers. Consecutive elements of array A represent consecutive positions from 0 to N − 1 on the river. Array A contains only 0s and/or 1s:
0 represents a position without a leaf;
1 represents a position containing a leaf.
The goal is to count the minimum number of jumps in which the frog can get to the other side of the river (from position −1 to position N). The frog can jump between positions −1 and N (the banks of the river) and every position containing a leaf.
For example, consider array A such that:
A[0] = 0
A[1] = 0
A[2] = 0
A[3] = 1
A[4] = 1
A[5] = 0
A[6] = 1
A[7] = 0
A[8] = 0
A[9] = 0
A[10] = 0
The frog can make three jumps of length F(5) = 5, F(3) = 2 and F(5) = 5.
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A consisting of N integers, returns the minimum number of jumps by which the frog can get to the other side of the river. If the frog cannot reach the other side of the river, the function should return −1.
For example, given:
A[0] = 0
A[1] = 0
A[2] = 0
A[3] = 1
A[4] = 1
A[5] = 0
A[6] = 1
A[7] = 0
A[8] = 0
A[9] = 0
A[10] = 0
the function should return 3, as explained above.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer that can have one of the following values: 0, 1.
Complexity:
expected worst-case time complexity is O(N*log(N));
expected worst-case space complexity is O(N) (not counting the storage required for input arguments).
I wrote the following solution,
class Solution {
private class Jump {
int position;
int number;
public int getPosition() {
return position;
}
public int getNumber() {
return number;
}
public Jump(int pos, int number) {
this.position = pos;
this.number = number;
}
}
public int solution(int[] A) {
int N = A.length;
List<Integer> fibs = getFibonacciNumbers(N + 1);
Stack<Jump> jumps = new Stack<>();
jumps.push(new Jump(-1, 0));
boolean[] visited = new boolean[N];
while (!jumps.isEmpty()) {
Jump jump = jumps.pop();
int position = jump.getPosition();
int number = jump.getNumber();
for (int fib : fibs) {
if (position + fib > N) {
break;
} else if (position + fib == N) {
return number + 1;
} else if (!visited[position + fib] && A[position + fib] == 1) {
visited[position + fib] = true;
jumps.add(new Jump(position + fib, number + 1));
}
}
}
return -1;
}
private List<Integer> getFibonacciNumbers(int N) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 2; i++) {
list.add(i);
}
int i = 2;
while (list.get(list.size() - 1) <= N) {
list.add(i, (list.get(i - 1) + list.get(i - 2)));
i++;
}
for (i = 0; i < 2; i++) {
list.remove(i);
}
return list;
}
public static void main(String[] args) {
int[] A = new int[11];
A[0] = 0;
A[1] = 0;
A[2] = 0;
A[3] = 1;
A[4] = 1;
A[5] = 0;
A[6] = 1;
A[7] = 0;
A[8] = 0;
A[9] = 0;
A[10] = 0;
System.out.println(solution(A));
}
}
However, while the correctness seems good, the performance is not high enough. Is there a bug in the code and how do I improve the performance?
Got 100% with simple BFS:
public class Jump {
int pos;
int move;
public Jump(int pos, int move) {
this.pos = pos;
this.move = move;
}
}
public int solution(int[] A) {
int n = A.length;
List < Integer > fibs = fibArray(n + 1);
Queue < Jump > positions = new LinkedList < Jump > ();
boolean[] visited = new boolean[n + 1];
if (A.length <= 2)
return 1;
for (int i = 0; i < fibs.size(); i++) {
int initPos = fibs.get(i) - 1;
if (A[initPos] == 0)
continue;
positions.add(new Jump(initPos, 1));
visited[initPos] = true;
}
while (!positions.isEmpty()) {
Jump jump = positions.remove();
for (int j = fibs.size() - 1; j >= 0; j--) {
int nextPos = jump.pos + fibs.get(j);
if (nextPos == n)
return jump.move + 1;
else if (nextPos < n && A[nextPos] == 1 && !visited[nextPos]) {
positions.add(new Jump(nextPos, jump.move + 1));
visited[nextPos] = true;
}
}
}
return -1;
}
private List < Integer > fibArray(int n) {
List < Integer > fibs = new ArrayList < > ();
fibs.add(1);
fibs.add(2);
while (fibs.get(fibs.size() - 1) + fibs.get(fibs.size() - 2) <= n) {
fibs.add(fibs.get(fibs.size() - 1) + fibs.get(fibs.size() - 2));
}
return fibs;
}
You can apply knapsack algorithms to solve this problem.
In my solution I precomputed fibonacci numbers. And applied knapsack algorithm to solve it. It contains duplicate code, did not have much time to refactor it. Online ide with the same code is in repl
import java.util.*;
class Main {
public static int solution(int[] A) {
int N = A.length;
int inf=1000000;
int[] fibs={1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025};
int[] moves = new int[N+1];
for(int i=0; i<=N; i++){
moves[i]=inf;
}
for(int i=0; i<fibs.length; i++){
if(fibs[i]-1<N && A[fibs[i]-1]==1){
moves[ fibs[i]-1 ] = 1;
}
if(fibs[i]-1==N){
moves[N] = 1;
}
}
for(int i=0; i<N; i++){
if(A[i]==1)
for(int j=0; j<fibs.length; j++){
if(i-fibs[j]>=0 && moves[i-fibs[j]]!=inf && moves[i]>moves[i-fibs[j]]+1){
moves[i]=moves[i-fibs[j]]+1;
}
}
System.out.println(i + " => " + moves[i]);
}
for(int i=N; i<=N; i++){
for(int j=0; j<fibs.length; j++){
if(i-fibs[j]>=0 && moves[i-fibs[j]]!=inf && moves[i]>moves[i-fibs[j]]+1){
moves[i]=moves[i-fibs[j]]+1;
}
}
System.out.println(i + " => " + moves[i]);
}
if(moves[N]==inf) return -1;
return moves[N];
}
public static void main(String[] args) {
int[] A = new int[4];
A[0] = 0;
A[1] = 0;
A[2] = 0;
A[3] = 0;
System.out.println(solution(A));
}
}
Javascript 100%
function solution(A) {
function fibonacciUntilNumber(n) {
const fib = [0,1];
while (true) {
let newFib = fib[fib.length - 1] + fib[fib.length - 2];
if (newFib > n) {
break;
}
fib.push(newFib);
}
return fib.slice(2);
}
A.push(1);
const fibSet = fibonacciUntilNumber(A.length);
if (fibSet.includes(A.length)) return 1;
const reachable = Array.from({length: A.length}, () => -1);
fibSet.forEach(jump => {
if (A[jump - 1] === 1) {
reachable[jump - 1] = 1;
}
})
for (let index = 0; index < A.length; index++) {
if (A[index] === 0 || reachable[index] > 0) {
continue;
}
let minValue = 100005;
for (let jump of fibSet) {
let previousIndex = index - jump;
if (previousIndex < 0) {
break;
}
if (reachable[previousIndex] > 0 && minValue > reachable[previousIndex]) {
minValue = reachable[previousIndex];
}
}
if (minValue !== 100005) {
reachable[index] = minValue + 1;
}
}
return reachable[A.length - 1];
}
Python 100% answer.
For me the easiest solution was to locate all leaves within one fib jump of -1. Then consider each of these leaves to be index[0] and find all jumps from there.
Each generation or jump is recorded in a set until a generation contains len(A) or no more jumps can be found.
def gen_fib(n):
fn = [0,1]
i = 2
s = 2
while s < n:
s = fn[i-2] + fn[i-1]
fn.append(s)
i+=1
return fn
def new_paths(A, n, last_pos, fn):
"""
Given an array A of len n.
From index last_pos which numbers in fn jump to a leaf?
returns list: set of indexes with leaves.
"""
paths = []
for f in fn:
new_pos = last_pos + f
if new_pos == n or (new_pos < n and A[new_pos]):
paths.append(new_pos)
return path
def solution(A):
n = len(A)
if n < 3:
return 1
# A.append(1) # mark final jump
fn = sorted(gen_fib(100000)[2:]) # Fib numbers with 0, 1, 1, 2.. clipped to just 1, 2..
# print(fn)
paths = set([-1]) # locate all the leaves that are one fib jump from the start position.
jump = 1
while True:
# Considering each of the previous jump positions - How many leaves from there are one fib jump away
paths = set([idx for pos in paths for idx in new_paths(A, n, pos, fn)])
# no new jumps means game over!
if not paths:
break
# If there was a result in the new jumps record that
if n in paths:
return jump
jump += 1
return -1
https://app.codility.com/demo/results/training4GQV8Y-9ES/
https://github.com/niall-oc/things/blob/master/codility/fib_frog.py
Got 100%- solution in C.
typedef struct state {
int pos;
int step;
}state;
int solution(int A[], int N) {
int f1 = 0;
int f2 = 1;
int count = 2;
// precalculating count of maximum possible fibonacci numbers to allocate array in next loop. since this is C language we do not have flexible dynamic structure as in C++
while(1)
{
int f3 = f2 + f1;
if(f3 > N)
break;
f1 = f2;
f2 = f3;
++count;
}
int fib[count+1];
fib[0] = 0;
fib[1] = 1;
int i = 2;
// calculating fibonacci numbers in array
while(1)
{
fib[i] = fib[i-1] + fib[i-2];
if(fib[i] > N)
break;
++i;
}
// reversing the fibonacci numbers because we need to create minumum jump counts with bigger jumps
for(int j = 0, k = count; j < count/2; j++,k--)
{
int t = fib[j];
fib[j] = fib[k];
fib[k] = t;
}
state q[N];
int front = 0 ;
int rear = 0;
q[0].pos = -1;
q[0].step = 0;
int que_s = 1;
while(que_s > 0)
{
state s = q[front];
front++;
que_s--;
for(int i = 0; i <= count; i++)
{
int nextpo = s.pos + fib[i];
if(nextpo == N)
{
return s.step+1;
}
else if(nextpo > N || nextpo < 0 || A[nextpo] == 0){
continue;
}
else
{
q[++rear].pos = nextpo;
q[rear].step = s.step + 1;
que_s++;
A[nextpo] = 0;
}
}
}
return -1;
}
//100% on codility Dynamic Programming Solution. https://app.codility.com/demo/results/training7WSQJW-WTX/
class Solution {
public int solution(int[] A) {
int n = A.length + 1;
int dp[] = new int[n];
for(int i=0;i<n;i++) {
dp[i] = -1;
}
int f[] = new int[100005];
f[0] = 1;
f[1] = 1;
for(int i=2;i<100005;i++) {
f[i] = f[i - 1] + f[i - 2];
}
for(int i=-1;i<n;i++) {
if(i == -1 || dp[i] > 0) {
for(int j=0;i+f[j] <n;j++) {
if(i + f[j] == n -1 || A[i+f[j]] == 1) {
if(i == -1) {
dp[i + f[j]] = 1;
} else if(dp[i + f[j]] == -1) {
dp[i + f[j]] = dp[i] + 1;
} else {
dp[i + f[j]] = Math.min(dp[i + f[j]], dp[i] + 1);
}
}
}
}
}
return dp[n - 1];
}
}
Ruby 100% solution
def solution(a)
f = 2.step.inject([1,2]) {|acc,e| acc[e] = acc[e-1] + acc[e-2]; break(acc) if acc[e] > a.size + 1;acc }.reverse
mins = []
(a.size + 1).times do |i|
next mins[i] = -1 if i < a.size && a[i] == 0
mins[i] = f.inject(nil) do |min, j|
k = i - j
next min if k < -1
break 1 if k == -1
next min if mins[k] < 0
[mins[k] + 1, min || Float::INFINITY].min
end || -1
end
mins[a.size]
end
I have translated the previous C solution to Java and find the performance is improved.
import java.util.*;
class Solution {
private static class State {
int pos;
int step;
public State(int pos, int step) {
this.pos = pos;
this.step = step;
}
}
public static int solution(int A[]) {
int N = A.length;
int f1 = 0;
int f2 = 1;
int count = 2;
while (true) {
int f3 = f2 + f1;
if (f3 > N) {
break;
}
f1 = f2;
f2 = f3;
++count;
}
int[] fib = new int[count + 1];
fib[0] = 0;
fib[1] = 1;
int i = 2;
while (true) {
fib[i] = fib[i - 1] + fib[i - 2];
if (fib[i] > N) {
break;
}
++i;
}
for (int j = 0, k = count; j < count / 2; j++, k--) {
int t = fib[j];
fib[j] = fib[k];
fib[k] = t;
}
State[] q = new State[N];
for (int j = 0; j < N; j++) {
q[j] = new State(-1,0);
}
int front = 0;
int rear = 0;
// q[0].pos = -1;
// q[0].step = 0;
int que_s = 1;
while (que_s > 0) {
State s = q[front];
front++;
que_s--;
for (i = 0; i <= count; i++) {
int nextpo = s.pos + fib[i];
if (nextpo == N) {
return s.step + 1;
}
//
else if (nextpo > N || nextpo < 0 || A[nextpo] == 0) {
continue;
}
//
else {
q[++rear].pos = nextpo;
q[rear].step = s.step + 1;
que_s++;
A[nextpo] = 0;
}
}
}
return -1;
}
}
JavaScript with 100%.
Inspired from here.
function solution(A) {
const createFibs = n => {
const fibs = Array(n + 2).fill(null)
fibs[1] = 1
for (let i = 2; i < n + 1; i++) {
fibs[i] = fibs[i - 1] + fibs[i - 2]
}
return fibs
}
const createJumps = (A, fibs) => {
const jumps = Array(A.length + 1).fill(null)
let prev = null
for (i = 2; i < fibs.length; i++) {
const j = -1 + fibs[i]
if (j > A.length) break
if (j === A.length || A[j] === 1) {
jumps[j] = 1
if (prev === null) prev = j
}
}
if (prev === null) {
jumps[A.length] = -1
return jumps
}
while (prev < A.length) {
for (let i = 2; i < fibs.length; i++) {
const j = prev + fibs[i]
if (j > A.length) break
if (j === A.length || A[j] === 1) {
const x = jumps[prev] + 1
const y = jumps[j]
jumps[j] = y === null ? x : Math.min(y, x)
}
}
prev++
while (prev < A.length) {
if (jumps[prev] !== null) break
prev++
}
}
if (jumps[A.length] === null) jumps[A.length] = -1
return jumps
}
const fibs = createFibs(26)
const jumps = createJumps(A, fibs)
return jumps[A.length]
}
const A = [0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0]
console.log(A)
const s = solution(A)
console.log(s)
You should use a QUEUE AND NOT A STACK. This is a form of breadth-first search and your code needs to visit nodes that were added first to the queue to get the minimum distance.
A stack uses the last-in, first-out mechanism to remove items while a queue uses the first-in, first-out mechanism.
I copied and pasted your exact code but used a queue instead of a stack and I got 100% on codility.
100% C++ solution
More answers in my github
Inspired from here
Solution1 : Bottom-Top, using Dynamic programming algorithm (storing calculated values in an array)
vector<int> getFibonacciArrayMax(int MaxNum) {
if (MaxNum == 0)
return vector<int>(1, 0);
vector<int> fib(2, 0);
fib[1] = 1;
for (int i = 2; fib[fib.size()-1] + fib[fib.size() - 2] <= MaxNum; i++)
fib.push_back(fib[i - 1] + fib[i - 2]);
return fib;
}
int solution(vector<int>& A) {
int N = A.size();
A.push_back(1);
N++;
vector<int> f = getFibonacciArrayMax(N);
const int oo = 1'000'000;
vector<int> moves(N, oo);
for (auto i : f)
if (i - 1 >= 0 && A[i-1])
moves[i-1] = 1;
for (int pos = 0; pos < N; pos++) {
if (A[pos] == 0)
continue;
for (int i = f.size()-1; i >= 0; i--) {
if (pos + f[i] < N && A[pos + f[i]]) {
moves[pos + f[i]] = min(moves[pos]+1, moves[pos + f[i]]);
}
}
}
if (moves[N - 1] != oo) {
return moves[N - 1];
}
return -1;
}
Solution2: Top-Bottom using set container:
#include <set>
int solution2(vector<int>& A) {
int N = A.size();
vector<int> fib = getFibonacciArrayMax(N);
set<int> positions;
positions.insert(N);
for (int jumps = 1; ; jumps++)
{
set<int> new_positions;
for (int pos : positions)
{
for (int f : fib)
{
// return jumps if we reach to the start point
if (pos - (f - 1) == 0)
return jumps;
int prev_pos = pos - f;
// we do not need to calculate bigger jumps.
if (prev_pos < 0)
break;
if (prev_pos < A.size() && A[prev_pos])
new_positions.insert(prev_pos);
}
}
if (new_positions.size() == 0)
return -1;
positions = new_positions;
}
return -1;
}

How Do I Identify The Edge Case That Is Failing My Code?

I'm working on a coding question and I'm given an array for example something like this: [1, 7, 3, 21, 13, 19]
I'm suppose to pair up items in the array. Then after that I'm suppose to apply this simple rule.
Say I choose a pair x and y:
Rule:
if x > y : y = 2*y and x = x - y
if y > x : x = 2*x and y = y - x
if x == y : break # x and y is a pair that does not cause an infinite loop
Example:
Say x = 7 and y = 3
1st round : x = 7 and y = 3
2nd round : x = 4 and y = 6
3rd round : x = 8 and y = 2
4th round : x = 6 and y = 4
at this point you know that this pair will loop forever
If for example x = 1 and y = 3
1st round : x = 1 and y = 3
2nd round : x = 2 and y = 2
At this point you know that this pair doesn't loop
So in order to solve this problem. I saw it as some kind of TSP but instead of minimizing path, I'm maximizing path.
So first step I did is create a graph of nodes and label whether a pair is a loop or not
In this array the graph generated (adjacency matrix) is this:
0 0 0 1 1 1
0 0 1 0 1 1
0 1 0 0 0 1
1 0 0 0 1 1
1 1 0 1 0 0
1 1 1 1 0 0
the index in the graph represent index in the array. For example let's say that i is row and j is column. If you look at i=0, j=2 that represents array[i] = x, array[j] = y which is array[0] = x = 1, array[2] = y = 3. From the above example we know that that is not a loop. Therefore there is a 0 weight on that index.
Then I do a nearest neighbor TSP algorithm (modified to be max route) in order to get the max pair that maximized the amount of loop pairs. This method passes the coding test cases except for one. I can't identify an array of integers that would fail my code. And the test cases on the coding challenge does not give me any info on what test it is failing on.
Here is my code:
import java.util.HashMap;
public class DistractTheGuards {
private static boolean IsPairLoop(int first, int second)
{
long result = first + second;
boolean success = true;
while ((result & 1) == 0)
{
if (first == second)
{
success = false;
break;
}
else if (first > second)
{
first = (first - second) / 2;
}
else
{
second = (second - first) / 2;
}
result = first + second;
}
return success;
}
public static void GenWeights(int[][] graph, int[] banana_list)
{
for (int i = 0; i < graph.length; ++i)
{
for (int j = 0; j < graph.length; ++j)
{
if (IsPairLoop(banana_list[i], banana_list[j]))
{
graph[i][j] = 1;
}
else
{
graph[i][j] = 0;
}
}
}
}
private static boolean AreAllNodesVisited(boolean[] visited)
{
boolean all_visited = true;
for (int i = 0; i < visited.length; ++i)
{
all_visited &= visited[i];
if (!all_visited)
break;
}
return all_visited;
}
private static int FindMaxTourKey(HashMap<Integer, int[]> tours)
{
int cur_max_r = -1;
for (Integer rank : tours.keySet())
{
if (cur_max_r < rank)
cur_max_r = rank;
}
return cur_max_r;
}
private static int GetN(int[][] graph, int[] max_tour, int n)
{
for (int i = 0; i < max_tour.length; i += 2)
{
if (i + 1 >= max_tour.length)
break;
if (graph[max_tour[i]][max_tour[i+1]] == 0)
{
n -= 2;
}
}
return n;
}
public static int answer(int[] banana_list)
{
int n = banana_list.length;
if (n < 1)
return 0;
if (n == 1)
return 1;
int[][] graph = new int[n][n];
GenWeights(graph, banana_list);
HashMap<Integer, int[]> tours = new HashMap<>();
for (int i = 0; i < n; ++i)
{
int[] cur_tour = new int[n];
boolean[] visited = new boolean[n];
int start_node = i;
int cur_tour_i = 0;
while (!AreAllNodesVisited(visited))
{
int s_n = start_node;
visited[start_node] = true;
cur_tour[cur_tour_i++] = start_node;
int cur_max = 0;
for (int j = 0; j < n; ++j)
{
if (!visited[j])
{
if (cur_max < graph[start_node][j])
{
cur_max = graph[start_node][j];
start_node = j;
break;
}
}
}
if (s_n == start_node)
{
for (int x = n - 1; x >= 0; --x)
{
if (!visited[x])
{
start_node = x;
break;
}
}
}
}
int cur_tour_r = 0;
for (int x = 0; x < n; x += 2)
{
if (x + 1 >= n)
break;
cur_tour_r += graph[cur_tour[x]][cur_tour[x+1]];
}
tours.put(cur_tour_r, cur_tour.clone());
if (cur_tour_r == n - 1)
break;
}
int cur_max_r = FindMaxTourKey(tours);
if (tours.size() == 0)
return 0;
int[] max_tour = tours.get(cur_max_r);
return GetN(graph, max_tour, n);
}
}
I just need help identifying an edge case that would fail my method. Can anyone help me or give me an array that would certainly fail my method? I can take it from there. Thanks
Update
Constraints
1 <= integers <= 2^30
1 <= len(array) <= 100

Issue with Game of life code method? (User interface is complete but actual GOL methods aren't generating what they should)

I've been working on a Game of Life assignment and am nearing the stage of completion, but am struggling to figure out what I've messed up on such that the GOL rules (and Fredkin rules that the assignment requires us to implement as well) are not generating the proper result.
As I have little experience working with graphics I decided to output everything in the interactions window (using Dr.Java). (It's used to set up menu options like the scale, coordinates (you manually enter), generations, and output the final generation of whichever rule you choose to run (GOL or Fredkin).
The program nextGeneration takes a Boolean array map from the main method (where people input coordinates), and should change it to correspond to the next generation of the Game of Life. This happens by creating an entirely new 2D array, map2, which gets values loaded into it based on the number of neighbors which are turned on for each point. At the end of the program, map gets loaded into map2.(Note: this isn't original, this is required by the assignment)
The program living merely checks if a point in the map array is on or off. countNeighbors takes the 8 neighbors of a particular square, passes them each through the living method, and returns the number of neighbors which are currently on. Since countNeighbors sometimes demands either a negative number, or a number greater than the scale of the map, we implemented conditions in living to create that wraparound universe.
I think the problem(s) most likely arise in nextGeneration. I am somewhat tense about using the operand "or" (written as || ), and I think this may be where I screwed up. If you could just look through the code, and see if what I have said is true is written as true, that would be absolutely wonderful.
Below is the code for the program. It also utilizes a Keyboard.class file which I'm happy to post (however one would do that) if that helps (it's required to compile).
public class GameOfLife {
public static void main(String[] args) {
int r = 0; //rules set. Either 0 or 1, 0 for life game, 1 for Fredkin game
int i = 0; // looping variable
int j = 0; // looping variable
int b = 0; // used to read integer inputs from keyboard
int x = 0; // used during the stage where the player manually changes the board. Represents x coordinate.
int y = 0; // used during the stage where the player manually changes the board. Represents x coordinate.
int gen = 0; //number of generations to be skipped before printing out new map
int scale = 0;
boolean[][] map = new boolean[0][0];
System.out.println("Start game? y/n");
String a = Keyboard.readString();
if (a.equals("n")) {
return;
} else {
System.out.println("Do you wish to know the rules? y/n");
a = Keyboard.readString();
if (a.equals("y")) {
System.out.println("Each coordinate in the printed graph is represented by a 0 or a .");
System.out.println("0 represents a live cell, . represents a dead one.");
System.out.println("Each cell has 8 neighboring cells.");
System.out.println("There are two ways in which the game can be played.");
System.out.println("In the Life model, if a cell has 3 neighbors, if dead, it turns on.");
System.out.println("If it has 2 neighbors, it keeps its current condition.");
System.out.println("Else, it dies. Brutal.");
System.out.println("In the Fredkin Model, only non-diagnol neighbors count.");
System.out.println("If a cell has 1 or 3 neighbors, it is alive.");
System.out.println("If it has 0, 2 or 4, it dies. WAY more Brutal.");
}
System.out.println("Do you want to play by Fredkin or Life Rules? 0 for life, 1 for Fredkin");
while (i == 0) {
b = Keyboard.readInt();
if (b == 1) {
r = 1;
i = 1;
}
if (b == 0) {
r = 0;
i = 1;
}
}
while (j == 0) {
System.out.println("What scale would you like to use? Please enter an integer larger than 4");
b = Keyboard.readInt();
if (b >= 5) {
map = new boolean[b][b];
scale = b;
j = 1;
} else {
System.out.println("Come on, buddy, read the rules");
}
}
j = 0;
while (j == 0) {
System.out.println("Do you want to enter coordinates? y to continue entering coordinates, n to go to next option");
a = Keyboard.readString();
if (a.equals("y")) {
i = 0;
while (i == 0) {
System.out.println("Please enter a value for an X coordinate from 0 to " + (scale - 1));
b = Keyboard.readInt();
if (b >= 0) {
if (b < scale) {
i = 1;
x = b;
}
}
}
i = 0;
while (i == 0) {
System.out.println("Please enter a value for a Y coordinate from 0 to " + (scale - 1));
b = Keyboard.readInt();
if (b >= 0) {
if (b < scale) {
i = 1;
y = b;
}
}
}
map[y][x] = true;
printgame(map);
} else {
if (a.equals("n")) {
j = 1;
}
}
}
i = 0;
while (i == 0) {
System.out.println("How many generations would you like to skip ahead? Please enter a value greater than 0");
b = Keyboard.readInt();
if (b > 0) {
gen = b;
i = 1;
}
}
i = 0;
if (r == 0) {
for (i = 0; i <= gen; i++) {
nextGeneration(map);
}
printgame(map);
} else {
if (r == 1) {
for (i = 0; i <= gen; i++) {
FredGen(map);
}
printgame(map);
}
}
}
}
public static void printgame(boolean[][] map) {
int x = map[0].length;
int y = map[0].length;
int i = 0;
int j = 0;
char c;
String Printer = "";
for (j = 0; j < y; j++) {
for (i = 0; i < x; i++) {
if (map[j][i]) {
c = '0';
} else {
c = '.';
}
Printer = (Printer + " " + c);
}
System.out.println(Printer);
Printer = new String("");
}
}
private static void nextGeneration(boolean[][] map) {
int x = map[0].length;
int y = map[0].length;
int[][] neighborCount = new int[y][x];
boolean[][] map2 = new boolean[y][x];
for (int j = 0; j < y; j++)
for (int i = 0; i < x; i++)
neighborCount[j][i] = countNeighbors(j, i, map);
//this makes a new generation array
for (int j = 0; j < y; j++) {
for (int i = 0; i < x; i++) {
if (map[j][i] = true) { //assumes initial value of array is true (AKA "ALIVE")
if (neighborCount[j][i] == 3) { //check if alive AND meeting condition for life
map2[j][i] = true; //sets character array coordinate to ALIVE: "0"
} else if ((neighborCount[j][i] <= 2) || (neighborCount[j][i] > 3)) { //check if dead from isolation or overcrowding
map2[j][i] = false; //sets character array coordinate to DEAD: "."
}
}
}
}
map = map2;
}
private static int countNeighbors(int j, int i, boolean[][] map) { //counts all 8 elements living/dea of 3x3 space surrounding and including living/dead central coordinate)
return living(j - 1, j - 1, map) + living(j - 1, i, map) +
living(j - 1, i + 1, map) + living(j, i - 1, map) + living(j, i + 1, map) +
living(j + 1, i - 1, map) + living(j + 1, i, map) + living(j + 1, i + 1, map);
}
private static int living(int j, int i, boolean[][] map) {
int x = map[0].length - 1;
if (i < 0) {
i = i + x;
} else {
i = i % x;
}
if (j < 0) {
j = j + x;
} else {
j = j % x;
}
if (map[j][i] == true) {
return 1;
} else {
return 0;
}
}
private static void FredGen(boolean[][] map) {
int x = map[0].length;
int y = map[0].length;
int[][] neighborCount = new int[y][x];
for (int j = 0; j < y; j++)
for (int i = 0; i < x; i++)
neighborCount[j][i] = Freddysdeady(j, i, map);
//this makes a new generation array
for (int j = 0; j < y; j++)
for (int i = 0; i < x; i++)
if (map[j][i] = true) { //assumes initial value of array is true (AKA "ALIVE")
if ((neighborCount[j][i] < 1) || (neighborCount[j][i] == 2) || (neighborCount[j][i] > 3)) { //check if dead from isolation or overcrowding
map[j][i] = false; //sets chracter array coordinate to DEAD: "."
} else if ((neighborCount[j][i] == 1) || (neighborCount[j][i] == 3)) { //check if alive AND meeting condition for life
map[j][i] = true; //sets character array coordinate to ALIVE: "0"
}
}
}
private static int Freddysdeady(int j, int i, boolean[][] map) {
return living(j - 1, i, map) + living(j, i - 1, map) + living(j, i + 1, map) + living(j + 1, i, map);
}
}
There might be other problems, here are a few that I could spot by eye:
In the nextGeneration method, you handle cases where a cell should stay alive or die, but you do not have anything for when cells should be born. You should have something like this:
if(map[x][y]) {
//should this cell stay alive? if yes = live, else die
} else {
//should a cell be born in this slot? if yes = born, else nothing
}
This is a minor issue, still in nextGeneration, in if(count==3)live; else if(count <=2 || count > 3) die; is redundant, you only need if(count == 3) live; else die;
let us know, if you still have problems

How to improve code that returns an int array with sorted index, of a given int array?

I have made a method that I believe gets an array a, take the three first values in the array and finds the values from low to high. Then those values are put in an new array and send back sorted. This means that with for example:
int[] a = {9,5,7} returns {1,2,0}. This because a[1] = 5, a[2] = 7 og a[0] = 9.
int[] a = {1,3,2} should return {0,2,1}. Array a should not be changed.
public class Testprogram {
public static void main(String[] args) {
int[] a = {9,8,7,2,7,8};
System.out.println(Arrays.toString(index(a)));
}
public static int[] index(int[] a)
{
int n = a.length;
if (n < 3)
{
throw new IllegalArgumentException("array must have at least 3 elements!");
}
int min = 0; //lowest index
int nmin = 1; //second lowest index
int tmin = 2; //third lowest index
// Controlling that the values in start are in the correct position
if (a[2] < a[1] && a[1] < a[0])
{
min = 2;
nmin = 1;
tmin = 0;
}
else if (a[2] < a[0] && a[0] < a[1])
{
min = 2;
nmin = 0;
tmin = 1;
}
else if (a[1] < a[2] && a[2] < a[0])
{
min = 1;
nmin = 2;
tmin = 0;
} else if (a[1] < a[0] && a[0] < a[2])
{
min = 1;
nmin = 0;
tmin = 2;
}
else if(a[0] < a[1] && a[1] < a[2])
{
min = 0;
nmin = 1;
tmin = 2;
} else if(a[0] < a[2] && a[2] < a[1])
{
min = 0;
nmin = 2;
tmin = 1;
}
int[] index = new int[] {min, nmin, tmin};
return index; //returns the array
}}
This method should work with only three comparisons (and max three exchanges (changes?)).
My method with the if(n < 3), has 7 comparisons.
Anyone that can help my improve my code?
Here is a possible solution
if(a[0]>a[1]){
min=1;
nmin=0;
}
if(a[nmin]>a[tmin]){
int tmp =nmin;
nmin=tmin;
tmin=tmp;
}
if(a[min]>a[nmin]){
int tmp =min;
min=nmin;
nmin=tmp;
}
it's a kind of bubble sort for this specific case (array of 3 elements).

Faster way to find neighbors indexes

I'm creating a minesweeper game and I really need a fast and Efficient way of calculating the neighbors of a mine, Actually im storing my tiles in an Arraylist so I can use them in a gridview, so the position is lineal but the rendering will be a matrix n*n. I have a way to do it but I think someone can have a more efficient way.
What I want to achieve:
0 1 1 1
0 1 * 1
0 1 1 1
0 0 0 0
So given that matrix having the indexes in a lineal List the position should be the following:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
So I need an efficient way of obtaining 2, 3, 4, 6, 8, 10, 11, 12 giving the index 7.
Code to generate bombs:
public void plantMines(){
Random rand = new Random();
//Used set so we dont get duplicates
Set<Integer> mineCoords = new LinkedHashSet<>(mDifficulty.mines);
//First we randomly select all coordenates
while (mineCoords.size() < mDifficulty.mines){
Integer coord = rand.nextInt(mListCap) + 1;
mineCoords.add(coord);
}
//Now we can set the mines accordingly
for (Integer coord: mineCoords){
mTiles.get(coord).setMine(true);
}
}
Actual code to find neighbors:
for (int row = 0; row < ROW_SIZE; row++) {
for (int col = 0; col < COL_SIZE; col++) {
int neighbourBombSize = 0;
// TOP ROW
if ((row-1) >= 0 && (col-1) >= 0) {
if (getTile(row-1, col-1).hasBomb()) {
neighbourBombSize++;
}
}
if ((row-1) >= 0) {
if (getTile(row-1, col).hasBomb()) {
neighbourBombSize++;
}
}
if ((row-1) >= 0 && (col+1) < COL_SIZE) {
if (getTile(row-1, col+1).hasBomb()) {
neighbourBombSize++;
}
}
// SAME ROW
if ((col-1) >= 0) {
if (getTile(row, col-1).hasBomb()) {
neighbourBombSize++;
}
}
if ((col+1) < COL_SIZE) {
if (getTile(row, col+1).hasBomb()) {
neighbourBombSize++;
}
}
// BOTTOM ROW
if ((row+1) < ROW_SIZE && (col-1) >= 0) {
if (getTile(row+1, col-1).hasBomb()) {
neighbourBombSize++;
}
}
if ((row+1) < ROW_SIZE) {
if (getTile(row+1, col).hasBomb()) {
neighbourBombSize++;
}
}
if ((row+1) < ROW_SIZE && (col+1) < COL_SIZE) {
if (getTile(row+1, col+1).hasBomb()) {
neighbourBombSize++;
}
}
getTile(row, col).setNeighbourBombSize(neighbourBombSize);
}
}
Help will be appreciated, thanks.
WARNING : I've take your code as starting point, but your index start a 1, but in java array index start at 0, so it may not work.
I would do something like that :
int neighbourBombSize = 0;
// Compute currentCell row / col
int currentCellCol = ((currentCellIndex - 1) % COL_SIZE) + 1;
int currentCellRow = ((currentCellIndex - 1) / COL_SIZE) + 1;
System.out.println("Neighbors of " + currentCellIndex + " (" + currentCellRow + ", " + currentCellCol + ")");
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
if (x == 0 && y == 0) {
continue; // Current cell index
}
int neighborCol = currentCellCol + y;
int neighborRow = currentCellRow + x;
if (neighborCol > 0 && neighborRow > 0 && neighborCol <= COL_SIZE && neighborRow <= ROW_SIZE ) {
int computedNeighborIndex = neighborCol + ((neighborRow - 1) * COL_SIZE);
if (getTile(neighborRow , neighborCol ).hasBomb()) {
neighbourBombSize++;
}
}
}
}
You can see a running example (computing neighbors index for all case) here : Running example
Are you planning to write the whole game referring to cells using this 1-based linear index? If so, you will want to isolate the conversion to and from coordinates. Otherwise you will eventually mess up somewhere.
Try something like this:
class Board {
final int rows;
final int cols;
Board(int cols, int rows) {
this.rows = rows;
this.cols = cols;
}
int col(int index) {
assert index > 0 && index <= rows * cols;
return (index - 1) % cols; // -1 because you are using 1-based indexing.
}
int row(int index) {
assert index > 0 && index <= rows * cols;
return (index - 1) / cols;
}
int index(int x, int y) {
assert x >= 0 && x < cols && y >= 0 && y < rows;
return y * cols + x + 1;
}
int[] neighbors(int point) {
int x = col(point);
int y = row(point);
int[] result = new int[8];
int cnt = 0;
// go over possible neighbors and collect valid ones
for (int ny = max(y - 1, 0); ny < min(y + 2, rows); ny++) {
for (int nx = max(x - 1, 0); nx < min(x + 2, cols); nx++) {
if (nx != x || ny != y) {
result[cnt++] = index(nx, ny);
}
}
}
return Arrays.copyOf(result, cnt);
}
}
Board brd = new Board(4, 4);
int colOf7 = brd.col(7); // 2 (0-based from left)
int rowOf7 = brd.row(7); // 1 (0-based from top)
int[] neighborsOf7 = brd.neighbors(7); // [2, 3, 4, 6, 8, 10, 11, 12]
int index = brd.index(2,1); // 7 (1-based linear index)

Categories

Resources