Why am i getting the garbage value at index 0 - c++

#include <iostream>
using namespace std;
int main()
{
int arr[8];
int n = 0;
while (n < 8)
{
arr[n] = ++n;
}
for (n = 0; n < 8; n++)
{
cout << arr[n]<<" ";
}
}
output- garbage 1 2 3 4 5 6 7
expected output- 1 2 3 4 5 6 7 8

The statement arr[n] = ++n; has Undefined Behavior because it is unspecified if n is incremented before being used as the subscript in arr.
In your case, with your compiler, the increment happens first, so that you never assign anything to arr[0] and write past the end arr[8] of the array.
One way to address this is to split it into two statements:
arr[n] = n;
++n;
The evaluation order is known as sequencing, and the rules have changed as the language has evolved. Of significance, with C++17 the increment of n will happen before calculating the address to store the result in, so you'll always end up with an uninitalized first element and the write past the end of the array.

Turn on your warning flags! Your program can have undefined behavior;
main.cpp:34:18: warning: operation on 'n' may be undefined [-Wsequence-point]
34 | arr[n] = ++n;
| ^~~
main.cpp:34:16: warning: iteration 7 invokes undefined behavior [-Waggressive-loop-optimizations]
34 | arr[n] = ++n;
| ~~~~~~~^~~~~
main.cpp:32:14: note: within this loop
32 | while (n < 8)
Maybe you could do this instead:
int arr[8] { };
int n = 0;
while ( n < 8 )
{
arr[n] = n + 1;
++n;
}
for ( n = 0; n < 8; ++n )
{
std::cout << arr[n] << " ";
}

In C++ the expression on the right hand side (RHS) of the = sign is evaluated first, because you can't store (assign) a value in a variable if you haven't calculated what it is!
int myAge = 10 + 10; // calculates 20 first, then stores it.
You're changing the value of n before assigning to position n in your array - increasing it from 0 to 1 in the first iteration of the loop - and so assigning the result, 1, to array[1].
Why? Well, ++n and n++ are complicated (and frequently confusing) operators in c++, in that that they're both mathematical and assignment operators. ++n is essentially equivalent to:
n = n + 1;
return n;
Where n++ is closer to:
n = n+1;
return n -1;
You can code it more explicitly with simpler operators:
arr[n] = n+1;
n = n+1;
.. or use a for loop as you did in your output code. Using the same looping structures for both might help you achieve consistent outcomes.
You're not alone in struggling with this one. Chris Lattner felt the ++ and -- unary operators' potential for obfuscation and bugs sufficiently outweighed their benefits that they were dropped from Swift 3.

Related

O(n^2) algorithm to find largest 3 integer arithmetic series

The problem is fairly simple. Given an input of N (3 <= N <= 3000) integers, find the largest sum of a 3-integer arithmetic series in the sequence. Eg. (15, 8, 1) is a larger arithmetic series than (12, 7, 2) because 15 + 8 + 1 > 12 + 7 + 2. The integers apart of the largest arithmetic series do NOT have to be adjacent, and the order they appear in is irrelevant.
An example input would be:
6
1 6 11 2 7 12
where the first number is N (in this case, 6) and the second line is the sequence N integers long.
And the output would be the largest sum of any 3-integer arithmetic series. Like so:
21
because 2, 7 and 12 has the largest sum of any 3-integer arithmetic series in the sequence, and 2 + 7 + 12 = 21. It is also guaranteed that a 3-integer arithmetic series exists in the sequence.
EDIT: The numbers that make up the sum (output) have to be an arithmetic series (constant difference) that is 3 integers long. In the case of the sample input, (1 6 11) is a possible arithmetic series, but it is smaller than (2 7 12) because 2 + 7 + 12 > 1 + 6 + 11. Thus 21 would be outputted because it is larger.
Here is my attempt at solving this question in C++:
#include <bits/stdc++.h>
using namespace std;
vector<int> results;
vector<int> middle;
vector<int> diff;
int main(){
int n;
cin >> n;
int sizes[n];
for (int i = 0; i < n; i++){
int size;
cin >> size;
sizes[i] = size;
}
sort(sizes, sizes + n, greater<int>());
for (int i = 0; i < n; i++){
for (int j = i+1; j < n; j++){
int difference = sizes[i] - sizes[j];
diff.insert(diff.end(), difference);
middle.insert(middle.end(), sizes[j]);
}
}
for (size_t i = 0; i < middle.size(); i++){
int difference = middle[i] - diff[i];
for (int j = 0; j < n; j++){
if (sizes[j] == difference) results.insert(results.end(), middle[i]);
}
}
int max = 0;
for (size_t i = 0; i < results.size(); i++) {
if (results[i] > max) max = results[i];
}
int answer = max * 3;
cout << answer;
return 0;
}
My approach was to record what the middle number and the difference was using separate vectors, then loop through the vectors and search if the middle number minus the difference is in the array, where it gets added to another vector. Then the largest middle number is found and multiplied by 3 to get the sum. This approach made my algorithm go from O(n^3) to roughly O(n^2). However, the algorithm doesn't always produce the correct output (and I can't think of a test case where this doesn't work) every time, and since I'm using separate vectors, I get a std::bad_alloc error for large N values because I am probably using too much memory. The time limit in this question is 1.4 sec per test case, and memory limit is 64 MB.
Since N can only be max 3000, O(n^2) is sufficient. So what is an optimal O(n^2) solution (or better) to this problem?
So, a simple solution for this problem is to put all elements into an std::map to count their frequencies, then iterate over the first and second element in the arithmetic progression, then search the map for the third.
Iterating takes O(n^2) and map lookups and find() generally takes O(logn).
include <iostream>
#include <map>
using namespace std;
const int maxn = 3000;
int a[maxn+1];
map<int, int> freq;
int main()
{
int n; cin >> n;
for (int i = 1; i <= n; i++) {cin >> a[i]; freq[a[i]]++;} // inserting frequencies
int maxi = INT_MIN;
for (int i = 1; i <= n-1; i++)
{
for (int j = i+1; j <= n; j++)
{
int first = a[i], sec = a[j]; if (first > sec) {swap(first, sec);} //ensure that first is smaller than sec
int gap = sec - first; //calculating difference
if (gap == 0 && freq[first] >= 3) {maxi = max(maxi, first*3); } //if first = sec then calculate immidiately
else
{
int third1 = first - gap; //else there're two options for the third element
if (freq.find(third1) != freq.end() && gap != 0) {maxi = max(maxi, first + sec + third1); } //finding third element
}
}
}
cout << maxi;
}
Output : 21
Another test :
6
3 4 5 7 7 7
Output : 21
Another test :
5
10 10 9 8 7
Output : 27
You can try std::unordered_map to try and reduce the complexity even more.
Also see Why is "using namespace std;" considered bad practice?
The sum of a 3-element arithmetic progression is 3-times the middle element, so I would search around a middle element, and would start the search from the "upper" end of the "array" (and have it sorted). This way the first hit is the largest one. Also, the actual array would be a frequency-map, so elements are unique, but still track if any element has 3 copies, because that can become a hit (progression by 0).
I think it may be better to create the frequency-map first, and sort it later, simply because it may result in sorting fewer elements - though they are going to be pairs of value and count in this case.
function max3(arr){
let stats=new Map();
for(let value of arr)
stats.set(value,(stats.get(value) || 0)+1);
let array=Array.from(stats); // array of [value,count] arrays
array.sort((x,y)=>y[0]-x[0]); // sort by value, descending
for(let i=0;i<array.length;i++){
let [value,count]=array[i];
if(count>=3)
return 3*value;
for(let j=0;j<i;j++)
if(stats.has(2*value-array[j][0]))
return 3*value;
}
}
console.log(max3([1,6,11,2,7,12])); // original example
console.log(max3([3,4,5,7,7,7])); // an example of 3 identical elements
console.log(max3([10,10,9,8,7])); // an example from another answer
console.log(max3([1,2,11,6,7,12])); // example with non-adjacent elements
console.log(max3([3,7,1,1,1])); // check for finding lowest possible triplet too

Integer Underflow when initializing for loop variable with size_t

I was running the code example below, initially trying to print a character array backwards where count represented the number of characters in the array. Everytime I ran the for loop, i was not initalized to count - 1 instead it was initialized to some very large number. But outside the loop, i is properly initalized to 4. I can't explain why this is happening.
size_t count {5};
size_t i {count - 1UL}; // i is initalized to 4
for(size_t i {count - 1}; i >= 0UL; --i) {
std::cout << i << std::endl;
} // infinite loop, i is initalized to 18446744073709141874
An "unsigned" integer does not have a sign and is always nonnegative. If you do --i on i = 0 then you will get the maximum value of std::size_t.
Do this instead:
// iterates from (count - 1) to 0
for (std::size_t i = count; i--;)
So how does this work? i-- is the postfix decrement operator, which returns the prior value of i. This way, the loop condition is actually comparing count, ..., 1 to zero, while in the loop we get count - 1, ..., 0.
A more generalized version of this idiom is sometimes called the --> operator:
// iterates from (high - 1) to low
for (std::size_t i = high; i-- > low;)
Firstly, i in the outer scope is unused and shaded, secondly an unsigned integer is always greater than or equal to 0. You could have your compiler detect these if only you turned on your compiler warnings:
<source>:7:38: error: comparison of unsigned expression >= 0 is always true [-Werror=type-limits]
7 | for(std::size_t i {count - 1}; i >= 0UL; --i) {
| ~~^~~~~~
<source>:5:17: error: unused variable 'i' [-Werror=unused-variable]
5 | std::size_t i {count - 1UL}; // i is initalized to 4
|
Solution:
for (unsigned long long i = 4ull; i != -1ull; --i) {
std::cout << i << '\n';
}
std::size_t is unsigned integer type. So values of the type never can be negative.
Rewrite the loop like
std::size_t i {count - 1};
do
{
std::cout << i << std::endl;
} while ( i-- );

Task on the number of iterations

There is a number N
every iteration it becomes equal to (N*2)-1
I need to find out how many steps the number will be a multiple of the original N;
( 1≤ N ≤ 2 · 10 9 )
For example:
N = 7; count = 0
N_ = 7*2-1 = 13; count = 1; N_ % N != 0
N_ = 13*2-1 = 25; count = 2; N_ % N != 0
N_ = 25*2-1 = 49; count = 3; N_ % N == 0
Answer is 3
if it is impossible to decompose in this way, then output -1
#include <iostream>
using namespace std;
int main(){
int N,M,c;
cin >> N;
if (N%2==0) {
cout << -1;
return 0;
}
M = N*2-1;
c = 1;
while (M%N!=0){
c+=1;
M=M*2-1;
}
cout << c;
return 0;
}
It does not fit during (1 second limit). How to optimize the algorithm?
P.S All the answers indicated are optimized, but they don’t fit in 1 second, because you need to change the algorithm in principle. The solution was to use Euler's theorem.
The problem, as other answers have suggested, is equivalent to finding c such that pow(2, c) = 1 mod N. This is impossible if N is even, and possible otherwise (as your code suggests you know).
A linear-time approach is:
int c = 1;
uint64_t m = 2;
while (m != 1){
c += 1;
m = (2*m)%N;
}
printf("%d\n", c);
To solve this in 1 second, I don't think you can use a linear-time algorithm. The worst cases will be when N is prime and large. For example 1999999817 for which the above code runs in around 10 seconds on my laptop.
Instead, factor N into its prime factors. Solve 2^c = 1 mod p^k for each prime factor (where p^k appears in the prime factorization of N. Then combine the results using the Chinese Remainder theorem.
When finding the c for a given prime power, if k=1, the solution is c=p-1. When k is larger, the details are quite messy, but you can find a written solution here: https://math.stackexchange.com/questions/1863037/discrete-logarithm-modulo-powers-of-a-small-prime
The problem is that you're overflowing, the int data type only has 32 bits, and overflows 2^31-1 , in this problem you don't need to keep the actual value of M, you can just keep the modulo of n.
while (M%N!=0){
c+=1;
M=M*2-1;
M%=N
}
Edit:In addition, you don't actually need more than N iterations to check if a 0 mod exists, as there are only N different mods to N and it just keeps cycling. so you also need to keep that in mind in case there is no 0 mod.
There is no doubt that the main problem with your code is signed integer overflow
I added a print of M whenever M was changed (i.e. cout << M << endl;) and gave it the input 29. This is what I got:
57
113
225
449
897
1793
3585
7169
14337
28673
57345
114689
229377
458753
917505
1835009
3670017
7340033
14680065
29360129
58720257
117440513
234881025
469762049
939524097
1879048193
-536870911
-1073741823
-2147483647
1
1
1
1
... endless loop
As you see you have signed integer overflow. That is undefined behavior in C so anything may happen!! On my machine I ended up with a nasty endless loop. That must be fixed before considering performance.
The simple fix is to add a line like
M = M % N;
whenever M is changed. See the answer from #Malek
Besides that you shall also use an unsigned integer, i.e. use uint32_t for all variables.
However, that will not improve performance.
If you still have performance issue after the above fix, you can try this instead:
uint32_t N;
cin >> N;
if (N%2==0) {
cout << -1;
return 0;
}
// Alternative algorithm
uint32_t R,c;
R = 1;
c = 1;
while (R != N){
R = 2*R + 1;
if (R > N) R = R - N;
++c;
}
cout << c;
On my laptop this algorithm is 2.5 times faster when testing on all odd numbers in the range 1..100000. However, it might not be sufficient for all numbers in the range 1..2*10^9.
Also notice the use of uint32_t to avoid integer overflow.

What does it mean for an array to have incremented element in square brackets?

In the following algorithm for merge-sort, within the 3rd definition, first while loop there is:
a[k++] = (a[j] < b[i]) ? a[j++] : b[i++].
I understand that the RHS is a conditional statement stating that if the first operand is satisfied, then we should perform the second operand, and if it is not satisfied, we should perform the third operand.
What element does a[k++], a[j++] and b[i++] correspond to?
From my understanding, it should mean in each successive while loop, the element is incremented.
ie. beginning with the initialised values (i=1, j=m+1, k=1) for the first while loop, the next while loop will consist of (i=2, j=m+2, k=2), and so on.
Here is the entire algorithm:
# split in half
m = n / 2
# recursive sorts
sort a[1..m]
sort a[m+1..n]
# merge sorted sub-arrays using temp array
b = copy of a[1..m]
i = 1, j = m+1, k = 1
while i <= m and j <= n,
a[k++] = (a[j] < b[i]) ? a[j++] : b[i++]
→ invariant: a[1..k] in final position
while i <= m,
a[k++] = b[i++]
→ invariant: a[1..k] in final position
a[k] takes the kth element of the array a.
k++ increases the value of k, but returns the previous value.
Thus, a[k++] returns a[k] with the side-effect of increasing k after returning the value of a[k]. a[k++] = 4 is equivalent to:
a[k] = 4
k = k + 1
On the other hand, ++k would increase k before returning it, so a[++k] = 4 would be
k = k + 1
a[k] = 4
The increment and decrement operators work the same in array subscripts as they do in other locations. The postfix version increments the variable and returns its original value, and the prefix version increments the variable and returns its new value.
int i = 0;
do {
if (i++) { std::cout << "i > 0" << std::endl; }
} while (i < 10);
// Checks "i"'s original value.
// First check fails, because i was 0 before incrementing.
// Outputs line 9 times.
// -----
int i = 0;
do {
if (++i) { std::cout << "i > 0" << std::endl; }
} while (i < 10);
// Checks "i"'s incremented value.
// First check succeeds, because i is incremented before being read.
// Outputs line 10 times.
Similarly, if we have this:
int arr[5] = { 1, 2, 3, 4, 5 };
int i = 0;
do {
std::cout << arr[i++] << std::endl;
} while (i < 5);
The variable's original value will be used as the index, and the output will be:
1
2
3
4
5
However, if we have this:
int arr[5] = { 1, 2, 3, 4, 5 };
int i = 0;
do {
std::cout << arr[++i] << std::endl;
} while (i < 5);
The variable's incremented value is used as the index, and the output will be:
2
3
4
5
Considering this, we can take your example line, a[k++] = (a[j] < b[i]) ? a[j++] : b[i++], and read it as meaning this:
Assign value to a[k], then increment k.
Value is conditionally determined based on:
(a[j] < b[i])
If true, value is:
Read a[j], then increment j.
If false, value is:
Read b[i], then increment i.
It can be a useful time-saver if you know how to use it properly, but it can also make things harder to parse if used improperly.

My code is trying to finding all prime numbers between 0 - nth number, what is the use of '+ 1' within the statement 'bool prime[n + 1];'?

I'm new to C++ and is trying to solve the beginner's problem of finding all prime numbers between 0 - nth number. I saw this code online and it works perfectly.
However, my question is what is the use of '+ 1' within the statement 'bool prime[n + 1];'? I have deleted it from the code and everything seems to work just fine. Is it necessary or is it redundant?
void SieveOfEratosthenes(int n) {
bool prime[n + 1];
memset(prime, true, sizeof (prime));
for (int p = 2; p * p <= n; p++) {
// If prime[p] is not changed, then it is a prime
if (prime[p] == true) {
// Update all multiples of p
for (int i = p * 2; i <= n; i += p)
prime[i] = false;
}
}
// Print all prime numbers
for (int p = 2; p <= n; p++)
if (prime[p])
cout << p << endl;
}
int main() {
int n = 1000;
cout << "Following are the prime numbers smaller "
<< " than or equal to " << n << endl;
SieveOfEratosthenes(n);
return 0;
}
In C++ an array of size N have index start from 0 to N-1. so for your problem, for N index assign N+1 size array. so that define the primality to N number.
In C++ (and many other languages) an array of size n has an index for 0 to (n - 1). In this case, you will need to check each number, up to and including n. You therefore need a spot in the array for n, at index prime[n]. This index will only exist if you oversize the array by 1. Otherwise, the array will stop at prime[n - 1].
The reason this works even if you take out the - 1 is that C++ is not fussy about array bounds - once you have an array you can legally read or write at any index, whether or not that index is safe. Notice I said legally, not safely - this is potentially very dangerous behaviour.