java.lang.ArrayIndexOutOfBoundsException: -6 - java

Any solution for this i need to swap element x with y in unsorted array ,x and y are in array
I have this error for array lengths >= 6.
The code works for tabX[] < 6 length.
java.lang.ArrayIndexOutOfBoundsException:-6.
int tabX[] = {
20, 40, 50, 60, 80, 70
};
int elemA[];
int elemB[];
int sumA = 0;
int sumB = 0;
int tmp, lastButOne;
Arrays.sort(tabX);
while (sumA > sumB || sumA == 0 || sumB == 0) {
for (int i = 0; i < tabX.length; i++) {
sumA = 0;
sumB = 0;
elemA = new int[tabX.length - (i + 1)];
elemB = new int[i + 1];
for (int j = 0; j < tabX.length - (i + 1); j++) {
elemA[j] = tabX[j];
sumA += elemA[j];
}
for (int k = 0; k < elemB.length; k++) {
elemB[k] = tabX[tabX.length - (k + 1)]; //i
sumB += tabX[tabX.length - (k + 1)];
}
if (sumA == sumB) {
System.out.println("Secventa A = " + Arrays.toString(elemA));
System.out.println("Secventa B = " + Arrays.toString(elemB));
break;
} else if (sumA < sumB) {
System.out.println("Not a solution");
break;
}
/************ Swap element in array****************/
lastButOne = tabX[tabX.length - (i + 2)];
int indexOfLastButOne = Arrays.binarySearch(tabX, lastButOne);
tmp = tabX[i];
tabX[indexOfLastButOne] = tmp; //here is error
tabX[i] = lastButOne;
} //for
} //while

Well, that's exactly how Arrays.binarySearch works: when the actual element you're asking for isn't there, you get the -(insertion point) - 1, which happens to be -6 in your case.
But also: binarySearch assumes the elements are sorted, so if they're not, it can indeed happen that it isn't found, even if the value is in the list.

It would be helpfull if you pointed out where the exception is thrown (add a comment like // AIOOBE here. From looking at your code, I guess you get a negative return value from Arrays.binarySearch():
int indexOfLastButOne = Arrays.binarySearch(tabX, lastButOne);
...
tabX[indexOfLastButOne] = tmp; // ArrayOutOfBoundsException
From the documentation of Arrays.binarySearch: returns index of the search key, if it is contained in the array; otherwise, (-(insertion point) - 1).

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 to refactor this java code [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have the below java method called solution, there are two large for loops, as you can see, the two for loops are very samilar, so I think it's possible to refactor the code by having a method like public int getElementSize(ArrayList<Integer> factor1, ArrayList<Integer> factor2) which does the work of the for loop, so I can just call the method twice with different parameters instead repeating the two for loop. But since these two for loops have different loop orders, one from head to tail, another one from tail to head, beside this, all other parts of the loop are the same, any ideas how to refactor this code?
class Solution {
public int solution(int[] A) {
ArrayList<Integer> factor1 = new ArrayList<Integer>();
ArrayList<Integer> factor2 = new ArrayList<Integer>();
int factor = 1;
int N = A.length;
while(factor * factor <= N){
if(N % factor == 0){
factor1.add(factor);
factor2.add(N / factor);
}
factor++;
}
for(int i = 1; i < factor2.size(); i++){
int blockSize = factor2.get(i);
int elementSize = factor1.get(i);
int peaks = 0;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
if(peaks == blockSize)
return blockSize;
}
for(int i = factor1.size() - 1; i >= 0; i--){
int blockSize = factor1.get(i);
int elementSize = factor2.get(i);
int peaks = 0;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
if(peaks == blockSize)
return blockSize;
}
return 0;
}
}
How about this?
Conditional operator, ? and : similar to, (these are called ternary operators and resolve at compile time to if else blocks)
if(condition) {
this();
} else {
that();
}
In the above, you can single line that as, (condition ? this() : that())
class Solution {
public int solution(int[] A) {
ArrayList<Integer> factor1 = new ArrayList<Integer>();
ArrayList<Integer> factor2 = new ArrayList<Integer>();
int factor = 1;
int N = A.length;
while(factor * factor <= N){
if(N % factor == 0){
factor1.add(factor);
factor2.add(N / factor);
}
factor++;
}
// let i = 0 to be factor2, i = 1 is factor 1
for(int i = 0; i < 2; i++) {
for(int x = (i == 0 ? 1 : factor1.size() - 1); (i == 0 ? x < factor2.size() : x >= 0); (i == 0 ? x++ : x--)){
int blockSize = (i == 0 ? factor2.get(x) : factor1.get(x));
int elementSize = (i == 0 ? factor1.get(x) : factor2.get(x));
int peaks = 0;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
if(peaks == blockSize)
return blockSize;
}
}
return 0;
}
}
You can refactor the code inside the the for loops to the new method inside move the two big for loops to the new method, in this way, the order of the two loops are still independent, basically it looks like below, the correctness needs to be verified, this is just one idea to not repeat:
class Solution {
public int solution(int[] A) {
ArrayList<Integer> factor1 = new ArrayList<Integer>();
ArrayList<Integer> factor2 = new ArrayList<Integer>();
int factor = 1;
int N = A.length;
while(factor * factor <= N){
if(N % factor == 0){
factor1.add(factor);
factor2.add(N / factor);
}
factor++;
}
for(int i = 1; i < factor2.size(); i++){
int blockSize = factor2.get(i);
int elementSize = factor1.get(i);
int peaks = getElementSize(A, blockSize, elementSize); //call the method
if(peaks == blockSize)
return blockSize;
}
for(int i = factor1.size() - 1; i >= 0; i--){
int blockSize = factor1.get(i);
int elementSize = factor2.get(i);
int peaks = getElementSize(A, blockSize, elementSize); //call the method
if(peaks == blockSize)
return blockSize;
}
return 0;
}
//this method include the code which was repeated inside the loops
public int getElementSize(int[] A, int blockSize, int elementSize){
int peaks = 0;
int N = A.length;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
return peaks;
}
}

Tape-Equilibrium Codility Training program

I submitted a solution to Tape Equilibrium problem in Codility. [Codility training][1]
The problem is described as follows:
A non-empty zero-indexed array A consisting of N integers is given. Array A represents numbers on a tape.
Any integer P, such that 0 < P < N, splits this tape into two non-empty parts: A[0], A[1], ..., A[P − 1] and A[P], A[P + 1], ..., A[N − 1].
The difference between the two parts is the value of: |(A[0] + A[1] + ... + A[P − 1]) − (A[P] + A[P + 1] + ... + A[N − 1])|
In other words, it is the absolute difference between the sum of the first part and the sum of the second part.
The solution I submitted is:
class Solution {
public int solution(int[] A) {
long d = A[0] - A[A.length-1];
int l = 1;
int r = A.length -2;
while(l <= r) {
if (Math.abs(d + A[l]) < Math.abs(d - A[r])) {
d += A[l];
l++;
}
else {
d -= A[r];
r--;
}
}
return (int) Math.abs(d);
}
}
I achieved 85% accuracy but couldn't get to correct for some use case. Can someone help me to find what's wrong with this solution. Thanks
The following is my 100% solution:
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
// int idx = 0;
int sumPre = A[0];
int sumPost = 0;
for (int i = 1; i < A.length; i++) {
sumPost += A[i];
}
int difMin = Math.abs(sumPost - sumPre);
int tempSub = 0;
for (int i = 1; i < A.length - 1; i++) {
sumPre += A[i];
sumPost -= A[i];
tempSub = Math.abs(sumPost - sumPre);
if (tempSub < difMin) {
difMin = tempSub;
// idx = i+1;
}
}
return difMin;
}
}
I can not find their test input, but I find a weird thing is that when "for(int i = 1; i < A.length - 1; i++) " is changed to " for(int i = 1; i < A.length; i++)", then it will trigger two wrong runs...So it still must be a border value issue.
If any one find a test input can break the validity, please share with us, thanks.
Caution: {1,-1} indeed triggered the problem, since P < N, so at least one element should be left in the right part. -> {1,-1},{} is not a valid solution according to the problem definition.
Problem solved.
C# and Linq version for 100% as of May 2021:
public int solution(int[] A)
{
int left = A[0];
int right = A.Skip(1).Aggregate((c,x)=> c+=x);
int min = Math.Abs(left-right);
for(int i=1; i < A.Length-1; i++)
{
left+=A[i];
right-=A[i];
min = Math.Min(min,Math.Abs(left-right));
}
return min;
}
I also tried and got only 83%. My solution:
class Solution {
public int solution(int[] A) {
int[] leftSums = new int[A.length];
for (int i = 0; i < leftSums.length; i++) {
leftSums[i] = 0;
}
int sum = 0;
for (int i = 0; i < A.length; i++) {
sum += A[i];
leftSums[i] = sum;
}
/*
for (int i = 0; i < leftSums.length; i++) {
if (i == 0) {
System.out.print("Left Sums Array is : [");
}
if (i == leftSums.length - 1) {
System.out.println(leftSums[i] + "]");
}
System.out.print(leftSums[i] + ", ");
}
*/
final int total = sum;
//System.out.println("Total is " + total);
int minDiff = Integer.MAX_VALUE;
int currDiff = 0;
for (int i = 0; i < leftSums.length; i++) {
currDiff = Math.abs(leftSums[i] - (total - leftSums[i]));
if (currDiff < minDiff) {
minDiff = currDiff;
}
}
return minDiff;
}
}
Below are those which failed for correctness.
double
two elements 1.280 s WRONG ANSWER
got 0 expected 2000
small
small elements 1.304 s WRONG ANSWER
got 0 expected 20
I tested myself for 2 elements and it worked for me.
I share my 100% score Java solution:
class Solution {
public int solution(int[] A) {
final int size = A.length;
long sumMin = (int)A[0];
long sumMax = 0;
for (int i = 1; i < size; i++) {
sumMax += (int)A[i];
}
int minDif = (int)Math.abs(sumMax - sumMin);
for (int i = 1; i < size; i++) {
int dif = (int)Math.abs(sumMax - sumMin);
if (dif < minDif) {
minDif = dif;
}
sumMin += A[i];
sumMax -= A[i];
}
return minDif;
}
}
The trick is that looping the array twice your complexity is 2N, which is O(N).
Addition results should be 'long' in order not to have problems with big extremes.
For %83 results, the problem is it says "splits this tape into two non-empty parts". So if you split for A[0], your first array will be empty. So you should start with A[1].
Ruby 100%
def solution(a)
left = a.inject(:+)
right = 0
a[0...-1].inject(Float::INFINITY) do |min, el|
left -=el
right += el
candidate = (right-left).abs
min < candidate ? min : candidate
end
end
You can actually do that, with one loop in C#.
Add Linq:
public int solution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
long sum = A.Sum(p => (long)p);
int val1 = Convert.ToInt32(A.GetValue(0));
int val2 = Convert.ToInt32(sum - val1);
int result = Math.Abs(val1 - val2);
for (int i = 1; i < A.Length-1; i++)
{
val1 += Convert.ToInt32(A.GetValue(i));
val2 -= Convert.ToInt32(A.GetValue(i));
if (result > Math.Abs(val1 - val2))
{
result = Math.Abs(val1 - val2);
}
}
return result;
}
Counterexample for user699681: A = {0, 1, 2, -5, 2},
and for Ism: A = {1, -1}.
TapeEquilibrium in C
int solution(int A[], int N) {
// write your code in C90
long int s_r=0,s_l=A[0],sum=A[0];
int i,min=11111111,r;
for(i=1;i<N;i++)
sum+=A[i];
for(i=1;i<N;i++)
{
s_r=sum-s_l;
r=(int)(s_l-s_r);
if(r<0) r=-r;
if(min>r)min=r;
if(min==0)break;
s_l=sum-s_r+A[i];
}
return min;
}
.. Or even a bit shorter to get 100%
public int solution(int[] A) {
int sumMin = A[0];
int sumMax = 0;
for (int i = 1; i < A.length; i++) {
sumMax += A[i];
}
int minDif = Math.abs(sumMin - sumMax);
for (int i = 1; i < A.length - 1; i++) {
sumMin += A[i];
sumMax -= A[i];
minDif = Math.min(minDif, Math.abs(sumMin - sumMax));
}
return minDif;
}
Here's my implementation using Java 8 IntStream to simplify the sum process...
100% Correct, 100% Performance.
import java.util.stream.IntStream;
public class TapeEquilibrium {
public static int diffIndex( int[] A ) {
long lower = 0, diff = 0, higher = IntStream.of( A ).asLongStream().sum(), minDiff = Integer.MAX_VALUE;
for(int i = 0; i < A.length-1; i++) {
lower += A[i];
higher -= A[i];
diff = Math.abs( higher - lower);
if( diff < minDiff ) {
minDiff = diff;
}
}
return (int) minDiff;
}
public static void main( String[] args ) {
int[] A = { 3, 1, 2, 4, 3 };
System.out.println( diffIndex( A ) );
}
}
here is my Solution with 100% correctness & performance
int solution(int A[], int N)
{
int sum,i;
sum=0;
for(i=0;i<N;i++)
{
sum+=A[i];
A[i]=sum;
}
int min_diff=abs(sum-A[0]*2);
for(i=0;i<N-1;i++)
{
int tmp;
tmp=abs(sum-A[i]*2);
if(tmp<min_diff)
min_diff=tmp;
}
return min_diff;
}
Try this one:
Class Solution {
public int solution(int[] A) {
int sum1 = 0;
int sum2 = 0;
int sum3 = 0;
int len = A.length;
int min = 1 ;
for(int i=0; i<len; i++){
sum2 += A[i];
}
for(int i=0; i< len-1 ; i++){
sum1 += A[i];
sum3 = sum2-sum1;
if( min > Math.abs(sum1- sum3)){
min = Math.abs( sum1 - sum3);
}
}
return min;
}
}
Here is 100% in scala.
def solution(A: Array[Int]): Int = {
//get the whole sum
val allSum = A.sum
//calculate left and right sum
var sumLeft = A(0)
var sumRight = allSum - sumLeft
//set initial diff for P=1
var minDiff = math.abs(sumLeft-sumRight) //difference
// loop for all P after the initial P position
for(p <- 1 to A.length-2){
//recalculate values
sumLeft += A(p)
sumRight -= A(p)
if(math.abs(sumLeft-sumRight) < minDiff){
// if difference is smaller then save new min diff
minDiff = math.abs(sumLeft-sumRight)
}
}
minDiff
}
Performance: https://codility.com/demo/results/trainingZNZCZN-AGC/
long sumofall = 0, leftsideSum = A[0], rightsidesum=0;
int x,LR = 0;
ArrayList listResult = new ArrayList();
for(x=0;x<A.Length;x++)
{
sumofall+= A[x];
}
for(x=1;x<A.Length;x++)
{
rightsidesum = sumofall-leftsideSum;
LR = (int)(rightsidesum - leftsideSum);
if(LR < 0)
{
LR=-LR;
}
listResult.Add(LR);
leftsideSum+=A[x];
}
listResult.Sort();
return Convert.ToInt32(listResult[0].ToString());
}
I share my 100% solution using Java 8.
public class TapeEquilibrium {
public int tapeEquilibrium(int[] A) {
final int N = A.length;
long minimalSum = (int) A[0];
int[] rightSide = Arrays.copyOfRange(A, 1, N);
long maximalSum = IntStream.of(rightSide).sum();
int minimalDifference = (int) Math.abs(maximalSum - minimalSum);
for (int i = 1; i < N; i++) {
int difference = (int) Math.abs(maximalSum - minimalSum);
minimalDifference = difference < minimalDifference ? difference : minimalDifference;
minimalSum += A[i];
maximalSum -= A[i];
}
return minimalDifference;
}
}
Here is my C# solution. Score 100%
if (A == null || A.Length == 0)
{
return 0;
}
int d1 = 0;
int d2 = A.Sum();
int p = 1;
int x = int.MaxValue;
// Replaced using A.sum();
//for (int i=0; i < A.Length; i++)
//{
// d2 += A[i];
//}
for (int j = 0; j < A.Length; j++)
{
if (j < p)
{
d1 += A[j];
}
int ad = Math.Abs(d1 - (d2 - d1));
x = Math.Min(x, ad);
if (p == A.Length -1) { break; }
p++;
}
return x;
Below is my solution which got 100% . As most of you guys did I first got the sum of the array then go through it while adding up left and right parts and then getting the absolutes of them and putting the results into a map then checking the map for the minimum value .
int totalLeft = 0;
int totalRight = 0;
int total = 0;
int result = 0;
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < A.length; i++) {
total += A[i];
}
for (int i = 0; i < A.length - 1; i++) {
totalRight = total - (A[i] + totalLeft);
totalLeft += A[i];
result = Math.abs(totalLeft - totalRight);
map.put(i, result);
}
return Collections.min(map.values());
TapeEquilibrium in Swift 4
public func solution(_ A : inout [Int]) -> Int {
let P = 1
var splitIndex = P
var firstPartSum = A[splitIndex - 1]
var secondPartSum = Array(A[splitIndex..<A.count]).reduce(0, +)
var minimalDifference = abs(firstPartSum - secondPartSum)
if minimalDifference == 0 {
return minimalDifference
}
splitIndex += 1
while splitIndex < A.count {
firstPartSum += A[splitIndex - 1]
secondPartSum -= A[splitIndex - 1]
let dif = abs(firstPartSum - secondPartSum)
if dif == 0 {
return dif
}
if dif < minimalDifference {
minimalDifference = dif
}
splitIndex += 1
}
return minimalDifference
}
No one posted Javascript solution yet so here is mine with comments:
// you can write to stdout for debugging purposes, e.g.
// console.log('this is a debug message');
function solution(A) {
// write your code in JavaScript (Node.js 8.9.4)
// Making it shorter.
let len = A.length;
// Definitely need to store, and initialise first value.
let left = new Array(len);
left[0] = A[0];
// Same as above, but initialise for last value.
let right = new Array(len);
right[len - 1] = A[len - 1];
let trackLowest = Number.MAX_SAFE_INTEGER;
// One shot calculate for both at any element (from 'outwards' 'in').
// Note there is 2 elements at least, and we already preset the first
// element, so we start and build from index 1.
for (let i = 1; i < len; ++i) {
left[i] = left[i - 1] + A[i];
right[len - 1 - i] = right[len - i] + A[len - 1 - i];
}
// Once the above is done, it's time to calculate the difference.
// If I am at index 0, then I want sum of index 0 AND left, and sum of index
// 1 and right (note not index 0 also).
// We stop before len - 1 because that's the rules and the sum of right will
// have been out of bounds if we want difference for last index, isn't it?
for (let i = 0; i < len - 1; ++i) {
let smallestDiff = Math.abs(left[i] - right[i + 1]);
if (smallestDiff < trackLowest) {
trackLowest = smallestDiff;
}
}
return trackLowest;
}
Basically sum up as you walk the loop simultaneously for the left and right side.
Once done, just get the difference, that's it. O(n) complexity.
My 100% JavaScript solution with O(N) time complexity (should be pretty self-explanatory):
function solution(A) {
let left = 0;
let right = A.reduce((sum, cur) => sum + cur, 0);
let min = Infinity;
for (let p = 0, len = A.length - 1; p < len; p++) {
left += A[p];
right -= A[p];
min = Math.min(min, Math.abs(left - right));
}
return min;
}
100% in Swift 4 for correctness & performance
Detected Time Complexity: 0(n)
var sumMin = A[0]
var sumMax = 0
for i in 1..<A.count {
sumMax += A[i]
}
var diff = abs(sumMin - sumMax)
for i in 1..<A.count-1 {
sumMin += A[i]
sumMax -= A[i]
diff = min(diff, abs(sumMin - sumMax));
}
return diff
Here mine in Java,
// got 91% because "int totalRight = (Arrays.stream(A).sum() - A[0]);" take too long to load
int totalLeft = A[0];
int totalRight = (Arrays.stream(A).sum() - A[0]);
//int afterMinus = 0;
int min = 0;
min = Math.abs(totalLeft - totalRight);
for(int i=1; i<(A.length-1); i++) {
//for(int j=A.length; j>0; j--) {
totalLeft += A[i];
totalRight -= A[i];
//System.out.println("totalLeft = "+ totalLeft);
//System.out.println("totalRight = "+ totalRight);
if(Math.abs(totalLeft - totalRight) < min) {
//System.out.println("min = "+ min);
min = Math.abs(totalLeft - totalRight);
}
}
return min;
// got 100% because change "int totalRight = (Arrays.stream(A).sum() - A[0]);" into for loop
//int totalSum = Arrays.stream(A).sum();
int totalLeft = A[0];
int totalRight = 0;
//int afterMinus = 0;
int min = 0;
for(int i=1; i<A.length; i++) {
totalRight += A[i];
}
min = Math.abs(totalLeft - totalRight);
for(int i=1; i<(A.length-1); i++) {
//for(int j=A.length; j>0; j--) {
totalLeft += A[i];
totalRight -= A[i];
//System.out.println("totalLeft = "+ totalLeft);
//System.out.println("totalRight = "+ totalRight);
if(Math.abs(totalLeft - totalRight) < min) {
//System.out.println("min = "+ min);
min = Math.abs(totalLeft - totalRight);
}
}
return min;
Well, from 91% to 100%, thanks to #sebadagostino after surfing for almost 2 hours for the logic and hints.

Traversing a 2D array matrix diagonally from bottom left to upper right

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;
}
}

Searching a word in a given string array

You are given a 2D array as a string and a word via keyboard. The word
can be in any way (all 8 neighbors to be considered) but you can’t use
same character twice while matching. Return word's first and last
character's index as (x,y). If match is not found return -1.
That's the question. I'm having trouble with searching. I tried that:
int x=0,y=0;
for(int f=0; f<WordinArray.length; f++){
for(int i=0; i<matrix.length; i++){
for(int j=0; j<matrix[0].length; j++){
if(matrix[i][j].equals(WordinArray[f])){
x=i; y=j;
System.out.print("("+x+","+y+")");
}
}
}
}
But, That code is not working as it is supposed to. How else I can write this searching code?
Referring to Sixie's code
Assuming this is a valid input/output to your program?
Size:
4x4
Matrix:
a b c d
e f g h
i j k l
m n o p
Word: afkp
(0,0)(3,3)
I edited your code, so that it should work for input on this form (it is case sensitive at the moment, but can easily be changed by setting .toLowerCase()
Scanner k = new Scanner(System.in);
System.out.println("Size: ");
String s = k.nextLine();
s.toUpperCase();
int Xindex = s.indexOf('x');
int x = Integer.parseInt(s.substring(0, Xindex));
int y = Integer.parseInt(s.substring(Xindex + 1));
System.out.println("Matrix:");
char[][] matrix = new char[x][y];
for (int i = 0; i < x; i++) {
for (int p = 0; p < y; p++) {
matrix[i][p] = k.next().charAt(0);
}
}
System.out.print("Word: ");
String word = k.next();
int xStart = -1, yStart = -1;
int xEnd = -1, yEnd = -1;
// looping through the matrix
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
// when a match is found at the first character of the word
if (matrix[i][j] == word.charAt(0)) {
int tempxStart = i;
int tempyStart = j;
// calculating all the 8 normals in the x and y direction
// (the 8 different directions from each cell)
for (int normalX = -1; normalX <= 1; normalX++) {
for (int normalY = -1; normalY <= 1; normalY++) {
// go in the given direction for the whole length of
// the word
for (int wordPosition = 0; wordPosition < word
.length(); wordPosition++) {
// calculate the new (x,y)-position in the
// matrix
int xPosition = i + normalX * wordPosition;
int yPosition = j + normalY * wordPosition;
// if the (x,y)-pos is inside the matrix and the
// (x,y)-vector normal is not (0,0) since we
// dont want to check the same cell over again
if (xPosition >= 0 && xPosition < x
&& yPosition >= 0 && yPosition < y
&& (normalX != 0 || normalY != 0)) {
// if the character in the word is not equal
// to the (x,y)-cell break out of the loop
if (matrix[xPosition][yPosition] != word
.charAt(wordPosition))
break;
// if the last character in the word is
// equivalent to the (x,y)-cell we have
// found a full word-match.
else if (matrix[xPosition][yPosition] == word
.charAt(wordPosition)
&& wordPosition == word.length() - 1) {
xStart = tempxStart;
yStart = tempyStart;
xEnd = xPosition;
yEnd = yPosition;
}
} else
break;
}
}
}
}
}
}
System.out.println("(" + xStart + "," + yStart + ")(" + xEnd + ","
+ yEnd + ")");
k.close();
I think you need to plan your algorithm a bit more carefully before you start writing code. If I were doing it, my algorithm might look something like this.
(1) Iterate through the array, looking for the first character of the word.
(2) Each time I find the first character, check out all 8 neighbours, to see if any is the second character.
(3) Each time I find the second character as a neighbour of the first, iterate along the characters in the array, moving in the correct direction, and checking each character against the word.
(4) If I have matched the entire word, then print out the place where I found the match and stop.
(5) If I have reached the edge of the grid, or found a character that doesn't match, then continue with the next iteration of loop (2).
Once you have your algorithm nailed down, think about how to convert each step to code.
If I understood your question right. This is a quick answer I made now.
int H = matrix.length;
int W = matrix[0].length;
int xStart = -1, yStart = -1;
int xEnd = -1, yEnd = -1;
String word = "WordLookingFor".toLowerCase();
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (matrix[i][j] == word.charAt(0)) {
int tempxStart = i;
int tempyStart = j;
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
for (int k = 0; k < word.length(); k++) {
int xx = i+x*k;
int yy = j+y*k;
if(xx >= 0 && xx < H && yy >= 0 && yy < W && (x != 0 || y != 0)) {
if(matrix[xx][yy] != word.charAt(k))
break;
else if (matrix[xx][yy] == word.charAt(k) && k == word.length()-1) {
xStart = tempxStart;
yStart = tempyStart;
xEnd = xx;
yEnd = yy;
}
} else
break;
}
}
}
}
}
}
A little trick I used for checking all the 8 neighbors is to use two for-loops to create all the directions to go in:
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
if(x !=0 || y != 0)
System.out.println(x + ", " + y);
}
}
This creates
-1, -1
-1, 0
-1, 1
0, -1
0, 1
1, -1
1, 0
1, 1
Notice: All but 0,0 (you don't want to revisit the same cell).
The rest of the code is simply traversing though the matrix of characters, and though the whole length of the word you are looking for until you find (or maybe you don't find) a full match.
This time the problem is that how could I print word's first and last
letter's indexes. I tried various ways like printing after each word
was searched. But, all of them didn't work. I am about to blow up.
int[] values = new int[2];
for(int i=0; i<matrix.length; i++){
for(int j=0; j<matrix[0].length; j++){
if(Character.toString(word.charAt(0)).equals(matrix[i][j]) == true || Character.toString(ReversedWord.charAt(0)).equals(matrix[i][j]) == true ){
System.out.print("("+ i + "," +j+")");
//First letter is found.Continue.
for(int p=1; p<word.length(); p++){
try{
for (int S = -1; S <= 1; S++) {
for (int SS = -1; SS <= 1; SS++) {
if(S !=0 || SS != 0)
if(matrix[i+S][j+SS].equals(Character.toString(word.charAt(p))) && blocksAvailable[i+S][j+SS] == true ||
matrix[i+S][j+SS].equals(Character.toString(ReversedWord.charAt(p))) && blocksAvailable[i+S][j+SS] == true) {
values[0] = i+S;
values[1] = j+SS;
blocksAvailable[i+S][j+SS] = false;
}
}
}
}catch (ArrayIndexOutOfBoundsException e) {}

Categories

Resources