Related
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;
}
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;
}
I'm working on a couple of Project Euler problems and want to test my solution. My recursive function never ends even with reachable base cases.
in a 20x20 grid I am using x and y coordinates to navigate up and left to find the number of paths from (19,19) to (0,0). My base case is to return 1 when we reach (0,0). Otherwise I add the current count to the recursive call.
Function:
private static int numPaths(int x, int y, int pathsFound)
{
if(x == 0 && y == 0)
return 1;
else
{
if(x > 0)
{
pathsFound += numPaths(x - 1, y, pathsFound);
}
if(y > 0)
{
pathsFound += numPaths(x, y - 1, pathsFound);
}
}
return pathsFound;
}
Main:
int x = 19;
int y = 19;
System.out.println("Answer: " + numPaths(x, y, 0));
Is there a flaw in my recursive logic, or is just taking a very long time to compute? If you know the solution to this Euler problem, please do not post it.
https://projecteuler.net/problem=15
So if anyone is interested, I looked into memoization and came up with an elegant solution without recursion.
Function:
private static BigInteger numberPaths(ArrayList<ArrayList<BigInteger>> grid)
{
for(int i = 0; i <= 20; ++i)
{
for(int j = 0; j <= 20; ++j)
{
int x = j;
int y = i;
if(x - 1 < 0 || y - 1 < 0)
{
grid.get(x).set(y, BigInteger.ONE);
}
else
{
BigInteger topVal = grid.get(x - 1).get(y);
BigInteger leftVal = grid.get(x).get(y - 1);
grid.get(x).set(y, topVal.add(leftVal));
}
}
}
return grid.get(20).get(20); //the solution
}
Main:
ArrayList<ArrayList<BigInteger>> grid = new ArrayList<>();
for(int i = 0; i <= 20; ++i)
{
ArrayList<BigInteger> column = new ArrayList<>();
for(int j = 0; j <= 20; ++j)
{
column.add(BigInteger.valueOf(0));
}
grid.add(column);
}
System.out.println("Answer: " + numberPaths(grid));
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)
I have a 3x4 matrix represented by a 2D array:
. 0 1 2 3
0 a c f i
1 b e h k
2 d g j l
and my approach to traverse the diagonal slice was to treat each slice as a sum, like this:
a = (0+0) = 0
b,c = (0+1),(1+0) = 1
d,e,f = (0+2),(1+1),(2+0) = 2
g,h,i = (1+2),(2+1),(3+0) = 3
j, k = (2+2),(3+1) = 4
l = (3+2) = 5
However, my code right now prints it in the opposite way that I want it to, which is from upper right to bottom left.
Current Output is:
acbfedihgkjl
Desired Output is:
abcdefghijkl
for (int sum = 0; sum <= numRows + numColumns - 2; sum++) {
for (int i = 0; i < numRows; i++) {
int j = sum - i;
if ((i >= 0 && i < numRows) && (j >= 0 && j < numColumns)) {
System.out.print(array[i][j]);
}
}
}
Can somebody point me in the right direction on how to fix my code to get the output that I want?
While it isn't very pretty, I think this will do it:
int i = 0;
int j = 0;
while (true) {
System.out.println("" + array[i][j]);
--i;
++j;
if (i < 0) {
if (j == numCols)
break;
i = Math.min(j, numRows - 1);
j = Math.max(j - numCols + 2, 0);
} else if (j >= numCols) {
if (i == numRows - 2)
break;
i = numRows - 1;
j = Math.max(j + 2 - numCols + i, 0);
}
}
int i = 0;
int j = 0;
int n = 0;
int x = 3;
int y = 4;
int newSize = Math.max(x,y) * Math.max(x,y);
while(n < newSize){
if(i <= x && j <= y)
System.out.println(array[i][j]);
n++;
if(i == 0) {
i = n:
j = 0;
} else {
--i;
++j;
}
}