Related
I have a programming exam in a few days so I'm doing some exercises just to practice. However, I've been stuck with this problem and I started to doubt if it's possible to do it. Write a recursive method called arrayReverse which takes in an array of integers and returns said array in reversed sorted order. So an example would be:
input: [1,2,3]
output:[3,2,1]
I wasn't able to solve it. My intuition was to take the last element of the array, put it at the beginning, i,e: index[0] and then recursively call the rest of the array but then taking the new last element and put it on index[1]. Unfortunately, the implementation was harder than I thought but I (for the sake of trying) edited the question in a way that it accepts 2 arrays and this was my code:
import java.util.Arrays;
class Test {
int[] arrayReverse(int[] m, int[] mReverse) {
if (m.length == 1) {
mReverse[mReverse.length - 1] = m[0];
return mReverse;
} else {
int lastNum = m[m.length - 1];
mReverse[mReverse.length - m.length] = lastNum;
int[] arrayMinusOne = cropArray(m);
return arrayReverse(arrayMinusOne, mReverse);
}
}
int[] cropArray(int[] m) {
int[] mCropped = new int[m.length - 1];
for (int i = 0; i < m.length - 1; i++) {
mCropped[i] = m[i];
}
return mCropped;
}
}
void demo() {
int[] helpTest4 = new int[]{1, 2, 3};
int[] emptyArray = new int[helpTest4.length];
int[] test4 = arrayReverse(helpTest4, emptyArray);
System.out.println(Arrays.toString(test4));
}
public static void main(String[] args) {
new Test().demo();
}
}
It works perfectly but I'm not satisfied with the result because of two reasons:
I wasn't able to do it completely recursive. I used a for loop in cropArray.
I couldn't do it on one array.
How can this be done?
Option1: Using only one parameter (array) in the recursive function
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
public class MyClass {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
int[] reversed = reverseArray(arr);
System.out.println(Arrays.toString(reversed));
}
public static int[] reverseArray(int[] arr)
{
if (arr.length == 0)
return arr;
// remove first element
int first = arr[0];
int[] list = Arrays.copyOfRange(arr, 1, arr.length);
//Calling Function Recursively get reversed array
int[] returnArr = reverseArray(list);
//Add original first to the last of the arrayToReturn
returnArr = Arrays.copyOf(returnArr, returnArr.length + 1);
returnArr[returnArr.length - 1] = first;
return returnArr;
}
}
Option2:
void reverseArray(int[] x){
reverse(x, 0, x.length -1);
}
void reverse(int[] x, int i, int j){
if(i<j){//Swap ith with jth element where i and j are equidistant from ends
int tmp = x[i];
x[i] = x[j];
x[j] = tmp;
reverse(x, ++i, --j);//Recursive
}
}
Test:
int[] s = new int[]{1,2,3,4,5};
reverseArray(s);
System.out.println(Arrays.toString(s));//"5,4,3,2,1"
Recursive, O(n), no temporary Array needed.
Please try the code below:
import java.util.*;
public class HelloWorld{
public static void main(String []args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[]= new int[n];
for(int i=0;i<n;i++)
{
arr[i] = sc.nextInt();
}
Printsum(arr,0);
}
public static void Printsum(int arr[], int idx)
{
if(idx == arr.length)
return ;
Printsum(arr,idx+1);
System.out.println(arr[idx]);
}
}
I don't think this is a particularly good question - there is obviously a direct and clear way to do it without recursion; so the question does little to demonstrate any useful knowledge of recursion.
That said I believe the algorithm they were seeking uses the facts that:
a) reversing a 1 length array is trivial
b) you can reverse an n length array by appending the first element to the reverse the the last n-1 elements.
So code for this solution will look much simpler that what you currently have.
Ruby:
def reverse(a)
if a.empty?
return []
else
return [a.last] + reverse(a[0..-2])
end
end
a = [1, 2, 3]
reverse(a)
Taking the request literally, I have come out with a solution which only needs ONE recursive function with just ONE input/output parameter:
public static void arrayReverse(int[] input)
{
if (input.length > 0)
{
// Store locally the fist element:
int firstElement=input[0];
// Creates a sub-array and reverses it:
int[] input2=new int[input.length - 1];
System.arraycopy(input, 1, input2, 0, input2.length);
arrayReverse(input2);
// Copies back the reversed array into the current array:
System.arraycopy(input2, 0, input, 0, input2.length);
// Puts the stored fist element in the last position:
input[input.length - 1]=firstElement;
}
}
This solution is based upon a stack structure, for which it takes advantage of the machine calling stack at runtime, where the local values are stored while the function is executing.
The base case of this recursion is, of corse, the empty array.
In the generic case, the function stores locally the first element, then re-invokes itself recursively to reverse the rest of the array, and last, puts back the first element in the last position.
For example if I enter inRange(1,6) then it must print {2,2,2,3,5} for the below array. I am not sure if my logic is right. Is there a better way to do this? I am also not sure of how to construct my return statement. I want to do this without using arraylist or array.
public class AgeCount {
static int[] a=new int[]{1,2,45,6,3,2,1,2,5,6,65,45,43,21,34,34};
public AgeCount(){
}
public static int inRange(int b,int e)
{
int store[]=new int[a.length];
int count=0;
for (int i = 0; i < a.length; i++) {
if(a[i]>b && a[i]<e)
{
return a[i];
}
}
return 0;
}
If your method only has to print the numbers of the given range, it doesn't have to return anything :
public static void inRange(int b,int e)
{
int count=0;
System.out.print('{');
boolean first = true;
for (int i = 0; i < a.length; i++) {
if(a[i]>=b && a[i]<=e)
{
if (!first) {
System.out.print(',');
} else {
first = false;
}
System.out.print(a[i]);
}
}
System.out.print('}');
}
This is assuming the order of the output doesn't matter. If it does matter, sort the input array prior to the loop.
Java 8 approach:
int[] arr = new int[] {1,2,45,6,3,2,1,2,5,6,65,45,43,21,34,34};
int res[] = Arrays.stream(arr).filter(n -> n >= b && n <= e).toArray();
System.out.println(Arrays.toString(res));
I'm not sure why you don't want to use arrays or some kind of a list. If it's for homework purposes, then instead of returning a value from the method, print it if you only want to display the result. Otherwise, you should consider using List.
Java8:
public static void main(String[] args) {
int[] arrayToFilter = new int[]{1, 2, 45, 6, 3, 2, 1, 2, 5, 6, 65, 45, 43, 21, 34, 34};
int upperLimit = 5;
inRange(arrayToFilter, upperLimit);
}
private static void inRange(int[] arrayToFilter, int upperLimit) {
String sortedAndLimitedString = Arrays.stream(arrayToFilter)
.sorted()
.filter(value -> value < upperLimit)
.mapToObj(String::valueOf)
.collect(Collectors.joining(",", "{", "}"));
System.out.println(sortedAndLimitedString);
}
Output:
{1,1,2,2,2,3}
This sounds like a homework question. Still here goes.
Your return being a single int it has to be something like 122235 which represents all the ints satisfying your range condition.
So you use BitSet class and set the bits when found in range, which you can convert to an int like above and return.
I assumed that the result must be sorted.
public static int[] inRange(int b,int e) {
return IntStream.of(a)
.filter(n -> n > b && n < e)
.sorted()
.toArray();
}
System.out.println(Arrays.toString(AgeCount.inRange(1, 6)));
// -> [2, 2, 2, 3, 5]
```
Here is the simple & the shortest solution.
import java.util.*;
public class AgeCount
{
static int[] a=new int[]{1,2,45,6,3,2,1,2,5,6,65,45,43,21,34,34};
public AgeCount()
{
}
public static void inRange(int b,int e)
{
int store[]=new int[a.length];
Arrays.sort(a);
for (int i = b; i < e; i++)
{
System.out.print(a[i+1]+",");
}
}
}
And this is how you return a value for the same.
//sort an array, get a defined index values, and print it on the screen.
import java.util.*;
public class AgeCount
{
static int[] a=new int[]{1,2,45,6,3,2,1,2,5,6,65,45,43,21,34,34};
public AgeCount()
{
}
public static int[] inRange(int b,int e)
{
int store[]=new int[a.length];
int[] myRange = new int[e-b];
Arrays.sort(a);
for (int i = b; i < e; i++)
{
for (int j = 0; j < (e-b); j++)
{
myRange[j] = a[i+1];
}
System.out.print(a[i+1]+",");
}
return myRange;
}
}
Nice start so far! Even though you said you didn't want to use array or ArrayList, it makes the most sense here to use one. I would use an ArrayList of Integers instead of just an array, because we don't know the length yet. Instead of saying return a[i];, you would say store.append(a[i]);. I haven't tested this code, so there may be an error or two, so please correct me if I'm wrong, but here's the fixed version:
public class AgeCount {
static int[] a=new int[]{1,2,45,6,3,2,1,2,5,6,65,45,43,21,34,34};
public AgeCount(){
}
public static void inRange(int b,int e)
{
ArrayList<Integer> store = new ArrayList<Integer>();
int count=0;
for (int i = 0; i < a.length; i++) {
if(a[i]>=b && a[i]<=e)
{
store.append(a[i]);
}
}
println(store);
}
}
Well first things first, it seems like you aren't fully clear on what you are trying to do. And that's okay! Sometimes a problem can seem overwhelming and confusing if we're not really sure what's supposed to happen.
I recommend when you're starting a new task you take some time to decompose the task. Take a piece of paper and try and break it down into its smallest and simplest parts and go from there, coding and testing it bit by bit. The basics of the SDLC (try googling the software development lifecycle) could help you here too - it's all about figuring out what you are trying to achieve and what are the various things you need to implement to get there.
And please, Don't panic and throw code you don't understand down! You'll only sink deeper into the confusion!
I need a shuffle method to shuffle elements of an array which holds objects from another class. At the moment I wrote this code to test with integers first, but it seems to not working perfectly. Most of the elements are being duplicated.
Can someone please spot the mistake?
And also come up with a more efficient method for this.
I am not sure if I can use collections.shuffle because I have further use of my shuffled array later.
public static void shuffle()
{
int[] a = new int[52];
int count = 0;
int random = 0;
while (count!=51){
random = (int)(Math.random() * 52);
for (int i=0; i <=count; i++){
if (a[count] != b[random])
result = true;
}
if (result){
a[count] = b[random];
count++;
}
b = Arrays.copyOf(a, a.length);
}
}
First you should not define shuffle() in this way. I would treat b as a parameter and pass it into shuffle() instead of a static field (as your shuffle() is declared as static, your b is also static right? It looks strange to share b between all instances), and result is declared as a local variable.
This part
for (int i=0; i <=count; i++){
if (a[count] != b[random])
result = true;
}
checks whether any one of a[0], a[1] until a[count] is not equal to b[random]. If yes, then assign b[random] to a[count] and increase count by 1. As a[] is not initialized, it is only an array of 0. (a[count] != b[random]) appears to be always true and hence result is true.
Then, for this part,
if (result){
a[count] = b[random];
count++;
}
say for example random=5, then at the first round of the while loop a[0]=b[5], count=1 (due to count++), and b becomes an array of b[5] and a series of 0. (Due to
b = Arrays.copyOf(a, a.length);
all other elements are replaced by 0.)
Edit: Here I provide a simple method, not thoroughly tested, but should work:
public static int[] shuffle(int[] array) {
int[] a = new int[array.length];
//convert int[] to ArrayList<Integer>
ArrayList<Integer> list = new ArrayList<>();
for (int i: array)
list.add(i);
//now shuffle:
for (int i=0; i<array.length; i++) {
int rand = (int)(Math.random()*list.size());
a[i] = list.remove(rand);
}
return a;
}
The array returned is shuffled. Actually I can't say the method "shuffles" the array. It simply creates an empty array, and repeatedly selects an element randomly and put it at the front.
Edit2: This really "shuffles", and this is another approach: does not return a new array. It shuffles the array, 100 times.
public static void shuffle(int[] array) {
for (int i=0; i<100; i++) {
int r1 = (int)(Math.random()*array.length);
int r2 = (int)(Math.random()*array.length);
int tmp = array[r1];
array[r1] = array[r2];
array[r2] = tmp;
}
}
import java.util.Random;
public class Shuffle {
public static void main(String[] args) {
Integer[] a = new Integer[52];
for (Integer i=0;i<a.length;i++) a[i] = i+1;
// Let's shuffle
Random rd = new Random();
for (Integer i=0;i<a.length;i++){
Integer changeBy = rd.nextInt(a.length);
Integer aux=a[i];
a[i]=a[changeBy];
a[changeBy] = aux;
}
// Now show the shuffled array
for (Integer i=0;i < a.length; i++) System.out.print(a[i]+",");
}
}
Hope this small algorithm helps you. As you can see from 2 different runs, it really shuffles your array:
11,1,24,13,28,15,25,48,5,22,12,32,29,42,34,7,33,31,47,18,51,40,8,17,41,20,6,36,21,45,27,52,38,10,30,14,23,19,43,4,50,46,44,3,49,37,35,2,9,26,16,39
3,10,37,26,41,15,28,52,6,24,20,43,33,21,51,32,25,40,50,8,7,5,4,35,13,16,49,17,29,47,12,14,36,39,45,30,2,42,23,38,31,19,27,46,34,11,18,1,22,48,9,44
Why no you HashSet for shuffle?
Elements in java.lang.HashSet are shuffling by their hashcode.
public static void shuffle()
{
int [] b; // you origin array
Set<Integer> temp = new HashSet<Integer>();
for (int i : b) {
temp.add(i);
}
Integer [] a = new Integer[b.length];
a = temp.toArray(a); // new shuffle array
}
I essentially want a method that takes in my declared array and then copies the elements into a new array and then doubles the size with the remaining elements as 0. How can I make this possible? I am confused on the doubling of the array, I realize I can equal the array to the previous array to copy the elements.
class Untitled
{
public static void main(String[] args)
{
int[] a = {6, 3, 5, 2};
}
public static int[] doubleSize(int[] j)
{
int[] new = int [] j + int[] j
return int[] j;
}
}
Java automatically initialized the elements in an integer array as 0, so you don't have to do that manually.
public static int[] doubleSize(int[] j)
{
int[] newArray = new int[j.length * 2]
for (int i = 0; i < j.length; i++) {
newArray[i] = j[i];
}
return newArray;
}
Edit: A more Java-esque solution is
public static int[] doubleSize(int[] j)
{
return Arrays.copyOf(j, 2 * j.length);
}
This is pretty simple. To create a new array with twice the length you can do:
int[] newArray = new int[j.length * 2];
Since the array is type int, each element will be initialized to 0.
So once you copy the elements from the old array you should be done.
Also, you will want to change your return statement to just
return newArray;
Hi you achieve required functionality in this way.
public class DoubleArray
{
public static void main( String[] args )
{
int a[]={2,3,4,5};
int b[]=new int[2*a.length];
b =Arrays.copyOf(a, b.length);
System.out.println("DoubleArray.main()"+b);
for(int i=0;i<b.length;i++)
{
System.out.println(b[i]);
}
}
}
I'm writing a module to handle dice rolling. Given x die of y sides, I'm trying to come up with a list of all potential roll combinations.
This code assumes 3 die, each with 3 sides labeled 1, 2, and 3. (I realize I'm using "magic numbers" but this is just an attempt to simplify and get the base code working.)
int[] set = { 1, 1, 1 };
list = diceroll.recurse(0,0, list, set);
...
public ArrayList<Integer> recurse(int index, int i, ArrayList<Integer> list, int[] set){
if(index < 3){
// System.out.print("\n(looping on "+index+")\n");
for(int k=1;k<=3;k++){
// System.out.print("setting i"+index+" to "+k+" ");
set[index] = k;
dump(set);
recurse(index+1, i, list, set);
}
}
return list;
}
(dump() is a simple method to just display the contents of list[]. The variable i is not used at the moment.)
What I'm attempting to do is increment a list[index] by one, stepping through the entire length of the list and incrementing as I go.
This is my "best attempt" code. Here is the output:
Bold output is what I'm looking for. I can't figure out how to get rid of the rest. (This is assuming three dice, each with 3 sides. Using recursion so I can scale it up to any x dice with y sides.)
[1][1][1] [1][1][1]
[1][1][1] [1][1][2] [1][1][3] [1][2][3]
[1][2][1] [1][2][2] [1][2][3] [1][3][3]
[1][3][1] [1][3][2] [1][3][3] [2][3][3] [2][1][3]
[2][1][1] [2][1][2] [2][1][3] [2][2][3]
[2][2][1] [2][2][2] [2][2][3] [2][3][3]
[2][3][1] [2][3][2] [2][3][3] [3][3][3] [3][1][3]
[3][1][1] [3][1][2] [3][1][3] [3][2][3]
[3][2][1] [3][2][2] [3][2][3] [3][3][3]
[3][3][1] [3][3][2] [3][3][3]
I apologize for the formatting, best I could come up with.
Any help would be greatly appreciated. (This method was actually stemmed to use the data for something quite trivial, but has turned into a personal challenge. :)
edit: If there is another approach to solving this problem I'd be all ears, but I'd also like to solve my current problem and successfully use recursion for something useful.
edit2:
Running code including the "easy fix." Beware unused variables and weird hacks, I haven't cleaned it up yet.
package code.testing;
import java.util.ArrayList;
public class CodeTesting {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
int[] set = { 1, 1, 1 };
list = recurse(0,0, list, set);
}
public static ArrayList<Integer> recurse(int index, int i, ArrayList<Integer> list, int[] set){
if(index < 3){
// System.out.print("\n(looping on "+index+")\n");
for(int k=1;k<=3;k++){
// System.out.print("setting i"+index+" to "+k+" ");
set[index] = k;
if (index==2){
dump(set);
}
recurse(index+1, i, list, set);
}
}
return list;
}
static void dump(int[] arr) {
for (int s : arr) {
System.out.format("[%s]", s);
}
System.out.println();
}
}
I'm sorry I had to rewrite the code, but it's pretty much the same algorithm as yours with some corrections:
public class DiceRolls {
static void recurse(int diceNumber, int[] values, final int MAX) {
if (diceNumber == values.length) {
System.out.println(java.util.Arrays.toString(values));
} else {
for (int v = 1; v <= MAX; v++) {
values[diceNumber] = v;
recurse(diceNumber + 1, values, MAX);
}
}
}
public static void main(String[] args) {
recurse(0, new int[3], 4);
}
}
This is a standard tuplet recursive generator. If you want to add all the int[] into a List, then make sure to add(values.clone()) so they are independent int[] objects.
But what's with the extra output?
The problem is that you were dumping prematurely, before you're done throwing all the dices. In pseudocode, this is what you're doing:
if we're not done yet
trying all possibilities for this dice
dump result so far // premature dumping!
recurse for next dice
An easy fix to your code is to do the following:
if we're not done yet
trying all possibilities for this dice
recurse for next dice
else, we're done, so
dump result // timely!
So back to the Java implementation, the fix is merely moving dump(set); to an else case for the if (index < 3) statement.
Call dump() only when index == 2.
Incidentally, i and list seem unused. And the verb is "recur". :)
Here is a non-recursive alternative. Change the two constants to calculate all combinations for different dices and different numbers of dice.
package utils;
public class Dice {
private static int FACES = 3;
private static int NUMBER_OF_DICE = 3;
public static void main(String[] args) {
int start = createPair(1);
int end = createPair(FACES);
for (int i = start; i <= end; i++) {
String combination = Integer.toString(i, FACES+1);
if (combination.indexOf('0') < 0)
System.out.println(combination);
}
}
private static int createPair(int number) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < NUMBER_OF_DICE; i++) {
sb.append(number);
}
return Integer.parseInt(sb.toString(), FACES+1);
}
}