Generate 100 random UNIQUE Double numbers between 1-10 in java? [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I want to generate a 100 unique random numbers, but the numbers need to be in the range of 1-10.
Right now I am doing this:
for (int i = 0; i < 100; i++) {
Double n = rand.nextDouble(10) + 1;
arr[i] = n;
}
I could get Double numbers by checking if they're unique using if/else statements in arrays but it is very difficult and inefficient because the numbers(Doubles) could be almost infinite.
So how do i make sure the numbers are unique without using arrays?
Are there any data structures in java which do not allow duplicate elements?

As you alluded to in the comments, there's no way to generate 100 unique integers between 1 and 100. Using doubles allows you to do that, but does not guarantee uniqueness by itself (even though there's an infinitesimal chance of getting repeating items), so you would have to guarantee this yourself - e.g., by using a Set:
Set<Double> doubles = new HashSet<>();
while (doubles.size() < 100) {
doubles.add(1 + rand.nextDouble() * 9);
}
EDIT:
JDK 8 provides an arguably more elegant way of achieving this with streams:
List<Double> doubles =
rand.doubles()
.distinct()
.map(d -> 1 + d * 9)
.limit(100)
.boxed()
.collect(Collectors.toList());

You can use something like this.
import java.util.*;
public class MyClass {
public static void main(String args[]) {
double[] arr = new double[100];
for (int i = 0; i < 100; i++) {
Random rand = new Random();
double n = 10*rand.nextDouble();
System.out.println(n);
arr[i] = n;
}
}
}
But it is not possible to get unique 100 integers between 1-10.
The above program generate something like this
4.142037859604101
2.655156962359073
3.7397565068261205
2.9699181925544247
2.747362791293101
3.243100861992423
9.308481386292623
4.96298205308679
3.4319099852820822
9.951375372917328
3.6941158775736316
1.0388381644118727
1.6895078811799191
0.9166823110491484
9.60259797093202
2.3365812211691708
8.556399515524168
2.570971809286772
1.6621912919374215
0.5896588206170794
6.921688301938134
6.325470591144598
2.35492413118687
2.1778674294915454

The class Math has a bunch of useful functions, also at least one which you could use for this.
for(int i = 0; i < 100; i++) {
double n = (Math.random()*9) + 1;
arr[i] = n;
}
Math.random returns a random positive greater than or equal to 0.0 and less than 1.0, so if you multiply that by 9, you get a number greater than or equal to 0.0 and less than 9.0. And then the plus 1 is to make sure the range is between 1 - 10.
If you really want to make sure that all numbers are unique you could write a method that checks if the number is not already in the array.
Hopefully this helps you out. Good luck!

Related

Generating vampire numbers for a free range in Java (For big ranges) [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
A vampire number is a natural number with an even number of digits, that can be factored into two integers. These two factors are called the fangs, and must have the following properties:
they each contain half the number of the digits of the original number
together they consist of exactly the same digits as the original number
at most one of them has a trailing zero
An example of a Vampire number and its fangs: 1260 : (21, 60)
This is a simple code to generate vampire numbers 4 digits . How to modify this to generate vampire numbers for large numbers (100000,200000) efficiently
import java.util.Arrays;
public class Vampire
{
final static int START = 11, END = 1000;
public static void main(String[] args)
{
char[] kChar, checkChar;
String kStr, checkStr;
int k;
for(int i=START; i<END; i++) {
for(int i1=i; i1<100; i1++) {
k = i * i1;
kStr = Integer.toString(k);
checkStr = Integer.toString(i) + Integer.toString(i1);
kChar = kStr.toCharArray();
checkChar = checkStr.toCharArray();
Arrays.sort(kChar);
Arrays.sort(checkChar);
if(Arrays.equals(kChar, checkChar) ) {
System.out.println(i + " * " + i1 + " = " + k);
}
}
}
}
}
I came up with this, which is basically the same as your approach,
just adjusted for slightly "larger" ranges.
On my pc it takes less than 1 seconds to fully scan all vampiric numbers in the 8 digit range and around 80 seconds for the 10 digit range. Anything beyond that takes a while ...
I have also added in the elimination of two fangs with trailing zeroes, which was not mentioned in your definition.
import java.util.Arrays;
public class Vampire {
final static int START = 10, END = 10000;
public static void main(String[] args) {
for (int fangA = START; fangA < END; fangA++) {
String sFangA = String.valueOf(fangA);
boolean trailingZeros = sFangA.endsWith("0");
int max = (int) Math.min(END, Math.pow(10, sFangA.length()));
for (long fangB = fangA; fangB < max; fangB++) {
long candidate = fangA * fangB;
if (candidate % 9 == (fangA + fangB) % 9) {
String sCandidate = String.valueOf(candidate);
String sFangB = String.valueOf(fangB);
if ((trailingZeros && sFangB.endsWith("0")) == false) {
char[] cVampire = sCandidate.toCharArray();
Arrays.sort(cVampire);
char[] cFangs = (sFangA + sFangB).toCharArray();
Arrays.sort(cFangs);
if (Arrays.equals(cVampire, cFangs)) {
System.out.println(sFangA + " * " + sFangB + " = " + sCandidate);
}
}
}
}
}
}
}
You might also want to check this page. It contains an optimized c program and a description of the algorithm it is based on.
But it still took around 19 hours to compute all 14-digits vampiric numbers (back in 2002, might be a bit faster nowadays on a decent pc).
I noticed that the result for (fangA + fangB) % 9 always seems to be either 0 or 4. I image that it has something to do with the assumption from Pete Hartley, but I can't really explain that.
Using that knowledge allows one to optimize the inner loop, and skipping 7 out of 9 possible values. The results up to the 10 digits numbers were identical (I didn't test further than that), the time improvement is around 15% (~68 seconds).
[The linked page mentions only 6 out 81 pairs need to be tested, but I haven't figured out how to apply that]
EDIT:
START and END describe the search range for each fang (and not the vampire number). If you want to only have a specific range of vampire numbers then apply that to the results you get here. Unless you have a efficient way to generate the valid permutations of a vampire number this approach seems to be much faster.
Math.pow(10, sFangA.length()) is used to limit the search in the inner loop to fangB's with the same number of digits as fangA.
I've added the Math.min to ensure that fangB's range is also between START and END (before that fangB's range was always the complete fangA's-digit range).

Java finding all combos in array that add up to specific number [duplicate]

This question already has an answer here:
Finding all the number combos in array that add up to input number
(1 answer)
Closed 6 years ago.
I'm currently working on the following question from a interviewing book:
You are given a random array of 50 unique integers ranging from 1 to 100 inclusive. Write a method using Java that takes in a positive integer as a parameter and returns an array of all the number combinations that add up to that value.
For example, given an array of integers [3,6,1,9,2,5,12] and being passed the integer value 9, you would return [[3,6],[6,1,2],[9],[3,1,5]]. Order of returning the results in the array does not matter, though you should return unique sets (ie. [6,3] and [3,6] are the same and only one should be returned). Also, the individual results should be in the order they are found (ie [6,1,2] should be returned, not [1,2,6]).
I've made decent progress on it, but I fear I may solving this the wrong way.
import java.util.*;
public class findCombinations {
public static void main(String[] args) {
int number;
int[] list = new int[10];
Scanner reader = new Scanner(System.in);
//fill the array
for (int i = 0; i < list.length; i++) {
number = (int)(Math.random() * 10) + 1;
list[i] = number;
for (int j = 0; j < i; j++) { //remove duplicates
if (list[i] == list[j]) {
i--;
break;
}
}
}
Arrays.sort(list);
//test output
for (int i = 0; i < list.length; i++) {
System.out.println(list[i]);
}
System.out.println("Enter a number: ");
int input = reader.nextInt();
ArrayList<Integer> trimmedList = new ArrayList<Integer>();
//cut out the numbers that are impossible to use
for (int i = 0; i < list.length; i++) {
if (list[i] <= input) {
trimmedList.add(list[i]);
}
}
//test output
printList(trimmedList);
ArrayList<Integer> comboList = new ArrayList<Integer>();
System.out.println("Finding combinations...");
for (int i = 0; i < trimmedList.size(); i++) {
int current = trimmedList.get(i);
if (current == input) { System.out.println(current); }
else if (current < input) {
comboList.add(current);
if (isCombo(comboList, input)) {
printList(comboList);
}
else { continue; }
}
else { continue; }
}
}
public static boolean isCombo(ArrayList<Integer> list, int input) {
ArrayList<Integer> combo = new ArrayList<Integer>();
int sum = 0;
for (int i : list)
sum += i;
if (sum == input) { return true; }
else { return false; }
}
public static void printList(ArrayList<Integer> list) {
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i));
}
}
}
I know this is incomplete but I wanted to ask if anyone had any suggestions or improvements I could make on this? I sorted my list and trimmed out all the integers that won't possibly be used, but now the hard part is finding all the combos.
There are many different approaches to solve this problem, each with their own merits, so I wouldn't worry too much about whether your answer is the 'right' one or not...so long as it actually solves the problem! Also, an interviewer will likely be more interested in your thought-process, and the strategies you use, rather than a 100% perfect solution written in the span of a few minutes on a whiteboard.
Here's a couple of things to consider:
As you noticed, you can immediately eliminate any integers larger than your target value.
You're essentially generating arbitrarily-sized subsets of your starting array—so Set is likely the most useful data type to work with. {2, 3} and {3, 2} should be seen as identical when you're generating your response set.
Integer partitioning is an NP-Complete problem. It's hard. I think you've taken the correct approach of starting with the array, rather than with the target value.
There are many algorithms for generating combinations of integers from a larger set. Check out this SO answer for a few of them. You can generate k sized combinations from your (already-filtered) starting set, for k from 1-50.
Actually...there are more direct ways to get the power set of your starting set. Consider the inherent structure of a power set (shown below). By enumerating a few examples, you'll notice a natural recurrence in your strategy for identifying the subsets.
As you're generating these combinations, discard any whose elements don't sum to your target value.
Image Source: https://en.wikipedia.org/wiki/Power_set
Since this is a learning exercise, you will benefit most if you can solve this for yourself. So ...
Hints:
Sorting the numbers first is on the right track
I would use recursion to iterate the solutions. Given a partial sum, only numbers less than a certain number are possible candidates to be added to the sum ...
Work out the algorithm in your head >before< you start coding it.
And I agree with what #nbrooks says on the topic of what the interviewers are looking for. You need to be able to think ... and explain your thinking to the interviewer ... at the algorithmic level. That is what will distinguish the excellent candidates from the ordinary ones.
I realize generating your array of random numbers is not part of the problem statement, but I think your difficulties begin here.
First of all, use a Set<Integer> type collection to collect your generated numbers; break when the set reaches the desired size. If generated order is important, use a LinkedHashSet.
Set<Integer> origSet = new HashSet<Integer>(); // fill with random numbers
At some point, you have a list of numbers for which the order matters. Maintain this list as a List<Integer>. The list preserves the order of your original list so that you can produce the number combinations in the right order (i.e., 6 precedes 1, 1 precedes 2).
List<Integer> origList = new ArrayList<Integer>(origSet); // use indexOf method to find index of a number
You create a second list that is sorted; this list is the one used by your recursion algorithm.
List<Integer> sortedList = new ArrayList<Integer>(origList); // sort this
You don't need to trim the list because a recursive algorithm will trim any branch with no feasible solution.
A recursive algorithm can generate the combos in fewer lines of code. Reordering takes a few more lines.

Select 100 random lines from a file with a 1 million which can`t be read into memory [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Actually, this question was asked one of the interviews, I do not know the exact answer, could you explain in detail ?
How would you select 100 random lines from a file with a 1 million
lines? Can`t read file into memory.
Typically, in such scenarios, you do not know the number of items in the input file in advance (and you want to avoid requiring two passes over your data, to check the number of available items first). In that case the solution proposed by #radoh and others, where you will create indices to select from, will not work.
In such cases, you can use reservoir sampling: You only need to know the number of items you want to select (k as follows) and you iterate over the input data (S[1..n]). Below is the pseudocode taken from Wikipedia, I'll leave it to your practice to convert this into a working Java method (the method would typically look something like List<X> sample(Stream<X> data, int k)):
/*
S has items to sample, R will contain the result
*/
ReservoirSample(S[1..n], R[1..k])
// fill the reservoir array
for i = 1 to k
R[i] := S[i]
// replace elements with gradually decreasing probability
for i = k+1 to n
j := random(1, i) // important: inclusive range
if j <= k
R[j] := S[i]
Note that although the code mentions n explicitly (i.e. the number of input items), you do not need to know that value prior to computation. You can simply iterate over an Iterator or Stream (representing lines from a file in your case) and only need to keep the result array or collection R in memory. You can even sample a continuous stream, and at each point in time (at least, as soon, as you've seen k samples) you have k randomly chosen items.
Generate the 100 random (unique) numbers (ranging from 0..1000000-1) into a list and then go through the file reading the lines with indexes from the list. Ideally, the list of numbers should be a Set.
Pseudocode:
int i = 0;
List<String> myLines = new ArrayList();
while (fileScanner.hasNext()) {
String line = fileScanner.nextLine();
if (myRandomNumbers.contains(i)) {
myLines.add(line);
}
i++;
}
Here's a pretty efficient way to do it:
Iterator<String> linesIter = ...
List<String> selectedLines = new ArrayList();
Random rng = new Random(seed);
int linesStillNeeded = 100;
int linesRemaining = 1000000;
while (linesStillNeeded > 0) {
String line = linesIter.next();
linesRemaining--;
if (rng.nextInt(linesRemaining) < linesStillNeeded) {
selectedLines.add(line);
linesStillNeeded--;
}
}
I haven't coded in Java in a while, so you might want to treat this as pseudo-code.
This algorithm is based on the fact that the probability that any given line (assuming we are uniformly selecting k distinct lines out of a total of n lines) will be contained in the collection with probability k/n. This follows from
1) the number collections of k distinct lines (out of n lines) is choose(n, k),
2) the number of collections of k distinct lines (out of n lines) which contain a particular line is choose(n-1, k-1), and
3) choose(n-1,k-1)/choose(n,k) = k/n
Note that k and n here correspond to linesStillNeeded and linesStillRemaining in the code respectively.

Select a random int that doesn't exist [duplicate]

This question already has answers here:
Generating Unique Random Numbers in Java
(21 answers)
Closed 8 years ago.
I am doing something where I have to choose a couple random numbers, without choosing the same number again. I have tried many ways, but they will not work. I checked if the random number exists in my int[], and reset the int to another random, but what is that other random also exists, I tried fixing that but I ran into problems.
Here's my current code:
p.sendMessage("debug over max");
Random r = new Random();
for (int i=0;i<max + 1;i++) {
int ran = r.nextInt(arenaAmount);
if (ran == 0) ran = 1;
arenas[i] = ran;
}
Thats what I have so far,
so how can I make sure it doesn't have the same number. If there is another thread already please link me to it.
Thanks, Joey.
A simple solution would be to add the already generated numbers to a Set and generate random numbers until you hit one that isn't already in that Set.
But that's probably not a very good solution, check the accepted answer here for a thorough explanation.
As mentioned by Giovanni Botta in the comments, here's another simple solution that's probably better than the Set based one.
make a arenas a Set
Random r = new Random();
int ran = r.nextInt();
while( ! arenas.add(ran) ) {
ran = r.nextInt();
}
add will fail on an attempted re-entry of a value.
You could create a list of integers from 1 to maxValue, shuffle it and get the numElements first elements:
List<Integer> shuffledList(int maxValue, int numElements) {
if (numElements >= maxValue) {
throw new IllegalArgumentException("The number of elements in the list must be less than maxValue.");
}
List<Integer> numbers = range(1, maxValue);
Collections.shuffle(numbers);
return numbers.subList(0, numElements);
}
List<Integer> range(int from, int to) {
List<Integer> numbers = new ArrayList<>(to - from);
for (int i = from; i < to; i++) {
numbers.add(i);
}
return numbers;
}
This way, you are sure to get different numbers without the Set overhead. Making a call like shuffledList(10, 5) would, for example, return a list like [8, 7, 5, 1, 2], with 5 elements, where the smallest possible element is 1 and the greatest possible element is 9.
Also, if you are using Java 8 you can discard the range function and do this instead:
List<Integer> numbers = IntStream.range(1, maxValue)
.boxed()
.collect(Collectors.toList());

Generating Random integers within a range to meet a percentile in java

I am trying to generate random integers within a range to sample a percentile of that range. For example: for range 1 to 100 I would like to select a random sample of 20%. This would result in 20 integers randomly selected for 100.
This is to solve an extremely complex issue and I will post solutions once I get this and a few bugs worked out. I have not used many math packages in java so I appreciate your assistance.
Thanks!
Put all numbers in a arraylist, then shuffle it. Take only the 20 first element of the arraylist:
ArrayList<Integer> randomNumbers = new ArrayList<Integer>();
for(int i = 0; i < 100; i++){
randomNumbers.add((int)(Math.random() * 100 + 1));
}
Collections.shuffle(randomNumbers);
//Then the first 20 elements are your sample
If you want 20 random integers between 1 and one hundred, use Math.random() to generate a value between 0 and 0.999... Then, manipulate this value to fit your range.
int[] random = new int[20];
for(int i =0; i< random.length;i++)
{
random[i] = (int)(Math.random()*100+1);
}
When you multiply Math.random() by 100, you get a value between 0 and 99.999... To this number you add 1, yielding a value between 1.0 and 100.0. Then, I typecasted the number to an integer by using the (int) typecast. This gives a number between 1 and 100 inclusive. Then, store the values into an array.
If you are willing to go with Java 8, you could use some features of lambdas. Presuming that you aren't keeping 20% of petabytes of data, you could do something like this (number is the number of integers in the range to get) it isn't efficient in the slightest, but it works, and is fun if you'd like to do some Java 8. But if this is performance critical, I wouldn't recommend it:
public ArrayList<Integer> sampler(int min, int max, int number){
Random random = new Random();
ArrayList<Integer> generated = new ArrayList<Integer>();
IntStream ints = random.ints(min,max);
Iterator<Integer> it = ints.iterator();
for(int i = 0; i < number; i++){
int k = it.next();
while(generated.contains(k)){
k = it.next();
}
generated.add(k);
}
ints.close();
return generated;
}
If you really need to scale to petabytes of data, you're going to need a solution that doesn't require keeping all your numbers in memory. Even a bit-set, which would compress your numbers to 1 byte per 8 integers, wouldn't fit in memory.
Since you didn't mention the numbers had to be shuffled (just random), you can start counting and randomly decide whether to keep each number or not. Then stream your result to a file or wherever you need it.
Start with this:
long range = 100;
float percentile = 0.20f;
Random rnd = new Random();
for (long i=1; i < range; i++) {
if (rnd.nextFloat() < percentile) {
System.out.println(i);
}
}
You will get about 20 percent of the numbers from 1 to 100, with no duplicates.
As the range goes up, the accuracy will too, so you really wouldn't need any special logic for large data sets.
If an exact number is needed, you would need special logic for smaller data sets, but that's pretty easy to solve using other methods posted here (although I'd still recommend a bit set).

Categories