generate random order but with constraint in java - java

When I put a integer list, how can I generate another random order but with constraint?
For example, I put integer 1, 2, 3, 4 into the collection and when I try to print result like be "1 2 3 4","1 2 4 3","1 3 2 4" ,"2 1 3 4",or "2 1 4 3"(1 must before 3, 2 must before 4)
thanks in advance

One thing you can consider is swapping elements at random. You could pick a random position in your collection, then swap the element in that position with the next element. This way, you can prevent swapping 1 with 3, or 2 with 4. You can do this repetitively, until the numbers are properly scrambled:
[1, 2, 3, 4] random number is 0, swap with element at position 1.
[2, 1, 3, 4] random number is 1, swap with element at position 2.
elements are 1 and 3, so don't swap.
[2, 1, 3, 4] random number is 2, swap with element at position 3.
[2, 1, 4, 3] etc.
If you'd like to generalize the constraint, you can simply change the condition. Instead of refusing to swap when the elements are either 1 and 3, or 2 and 4 (as in the example above), you could make sure the two elements at the positions to be swapped are not within 2 of each other, so something like if(b==a+2)continue;:
elements are 5 and 7, so don't swap.
if(7==5+2)continue; // ie don't swap.

What you've defined here is known as a partial order. You wish to generate a random permutation which still satisfies the partial order, i.e. a random linear extension.
Luckily, the Java API specifies Collections.shuffle, which implements the Fisher-Yates algorithm to generate a random permutation.
Unfortunately, the standard Java technique via Collections.sort is a comparison sort, and thus focused on total orders -- unlike the partial order we want. In fact, the Java API lacks a sorting algorithm we could use here.
One approach covered in "Generating Linear Extensions of Posets by Transpositions" involves that of swapping adjacent elements in the set in a fashion similar to Hassan's solution. This appears to be a functioning way for the localized problem at hand.

If you use it as a string then you could use this answer's algorithm to swap all the numbers
When you enter all the numbers then just concatenate them together. There is no need to treat them as numbers or strings. All you want to do is reorder them.
When you get the result you could then check to see if your constraints match and then print out another list. Something like this perhaps
private boolean isConstraintSatisfied(String wholeString, String firstNum, String secondNum){
return wholeString.indexOf(firstNum) <= wholeString.indexOf(secondNum);
}
Not the most elegant solution but I think it would work. For small input sets it shouldnt be too inefficient.

Related

Equal elements in a Array

Today I had Interview where I was asked one problem, and I couldnt even understand.
Problem:
Given one array 𝑎 consisting of 𝑛 integers.
Get at least 𝑘 equal elements in the array 𝑎.
While calculating, you can do below two operations
Take one of the minimum elements of the array and increase its value by one (more formally, if the minimum value of 𝑎 is 𝑚𝑛 then you choose such index 𝑖 that 𝑎𝑖=𝑚𝑛 and set 𝑎𝑖:=𝑎𝑖+1);
take one of the maximum elements of the array and decrease its value by one (more formally, if the maximum value of 𝑎 is 𝑚𝑥 then you choose such index 𝑖 that 𝑎𝑖=𝑚𝑥 and set 𝑎𝑖:=𝑎𝑖−1).
Calculate the minimum number of moves required to obtain at least 𝑘 equal elements in the array.
Can anyone help me to undestand, what's a actual problem is about so that I could write code ?
To answer your question directly, which is "Help me understand the problem":
For example, here's your array:
{1,2,5,7,8,3}
Now, you can do only those two operations:
Find the minimum element and increase it:
{2,2,5,7,8,3} // <-- increased 1
Decrease the maximum element:
{2,2,5,7,7,3} // <-- decreased 8
And the question now is: What is the minimum number of moves to make this array contain k identical numbers?
So if k = 3 and the array is like the above, then one of the solutions would be to run operation 1 three times:
Before any moves:
{1,2,5,7,8,3}
After first move:
{2,2,5,7,8,3} // <-- `1` changed to `2`
After second move:
{3,2,5,7,8,3} // <-- `2` changed to `3`
After third move:
{3,3,5,7,8,3} // <-- `2` changed to `3`
So the resulting array would be:
{3,3,5,7,8,3}
Do you understand the problem now?
In terms of the algorithm to find k equal elements:
At any given step in the algorithm, there are some number of equal elements, say j. If j >= k, you're done. Otherwise, you need to choose some combination of the moves to increase j.
You don't have much flexibility in what you can do. You can only reduce a maximal element, or increase a minimal element.
Let's say there is a unique maximal element (i.e. when there is only one element in the array equal to the maximum element). You can increase j by (at least) 1 by reducing that until it equals the second-largest element.
Similarly, you can increase j by (at least) 1 by increasing a unique minimal element (i.e. when there is only one element in the array equal to the maximum element) until it equals the second-smallest element.
Therefore, the smallest number of moves to achieve the (at least) 1 increase is the one out of [decrease the maximal; increase the maximal] which achieve this.
For example, in the array [1, 3, 5, 6], your choices are:
Take 2 moves to increase the 1 so it equals 3: [3, 3, 5, 6]
Take 1 move to decrease the 6 so it equals 5: [1, 3, 5, 5]
In this case, you increase j by 2 most cheaply by decreasing the 6.
But after doing that, there are equal maximal elements: there are two elements equal to 5. By decreasing one of these, you decrease j by 2 (because [1, 3, 4, 5] has no equal elements); but by decreasing the maximum again, you make j the same as it was before (because [1, 3, 4, 4] again has 2 equal elements). So, you've got to do some work to "stand still" (that is, get j back to its previous value), before you can then decrease the maximum to increase j.
(Similarly for the minimal elements)
So, your algorithm can find the (greedy) minimum number of steps to make j == k by deciding whether to [decrease the maximal elements] or [increase the minimal element]. I don't know if the greedy minimum is actually the minimum, but I can't think of an obvious algorithm to find it non-greedily, other than searching all possibilities, which would have awful computational complexity, so is probably not what this interview was looking for.

Optimizing this solution: Longest consecutive distinct sequence of integers

Sample input:
5
1
2
1
3
1
First number = # of members in the set, N
Following N numbers = ID's of the members
I'd have to find the size of the longest consecutive sequence of distinct integers in the set. In this instance, it'd be the sequence of {2, 1, 3}, so the output would be 3.
My brute force solution would be to generate a sliding window that shrinks in size by 1 every iteration. The initial size is the size of the input. So, for the sample input, it'd evaluate {1, 2, 1, 3, 1} first, if set is not all unique, then decrease the window to 4, and evaluate {1, 2, 1, 3}, {2, 1, 3, 1}. Keep going until you found a set that's unique.
For one, I believe this algorithm would be O(N^2) time. So, how might I optimize this?
You can use a hash table for an O(N) solution. Simply put, keep track of the last index of each unique element and the last time a repetition happens. The maximum between these two variables at each index is how far back you can go at that index without repeating.
For sake of completeness here is a straightforward and (hopefully) well commented python implementation:
def longestDistinctSequence(iterable):
res = 0
# store the indices of each unique element
hashmap = {}
# keep track of how back you can go before you run into a repetition
last_repeat = 0
# loop through each index and item
for index, item in enumerate(iterable):
# how back you can go before you can run into a repetition is the max of:
# 1. The last occurence of this element (zero if this is first instance)
# 2. The last_repeat of the last iteration
last_repeat = max(hashmap.get(item, 0), last_repeat)
# calculate the global maximum
res = max(res, index - last_repeat + 1)
# update the hashmap to reflect the repetition of this element
hashmap[item] = index + 1
return res

Obtaining the absolute difference between consecutive elements in an array, and returning which difference occurred the most

So if there's an array like [2, 3, 5, 7, 11], the differences would be 1, 2, 2, 4, therefore you'd return 2.
Brute force would be to just iterate over the initial structure, store each calculated difference in a new structure, and count the most number of occurrences of an element in that new structure.
I'm wondering if there's a different, better way to do this, or if that solution would be considered efficient?
That solution will be efficient, if implemented "properly". If you're using a package with a vectorized array type, then use the shift operation to get the vector of differences. That's O(N) with or without the vectorization.
A second linear pass will find the mode of the array, yielding your final answer. Keep a simple array to count how many times each value appears:
for item in diff_array:
mode_ct[item] += 1
Then find the max of mode_ct; return its index.

How to determine if 3 out of 5 numbers match in java?

I have 5 numbers randomly generated by "dice" which are all 10, 2, 3, 4, 5, or 6. Is there a way I could determine whenever 3 of the 5 generated numbers are all the same(a roll of 4, 4, 4, 5, 2 or a roll of 10, 3, 5, 3, 3 for example)?
I could use a series of nested if statements but is there a simpler way that I'm missing?
This is a simple algorithm question, and you should understand how to write such an algorithm as well as how it will behave in different situations.
Don't use nested if statements. That will be hard to maintain, especially if the code has to change. Try to create generalized algorithms.
I don't know the requirements of your answer completely, so I'll answer it in two ways.
If ordering does not matter:
Create a dictionary of integer to integer. (Java calls this a Map. You can use HashMap in your case.) The key will be the value from the dice (10, 2, 3, 4, 5, or 6 in your case), and the value will be the number of times that number has appeared. Then you can just look at each key in the dictionary and see if its value hits your threshold.
Alternatively, you can store all the results in an array, and just loop over the elements in the array and count.
If ordering does matter (e.g., you have to get 3 2's in a row):
You'll have to keep an array of the dice roll results, and then you can check after each dice roll if the previous 2 values were the same. Or, you can wait until you have all the rolls and then just check one by one to see if you get 3 in a row.
I haven't put any code down because I don't think that's as instructive. If you need more guidance let me know.
Sort the array. Then look for 3 numbers in a row with the same value.
Sure, I'll do your homework for you.
boolean hasTriplets = false;
Arrays.sort(nums); //Your array of random ints
for(int x=1; x<nums.length-1; x++)
if(nums[x-1] == nums[x] && nums[x] == numx[x+1])
{
hasTriplets = true;
break;
}
This should do:
if (Stream.of(4, 4, 4, 5, 2)
.collect(Collectors.groupingBy(Function.identity()))
.values().stream().mapToInt(List::size)
.filter(value -> value == 3)
.count() > 0) {
System.out.println("found exactly 3 occurrences of one number");
}
Assuming the 10 in the question should have been a 1, it would seem you're rolling five 6-sided dice, and want to find three-of-a-kind for a Yahtzee (or Yatzy) game.
If that is the case, you'll want other combinations detected too, so it would be best to collect count of each value, i.e. how many 1's, 2's, ..., and 6's, then find the highest count (and second highest).
See my answer here for longer description of how to do that for Yahtzee/Yatzy game.
If all you're interested in is three-of-a-kind, and it's ok to sort the values, as other have suggested, you can optimize the search a bit.
Once you sort the list, three-of-a-kind will be one of these combinations:
3 3 3 4 5
2 3 3 3 4
1 2 3 3 3
As you can see, the middle number is always part of the sequence, so you'll start with that. For the first combination, if the first value is equal to the third value, you don't have to test the second value, since it must be the same (sorted, remember). Same for the last combination.
So you code can be:
int[] dice = { 4, 4, 4, 5, 2 };
Arrays.sort(dice);
int candidate = dice[2];
if (dice[0] == candidate || dice[4] == candidate
|| (dice[1] == candidate && dice[3] == candidate)) {
System.out.println("Found three-of-a-kind for " + candidate);
}

creating set from input

I want to create a set of elements from the given input.
(i.e. i/p : 5 5 4 4 4 3 3 3 3 2 2 2 1 1 1 ,then o/p : 5 4 3 2 1)
I have a logic: create an array and store the elements in it.successively read elements and write a loop which will assign boolean false if two elements (the current chosen element and an element from the array whose index is less than that of the current element) are not the same. After the loop has executed for an element , all the boolean values stored are passed through bitwise OR operation and if the overall value is false , then the current element is pushed to an array that stores the set and the next element is the given sequence is chosen and same operation is performed.
I haven't yet written the code for this. So, is this algo. right? Also, do you know a better algo. to find a set?
Thanks.
You never need to use arrays for this sort of thing. Learn about Lists and Sets and use those instead.
Set<Integer> set = new LinkedHashSet<Integer>(Arrays.asList(5, 5, 4, 4, 3, 2, 4, 3, 1));
System.out.println(set); // prints [5, 4, 3, 2, 1]

Categories

Resources