How to auto generate overlapping integers in a certain range - java

If the number range is 0 - 10. I would like to generate the following numbers
e.g.
unique 5 numbers [3, 8, 5, 1, 9]
unique 3 numbers [2, 6, 5]
5 numbers of which 2 numbers occur twice [2, 3, 2, 6, 3]
7 numbers of which 2 numbers occur twice [2, 5, 9, 2, 7, 5, 3] (Here 2, 5 occur twice)
5 numbers of which 1 number occur thrice [2, 3, 8, 3, 3] (Here 3 occurs twice)
7 numbers of which 1 number occur thrice and 1 number occurs twice [1, 5, 9, 1, 1, 5, 3] (Here 1 occurs thrice, 5 occurs twice)
How would you implement a generic function which caters to the above requirements.
EDIT1:
This is what I have right now..
protected List<Integer> fetchOverlapIntegers(int min, int max,
int howMany, int overlap) {
// The following code fetches unique numbers within the range
List<Integer> numbers = this.fetchRandomIntegers(min, max, howMany);
if (overlap > 0) {
int size = numbers.size();
for (int i = 0; i < overlap; i++) {
numbers.set(size - 1 - i, numbers.get(i));
}
}
Collections.shuffle(numbers);
return numbers;
}

Just for grins I wrote this up for this very underspecified problem:
public static List<Integer> weirdFunction(List<Integer> criteria, List<Integer> candidateNumbers) {
List<Integer> results = new ArrayList<Integer>();
for (int occurrenceCount = 0; occurrenceCount < criteria.size(); occurrenceCount++) {
int thisMany = criteria.get(occurrenceCount);
for (int i=0; i < thisMany; i++) {
Integer theChoice = candidateNumbers.get(new Random().nextInt(candidateNumbers.size()));
for (int ct=0; ct < occurrenceCount; ct++) {
results.add(theChoice);
}
}
}
Collections.shuffle(results);
return results;
}
It takes two lists, one which is the criteria which is basically a list of how many times it'll place a randomly chosen number in the results (the 1st one gets chosen once, the 2nd twice, etc.), and a list of candidateNumbers from which they'll be chosen.
But, this way only allows you to specify one particular "count" for each criteria. e.g. you can't have a list where "two numbers appear twice" because "appear twice" only has one slot. You could make this a list of lists or some other data structure of course.
Also, it doesn't eliminate duplicates when it pulls them in. So if we had a criteria of {1, 1, 1} it'd try and pull one number once, one number twice, and one number thrice. But it doesn't check if any of those are the same number - so it could end up pulling the same number each time and effectively pulling just one number six times instead of 3 separate numbers once, twice, and thrice.

You can randomly pull out items from the list of contender values, for example:
List<int> numbers = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Random r = new Random();
for (int i = 0; i < 4; i++)
{
int index = r.Next() % numbers.Count;
Console.WriteLine(numbers[index]);
numbers.RemoveAt(index);
}
If you want a value tripled, just triple the first removed. Then shuffle your results at the end.

Related

Java arrays question with multiple answers

I have a java problem at codewars.
In this kata, you will write a function that returns the positions and
the values of the "peaks" (or local maxima) of a numeric array.
For example, the array arr = [0, 1, 2, 5, 1, 0] has a peak at
position 3 with a value of 5 (since arr[3] equals 5).
The output will be returned as a Map<String,List>with two key-value pairs:"pos"and"peaks". If there is no peak in the given array, simply
return `{"pos" => [], "peaks" => []}.
Example: pickPeaks([3, 2, 3, 6, 4, 1, 2, 3, 2, 1, 2, 3]) should
return {pos: [3, 7], peaks: [6, 3]} (or equivalent in other
languages)
All input arrays will be valid integer arrays (although it could
still be empty), so you won't need to validate the input.
The first and last elements of the array will not be considered as
peaks (in the context of a mathematical function, we don't know what
is after and before and therefore, we don't know if it is a peak or
not).
Also, beware of plateaus! [1, 2, 2, 2, 1] has a peak while [1, 2, 2, 2, 3] and [1, 2, 2, 2, 2] do not. In case of a plateau-peak,
please only return the position and value of the beginning of the
plateau. For example: pickPeaks([1, 2, 2, 2, 1]) returns {pos: [1], peaks: [2]} (or equivalent in other languages)
Here is my answer:
public static Map<String, List<Integer>> getPeaks(int[] arr) {
HashMap<String, List<Integer>> stringListHashMap = new HashMap<>();
List<Integer> positions = new ArrayList<>();
List<Integer> values = new ArrayList<>();
values.add(arr[1]);
positions.add(1);
for (int i = 2; i < arr.length - 1; i++) {
if (values.get(values.size() - 1) < arr[i]) {
values.clear();
positions.clear();
values.add(arr[i]);
positions.add(i);
}
}
stringListHashMap.put("pos", positions);
stringListHashMap.put("peaks", values);
return stringListHashMap;
}
The above code works fine, but I don't pass the unit tests because of this ->
should support finding peaks expected:<{pos=[3, 7], peaks=[6, 3]}> but was:<{pos=[3], peaks=[6]}>
I have narrowed down the problem to this ->
Example: pickPeaks([3, 2, 3, 6, 4, 1, 2, 3, 2, 1, 2, 3]) should return {pos: [3, 7], peaks: [6, 3]} (or equivalent in other languages)
There is clearly only one peak which is 6 and its index 3. Then what is the person asking the question trying to say? I feel like I'm missing something.
The question is asking for local maxima, not global maxima. If a value is larger than its neighbours (and is not the first or last value), it's a peak, even if there is another value elsewhere that is even greater. Hence, with the input [3, 2, 3, 6, 4, 1, 2, 3, 2, 1, 2, 3], the eighth value (pos 7) is a peak, since the value 3 is greater than both the preceding neighbour (2) and following neighbour (2).
From what I understand, peak is surrounded by valley. So if you go up than down you have a peak, if you again go up and again down you have another peak. If you go up and than horizontal and than down, first position is peak, you just walk on plateau. It's like when you go mountain. You can climb 2 or 3 peaks in one trip.
Here is the solution:
public static Map<String, List<Integer>> getPeaks(int[] arr) {
Map<String, List<Integer>> result = new HashMap<>();
int peak = 0;
for (int i = 1; i < arr.length - 1; i++) {
if (arr[i-1] < arr[i]){
peak = i;
}
if(arr[i] > arr[i+1] && peak !=0) {
result.computeIfAbsent("pos", k -> new ArrayList<>()).add(peak);
result.computeIfAbsent("peaks", k -> new ArrayList<>()).add(arr[i]);
peak = 0;
}
}
return result;
}
I had to keep the current peak, as you can go horizontal and we need first position when you reach peak.
And I reset it when I go down.
So if arr[i-1] < arr[i] it means I reach a peak and if arr[i] > arr[i+1] && peak !=0 it means I went down.
Another mention, use Map as reference instead of HashMap. Same as you proceed for List.

What is the Nth card after k piles?

You have 100 cards, numbered 1 to 100. You distribute them into k piles and collect back the piles in order. For example, if you distribute them into 4 piles, then the first pile will contain the cards numbered 1, 5, 9, … and the 4 th pile will contain the cards numbered 4, 8, 12, …. While collecting back the cards you collect first the last pile, flip it bottom to top, then take the third pile, flip it bottom to top and put the cards on top of the 4th pile and so on. Next round, you distribute the cards into another set of piles and collect in the same manner (last pile first and first pile last).
If we have 10 cards, and put them into 2 piles, the order of the cards in the piles (top to bottom) would be 9, 7, 5, 3, 1 and 10, 8, 6, 4, 2
We flip the piles to get the order 1, 3, 5, 7, 9 and 2, 4, 6, 8, 10
We put the second pile at the bottom and first on top of it to get the deck 1, 3, 5, 7, 9, 2, 4, 6, 8, 10
Given the number of rounds (m), the number of piles in each round (ki), you need to write a program to find the Nth card from the top at the end of the final round.
Input:
The input consists of a single line of (m+2) comma-separated integers.
The first number is m, the number of rounds. The next m numbers are ki which represent the number of piles in each round.
The last number in the input is N, the position in the final pile whose value is to be determined.
Output: One integer representing the Nth card after all rounds have been played.
Constraints: Number of rounds <= 10, number of piles in each round <= 13.
Example 1
Input: 2, 2, 2, 4
Output: 13
Explanation:
m = 2, k1 = 2, k2 = 2 and N = 4.
We have two rounds. The first round has two piles. At the end of the round, the deck is in the following order: 1, 3, 5, …, 99, 2, 4, 6, …, 100
The next round also has 2 piles and after the second round, the cards are in the order 1, 5, 9, 13, ….
The fourth card from the top has number 13.
Example 2
Input: 3, 2, 2, 3, 2
Output: 13
Explanation:
m = 3, k1 = 2, k2 = 2, k3 = 3 and N = 2.
After the second round, the cards are in the order 1, 5, 9, 13, …
The third round has 3 piles. Thus after this round the cards will be in the order 1, 13, …. the Second card is 13
package leetcode;
import java.util.*;
public class Cards {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int arr[] = new int[100];
int temp[] = new int[100];
for(int i=0;i<100;i++)arr[i]=i+1;
int m = sc.nextInt();
for(int i=0;i<m;i++) {
int k = sc.nextInt();
int j=0,count=0;
while(count < k) {
for(int l=count;l<100;l=l+k) {
temp[j] = arr[l];j++;
}
count++;
}
for(int i1=0;i1<100;i1++) {
//System.out.print(temp[i1] + " ");
arr[i1] = temp[i1];
}
System.out.println("\n");
}
int res = sc.nextInt();
System.out.println(arr[res-1]);
}
}

Java change the position of integers in an array

I have to introduce 10 integers in an array. For example int A[] = {1,2,3,4,5,6,7,8,9,10}. Then I have to print the array in normal order which is fine, and after I have to make each element of the array hop over to the next position and the last element to the first position. Assuming we have the same integers in the array as before the result would be this: A[] = {10,1,2,3,4,5,6,7,8,9}
Here's my code so far but I get the out of bounds error. Also I don't know how to flip the last element to the first position
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int A[] = new int[10];
System.out.println("Introduce the array numbers");
for (int i = 0; i < 10; i++) {
A[i] = sc.nextInt();
}
//array in normal order
for (int i = 0; i < 10; i++) {
System.out.print("["+A[i]+"]");
}
//here i have to print the modified array
System.out.println("");
for (int i = 0; i < 10; i++) {
System.out.print("["+A[i+1]+"]");
}
}
As stated, the goal is to start with this array:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
And to modify it such that you wind up with this:
[10, 1, 2, 3, 4, 5, 6, 7, 8, 9]
What you are doing here, in essence, is pushing every number one spot to the right. The right-most number, when "pushed one spot to the right", will wrap around to the start of the array.
If we start by just taking the first number and copying it to the right, we run into a problem. The start of the array [1, 2] is now [1, 1]... which means we no longer know what number to push forward into the third slot. In other words, if we just blindly started at the beginning of the array and pushed numbers to the right, we'd wind up with this:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
The best way to solve this issue is to do our work starting at the end of the array, and then to work backwards. So first we push the 9 over to the right, then the 8, and so on.
Once we do that, the only problem is what we do with the first position. If we just moved everything over by one, we'd have this:
[???, 1, 2, 3, 4, 5, 6, 7, 8, 9]
To make matters worse, we might actually crash the program by trying to acces the "negative one-th" element to move it over to the zero index.
The best way around this is to break our problem up into three steps:
Save the last number in the array for later
For each position, starting from the end and working back to the second position, set the number to be equal to the number at the position before it
Set the first number in the array to the saved "last" number
Here's what that looks like in code:
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int last = numbers[numbers.length - 1]; // last now stores 10
// for index 9 to index 1, copy numbers to the right
for (int i = numbers.length - 1; i > 0; --i) {
numbers[i] = numbers[i - 1];
}
numbers[0] = last; // the first number is now 10

find unique elements from sorted array with complexity < O(n) [duplicate]

This question already has answers here:
Finding unique numbers from sorted array in less than O(n)
(5 answers)
Closed 8 years ago.
An interveiewer asked me below question:
Search out unique integer values(approx. 1000) from a sorted array of billion records(like 1,1,1,1,3,3,3,4,5,5,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8...........) with complexity less than O(n).
NOTE: NOt to use SET.
One solution that i tried to implement:
Divide that array into two set of arrays,then iterate both subarrays and search in hashmap if element doesnot exit,then add it into hashmap otherwise move to next iteration.
public static void main(String[] args) {
int arr[] = {1,2,4,9,-3,5,6,3,6,12,5,6,2,-1,-3,6,87,9,2,3,5,7,9,1,0,1,3,5,7,6,3,8,6,3,21,45,6};
int size1 =0, size2 = 0;
HashMap<Integer, Integer> map = new HashMap<Integer,Integer>();
System.out.println("length of Array:"+arr.length);
if((arr.length)%2 == 0){
size1 = size2 = arr.length/2;
}else{
size1 = (arr.length + 1)/2;
size2 = (arr.length)/2;
}
for(int i=0;((size1-i-1)>= 0)||((size2+i)<(arr.length - 1));i++){
if(map.containsKey(arr[size1 -i-1])== false){
map.put(arr[size1 -i-1],arr[size1 -i-1]);
}
if(map.containsKey(arr[size2 + i]) == false){
map.put(arr[size2 + i], arr[size2 + i]);
}
}
System.out.println(map.keySet());
}
And its working as expected, then he asked what if we divide the array into n sets?
then the complexity would be O(1) or O(n/n)? Is it possible?
Please suggest if there is another way to implement the same without using hashmap?
I'd try a binary search based approach, start from the middle element - if it's identical to one of the edges, then you can use the fact the array is sorted and eliminate that half. If it's different from each of the ones on the edges - divide the array into halves and proceed on each of them recursively.
This is still O(n) in the worst case, but on average it may be better then passing over the entire array (especially if there are many repetitions)
example -
1 1 1 1 1 2 2 2 2
could be done in two steps
why don't you use a Set instead of Map. Anyways, Set does not allow duplicate elements.
public static void main(String[] args) {
int arr[] = { 1, 2, 4, 9, -3, 5, 6, 3, 6, 12, 5, 6, 2, -1, -3, 6, 87,
9, 2, 3, 5, 7, 9, 1, 0, 1, 3, 5, 7, 6, 3, 8, 6, 3, 21, 45, 6 };
Set<Integer> aset = new HashSet<Integer>();
System.out.println("length of Array:" + arr.length);
for (int i : arr) {
aset.add(i);
}
System.out.println(aset);
}

Divide a group into subgroups of size k

I am stuck with one problem :
Finding all the possible ways of dividing a group of size 'n' into subgroups of size 'k'. (here n%k =0)
e.g., let set be {1,2,3,4,5,6} to divide into subgroups of 3 (k = 3,n = 6), possible sets are
a) {1,2,3},{4,5,6}
b) {1,3,5},{2,4,6}
c) {1,3,6},{2,4,5}
d) {1,3,4},{2,5,6} etc....
What i tried doing was, to first find all the combination of size k from the set.
Then loop through these combinations and find out which all combinations can be grouped together to find the list of subgroups.
But I believe the time complexity is pretty bad in this approach. Is there any better approach for this problem?
I would use a recursive method. I think this one has the optimal running time, since it exactly produces all needed subsets.
public static void solve(int[] a, int k, int i, List<List<Integer>> subsets) {
if (i == a.length) {
for (List<Integer> subset : subsets) {
System.out.print(subset);
}
System.out.println();
} else {
// loop over all subsets and try to put a[i] in
for (int j = 0; j < subsets.size(); j++) {
if (subsets.get(j).size() < k) {
// subset j not full
subsets.get(j).add(a[i]);
solve(a, k, i+1, subsets); // do recursion
subsets.get(j).remove((Integer)a[i]);
if (subsets.get(j).size() == 0) {
// don't skip empty subsets, so you won't get duplicates
break;
}
}
}
}
}
Usage:
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5, 6};
int k = 3;
List<List<Integer>> subsets = new ArrayList<List<Integer>>(a.length / k);
for (int i = 0; i < a.length / k; i++)
subsets.add(new ArrayList<Integer>(k));
solve(a, k, 0, subsets);
}
Prints:
[1, 2, 3][4, 5, 6]
[1, 2, 4][3, 5, 6]
[1, 2, 5][3, 4, 6]
[1, 2, 6][3, 4, 5]
[1, 3, 4][2, 5, 6]
[1, 3, 5][2, 4, 6]
[1, 3, 6][2, 4, 5]
[1, 4, 5][2, 3, 6]
[1, 4, 6][2, 3, 5]
[1, 5, 6][2, 3, 4]
Think about it combinatorially. If n % k != 0, you can't do it because you'll end up with one set that has less than k elements, so start off with checking whether that is the case.
Afterwards, all you need to do is recursively produce k-combinations from an n-i*k set for all i in [0; n/k]. Algorithms for producing all k-combinations of a given set can be found on SO easy enough. The idea is: there are (n choose k) possible such sets you can choose for your first set; from the remaining n-k elements, you can choose ((n-k) choose k) sets); from the remaining n-2k elements, you can choose ((n-2k) choose k) sets and so on. Assuming the order of your sets doesn't matter, you have (n choose k) * ((n-k) choose k) * ... * ((n-(n-1)k) choose k) / ((n/k)!) possibilities to choose your sets, which depending on k can be exponential in the number of elements your original set has, so if you really want to produce each and every one of them, you won't get below exponential complexity.
I found a formula for the # of possible subgroupings, in case anyone finds it interesting. (Would this be considered too off-topic? Am I posting this correctly?)
First let m = n/k be the # of subgroups. Now let the first subgroup be fixed as the first k elements of the group, the second subgroup be the next k, and so on. If we consider all possible permutations of the group, this will give us all the different subgroupings. There are n! permutations of the n elements, but we don't care about ordering, so we factor out the k! permutations of each of the m subgroups and the m! permutations of the subgroups themselves. This gives us:
n!/(m!*(k!)^m).
As a check, if k = 1 or k = n, this gives us 1 subgrouping. In the original example, n = 6, k = 3, m = 2, and we get 10 possible subgroupings (which Heuster's code found).
Now, if you compare this expression to the one G. Bach gave and use (n choose k) = n!/(k!*(n-k)!), you will see that all the (n-k)! terms cancel and it reduces to the expression above.
Bonus: if you use Stirling's approximation for n!, then the expression simplifies nicely, and you get that the # of subgroupings scales as (m^n)/m!.

Categories