I'm getting an heap corruption error and I can't figure out where it is.
The problem is a coin change problem using dynamic programming. C is the array with the coin values, n is the size of the array, T is the target change, usedCoins is an array where the number of used coins should be mapped (i.e if C[1] = 2 and 3 2-coins are used, usedCoins[2] = 2 with all other indexes to 0.
Here's the code:
bool changeMakingUnlimitedDP(unsigned int C[], unsigned int n, unsigned int T, unsigned int usedCoins[]) {
static auto minCoins = new unsigned int[T+1]{UINT_MAX};
minCoins[0] = 0;
static auto lastCoin = new unsigned int[T+1]{0};
for(int i = 0; i < n; i++)
usedCoins[i] = 0;
for(int i = 0; i < n; i++){
for(int j = 1; j <= T; j++){
if(j >= C[i]){
minCoins[j-C[i]] == 0? minCoins[j] = 1 : minCoins[j] = std::min(1 + minCoins[j - C[i]], minCoins[j-C[i]]);
lastCoin[j] = i;
}
}
}
while(T > 0){
unsigned int last = lastCoin[T];
if(last == UINT_MAX || last < 0) return false;
usedCoins[last]++;
T -= C[last];
}
free(minCoins);
free(lastCoin);
return true;
}
When running on debug mode it goes through.
Related
I'm struggling with the bit shifting algorithm for computing the square root of big numbers. I've got arrays of 32bit words and doesn't matter the input, the output is always the same number. Previously the algorithm worked with 1 bit per array cell, but when I switched to words in cells it doesn't work anymore.
I wrote methods that work perfectly separately (adding words, subtracting words, shifting bits to the right) but the whole program doesn't give what I expect.
When the input number has 0 in it's first position, the output is 0, when it has any number but the 1st cell of the array isn't 0, the output is always the same.
The variables:
uint32_t var[4] = {0,0,0,0};
uint32_t w_number[word_len] = {1, 0,0,234324};
uint32_t one[word_len] = {0,0,0,0};
uint32_t var[word_len] = {0,0,0,0};
uint32_t buff[word_len] = {0,0,0,0};
uint32_t result[word_len] = {0,0,0,0};
The code:
one[0] = 1L << 30;
while (isBigger(one, input))
{
shiftR_word(one);
shiftR_word(one);
}
while (!isZero(one))
{
add_word(result, one, var); //the result of one+result is put in Var.
if ((isBigger(input, var) || equals(input, var))) // if (input >= var)
{
subtract_word(input, var, input); // input-=var
shiftR_word(result);
add_word(result, one, result);
}
else
{
shiftR_word(result);
}
shiftR_word(one);
shiftR_word(one);
}
std::cout << "\nOut: ";
printAsBit(result);
std::cout << std::endl;
Here's the shifting algorithm I'm using that may cause the problems.
void shiftR_word(uint32_t w_number[], int n=4)
{
// n - how many words
//(n*32b word) >> 1
bool* odd = new bool[n];
for (int i = 0; i < n; i++)
{
if( w_number[i] & 1 )
odd[i]=true;
else
odd[i]=false;
}
for (int i = 0; i < n; i++)
w_number[i] >>= 1;
for (int i = 0; i <= n-1; i++)
{
if(odd[i])
{
w_number[i+1] = w_number[i+1] | 1 << 31;
}
}
delete[] odd;
}
The add function:
void add_word(uint32_t a[], uint32_t b[], uint32_t result[], int len=4)
{
int carry=0;
for (int i = len-1; i >=0; i--)
{
result[i]=a[i]+b[i]+carry;
carry = (a[i]>result[i] || b[i]>result[i]) ? 1 : 0;
}
}
isBigger method:
bool isBigger(uint32_t a[],uint32_t b[] ,int len=4)
{
for (int i = 0; i < len; i++)
{
if (a[i]>b[i])
{
return true;
}
}
return false;
}
I am unable to spot the error in the code, especially that all of the methods seem to work when I test them separately.
isBigger does not work. If you have (length 2) values of {2, 5} for a and {6, 3} for b it will return true when it should return false. Inside the loop, you want to return false if a[i] < b[i], and only check the next value if the two values are equal.
bool isBigger(const uint32_t a[], const uint32_t b[], int len = 4)
{
for (int i = 0; i < len; i++)
{
if (a[i] > b[i])
return true;
if (a[i] < b[i])
return false;
}
// Only get here if `a` and `b` are equal
return false;
}
Additionally, shiftR_word has Undefined Behavior, because w_number[i+1] can be past the end of the array (when i == n-1, you'll access w_number[n - 1 + 1] or w_number[n]). Your loop condition in this instance should be i < n-1. However, that function is rather inefficient. It can be rewritten to only need one loop and no memory allocation, but that's left as an exercise for the reader.
I have the following code used to calculate primes of the form x^2+ny^2 whihc are not exceeding N. This code runs fine when N is around 80000 but when N is around 10^5 the code breaks down. Why this happens and how to fix this ?
#include <iostream>
#include<iostream>
#include<vector>
const int N = 100000; //Change N in this line
using namespace std;
typedef long long int ll;
bool isprime[N] = {};
bool zprime[N] = {};
vector<int> primes;
vector<int> zprimes;
void calcprime(){
for (int i = 2; i < N; i+=1){isprime[i] = true;}
for (int i = 2; i < N; i+=1){
if (isprime[i]){
primes.push_back(i);
for (int j = 2; i*j < N; j+=1){
isprime[i*j] = false;
}
}
}
}
void zcalc(){
int sqrt = 0; for (int i = 0; i < N; i+=1){if(i*i >= N){break;} sqrt = i;}
for (int i = 0; i <= sqrt; i +=1){
for (int j = 0; j <= sqrt; j+=1){
ll q = (i*i)+(j*j);
if (isprime[q] && !zprime[q] && (q < N)){
zprimes.push_back(q);
zprime[q] = true;
}
}
}
}
int main(){
calcprime();
zcalc();
cout<<zprimes.size();
return 0;
}
Why the code breaks
Out of bounds access. This code breaks because you're doing out of bounds memory accesses on this line here:
if (isprime[q] && !zprime[q] && (q < N)) {
If q is bigger than N, you're accessing memory that technically doesn't belong to you. This invokes undefined behavior, which causes the code to break if N is big enough.
If we change the order so that it checks that q < N before doing the other checks, we don't have this problem:
// Does check first
if((q < N) && isprime[q] && !zprime[q]) {
It's not recommended to have very large c-arrays as global variables. It can cause problems and increase executable size.
(Potentially) very large global arrays. You define isprime and zprime as c-arrays:
bool isprime[N] = {};
bool zprime[N] = {};
This could cause problems down the line for very big values of N, because c-arrays allocate memory statically.
If you change isprime and zprime to be vectors, the program compiles and runs even for values of N greater than ten million. This is because using vector makes the allocation dynamic, and the heap is a better place to store large amounts of data.
std::vector<bool> isprime(N);
std::vector<bool> zprime(N);
Updated code
Here's the fully updated code! I also made i and j to be long long values, so you don't have to worry about integer overflow, and I used the standard library sqrt function to compute the sqrt of N.
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
typedef long long int ll;
constexpr long long N = 10000000; //Change N in this line
std::vector<bool> isprime(N);
std::vector<bool> zprime(N);
vector<int> primes;
vector<int> zprimes;
void calcprime() {
isprime[0] = false;
isprime[1] = false;
for (ll i = 2; i < N; i+=1) {
isprime[i] = true;
}
for (ll i = 2; i < N; i+=1) {
if (isprime[i]) {
primes.push_back(i);
for (ll j = 2; i*j < N; j+=1){
isprime[i*j] = false;
}
}
}
}
void zcalc(){
ll sqrtN = sqrt(N);
for (ll i = 0; i <= sqrtN; i++) {
for (ll j = 0; j <= sqrtN; j++) {
ll q = (i*i)+(j*j);
if ((q < N) && isprime[q] && !zprime[q]) {
zprimes.push_back(q);
zprime[q] = true;
}
}
}
}
int main(){
calcprime();
zcalc();
cout << zprimes.size();
return 0;
}
The value of q can exceed the value of N in your code and can cause a segmentation fault when zprime[q],isprime[q] is accessed. You're iterating i, j till sqrt(N) and have allocated zprime,isprime with N booleans. The value of q can vary from 0 to 2N.
ll q = (i*i)+(j*j);
You can replace bool zprime[N] = {}; and bool isprime[N] = {}; with
bool zprime[N * 2 + 1] = {};
and
bool isprime[N * 2 + 1] = {};
respectively.
The program will no longer segfault. Or, you could check for q < N before accessing isprime[q] and zprime[q].
Also, as has already been pointed out in the comments, (i*i)+(j*j) is an int. It is useless to assign that value to a long long. If you intend to prevent overflow, replace it with ((ll)i*i)+(j*j).
Moreover, for large sized arrays, you should prefer to allocate it on the heap.
I'm finalizing a HW assignment to learn C++ coming from Java and had the code working until they tested it with the entire Gettysburg Address, now I get segment faults. I cannot figure out how to solve this problem, I've tried creating a string using the NEW keyword but still can't get things to sizzle. Any help would be greatly appreciated. Below is the function giving me problems.
void PalindromeFinder::truncateToLargestPalindrome(string& inputString){
//std::string *big = new std::string;
//*big=inputString;
int n = inputString.length();
int longestBegin = 0;
int maxLen = 1;
bool table[1000][1000] = {false};
for (int i = 0; i < n; i++) {
table[i][i] = true;
}
for (int i = 0; i < n-1; i++) {
if (inputString[i] == inputString[i+1]) {
table[i][i+1] = true;
longestBegin = i;
maxLen = 2;
}
}
for (int len = 3; len <= n; len++) {
for (int i = 0; i < n-len+1; i++) {
int j = i+len-1;
if (inputString[i] == inputString[j] && table[i+1][j-1]) {
table[i][j] = true;
longestBegin = i;
maxLen = len;
}
}
}
if(largestPalindromeFound.length()<inputString.substr(longestBegin, maxLen).length()){
this->largestPalindromeFound = inputString.substr(longestBegin, maxLen);}
}
If your input string is bigger than 999 then you'll start accessing memory positions outside of your table matrix that's only 1000x1000.
Accessing memory positions outside of your allocated memory can yield segmentation faults and Gettysburg Address is longer than 1000 characters long.
I cant find out whats wrong with this part of my program, i want to find out most occuring number in my structure(array), but it finds only the last number :/
void Daugiausiai(int n)
{
int max = 0;
int sk;
for(int i = 0; i < n; i++){
int kiek = 0;
for(int j=0; j < n; j++){
if(A[i].datamet == A[j].datamet){
kiek++;
if(kiek > max){
max = kiek;
sk = A[i].datamet;
}
}
}
}
}
ps. its only a part of my code
You haven't shown us enough of your code, but it is likely that you are not looking at the real result of your function. The result, sk is local to the function and you don't return it. If you have global variable that is also named sk, it will not be touched by Daugiausiai.
In the same way, you pass the number of elements in your struct array, but work on a global struct. It is good practice to "encapsulate" functions so that they receive the data they work on as arguments and return a result. Your function should therefore pass both array length and array and return the result.
(Such an encapsulation doesn't work in all cases, but here, it has the benefit that you can use the same function for many different arrays of the same structure tape.)
It is also enough to test whether the current number of elements is more than the maximum so far after your counting loop.
Putting all this together:
struct Data {
int datamet;
};
int Daugiausiai(const struct Data A[], int n)
{
int max = 0;
int sk;
for (int i = 0; i < n; i++){
int kiek = 0;
// Count occurrences
for(int j = 0; j < n; j++){
if(A[i].datamet == A[j].datamet) kiek++;
}
// Check for maximum
if (kiek > max) {
max = kiek;
sk = A[i].datamet;
}
}
return sk;
}
And you call it like this:
struct Data A[6] = {{1}, {2}, {1}, {4}, {1}, {2}};
int n = Daugiausiai(A, 6);
printf("%d\n", n); // 1
It would be nice if you had english variable names, so I could read them a bit better ^^. What should your paramter n do? Is that the array-length? And what should yout funtion do? It has no return value or something.
int getMostOccuring(int array[], int length)
{
int current_number;
int current_count = 0;
int most_occuring_number;
int most_occuring_count = 0;
for (int i = 0; i < length; i++)
{
current_number = array[i];
current_count = 0;
for (int j = i; j < length; j++)
{
int test_number = array[j];
if (test_number == current_number)
{
current_count ++;
if (current_count > most_occuring_count)
{
most_occuring_number = current_number;
most_occuring_count = current_count;
}
}
}
}
return most_occuring_number;
}
this should work and return the most occuring number in the given array (it has a bad runtime, but is very simple and good to understand).
Given code is for generating a magic square in which i have used VLA for the function
create_magic_square(int n, int magic_square[n][n])
print_magic_square(int n, int magic_square[n][n])
#include <stdio.h>
void create_magic_square(int n, int magic_square[n][n]);
void print_magic_square(int n, int magic_square[n][n]);
int main()
{
int size;
printf("This program creates a magic square of a specified size");
printf("The size be an odd number between 1 and 99");
printf("Enter the size of magic square: ");
scanf("%d", &size);
if(size%2 == 0 || size < 0 || size > 99)
{
printf("Wrong Entry!!!");
return 0;
}
int square[size][size];
for( int i = 0; i < size; i++)
for(int j = 0; j < size; j++)
square[i][j] = 0;
create_magic_square(size, square);
print_magic_square(size, square);
return 0;
}
void create_magic_square(int n, int magic_square[n][n])
{
int row = 0, col = n/2;
magic_square[row][col] = 1;
while(magic_square[row][col] <= n*n)
{
int new_row = ((row - 1) + n) % n;
int new_col = ((col + 1) + n) % n;
if(magic_square[new_row][new_col] == 0)
{
magic_square[new_row][new_col] = magic_square[row][col] + 1;
row = new_row;
col = new_col;
}
else if(magic_square[new_row][new_col] != 0)
{
magic_square[row + 1][col] = magic_square[row][col] + 1;
row = row + 1;
}
}
}
void print_magic_square(int n, int magic_square[n][n])
{
for( int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
printf("%d ", magic_square[i][j]);
printf("\n\n");
}
}
when file saved with extension .cpp ,On compiling it is giving the following error:
When I changed this extension to .c, it worked fine.
What is the reason behind this?
I think VLAs are not allowed in C++, is it right?
NOTE: Check this link regarding VLAs as parameter:
Why use an asterisk "[*]" instead of an integer for a VLA array parameter of a function?
You can't use C-style array that way, all but the first extent must be compile-time constant.
What you can do is pass int *magic_square that points to a one-dimensional n*n array, and use a simple index-mapping function to get the linear index of the cell.
You tagged the question as C++, so you should know that
int square[size][size];
is not valid C++ either, though it's valid C99 and some compilers support it through extension.
For C++ I'd suggest to use std::vector<int> vec(size*size) as holder.