Finding Similar Birthday through structure data - java

Hey guys I am trying to get the number of people who have the same birthday but this solution isn't working.This program is showing 0.0% .Please help me ...!.
public double calculate(int size, int count) {
int matches = 0;//initializing an integer variable
boolean out = false;
List<Integer> days=new ArrayList<Integer>();// creating arraylist name days of type int
for (int j = 0; j <count; j++) {
for (int i = 0; i < size; i++) {// initializing for loop till less than size
Random rand = new Random(); // creating an object of random function
int Brday = rand.nextInt(364) + 0;//initializing the limit of randomc number chozen
days.add(Brday); //adding values to arraylist
}
for (int l = 0; l < size; l++) {
int temp = l;//assigning value of l to a variable
for (int k = l + 1; k < size; k++) {
if (days.get(k) == temp) {// check statement to check values are same
matches++;//incrementing variable
out = true;
mOut.print("Count does have same birthday" + matches);
break;
} else {
mOut.print("does not have same birthday");
}
}
if (out) {
out = false;
break;
}
}
}
double prob = (double) matches / count;
mOut.print("The probability for two students to share a birthday is " + prob*100 + ".");
return prob;//returning double value of the function
}

Actually, you get either 0 percent or 100 percent with your code. Try invoking it with calculate(100, 100) if you want to see.
There are two things that are wrong in this code. First, if you run the simulation more than once (count > 1) then you never clear the list of birthdays before the second iteration.
Your method should begin with:
public double calculate(int size, int count) {
int matches = 0;
boolean out = false;
List<Integer> days;
for (int j = 0; j <count; j++) {
days = new ArrayList<Integer>();
Secondly, you're not comparing two birthdays but you're comparing a birthday to the index in the list.
This line:
int temp = l;//assigning value of l to a variable
Should read:
int temp = days.get(l); // Remember the birthday at index l
With those changes you'll get a much better result.

Related

How to create random numbers a specific number of times?

How can i create a random number a specific numbers of time?
public class Feld {
public static void main(String[] args) {
double k = (int)(Math.random()*1000001);
int n = 1000000;
int arr[] = new int[n];
int i = 0;
for(i = 0;i<n;i++){
arr[i] = i;
}
boolean found = false;
i=0;
while (i < arr.length) {
if (arr[i] == k) {
found = true;
break;
}
i++;
}
if (found) {
i++;
System.out.println(i);
}
else {
System.out.println((arr.length + 1));
}
}
}
My problem is, that if i put k into a loop to create it more than one time i'll get an error at:
if (arr[i] == k)
!!I just found out that i made a mistake explaining my problem. The array should be filled with values from 0-1.000.000 and i am supposed to print out the position of a random generated number for a specific amount of times.
If you want to have an array full of random numbers, I suggest using the following:
int n = 1000000;
int arr[] = new int[n];
for(int i = 0; i < n; i++){
arr[i] = (int)(Math.random() * 1000001);
}
That will work and you don't even need the variable k.
Edit:
If you want to print at what position you find a specific value (for example x = 543), you can use the following code:
int x = 543;
int n = 1000000;
int arr[] = new int[n];
for(int i = 0; i < n; i++){
arr[i] = (int)(Math.random() * 1000001);
if(arr[i] == x) {
System.out.println(i);
break;
}
}
Edit2
One possible solution to your new problem looks like this:
public class Feld {
public static void main(String[] args) {
int n = 1000000;
int arr[] = new int[n];
int i = 0;
for(i = 0; i < n; i++){
arr[i] = i; //Filling array with values 0-1000000
}
int number = 20; //Print out position of a random generated number a specific amount of times
int randomNumber = (int)(Math.random()*1000001); //The random number
for(int j = 0; j < number; j++) { //Find number for a specific amount of times
for(int k = 0; k < arr.length; k++) { //Find number in array
if(arr[k] == randomNumber) {
System.out.println(arr[k]); //Print
break; //Number found, don't have to search anymore
}
}
}
}
}
I would write a method that returns an array of random numbers and takes an int argument that defines the length of the array.
One possible solution is this:
public static int[] createRandomArray(int length) {
// create an array of the given length
int[] result = new int[length];
// and use a single for loop that puts random int values into every index
for (int i = 0; i < result.length; i++) {
result[i] = ThreadLocalRandom.current().nextInt();
}
// then simply return the result
return result;
}
Try it as follows
public static void main(String[] args) {
// super primitive time measurement:
// take the moment in time before calling the method
Instant start = Instant.now();
// then call the method
int[] array = createRandomArray(1000000);
// and take the moment in time after the method returned
Instant end = Instant.now();
// then calculate the duration
Duration duration = Duration.between(start, end);
// and print the duration in milliseconds
System.out.printf("Array creation took %d milliseconds\n", duration.toMillis());
}
The result is the following output on my system:
Array creation took 10 milliseconds

How to solve "the birthday paradox" in java without using nested loop?

I have tried the problem with nested loop, but how can I solve it without using nested loops and within the same class file. The Question is to find the probability of two people having the same birthday in a group. And it should produce the following output : In a group of 5 people and 10000 simulations, the probability is 2.71%. Note: using arraylist or hashmap is possible. But I don't know how. Thank you
public void process() {
int groupSize = System.out.getSize();
int simulationCount = System.out.getCount();
if (groupSize < 2 || groupSize > 365) {
System.out.makeAlertToast("Group Size must be in the range 2-365.");
return;
}
if (simulationCount <= 0) {
System.out.makeAlertToast("Simulation Count must be positive.");
return;
}
double percent = calculate(groupSize, simulationCount);
// report results
System.out.println("For a group of " + groupSize + " people, the percentage");
System.out.println("of times that two people share the same birthday is");
System.out.println(String.format("%.2f%% of the time.", percent));
}
public double calculate(int size, int count) {
int numTrialSuccesses = 0;
// Repeat and count.
for (int n=0; n < count; n++) {
Random rand = new Random(n);
// Generate birthdays (random array)
int[] birthdays = new int [size];
for (int i=0; i <size; i++) {
birthdays[i] = rand.nextInt (365);
}
// Check if any two match.
boolean matchExists = false;
for (int i=0; i < size; i++) {
for (int j=0; j < size; j++) {
if ( (i != j) && (birthdays[i] == birthdays[j]) ) {
// Note: musn't forget the i!=j test above!
matchExists = true;
if (matchExists) break;
}
}
}
if (matchExists) {
numTrialSuccesses ++;
}
} //end-for-trials
double prob = ((double) numTrialSuccesses *100)/ (double) count;
return prob ;
}
}
A solution using fancy data structure HashSet. As some mentioned in the comments you could use an 365 element array of bools which you switch to true if encountered.
The below is a similar idea. You add each birthday to the set if it does not contain the birthday yet. You increment the counter if the Set does contain the birthday. Now you don't need that pesky second iteration so your time complexity goes down to O(n). It goes down to O(n) since a lookup in a set has constant time.
public double calculate(int size, int count) {
int numTrialSuccesses = 0;
// Repeat and count.
for (int n=0; n < count; n++) {
Random rand = new Random(n);
Set<Integer> set = new HashSet<Integer>();
for (int i=0; i <size; i++) {
int bday = rand.nextInt (365);
Integer bday1 = new Integer(bday);
if(set.contains(bday1)){
numTrialSuccesses++;
break;
}else{
set.add(bday1);
}
}
} //end-for-trials
double prob = ((double) numTrialSuccesses *100)/ (double) count;
//like wise comments have noted this is not the probability!!! Just a simulation
return prob ;
}
This code:
int[] birthdays = new int [size];
for (int i=0; i <size; i++) {
birthdays[i] = rand.nextInt (365);
}
// Check if any two match.
boolean matchExists = false;
for (int i=0; i < size; i++) {
for (int j=0; j < size; j++) {
if ( (i != j) && (birthdays[i] == birthdays[j]) ) {
// Note: musn't forget the i!=j test above!
matchExists = true;
if (matchExists) break;
}
}
}
if (matchExists) {
numTrialSuccesses ++;
}
can be changed to:
List<Integer> list = new ArrayList<Integer>();
for (int i=0; i <size; i++) {
int day=rand.nextInt (365);
if(list.contains(day)){
numTrailSuccesses++;
break;
}else{
list.add(day);
}
}
In java-8,
double calculateProbability(int trials, int people) {
//for trials = 10_000, people = 5
int timesWithSharedBirthday = IntStream.range(0,trials) // Run 10_000 trials
// generate 5 bdays, count distinct ones. Filter out those with 5 distinct
.filter(i -> ThreadLocalRandom.current().ints(people,1,365).distinct().count() != people)
.count(); // Add up the runs without five distinct bdays.
return probability = 100.0 * timesWithSharedBirthday / trials;
}
I don't know how it will fare with your online grader, but it's fun to practice with streams.
There isn't any need to go beyond primitives with something like a fixed number of birthdays.
Create an array of 365 buckets, and make a note in each bucket of when a birthday hit that date. This allows the use of efficient array operations.
Rather than creating a new array each time, the code below uses System.arraycopy to copy a zeroed-out array over the existing one--this gains a bit of performance.
Nevertheless, the performance gain over the HashSet example given earlier is modest at best, performing 5 or 6 times faster, but not orders of magnitude faster.
As such, if using HashSet and similar tools improves clarity, then go for clarity.
public double calculate(int size, int count) {
int numTrialSuccesses = 0;
int[] daysOfYear = new int[365];
final int[] empty = new int[365];
// Repeat and count.
for (int n = 0; n < count; n++) {
Random rand = new Random(n);
// Efficiently clear out the array
System.arraycopy(empty, 0, daysOfYear, 0, 365);
boolean matchExists = false;
for (int i = 0; i < size; i++) {
int birthday = rand.nextInt(365);
// Compare, then increment, the bucket for the birthday
if(daysOfYear[birthday]++>0){
matchExists = true;
break;
}
}
if (matchExists) {
numTrialSuccesses++;
}
} //end-for-trials
double prob = ((double) numTrialSuccesses * 100) / (double) count;
return prob;
}

Returning wrong percentage

I am trying to calculate how many times two people in a group have the same birthday when given a size of the group. I am also given how many times the simulation is ran. I am trying to return the correct percentage for how many times we have two people share the same birthday out of the given amount of simulations.
I created an array first and then called a method to put the elements in a hashMap which would then show when there are two of the same values in the hashMap. However, I am not getting the correct percentage when running on Android Studio. In fact I am getting a percentage way off. I also declared a global static match variable of type int above this block.
/**
* sameBday: Create a word count mapping from an array
*/
public void sameBday(int[] valueHolder) {
Map<Integer, Integer> myMap = new HashMap<Integer, Integer>();
for(int number: valueHolder){
if(!myMap.containsKey(number)){
myMap.put(number, 1);
}
else if(myMap.containsKey(number)){
myMap.put(number, myMap.get(number) + 1);
match++;
break;
}
}
}
public double calculate(int size, int count) {
double percentage = 0.0;
int[] myArray = new int[size];
for(int i = 1; i <= count; i++){
Random r = new Random(i);
for(int j = 0; j < size; j++){
myArray[j] = r.nextInt(365) + 1;
}
sameBday(myArray);
if(i == count){
percentage = (match * (100.0/i));
}
}
return percentage;
}
Well your code is full of weird things, but that's OK we all did that. The first thing is Map, you don't need it. You can create just good old for loop and by additional check you will not compare the same person (it is i != j condition), but if you really want to do this by map you need to at the end of adding number (as key) to map check if some value of key is higher than 1, if true it's a match.
How to do something at the end of loop?
if(i == count){
percentage = (match * (100.0/i));
}
No, just do this after loop :)
//At the beginning there is int match = 0;
public void sameDayBirthday(int[] birthdays) {
for(int i = 0; i < birthdays.length; i++) {
for(int j = 0; j < birthdays.length; j++) {
if(birthdays[i] == birthdays[j] && i != j) {
match++;
return;
}
}
}
}
public double calculate(int size, int count) {
int[] birthdays = new int[size];
Random r = new Random();
for(int i = 1; i <= count; i++){ //looping through i counts (or 20 counts in this case
for(int j = 0; j < size; j++){ //looping through j times every i iteration
birthdays[j] = r.nextInt(365) + 1;
}
sameDayBirthday(birthdays);
}
return (match * (100.0/(double) count));
}
This code by calling calculate(23, 1000000) got me 50.7685% chance, for 22 persons 47.48690%
I am sorry if I offend you I didn't mean it. Leave a comment if you have questions.
I would use a HashSet and skip the sameBday function:
public double calculate(int size, int count) {
int match = 0;
Random r = new Random();
for(int i = 1; i <= count; i++){ //looping through i counts (or 20 counts in this case
Set<Integer> birthdays = new HashSet<Integer>(size);
for(int j = 0; j < size; j++){ //looping through j times every i iteration
Integer birthday = r.nextInt(365) + 1;
if (birthdays.contains(birthday)) {
match++;
break;
} else {
birthdays.add(birthday);
}
}
}
return (match * (100.0/count));
}

Getting the most "popular" number from array

I need for homework to get the most "popular" number in an array (the number in the highest frequency), and if there are several numbers with the same number of shows, get some number randomly.
After more then three hours of trying, and either searching the web, this is what I got:
public int getPopularNumber(){
int count = 1, tempCount;
int popular = array[0];
int temp = 0;
for ( int i = 0; i < (array.length - 1); i++ ){
if ( _buses[i] != null )
temp = array[i];
tempCount = 0;
for ( int j = 1; j < _buses.length; j++ ){
if ( array[j] != null && temp == array[j] )
tempCount++;
}
if ( tempCount > count ){
popular = temp;
count = tempCount;
}
}
return popular;
}
This code work, but don't take into account an important case- if there is more than one number with the same count of shows. Then it just get the first one.
for example: int[]a = {1, 2, 3, 4, 4, ,5 ,4 ,5 ,5}; The code will grab 4 since it shown first, and it's not random as it should be.
Another thing- since it's homework I can't use ArrayList/maps and stuff that we still didn't learn.
Any help would be appreciated.
Since they didn't give you any time complexity boundary, you can "brute force" the problem by scanning the the array N^2 times. (disclaimer, this is the most intuitive way of doing it, not the fastest or the most efficient in terms of memory and cpu).
Here is some psuedo-code:
Create another array with the same size as the original array, this will be the "occurrence array"
Zero its elements
For each index i in the original array, iterate the original array, and increment the element in the occurrence array at i each time the scan finds duplicates of the value stored in i in the original array.
Find the maximum in the occurrence array
Return the value stored in that index in the original array
This way you mimic the use of maps with just another array.
If you are not allowed to use collection then you can try below code :
public int getPopularNumber(){
int inputArr[] = {1, 2, 3, 4, 4, 5 ,4 ,5 ,5}; // given input array
int[] tempArr = new int[inputArr.length];
int[] maxValArr = new int[inputArr.length];
// tempArr will have number as index and count as no of occurrence
for( int i = 0 ; i < inputArr.length ; i++){
tempArr[inputArr[i]]++;
}
int maValue = 0;
// find out max count of occurrence (in this case 3 for value 4 and 5)
for( int j = 0 ; j < tempArr.length ; j++){
maValue = Math.max(maValue, tempArr[j]);
}
int l =0;
// maxValArr contains all value having maximum occurrence (in this case 4 and 5)
for( int k = 0 ; k < tempArr.length ; k++){
if(tempArr[k] == maValue){
maxValArr[l] = k;
l++;
}
}
return maxValArr[(int)(Math.random() * getArraySize(maxValArr))];
}
private int getArraySize(int[] arr) {
int size = 0;
for( int i =0; i < arr.length ; i++){
if(arr[i] == 0){
break;
}
size++;
}
return size;
}
that's hard as hell :D
After some trying, I guess I have it (If there will be 2 numbers with same frequency, it will return first found):
int mostPopNumber =0;
int tmpLastCount =0;
for (int i = 0; i < array.length-1; i++) {
int tmpActual = array[i];
int tmpCount=0;
for (int j = 0; j < array.length; j++) {
if(tmpActual == array[j]){
tmpCount++;
}
}
// >= for the last one
if(tmpCount > tmpLastCount){
tmpLastCount = tmpCount;
mostPopNumber = tmpActual;
}
}
return mostPopNumber;
--
Hah your code give me idea- you cant just remember last most popular number, btw I've found it solved there Find the most popular element in int[] array
:)
EDIT- after many, and many years :D, that works well :)
I've used 2D int and Integer array - you can also use just int array, but you will have to make more length array and copy actual values, Integer has default value null, so that's faster
Enjoy
public static void main(String[] args) {
//income array
int[] array= {1,1,1,1,50,10,20,20,2,2,2,2,20,20};
//associated unique numbers with frequency
int[][] uniQFreqArr = getUniqValues(array);
//print uniq numbers with it's frequency
for (int i = 0; i < uniQFreqArr.length; i++) {
System.out.println("Number: " + uniQFreqArr[i][0] + " found : " + uniQFreqArr[i][1]);
}
//get just most frequency founded numbers
int[][] maxFreqArray = getMaxFreqArray(uniQFreqArr);
//print just most frequency founded numbers
System.out.println("Most freq. values");
for (int i = 0; i < maxFreqArray.length; i++) {
System.out.println("Number: " + maxFreqArray[i][0] + " found : " + maxFreqArray[i][1]);
}
//get some of found values and print
int[] result = getRandomResult(maxFreqArray);
System.out.println("Found most frequency number: " + result[0] + " with count: " + result[1]);
}
//get associated array with unique numbers and it's frequency
static int[][] getUniqValues(int[] inArray){
//first time sort array
Arrays.sort(inArray);
//default value is null, not zero as in int (used bellow)
Integer[][] uniqArr = new Integer[inArray.length][2];
//counter and temp variable
int currUniqNumbers=1;
int actualNum = inArray[currUniqNumbers-1];
uniqArr[currUniqNumbers-1][0]=currUniqNumbers;
uniqArr[currUniqNumbers-1][1]=1;
for (int i = 1; i < inArray.length; i++) {
if(actualNum != inArray[i]){
uniqArr[currUniqNumbers][0]=inArray[i];
uniqArr[currUniqNumbers][1]=1;
actualNum = inArray[i];
currUniqNumbers++;
}else{
uniqArr[currUniqNumbers-1][1]++;
}
}
//get correctly lengthed array
int[][] ret = new int[currUniqNumbers][2];
for (int i = 0; i < uniqArr.length; i++) {
if(uniqArr[i][0] != null){
ret[i][0] = uniqArr[i][0];
ret[i][1] = uniqArr[i][1];
}else{
break;
}
}
return ret;
}
//found and return most frequency numbers
static int[][] getMaxFreqArray(int[][] inArray){
int maxFreq =0;
int foundedMaxValues = 0;
//filter- used sorted array, so you can decision about actual and next value from array
for (int i = 0; i < inArray.length; i++) {
if(inArray[i][1] > maxFreq){
maxFreq = inArray[i][1];
foundedMaxValues=1;
}else if(inArray[i][1] == maxFreq){
foundedMaxValues++;
}
}
//and again copy to correctly lengthed array
int[][] mostFreqArr = new int[foundedMaxValues][2];
int inArr= 0;
for (int i = 0; i < inArray.length; i++) {
if(inArray[i][1] == maxFreq){
mostFreqArr[inArr][0] = inArray[i][0];
mostFreqArr[inArr][1] = inArray[i][1];
inArr++;
}
}
return mostFreqArr;
}
//generate number from interval and get result value and it's frequency
static int[] getRandomResult(int[][] inArray){
int[]ret=new int[2];
int random = new Random().nextInt(inArray.length);
ret[0] = inArray[random][0];
ret[1] = inArray[random][1];
return ret;
}

Retrieving the index of a maximum value of an array

Say I have an array with elements {1,5,2,3,4}.
I have the code to find the maximum value, which is 5.
I would like to remove this value from the array by replacing array[1] with array[2], array[2] with array[3], etc., and then making a new array with one less index (to not repeat the last value).
How can I find/state the index of the maximum value for an array, knowing what the maximum value is?
Would it be a lot different if we had an array where the maximum value occurs twice? {1,5,5,2,3}
Thank you very much.
EDIT1: I have figured out how to do it for one instance incorporating int maxIndex = 0; and setting it at the same time as the max value is set.
Now I just need to figure out for multiple instances.
int[] score = new int[5];
for (int i=0 ; i<=4 ;i++)
{
System.out.println("enter Score");
score[i] = keyb.nextInt();
}
System.out.println(Arrays.toString(score)); //need import java.util.Arrays;
int max = score[0];
int maxIndex = 0;
for (int i = 1 ; i<=score.length-1 ; i++)
{
if (score[i] > max)
{max = score[i];
maxIndex= i; }
}
System.out.println("The maximum is " +max); //this finds the maximum. Now say we want to remove the maximum (no matter what the position)..
System.out.println("it is located at index " + maxIndex);
For multiple instances, you can use a Set to keep track of the indices in the array that corresponds to the max number.
int max = score[0];
Set<Integer> maxIndices = new HashSet<>(); // a set that contains the indices of the max number in the array
maxIndices.add(0);
for (int i = 1; i <= score.length - 1; i++) {
if (score[i] > max) {
max = score[i];
maxIndices.clear(); // clear the set as we have a new max number
maxIndices.add(i);
} else if (score[i] == max) {
maxIndices.add(i); // keep track of all the indices in the array that corresponds to the max number
}
}
// create the new array with the new size
int newArrayWithoutMaxNums[] = new int[score.length - maxIndices.size()];
int newCounter = 0;
for (int i = 0; i < score.length; ++i) {
if (!maxIndices.contains(i)) { // determine if the score is the max
newArrayWithoutMaxNums[newCounter++] = score[i];
}
}
for (int i = 0; i < newArrayWithoutMaxNums.length; ++i) {
System.out.print(newArrayWithoutMaxNums[i] + "\t");
}
You can try something like this:
public class findMaxIndex {
public static void main(String[] args) {
int[] score = new int[]{1,5,5,5,5,2,4,6,6,6,6,1,4,1};
int max = score[0];
int[] maxIndexArray = new int[score.length];
int j = 0;
for (int i = 1; i <= score.length-1 ; i++) {
if (score[i] > max) {
max = score[i];
j = 0;
maxIndexArray = new int[score.length];
maxIndexArray[j++] = i;
}
else if (score[i] == max) {
maxIndexArray[j++] = i;
}
}
System.out.println("The maximum is " +max); //this finds the maximum. Now say we want to remove the maximum (no matter what the position)..
System.out.println("it is located at index ");
for (int i = 0; i < maxIndexArray.length - 1; i++) {
System.out.println(maxIndexArray[i]);
}
}
}
There are better things that you can do. However, I figure at least one simple example is good. Thus the below, though I certainly recommend trying to figure out the other answers as well even if the methods used are things you haven't learned yet.
Let's start by altering your code slightly.
int max = score[0];
int maxIndex[] = new int[score.length]
int maxCount = 0;
for (int i = 1 ; i < score.length ; i++){
if (score[i] > max){
max = score[i];
maxCount = 0;
maxIndex[maxCount++] = i;
}
else if (score[i] == max)
{
//maxCount++ performs maxCount = maxCount+1; after the specified operation
maxIndex[maxCount++] = i;
}
}
System.out.println("The maximum is " + max);
System.out.print("This value occurs at: ");
for(int i = 0; i < maxCount; i++){
System.out.print(maxIndex[i]);
}

Categories