Ratiorg got statues of different sizes as a present from CodeMaster for his birthday, each statue having an non-negative integer size. Since he likes to make things perfect, he wants to arrange them from smallest to largest so that each statue will be bigger than the previous one exactly by 1. He may need some additional statues to be able to accomplish that. Help him figure out the minimum number of additional statues needed.
Example
For statues = [6, 2, 3, 8], the output should be
makeArrayConsecutive2(statues) = 3.
This is a problem from codefights.
Here is my code written below
#include <iostream>
#include <vector>
#include<algorithm>
using std::vector;
int makeArrayConsecutive2(std::vector <int> statues) {
vector<int>::size_type size = statues.size();
sort( statues.begin(), statues.end() );
int counter = 0;
for( int i = 0; i<size; i++ )
{
int dif = statues[i+1] - statues[i] - 1;
if( dif >= 1 ) {counter+=dif;}
}
return counter;
}
int main()
{
vector<int> c = {1,2,3,4,5,6,7,8,9,10};
std :: cout<<"You need "<<makeArrayConsecutive2(c)<<" statues"<<std::endl;
return 0;
}
When I run code with this certain value of vector c it outputs misunderstanding value.All other cases runs correct, but when I declare 10 dimensional vector(I mean vector with 10 values) it doesn't work correct .Could you please explain what's the problem?
On the last iteration of for cycle statues[i+1] will be out of bounds causing undefined behavior. You need to add checks that statuses is not empty before for loop and then iterate until size - 1.
Related
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;
}
}
}
}
I know, the question is really complicated. Believe me, I am too. But I think a better programmer than me should know the solution. I have the following:
int cash[5] = {90000, 50000, 50000, 20000, 0};
int bankaccounts[3];
int dicenumberforeachplayer[3] = {6, 3, 9}; //Every indice is a player,
so dicenumberforeachplayer[0] is player one and so on
I have to add the highest cashnumber to the player, with the highest dicenumber, then the second player the second highest cash and so on. but I really don't know how. I am really confused, bc I am working on a project all day and I've come really far (i've written maybe 3000 lines of code) but I really hate to stop and confuse me with this problem for hours. Pls help me :((
I think, that I have to sort the player or sth like this and then I could use a for-loop for inserting the cash in every acc but I am really tired and I can't think right now XD
Modern C++ approach. There are no Magic numbers. Every thing is governed by the size of its respective array.
#include <algorithm>
#include <iostream>
int main()
{
int cash[5] = {90000, 50000, 50000, 20000, 0};
int bankaccounts[3] = {}; // added initializer to zero accounts
int dicenumberforeachplayer[3] = {6, 3, 9};
// iterate until we run out of prizes or players, whichever comes first
for (size_t cashcounter = 0;
cashcounter < std::min(std::size(dicenumberforeachplayer),
std::size(cash));
cashcounter++)
{
// find location in array of highest-rolling player
auto location = std::max_element(std::begin(dicenumberforeachplayer),
std::end(dicenumberforeachplayer));
// transform location into array index
auto index = std::distance(std::begin(dicenumberforeachplayer),
location);
//increase money in bank account for this player
bankaccounts[index] += cash[cashcounter];
// give winner impossibly low dice roll so they don't win again next time.
// Assumption: rolls cannot be negative. If they can, -1 might not be small enough
dicenumberforeachplayer[index] = -1;
}
// for display and test, print all accounts
for (const auto & val : bankaccounts)
{
std::cout << val << std::endl;
}
}
Use max_element to find the maximum and set the element to -1 then you can use the same max_element to get the next maximum element
int *max_player = max_element(dicenumberforeachplayer, dicenumberforeachplayer + 3);
int *max_money = max_element(cash, cash + 5);
bankaccount[(max_player - dicenumberforeachplayer)] += *max_money;
*max_player = *max_money = -1;
Can someone help me with the code in c++ below?
#include <iostream>
#include <fstream>
using namespace std;
int PARENT(int i)
{
return (i/2);
}
int Heapify_up(int arra[], int i)
{
int j,k;
if (i>1){
j = PARENT(i);
if (arra[i]<arra[j]){
k=arra[i];
arra[i]=arra[j];
arra[j]=k;
Heapify_up(arra, j);
}
}
return j;
}
int main()
{
int array3[15];
int i,p,array_length;
ifstream inputFile1("Heapfile.txt");
if (inputFile1.good()){
int current_number = 0;
i=1;
while (inputFile1>> current_number)
array3[i++] = current_number;
inputFile1.close();
}
array_length = i;
cout<<"Please, enter an integer: ";
cin>>p;
array3[array_length+1]=p;
int pos=Heapify_up(array3, array_length+1);
for (i=1; i<15; i++){
cout<<array3[i]<<" ";
}
cout<<"The position is "<<pos;
}
Let me explain you that have an array in a txt file. After i insert a random integer and with the heapify-up algorith I'm sorting this random number to the array. I want to print the new sorted array(I' have done that) and the new position of the random element that i have entered. Any idea?
thanks in advance!
P.S. I am new here and i find it somehow difficult to post my code correctly... still learning! XD
Okay, there are multiple problems with your code.
You make no effort to ensure you don't blow past the size of your
static array.
You skip a spot in the array when appending your manually-added
value
Your array length is wrong
You aren't initializing your variables
Let's start with the last one. Please do something like this:
int i{0}, p, array_length;
This ensures the i variable is properly initialized to zero.
Next, your code does this:
array3[i++] = current_number;
This means that at any given time, i is the length of the array.
But later you do this:
array_length = i;
array3[array_length+1]=p;
Frankly, I would drop variable i entirely and use array_length instead. There is no need for both.
But even without that, you're setting array_length correctly, but then you're inserting to a point AFTER that, so you might start with:
[ 1, 2, 3, 4, 5 ]
At this point, i == 5. Input a 6 and have:
[ 1, 2, 3, 4, 5, 0, 6 ]
Because you put it at index i+1 not at index i.
At this point, array_length is no longer an accurate length. But you do this:
int pos=Heapify_up(array3, array_length+1);
So it kind of works.
I don't know why Heapify_up is returning j -- it's just the midpoint of the array. That's not a useful value.
Furthermore, I don't really know what your heapify thing is trying to accomplish.. It certainly isn't a heap-sort. If the middle and end numbers are in sorted order, it doesn't actually do a thing.
This URL might help you with some code:
Heap sort at Geeks for Geeks
As for using a fix-length array -- that's problematic, too, but using std::vector is probably a bit much for you. I'd make sure that your input loop doesn't run into issues or start with a much longer beginning array.
So I was asked to write a function that changes array's values in a way that:
All of the values that are the smallest aren't changed
if, let's assume, the smallest number is 2 and there is no 3's and 4's then all 5's are changed for 3's etc.
for example, for an array = [2, 5, 7, 5] we would get [2, 3, 4, 3], which generalizes to getting a minimal value of an array which remains unchanged, and every other minimum (not including the first one) is changed depending on which minimum it is. On our example - 5 is the first minimum (besides 2), so it is 2 (first minimum) + 1 = 3, 7 is 2nd smallest after 2, so it is 2+2(as it is 2nd smallest).
I've come up with something like this:
int fillGaps(int arr[], size_t sz){
int min = *min_element(arr, arr+sz);
int w = 1;
for (int i = 0; i<sz; i++){
if (arr[i] == min) {continue;}
else{
int mini = *min_element(arr+i, arr+sz);
for (int j = 0; j<sz; j++){
if (arr[j] == mini){arr[j] = min+w;}
}
w++;}
}
return arr[sz-1];
}
However it works fine only for the 0th and 1st value, it doesnt affect any further items. Could anyone please help me with that?
I don't quite follow the logic of your function, so can't quite comment on that.
Here's how I interpret what needs to be done. Note that my example implementation is written to be as understandable as possible. There might be ways to make it faster.
Note that I'm also using an std::vector, to make things more readable and C++-like. You really shouldn't be passing raw pointers and sizes, that's super error prone. At the very least bundle them in a struct.
#include <algorithm>
#include <set>
#include <unordered_map>
#include <vector>
int fillGaps (std::vector<int> & data) {
// Make sure we don't have to worry about edge cases in the code below.
if (data.empty()) { return 0; }
/* The minimum number of times we need to loop over the data is two.
* First to check which values are in there, which lets us decide
* what each original value should be replaced with. Second to do the
* actual replacing.
*
* So let's trade some memory for speed and start by creating a lookup table.
* Each entry will map an existing value to its new value. Let's use the
* "define lambda and immediately invoke it" to make the scope of variables
* used to calculate all this as small as possible.
*/
auto const valueMapping = [&data] {
// Use an std::set so we get all unique values in sorted order.
std::set<int> values;
for (int e : data) { values.insert(e); }
std::unordered_map<int, int> result;
result.reserve(values.size());
// Map minimum value to itself, and increase replacement value by one for
// each subsequent value present in the data vector.
int replacement = *values.begin();
for (auto e : values) { result.emplace(e, replacement++); }
return result;
}();
// Now the actual algorithm is trivial: loop over the data and replace each
// element with its replacement value.
for (auto & e : data) { e = valueMapping.at(e); }
return data.back();
}
So I got this code sample that needs fixing. From what I can gather it takes an array, reverses it and then counts all the elements within it. Here is the code.
//-------------------------------------------------------------------
void ReverseTheArray( const short *pArrayStart, const int nArrayByteLength )
{
const short *pArrayEnd = (pArrayStart + nArrayByteLength);
while(pArrayStart != pArrayEnd)
{
short tmp = *pArrayStart;
*pArrayStart = *pArrayEnd;
*pArrayEnd = tmp;
pArrayStart++;
pArrayEnd--;
}
}
//-------------------------------------------------------------------
int CountTheArrayContents( const short *pArrayStart, int nNumEntries )
{
assert(nNumEntries-- > 0);
int nCount = 0;
for(unsigned uArrayIndex = nNumEntries; uArrayIndex >= 0; uArrayIndex--)
{
nCount += pArrayStart[uArrayIndex];
}
return nCount;
}
const short g_nSomeNumbers[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
//-------------------------------------------------------------------
int main()
{
short *pDataArray = new short[10];
memcpy(pDataArray, g_nSomeNumbers, sizeof(g_nSomeNumbers));
ReverseTheArray(pDataArray, 10*sizeof(short));
int nCount = CountTheArrayContents(pDataArray, 10);
printf("Sum total is %0.02f\n", nCount);
return 0;
}
I have ideas of what the problems are but can't seem to figure out a simple solution to the problem, one that doesn't require rewriting the entire code. If anyone can read this and see how the errors can be fixed it would be much appreciated.
I'm going to mention some things that I think are causing problems.
All the parameters and the pArrayEnd variable in the ReversTheArray() function are all const but are trying to be changed within the while loop, which is throwing an error. Should the const's be removed? Is there a reason const's would be used for this?
If the const's are remove a runtime error happens when trying to run the for loop in the CountTheArrayContents() function expressing an unhandled exception and saying "Access violation reading location 0x003DFFFE". Drawing a complete blank on that one.
Again any help on the code would be very much appreciated and I couldn't thank you guys enough.
PS. This is a challenge to create a reverse and accumulate function so I'm looking for a fix for the code and not a removal of the two functions. Thank you
PSS. Thanks to everyone who answered. I'm glad I did this (this being the first problem that I've posted about myself) and you've all been a huge help. I've got to say I've learnt alot.
Adding the actual length in bytes will add too many because pointer arithmetic is defined in terms of units of the size of the type pointed to. That is, pArrayEnd becomes &pDataArray[10 * sizeof(short)] instead of &pDataArray[10]. You don't need to multiply by sizeof(short) when calling the reversal function. Alternatively, you can divide nArrayByteLength by sizeof(short) when calculating the initial value of pArrayEnd.
The second issue is the fact that you only have 10 elements (0..9) allocated, meaning &pDataArray[10] would be one element beyond the array. The reversal function then tries to assign data to this unallocated area of memory, which can cause problems. The function should initialize pArrayEnd as shown, but immediately after, it should decrement pArrayEnd by 1. This way you won't be assigning to memory that might not belong to you. Beware of pArrayStart == pArrayEnd before you decrement pArrayEnd. An alternative test would be to ensure nArrayByteLength != 0.
Another problem is if the array has an even number of elements, and you try to do a reversal. If it does have an even number (like 10), pArrayStart will point to pDataArray[4], pArrayEnd will point to pDataArray[5], and after the data is assigned, pArrayStart++ will make pArrayStart point to pDataArray[5] and pArrayEnd-- point to pDataArray[4]. Then (6,3), (7,2), (8,1), (9,0), ... In other words, pArrayStart will never be equal to pArrayEnd in such a case. Instead, you should ensure that pArrayStart < pArrayEnd.
Hope this helps!
Also, any reason for not using std:: reverse? Just wondering.
Edit
The accumulation function can be rewritten as the following, which will avoid the issue with the assert macro while doing the same thing:
int CountTheArrayContents( const short *pArrayStart, int nNumEntries )
{
int count = 0;
assert(nNumEntries);
while (nNumEntries--)
count += pArrayStart[nNumEntries];
return count;
}
Hopefully count doesn't overflow.
If all you're trying to do is reverse the contents of the array and accumulate the result, std::reverse and std::accumulate will do the trick (per the suggestion by #chris). Here's an example, which maintains the dynamically allocated short*. A better solution would use std::vector or std::array.
#include <algorithm>
#include <numeric>
#include <stdio.h>
#include <memory.h>
const short g_nSomeNumbers[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
int main()
{
short *pDataArray = new short[10];
memcpy(pDataArray, g_nSomeNumbers, sizeof(g_nSomeNumbers));
std::reverse(pDataArray, pDataArray+10);
int nCount = std::accumulate(pDataArray, pDataArray+10, 0);
for( size_t i=0; i<10; ++i )
printf("%d ", pDataArray[i]);
printf("\n");
printf("Sum total is %d\n", nCount);
delete [] pDataArray;
return 0;
}
This prints
9 8 7 6 5 4 3 2 1 0
Sum total is 45