Print sum of unique values of an integer array in Java - java

I am yet again stuck at the answer. This program prints the unique values but I am unable to get the sum of those unique values right. Any help is appreciated
public static void main(String args[]){
int sum = 0;
Integer[] numbers = {1,2,23,43,23,56,7,9,11,12,12,67,54,23,56,54,43,2,1,19};
Set<Integer> setUniqueNumbers = new LinkedHashSet<Integer>();
for (int x : numbers) {
setUniqueNumbers.add(x);
}
for (Integer x : setUniqueNumbers) {
System.out.println(x);
for (int i=0; i<=x; i++){
sum += i;
}
}
System.out.println(sum);
}

This is a great example for making use of the Java 8 language additions:
int sum = Arrays.stream(numbers).distinct().collect(Collectors.summingInt(Integer::intValue));
This line would replace everything in your code starting at the Set declaration until the last line before the System.out.println.

There's no need for this loop
for (int i=0; i<=x; i++){
sum += i;
}
Because you're adding i rather than the actual integers in the set. What's happening here is that you're adding all the numbers from 0 to x to sum. So for 23, you're not increasing sum by 23, instead, you're adding 1+2+3+4+5+....+23 to sum. All you need to do is add x, so the above loop can be omitted and replaced with a simple line of adding x to sum,
sum += x;

This kind of error always occures if one pokes around in low level loops etc.
Best is, to get rid of low level code and use Java 8 APIs:
Integer[] numbers = {1,2,23,43,23,56,7,9,11,12,12,67,54,23,56,54,43,2,1,19};
int sum = Arrays.stream(numbers)
.distinct()
.mapToInt(Integer::intValue)
.sum();
In this way there is barely any space for mistakes.
If you have an int array, the code is even shorter:
int[] intnumbers = {1,2,23,43,23,56,7,9,11,12,12,67,54,23,56,54,43,2,1,19};
int sumofints = Arrays.stream(intnumbers)
.distinct()
.sum();

So this is my first time commenting anywhere and I just really wanted to share my way of printing out only the unique values in an array without the need of any utilities.
//The following program seeks to process an array to remove all duplicate integers.
//The method prints the array before and after removing any duplicates
public class NoDups
{
//we use a void static void method as I wanted to print out the array without any duplicates. Doing it like this negates the need for any additional code after calling the method
static void printNoDups(int array[])
{ //Below prints out the array before any processing takes place
System.out.println("The array before any processing took place is: ");
System.out.print("{");
for (int i = 0; i < array.length; i++)
{
System.out.print(array[i]);
if (i != array.length - 1)
System.out.print(", ");
}
System.out.print("}");
System.out.println("");
//the if and if else statements below checks if the array contains more than 1 value as there can be no duplicates if this is the case
if (array.length==0)
System.out.println("That array has a length of 0.");
else if (array.length==1)
System.out.println("That array only has one value: " + array[0]);
else //This is where the fun begins
{
System.out.println("Processed Array is: ");
System.out.print( "{" + array[0]);//we print out the first value as it will always be printed (no duplicates has occured before it)
for (int i = 1; i < array.length; i++) //This parent for loop increments once the all the checks below are run
{
int check = 0;//this variable tracks the amount of times an value has appeared
for(int h = 0; h < i; h++) //This loop checks the current value for array[i] against all values before it
{
if (array[i] == array[h])
{
++check; //if any values match during this loop, the check value increments
}
}
if (check != 1) //only duplicates can result in a check value other than 1
{
System.out.print(", " + array[i]);
}
}
}
System.out.print("}"); //formatting
System.out.println("");
}
public static void main(String[] args)
{ //I really wanted to be able to request an input from the user but so that they could just copy and paste the whole array in as an input.
//I'm sure this can be done by splitting the input on "," or " " and then using a for loop to add them to the array but I dont want to spend too much time on this as there are still many tasks to get through!
//Will come back and revisit to add this if I remember.
int inpArray[] = {20,100,10,80,70,1,0,-1,2,10,15,300,7,6,2,18,19,21,9,0}; //This is just a test array
printNoDups(inpArray);
}
}

the bug is on the line
sum += i;
it should be
sum += x;

Related

Java program to find the duplicate values of an array of integer using simple loop

public class ArrayTest{
public static void main(String[] args) {
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
for(int i= 0;i<array.length-1;i++){
for(int j=i+1;j<array.length;j++){
if((array[i])==(array[j]) && (i != j)){
System.out.println("element occuring twice are:" + array[j]);
}
}
}
}
}
this program work fine but when i compile it, it print the values again and again i want to print the duplicate value once for example if 9 is present 5 times in array so it print 9 once and if 5 is present 6 times or more it simply print 5...and so on....this what i want to be done. but this program not behave like that so what am i missing here.
your help would be highly appreciated.
regards!
Sort the array so you can get all the like values together.
public class ArrayTest{
public static void main(String[] args) {
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
Arrays.sort(array);
for (int a = 0; a < array.length-1; a++) {
boolean duplicate = false;
while (array[a+1] == array[a]) {
a++;
duplicate = true;
}
if (duplicate) System.out.println("Duplicate is " + array[a]);
}
}
}
The problem statement is not clear, but lets assume you can't sort (otherwise the problem greatly simplifies). Lets also assume the space complexity is constrained, and you can't keep a Map, etc, for counting the frequency.
You can use use lookbehind, but this unnecessarily increases the time complexity.
I think a reasonable approach is to reserve the value -1 to indicate that an array position has been processed. As you process the array, you update each active value with -1. For example, if the first element is 32, then you scan the array for any value 32, and replace with -1. The time complexity does not exceed O(n^2).
This leaves the awkcase case where -1 is an actual value. It would be required to do a O(n) scan for -1 prior to the main code.
If the array must be preserved, then clone it prior to processing. The O(n^2) loop is:
for (int i = 0; i < array.length - 1; i++) {
boolean multiple = false;
for (int j = i + 1; j < array.length && array[i] != -1; j++) {
if (array[i] == array[j]) {
multiple = true;
array[j] = -1;
}
}
if (multiple)
System.out.println("element occuring multiple times is:" + array[i]);
}
What you can do, is use a data structure that only contains unique values, Set. In this case we use a HashSet to store all the duplicates. Then you check if the Set contains your value at index i, if it does not then we loop through the array to try and find a duplicate. If the Set contains that number already, we know it's been found before and we skip the second for loop.
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
HashSet<Integer> duplicates = new HashSet<>();
for(int i= 0;i<array.length-1;i++)
{
if(!duplicates.contains(array[i]))
for(int j=i+1;j<array.length;j++)
{
if((array[i])==(array[j]) && (i != j)){
duplicates.add(array[i]);
break;
}
}
}
System.out.println(duplicates.toString());
Outputs
[3, 4, 5, 6, 7, 88, 8, 9]
I recommend using a Map to determine whether a value has been duplicated.
Values that have occurred more than once would be considered as duplicates.
P.S. For duplicates, using a set abstract data type would be ideal (HashSet would be the implementation of the ADT), since lookup times are O(1) since it uses a hashing algorithm to map values to array indexes. I am using a map here, since we already have a solution using a set. In essence, apart from the data structure used, the logic is almost identical.
For more information on the map data structure, click here.
Instead of writing nested loops, you can just write two for loops, resulting in a solution with linear time complexity.
public void printDuplicates(int[] array) {
Map<Integer, Integer> numberMap = new HashMap<>();
// Loop through array and mark occurring items
for (int i : array) {
// If key exists, it is a duplicate
if (numberMap.containsKey(i)) {
numberMap.put(i, numberMap.get(i) + 1);
} else {
numberMap.put(i, 1);
}
}
for (Integer key : numberMap.keySet()) {
// anything with more than one occurrence is a duplicate
if (numberMap.get(key) > 1) {
System.out.println(key + " is a reoccurring number that occurs " + numberMap.get(key) + " times");
}
}
}
Assuming that the code is added to ArrayTest class, you could all it like this.
public class ArrayTest {
public static void main(String[] args) {
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
ArrayTest test = new ArrayTest();
test.printDuplicates(array);
}
}
If you want to change the code above to look for numbers that reoccur exactly twice (not more than once), you can change the following code
if (numberMap.get(key) > 1) to if (numberMap.get(key) == 2)
Note: this solution takes O(n) memory, so if memory is an issue, Ian's solution above would be the right approach (using a nested loop).
// print duplicates
StringBuilder sb = new StringBuilder();
int[] arr = {1, 2, 3, 4, 5, 6, 7, 2, 3, 4};
int l = arr.length;
for (int i = 0; i < l; i++)
{
for (int j = i + 1; j < l; j++)
{
if (arr[i] == arr[j])
{
sb.append(arr[i] + " ");
}
}
}
System.out.println(sb);
Sort the array. Look at the one ahead to see if it is duplicate. Also look at one behind to see if this was already counted as duplicate (except when i == 0, do not look back).
import java.util.Arrays;
public class ArrayTest{
public static void main(String[] args) {
int array[] = {32,32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
Arrays.sort(array);
for(int i= 0;i<array.length-1;i++){
if((array[i])==(array[i+1]) && (i == 0 || (array[i]) != (array[i-1]))){
System.out.println("element occuring twice are:" + array[i]);
}
}
}
}
prints:
element occuring twice are:3
element occuring twice are:4
element occuring twice are:5
element occuring twice are:6
element occuring twice are:7
element occuring twice are:8
element occuring twice are:9
element occuring twice are:32
element occuring twice are:88

How to sort number when entering vector in java

I want to add numbers in sorted way before entering vector. But the result is not right and I am confused where the problem is ? Output is shown below.
I want to sort using some algorithm without any inbuilt methods.
import java.util.Vector;
public class Test {
public static void main(String ar[]){
//Numbers to enter in vector
int[] number = {5,2,98,3,10,1};
Vector<Integer> v = new Vector<Integer>();
v.add(number[0]);
for(int i=1;i<number.length;i++){
for(int j=v.size();j>0;j--){
System.out.println("Entered: "+number[i]);
if(number[i] <= v.get(j-1)){
v.add(j-1,number[i]);
break;
}else{
v.add(j,number[i]);
break;
}
}
}
for(int s:v)
System.out.print(s + " ");
}
}
OUTPUT:
Entered: 2
Entered: 98
Entered: 3
Entered: 10
Entered: 1
2 5 3 10 1 98
You have a second (inner) for loop based on the variable j, but that "loop" will only execute exactly one time. Both conditions inside the j loop cause the loop to exit (break;).
When you're adding each number, the only possibilities are last or next to last.
Your inner for loop doesn't actually loop.
Regardless of the condition number[i] <= v.get(j-1),
the loop will exit after one step.
What you want to do is,
iterate from the beginning of the vector,
and when you find an element that's bigger than the one you want to insert,
then insert it, and break out of the loop.
This is opposite of what you did so far, which is iterating from the end of the vector.
If the end of the loop is reached without inserting anything,
then append the value.
The program badly needs some other improvements too:
If you don't need the vector to be thread-safe, then you don't need Vector. Use ArrayList instead.
The special treatment for the first number is unnecessary.
The outer loop can be written in a more natural way using the for-each idiom.
No need to loop to print the elements, the toString implementation of Vector is already easy to read.
The variable names are very poor and can be easily improved.
The indentation is inconsistent, making the code very hard to read.
With the problem fixed and the suggestions applied:
List<Integer> list = new ArrayList<>();
for (int current : numbers) {
boolean inserted = false;
for (int j = 0; j < list.size(); j++) {
if (current <= list.get(j)) {
list.add(j, current);
inserted = true;
break;
}
}
if (!inserted) {
list.add(current);
}
}
System.out.println(list);
Last but not least, instead of searching for the insertion point by iterating over the list,
you could achieve much better performance using binary search,
especially for larger sets of values.
Another simple solution would be:
import java.util.Vector;
public class Test {
public static void main(String ar[]){
//Numbers to enter in vector
int[] number = {5,2,98,3,10,1};
Vector<Integer> v = new Vector<Integer>();
v.add(number[0]);
for(int i=1, j;i<number.length;i++){ //j declared here for better scope
for(j=v.size();j>0 && v.get(j-1)>number[i] ;j--); //<-- some changes here,
v.add(j,number[i]); //<-- and here
}
}
for(int s:v)
System.out.print(s + " ");
}
}
The inner for loop is simply used to find the right index for an element to be inserted.
Your inner loop seems to not looping more than one time. That's why the key is not being inserted into right place.
A more concise solution would be
public class Test {
public static void main(String ar[]){
//Numbers to enter in vector
int[] number = {5,2,98,3,10,1};
Vector<Integer> v = new Vector<Integer>();
v.setSize(number.length);
v[0] = number[0];
for(int i=1, vSize = 1; i < number.length; i++, vSize++){
int j = 0, k = 0;
for(j = 0; j < vSize; j++) {
if(v[j] < number[i]) {
break;
}
for(k = vSize; k > j; k--) {
v[k] = v[k -1];
}
v[k] = number[i];
}
for(int s:v)
System.out.print(s + " ");
}
}

How to calculate average from command line? Homework excercize

I have to make a program which calculates the average, the modal value and the median of some numbers insert on command line. The numbers have to be in a range [1,10] I can't understand why it stops. Where am I wrong? This is the code:
import java.lang.Integer;
import java.util.Arrays;
class Stat{
public static void main(String[] args){
int i,median,modalValue = 0;
float average, sum = 0;
int repetition[] = new int[args.length];
Integer allNumbers[] = new Integer[args.length];
//check numbers range
try{
//reading args from command line
for( i = 0; i < args.length; i++){
//if not in range --> exception
if(Integer.parseInt(args[i]) < 1 || Integer.parseInt(args[i]) > 10)
throw new Exception("Exception: insert number out of range. Restart the programm.");
//put numbers in an array
allNumbers[i] = new Integer(args[i]);
}
//sorting the array
Arrays.sort(allNumbers);
//calculate average
for( i = 0; i < allNumbers length; i++ ){
sum += allNumbers[i];
}
average = sum / (i + 1) ;
System.out.println("Average: " + average);
//calcolate modal value (most frequent number)
for( i = 0; i < repetition.length; i++){ //counting numbers occurrences
repetition[allNumbers[i]]++;
}
for( i = 1; i < repetition.length; i++){ //checking which number occurrences the most
if(repetition[i] >= repetition[i-1])
modalValue = repetition[i];
}
System.out.println("Modal Value: " + modalValue);
//calculating median value
if((allNumbers.length) % 2 == 0){ //even
median = allNumbers.length/2;,
}else{ //odd
median = (allNumbers.length/2) + 1;
}
System.out.println("Median: " + allNumbers[median]);
}catch(Exception e) { //out of range
System.out.println(e.getMessage());
}
}
}
First Step
You will get more information about errors if you remove that try/catch. By catching the exception and printing out just its message, you are missing out on its stack trace, which will tell you exactly which line the error occurs on.
So firstly, remove the try/catch, and allow your main method to throw exceptions by changing its declaration to: public static void main(String[] args) throws Exception {. Compile and run it again, to allow the exception to crash the program.
What type of exception is thrown? What line number does it say?
Second Step
Next, let's look at some of your code that helps calculate the modal value:
int repetition[] = new int[args.length];
for (i = 0; i < repetition.length; i++) {
repetition[allNumbers[i]]++;
}
The first line will create an array with the same number of elements as numbers provided on the command line. For example, if you provide numbers 5 8 9, that's three numbers, so the array will have three elements. Array indexes start at zero, so the indexes will be 0, 1 and 2.
The for loop will then take the first number, allNumbers[0] which in my example is a 5, and increment the value in the array at index 5. This causes an exception because the array does not have an index 5. That would be "outside the bounds" of the array.
The problem here is how you create the repetition array. Creating it with only three elements is not enough. You need to think about how to create it so that it will be able to handle any number in the range of [1, 10] that you were given.

Adding and finding the average in an array

I"m trying to make a program that retrieves an endless amount of numbers that user inputs, and then it tells you how many numbers that you inputted, the sum of all the numbers, and then the average of the numbers. Here is the code I have so far. I don't know why it does not work. I get no errors, but it just does not get a valid sum or average.
import javax.swing.*;
public class SumAverage {
public static float sum;
public static float averageCalculator;
public static float average;
public static void main(String[]args) {
float numbers[] = null;
String userInput = JOptionPane.showInputDialog(null, "Ready to begin?");
if(userInput.equalsIgnoreCase("no"))
{
System.exit(0);
}
for(int i = 0; i != -2; i++)
{
numbers = new float[i + 1];
userInput = JOptionPane.showInputDialog(null, "Input any number. Input * to exit");
if(userInput.length() == 0 || userInput.equals("*") || userInput.equals(null))
{
break;
}
else
{
numbers[i] = Float.parseFloat(userInput);
}
}
for (int i = 0; i < numbers.length; i++)
{
sum += numbers[i];
}
average = sum / numbers.length;
JOptionPane.showMessageDialog(null, "The sum of all your numbers is " + sum + ". The average is " + average + ". You entered a total of " + numbers.length + " numbers.");
}
}
The problem is in this line:
numbers = new float[i + 1];
You are creating a new array, but you aren't copying the values from the previous array assigned to numbers into it.
You can fix this in two ways:
copy the values using System.arraycopy() (you'll need to use a new variable to make the call then assign it to numbers)
Don't use arrays! Use a List<Float> instead, which automatically grows in size
In general, arrays are to be avoided, especially for "application logic". Try to always use collections - they have many powerful and convenient methods.
If you wanted to store the numbers for later use, try making your code look like this:
List<Float> numbers = new ArrayList<Float>();
...
numbers.add(Float.parseFloat(userInput));
...
for (float n : numbers) {
sum += n;
}
average = sum / numbers.size(); // Note: Don't even need a count variable
And finally, if you don't need to store the numbers, just keep a running sum and count and avoid any kind of number storage.
Unrelated to the Q, but note also you can compute a running count/average without storing all the input data - or assuming you want to keep the input - without traversing over it each iteration. Pseudocode:
count = 0
sum = 0
while value = getUserInput():
count++
sum += value
print "average:" + (sum / count)
with
numbers = new float[i + 1];
you are creating a whole new array on every iteration. That means you are always creating a new array that will increase its size by 1 on each iteration but only having one field filled with the current user input and having all the other fields been empty.
Delete this line and initialize the array before.
If the size of the array should grow dynamically within the loop
do not use an array at all and use a dynamic data structure like a List or an ArrayList instead.
Further i would suggest to use
while (true) {
//...
}
to realize an infinite loop.

Java Double Array

I'm having trouble setting up and placing values into an array using a text file containing the floating point numbers 2.1 and 4.3 each number is separated by a space - below is the error I'm getting:
Exception in thread "main" java.util.NoSuchElementException
import java.util.*;
import java.io.*;
public class DoubleArray {
public static void main(String[] args) throws FileNotFoundException {
Scanner in = new Scanner(new FileReader("mytestnumbers.txt"));
double [] nums = new double[2];
for (int counter=0; counter < 2; counter++) {
int index = 0;
index++;
nums[index] = in.nextDouble();
}
}
}
Thanks, I'm sure this isn't a hard question to answer... I appreciate your time.
You should always use hasNext*() method before calling next*() method
for (int counter=0; counter < 2; counter++) {
if(in.hasNextDouble(){
nums[1] = in.nextDouble();
}
}
but I think you are not doing the right, I'd rather
for (int counter=0; counter < 2; counter++) {
if(in.hasNextDouble(){
nums[counter] = in.nextDouble();
}
}
NoSuchElementException is thrown by nextDouble method #see javadoc
I would suggest printing the value of index out immediately before you use it; you should spot the problem pretty quickly.
It would appear you're not getting good values from your file.
Oli is also correct that you have a problem with your index, but I would try this to verify you're getting doubles from your file:
String s = in.next();
System.out.println("Got token '" + s + "'"); // is this a double??
double d = Double.parseDouble(s);
EDIT: I take this partly back...
You simply don't have tokens to get. Here's what next double would have given you for exceptions:
InputMismatchException - if the next token does not match the Float
regular expression, or is out of range
NoSuchElementException - if the input is exhausted
IllegalStateException - if this scanner is closed
I did not understand what you are trying to do in your loop ?
for (int counter=0; counter < 2; counter++) {
int index = 0;
index++; <--------
nums[index] = in.nextDouble();
}
You are declaring index = 0 then incrementing it to 1 and then using it.
Why are you not writing int index = 1; directly ?
Because it is getting declared to be zero each time loop is run and then changes value to 1.
Either you should declare it out side the loop.
You should initialize index outside of your for loop.
int index = 0;
for (int counter=0; counter < 2; counter++)
{
index++;
nums[index] = in.nextDouble();
}
Your index was getting set to zero at the beginning of each iteration of your for loop.
EDIT:
You also need to check to make sure you still have input.
int index = 0;
for (int counter=0; counter < 2; counter++)
{
if(!in.hasNextDouble())
break;
index++;
nums[index] = in.nextDouble();
}
Every time the cycle does an iteration, it's declaring the variable index and then you increase index with index++. Instead of using index, use counter, like this: num [counter] = in.nextDouble().
Check your mytestnumbers.txt file and ensure that the data that you are trying to scan is in the correct format. The exception that you are getting implies it is not.
Keep in mind that in.nextDouble() will be searching for double numbers separated by white space. In other words, "4.63.7" is not equal to "4.6 3.7" — the space is required. (I do not remember off the top of my head, but I believe that nextDouble() will only search for numbers containing a decimal point, so I do not believe that "4" is equal to "4.0". If you are seeking decimal numbers with this method, then you should have decimal numbers in your file.)

Categories

Resources