Issues understanding this java recursive backtracking example - java

The problem is as follows:
You have an array of integers, such as [2,3,1,4,0]. You want to find a path to the last index. You can either move left or right, starting from index 0. The amount of steps you can move along the array depends on the value at the index position. In the end you want to print all the paths.
In my example, you start at index 0, which contains 2. You cannot move left, therefore you move right. Now you are at index 2, which contains 1. You can then move left 1 to reach index 1 which contains 3, then move right 3 to reach the last index.
I am having issues with both the implementation and an idea of how to print out all possible solutions.
My code is as follows:
public static boolean solveH(int index){
if(index == data.size()-1){
printSol(stages);
return true;
}
boolean success = false;
if(!success && (index + Integer.parseInt(data.get(index)) < data.size())){
String temp = data.get(index);
data.set(index, temp + "R");
stages.add(copy(data));
data.set(index, temp);
success = solveH(index + Integer.parseInt(data.get(index)));
stages.remove(stages.size()-1);
}
if(!success && (index - Integer.parseInt(data.get(index)) > 0)){
String temp = data.get(index);
data.set(index, temp + "L");
stages.add(copy(data));
data.set(index, temp);
success = solveH(index - Integer.parseInt(data.get(index)));
stages.remove(stages.size()-1);
}
return false;
}

My approach would be: At every field visit left, visit right (in fact - branch at every step).
Ok - first, like you did: look if we reached the target.
Then, save the value at that index for stepping left and right and then set the value to 0 as mark for 'visited'. You're anyhow frozen on a zero field and the check for reaching the target is based on the index = last index.
Instead of strings and parsing, just store plain numbers in an array.
Code:
public class StepArray {
// using static fields/methods is a bit ugly. Maybe improve main,
// to allow passing an array to visit dynamically.
static int[] data = new int [] {2, 3, 1, 4, 0};
static int len = data.length;
public static boolean solveH (int index){
if (index == len - 1) {
System.out.println ("found at index " + index + "!");
return true;
}
// save the value before overwriting:
int step = data[index];
// already visited?
if (step == 0) return false;
// mark for later visitors as visited by setting to 0:
data[index] = 0;
if (index + step < len) {
System.out.print (" R:" + step);
solveH (index + step);
}
// no need to visit 0 again, which is always the starting point
if (index - step > 0) {
System.out.print (" L:" + step);
solveH (index - step);
}
return false;
}
public static void main (String args[]) {
solveH (0);
}
}
Here is the improved version for more fun and flexibility (the core algorithm only has cosmetic changes):
import java.util.Random;
public class ArraySteps {
int[] data;
int len;
public ArraySteps (int [] values) {
data = values;
len = data.length;
solveH (0);
System.out.println ();
}
boolean solveH (int index) {
if (index == len - 1) {
System.out.println (" found at index " + index + "!");
return true;
}
int step = data[index];
// already visited
if (step == 0) return false;
// mark for later visitors as visited by setting to 0:
data[index] = 0;
boolean r = false, l = false;
if (index + step < len) {
System.out.print (" R:" + step);
r = solveH (index + step);
}
if (index - step > 0) {
System.out.print (" L:" + step);
l = solveH (index - step);
}
if (r || l) return true;
System.out.println (" dead end.");
return false;
}
public static void main (String args[]) {
// default, no args:
int [] param;
System.out.println ("args.length: " + args.length);
if (args.length == 0)
{
System.out.println ("default: ");
param = new int [] {2, 3, 1, 4, 0};
}
// one arg: Generate count N random values
else if (args.length == 1)
{
System.out.println ("Random: ");
int anz = Integer.parseInt (args[0]);
Random r = new Random ();
param = new int [anz];
for (int i = 0; i < anz - 1; ++i) {
param [i] = r.nextInt (Math.min (anz/2, 9)) + 1;
}
param[anz-1] = 0;
}
else {
System.out.println ("User defined: ");
param = new int [args.length + 1];
for (int i = 0; i < args.length; ++i)
{
param[i] = Integer.parseInt (args[i]);
}
param [args.length] = 0;
}
show (param);
new ArraySteps (param);
}
private static void show (int[] ls)
{
for (int i: ls)
System.out.print (i + " ");
System.out.println ();
}
}

Related

Error on Binary Search & Merge Sort Functions (with IO & command line)

I am experiencing an error. Running this program requires referencing the compiled jar file in a command line to specify the targets that must be found in the input file.
The error that is happening is any target string specified in the command line (that is present in the input file) gets an output of " not found", when it should be outputting " found on line {lineNumber}".
I went through the entirety of the class and frankly, I'm completely lost as to where this error occurs.
Any help is appreciated.
Main Class:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Search {
public static void main(String[] args) throws FileNotFoundException {
Scanner in = null;
int index = 0;
String[] word = null;
int[] lineNumber = null;
// check number of command line arguments is at least 2
if (args.length < 2) {
System.out.println("Usage: Search <input file> <target1> [target2...]");
System.exit(1);
}
// initialize Scanner
in = new Scanner(new File(args[0]));
// matches the end of a file character
in.useDelimiter("\\Z");
// puts entire file into one string
String temp = in.next();
in.close();
// intialize arrays & plug elements in
word = temp.split("\n");
lineNumber = new int[word.length];
populate(lineNumber);
// sort String array
mergeSort(word, lineNumber, 0, word.length - 1);
// if multiple targets exist
if (args.length > 2) {
for (int i = 1; i < args.length; i++) {
index = binarySearch(word, 0, word.length - 1, args[i]);
if (index < 0) {
System.out.println(args[i] + " not found");
} else {
System.out.println(args[i] + " found on line " + lineNumber[index]);
}
}
// if only single target specified in command line
} else {
index = binarySearch(word, 0, word.length - 1, args[1]);
if (index < 0) {
System.out.println(args[1] + " not found");
} else {
System.out.println(args[1] + " found on line " + lineNumber[index]);
}
}
}
// recursively halves arrays then plugs into merge function
public static void mergeSort(String[] word, int[] lineNumber, int p, int r) {
int q;
if (p < r) {
// q is midpoint
q = (p + r) / 2;
// recursive stuff
mergeSort(word, lineNumber, p, q);
mergeSort(word, lineNumber, q + 1, r);
// merge arrays
merge(word, lineNumber, p, q, r);
}
}
// merges sorted String arrays into one large sorted String array
public static void merge(String[] word, int[] lineNumber, int p, int q, int r) {
// element ranges
int n1 = q - p + 1;
int n2 = r - q;
// half String arrays to be merged
String[] L = new String[n1];
String[] R = new String[n2];
// half int arrays to be merged
int[] iL = new int[n1];
int[] iR = new int[n2];
// array indexes (for looping)
int i, j, k;
// plugging specific elements into new array
for (i = 0; i < n1; i++) {
L[i] = word[p + i];
iL[i] = lineNumber[p + i];
}
// plugging specific elements into new array
for (j = 0; j < n2; j++) {
R[j] = word[q + j + 1];
iR[j] = lineNumber[q + j + 1];
}
// reset array indexes
i = 0;
j = 0;
// loop through entirety of elements
for (k = p; k <= r; k++) {
// if both arrays still have unmerged element(s)
if (i < n1 && j < n2) {
// if left array's element precedes right's element
// lexicographically
if (L[i].compareTo(R[j]) < 0) {
word[k] = L[i];
lineNumber[k] = iL[i];
i++;
} else { // if right's element precedes (or the words are equal)
word[k] = R[j];
lineNumber[k] = iR[j];
j++;
}
// if only left array has unmerged element(s)
} else if (i < n1) {
word[k] = L[i];
lineNumber[k] = iL[i];
i++;
// if only right array has unmerged element(s)
} else {
word[k] = R[j];
lineNumber[k] = iR[j];
j++;
}
}
}
// searches sorted String array and returns index of target (or -1 if not
// found)
public static int binarySearch(String[] word, int p, int r, String target) {
int q;
if (p > r) {
return -1;
} else {
q = (p + r) / 2;
if (target == word[q]) {
return q;
} else if (target.compareTo(word[q]) < 0) {
return binarySearch(word, p, q - 1, target);
} else {
return binarySearch(word, q + 1, r, target);
}
}
}
// helper method: plugs numbers (in order) into an int array
public static void populate(int[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = i + 1;
}
}
}
You need to change the below method. String should be compared with equals() method and use trim() method to avoid trailing spaces.
public static int binarySearch(String[] word, int p, int r, String target) {
int q;
if (p > r) {
return -1;
} else {
q = (p + r) / 2;
if (target.trim().equals(word[q].trim())) {
return q;
} else if (target.compareTo(word[q]) < 0) {
return binarySearch(word, p, q - 1, target);
} else {
return binarySearch(word, q + 1, r, target);
}
}
}

Find the largest index occurrence of a number using binary search

This code, generates a random number, sorts it in ascending order and does the binary search to find a target value. MY QUESTION IS HOW DO I MODIFY THIS CODE TO FIND THE LARGEST INDEX OF THE GIVEN TARGET. For example the array has { 1, 2 , 3, 5, 5, 5, 5}, the target is 5, so the output should be 6 instead of 3. Thankyou.
import java.util.*;
public class Sort
{
public static void main(String args[])
{
Scanner in = new Scanner(System.in);
System.out.print("How many numbers do you want? ");
int howMany = in.nextInt();
int [] myArray = getSortedRandomArray(howMany);
System.out.print("\nFor what value would you like to search? ");
int target = in.nextInt();
int index = bsearch ( myArray, target);
if (index >= 0)
{
System.out.println("The value " + target + " occurs at index " + index);
}
else
{
System.out.println("The value " + target + " does not occur in the array. ");
}
}
public static int bsearch(int[] arr, int key)
{
int lo = 0, hi = arr.length - 1;
{
while (lo < hi)
{
int mid = (lo + hi) / 2;
if (arr[mid] <= key)
lo = mid + 1;
if (arr[mid] > key)
hi = mid;
}
if (arr[lo] == key) {
return lo;
}
else if ((arr[lo] != key) && (arr[lo-1] == key)){
return lo - 1;
}
else{
System.out.print("The value " + key + " does not occur in the array. ");
}
return -1 ;
}
public static int[] getSortedRandomArray (int howMany)
{
int[] returnMe = new int [howMany];
Random rand = new Random();
for (int i = 0; i < howMany ; i++)
returnMe[i] = rand.nextInt(Integer.MAX_VALUE) + 1;
for (int i = 1; i <= (howMany - 1); i++)
{
for (int j = 0; j <= howMany - i -1; j++)
{
int tmp = 0;
if (returnMe[j] > returnMe[j+1])
{
tmp = returnMe[j];
returnMe[j] = returnMe[j + 1];
returnMe[j + 1] = tmp;
}
}
}
System.out.print("Here is a random sorted array: ");
for ( int i = 0; i < howMany; i++)
System.out.print(returnMe[i] + " ");
return returnMe;
}
You can do this by modifying the binary search algorithms code like this:
public static int bsearch(int[] arr, int key) {
int lo = 0, hi = arr.length - 1;
while (lo < hi) {
int mid = (lo + hi) / 2;
if (arr[mid] <= key)
lo = mid + 1;
if (arr[mid] > key)
hi = mid;
}
if (arr[lo] == key) {
return lo;
}
else {
return lo - 1;
}
}
This code instead searches for the first number larger than key. That can be any number, 6 or 10000, it doesn't matter. As you can see, if arr[mid] is equal to key, the code will still run on the interval [mid, hi]. Why those two returns at the end? Well if input array is like the one you gave, lo will end being the index of the last 5, but if we add another number at the end of input array, lo will be index of the number behind the last 5. Therefore, we have 2 different cases.
Also, you can't do it with a linear loop like other answers, because that reduces the algorithm to O(n) and it ends just being a linear search on a reduced array.
If you update your bsearch algorithm a little you can ask it to seek higher matches recursively. However whether this is more efficient than a linear loop would depend on what the input array looked like.
public static int bsearch(int[] arr, int key, int lo, int hi) {
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (arr[mid] == key) {
System.out.println("The value " + key + " is found at " + mid);
int higherResult = bsearch(arr, key, mid + 1, hi);
if (higherResult < 0) {
return mid;
}
return higherResult;
}
if (arr[mid] < key) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return -1;
}

Beginning Java - Creating a successful binary search algorithm

Design an application that has an array of at least 20 integers. It should call a module that uses the sequential search algorithm to locate one of the values. The module should keep a count of the number of comparisons it makes until it finds the value. Then the program should call another module that uses the binary search algorithm to locate the same value. It should also keep a count of the number of comparisons it makes. Display these values on the screen.
I already have the sequential search working properly, and it displays the number of iterations it took to find the desired value. However, I am having trouble with my binary search module. Every time it searches for a value, it always returns the value 1. Here is the code I have excluding the sequential search module.
Appreciate any help.
//Scanner class
import java.util.Scanner;
public class JavaProgramCh9Ex7_test {
//global scanner to read input
static Scanner keyboard = new Scanner(System.in);
//size of array
final static int SIZE = 20;
//main
public static void main(String[] args) {
//populate the array
int [] twentyNumbers = new int [SIZE];
populateTwentyNumbersArray(twentyNumbers);
//sort the numbers using bubble sorting:
bubbleSort(twentyNumbers);
displayTwentyNumbersSorted(twentyNumbers);
//ask the user for a value to search for:
int desiredValue = getValidInteger("Search for a number", 1, 20);
//start the binary search algorithm:
int binSearchComparison = performBinarySearch (twentyNumbers, desiredValue);
System.out.println(binSearchComparison);
}
//Display the 20 integers in the array in ascending-order:
public static void displayTwentyNumbersSorted (int [] numArray){
System.out.println("");
System.out.println("Here are the 20 numbers sorted in ascending-order");
for (int i = 0; i < numArray.length; i++) {
if(i < 19){
System.err.print(numArray[i] + ", ");
}
else{
System.err.print(numArray[i]);
}
}
}
//Perform the binary search for the user's desired value:
public static int performBinarySearch (int [] numArray, int userValue){
int first = 0;
int middle;
int last = (numArray.length - 1);
int iteration = -1;
boolean found = false;
for (int i = 0; i < numArray.length; i++) {
while ((!found) && (first <= last)) {
middle = ((first + last) / 2);
if (numArray [middle] == userValue) {
found = true;
iteration = (i + 1);
}
if(numArray [middle] > userValue) {
last = (middle - 1);
}
if(numArray [middle] < userValue) {
first = (middle + 1);
}
}
}
return iteration;
}
//Populate the array with 20 random integers:
public static void populateTwentyNumbersArray (int [] numArray){
int number = 0;
for (int i = 0; i < numArray.length; i++) {
do{
number = getRandomNumber(1, 20);
}while (checkNum(numArray, number));
numArray[i] = number;
}
}
//Check to make sure the number is unique:
public static boolean checkNum (int [] numArray, int num) {
boolean value = false;
for (int i = 0; i < numArray.length; i++) {
if (numArray[i] == num) {
value = true;
}
}
return value;
}
//Sort the array in ascending order
public static void bubbleSort(int [] numArray){
int temp;
int maxElement;
for(maxElement = (SIZE - 1); maxElement > 0; maxElement--){
for(int i = 0; i <= (maxElement - 1); i++){
if(numArray[i] > numArray[i + 1]){
temp = numArray[i];
numArray[i] = numArray[i + 1];
numArray[i + 1] = temp;
}
}
}
}
//Get a valid Integer from the user to determine the number of seats sold per section:
public static int getValidInteger(String msg, int low, int high) {
int newValue = getInteger(msg);
//Check that the user entered a valid number within the range:
while (newValue < low || newValue > high) {
System.err.println("Please enter a number from " + low + " to " + high + ".");
newValue = getInteger(msg);
}
return newValue;
}
//Check for a valid Integer input from the user:
public static int getInteger(String msg) {
System.out.println(msg);
while (!keyboard.hasNextInt()) {
keyboard.nextLine();
System.err.println("Invalid integer. Please try again.");
}
int number = keyboard.nextInt();
keyboard.nextLine(); //flushes the buffer
return number;
}
//Get a random number to represent the computer's choice:
public static int getRandomNumber(int low, int high){
return (int)(Math.random() * ((high + 1) - low)) + low;
}
}
In your performBinarySearch you check for the all values of array, this maximizes the binary search complexity, though the loop hasn't any effect on searching. If the value present in the array, then the searching function checks whether it is present or not when i=0 and make found=true. After that the inner while loop don't executes as found=true all the times.
For that reason, iterator=(i+1) for i=0 all the times if the value is present in the array, otherwise iterator=-1.
Consider the below performBinarySearch function :
public static int performBinarySearch(int[] numArray, int userValue) {
int first = 0;
int middle;
int last = (numArray.length - 1);
int iteration = 0;
boolean found = false;
while ((!found) && (first <= last)) {
iteration++;
middle = ((first + last) / 2);
if (numArray[middle] == userValue) {
found = true;
break;
}
if (numArray[middle] > userValue) {
last = (middle - 1);
}
if (numArray[middle] < userValue) {
first = (middle + 1);
}
}
if (found) return iteration;
else return -1;
}
Here, I have reused your code with a simple modification. I have deleted your redundant outer loop and calculated the number of iteration each time the while loop executes. If found then make found=true and break the loop(as I have already found the expected value) and return the value.

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)

Finding Consecutive Duplicate integers in an array

I have a problem in which I need to ask for user input for how many times they wish to roll a die and to create and print that an array that has the rolls requested. So far I can create the array, however another part of the problem is that whenever there are consecutive duplicate rolls I must put parentheses around them. For example inputting 11, creates the array
{1 , 2 , 1 , 4 , 4, 6 , 2 , 3 , 5 , 5 , 5} would print 1 2 1 ( 4 4 ) 6 2 3 ( 5 5 5 )
So far I have written
import java.util.Scanner;
import java.util.Random;
public class HW0603 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("How many times would you like to roll: ");
System.out.println();
int x = input.nextInt();
run(rolls(x), x);
}
public static int[] rolls(int x) {
Random random = new Random();
int y[] = new int[x];
for (int i = 0; i < x; i++) {
int z = random.nextInt(6) + 1;
y[i] = z;
}
return y;
}
public static void run(int a[], int b) {
for (int i = 1; i < b; i++) {
System.out.print(a[i] + " ");
}
}
}
As for the parentheses I honestly don't know how to start. Using if statements didn't work for me, my if statement variations seem to give me out of bound errors since I compare a[i] to a[i+1] and a[i-1]. Could anyone give me a place to start or some tips to being extracting consecutive duplicates?
you need to compare current item with next item
if equal, print "(" then print the item
make flag paranOpened that you have opened (, so you don't reopen ( again, to avoid this: 1 (2(2(2..., then when curr!=next, based on that flag either print the item or print the item then close the ")"
at end of loop
print lat item (b-1) that was excluded from the loop ..;i < b - 1;.., and check if you have opened "("
your run() method will be like this
static boolean paranOpened = false;
public static void run(int a[], int b) {
for (int i = 0; i < b - 1; i++) {
if (a[i] == a[i + 1]) {
if (!paranOpened) {
paranOpened = true;
System.out.print(" (");
}
System.out.print(a[i] + " ");
} else {
System.out.print(a[i] + " ");
if (paranOpened) {
System.out.print(") ");
paranOpened = false;
}
}
}// for loop
// print last item in array #(b-1)
System.out.print(a[b - 1] + " ");
// check if opened ( , then close it
if (paranOpened) {
System.out.print(") ");
}
}// run()
this is a quick solution, there could be better algorithms
The first problem with you program is that the counter in your run method starts
from 1 which should be zero. Your current program does not print the first element of the array.
then you need to check each element with the next one to see if they are duplicate and if they are open the parenthesis and vice versa.
The last element does not need to be checked so print it outside the loop and close the parenthesis if needed.
By the way you do not need to pass the array size element with it. Just use the array.length method.
public static void run(int a[], int b)
{
boolean pOpen = false;//keep track if parenthesis is open
for (int i = 0; i<a.length; i++)
{
if (i < a.length-1)//prevent out of bound exception
{
if (a[i] == a[i+1] && !pOpen )// check if it is needed to `open or close the parenthesis`
{
System.out.print("(");
pOpen = true;
}
System.out.print(a[i] + " ");
if (a[i] != a[i+1] && pOpen)
{
System.out.print(")");
pOpen = false;
}
}
}
System.out.print(a[a.length-1]);//print the last element
if (pOpen)//close the parenthesis if open
{
System.out.print(")");
}
}
Iterate through your array and keep a boolean that marks if parenthesis have opened.
import java.util.*;
class Ideone
{
public static int[] rolls(int x) {
Random random = new Random();
int y[] = new int[x];
for (int i = 0; i < x; i++) {
int z = random.nextInt(6) + 1;
y[i] = z;
}
return y;
}
public static void run(int a[], int b) {
StringBuilder sb = new StringBuilder();
String out = "";
boolean parens = false;
for (int j = 0; j < a.length; j++)
{
out = "" + a[j]; //by default just add an element
//check for duplicate and build parenthesis
if (j + 1 < a.length && a[j] == a[j+1]) //duplicate found
{
if (!parens) // if no parenthesis
{
parens = true; //start parenthesis
out = "( " + a[j];
}
}
else
{
if (parens) //if parenthesis already started
{
out = a[j] + " )";
parens = false; //stop parenthesis
}
}
sb.append(" " + out);
}
// if the last element occured multiple times
if (parens) //should end parens
{
sb.append(a[a.length-1] + " )");
}
//print out the result
System.out.println(sb.toString());
}
public static void main (String[] args) throws java.lang.Exception
{
Scanner input = new Scanner(System.in);
System.out.print("How many times would you like to roll: ");
System.out.println();
int x = input.nextInt();
run(rolls(x), x);
}
}
You need to use boolean to check whether your parenthesis is open or no.
Here I've tried to create a clean and readable example:
Sample code:
public class HelloWorld {
public static void main(String[] args) {
int arr[] = { 1, 2, 1, 4, 4, 6, 2, 3, 5, 5, 5 };
printConsecutiveInBrace(arr);
}
public static void printConsecutiveInBrace(int arr[]) {
int printFrom = 0;
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1 || arr[i] != arr[i + 1]) {
print(arr, printFrom, i);
printFrom = i + 1;
}
}
}
public static void print(int arr[], int printFrom, int printTo) {
if (printFrom < printTo) //Here check: Consecutive Duplicate
System.out.print("( ");
for (int i = printFrom; i <= printTo; i++)
System.out.print(arr[i] + " ");
if (printFrom < printTo)
System.out.print(") ");
}
}
Output:
1 2 1 ( 4 4 ) 6 2 3 ( 5 5 5 )

Categories