Iterate through array, sum and put results in new array - java

I have an arrayList filled with integers and I need to iterate through this arrayList, add the numbers up until a threshold is reached, then put the resulting sum into a second arrayList slot, and move back to where I left off in the original arrayList, keep iterating and summing until the threshold is reached and then put that in the second slot, and so on until all 40 original items have been summed and put into a smaller arrayList.
I've thought of using two nested loops but I can't get the two loops to work together.
I'm very new to Java and don't know how to do this. Any suggestions will be helpful.
This is what I have so far:
int threshold = 12;
int sumNum = 0;
int j = 0;
int arr1[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
for (int i = 0; i < arr1.length; i++) {
while (sumNum <= threshold) {
sumNum += arr[j];
j++
}//end while
}//end for

You can actually do this with just one loop. You don't need to move back, just stay where you are and keep going on the sum.
public static ArrayList<Integer> sums(ArrayList<Integer> arr, int threshold){
ArrayList<Integer> sumArr = new ArrayList<Integer>();
int s = 0; //Sum thus far, for the current sum
for(int i : arr){
s += i; //Add this element to the current sum
if(s >= threshold){ //If the current sum has reached/exceeded the threshold
sumArr.add(s); //Add it to the sumArray, reset the sum to 0.
s = 0;
}
}
return sumArr;
}
You can change the input param from ArrayList to int[] or Integer[] without any trouble whatsoever. Hooray for for-each loops!
Code to use the above:
public static void main(String[] args){
ArrayList<Integer> i = new ArrayList<Integer>();
//create arraylist 1..20
for(int x = 1; x <= 20; x++){
i.add(x);
}
System.out.println(sums(i).toString());
}

package com.test;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
int threshold = 12;
int sumNum = 0;
int j = 0;
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
List myList = new ArrayList();
for (int i = 0 ; i < arr1.length ; i++) {
sumNum += i;
if (sumNum >= threshold) {
myList.add(sumNum);
sumNum = 0;
}
}
for (int a = 0 ; a < myList.size() ; a++) {
System.out.println(myList.get(a));
}
}
}
output
15
13
17
21
12
13
14

How about something like this:
/**
* Sequentially adds numbers found in the source array until the sum >= threshold.
* <p/>
* Stores each threshold sum in a separate array to be returned to the caller
* <p/>
* Note that if the last sequence of numbers to be summed does not meet the threshold,
* no threshold sum will be added to the result array
*
* #param numbersToSum The source number list
* #param threshold The threshold value that determines when to move on to
* the next sequence of numbers to sum
*
* #return An array of the calculated threshold sums
*/
public static Integer[] sumWithThreshold(int[] numbersToSum, int threshold)
{
List<Integer> thresholdSums = new ArrayList<Integer>();
if (numbersToSum != null)
{
int workingSum = 0;
for (int number: numbersToSum)
{
workingSum = workingSum + number;
if (workingSum >= threshold)
{
thresholdSums.add(workingSum);
workingSum = 0;
}
}
}
return thresholdSums.toArray(new Integer[thresholdSums.size()]);
}
public static void main(String[] args)
{
int[] testNumbers =
{
1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40};
int[] thresholds = {1, 42, 100, 200};
for (int threshold: thresholds)
{
System.out.println("Threshold sums for threshold = " + threshold + ":\n" + Arrays.toString(sumWithThreshold(testNumbers, threshold)));
}
}
That produces the following output:
Threshold sums for threshold = 1:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
Threshold sums for threshold = 42:
[45, 46, 45, 54, 63, 47, 51, 55, 59, 63, 67, 71, 75, 79]
Threshold sums for threshold = 100:
[105, 105, 115, 110, 126, 105, 114]
Threshold sums for threshold = 200:
[210, 225, 231]

Related

How can I reorder my array based off the first value?

I'm working on a problem that says "Write a function called splay that reorganizes a list based on the first value. The first value is called the splaymaster. This function will rearrange the list such that all of the values before the splaymaster are less than or equal to the splaymaster and all of the values after it are greater than the splaymaster. The function also returns the index where the splaymaster is located after the list is rearranged. For example, if the list is [8, 15, 4, 48, 26, 45, 18, 29, 2, 1], the function will rearrange it to become [2, 1, 4, 8, 26, 45, 18, 29, 48, 15] and return the value 3. You may not sort the list." The problem that I seem to be having is for the example above it complains that the index is out of bounds which is my first problem. The next is if I use another array such as {90, 8, 15, 4, 48, 26, 45, 18, 29, 2, 1} I get {1, 90, 8, 15, 4, 48, 26, 45, 18, 29, 2} this is my output when it's not correct. What am I doing wrong? and How do I fix it?
public static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static int splay(int[] x) {
int left = 1;
int right = x.length;
int splaymaster = x[0];
while (left < right) {
if (x[left] <= splaymaster) {
left++;
} else {
swap(x, left, right);
}
swap(x, 0, left - 1);
}
return splaymaster;
}
}
int right = x.length;
The index of the last element in an array is x.length - 1, hence the index is out of bounds. Nonetheless, your algorithm seems incorrect. Merely swapping the elements at different locations is not sufficient. If an element is less than the splaymaster then you need to move all the elements up one and insert the smaller element into the array before the splaymaster. I assume there may be other conditions regarding the way to solve the problem but if there are then they are not clear to me from your question, for example it appears that the order of the elements is not important just as long as all elements before the splaymaster are less than or equal to it. I also assume you need to change the array in place, i.e. you are not allowed to use a second array.
Consider the following code:
import java.util.Arrays;
public class SplayTst {
public static int splay(int x[]) {
int index = 0;
int splaymaster = x[0];
for (int i = 1; i < x.length; i++) {
if (x[i] <= splaymaster) {
int temp = x[i];
for (int j = i; --j >= 0;) {
x[j + 1] = x[j];
}
x[0] = temp;
index++;
}
}
return index;
}
public static void main(String[] args) {
int[] test = new int[]{8, 15, 4, 48, 26, 45, 18, 29, 2, 1};
int ndx = splay(test);
System.out.println(Arrays.toString(test));
System.out.println(ndx);
test = new int[]{90, 8, 15, 4, 48, 26, 45, 18, 29, 2, 1};
ndx = splay(test);
System.out.println(Arrays.toString(test));
System.out.println(ndx);
}
}
Running the above code produces the following output:
[1, 2, 4, 8, 15, 48, 26, 45, 18, 29]
3
[1, 2, 29, 18, 45, 26, 48, 4, 15, 8, 90]
10
Alternatively, assuming that you can use any method to solve the problem, consider the following which uses ArrayList and then converts it to an array and then all the array elements are copied to the original array. Note that the single code line for converting ArrayList<Integer> to int[] is taken from the following question:
How to convert an ArrayList containing Integers to primitive int array?
I refer to this line of the below code:
int[] arr = list.stream().mapToInt(i -> i).toArray();
I iterate through the original array. If an element is greater than the splaymaster then it is appended to the ArrayList, otherwise it is inserted as the first element in the ArrayList.
import java.util.ArrayList;
import java.util.Arrays;
public class SplayTst {
public static int splay(int[] x) {
ArrayList<Integer> list = new ArrayList<>();
list.add(x[0]);
int index = 0;
for (int i = 1; i < x.length; i++) {
if (x[i] <= x[0]) {
list.add(0, x[i]);
index++;
}
else {
list.add(x[i]);
}
}
int[] arr = list.stream().mapToInt(i -> i).toArray();
for (int i = 0; i < x.length; i++) {
x[i] = arr[i];
}
return index;
}
public static void main(String[] args) {
int[] test = new int[]{8, 15, 4, 48, 26, 45, 18, 29, 2, 1};
int ndx = splay(test);
System.out.println(Arrays.toString(test));
System.out.println(ndx);
test = new int[]{90, 8, 15, 4, 48, 26, 45, 18, 29, 2, 1};
ndx = splay(test);
System.out.println(Arrays.toString(test));
System.out.println(ndx);
}
}

code for generating none repeating random numbers. Looks fine to me but when i run it gives me the same number

import java.util.Random;
public class Practice_assignment {
public static void main(String[] args){
int[] winning_numbers = {0,0,0,0,0,0,0,0,0,0} ;
//The i++ for the first loop is in the second loop. I was trying to ensure it only goes to
the next value of the loop once a unique value has been gotten.
for (int i=0; i<10;){
int max = 99;
int min = 1;
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
for (int j=0;j<=i;j++){
if (j<i && winning_numbers[j]==randomNum){
break;
}
else if (j==i && i<10){
winning_numbers[i] = randomNum;
System.out.println(winning_numbers[i]+" ");
i++;
}
}
}
}
}
If I understood correctly what you are trying to achieve, I think you could use something like this:
public class RandomNumbers {
public static void main(String[] args) {
int[] winning_numbers = {0,0,0,0,0,0,0,0,0,0} ;
Random random = new Random();
for(int i = 0; i < winning_numbers.length; i++) {
OptionalInt generatedInt = random.ints(1, 0, 100).findFirst(); // generates a stream of 1 number between 0 and 99 and gets the first (and only) one generated
while (contains(winning_numbers, generatedInt)) {
generatedInt = random.ints(1, 0, 100).findFirst(); // while the generated number is already in the array, generate a new one
}
winning_numbers[i] = generatedInt.getAsInt();
}
System.out.println(Arrays.toString(winning_numbers));
}
// this method will check if the given array already contains the generated int
private static boolean contains(int[] arr, OptionalInt generatedInt) {
return Arrays.stream(arr).anyMatch(number -> generatedInt.getAsInt() == number);
}
}
I ran it a couple of times and here are some outputs I generated with this code:
[52, 54, 21, 62, 47, 13, 94, 36, 82, 25]
[35, 37, 16, 81, 22, 71, 17, 94, 56, 8]
[51, 50, 80, 62, 18, 88, 1, 53, 44, 79]
[16, 95, 18, 66, 31, 4, 1, 55, 52, 26]
[4, 11, 65, 68, 22, 76, 95, 67, 35, 92]
[49, 87, 34, 88, 71, 57, 12, 76, 70, 78]
It appears you want to generate an array of winning_numbers. Here is one ways to do it.
create a helper method to look for duplicate numbers and return true if a duplicate is found.
then iterate over the array checking for the current random number and adding it if unique.
note that min, max, and rand should be initialized outside the loop.
Random rand = new Random();
int[] winning_nummbers = new int[10];
int max = 99;
int min = 1;
for (int i = 0; i < 10;) {
int randomNum = rand.nextInt((max - min) + 1) + min;
// if does not contain a duplicate, then assign
if (!contains(winning_numbers, randomNum)) {
winning_numbers[i++] = randomNum;
}
}
System.out.println(Arrays.toString(winning_numbers));
Prints something like this.
[46, 91, 5, 2, 42, 58, 74, 24, 53, 36]
The helper method.
public static boolean contains(int[] array, int v) {
for (int i = 0; i < array.length; i++) {
if (array[i] == v) {
return true;
}
}
return false;
}
If you want to use streams you can do it like so using a Random instance.
stream values form min to max inclusive.
drop duplicates with distinct
limit(10) limits to 10 values.
put them in an array
int[] winning_numbers = rand.ints(min,max+1)
.distinct()
.limit(10)
.toArray();

Unable to think of a way to shift array

I am stuck and can't think of a way to properly shift an array by __ units. I am trying to create an array of 30 items (numbers 1-30) which can then be shifted to the right by the number the user inputs. This would mean that the first few numbers in the array would take the index's at the end of the array, and the rest of the numbers would be shifted to the left. (Ex, if shift = 3, numbers 1,2,3 would take the index of 27,28,29, and the rest of the numbers 4-30 would shift left making index 0 =4, index 1=5, index 2=6....
import java.util.*;
class Main {
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
System.out.println("\nEnter the shift/rotation:");
int shiftNum = input.nextInt();
int [] numArray = new int [30];
for(int i = 0; i < 30; i++){
numArray [i] = i+1;
System.out.print(numArray[i]+" ");
}
}
}
This is the code I have so far, any suggestions to how I can do this? I have tried to make a separate for loop like
numArray [i-shiftNum] = numArray[i];
But when doing this, the index of 0-shiftNum would be negative and would not work. This is the context of the problem:
Create a program that will create an array of 30 items. Then it will rotate the array by a number selected by the user.
In order to shift the numbers in the array, the following for loop works for shifting the values within the array.
// prerequisite: array is already filled with values
for(int i = 0; i < numArray.length; i++) {
arr[i] += shiftNum;
if (numArray[i] > 30) {
numArray[i] -= 30;
} else if (numArray[i] <= 0) {
numArray[i] += 30;
}
}
According to you code, the array created will contain value from 1 - 30 including 1 and 30. If you want your code to contain values from 0 - 29 instead, change numArray[i] > 30 to numArray[i] >= 30 and change numArray[i] <= 0 to numArray[i] < 0.
Use Java's convenience methods. Most people still want to write for loops. Basically, you need to save off the elements you are overwriting with the shift. Then place those saved ones back in the array. System.arraycopy is nice in that it takes care of some nasty parts of moving elements in an array.
void shift(int shiftBy, int... array) {
int[] holdInts = Arrays.copyOf(array, shiftBy);
System.arraycopy(array, shiftBy, array, 0, array.length - shiftBy);
System.arraycopy(holdInts, 0, array, array.length - shiftBy, holdInts.length);
}
Here is quick fix for you. Please check following code.
Input :
Enter the shift/rotation: 4
Output :
Rotate given array [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
After Rotate [27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
public static void main(String[] args) {
RotationDemo rd = new RotationDemo();
int[] input = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
int k = 0;
Scanner scan = new Scanner (System.in);
try{
System.out.println("\nEnter the shift/rotation:");
int shiftNum = scan.nextInt();
if(shiftNum < 30) {
k = shiftNum;
System.out.println("Rotate given array " + Arrays.toString(input));
int[] rotatedArray = rd.rotateRight(input, input.length, k);
System.out.println("After Rotate " +
Arrays.toString(rotatedArray));
} else {
System.out.println("Shift number should be less than 30");
}
} catch(Exception ex){
} finally {
scan.close();
}
}
public int[] rotateRight(int[] input, int length, int numOfRotations) {
for (int i = 0; i < numOfRotations; i++) {
int temp = input[length - 1];
for (int j = length - 1; j > 0; j--) {
input[j] = input[j - 1];
}
input[0] = temp;
}
return input;
}
Hope this example works.

Selection Sort in Java produces incorrect results

I am new to Java and I am trying to write a selection sort program.
Below is my code :
public class SelectionSort {
public static int a[] = {6, 4, 9, 3, 1, 7};
public static void main(String[] args) {
int min, i, j;
for(i = 0; i < a.length - 1; i++) {
min = i ;
for(j = i + 1; j < a.length; j++) {
if (a[j] < a[min]) {
min = j;
}
if (min != i) {
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
}
for (i = 0; i < a.length; i++) {
System.out.println("a : " + a[i]);
}
}
}
My input array is 6,4,9,3,1,7. The sorted output should be 1,3,4,6,7,9
But the output I am getting is:
a : 3
a : 4
a : 6
a : 7
a : 1
a : 9
I am doing some small mistake which I am unable to figure out. Can anyone please help me fix it?
You are almost there.
The part that swaps elements should be outside the inner loop.
In other words, you need to first find the smallest element in the remainder of the array, and then swap it into the current position. Right now you're swapping as soon as you have found a smaller number, and in the process failing to keep track of the new position of this smaller number.
Another way to fix the code is to keep the swap where it is, but update min after each swap:
if (min !=i) {
int temp = a[i];
a[i] = a[min];
a[min]= temp;
min = i; /* Update `min' to reflect the number's new position */
}
This too will work, but is rather inefficient.
P.S. The if (min != i) check is unnecessary since swapping an element with itself is a harmless no-op.
You are swapping the elements for each iteration of inner loop Put the below block outside the inner loop. You should swap only for each iteration of outer loop.
if (min !=i) {
int temp = a[i];
a[i] = a[min];
a[min]= temp;
}
Why cant you go with comparator in collection. As you are new to java, you can learn the feature provided by java too. Check the below example for that.
import java.util.Comparator;
public class MyIntComparator implements Comparator<Integer>{
#Override
public int compare(Integer o1, Integer o2) {
return (o1>o2 ? -1 : (o1==o2 ? 0 : 1));
}
}
--------------------------------------------------------
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Simple2 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(4);
list.add(3);
list.add(7);
list.add(2);
list.add(1);
Collections.sort(list, new MyIntComparable());
for (Integer integer : list) {
System.out.println(integer);
}
}
}
Simple logic to approach any algo is to break into multiple step :
### Step 1 − Set MIN to location 0 or any high Value
### Step 2 − Search the minimum element in the list
### Step 3 − Swap with value at index of minimum
### Step 4 − Repeat until iteration gets over
e.g. <br>
14, 33, 27, 10, 35, 19, 42, 44 <br>
**10**, 33, 27, **14**, 35, 19, 42, 44 <br>
10, **14**, 27, **33**, 35, 19, 42, 44 <br>
10, 14, **19**, 33, 35, **27**, 42, 44 <br>
10, 14, 19, **27**, 35, **33**, 42, 44 <br>
10, 14, 19, 27, **33**, **35**, 42, 44 <br>
10, 14, 19, 27, 33, 35, **42**, 44 skip as no min found
final int[] intArr = new int[]{14, 33, 27, 10, 35, 19, 42, 44};
int index = -1;
boolean isMin;
for (int i = 0; i < intArr.length; i++) {
int min = 999999999;
isMin = false;
for (int j = i + 1; j < intArr.length; j++) {
if (intArr[j] < min && intArr[i] >= intArr[j]) {
min = intArr[j];
index = j;
isMin = true;
}
}
if (isMin) {
intArr[index] = intArr[i];
intArr[i] = min;
}
}
Arrays.stream(intArr).forEach(System.out::println);

Finding mode and frequency of mode without sorting in Java

I'm new to Java, and was given a question to solve as a weekend project. I ran into some troubles, and would like your help. Please understand I am a beginner. If I'm wrong somewhere, please explain it to me. I hope to be a good programmer too some day.
I did a through search, and found answers with things like "heatmaps" or "arraylists", something I probably won't be allowed to use since I haven't learned it yet.
Ok, so the question given to me was:
Find: 1) Mode, the most frequently occurring marks in the class. If 2 or more marks occur equally frequently, then the highest of these marks is the mode.
2) Mode Frequency: Frequency of mode.
It is assumed that the class has 10 students and marks are between 0 to 100.You are not allowed to sort the marks.
This is my code for finding the mode:
void mode()
{
int c[]=new int[10];
int arr[]=new int[10];
for (int i=0;i<10;i++)
{
for (int j=i+1;j<10;j++)
{
for (int k=0;k<10;k++)
{
if (marks[i]!=arr[k])
{
if (marks[i]==marks[j])
{
c[i]++;
break;
}
}
}
arr[i]=marks[i];
}
}
for (int k=0;k<10;k++)
{
System.out.println();
System.out.println(c[k]);
}
}
Where marks[] is the int array where I take the input, c[] is to count the number of times the number is occurring, and arr[] is an array to cross check if the number has previously occurred or not.
Let's assume the 10 numbers inputted are 99, 95, 97, 92, 80, 95, 73, 80, 95, 80. As you can see 95 and 80 occur three times.
So my c[] should have {0, 2, 0, 0, 2, 0, 0, 0, 0, 0}, but when I run it, it comes as {0, 2, 0, 0, 2, 1, 0, 1, 0, 0}, which means my program isn't cross checking with arr[].
I think I've made a mess using three for-loops. I can't seem to figure out how to solve it.
One solution would be to have an array of length 101 initialized to zero. This array would represent the number of times a specific mark had occurred. each time you encounter a specific mark you increment the count. Then to find the mode, you simple find the index with the highest count.
public class Loader
{
// We suppose that the parameter is not null
public static void mode_frequency(long collection[])
{
long frequencies[] = new long[collection.length];
for (int i = 0, l = collection.length; i < l; i++)
{
for (int j = i; j < l; j++)
{
if (collection[i] == collection[j])
{
++frequencies[i];
}
}
}
// With your example {99, 95, 97, 92, 80, 95, 73, 80, 95, 80}
// You should have somthing like {1, 3, 1, 1, 3, 2, 1, 2, 1, 1}
//
// As you can see, you just have to find the MAX frequency and then, print corresponding values from initial array
long frequency = 0;
for (int i = 0, l = frequencies.length; i < l; i++)
{
if (frequency < frequencies[i])
{
frequency = frequencies[i];
}
}
// Print each mode
for (int i = 0, l = collection.length; i < l; i++)
{
if (frequencies[i] == frequency)
{
System.out.println(collection[i]);
}
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
mode_frequency(new long[]
{
99,
95,
97,
92,
80,
95,
73,
80,
95,
80
});
}
}
You may want to use an algorithm in which you use secondary arrays to accumulate the counts for individual marks, and then search through those secondary arrays for the mark with the highest frequency with largest value. Consider:
package com.example.mode;
public class Mode {
public static void main(String[] args) {
int[] marks = { 99, 95, 97, 92, 80, 95, 73, 80, 95, 80};
//One algorithm .. insert marks and add occurances, keeping in order
int[] unique = new int[marks.length];
int[] count = new int[marks.length];
int maxUnique = 0;
for (int i=0; i < marks.length ; i++) {
int loc = -1;
for (int j=0; j < maxUnique; j++) {
if (marks[i] == unique[j]) {
loc = j;
break;
}
}
if (loc == -1) {
loc = maxUnique;
unique[loc] = marks[i];
count[loc] = 0;
maxUnique++;
}
count[loc] = count[loc]+1;
}
int maxValue = unique[0];
int maxCount = count[0];
for (int j=1; j < maxUnique; j++) {
if (count[j] > maxCount || (count[j] == maxCount && maxValue < unique[j]) ) {
maxValue = unique[j];
maxCount = count[j];
}
}
System.out.println("Mode = " + maxValue + ", frequency = " + maxCount);
}
}

Categories