java random generator without repeat - java

Im trying to generate a 2d array using a random generator. basically, each column should contain a random value between 1-50 that is not repeated but the problem is, I can't get a repeat value on the same row, or any other row or column in the program. In other words, each I integer should only display once. My objects were created via linked list and I will probably integrate the algorthim in there once I figure it out but for now, heres what I did.
int[] array = new int[50];
for(int i=1;i<=9;i++)
{
int[] grades = new int[5];
for(int j=0;j<=4;j++)
{
int unique = gen.nextInt(50)+1;
grades[j] = unique;
}
list.add(new Student(i, grades));
}
System.out.println(list);
My output:
Student1: 20 49 45 16 13
Student2: 28 10 11 30 6
Student3: 13 25 37 31 49
Student4: 8 23 8 12 32
Student5: 22 18 35 2 7
Student6: 35 8 16 23 36
Student7: 35 3 15 42 2
Student8: 43 12 44 2 35
Student9: 12 21 36 23 12
So my issue is this. How can I implement the random gen without repeating values. Normally I would try a collection list by now, but I'm trying to do this using java.util.Random Personally, I would do this a different way but I'm instructed. Thank you

Here's what I would do:
Take an ArrayList of numbers 1-50, then use Collections.shuffle on the list.

You could check if the number is unique before accepting it. For example you could try something like the following:
int count=0;
List<Integer> list=new ArrayList<Integer>();
while(count<50){
int num=random.nextInt(50);
if(!list.contains(num)){
list.add(num);
++count;
}
}

Related

How to get the top M values from a Map?

So I am writing this program, which calculates different things about the Collatz-conjucture.
So basically for a number I calculate a cycle and its length, like this:
For 8: [8, 4, 2, 1]
Length: 4
Now I want to calculate until 1000.
And for every number the length of the cycle is different.
So for example the length of the cycle for number 43 can be bigger than that for 45.
And I want to get the biggest lengths in ascending order.
Like this:
Number 1 2 3 6 7 9 1825 27 54 73 97 129 171 231 313 327 649 703 871
Length(N) 0 1 7 8 16 19 20 23 111 112 115 118 121 124 127 130 143 144 170 178
I put the numbers in HashMap with the numbers as keys and the lengths as values.
Now I have no clue how to get the biggest lengths in ascending order.
Is there a function that helps me with that?
Do I have to use a loop and more lists?
The Collections.Max is of no help, because it gets only one value, but I need more than one.
You should use any sorting algorithm, (like merge) and then pick the amount you'd like to get from the sorted map.
This amounts to essentially sorting a list composed of the map's values.
Returns the top m values of your Map, ascending:
public static List<Integer> topMValuesAscending(Map<?, Integer> map, int m){
final List<Integer> values = new ArrayList<Integer>(map.values());
Collections.sort(values);
final int valuesCount = values.size();
return values.subList(valuesCount - m, valuesCount);
}
I believe this is optimal, and is O[s*Log(s)] log-linear, where s is the size of the map.

Array Shuffle (With same Start and end Value)

I'm currently working on a Travelling salesman problem and i'm having trouble generating random paths with the same start and end value
This is my current path(path of cities visited)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 38 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 14 39 40 41 42 43 44 45 46 47 48 49 50 51 0
See how the last node arrives back at 0(TSP logic)
Now i'm trying to shuffle this array randomly because random start points generate better results then others However I know how to shuffle the array using Collections but that would shuffle every value randomly
Basically i'm trying to create a method to shuffle an array randomly WITH THE EXCEPTION THE START and END VALUES must be the same and every number must be distinct 0-51
This is my current code, it basically shuffles the array and sets the last index to the first index
static void shuffleArray(int[] ar)
{
// If running on Java 6 or older, use `new Random()` on RHS here
Random rnd = new Random();
for (int i = ar.length - 1; i > 0; i--)
{
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
ar[ar.length-1]=ar[0];
}
however this is giving me duplicate values for some reason
Could you not remove the start and end position, shuffle the array, and then add the start and end position again?

how to create a Java List of two integers

Hello I am new to java and I am trying to create a list like
List<Int, Int> list = new List<Int, Int>();
the first int is the value and the second int is the finished time. I want to be able to read from a file and save in my list, So can I later get the finished time or value list in a sorted way. I am going to ue these two list together so when the first one is sorted the second one also needs to be sorted accordingly.
If I use HashMap I cant add duplicate values, can someone help me please?
I tried with TreeMap but it also didnt work.
You should create a class to wrap your values. Something like:
public class IntPair {
public int value;
public int time;
}
should do. You can then add a constructor, a compare method for sorting, and whatever other functionality you need.
Create the list as follows:
List<IntPair> list = new ArrayList<>();
Using java inbuilt Pair class. ArrayList or any List of pairs can be constructed. you need to import javafx.util.pair for that. Similarly for 3 values. Use java's Triplet class.
eg: Pair p=new Pair(1, 2);
ArrayList or any List of these pairs can be constructed easily now
The 'lazy' way you could create an ArrayList<Integer[]> at each index you add an array of 2 places holding the value and the time ex new Integer[]{val,time} and then you can sort the arraylist using the Collection.sort and with the help of a Comparator
Here is a small example :
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Random;
public class Test {
public static void main(String[] args) {
ArrayList<Integer[]> values = new ArrayList<>();
Random rand = new Random();
// just for testing I add random values but you
// should add your values you read from your file
for (int i = 0; i < 10; i++) {
values.add(new Integer[] { rand.nextInt(100), rand.nextInt(100) });
System.out.println(values.get(i)[0] + "\t" + values.get(i)[1]);
}
// Let's sort our ArrayList looking at the first index of each array
// which holds the value
Collections.sort(values, new Comparator<Integer[]>() {
public int compare(Integer[] array1, Integer[] array2) {
return array1[0].compareTo(array2[0]);
}
});
// Print the results
System.out.println();
System.out.println();
for (int i = 0; i < 10; i++) {
System.out.println(values.get(i)[0] + "\t" + values.get(i)[1]);
}
}
}
Output :
82 21
3 54
60 73
14 35
45 30
16 30
8 19
62 43
67 51
7 34
3 54
7 34
8 19
14 35
16 30
45 30
60 73
62 43
67 51
82 21

How to split multiple tab delimited lines in Java if they all have a different number of columns?

I have a text file which is tab delimited, but there are a different number of columns on each line. Here is an example:
1 : 2 16 17 24 31 34 40 41 45 47 48
2 : 1 3 4 5 6 7 8 13 18 20 22 28 33 35 37 38 42 44 46 49
3 : 2 10 12 16 17 19 24 25 29 31 34 40 41 45
I want to use the split function, like I did here for a different assignment:
String[] words = line.split("\t");
col1 = Integer.parseInt(words[0]);
col2 = Integer.parseInt(words[1]);
col3 = Integer.parseInt(words[2]);
col4 = Integer.parseInt(words[3]);
This puts each column from a line into a different variable. I want to do the same but I'm not sure how to do this with a varying number of columns.
As said in the comments, you're quite good with what you've done. If you really want to have your Integer values stored somehow, you could simply use an Integer array, and fill it with a loop like this:
String[] words = line.split("\t");
int[] numbers = new int[words.length];
for (int i = 0; i < words.length; i++)
{
numbers[i] = Integer.parseInt(words[i]);
}
That whole thing being inside the loop you use to iterate your lines.
I don't think you need anything more complex than an array.

Memory error in java

I am trying to code in java prime number algorithm. I am trying to face the problems with the integer and long size. My simply code is the following which works until a limit for n:
public static long f(int n) {
if (n == 1 || n == 2)
return 1;
else {
long value = f(n-2) + f(n-1);
return value;
}
}
If in my main I ll give 50 for example my code will be crushed, I am guessing due to the size of the outcome. I ve got also another approach which I am struggle to understand it, which is the following:
private static long[] cache = new long[60];
public static long f(int n) {
if (n == 1 || n == 2)
return 1;
else if (cache[n] > 0)
return cache[n];
else {
long value = f(n-2) + f(n-1);
cache[n] = value;
return value;
}
}
With this approach everything works fine whatever is the n, my issue is that I cannot get the difference.
By "crushed" you mean that the computation runs very long. The reason is that the same call is made many times. If you add this to your method:
static long count;
public static long f(int n) {
count++;
...
you'll see how many times the method is executed. For f(50), it is actually calling the method 25,172,538,049 times, which runs in 41 seconds in my machine.
When you cache the result of previous invocations, called memoization, you eliminate all the redundant calls, e.g. f(40) = f(39) + f(38), but f(39) = f(38) + f(37), so f(38) is called twice. Remembering the result of f(38) means that subsequent invocation has the answer immediately, without having to redo the recursion.
Without memoization, I get this:
n f(n) count time(ns)
== ============== =============== ==============
1 1 1 6,273
2 1 1 571
3 2 3 855
4 3 5 1,141
5 5 9 1,425
6 8 15 1,140
7 13 25 1,996
8 21 41 2,851
9 34 67 7,413
10 55 109 16,536
11 89 177 8,839
12 144 287 19,103
13 233 465 21,098
14 377 753 11,405
15 610 1,219 5,703
16 987 1,973 9,979
17 1,597 3,193 21,099
18 2,584 5,167 32,788
19 4,181 8,361 35,639
20 6,765 13,529 57,307
21 10,946 21,891 91,521
22 17,711 35,421 147,687
23 28,657 57,313 237,496
24 46,368 92,735 283,970
25 75,025 150,049 331,583
26 121,393 242,785 401,720
27 196,418 392,835 650,052
28 317,811 635,621 1,053,483
29 514,229 1,028,457 1,702,679
30 832,040 1,664,079 2,750,745
31 1,346,269 2,692,537 4,455,137
32 2,178,309 4,356,617 12,706,520
33 3,524,578 7,049,155 11,714,051
34 5,702,887 11,405,773 19,571,980
35 9,227,465 18,454,929 30,605,757
36 14,930,352 29,860,703 51,298,507
37 24,157,817 48,315,633 84,473,965
38 39,088,169 78,176,337 127,818,746
39 63,245,986 126,491,971 208,727,118
40 102,334,155 204,668,309 336,785,071
41 165,580,141 331,160,281 543,006,638
42 267,914,296 535,828,591 875,782,771
43 433,494,437 866,988,873 1,429,555,753
44 701,408,733 1,402,817,465 2,301,577,345
45 1,134,903,170 2,269,806,339 3,724,691,882
46 1,836,311,903 3,672,623,805 6,010,675,962
47 2,971,215,073 5,942,430,145 9,706,561,705
48 4,807,526,976 9,615,053,951 15,715,064,841
49 7,778,742,049 15,557,484,097 25,427,015,418
50 12,586,269,025 25,172,538,049 41,126,559,697
If you get a StackOverflowError, it is due to the recursive nature of your algorithm. The second algorithm stores known results into an array to prevent functions piling up when it asks for an already computed result.
One of the problem can be the big number result, which is more than integer limit:
fibonacci for 50 =
12,586,269,025
2,147,483,647 - int max
and the other can be due to the recursion stackoverflow like #Xalamadrax pointed.

Categories