Manual list shuffling in Java produces same result each time - java

I am trying to create a method for shuffling a list manually. The list is shuffled, but the same result is produced every time. Code example below:
package ch11;
import java.util.ArrayList;
import java.util.Arrays;
public class Chapter_11_E07_ShuffleArrayList {
public static void main(String[] args) {
Integer[] array = {1, 2, 3, 4, 5, 6, 7, 8};
ArrayList<Integer> intList = new ArrayList<>(Arrays.asList(array));
System.out.println("Before shuffle: ");
for (Integer x: intList)
System.out.print(x + " ");
shuffle(intList);
System.out.println("\nAfter shuffle: ");
for (Integer x: intList)
System.out.print(x + " ");
}
public static void shuffle(ArrayList<Integer> intList) {
// Simple solution
// java.util.Collections.shuffle(intList);
// Manual shuffle
for (Integer x: intList) {
int newIndex = (int) Math.random() * intList.size();
Integer temp = intList.get(x);
intList.set(x, intList.get(newIndex));
intList.set(newIndex, temp);
}
}
}
It seems to work to some extent, but is Math.random * intList.size() producing the same random index every time? Inputs are highly appreciated!

This is because
int newIndex = (int) Math.random() * intList.size();
is not parenthesized properly. It should be
int newIndex = (int)(Math.random() * intList.size());
To avoid simple errors like this, make new Random object, and call nextInt(intList.size()).

To show what I've meant in the comments above, here the code:
for (Integer x: intList) {
int newIndex = (int) (Math.random() * intList.size());
int oldIndex = intList.indexOf(x);
Integer temp = intList.get(newIndex);
intList.set(newIndex, x);
intList.set(oldIndex, temp);
}

Related

Finding the mode from an user-input array if there are multiple modes or no mode

I'm working on a project that prompts the user to create and fill an array with integers, then displays the mean, mode, median, and standard deviation of that array. It starts by asking the user what the size of the array will be, to which the number entered will declare and initialize the array. The program will then iterate several times asking the user to declare an integer value, and each value will be stored into the array until the array is filled. The program will then print the contents of the array, as well as the mean, mode, median, and standard deviation.
I have a code that seems to meet all these requirements. However, one thing I am struggling on is the mode. While it does print out the most repeated number in the array, it doesn't take into account multiple modes with the same number of repetitions, nor does it take into account what will happen if there is no mode.
Right now, if two numbers are entered twice each, the mode displayed is the first number to be repeated more than once. For example, if I have an array size of 10 integers, and the integers I enter are 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, it will print out "2.0" for the mode instead of printing both "2.0" and "3.0." If there is no mode, it simply enters the number first entered, rather than saying "None."
What would be the best course of action to go about accomplishing this?
Here is my code:
import java.util.*;
public class ArrayStatistics {
public static void main(String[] args) {
double total = 0;
Scanner input = new Scanner(System.in);
System.out.print("Enter the size of your array >> ");
int size = input.nextInt();
double[] myArray = new double[size];
System.out.print("Enter the integer values >> ");
for (int i=0; i<size; i++) {
myArray[i] = input.nextInt();
}
System.out.println("\nIntegers:");
for (int i=0; i<size; i++) {
System.out.println(myArray[i]);
}
double mean = calculateMean(myArray);
System.out.println("\nMean: " + mean);
double mode = calculateMode(myArray);
System.out.println("Mode: " + mode);
double median = calculateMedian(myArray);
System.out.println("Median: " + median);
double SD = calculateSD(myArray);
System.out.format("Standard Deviation: %.6f", SD);
}
public static double calculateMean(double myArray[]) {
int sum = 0;
for(int i = 0; i<myArray.length; i++) {
sum = (int) (sum + myArray[i]);
}
double mean = ((double) sum) / (double)myArray.length;
return mean;
}
public static double calculateMode(double myArray[]) {
int modeCount = 0;
int mode = 0;
int currCount = 0;
for(double candidateMode : myArray) {
currCount = 0;
for(double element : myArray) {
if(candidateMode == element) {
currCount++;
}
}
if(currCount > modeCount) {
modeCount = currCount;
mode = (int) candidateMode;
}
}
return mode;
}
public static double calculateMedian(double myArray[]) {
Arrays.sort(myArray);
int val = myArray.length/2;
double median = ((myArray[val]+myArray[val-1])/2.0);
return median;
}
public static double calculateSD(double myArray[]) {
double sum = 0.0;
double standardDeviation = 0.0;
int length = myArray.length;
for(double num : myArray) {
sum += num;
}
double mean = sum/length;
for(double num : myArray) {
standardDeviation += Math.pow(num - mean, 2);
}
return Math.sqrt(standardDeviation/length);
}
First the code, then the explanations.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.stream.Collectors;
public class ArrayStatistics {
public static void main(String[] args) {
int total = 0;
Scanner input = new Scanner(System.in);
System.out.print("Enter the size of your array >> ");
int size = input.nextInt();
int[] myArray = new int[size];
Map<Integer, Integer> frequencies = new HashMap<>();
System.out.print("Enter the integer values >> ");
for (int i = 0; i < size; i++) {
myArray[i] = input.nextInt();
if (frequencies.containsKey(myArray[i])) {
int frequency = frequencies.get(myArray[i]);
frequencies.put(myArray[i], frequency + 1);
}
else {
frequencies.put(myArray[i], 1);
}
total += myArray[i];
}
System.out.println("\nIntegers:");
for (int i = 0; i < size; i++) {
System.out.println(myArray[i]);
}
double mean = calculateMean(size, total);
System.out.println("\nMean: " + mean);
List<Integer> mode = calculateMode(frequencies);
System.out.println("Mode: " + mode);
double median = calculateMedian(myArray);
System.out.println("Median: " + median);
double stdDev = calculateSD(mean, total, size, myArray);
System.out.format("Standard Deviation: %.6f", stdDev);
}
public static double calculateMean(int count, int total) {
double mean = ((double) total) / count;
return mean;
}
public static List<Integer> calculateMode(Map<Integer, Integer> frequencies) {
Map<Integer, Integer> sorted = frequencies.entrySet()
.stream()
.sorted((e1, e2) -> e2.getValue() - e1.getValue())
.collect(Collectors.toMap(e -> e.getKey(),
e -> e.getValue(),
(i1, i2) -> i1,
LinkedHashMap::new));
Iterator<Integer> iterator = sorted.keySet().iterator();
Integer first = iterator.next();
Integer val = sorted.get(first);
List<Integer> modes = new ArrayList<>();
if (val > 1) {
modes.add(first);
while (iterator.hasNext()) {
Integer next = iterator.next();
Integer nextVal = sorted.get(next);
if (nextVal.equals(val)) {
modes.add(next);
}
else {
break;
}
}
}
return modes;
}
public static double calculateMedian(int myArray[]) {
Arrays.sort(myArray);
int val = myArray.length / 2;
double median = ((myArray[val] + myArray[val - 1]) / 2.0);
return median;
}
public static double calculateSD(double mean, int sum, int length, int[] myArray) {
double standardDeviation = 0.0;
for (double num : myArray) {
standardDeviation += Math.pow(num - mean, 2);
}
return Math.sqrt(standardDeviation / length);
}
}
In order to determine the mode(s), you need to keep track of the occurrences of integers entered into your array. I use a Map to do this. I also calculate the total while entering the integers. I use this total in methods that require it, for example calculateMean. Seems like extra work to recalculate the total each time you need it.
You are dealing with integers, so why declare myArray as array of double? Hence I changed it to array of int.
Your question was how to determine the mode(s). Consequently I refactored method calculatMode. In order to determine the mode(s), you need to interrogate the frequencies, hence the method parameter. Since you claim that there can be zero, one or more than one modes, the method returns a List. First I sort the Map entries according to the value, i.e. the number of occurrences of a particular integer in myArray. I sort the entries in descending order. Then I collect all the sorted entries to a LinkedHashMap since that is a map that stores its entries in the order in which they were added. Hence the first entry in the LinkedHashMap will be the integer with the most occurrences. If the number of occurrences of the first map entry is 1 (one), that means there are no modes (according to this definition that I found):
If no number in the list is repeated, then there is no mode for the list.
In the case of no modes, method calculateMode returns an empty List.
If the number of occurrences of the first entry is more than one, I add the integer to the List. Then I iterate through the remaining map entries and add the integer to the List if its occurrences equals that of the first map entry. As soon as the number of occurrences in an entry does not equal that of the first entry, I exit the while loop. Now List contains all the integers in myArray with the highest number of occurrences.
Here is a sample run (using example data from your question):
Enter the size of your array >> 10
Enter the integer values >> 1 2 2 3 3 4 5 6 7 8
Integers:
1
2
2
3
3
4
5
6
7
8
Mean: 4.1
Mode: [2, 3]
Median: 3.5
Standard Deviation: 2.211334

Compilation error - Inversions counting algorithm

I am struggling in my code with an error.
This is the error I got:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The method recur(Integer[]) in the type D_and_con is not applicable for the arguments (int[])
at edu.uqu.algorithms.inversions.D_and_con.recur(D_and_con.java:27)
at edu.uqu.algorithms.inversions.MainTest.main(MainTest.java:27)
The code computes the number of inversions.
It is:
package edu.uqu.algorithms.inversions;
import java.io.FileNotFoundException;
import java.util.Arrays;
import edu.uqu.algorithms.inversions.util.IOUtil;
public class MainTest {
public static void main(String[] args) {
try {
/*//Inversions using BRUTE FORCE
Integer[] tokens1 = IOUtil.loadFileIntoArray("IntegerArray.txt");
long startTime1 = System.currentTimeMillis();
System.out.println("Started Computing Total nb of invertions BRUTE FORCE..........................");
System.out.println("Total nb of invertions BRUTE FORCE: " + Inversions.countInvertionsBruteForce(tokens1));
long runningTime1 = (System.currentTimeMillis() - startTime1);
System.out.println("BRUTE FORCE Running time: " + runningTime1);
System.out.println("\n");*/
//Inversions using DIVIDE & CONQUER
Integer[] tokens2 = IOUtil.loadFileIntoArray("IntegerArray.txt");
long startTime2 = System.currentTimeMillis();
System.out.println("Started Computing Total nb of invertions DIVIDE & CONQUER..........................");
System.out.println("MMMMM" + D_and_con.recur(tokens2) );
long runningTime2 = (System.currentTimeMillis() - startTime2);
System.out.println("DIVIDE & CONQUER Running time: " + runningTime2);
System.out.println("----------------------- FINISHED -------------------------");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
----------------------------------------
/************************************
*
* The aim of this code is to count the number of inversions in
* an array of integers. Two ways of counting are used, a Brute Force algorithm and
* a recursive Divide and Conquer algorithm.
*
***********************************/
package edu.uqu.algorithms.inversions;
/**
public class Inversions{
/**
* Brute force inversions counting method.
*/
public static long countInvertionsBruteForce(Integer[] entries_p)
{
long result = 0;
for(int i = 0; i < entries_p.length; i++){
for(int j = i+1; j < entries_p.length; j++){
if(entries_p[i] > entries_p[j]) result++;
}
//System.out.println("BRUTE FORCE intermediate result for i = " + i + " IS: " + result);
}
return result;
}
}
--------------------------
Divide and conquer
/************************************
*
* The aim of this code is to count the number of inversions in
* an array of integers. Two ways of counting are used, a Brute Force algorithm and
* a recursive Divide and Conquer algorithm.
*
***********************************/
package edu.uqu.algorithms.inversions;
import java.math.BigDecimal;
public class D_and_con{
private static BigDecimal totalcount = new BigDecimal(0);
public static Integer[] recur(Integer[] entries_p)
{
int n = entries_p.length;
if(n == 1)
{
return entries_p;
}
int middel = n/2;
int[] Larray = new int[middel];
int[] Rarray = new int[n - middel];
System.arraycopy(entries_p , 0 , Larray, 0 , Larray.length );
System.arraycopy(entries_p , Larray.length , Rarray , 0 , Rarray.length);
recur(Larray);\\ERROR APPEAR HERE
recur(Rarray);\\ERROR APPEAR HERE
comb(Larray , Rarray , entries_p );
return entries_p;
}
private static void comb(int[] Larray, int[] Rarray, Integer[] newarray)
{
int LarrayL = Larray.length;
int RarrayL = Rarray.length;
int i=0 , j=0 , k=0 ;
while(i< LarrayL && i<RarrayL)
{
if(Larray[i] < Rarray[i] )
{
newarray[k] = Larray[i];
i++;
}
else
{
newarray[k] = Rarray[j];
i++;
totalcount = totalcount.add (new BigDecimal(Larray.length - 1));
}
k++;
}
while(i < LarrayL) {
newarray[k] = Larray[i];
i++;
k++;
}
while(j < RarrayL) {
newarray[k] = Rarray[j];
j++;
k++;
}
}
}
Explanation
The compiler complaints that you feed your recur method with something of type int[] but you declared that it accepts Integer[]. Therefore take a look at the method signature
// entries_p is Integer[], not int[]
public static Integer[] recur(Integer[] entries_p)
but you feed the method with int[] as seen here
int[] Larray = new int[middel];
int[] Rarray = new int[n - middel];
...
recur(Larray);
recur(Rarray);
Integer is different to int. Though Java can automatically convert both into each other (boxing) it won't do that for advanced types liked arrays Integer[] and int[].
Converting
You will need to convert the types by yourself. Note that Integer[] in contrast to int[] is capable of storing null.
Here are some easy conversions, first without using Streams:
// from int[] to Integer[]
int[] source = ...
Integer[] target = new Integer[source.length];
for (int i = 0; i < source.length; i++) {
// Convert int to Integer
target[i] = Integer.valueOf(source[i]);
}
// from Integer[] to int[]
Integer[] source = ...
int[] target = new int[source.length];
for (int i = 0; i < source.length; i++) {
if (source[i] == null) {
// Don't support null values
throw IllegalArgumentException();
}
// Convert Integer to int
target[i] = source[i].intValue();
}
And now the same using Streams (Java 8):
// from int[] to Integer[]
int[] source = ...
Integer[] target = Arrays.stream() // IntStream
.boxed() // Stream<Integer>
.toArray(Integer[]::new)
// from Integer[] to int[]
Integer[] source = ...
int[] target = Arrays.stream() // Stream<Integer>
.mapToInt(Integer::intValue) // Stream<Integer>
.toArray(int[]::new)
Changing method or argument
Instead of converting the array from one into the other type you may also adjust your method or the argument. For example you could change the method signature from
public static Integer[] recur(Integer[] entries_p)
to
public static Integer[] recur(int[] entries_p)
then it will accept int[] as argument. You may also change the return type to int[]. The other alternative would, as said, be to change the argument from int[] to Integer[]. This applies to that code section:
// You may change both to Integer[]
int[] Larray = new int[middel];
int[] Rarray = new int[n - middel];
Change your Integer[] arrays to int[] arrays!
"int" is a primitive data-type and "Integer" is a Class.
To solve your problem:-
1 - Integer[] tokens2 = IOUtil.loadFileIntoArray("IntegerArray.txt"); //Read data from file in int[].
2 - Integer[] recur(Integer[] entries_p){} //change it as int[] recur(int[] entries_p)

Get MIN and MAX from an array and remove them for Java [duplicate]

It's trivial to write a function to determine the min/max value in an array, such as:
/**
*
* #param chars
* #return the max value in the array of chars
*/
private static int maxValue(char[] chars) {
int max = chars[0];
for (int ktr = 0; ktr < chars.length; ktr++) {
if (chars[ktr] > max) {
max = chars[ktr];
}
}
return max;
}
but isn't this already done somewhere?
Using Commons Lang (to convert) + Collections (to min/max)
import java.util.Arrays;
import java.util.Collections;
import org.apache.commons.lang.ArrayUtils;
public class MinMaxValue {
public static void main(String[] args) {
char[] a = {'3', '5', '1', '4', '2'};
List b = Arrays.asList(ArrayUtils.toObject(a));
System.out.println(Collections.min(b));
System.out.println(Collections.max(b));
}
}
Note that Arrays.asList() wraps the underlying array, so it should not be too memory intensive and it should not perform a copy on the elements of the array.
You can simply use the new Java 8 Streams but you have to work with int.
The stream method of the utility class Arrays gives you an IntStream on which you can use the min method. You can also do max, sum, average,...
The getAsInt method is used to get the value from the OptionalInt
import java.util.Arrays;
public class Test {
public static void main(String[] args){
int[] tab = {12, 1, 21, 8};
int min = Arrays.stream(tab).min().getAsInt();
int max = Arrays.stream(tab).max().getAsInt();
System.out.println("Min = " + min);
System.out.println("Max = " + max)
}
}
==UPDATE==
If execution time is important and you want to go through the data only once you can use the summaryStatistics() method like this
import java.util.Arrays;
import java.util.IntSummaryStatistics;
public class SOTest {
public static void main(String[] args){
int[] tab = {12, 1, 21, 8};
IntSummaryStatistics stat = Arrays.stream(tab).summaryStatistics();
int min = stat.getMin();
int max = stat.getMax();
System.out.println("Min = " + min);
System.out.println("Max = " + max);
}
}
This approach can give better performance than classical loop because the summaryStatistics method is a reduction operation and it allows parallelization.
The Google Guava library has min and max methods in its Chars, Ints, Longs, etc. classes.
So you can simply use:
Chars.min(myarray)
No conversions are required and presumably it's efficiently implemented.
By sorting the array, you get the first and last values for min / max.
import java.util.Arrays;
public class apples {
public static void main(String[] args) {
int a[] = {2,5,3,7,8};
Arrays.sort(a);
int min =a[0];
System.out.println(min);
int max= a[a.length-1];
System.out.println(max);
}
}
Although the sorting operation is more expensive than simply finding min/max values with a simple loop. But when performance is not a concern (e.g. small arrays, or your the cost is irrelevant for your application), it is a quite simple solution.
Note: the array also gets modified after this.
Yes, it's done in the Collections class. Note that you will need to convert your primitive char array to a Character[] manually.
A short demo:
import java.util.*;
public class Main {
public static Character[] convert(char[] chars) {
Character[] copy = new Character[chars.length];
for(int i = 0; i < copy.length; i++) {
copy[i] = Character.valueOf(chars[i]);
}
return copy;
}
public static void main(String[] args) {
char[] a = {'3', '5', '1', '4', '2'};
Character[] b = convert(a);
System.out.println(Collections.max(Arrays.asList(b)));
}
}
I have a little helper class in all of my applications with methods like:
public static double arrayMax(double[] arr) {
double max = Double.NEGATIVE_INFINITY;
for(double cur: arr)
max = Math.max(max, cur);
return max;
}
You could easily do it with an IntStream and the max() method.
Example
public static int maxValue(final int[] intArray) {
return IntStream.range(0, intArray.length).map(i -> intArray[i]).max().getAsInt();
}
Explanation
range(0, intArray.length) - To get a stream with as many elements as present in the intArray.
map(i -> intArray[i]) - Map every element of the stream to an actual element of the intArray.
max() - Get the maximum element of this stream as OptionalInt.
getAsInt() - Unwrap the OptionalInt. (You could also use here: orElse(0), just in case the OptionalInt is empty.)
public int getMin(int[] values){
int ret = values[0];
for(int i = 1; i < values.length; i++)
ret = Math.min(ret,values[i]);
return ret;
}
import java.util.Random;
public class Main {
public static void main(String[] args) {
int a[] = new int [100];
Random rnd = new Random ();
for (int i = 0; i< a.length; i++) {
a[i] = rnd.nextInt(99-0)+0;
System.out.println(a[i]);
}
int max = 0;
for (int i = 0; i < a.length; i++) {
a[i] = max;
for (int j = i+1; j<a.length; j++) {
if (a[j] > max) {
max = a[j];
}
}
}
System.out.println("Max element: " + max);
}
}
A solution with reduce():
int[] array = {23, 3, 56, 97, 42};
// directly print out
Arrays.stream(array).reduce((x, y) -> x > y ? x : y).ifPresent(System.out::println);
// get the result as an int
int res = Arrays.stream(array).reduce((x, y) -> x > y ? x : y).getAsInt();
System.out.println(res);
>>
97
97
In the code above, reduce() returns data in Optional format, which you can convert to int by getAsInt().
If we want to compare the max value with a certain number, we can set a start value in reduce():
int[] array = {23, 3, 56, 97, 42};
// e.g., compare with 100
int max = Arrays.stream(array).reduce(100, (x, y) -> x > y ? x : y);
System.out.println(max);
>>
100
In the code above, when reduce() with an identity (start value) as the first parameter, it returns data in the same format with the identity. With this property, we can apply this solution to other arrays:
double[] array = {23.1, 3, 56.6, 97, 42};
double max = Arrays.stream(array).reduce(array[0], (x, y) -> x > y ? x : y);
System.out.println(max);
>>
97.0
Here's a utility class providing min/max methods for primitive types: Primitives.java
int [] numbers= {10,1,8,7,6,5,2};
int a=Integer.MAX_VALUE;
for(int c:numbers) {
a=c<a?c:a;
}
System.out.println("Lowest value is"+a);
Example with float:
public static float getMaxFloat(float[] data) {
float[] copy = Arrays.copyOf(data, data.length);
Arrays.sort(copy);
return copy[data.length - 1];
}
public static float getMinFloat(float[] data) {
float[] copy = Arrays.copyOf(data, data.length);
Arrays.sort(copy);
return copy[0];
}
Pass the array to a method that sorts it with Arrays.sort() so it only sorts the array the method is using then sets min to array[0] and max to array[array.length-1].
The basic way to get the min/max value of an Array. If you need the unsorted array, you may create a copy or pass it to a method that returns the min or max. If not, sorted array is better since it performs faster in some cases.
public class MinMaxValueOfArray {
public static void main(String[] args) {
int[] A = {2, 4, 3, 5, 5};
Arrays.sort(A);
int min = A[0];
int max = A[A.length -1];
System.out.println("Min Value = " + min);
System.out.println("Max Value = " + max);
}
}
Here is a solution to get the max value in about 99% of runs (change the 0.01 to get a better result):
public static double getMax(double[] vals){
final double[] max = {Double.NEGATIVE_INFINITY};
IntStream.of(new Random().ints((int) Math.ceil(Math.log(0.01) / Math.log(1.0 - (1.0/vals.length))),0,vals.length).toArray())
.forEach(r -> max[0] = (max[0] < vals[r])? vals[r]: max[0]);
return max[0];
}
(Not completely serious)
int[] arr = {1, 2, 3};
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
int max_ = Collections.max(list);
int i;
if (max_ > 0) {
for (i = 1; i < Collections.max(list); i++) {
if (!list.contains(i)) {
System.out.println(i);
break;
}
}
if(i==max_){
System.out.println(i+1);
}
} else {
System.out.println("1");
}
}

How to generate a random number that does not repeat

I'm writing a MasterMind program in Java. My intention was to generate a 4 digit number, but all digits need to be different. How would you do that using Math.random()? Or is there a better way?
example:
4321 (allowed)
4341 (not allowed)
You can simply achieve this using Collections.shuffle method.
List<Integer> l = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Collections.shuffle(l);
Integer result = 1000*l.get(0) + 100*l.get(1) + 10*l.get(2) + l.get(3);
Using Maps gives you cleaner code and better complexity
public static void main(String[] args) {
Set<Integer> fourUniqueRandonNumbers = new HashSet<Integer>() ;
int maxItems = 4;
StringBuilder flatValueToRetun = new StringBuilder();
while (fourUniqueRandonNumbers.size()<maxItems){
int randomNumber = (int )(Math.random() * 9 + 1);
if(!fourUniqueRandonNumbers.contains(randomNumber)){
fourUniqueRandonNumbers.add(randomNumber);
flatValueToRetun.append(randomNumber);
}
}
}
Use Collections to determine that you already have this digit:
import java.util.ArrayList;
public class MyRandom {
public static void main(String[] args) {
System.out.println(getRandom(4));
System.out.println(getRandom(4));
System.out.println(getRandom(10));
}
public static String getRandom(int length){
if (length>10) return "Hexadecimal?";
ArrayList<Integer> numbers=new ArrayList<Integer>();
while (length>0){
int digit=(int)(Math.random()*10);
if (numbers.contains(digit)) continue;
numbers.add(digit);
length--;
}
StringBuilder sb=new StringBuilder();
for (Integer integer : numbers) {
sb.append(integer);
}
return sb.toString();
}
}
Nothing really optimized here, but :
the simple/brutal way would be to generate digit by digit, and as you store them, as long as you get a digit you already have, you'll generate a new random digit.
A better solution would be to initially store the possible digits (let's say in a list), and for each digit you would get a random number up to the size of the list (minus 1 as list starts at 0), get the element at this position, and remove the element from the list.
Example :
Possible digits : 123456789
picks a random element, let's say "3"
Possible digits : 12456789
and so on.
There are probably many ways to solve this problem, I have provided two below.
First one:
Using a random generator, add random digits from 1-9 to a set.
Set prevents duplicates, so continue generating until the set size is 4.
Second one:
Add the digits 1-9 to an ArrayList, use Collections.shuffle to shuffle the numbers.
Take the first 4 numbers.
Note: Not using the digit 0, to prevent 0123 from becoming 123.
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
public class QuickTester {
public static void main(String[] args) {
for(int i = 0; i < 3; i++) {
setRandom();
}
for(int i = 0; i < 3; i++) {
shuffleRandom();
}
}
/**
* Use a random generator, generate digits from 1-9,
* add them to the set (prevents duplicates) until set size is 4
*/
public static void setRandom() {
Random rand = new Random();
Set<Integer> set = new HashSet<Integer>();
while(set.size() < 4) {
set.add(rand.nextInt(9)+1);
}
String numStr = "";
for(Integer n : set) {
numStr += n;
}
int num = Integer.parseInt(numStr);
System.out.println(num);
}
/**
* Add digits 1-9 to an ArrayList, shuffle it using Collections.shuffle
* Take the first 4 digits
*/
public static void shuffleRandom() {
List<Integer> intList = new ArrayList<Integer>();
for(int i = 1; i < 10; i++) {
intList.add(i);
}
Collections.shuffle(intList);
String numStr = "";
for(int i = 0; i < 4; i++) {
numStr += intList.get(i);
}
int num = Integer.parseInt(numStr);
System.out.println(num);
}
}
Output:
3459
1359
2589
3456
2198
2153
So you want to choose between 4 things, then the 3 remaining, then the 2 remaining, now take the last . How about:
n1 = generator.nextInt(4)+1;
n2 = generator.nextInt(3)+1;
if (!n2<n1) {n2 += 1;}//avoid the hole
n3 = generator.nextInt(2)+1;
if (!n3<n1) {n3 += 1;}//avoid the holes
if (!n3<n2) {n2 += 1;}

Finding the max/min value in an array of primitives using Java

It's trivial to write a function to determine the min/max value in an array, such as:
/**
*
* #param chars
* #return the max value in the array of chars
*/
private static int maxValue(char[] chars) {
int max = chars[0];
for (int ktr = 0; ktr < chars.length; ktr++) {
if (chars[ktr] > max) {
max = chars[ktr];
}
}
return max;
}
but isn't this already done somewhere?
Using Commons Lang (to convert) + Collections (to min/max)
import java.util.Arrays;
import java.util.Collections;
import org.apache.commons.lang.ArrayUtils;
public class MinMaxValue {
public static void main(String[] args) {
char[] a = {'3', '5', '1', '4', '2'};
List b = Arrays.asList(ArrayUtils.toObject(a));
System.out.println(Collections.min(b));
System.out.println(Collections.max(b));
}
}
Note that Arrays.asList() wraps the underlying array, so it should not be too memory intensive and it should not perform a copy on the elements of the array.
You can simply use the new Java 8 Streams but you have to work with int.
The stream method of the utility class Arrays gives you an IntStream on which you can use the min method. You can also do max, sum, average,...
The getAsInt method is used to get the value from the OptionalInt
import java.util.Arrays;
public class Test {
public static void main(String[] args){
int[] tab = {12, 1, 21, 8};
int min = Arrays.stream(tab).min().getAsInt();
int max = Arrays.stream(tab).max().getAsInt();
System.out.println("Min = " + min);
System.out.println("Max = " + max)
}
}
==UPDATE==
If execution time is important and you want to go through the data only once you can use the summaryStatistics() method like this
import java.util.Arrays;
import java.util.IntSummaryStatistics;
public class SOTest {
public static void main(String[] args){
int[] tab = {12, 1, 21, 8};
IntSummaryStatistics stat = Arrays.stream(tab).summaryStatistics();
int min = stat.getMin();
int max = stat.getMax();
System.out.println("Min = " + min);
System.out.println("Max = " + max);
}
}
This approach can give better performance than classical loop because the summaryStatistics method is a reduction operation and it allows parallelization.
The Google Guava library has min and max methods in its Chars, Ints, Longs, etc. classes.
So you can simply use:
Chars.min(myarray)
No conversions are required and presumably it's efficiently implemented.
By sorting the array, you get the first and last values for min / max.
import java.util.Arrays;
public class apples {
public static void main(String[] args) {
int a[] = {2,5,3,7,8};
Arrays.sort(a);
int min =a[0];
System.out.println(min);
int max= a[a.length-1];
System.out.println(max);
}
}
Although the sorting operation is more expensive than simply finding min/max values with a simple loop. But when performance is not a concern (e.g. small arrays, or your the cost is irrelevant for your application), it is a quite simple solution.
Note: the array also gets modified after this.
Yes, it's done in the Collections class. Note that you will need to convert your primitive char array to a Character[] manually.
A short demo:
import java.util.*;
public class Main {
public static Character[] convert(char[] chars) {
Character[] copy = new Character[chars.length];
for(int i = 0; i < copy.length; i++) {
copy[i] = Character.valueOf(chars[i]);
}
return copy;
}
public static void main(String[] args) {
char[] a = {'3', '5', '1', '4', '2'};
Character[] b = convert(a);
System.out.println(Collections.max(Arrays.asList(b)));
}
}
I have a little helper class in all of my applications with methods like:
public static double arrayMax(double[] arr) {
double max = Double.NEGATIVE_INFINITY;
for(double cur: arr)
max = Math.max(max, cur);
return max;
}
You could easily do it with an IntStream and the max() method.
Example
public static int maxValue(final int[] intArray) {
return IntStream.range(0, intArray.length).map(i -> intArray[i]).max().getAsInt();
}
Explanation
range(0, intArray.length) - To get a stream with as many elements as present in the intArray.
map(i -> intArray[i]) - Map every element of the stream to an actual element of the intArray.
max() - Get the maximum element of this stream as OptionalInt.
getAsInt() - Unwrap the OptionalInt. (You could also use here: orElse(0), just in case the OptionalInt is empty.)
public int getMin(int[] values){
int ret = values[0];
for(int i = 1; i < values.length; i++)
ret = Math.min(ret,values[i]);
return ret;
}
import java.util.Random;
public class Main {
public static void main(String[] args) {
int a[] = new int [100];
Random rnd = new Random ();
for (int i = 0; i< a.length; i++) {
a[i] = rnd.nextInt(99-0)+0;
System.out.println(a[i]);
}
int max = 0;
for (int i = 0; i < a.length; i++) {
a[i] = max;
for (int j = i+1; j<a.length; j++) {
if (a[j] > max) {
max = a[j];
}
}
}
System.out.println("Max element: " + max);
}
}
A solution with reduce():
int[] array = {23, 3, 56, 97, 42};
// directly print out
Arrays.stream(array).reduce((x, y) -> x > y ? x : y).ifPresent(System.out::println);
// get the result as an int
int res = Arrays.stream(array).reduce((x, y) -> x > y ? x : y).getAsInt();
System.out.println(res);
>>
97
97
In the code above, reduce() returns data in Optional format, which you can convert to int by getAsInt().
If we want to compare the max value with a certain number, we can set a start value in reduce():
int[] array = {23, 3, 56, 97, 42};
// e.g., compare with 100
int max = Arrays.stream(array).reduce(100, (x, y) -> x > y ? x : y);
System.out.println(max);
>>
100
In the code above, when reduce() with an identity (start value) as the first parameter, it returns data in the same format with the identity. With this property, we can apply this solution to other arrays:
double[] array = {23.1, 3, 56.6, 97, 42};
double max = Arrays.stream(array).reduce(array[0], (x, y) -> x > y ? x : y);
System.out.println(max);
>>
97.0
Here's a utility class providing min/max methods for primitive types: Primitives.java
int [] numbers= {10,1,8,7,6,5,2};
int a=Integer.MAX_VALUE;
for(int c:numbers) {
a=c<a?c:a;
}
System.out.println("Lowest value is"+a);
Example with float:
public static float getMaxFloat(float[] data) {
float[] copy = Arrays.copyOf(data, data.length);
Arrays.sort(copy);
return copy[data.length - 1];
}
public static float getMinFloat(float[] data) {
float[] copy = Arrays.copyOf(data, data.length);
Arrays.sort(copy);
return copy[0];
}
Pass the array to a method that sorts it with Arrays.sort() so it only sorts the array the method is using then sets min to array[0] and max to array[array.length-1].
The basic way to get the min/max value of an Array. If you need the unsorted array, you may create a copy or pass it to a method that returns the min or max. If not, sorted array is better since it performs faster in some cases.
public class MinMaxValueOfArray {
public static void main(String[] args) {
int[] A = {2, 4, 3, 5, 5};
Arrays.sort(A);
int min = A[0];
int max = A[A.length -1];
System.out.println("Min Value = " + min);
System.out.println("Max Value = " + max);
}
}
Here is a solution to get the max value in about 99% of runs (change the 0.01 to get a better result):
public static double getMax(double[] vals){
final double[] max = {Double.NEGATIVE_INFINITY};
IntStream.of(new Random().ints((int) Math.ceil(Math.log(0.01) / Math.log(1.0 - (1.0/vals.length))),0,vals.length).toArray())
.forEach(r -> max[0] = (max[0] < vals[r])? vals[r]: max[0]);
return max[0];
}
(Not completely serious)
int[] arr = {1, 2, 3};
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
int max_ = Collections.max(list);
int i;
if (max_ > 0) {
for (i = 1; i < Collections.max(list); i++) {
if (!list.contains(i)) {
System.out.println(i);
break;
}
}
if(i==max_){
System.out.println(i+1);
}
} else {
System.out.println("1");
}
}

Categories

Resources