About random numbers in C++ - c++

I am really new to C++. I am following a free online course, and one thing I had to do was to create a program which could scramble the characters of a string.
So, I created a function who received the word as parameter and returned the scrambled word. ctime and cstdlib were included and srand(time(0)); declared in the main.
Basically, the function looked like this :
std::string mixingWord(std::string baseWord)
{
std::string mixWord;
int pos(0);
for (int i = baseWord.length; i >= 0; i--)
{
if (i != 0)
{
pos = rand() % i;
mixWord += baseWord[pos];
baseWord.erase(pos,1);
}
else
{
mixWord += baseWord[0];
}
}
return mixWord;
}
And it worked just fine. But the correct solution was
std::string mixingWord(std::string baseWord)
{
std::string mixWord;
int pos(0);
while (baseWord.size() != 0)
{
pos = rand() % baseWord.size();
mixWord += baseWord[pos];
baseWord.erase(pos, 1);
}
return mixWord;
}
And it works fine as well.
My question is :
Why is the solution working ?
From what I understood, this :
rand() % value
gives out a value between 0 and the value given.
SO, since baseWord.size() returns, let's say 5 in the event of a word like HELLO. rand will generate a number between 0 and 5. So it COULD be 5. and baseWord[5] is out of bound, so it should crash once in a while, but I tried it over 9000 times (sorry, dbz reference), and it never crashed.
Am I just unlucky, or am I not understanding something ?

x % y gives the remainder of x / y. The result can never be y, because if it was, then that would mean y could go into x one more time, and the remainder would actually be zero, because y divides x evenly. So to answer your question:
Am I just unlucky, or am I not understanding something ?
You're misunderstanding something. rand() % value gives a result in the range [0,value - 1] (assuming value is positive), not [0, value].

rand() % 100 returns number between 0 and 99. This is 100 NUMBERs but includes 0 and does not include 100.
A good way to think about this is a random number (1000) % 100 = 0. If I mod a random number with the number N then there is no way to get the number N back.
Along those lines
pos = rand() % baseWord.size();
will never return pos = baseWord.size() so in your case there will not be an indexing issue

I guess you just misunderstood the modulo operator. a % b, with a and b any integer, will return values between 0 and b-1 (inclusive).
As for your HELLO example, it will only return values between 0 and 4, therefore will never encounter out of bound error.

Related

Music Chairs problem implementation in C++

I am currently practicing algorithms and DS. I have stumbled upon a question that I can't figure out how to solve. So the question's link is there:
In summary, it says that there is a number of chairs in a circle, and the position of the person (relative to a certain chair), and how many M movements he should make.
So the input is as following:
3 integer numbers N, M, X , The number of chairs, the number of times the boy should move and the first chair he will start from respectively ( 1  ≤  X  ≤  N < 2^63 , 0  ≤  M < 2^63 )
So, what have I done so far? I thought about the following:
So I thought that the relative position after M movements is (x+m) % n, and since this can cause Integer overflow, I have done it like that, ((x%n) + (m%n)) % n. I have figured out that if the person has reached the last index of chair, it will be 0 so I handled that. However, it passes only 2 tests. I don't need any code to be written, I want to directed in the right way of thinking. Here is my code so far:
#include <iostream>
using namespace std;
int main() {
long long n, m, x;
cin >> n >> m >> x;
// After each move, he reaches (X+1).
// X, N chairs.
// ((X % N) + (M % N)) % N;
// Odd conideration.
if ( m % 2 == 1) {
m += 1;
}
long long position = (x % n + m % n) % n;
if (position == 0) {
position = n;
}
cout << position;
return 0;
}
If the question required specific error handling, it should have stated so (so don't feel bad).
In every real-world project, there should be a standard to dictate what to do with weird input. Do you throw? Do you output a warning? If so, does it have to be translated to the system language?
In the absence of such instructions I would err toward excluding these values after reading them. Print an error to std::cerr (or throw an exception). Do this as close to where you read them as possible.
For overflow detection, you can use the methods described here. Some may disagree, and for a lab-exercise, it's probably not important. However, there is a saying in computing "Garbage in == Garbage out". It's a good habit to check for garbage before processing, rather than attempting to "recycle" garbage as you process.
Here's the problem:
Say the value of N is 2^63-1, and X and M are both 2^63 - 2.
When your program runs untill the ((X % N) + (M % N)) % N part,
X % N evaluates into 2^63 - 2 (not changed), and so does M % N.
Then, the addition between the two results occurs, 2^63 - 2 + 2^63 - 2 there is the overflow happening.
After the comment of #WBuck, the answer is actually rather easy which is to change the long long to unsigned because there are no negative numbers and therefore, increase the MAX VALUE of long long (when using unsigned).
Thank you so much.

if statement inside of for loop not being executed

Writing a program to solve problem four of project euler: Find the largest palindrome made from the product of two 2-digit numbers. Heres my reprex:
#include <iostream>
int reverseNumber(int testNum)
{
int reversedNum, remainder = 0;
int temp = testNum;
while(temp != 0)
{
remainder = temp % 10;
reversedNum = reversedNum * 10 + remainder;
temp /= 10;
}
return reversedNum;
}
int main()
{
const int MIN = 100;
int numOne = 99;
int product = 0;
for(int numTwo = 10; numTwo < 100; numTwo++)
{
product = numOne * numTwo;
if (reverseNumber(product) == product)
{
int solution = product;
std::cout << solution << '\n';
return 0;
}
}
return 0;
}
My main thought process behind this is that the for loop will go through every number from 10 to 99 and multiply it by 99. My intended outcome is for it to print 9009 which is the largest palindrome with 2 factors of 2 digits. So what I think should happen here is the for loop will go from 10 to 99, and each loop it should go through the parameters of the if statement which reverses the number and sees if it equals itself.
I've made sure it wasn't a compiler issue, as this is recurring between different compilers. The reverseNumber() function returns the proper number every time I've tested it, so that shouldn't be the problem, however this problem only occurs when the function is involved in the logical comparison. By this I mean if that even I set it equal to a variable and put the variable in the if parameters, the issue still occurs. I'm pretty much stumped. I just hope it's not some silly mistake as I've been on this for a couple days now.
int reversedNum, remainder = 0;
You should be aware that this gives you (in an automatic variable context) a zero remainder but an arbitrary reversedNum. This is actually one of the reasons some development shops have the "one variable per declaration" rule.
In other words, it should probably be:
int reversedNum = 0, remainder;
or even:
int reversedNum = 0;
int remainder;
One other thing that often helps out is to limit the scope of variable to as small an area as possible, only bringing them into existence when needed. An example of that would be:
int reverseNumber(int testNum) {
int reversedNum = 0;
while (testNum != 0) {
int remainder = testNum % 10;
reversedNum = reversedNum * 10 + remainder;
testNum /= 10;
}
return reversedNum;
}
In fact, I'd probably go further and eliminate remainder altogether since you only use it once:
reversedNum = reversedNum * 10 + testNum % 10;
You'll notice I've gotten rid of temp there as well. There's little to gain by putting testNum into a temporary variable since it's already a copy of the original (as it was passed in by value).
And one other note, more to do with the problem rather than the code. You seem to be assuming that there is a palindrome formed that is a multiple of 99. That may be the case but a cautious programmer wouldn't rely on it - if you're allowed to assume things like that, you could just replace your entire program with:
print 9009
Hence you should probably check all possibilities.
You also get the first one you find which is not necessarily the highest one (for example, let's assume that 99 * 17 and 99 * 29 are both palindromic - you don't want the first one.
And, since you're checking all possibilities, you probably don't want to stop at the first one, even if the nested loops are decrementing instead of incrementing. That's because, if 99 * 3 and 97 * 97 are both palindromic, you want the highest, not the first.
So a better approach may be to start high and do an exhaustive search, while also ensuring you ignore the palindrome check of candidates that are smaller that your current maximum, something like (pseudo-code)
# Current highest palindrome.
high = -1
# Check in reverse order, to quickly get a relatively high one.
for num1 in 99 .. 0 inclusive:
# Only need to check num2 values <= num1: if there was a
# better palindrome at (num2 * num1), we would have
# already found in with (num1 * num2).
for num2 in num1 .. 0 inclusive:
mult = num1 * num2
# Don't waste time doing palindrome check if it's
# not greater than current maximum - we can't use
# it then anyway. Also, if we find one, it's the
# highest possible for THIS num1 value (since num2
# is decreasing), so we can exit the num2 loop
# right away.
if mult > high:
if mult == reversed(mult):
high = mult
break
if high >= 0:
print "Solution is ", high
else:
print "No solution"
In addition to properly initializing your variables, if you want the largest palindrome, you should switch the direction of your for loop -- like:
for(int numTwo = 100; numTwo > 10; numTwo--) {
...
}
or else you are just printing the first palindrome within your specified range

/= operation in C++

As I understand this code returns the number of digits entered in the function but I don't understand this operation:
(number /= 10) != 0 at all..I understand that this line
number /= 10
equal to number = number / 10 but why not but why in this function they don't write number / 10 != 0? and what are the differences?
std::size_t numDigits(int number) // function definition.
{ // (This function returns
std::size_t digitsSoFar = 1; // the number of digits
// in its parameter.)
while ((number /= 10) != 0) ++digitsSoFar;
return digitsSoFar;
}
(number /= 10) != 0
This actually has 3 steps. It...
Calculates number / 10
Assigns that value to number
Checks if that value is not equal to 0
So in answer to your question, "why in this function they don't write number / 10 != 0," let's walk through what that does:
Calculates number / 10
Checks if that value is not equal to 0
Can you see the difference between the two?
If you're still not sure why this matters, put an output statement in the while loop that'll show number and digitsSoFar and try to run that function both the way it's written and then with your proposed version.

Having trouble understanding a portion of code (bit operation)

I can't understand how to count number of 1's in binary representation.
I have my code, and I hope someone can explain it for me.
Code:
int count (int x)
{
int nr=0;
while(x != 0)
{
nr+=x%2;
x/=2;
}
return nr;
}
Why while ? For example if i have 1011, it wouldn't stop at 0?
Why nr += x%2 ?
Why x/=2 ?!
First:
nr += x % 2;
Imagine x in binary:
...1001101
The Modulo operator returns the remainder from a / b.
Now the last bit of x is either a 0, in which case 2 will always go into x with 0 remainder, or a 1, in which case it returns a 1.
As you can see x % 2 will return (if the last bit is a one) a one, thus incrementing nr by one, or not, in which case nr is unchanged.
x /= 2;
This divides x by two, and because it is a integer, drops the remainder. What this means is is the binary was
....10
It will find out how many times 2 would go into it, in this case 1. It effectively drops the last digit of the binary number because in base 2 (binary) the number of times 2 goes into a number is just the same as 'shifting' everything down a space (This is a poor explanation, please ask if you need elaboration). This effectively 'iterates' through the binary number, allowing the line about to check the next bit.
This will iterate until the binary is just 1 and then half that, drop the remainder and x will equal 0,
while (x != 0)
in which case exit the loop, you have checked every bit.
Also:
'count`is possibly not the most descriptive name for a function, consider naming it something more descriptive of its purpose.
nr will always be a integer greater or equal to zero, so you should probably have the return type unsigned int
int count (int x)
{
int nr=0;
while(x != 0)
{
nr+=x%2;
x/=2;
}
return nr;
}
This program basically gives the numbers of set bits in a given integer.
For instance, lets start with the example integer 11 ( binary representation - 1011).
First flow will enter the while loop and check for the number, if it is equal to zero.
while(11 != 0)
Since 11 is not equal to zero it enter the while loop and nr is assigned the value 1 (11%2 = 1).nr += 11%2;
Then it executes the second line inside the loop (x = x/2). This line of code assigns the value 5 (11/2 = 5 ) to x.
Once done with the body of the while loop, it then again checks if x ie 5 is equal to zero.
while( 5 != 0).
Since it is not the case,the flow goes inside the while loop for the second time and nr is assigned the value 2 ( 1+ 5%2).
After that the value of x is divided by 2 (x/2, 5/2 = 2 )and it assigns 2 to x.
Similarly in the next loop, while (2 != 0 ), nr adds (2 + 2%2), since 2%2 is 0, value of nr remains 2 and value of x is decreased to 1 (2/2) in the next line.
1 is not eqaul to 0 so it enters the while loop for the third time.
In the third execution of the while loop nr value is increased to 3 (2 + 1%2).
After that value of x is reduced to 0 ( x = 1/2 which is 0).
Since it fails the check (while x != 0), the flow comes out of the loop.
At the end the value of nr (Which is the number of bits set in a given integer) is returned to the calling function.
Best way to understand the flow of a program is executing the program through a debugger. I strongly suggest you to execute the program once through a debugger.It will help you to understand the flow completely.

C++ reading a sequence of integers

gooday programers. I have to design a C++ program that reads a sequence of positive integer values that ends with zero and find the length of the longest increasing subsequence in the given sequence. For example, for the following
sequence of integer numbers:
1 2 3 4 5 2 3 4 1 2 5 6 8 9 1 2 3 0
the program should return 6
i have written my code which seems correct but for some reason is always returning zero, could someone please help me with this problem.
Here is my code:
#include <iostream>
using namespace std;
int main()
{
int x = 1; // note x is initialised as one so it can enter the while loop
int y = 0;
int n = 0;
while (x != 0) // users can enter a zero at end of input to say they have entered all their numbers
{
cout << "Enter sequence of numbers(0 to end): ";
cin >> x;
if (x == (y + 1)) // <<<<< i think for some reason this if statement if never happening
{
n = n + 1;
y = x;
}
else
{
n = 0;
}
}
cout << "longest sequence is: " << n << endl;
return 0;
}
In your program, you have made some assumptions, you need to validate them first.
That the subsequence always starts at 1
That the subsequence always increments by 1
If those are correct assumptions, then here are some tweaks
Move the cout outside of the loop
The canonical way in C++ of testing whether an input operation from a stream has worked, is simply test the stream in operation, i.e. if (cin >> x) {...}
Given the above, you can re-write your while loop to read in x and test that x != 0
If both above conditions hold, enter the loop
Now given the above assumptions, your first check is correct, however in the event the check fails, remember that the new subsequence starts at the current input number (value x), so there is no sense is setting n to 0.
Either way, y must always be current value of x.
If you make the above logic changes to your code, it should work.
In the last loop, your n=0 is execute before x != 0 is check, so it'll always return n = 0. This should work.
if(x == 0) {
break;
} else if (x > y ) {
...
} else {
...
}
You also need to reset your y variable when you come to the end of a sequence.
If you just want a list of increasing numbers, then your "if" condition is only testing that x is equal to one more than y. Change the condition to:
if (x > y) {
and you should have more luck.
You always return 0, because the last number that you read and process is 0 and, of course, never make x == (y + 1) comes true, so the last statement that its always executed before exiting the loop its n=0
Hope helps!
this is wrong logically:
if (x == (y + 1)) // <<<<< i think for some reason this if statement if never happening
{
Should be
if(x >= (y+1))
{
I think that there are more than one problem, the first and most important that you might have not understood the problem correctly. By the common definition of longest increasing subsequence, the result to that input would not be 6 but rather 8.
The problem is much more complex than the simple loop you are trying to implement and it is usually tackled with Dynamic Programming techniques.
On your particular code, you are trying to count in the if the length of the sequence for which each element is exactly the successor of the last read element. But if the next element is not in the sequence you reset the length to 0 (else { n = 0; }), which is what is giving your result. You should be keeping a max value that never gets reset back to 0, something like adding in the if block: max = std::max( max, n ); (or in pure C: max = (n > max? n : max );. Then the result will be that max value.