C++. Logical expression - c++

I am trying to solve the following task. Given an integer x, I want to compute 2 numbers (a and b) which are:
1) divisible by 2 or 3 (e.g a % 2 == 0 or a % 3 == 0 )
2) x = a +
b
I wrote the following code, to find such a and b.
cin >> x;
if (x % 2 == 0) {
a = b = x / 2;
} else {
a = x / 2;
b = a + 1;
}
while((a % 3 !=0 || a % 2 != 0) && (b % 2 != 0 || b % 3 != 0)) {
a++;
b--;
}
However it does not work. For example when x is 13, it prints out that a = 6 and b = 7. But 7 is not divisible by 2 or 3. What is the problem ?

Examine your continuation condition carefully (where n is some arbitrary integer, possibly different in each use so, for example a != 3n simply means that a is not a multiple of three). I'll show the process:
while((a % 3 != 0 || a % 2 != 0) && (b % 2 != 0 || b % 3 != 0))
( a != 3n OR a != 2n ) AND ( b != 2n OR b != 3n )
( a != 6n ) AND ( b != 6n )
It says: continue while both a is not a multiple of both two and three, and b is not a multiple of both two and three. In other words, it will only continue if both a and b are multiples of six. On the flip side of that, it will of course exit if either a or b is not a multiple of six.
Since an input value of 13 sets a = 6 and b = 7, the continuation case is false on the first iteration (seven is not a multiple of six).
Perhaps it would be better to rethink the way you figure out whether certain number combinations are valid(a). For example (assuming the numbers have to be between 1 and N - 1 since, otherwise, your solution space is likely to be infinite), you could use something like:
#include <iostream>
int main() {
// Get the number.
int num;
std::cout << "Number? ";
std::cin >> num;
// Check all i + j = n for 1 <= i,j < n.
for (int i = 1, j = num - 1; i < j; ++i, --j) {
// Disregard if either number not a multiple of 2 or 3.
if ((i % 2) != 0 && (i % 3) != 0) continue;
if ((j % 2) != 0 && (j % 3) != 0) continue;
std::cout << num << " => " << i << ", " << j << "\n";
return 0;
}
std::cout << num << " => no solution\n";
return 0;
}
Note my use of i < j is the for continuation condition, this is assuming they have to be distinct numbers. If they're allowed to be the same number, change that to i <= j.
(a) Using all of and, or, and not (even implicitly, by the reversal of continuation and exit conditions), is sometimes more trouble than it's worth since De Morgan's theorems tend to come into play:
_____ _ _
A ∩ B ⇔ A ∪ B : (not(A and B)) is ((not A) or (not B))
_____ _ _
A ∪ B ⇔ A ∩ B : (not(A or B)) is ((not A) and (not B))
In cases like that, code can become more readable if you break out the individual checks.
Interestingly, if you run that code with quite a few input values, you'll see the pattern that, if a solution exists, one of the numbers in that solution is always two or three.
That's because, other than the pathological cases of sums less than five (or less than four if the solution is allowed to have identical numbers):
every even number 2n, n > 1 is the sum of 2 and 2n - 2, both multiples of two (2n - 2 = 2(n - 1)); and
every odd number 2n + 1, n > 2 is the sum of 3 and 2n + 1 - 3, the first a multiple of three and the second a multiple of two (2n + 1 - 3 = 2n - 2 = 2(n - 1)).
So, in reality, no loop is required:
if (num < 5) { // 4 if allowing duplicates.
std::cout << num << " => no solution\n";
} else {
int first = (num % 2) == 0 ? 2 : 3;
std::cout << num << " => " << first << ", " << (num - first) << "\n";
}
This actually gives a different result for some numbers, such as 17 = 2 + 15 = 3 + 14 but both solutions are still correct.

Related

Unable to figure out why my solution for Codechef problem MXEVNSUB is failing

Question: https://www.codechef.com/problems/MXEVNSUB
The following is my understanding of the problem.
This problem is asking for the maximum length of its contiguous subsequence with an even sum.
For
N = 1, Sum = 1 (odd sum but we need not bother about N = 1, since 2 <= N <= 10000)
N = 2, Sum = 3 (odd sum)
N = 3, Sum = 6 (even sum)
N = 4, Sum = 10 (even sum)
N = 5, Sum = 15 (odd sum)
N = 6, Sum = 21 (odd sum)
.
.
.
N = k- 1, Sum = ((k - 1) * k) / 2 (I assume it’s sum is odd)
N = k, Sum = (k * (k + 1)) / 2 (Worst case, this one might be odd too)
So I used the following logic in my code.
If the sum of numbers up to N is even, I can simply print the value of N and break out of the loop, else I reduce N by 1 and repeat the process.
The inner while loop in my code is a O(1) operation since in the worst case it runs 3 times (2 times for odd sum and the third time when sum is even)
Here is the code which is giving me WA
#include<bits/stdc++.h>
using namespace std;
int main(){
int tc; cin >> tc;
while(tc--){
int n; cin >> n;
if(n == 2) {
cout<<-1<<endl;
continue;
}
while(n){
if( ( (n * (n + 1) ) / 2 ) % 2 == 0){
cout << n << endl;
break;
}
n--;
}
}
}
I tried to submit the solution and it works for the sample test cases but is giving me Wrong Answer on submitting.

Is there a way to optimise the Collatz conjecture into a branchless algorithm?

I'm trying to create an algorithm that will compute the collatz conjecture, this is the code so far:
while (n > 1) {
n % 2 == 0 ? n /= 2 : n = n * 3 + 1;
}
I was wondering if there was a way to optimize this any further since efficiency and speed is crucial for this, and I've heard about branchless programming but I'm not sure how to implement it, or if it's worth it to begin with.
Sure. You need the loop, of course, but the work inside can be done like this:
n /= (n&-n); // remove all trailing 0s
while(n > 1) {
n = 3*n+1;
n /= (n&-n); // remove all trailing 0s
}
It also helps that this technique does all the divisions by 2 at once, instead of requiring a separate iteration for each of them.
One way to make it branchless (except for the loop condition) is to multiply n / 2 with the n % 2 == 0 result (1 for true) and multiply (n * 3 + 1) with the negated result of (n % 2 == 0) and add them together.
void collatz(unsigned long long n) {
std::cout << n << '\n';
while (n > 1) {
auto m = n % 2 == 0;
n = m * (n / 2) + !m * (n * 3 + 1);
std::cout << n << '\n';
}
}
Demo

How does printing Josephus sequence work?

The CSES problem Josephus Problem I requires us to print the sequence of how people are chosen for n people and k = 2. I found an elegant solution to this here.
Basically, the code is similar to this:
void J(int n)
{
int a = 1, b = 0;
while (n > 0)
{
for (int i = 2; i <= n; i += 2)
{
cout << a * i + b << ' ';
}
if (n & 1)
cout << a + b << ' ', b += a;
else
b -= a;
a <<= 1;
n >>= 1;
}
}
Can someone explain why it works?
I made a few changes to the code to illustrate how it works.
void J(int n)
{
int a = 1, b = 0;
while (n > 0)
{
std::cout << "n=" << n << std::endl;
std::cout << "a=" << a << ", b=" << b << std::endl;
for (int i = 2; i <= n; i += 2)
{
std::cout << a * i + b << ' ';
}
if (n & 1) // equivalent to n % 2 == 1 (if n is odd)
std::cout << '*' << a + b << ' ', b += a;
else
b -= a;
std::cout << std::endl;
a <<= 1; // a = a * 2;
n >>= 1; // n = n / 2;
}
}
The first thing to note is that the variables a and b are initialized to values that allow us to compute the positions of people who will be eliminated as we go around the circle (also using the iterator i in the for loop). The initial values of a = 1, b = 0 are so we can eliminate every even numbered person on the first iteration.
Next, every time through the while(n) loop, half of the remaining people will be eliminated. If n is odd, we loop back to the beginning of the circle and also eliminate the person at the start of the current iteration.
I think the tricky part here is how the values of a and b change in the if statement. If n is odd we increment b by the value of a. If n is even we subtract the value of a from b. Then we double the value of a to get ready for the next iteration around the circle. The values of a and b are chosen to account for the gaps in the circle left by eliminating positions in the previous iterations.
Finally, we divide n by 2 before the next iteration, since there are half as many people left in the circle. Here's a sample run for n=19.
Output:
n=19
a=1, b=0
2 4 6 8 10 12 14 16 18 *1
n=9
a=2, b=1
5 9 13 17 *3
n=4
a=4, b=3
11 19
n=2
a=8, b=-1
15
n=1
a=16, b=-9
*7

c++ noob coder questions

using namespace std;
int main()
{
cout << "\n\n Find the perfect numbers between 1 and 500:\n";
cout << "------------------------------------------------\n";
int i = 1, u = 1, sum = 0;
cout << "\n The perfect numbers between 1 to 500 are: \n";
while (i <= 500)
{
while (u <= 500)
{
if (u < i)
{
if (i % u == 0)
sum = sum + u;
}
u++;
}
if (sum == i) {
cout << i << " " << "\n";
}
i++;
u = 1;
sum = 0;
}
}
why we added u=1 and sum=o in the last two lines? Can somebody help me with this? I am not able to comprehend the logic behind changing the logic at the end.
Those lines are for re-initializing the variables.
The code you have posted is for finding the perfect numbers which are just numbers that equals the sum of its own proper divisors. eg: 6, the proper divisors are 1, 2, 3. sum of 1 + 2 + 3 = 6. So, 6 is a perfect number.
The first while loop
while (i <= 500)
is for going through the numbers between 1 and 500 one by one
and the second while loop
while (u <= 500)
is for checking the divisors for a particular i. At first the loop will run for i = 1, the second while loop runs for 500 times and check the divisors of 1. Now, for i = 2, we have to check the divisors again from u = 1 right, so the re-initialization is done after the second while loop.
actually you should change the second loop to
while (u < i)
or even better
while (u <= (i / 2))

How to determine, how many number of digits 3 is in variable

I have a variable which contains this numbers
int n = 6396339;
I need to determine how many digits 3 is in variable.
So far i trued like this:
int n = 6396339, counter = 0;
while (n > 0)
{
if ((n % 10) % 3 == 0) {
counter++;
}
n /= 10;
}
cout << counter << endl;
But this algorithm is not working correctly. Could you please help me to solve problem.
(n % 10) % 3 == 0
is true for any digit that is divisible by three, i.e. 0, 3, 6 and 9. Just check whether the digit is equal to 3:
(n % 10) == 3
You could print the number to a string, then traverse the string and check each character whether it is '3'.