How can I shuffle a list - list

this code is for a game I create in unity. I have a list with 100 elements of coordinates and I want to instantiate boxes to them. The Amount of boxes should be 50% and totaly random. If I run my script, I get 50% of the boxes but in the default order. My script don't shuffle the elements in the list. Thanks for help!
// List has 100 elements of coordinates ( x & y)
public List<Vector2> ListPosBoxes = new List<Vector2>();
// Start
void Start()
{
AmountOfBoxes(ListPosBoxes);
}
// Method to display 50% shuffled boxes
void AmountOfBoxes(List<Vector2> list)
{
// Take list -> shuffle -> new list
list = ShuffleList(list);
for (int i = 0; i < list.Count/2; i++)
{
// Create Box
BoxGenerator(list[i]);
}
}
// Method to suffle list
List<Vector2> ShuffleList(List<Vector2> list)
{
Vector2 tmp;
// fisher–yates shuffle
for (int i = list.Count; i < 1; i--)
{
// Pick random Element
int j = Random.Range(0, list.Count);
// Swap Elements
tmp = list[j];
list[j] = list[i - 1];
list[i - 1] = tmp;
}
return list;
}
// Method to create Box
void BoxGenerator(Vector2 box)
{
CreateBox(box.x, box.y);
}
The problem is: the list isn't mixed.

You are running your for-loop from high numbers and decrease i.
// fisher–yates shuffle
for (int i = list.Count; i < 1; i--)
But the test in the for loop is i smaller than 1 so it never runs. Place a Debug.Log in the for-loop to test and flip the operator

I think the problem is that you are trying to re-declare a parameter.
For more info: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
Perhaps start with:
void AmountOfBoxes(List<Vector2> list)
{
// Take list -> shuffle -> new list
shuffled_list = ShuffleList(list);
for (int i = 0; i < list.Count/2; i++)
{
// Create Box
BoxGenerator(shuffled_list[i]);
}
}
// Method to suffle list
List<Vector2> ShuffleList(List<Vector2> list)
{
Vector2 tmp;
list *= list;
// fisher–yates shuffle
for (int i = list.Count; i < 1; i--)
{
// Pick random Element
int j = Random.Range(0, list.Count);
// Swap Elements
tmp = list[j];
list[j] = list[i - 1];
list[i - 1] = tmp;
}
return list;
}
I hope this helps.
What could also help you with debugging, is logging your variables someplace so that you know where it went wrong.

You have a couple of mistakes actually as mentioned in the previous answers but first of all, that Random.Range(0, list.Count); is quite biased actually, please check this link to have a better understanding of why.
And here is the corrected code:
// fisher–yates shuffle
for (int i = 0; i < list.Count; i++) {
// Pick random Element
int j = Random.Range(i, list.Count);
// Swap Elements
Vector2 tmp = list[i];
list[i] = list[j];
list[j] = tmp;
}

Related

How to erase or change element while iterating over vector in C++?

I was in the middle of creating a simple sieve of Erathostenes function when I stumbled upon one obstacle. In to order to accomplish the highest efficiency in this task I wanted to use only a vector. Here is the current code:
vector<int> sieveOfErathostenes(int N) {
vector <int> result(N, 1);
for(int i = 2; i < sqrt(N); i++)
if(result[i] == 1)
for(int j = 2*i; j < N; j += i)
result.at(j) = 0;
// :c
return result;
}
This vector returns 1 and 0 in the proper position but I can't figure out how to implement both erasing or changing an element's value in a single loop. When I use an iterator to erase an element as in erase set element while iterating/// I can't access the vector to change its value, and when I use a standard for loop to access the element I can't remove it. I have tried going from the end of the vector and counting non zero elements and giving some offset when erasing but no success.
TL DR: What I can't figure out is:
for(int i = 0; i < N; i++)
{
if(result[i] == 0) {
//remove at position i
} else {
result.at(i) = i;
}
}
Thank you in advance for your time :)
Instead of erasing elements in the middle of the vector, you should write the results from the beginning of the vector and eliminate the unused elements in the end of vector.
int finalSize = 0;
for(int i = 0; i < N; i++)
{
if(result[i] != 0) {
result[finalSize++] = i;
}
}
result.resize(finalSize);
If you still need to remove an element from a std::vector during traversal, keep in mind that erase returns an iterator following the last removed element:
std::vector<int> result = {1,1,1,0,1,1,1};
for(auto it = result.begin(); it != result.end(); )
{
if(*it==0)
it = result.erase(it);
else
it++;
}

Class Function that Inserts values into a sorted array without ruining the order

So I am really confused on the logic here, I get the general Idea of taking my values in 1 by 1 and comparing them to the elements in the array. If the value is larger move on to the next element, if the value is smaller or equal to the element move over all the elements over 1 index and replace the original index with your value. My problem is I cant get that last part into code and I have been sitting here stooped for half an hour. Here is what I have gotten so far.
void SortedArray::insertVal(int val)
{
//check for size == capacity
// if so, use .Expand function to double array capacity, then continue to below.
//if not continue
//here is where I am having my issues because I cant get the logic down.
for (int i = 0; i < capacity; i++)
{
if (val > arr[i])
arr[i] = arr[i + 1];
else if (val <= arr[i])
{
for (int x = 0; x < capacity; x++)
{
int temp = arr[i+1];
arr[i + 1] = arr[i];
//right about here I realized If I just assign temp to arr[1+2] the value of that index is lost.
}
}
}
}
I am just stooped, I wanted to check here and see if anyone can help before I have to contact my professor for help as a last resort.
Thanks in advance for anything :)
If I understood what you want, reading the array backwards should solve the problem.
for (int i = 0; i < capacity; i++)
{
if (val > arr[i])
{
for(int x = capacity - 1; x > i; x--)
{
arr[x] = arr[x - 1];
}
arr[i] = val;
break;
}
}

Intersection of 2 dynamically allocated arrays c++

I am trying to create a function that will find the intersection of two dynamically allocated arrays comparing array 1 to array 2. For any values in array 1 that are not in array 2, those values should be deleted in array 1 so that array 1 now only holds the common values of both arrays (no repeats). I cannot use vectors, hashes, or any other thing outside of my current functions in my class:
here is my code so far:
bool IntSet::contains(int val) const
{
for (int i = 0; i < numValues; i++)
{
if (set[i] == val)
return true;
}
return false;
}
this function compares an integer parameter to values currently stored in the array...if a value is in the array it returns true and if else false;
this next function takes in a value and removes that value from the array:
void IntSet::remove(int val)
{
for (int i = 0; i < numValues; i++)
{
if (set[i] == val)
for (int j = 0; j < numValues; j++)
set[j] = set[j + 1];
}
numValues--;
}
here's where I've been having problems, this next function is supposed to iterate through one array and compare those values with the values in the other array...if one value from one array is in the other, it should just skip it, but if a value is not in the array calling the function, it should delete that value from the calling array:
void IntSet::removeDifferent(const IntSet &set2)
{
for (int i = 0; i < set2.size(); i++)
{
if (!set2.contains(set[i]))
{
remove(set[i]);
}
}
}
ive tried about 50 different variations on the removeDifferent() function and I just can't seem to figure this one out. Could someone point me in the right direction?
You're iterating i through the indexes of set2, but then you're testing set[i]. Try this:
void IntSet::removeDifferent(const IntSet &set2)
{
for (int i = 0; i < numValues; ) {
if (!set2.contains(set[i])) {
remove(set[i]);
} else {
i++;
}
}
Note that I also removed i++ from the for loop header. This is because when you remove an element, all the following elements are shifted down, so the next element takes its place in the array. If you incremented i, it would skip that element.
You also need to fix remove. It should start its inner loop from i, so it only shifts down the elements after the one being removed, and it should stop at numValues-1, so it doesn't try to access outside the array when it copies set[j+1]. And as an optimization, it can break out of the outer loop once it has found a match (I assume IntSet doesn't allow duplicates, since you only decrement numValues by 1).
void IntSet::remove(int val)
{
for (int i = 0; i < numValues; i++)
{
if (set[i] == val) {
for (int j = i; j < numValues - 1; j++) {
set[j] = set[j + 1];
}
break;
}
}
numValues--;
}
Your problem is in your remove() function:
void IntSet::remove(int val)
{
for (int i = 0; i < numValues; i++)
{
if (set[i] == val)
for (int j = 0; j < numValues; j++)
set[j] = set[j + 1];
}
numValues--;
}
You can figure out yourself why this is wrong by using a paper and pencil here. Start with a typical example: let's say you found the value you're looking for in the third element of a five-element array:
if (set[i] == val)
In this example, i would be set to 2, and numValues would be set to five. It doesn't matter what val is. Whatever it is, you found it when i is 2, and numValues is five: you found it in the third element of a five element array. Keep that in mind.
Now, you know that you are now supposed to remove the third element in this five element array. But what do you think will happen next:
for (int j = 0; j < numValues; j++)
set[j] = set[j + 1];
Well, using the aforementioned paper and pencil, if you work it out, the following will happen:
set[1] will be copied to set[0]
set[2] will be copied to set[1]
set[3] will be copied to set[2]
set[4] will be copied to set[3]
set[5] will be copied to set[4]
There are two problems here:
A) There is no set[5]. Recall that this is a five-element array, si you only have set[0] through set[4]
B) You're not supposed to copy everything in array down to one element. You have to copy only the elements after the element you want to remove.
Fix these two problems, and you will probably find that everything will work correctly.

Bubble Sort Using Slides instead of swaps

currently I'm being asked to design four sorting algorithms (insertion, shell, selection, and bubble) and I have 3 of the 4 working perfectly; the only one that isn't functioning correctly is the Bubble Sort. Now, I'm well aware of how the normal bubble sort works with using a temp var to swap the two indexes, but the tricky part about this is that it needs to use the array index[0] as a temp instead of a normal temp, which is used in swapping, and slide the lower array variables down to the front of the list and at the end of the pass assign the last index to the temp which is the greatest value.
I've been playing around with this for a while and even tried to look up references but sadly I cannot find anything. I'm hoping that someone else has done this prior and can offer some helpful tips. This is sort of a last resort as I've been modifying and running through the passes with pen and paper to try and find my fatal error. Anyways, my code is as follows...
void BubbleSort(int TheArray[], int size)
{
for (int i = 1; i < size + 1; i++)
{
TheArray[0] = TheArray[i];
for (int j = i + 1; j < size; j++)
{
if (TheArray[j] > TheArray[0])
TheArray[0] = TheArray[j];
else
{
TheArray[j - 1] = TheArray[j];
}
}
TheArray[size- 1] = TheArray[0];
}
}
Thanks for any feedback whatsoever; it's much appreciated.
If I understand the problem statement, I think you're looking for something along these lines :
void BubbleSort(int theArray[], int size)
{
for (int i = 1; i < size + 1; i++)
{
theArray[0] = theArray[1];
for (int j = 1; j <= size + 1 - i; j++)
{
if (theArray[j] > theArray[0])
{
theArray[j-1] = theArray[0];
theArray[0] = theArray[j];
}
else
{
theArray[j - 1] = theArray[j];
}
}
theArray[size-i+1] = theArray[0];
}
}
The piece that you're code was missing, I think, was that once you find a new maximum, you have to put it back in the array before placing the new maximum in theArray[0] storage location (see theArray[j-1] = theArray[0] after the compare). Additionally, the inner loop wants to run one less each time since the last element will be the current max value so you don't want to revisit those array elements. (See for(int j = 1 ; j <= size + 1 - i ; j++))
For completeness, here's the main driver I used to (lightly) test this :
int main()
{
int theArray[] = { 0, 5, 7, 3, 2, 8, 4, 6 };
int size = 7;
BubbleSort(theArray, size);
for (int i = 1; i < size + 1; i++)
cout << theArray[i] << endl;
return 0;
}

Count triplets which satisfy given condition [duplicate]

This question already has answers here:
Number of all increasing subsequences in given sequence?
(7 answers)
Closed 8 years ago.
Given an array A of size N I need to count such triplets (i,j,k) such that:
Condition 1 : i < j < k
Condition 2 : A[i] > A[j] > A[k]
I know a O(N^3) solution to do it. Can their be something like O(N) or O(NlogN) solution to do this problem as N can be up to 100000
Example : Let N=4 and array be [4,3,2,1] then answer is 4 as {4,3,2},{4,3,1},{4,2,1} and {3,2,1} are all possible answers
How to find this count for given N and array A?
My Approach :
int n;
cin>>n;
vector<int> A(n);
for(int i=0;i<n;i++){
cin>>A[i];
}
int count=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
for(int k=j+1;k<n;k++){
if(A[i]>A[j] && A[j]>A[k]){
count++;
}
}
}
}
cout<<count<<"\n";
First, sort the array, maintain the index of each element.
class Node{
int index, val;
}
For comparing two nodes, we first need to compare their values. If the values equals, we will compare their index, consider a node is greater if its index is smaller.
Now, process each node in sorted order, we try to add each node's index into a Fenwick tree. So, for each index i, we query the tree for the frequency of this index, which added previously in the tree. This is the number of index that has value greater than value of the current index.
Note for the case elements have equal value, by the sorting mechanism mentioned above, we will add those have greater index to the tree first, thus, doesn't affect the frequency value query from the tree.
Apply similar step to obtains those elements that smaller than i and has index j < i.
For example:
If we have an array
{0(1) ,1(2) , 2(2) ,3(4) , 4(4) ,5(4) ,6(1)} //index(value)
After sort -> {5(4), 4(4), 3(4), 2(2), 1(2), 6(1), 0(1) }
Pseudo code
Node[]data;
sort(data)
Fenwick tree;
int[]less;
int[]more;
for(int i = 0; i < data.length; i++){
less[data[i].index] = tree.query(data[i].index);
tree.add(data[i].index, 1);
}
tree.clear();
for(int i = data.length - 1; i >= 0; i--){
more[data[i].index] = tree.query(data.length) -tree.query(data[i].index);
tree.add(data[i].index, 1);
}
int result = 0;
for(int i = 0; i < data.length; i++)
result += more[i]*less[i];
Time complexity will be O(n logn).
Working Java code (FT is my Fenwick tree)
PrintWriter out;
Scanner in = new Scanner(System.in);
out = new PrintWriter(System.out);
int n = in.nextInt();
Node[] data = new Node[n];
for (int i = 0; i < n; i++) {
data[i] = new Node(i + 1, in.nextInt());
}
FT tree = new FT(n + 2);
Arrays.sort(data, new Comparator<Node>() {
#Override
public int compare(Node o1, Node o2) {
if (o1.val != o2.val) {
return o2.val - o1.val;
}
return o2.index - o1.index;
}
});
int[] less = new int[n];//Store all nodes with greater index and smaller value;
int[] greater = new int[n];//Store all nodes with smaller index and greater value
for (int i = 0; i < n; i++) {
greater[data[i].index - 1] = (int) tree.get(data[i].index);
tree.update(data[i].index, 1);
}
tree = new FT(n + 2);
for (int i = n - 1; i >= 0; i--) {
less[data[i].index - 1] = (int) (tree.get(n) - tree.get(data[i].index));
tree.update(data[i].index, 1);
}
long total = 0;
for (int i = 0; i < n; i++) {
total += less[i] * greater[i];
}
out.println(total);
out.close();
You can do this in O(n*n) pretty easily, you just need to keep track of how many smaller number each element had:
vector<int> smallerNumbers(A.size());
for (int i = A.size() - 2; i >= 0; --i){
for (int j = i + 1; j < A.size(); ++j){
if (A[i] > A[j]){
smallerNumbers[i]++;
count += smallerNumbers[j];
}
}
}
For an O(nklogn) solution see my answer here: https://stackoverflow.com/a/28379003/2642059
Note that is for an increasing sequence and you're asking for a decreasing sequence.
To accomplish that you will need to reverse the ranking created by mapIndex. So simply reverse temp before creating mapIndex by swapping the partial_sort_copy line with this one:
partial_sort_copy(values.cbegin(), values.cend(), temp.rbegin(), temp.rend());