Increment working very strangely - c++

This program is supposed to give to the last 100 digits of any size factorial. However, there's something weird going on with the counter2++ in main(). counter2 is incremented +1 for each time the loop runs in the main() function (which is 99 times). However this is what is displayed:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
71
86
90
123
164
196
207
254
300
362
432
471
551
620
630
708
761
772
857
896
985
1036
1100
1116
1207
1209
1280
1356
1417
1452
1512
Counter2 ends up being 1512 instead of 100, but if I remove either mult(i) or carry() from main() then it displays 100. Why does counter2 end up being 1512 and not 100?
#include <iostream>
using namespace std;
int numbers[100];
int counter2 = 0;
void init(){
//sets elements 1-99 of numbers[] to 0, increments counter2 by 1, sets numbers[0] = 1
for (int i = 1; i < 100; i++){
numbers[i] = 0;
}
numbers[0] = 1;
counter2++;
}
void mult(int x){
//multiplies each element by 1 through n to calculate for !n
//this is used to represent a very large number without using a BigInt library
//the nth element is a placeholder for the n+1 position of the number
//e.g 2nd element represents 100-900 of the number, 4th represents 1000-9000, etc
//carry() is used to take care of overflow, so that it's only 1 digit per element
for (int i = 0; i < 100; i++){
numbers[i] *= x;
}
}
void carry(){
//in order to make previous function work, this adds any overflow to the next
//element. e.g: 8 * 4 = 32, 3 is added to numbers[i+1], sets numbers[i] to 2
int counter = 0;
for (int i = 0; i < 100; i++){
if (numbers[i] >= 10){
counter = numbers[i] / 10;
numbers[i+1] += counter;
numbers[i] = numbers[i] % (counter * 10);
}
}
}
int main()
{
init();
for (int i = 2; i < 101; i++){
//calculates the last 100 digits of !100, but counter2 ends up being 1512
mult(i);
carry();
counter2++;
cout << counter2 << endl;
}
}

You are writing past the end of the numbers array in carry():
numbers[i+1] += counter;
Here, i can be 99, in which case numbers[i+1] is out of bounds.
Technically, this is undefined behaviour. What happens in practice is that you overwrite the count2 variable, which happens to sit in memory right after the array.
One nasty thing about memory bugs is that they can go symptomless for a long time, and then surface in the worst possible circumstances. valgrind is a great tool for detecting problems of this type.

In this line
numbers[i+1] += counter;
you are writing out of bounds of array numbers[100];when i == 99 thus changing the value of int counter2 = 0; which (in your case, but not necessarily) sits right next to numbers in memory.

Related

Problem in Knights Tour using backtracking

I am getting a infinite loop when I try and run my solution for the Knights Tour problem using Backtracking
My Solution Code:
Link: https://ideone.com/Ud92vF
code:
#include <bits/stdc++.h>
using namespace std;
bool valid(int arr[8][8],int r,int c)
{
if(r>=0 and r<8 and c>=0 and c<8 and arr[r][c]== -1)
return true;
return false;
}
void fun(int arr[8][8],int r,int c,int x)
{
if(x==64){
cout<<"***********************ARRAY FOUND***********************\n";
for(int i=0;i<8;i++){
for(int j=0;j<8;j++)
cout<<arr[i][j]<<" ";
cout<<"\n";
}
return;
}
if(!valid(arr,r,c))
return;
arr[r][c] = x;
fun(arr,r-2,c+1,x+1); fun(arr,r-2,c-1,x+1);
fun(arr,r-2,c+2,x+1); fun(arr,r-2,c-2,x+1);
fun(arr,r+2,c+1,x+1); fun(arr,r+2,c-1,x+1);
fun(arr,r+1,c+2,x+1); fun(arr,r+1,c-2,x+1);
arr[r][c] = -1;
}
int main()
{
int arr[8][8] ;
for(int i=0;i<8;i++){
for(int j=0;j<8;j++)
arr[i][j] = -1;
}
int r=0,c=0,x=0; fun(arr,r,c,x);
}
Make sure your move array is correct:
fun(arr,r-2,c-1,x+1); fun(arr,r-2,c+1,x+1);
fun(arr,r-1,c-2,x+1); fun(arr,r-1,c+2,x+1);
fun(arr,r+1,c-2,x+1); fun(arr,r+1,c+2,x+1);
fun(arr,r+2,c-1,x+1); fun(arr,r+2,c+1,x+1);
With this I get a right answer:
***********************ARRAY FOUND***********************
0 11 8 5 2 13 16 19
9 6 1 12 17 20 3 14
30 27 10 7 4 15 18 21
63 24 31 28 35 22 47 44
32 29 26 23 48 45 36 57
25 62 51 34 39 56 43 46
52 33 60 49 54 41 58 37
61 50 53 40 59 38 55 42
Note that as you use the 65th move to validate you answer, you'll get 8 of the same correct answers in a row. And then another 8. Etc. You can fix this by printing after your 64th move:
void fun(int arr[8][8],int r,int c,int x)
{
if(!valid(arr,r,c))
return;
arr[r][c] = x;
if(x==63){
cout<<"***********************ARRAY FOUND***********************\n";
for(int i=0;i<8;i++){
for(int j=0;j<8;j++)
cout<<arr[i][j]<<" ";
cout<<"\n";
}
}
else
{
fun(arr,r-2,c-1,x+1); fun(arr,r-2,c+1,x+1);
fun(arr,r-1,c-2,x+1); fun(arr,r-1,c+2,x+1);
fun(arr,r+1,c-2,x+1); fun(arr,r+1,c+2,x+1);
fun(arr,r+2,c-1,x+1); fun(arr,r+2,c+1,x+1);
}
arr[r][c] = -1;
}
And one last issue is that you only ever start at {0,0} so you'll only find knights tours which start on that square. You really want to start from every square to find all possible knights tours. Or if you're feeling clever you only need to check a subset of the starting squares and use symmetry to generate the others.

Where is this array value coming from?

So I'm practicing coding before classes begin again and I wanted to create a random array of 10 integers and wanted to find which two numbers, when added together, equal greater than 100.
When I run the code below
int arr[9];
for(int i = 0; i<=9; i++){
arr[i]=(rand()%100)+1;
cout<<arr[i]<<endl;
}
cout<<endl;
for(int k = 0; k<=9; k++){
for (int j = k+1; j<=9; j++){
if((arr[k]+arr[j])>100){
cout<<arr[k]<<" + "<<arr[j]<<" "<<"over 100"<<endl;
}
else{
cout<<arr[k]<<" + "<<arr[j]<<" "<<"under 100"<<endl;
}
}
}
return 0;
I notice that the value of arr[9] is equal to one number but the program has another number for it.
For example: the array that's created is
[42
68
35
1
70
25
79
59
63
65]
but my output shows a 9 as arr[9]
42 + 68 over 100
42 + 35 under 100
42 + 1 under 100
42 + 70 over 100
42 + 25 under 100
42 + 79 over 100
42 + 59 over 100
42 + 63 over 100
42 + 9 under 100
(I'll just include the first loop to not make this any longer)
Where did my 65 go??
Where did the 9 come from??
Did I write something wrong??
Thanks
I notice that the value of arr[9] is equal to one number but the program has another number for it.
Counting in computers starts from 0 and ends at one number less than the total size. For int arr[9]
the ninth index is arr[8]
the 1st index is arr[0]
the 2nd index is arr[1]
When you do arr[9], you are crossing the boundary (accessing an element that's not in the range) which leads to undefined behaviour.
As a result, your loop should stop at i < 9:
for(int i = 0; i < 9; i++) // i < 9 now vs i <=9
The same changes need o be made to the loops below the first one.

Binary Search TestCase Not Returning a Value

So I am trying to solve the following question
Input Format is
N
x x x x x ...
q
y y y y y ...
N=size of array
x,x,x ... are elements of array
q=no of queries
y,y,y .. are queries to be searched in the array using binary search
Here is My code
#include <iostream>
#include<algorithm>
using namespace std;
int main()
{
int N,q;
cin>>N;
int a[N];
for(int i=1;i<=N;i++)
{
cin>>a[i];
}
cin>>q;
int b[q];
for(int i=0;i<q;i++)
{
cin>>b[i];
}
int len=sizeof(a)/sizeof(a[1]);
sort(a,a+len);
int beg=1,end=N;
for(int j=0;j<q;j++)
{
beg=1;end=N;
while(beg<=end)
{
int mid=(beg+end)/2;
if(b[j]==a[mid])
{
cout<<mid<<endl;
break;
}
else if(b[j]<a[mid])
{
end=mid-1;
}
else
beg=mid+1;
}
}
return 0;
}
My code is giving the following output which is wrong
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for the input
100
100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
correct output is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Arrays are 0-based.
Arrays are not variable-length in C++.
You have a wrong update here:
else if(b[j]<a[mid])
{
end=mid-1;
}
The end is non-inclusive.
You will also want to keep going until (beg<end) not beg<=mid - otherwise mid will simply equal both.
Here's C++ version that fixes all of the above and uses iterators instead of indexes. Iterators remove the ambiguity (base-0 vs base-1) and make it very explicit that a range is [begin, end), by contract.
Live ON Coliru
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main() {
int N;
cin >> N;
std::vector<int> a(N);
std::copy_n(std::istream_iterator<int>(std::cin), N, a.begin());
int q;
cin >> q;
std::vector<int> b(q);
std::copy_n(std::istream_iterator<int>(std::cin), q, b.begin());
sort(a.begin(), a.end());
for (auto query : b) {
auto beg = a.begin();
auto end = a.end();
while (beg < end) {
auto mid = beg + (end-beg) / 2;
if (query == *mid) {
cout << *mid << endl;
break;
} else if (query < *mid) {
end = mid;
} else beg = mid + 1;
}
}
}
Prints
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Problem 1
Your program has undefined behavior due to accessing a using an out of bounds index in the following loop.
for(int i=1;i<=N;i++)
{
cin>>a[i];
}
That loop needs to be changed to use a 0 based index.
for(int i = 0; i < N; i++)
{
cin >> a[i];
}
Problem 2
For similar reasons, the initial value of beg needs to be 0, not 1.
Problem 3
You are comparing with values of a[mid] but you are outputting mid. The output also needs to be a[mid].
Problem 4
else if(b[j]<a[mid])
{
end=mid-1;
}
needs to be
else if(b[j]<a[mid])
{
end=mid;
}
With the above changes, the program works as expected in my environment. Here's the updated program:
#include <iostream>
#include<algorithm>
using namespace std;
int main()
{
int N,q;
cin>>N;
int a[N];
for(int i=0;i<N;i++)
{
cin>>a[i];
}
cin>>q;
int b[q];
for(int i=0;i<q;i++)
{
cin>>b[i];
}
int len=sizeof(a)/sizeof(a[1]);
sort(a,a+len);
int beg=0,end=N;
for(int j=0;j<q;j++)
{
beg=0;end=N;
while(beg<end)
{
int mid=(beg+end)/2;
if(b[j]==a[mid])
{
cout << a[mid] << endl;
break;
}
else if(b[j]<a[mid])
{
end=mid;
}
else
beg=mid+1;
}
}
return 0;
}
See it working at https://ideone.com/wgF2IS.
Array start with 0 index.so make sure for N elements your loop must start with zero index.
for(int i = 0; i < N; i++)
{
cin >> a[i];
}
Similarly, for same reason assign beg '0' value and end 'N-1' value.

Wrong answer although the whole program logic seems to be working [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
This is my solution to the problem Codeforces-D2A-129 Cookies. The program outputs a wrong answer at testcase 11, which is:
82
43 44 96 33 23 42 33 66 53 87 8 90 43 91 40 88 51 18 48 62 59 10 22 20 54 6 13 63 2 56 31 52 98 42 54 32 26 77 9 24 33 91 16 30 39 34 78 82 73 90 12 15 67 76 30 18 44 86 84 98 65 54 100 79 28 34 40 56 11 43 72 35 86 59 89 40 30 33 7 19 44 15
My program:
#include <cstdio>
#include <algorithm> // for count() and sort()
#include <vector>
using namespace std;
// function prototype
void erase_duplicates(vector<int> &, int, int);
int main()
{
int num; // number of bags of cookies
int total = 0; // total number of cookies
int ways = 0; // number of ways Olga can take a bag of cookies
int duplicates = 0; // number of duplicates of an element
scanf("%i", &num); // getting number of bags of cookies
vector<int> cookies(num); // number of cookies in the ith bag
// getting number of cookies in each bag
for(int i = 0; i < num; i++)
scanf("%i", &cookies[i]);
for(int j = 0; j < num; j++) // calculating total number of cookies
total += cookies[j];
// sorting the input
sort(cookies.begin(), cookies.end());
for(int k = 0; k < cookies.size(); k++)
{
if((total - cookies[k]) % 2 == 0)
{
// adding number of duplicates of the current element to the number of ways
duplicates = count(cookies.begin(), cookies.end(), cookies[k]);
ways += duplicates;
// erasing the duplicates of that element
erase_duplicates(cookies, cookies[k], k);
}
}
//printing the possible number of ways
printf("%i", ways);
return 0;
}
// This function erases the duplicates of the element passed as the second argument.
// Parameters are: vector of integers, element, index of the element.
void erase_duplicates(vector<int> &cookies, int value, int k){
for(int i = k; i < cookies.size(); i++){
if(cookies[i] == value) // if it is a duplicate, remove it.
cookies.erase(cookies.begin() + i);
}
}
What's wrong with my code?
There is actually no need of sorting.
The problem can be solved as -
First sum all the array elements and find the number of even and odd elements.
Next if sum of array elements is odd then the bags having odd number of cookies can be stolen so answer would be the number of odd elements and if the sum is even then the answer is number of bags with even number of cookies.
Logic - Difference of two odd number is even
Difference of two even numbers is even
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n;
vector<int> num;
cin>>n;
num.resize(n);
int even=0,odd=0,sum=0;
for(int i=0;i<n;i++)
{
cin>>num[i];
sum+=num[i];
if(num[i]%2)
odd++;
else even++;
}
if(sum%2)
cout<<odd<<endl;
else cout<<even<<endl;
return 0;
}

how to check a matrix for duplicate numbers C++

I'm trying to generate a 5x20 matrix filled with random numbers. How can I make sure none of the random numbers are duplicates? This is the code I have for filling the matrix with random numbers.
srand(time(0));
int matrix[5][20];
int i = 0;
int j = 0;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 20; j++)
{
matrix[i][j] = 1 + (rand() % 100);
cout << matrix[i][j] <<"_";
}
cout << endl;
}
the code works but there are sometimes duplicates. If this were an array I could make use of a simple for loop and compare all of the elements in the array. but I have no idea how to do so with a matrix. I have searched everywhere but cant seem to find a solution.
It's not quite fit your question title but I think you should take a look.
for (i = 0; i < 5; i++)
{
for (j = 0; j < 20; j++)
{
matrix[i][j] = 1 + (rand() % 100);
cout << matrix[i][j] <<"_";
}
cout << endl;
}
I don't know the 5x20 and 100 (in rand() % 100) is compulsory or just an example you want to give. So I suggest for all case I can consider:
Let call the number of matrix elements is a, the number of set (contains all possible generated number) is b. In your is example, a is 5x20=100 and b is 100 (from 1 to 100).
a > b: no valid matrix without duplicates since Dirichlet principle
a == b: take a look at http://en.cppreference.com/w/cpp/algorithm/random_shuffle. Just create an 1-dimension array containing consecutive number from 0 to b-1 (or from min and max of your range) and permute them. Then use it to fill in the matrix.
a < b: similar to case a==b, but you just take a part of the permutation.
Of course, when a =< b then you can use rand() but you have to check duplicate and retry rand(), which is quite complicated. You can create a mark array (which cost memory) or iterate through your matrix again (which cost time).
as a heads up, you shouldn't use rand() unless you've got explicit reasons to (such as a professor's requirements).
The following approach uses a GetIndex function to simulate an int[5][20] with an int[100]. See if you can figure out how to use the code I wrote to create an int[5][20].
Your code fills the matrix with random numbers between 1 and 100 (1 + (rand() % 100)) inclusively, but you do no work to ensure you don't get duplicates! So you won't be able to guarantee that you don't get duplicates (in fact, it's very unusual for you to get no duplicates).
If you first initialize all your values to 1,...,100 and then later shuffle them, you know you have no duplicates.
#include <iostream>
#include <iomanip>
#include <random>
#include <algorithm>
constexpr size_t kDefaultMatrixHeight = 20;
constexpr size_t kDefaultMatrixWidth = 5;
constexpr size_t GetIndex(size_t i, size_t j) {
return i * kDefaultMatrixWidth + j;
}
int main() {
int matrix[kDefaultMatrixWidth * kDefaultMatrixHeight];
for (size_t i = 0 ; i < kDefaultMatrixHeight * kDefaultMatrixWidth ; i++) {
matrix[i] = i + 1;
}
std::mt19937 rng(std::random_device{}());
std::shuffle(std::begin(matrix), std::end(matrix), rng);
for (size_t i = 0 ; i < kDefaultMatrixHeight ; i++) {
for (size_t j = 0; j < kDefaultMatrixWidth ; j++) {
std::cout << std::setw(4) << matrix[GetIndex(i,j)];
}
std::cout << '\n';
}
}
And for example output:
Test#Test:/tmp/example$ g++ example.cpp && ./a.out
93 28 70 14 39
83 3 80 95 58
42 69 71 16 49
75 63 41 82 46
26 50 81 33 97
65 10 77 68 12
8 19 30 86 37
57 24 78 31 88
2 90 4 13 56
36 15 35 32 85
29 76 99 45 18
54 11 44 62 98
9 96 79 34 27
40 21 52 22 55
72 1 47 92 59
94 7 64 91 53
74 5 61 100 89
48 23 66 67 51
38 6 87 17 20
60 25 84 43 73
not exactly answer your question but for your purpose you can try something like this:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
srand(time(0));
int matrix[5][20];
int *pmatrix = &matrix[0][0];
int i = 0;
for (i = 0; i < 100; i++)
{
pmatrix[i] = i+1;
}
std::random_shuffle(pmatrix, pmatrix+100);
for (i = 0; i < 100; i++)
{
std::cout<<pmatrix[i]<<",";
}
}
cpp.sh/5bnyt
Update fixed memory out of bounds problem.