Sort Optimisation time - c++

I have 2 sorts:
void sort1(std::vector<int> &toSort)
{
for(VintIter i=toSort.begin(); i!=toSort.end(); i++)
{
for (VintIter j =(toSort.end()-1); j != i; --j)
{
if (*(j - 1) > *(j))
{
std::iter_swap(j - 1, j);
}
}
}
}
void sort2(std::vector<int> &toSort)
{
for(int i= 0; i<(toSort.size()-1); i++)
{
int minElem=i,maxElem=i+1;
if(toSort[minElem]>toSort[maxElem])
{
std::swap(toSort[minElem],toSort[maxElem]);
}
while(minElem>0 && toSort[minElem]<toSort[minElem-1])
{
std::swap(toSort[minElem],toSort[minElem-1]);
minElem--;
}
while(maxElem<(toSort.size()-1) && toSort[maxElem]>toSort[maxElem+1])
{
std::swap(toSort[maxElem],toSort[maxElem+1]);
maxElem++;
}
}
}
And I'm using QueryPerformanceFrequency and QueryPerformanceCounter to get times of those.
For Random vector of 1000 elements for sort1 returns 20.3 and for sort2 5.4. And this is ok..
But when I'm trying to get resoults for sorted array, so for the best situation when the toSort vector is already sorted, the resoults are little weird..
for sort1 it's 12.234 and for sort2 is 0.0213..
For 10 000 elements sort1 is 982.069 and for sort2 is 0.2!
I have assertion for comparing if the vector is sorted.
I'm using newest mingw on Windows 7 and windows 8. For i7-5700 HQ and for i5-6300U..
It's only exercise for my to create something better, that have no implementation. I's all about my idea, so i don't want to use std::sort.
My question is:
Why second algorithm gives my ~0 time with 10 000 elements?

The first one has complexity of n² in any case.
Whereas in the sorted case, your second algorithm is linear:
toSort[minElem] < toSort[minElem - 1] and toSort[maxElem] > toSort[maxElem+1] is always false, so your inner loop break immediately.

Related

How to choose a random number excluding those which were previously chosen? [duplicate]

I'd like to make a number generator that does not repeat the number it has given out
already (C++).
All I know is:
int randomgenerator(){
int random;
srand(time(0));
random = rand()%11;
return(random);
} // Added this on edition
That function gives me redundant numbers.
I'm trying to create a questionnaire program that gives out 10 questions in a random order and I don't want any of the questions to reappear.
Does anyone know the syntax?
What I would do:
Generate a vector of length N and fill it with values 1,2,...N.
Use std::random_shuffle.
If you have say 30 elements and only want 10, use the first 10 out the vector.
EDIT: I have no idea how the questions are being stored, so.. :)
I am assuming the questions are being stored in a vector or somesuch with random access. Now I have generated 10 random numbers which don't repeat: 7, 4, 12, 17, 1, 13, 9, 2, 3, 10.
I would use those as indices for the vector of questions:
std::vector<std::string> questions;
//fill with questions
for(int i = 0; i < number_of_questions; i++)
{
send_question_and_get_answer(questions[i]);
}
You are trying to solve the problem "the wrong way".
Try this instead (supposing you have a vector<int> with question ids, but the same idea will work with whatever you have):
Get a random R from 0 to N-1 where N is the number of questions in the container
Add question R to another collection of "selected" questions
If the "selected questions" collection has enough items, you 're done
Remove question R from your original container (now N has decreased by 1)
Go to 1
Sounds like you essentially want to shuffle a deck of cards (in this case, the "cards" being the questions, or question numbers).
In C++, I would do:
#include <vector>
#include <algorithms>
std::vector<int> question_numbers;
for (unsigned int i = 0; i < 10; ++i)
question_numbers.push_back(i+1);
std::random_shuffle(question_numbers.begin(), question_numbers.end());
// now dole out the questions based on the shuffled numbers
You do not have to hand out all of the questions, any more than you have to deal out a whole deck of cards every time you play a game. You can, of course, but there's no such requirement.
Create a vector of 10 elements (numbers 1-10), then shuffle it, with std::random_shuffle. Then just iterate through it.
Should look more like this: (Note: does not solve your original problem).
int randomgenerator(){
int random;
// I know this looks re-dunand compared to %11
// But the bottom bits of rand() are less random than the top
// bits do you get a better distribution like this.
random = rand() / (RAND_MAX / 11);
return random;
}
int main()
{
// srand() goes here.
srand(time(0));
while(true)
{
std::cout << randomgenerator() << "\n";
}
}
A better way to solve the original problem is to pre-generate the numbers so you know that each number will appear only once. Then shuffle the order randomly.
int main()
{
int data[] = { 0,1,2,3,4,5,6,7,8,9,10,11};
int size = sizeof(data)/sizeof(data[0]);
std::random_shuffle(data, data + size);
for(int loop = 0; loop < size; ++loop)
{
std::cout << data[loop] << "\n";
}
}
Why not use some STL to perform the checks for you? The idea:
Create an (initially empty) set of 10 integers that will be the indices of the random questions (they will be distinct as a set forbids duplicate items). Keep pushing random numbers in [0, num_of_questions-1] in there until it grows to a size of 10 (duplicates will get rejected automatically). When you have that set ready, iterate over it and output the questions of the corresponding indexes:
std::vector<std::string> questions = /* I am assuming questions are stored in here */
std::set<int> random_indexes;
/* loop here until you get 10 distinct integers */
while (random_indexes.size() < 10) random_indexes.insert(rand() % questions.size());
for (auto index: random_indexes){
std::cout << questions[index] <<std::endl;
}
I may be missing something, but it seems to me the answers that use shuffling of either questions or indexes perform more computations or use an unnecessary memory overhead.
//non repeating random number generator
for (int derepeater = 0; derepeater < arraySize; derepeater++)
{
for (int j = 0; j < arraySize; j++)
{
for (int i = arraySize; i > 0; i--)
{
if (Compare[j] == Compare[i] && j != i)
{
Compare[j] = rand() % upperlimit + 1;
}
}
}
}

Removing multiple elements from a vector c++

Here is some code which checks if 2 units are killed after they attack each other, I pass in the position in the vector however when I remove one the vector is changed in size and therefore the 2nd unit is out of range. How can I remove both simultaneously?
if ((MyHealth <= 0) && (EnemyHealth <= 0))
{
PlayerUnits.erase(PlayerUnits.begin() + MyUnit, PlayerUnits.begin() + EnemyUnit);
}
else if (MyHealth <= 0)
{
PlayerUnits.erase(PlayerUnits.begin() + MyUnit);
}
else if (EnemyHealth <= 0)
{
PlayerUnits.erase(PlayerUnits.begin() + EnemyUnit);
}
Instead of coding the removal logic yourself, it would be better managed using std::remove_if from algorithm. Depending on whether you have compiler supporting C++11 or not, the Predicate can either be a lambda or a named function.
First point: In your first block, the call erase(x, y) does something different than you expect - it erases a whole range of elements starting at index x until just before index y. For example, if we have the vector [a,b,c,d,e,f,g], then erase(2,5) will erase indexes 2,3,4, so we end up with [a,b,f,g]. I'm guessing you want to erase just two elements, not an entire range.
Second point: As Dieter Lücking pointed out, simply erase the higher index element first, like this:
if (MyUnit > EnemyUnit) {
PlayerUnits.erase(PlayerUnits.begin() + MyUnit);
PlayerUnits.erase(PlayerUnits.begin() + EnemyUnit);
} else {
PlayerUnits.erase(PlayerUnits.begin() + EnemyUnit);
PlayerUnits.erase(PlayerUnits.begin() + MyUnit);
}
I think a better way to handle this would be to add an "isDead" condition to your "unit" class:
void Unit::Update()
{
//other stuff
if(this->m_health <= 0) this->m_isDead = true;
}
then in the main loop:
void Game::Update()
{
size_t size = PlayerUnits.size();
//iterate backwards, so there is no skipping
for(int i = size-1; i>= 0; i--)
{
PlayerUnits[i]->Update();
if(PlayerUnits[i]->isDead()) PlayerUnits.erase(PlayerUnits.begin() + i);
}
}
This is at least how I personally do it.

How to determine the number of array 100 are not equal to each other

I am coding a Sudoku program. I found the number in the array determine whether duplicate each other is hard.
Now I have an array: int streamNum[SIZE]
if SIZE=3,I can handle this problem like:if(streamNum[0]!=streamNum[1])...
if SIZE=100,I think that I need a better solution, is there any standard practice?
There are a couple of different ways to do this, I suppose the easiest is to write two loops
bool has_duplicate = false;
for (int i = 0; i < SIZE && !has_duplicate; ++i)
for (int j = i + 1; j < SIZE && !has_duplicate; ++j)
if (streamNum[i] == streamNum[j])
has_duplicate = true;
if (has_duplicate)
{
...
}
else
{
...
}
The first loop goes through each element in the array, the second loop checks if there is a duplicate in the remaining elements of the array (that's why it starts at i + 1). Both loops quit as soon as you find a duplicate (that's what && !has_duplicate does).
This is not the most efficient way, more efficient would be to sort the array before looking for duplicates but that would modify the contents of the array at the same time.
I hope I've understand your requirements well enough.
for(int i=0;i<size;i++){
for(int j=i+1;j<size;j++){
if(streamNUM[i]==streamNUM[j]){
...........
}
}
}
I assume that u need whether there is duplication or not this may be helpful
If not comment
It's a little unclear what exactly you're looking to do here but I'm assuming as it's sudoku you're only interested in storing numbers 1-9?
If so to test for a duplicate you could iterate through the source array and use a second array (with 9 elements - I've called it flag) to hold a flag showing whether each number has been used or not.
So.. something like:
for (loop=0;loop<size;loop++) {
if (flag[streamNum[loop]]==true) {
//duplicate - do something & break this loop
break;
}
else {
flag[streamNum[loop]=true;
}
}
Here's how I'd test against Sudoku rules - it checks horizontal, vertical and 3x3 block using the idea above but here 3 different flag arrays for the 3 rules. This assumes your standard grid is held in an 81-element array. You can easily adapt this to cater for partially-completed grids..
for (loop=0;loop<9;loop++) {
flagH=[];
flagV=[];
flagS=[];
for (loop2=0;loop2<9;loop2++) {
//horizontal
if(flagH[streamNum[(loop*9)+loop2]]==true) {
duplicate
else {
flagH[streamNum[(loop*9)+loop2]]=true);
}
//column test
if(flagV[streamNum[loop+(loop2*9)]]==true) {
..same idea as above
//3x3 sub section test
basecell = (loop%3)*3+Math.floor(loop/3)*27; //topleft corner of 3x3 square
cell = basecell+(loop2%3+(Math.floor(loop2/3)*9));
if(flagS[streamNum[cell]]==true) {
..same idea as before..
}
}

How to get random and unique values from a vector? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Unique random numbers in O(1)?
Unique random numbers in an integer array in the C programming language
I have a std::vector of unique elements of some undetermined size. I want to fetch 20 unique and random elements from this vector. By 'unique' I mean that I do not want to fetch the same index more than once. Currently the way I do this is to call std::random_shuffle. But this requires me to shuffle the entire vector (which may contain over 1000 elements). I don't mind mutating the vector (I prefer not to though, as I won't need to use thread locks), but most important is that I want this to be efficient. I shouldn't be shuffling more than I need to.
Note that I've looked into passing in a partial range to std::random_shuffle but it will only ever shuffle that subset of elements, which would mean that the elements outside of that range never get used!
Help is appreciated. Thank you!
Note: I'm using Visual Studio 2005, so I do not have access to C++11 features and libraries.
You can use Fisher Yates http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
The Fisher–Yates shuffle (named after Ronald Fisher and Frank Yates), also known as the Knuth shuffle (after Donald Knuth), is an algorithm for generating a random permutation of a finite set—in plain terms, for randomly shuffling the set. A variant of the Fisher–Yates shuffle, known as Sattolo's algorithm, may be used to generate random cycles of length n instead. Properly implemented, the Fisher–Yates shuffle is unbiased, so that every permutation is equally likely. The modern version of the algorithm is also rather efficient, requiring only time proportional to the number of items being shuffled and no additional storage space.
The basic process of Fisher–Yates shuffling is similar to randomly picking numbered tickets out of a hat, or cards from a deck, one after another until there are no more left. What the specific algorithm provides is a way of doing this numerically in an efficient and rigorous manner that, properly done, guarantees an unbiased result.
I think this pseudocode should work (there is a chance of an off-by-one mistake or something so double check it!):
std::list chosen; // you don't have to use this since the chosen ones will be in the back of the vector
for(int i = 0; i < num; ++i) {
int index = rand_between(0, vec.size() - i - 1);
chosen.push_back(vec[index]);
swap(vec[index], vec[vec.size() - i - 1]);
}
You want a random sample of size m from an n-vector:
Let rand(a) return 0..a-1 uniform
for (int i = 0; i < m; i++)
swap(X[i],X[i+rand(n-i)]);
X[0..m-1] is now a random sample.
Use a loop to put random index numbers into a std::set and stop when the size() reaches 20.
std::set<int> indexes;
std::vector<my_vector::value_type> choices;
int max_index = my_vector.size();
while (indexes.size() < min(20, max_index))
{
int random_index = rand() % max_index;
if (indexes.find(random_index) == indexes.end())
{
choices.push_back(my_vector[random_index]);
indexes.insert(random_index);
}
}
The random number generation is the first thing that popped into my head, feel free to use something better.
#include <iostream>
#include <vector>
#include <algorithm>
template<int N>
struct NIntegers {
int values[N];
};
template<int N, int Max, typename RandomGenerator>
NIntegers<N> MakeNRandomIntegers( RandomGenerator func ) {
NIntegers<N> result;
for(int i = 0; i < N; ++i)
{
result.values[i] = func( Max-i );
}
std::sort(&result.values[0], &result.values[0]+N);
for(int i = 0; i < N; ++i)
{
result.values[i] += i;
}
return result;
};
Use example:
// use a better one:
int BadRandomNumberGenerator(int Max) {
return Max>4?4:Max/2;
}
int main() {
NIntegers<100> result = MakeNRandomIntegers<100, 500>( BadRandomNumberGenerator );
for (int i = 0; i < 100; ++i) {
std::cout << i << ":" << result.values[i] << "\n";
}
}
make each number 1 smaller in max than the last. Sort them, then bump up each value by the number of integers before it.
template stuff is just trade dress.

How to find first non-repeating element?

How to find first non-repeating element in an array.
Provided that you can only use 1 bit for every element of the array and time complexity should be O(n) where n is length of array.
Please make sure that I somehow imposed constraint on memory requirements. It is also possible that it can not be done with just an extra bit per element of the string. Also please let me know if it is possible or not?
I would say there is no comparison based algorithm, that can do it in O(n). As you have to compare the the first element of the array with all others, the 2nd with all except the first, the 3rd with all except the first = Sum i = O(n^2).
(But that does not necessarily mean that there is no faster algorithm, see sorting: There is a proof that you cant sort fast than O(n log n) if you are comparison based - and there is indeed one faster: Bucket Sort, which can do it in O(n)).
EDIT: In one of the other comments I said something about hash functions. I checked some facts about it, and here are the hashmap approach thoughts:
Obvious approach is (in Pseudocode):
for (i = 0; i < maxsize; i++)
count[i] = 0;
for (i = 0; i < maxsize; i++) {
h = hash(A[i]);
count[h]++;
}
first = -1;
for (i = 0; i < maxsize; i++)
if (count[i] == 0) {
first = i;
break;
}
}
for (i = 0; hash(A[i]) != first; i++) ;
printf("first unique: " + A[i]);
There are some caveats:
How to get hash. I did some research on perfect hash functions. And indeed you can generate one in O(n). (Optimal algorithms for minimal perfect hashing by George Havas et al. - Not sure how good this paper is, as it claims as Time Limit O(n) but speaks from non linear space limit (which is plan an error, I hope I am not the only seeing the flaw in the this, but according to all theorical computer science I know off time is an upper border for space (as you dont have time to write in more space)). But I believe them when they say it is possible in O(n).
The additional space - here I dont see a solution. Above papers cites some research that says that you need 2.7 bits for the perfect hash function. With the additional count array (which you can shorten to the states: Empty + 1 Element + More than 1 Element) you need 2 additional bits per element (1.58 if you assume you can it somehow combine with the above 2.7), which sums up to additional 5 bits.
Here I'm just taking one assumption that the string is Character String, just containing small alphabets, so that I can use one Integer (32 bit) so that with 26 alphabets it will be sufficient to take one bit per alphabet. Earlier I thought to take an array of 256 elements but then it will have 256*32 bits in total. 32 bits per element. But finally I found that I will be unable to do it without one more variable. So the solution is like this with just one integer (32 bits) for 26 alphabets:
int print_non_repeating(char* str)
{
int bitmap = 0, bitmap_check = 0;
int length = strlen(str);
for(int i=0;i<len;i++)
{
if(bitmap & 1<<(str[i] - 'a'))
{
bitmap_check = bitmap_check | ( 1 << (str[i] - 'a');
}
else
bitmap = bitmap | (1 << str[i] - 'a');
}
bitmap = bitmap ^ bitmap_check;
i = 0;
if(bitmap != 0)
{
while(!bitmap & (1<< (str[i])))
i++;
cout<<*(str+i);
return 1;
}
else
return 0;
}
You can try doing a modified bucketsort as exemplified below. However, you need to know the max value in the array passed into the firstNonRepeat method. So this runs at O(n).
For comparison based methods, the theoretical fastest (at least in terms of sorting) is O(n log n). Alternatively, you can even use modified versions of radix sort to accomplish this.
public class BucketSort{
//maxVal is the max value in the array
public int firstNonRepeat(int[] a, int maxVal){
int [] bucket=new int[maxVal+1];
for (int i=0; i<bucket.length; i++){
bucket[i]=0;
}
for (int i=0; i<a.length; i++){
if(bucket[a[i]] == 0) {
bucket[a[i]]++;
} else {
return bucket[a[i]];
}
}
}
}
This code finds the first repeating element. havent figured out yet if in the same for loop if it is possible to find the non-repeating element without introducing another for (to keep the code O(n)). Other answers suggest bubble sort which is O(n^2)
#include <iostream>
using namespace std;
#define max_size 10
int main()
{
int numbers[max_size] = { 1, 2, 3, 4, 5, 1, 3, 4 ,2, 7};
int table[max_size] = {0,0,0,0,0,0,0,0,0,0};
int answer = 0, j=0;
for (int i = 0; i < max_size; i++)
{
j = numbers[i] %max_size;
table[j]++;
if(table[j] >1)
{
answer = 1;
break;
}
}
std::cout << "answer = " << answer ;
}