How to break the if chains in a while .. do ...loop? [duplicate] - java

This question already has answers here:
What is x after "x = x++"?
(18 answers)
Closed 3 years ago.
This is a part of my 2nd method.. the method is using the first and last values of an array given by my main method and adding them together. If the sum is above (in my example "20"), then j (the last value of the array) decreases. If the sum is below 20, i (first value of the array) is increased. The process is repeated until either i == j or i + j = 20
I am using a do ... while loop with a couple of if statements...but for some reason, my program keeps running and gives no result. Help?
public static int checkSum(int[] array){
int i = 0;
int j = 6;
int sum;
sum = array[i] + array[j];
do {
if (sum == 20) {
break;
}
else if (sum < 20) {
i = i++;
sum = array[i] + array[j];
}
else {
j = j--;
sum = array[i] + array[j];
System.out.print("No");
}
sum = array[i] + array[j];
} while (i != j);
if (i == j) {
i = -1;
}
return i;
For the sake of not spamming the website.. i should be 2... but my program gives no results and keeps running infinitely..

The reason your program keeps running is because you are never changing the values of i and j.
The syntax i++ means "increment i, but return the original value (BEFORE the increment)"
So, when your code has a statement like :
i = i++;
you are assigning i to be the value BEFORE the increment - ie. it's not changing !
The fix is to simply use i++ and j++ without assignments.

public static int checkSum(int[] array) {
int i = 0;
int j = 6;
int sum;
do {
sum = array[i] + array[j];
if (sum == 20) {
break;
} else if (sum < 20) {
i++;
} else {
j--;
}
} while (i != j);
if (i == j) {
i = -1;
}
return i;
}
Issue is how you use i++. Check this thread for more details
And I have removed unnecessary code parts mainly the sum = array[i] + array[j].

Related

How can I assign a value to a an integer when a certain character appears in an array?

Given String[] c
I am trying to make it so that if "X" is present in the array 10 is added to int xvalue. Otherwise something else happens.
This is what I have tried so far I am not sure what exactly is going wrong.
if (i==c.length - 1 && !c[i].contains("X") )
sum += 0 ;
else if (c[i].contains("X"))
xvalue+=10;
else
sum += (Integer.parseInt(c[i])*pos) ;
Also the "X" is only ever present in the last value of the array.
Thanks for the help.
Don't know your actual logic make it simple
if (c[i].contains("X") )
xvalue+=10
else
sum += (Integer.parseInt(c[i])*pos)
Whats value is printing? Assuming i is a loop value..
Edit: It will check if the value X or not then add 10 value, if its other value its escape...
public void xCheck(String c[]){
int sum = 0;
int xValue = 0;
int pos = 1;
for (int i = c.length - 1; i >= 0; i--) {
if (c[i].contains("X")) {
xValue += 10;
} else if (pos == 1) {
pos++;
continue;
} else {
//if(sum==0)
sum += pos * (Integer.parseInt(c[i]));
}
pos++;
}
System.out.println(xValue);
System.out.println(sum);
}

Java: How to add lists to a list based on length or sum of values?

I have a requirement to create a list of lists where the each list if of length 5 or the sum of the values in the list is <= 10 (whichever happens first). So far I have:
int currentSize = 0;
Boolean size = false;
Boolean length = false;
for (int s : keyListMax) {
if(currentSize >= 10) {
sizeReached = true;
}
if(currentList.size() >= 5) {
lengthReached = true;
}
if(!sizeReached && !lengthReached) {
currentSize += currentList.stream().mapToInt(Integer::intValue).sum();
currentList.add(s);
}
else {
result.add(0, currentList);
currentList.clear();
currentSize = 0;
}
}
System.out.println("Result is: " + result);
But the result is list of empty lists (maybe because of the clear() I’m using?). Also, how can I achieve this using Java 8?
A much easier solution is just to keep a running total of the elements you have added:
int i = 0;
while (i < keyListMax.size()) {
int start = i;
int sum = 0;
do {
sum += keyListMax.get(i);
++i;
} while (i < keyListMax.size()
&& i < start + 5
&& sum + keyListMax.get(i) <= 10);
result.add(0, new ArrayList<>(keyListMax.subList(start, i)));
}

Need help to solve the hackerrank challenge

I'm trying to solve an "Almost Sorted" challenge in hackerrank the problem is:
Given an array with elements, can you sort this array in ascending order using only one of the following operations?
Swap two elements.
Reverse one sub-segment.
Input Format
The first line contains a single integer, , which indicates the size of the array.
The next line contains integers separated by spaces.
Sample Input #1
2
4 2
Sample Output #1
yes
swap 1 2
Sample Input #2
3
3 1 2
Sample Output #2
no
Sample Input #3
6
1 5 4 3 2 6
Sample Output #3
yes
reverse 2 5
I tried to solve the challenge and my code is working but it seems it's to slow for big arrays.
Kindly asking you to help me to find a better solution for mentioned problem.
Below is my code:
import java.util.*;
public class Solution
{
private static int[] arr;
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int N = in.nextInt();
arr = new int[N];
for (int i = 0; i < N; i++)
{
arr[i] = in.nextInt();
}
if (IsSorted(arr))
{
System.out.println("yes");
return;
}
if(CheckSingleSwap(arr))
return;
if(CheckSingleReverse(arr))
return;
System.out.println("no");
}
private static boolean CheckSingleReverse(int[] arr)
{
int length = arr.length;
int limit = length - 2;
int current = 1;
List<Integer> indexes = new ArrayList<Integer>();
while (current < limit)
{
for (int i = 0; i < length; i++)
{
int temp = current + i;
for (int j = i; j <= temp && temp < length; j++)
{
indexes.add(j);
}
if (IsSorted(ReverseArrayPart(arr, indexes)))
{
System.out.println("yes");
System.out.println("reverse " + (indexes.get(0) + 1) + " " + (indexes.get(indexes.size() - 1) + 1));
return true;
}
indexes.clear();
}
current++;
}
return false;
}
private static int[] ReverseArrayPart(int[] arr, List<Integer> indexes)
{
int[] result = new int[arr.length];
int[] arrayPart = new int[indexes.size()];
int j = 0;
for (int i = 0; i < arr.length; i++)
{
if (indexes.contains(i))
{
arrayPart[j] = arr[i];
j++;
}
result[i] = arr[i];
}
for(int i = 0; i < arrayPart.length / 2; i++)
{
int temp = arrayPart[i];
arrayPart[i] = arrayPart[arrayPart.length - i - 1];
arrayPart[arrayPart.length - i - 1] = temp;
}
j = 0;
for (int i = 0; i < result.length; i++)
{
if (indexes.contains(i))
{
result[i] = arrayPart[j];
j++;
}
}
return result;
}
private static boolean CheckSingleSwap(int[] arr)
{
int count = 0;
int[] B = Arrays.copyOf(arr, arr.length);
Arrays.sort(B);
List<Integer> indexes = new ArrayList<Integer>();
for(int i = 0; i < arr.length; i++)
{
if(arr[i] != B[i])
{
count++;
indexes.add(i+1);
}
}
if(count > 2)
return false;
System.out.println("yes");
System.out.println("swap " + indexes.get(0) + " " + indexes.get(1));
return true;
}
private static boolean IsSorted(int[] arr)
{
int length = arr.length;
for (int i = 0; i < length - 1; i++)
{
if (arr[i] > arr[i + 1])
{
return false;
}
}
return true;
}
}
For the following code, pass in A as the original array and B as the sorted array.
CheckSingleSwap:
Instead of adding the indices to another list, store the first swap you encounter, and keep going; if you find the corresponding other swap, then store it and record the finding; if you find a different swap, exit with false. At the end if you've recorded the finding, print the corresponding indices.
private static boolean CheckSingleSwap(int[] A, int[] B)
{
int L = A.length;
int firstSwap = -1, secondSwap = -1;
for(int i = 0; i < L; i++)
{
if(A[i] != B[i])
{
if (firstSwap == -1)
firstSwap = i;
else if (secondSwap == -1 && A[i] == B[firstSwap] && A[firstSwap] == B[i])
secondSwap = i;
else
return false;
}
}
if (firstSwap != -1 && secondSwap != -1)
{
System.out.println("yes");
System.out.println("swap " + (firstSwap + 1) + " " + (secondSwap + 1));
return true;
}
System.out.println("array is already sorted!");
return false; // or whatever you decide to do; maybe even an exception or enumerated type
}
CheckSingleReverse:
You are doing WAY too much here! You seem to be brute forcing every single possible case (at first glance).
What you can do instead is to find the region where all the numbers are different. If there are more than two of these, or two which are separated by more than one element, then return false immediately.
The reason for the "more than one" thing above is because of odd-number length regions - the middle element would be the same. If you find such two regions, treat them as one. Then you can proceed to find out if the region is reversed.
private static boolean CheckSingleReverse(int[] A, int[] B)
{
// find region
int L = A.length;
int diffStart = -1, diffEnd = -1; boolean mid = false, found = false;
for (int i = 0; i < L; i++)
{
if (A[i] != B[i])
{
if (found)
{
if (i - diffEnd == 2 && !mid)
{
mid = true;
found = false;
diffEnd = -1;
}
else
return false;
}
else if (diffStart == -1)
diffStart = i;
}
else
if (diffStart != -1 && diffEnd == -1)
{
found = true;
diffEnd = i - 1;
}
}
if (diffEnd == -1)
{
if (A[L - 1] != B[L - 1])
diffEnd = L - 1;
else if (!found)
{
System.out.println("array is already sorted!");
return false;
}
}
// find out if it's reversed
int count = (diffEnd - diffStart + 1) / 2;
for (int i = 0; i < count; i++)
{
int oneEnd = diffStart + i, otherEnd = diffEnd - i;
if (!(A[oneEnd] == B[otherEnd] && A[otherEnd] == B[oneEnd]))
return false;
}
System.out.println("yes");
System.out.println("reverse " + (diffStart + 1) + " " + (diffEnd + 1));
return true;
}
Just to give you an idea of the performance boost, on ideone.com, with an array length of 150, the original implementation of CheckSingleReverse took 1.83 seconds, whereas the new one took just 0.1 seconds. With a length of 250, the original actually exceeded the computational time limit (5 seconds), whereas the new one still took just 0.12 seconds.
From this it would seem that your implementation takes exponential time, whereas mine is linear time (ignoring the sorting).
Funnily enough, with an array size of 3 million I'm still getting around 0.26 seconds (ideone's execution time fluctuates a bit as well, probs due to demand)

ArrayIndexOutOfBoundsException: [duplicate]

This question already has answers here:
How can I avoid ArrayIndexOutOfBoundsException or IndexOutOfBoundsException? [duplicate]
(2 answers)
Closed 7 years ago.
Help me to solve this error. This code is for Gutherine series.Consider the following algorithm
Start with a positive number n
if n is even then divide by 2
if n is odd then multiply by 3 and add 1
continue this until n becomes 1
public class Gutherine {
public static void main(String[] args) {
int a[] = {8, 3,2, 1};
int result = isGutherineSequence(a);
System.out.println(result);
}
public static int isGutherineSequence(int a[]) {
int i = 0;
int t = 0;
for (i = 0; i < 4; i++) {
if (a[i] % 2 == 0) {
if (a[i + 1] == a[i] / 2) {
t++;
}
} else if (a[i + 1] == a[i] * 3 + 1) {
t++;
}
}
if (t == 3) {
return 1;
} else {
return 0;
}
}
}
Since inside your loop you access a[i+1], you should iterate i until the next to last element, so change
for (i = 0; i < 4; i++)
to
for (i = 0; i < a.length - 1; i++)
BTW, you don't need the t counter. Once you discover that the series is not a Gutherine sequence, you can return false. You also fail to check that the last element is 1. And you should return a boolean instead of 0 or 1.
Here's a suggested implementation :
public static boolean isGutherineSequence(int a[]) {
for (int i = 0; i < a.length - 1; i++) {
if (a[i] % 2 == 0) {
if (a[i + 1] != a[i] / 2) {
return false;
}
} else if (a[i + 1] != a[i] * 3 + 1) {
return false;
}
}
return (a[a.length - 1] == 1);
}
The exception is caused by your referring to
a[i + 1]
If a[i] could be any element of the array, a[i + 1] could be one to the right of the rightmost element. So your array index would be out of bounds in that case.
The out-of-bounds exception results from your the indirection a[i + 1] even when i is odd. The loop in your isGutherineSequence function will let i reach 3 and the offending line
} else if (a[i + 1] == a[i] * 3 + 1) {
Will effectively try to extract a non-existent a[4].
You should either stop the loop at a previous spot or provide an alternate test for the last element.

Binary to decimal, error message

I wrote a program that convert a binary number to decimal number.
When I run the program with some binary number, the program give me the decimal number but with an error message.
my code:
public class ohad {
public static void main(String[] args) {
String bin = "10011";
int length = bin.length();
int j = 0;
int sum = 0;
if (length != 0) {
for (int i=0; i < bin.length(); i++){
if (bin.charAt(i) == '0' || bin.charAt(i) == '1'){
for (int t = (length - 1); t >= 0; t--){
String s = bin.charAt(j) + "";
sum = (int)(sum + (Integer.valueOf(s)) * (Math.pow(2, t)));
j++;
}
System.out.println(sum);
}
else {
System.out.println("illegal input.");
}
}
} else {
System.out.println("illegal input.");
}
}
}
error message:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 5
at java.lang.String.charAt(String.java:646)
at ohad.main(ohad.java:15)
I think it's something with my j index. What should I do?
What should I do?
I would use Integer.parseInt(String,int) like
String bin = "10011";
System.out.println(Integer.parseInt(bin, 2));
Output is
19
Do you need j index? Looking at this quickly, I think you can use i index instead j.
String s = bin.charAt(j) + "";
String s = bin.charAt(i) + "";
You need to reset your j variable.
in the second iteration of the i for loop that is for (int i=0; i < bin.length(); i++){
j goes out of bounds as it is not set to zero again try the following code :
for (int i=0; i < bin.length(); i++){
j=0; // add this
if (bin.charAt(i) == '0' || bin.charAt(i) == '1'){
for (int t = (length - 1); t >= 0; t--){
String s = bin.charAt(j) + "";
sum = (int)(sum + (Integer.valueOf(s)) * (Math.pow(2, t)));
j++;
}
System.out.println(sum);
} else {
System.out.println("illegal input.");
}
}
While Elliott's answer is absolutely correct and gives a much easier way of solving the problem of converting a binary number to its decimal equivalent, it does not tell you what is causing the error.
You are correct that the exception is thrown because of the j variable, the issue lies in that the j variable is never set back to 0 when the inner loop (with index variable t). I changed your code to reflect this:
for (int t = (length - 1); t >= 0; t--){
String s = bin.charAt(j) + "";
sum = (int)(sum + (Integer.valueOf(s)) * (Math.pow(2, t)));
j++;
}
j = 0; //this is the added code
System.out.println(sum);
This prevents the exception being thrown however causes another issue with the loop being called again, printing each time until you hit 95. I'll let you fix this problem.
You've got one loop too much. That's why j keeps increasing causing the error message.
Delete the t loop:
public static void main(String[] args) {
String bin = "10011";
int length = bin.length();
int j = 0;
int sum = 0;
if (length != 0) {
for (int i = length - 1; i >= 0; i--) {
if (bin.charAt(i) == '0' || bin.charAt(i) == '1') {
String s = bin.charAt(j) + "";
sum = (int) (sum + (Integer.valueOf(s)) * (Math.pow(2, i)));
j++;
} else {
System.out.println("illegal input.");
}
}
System.out.println(sum);
} else {
System.out.println("illegal input.");
}
}

Categories