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
I had to make a program that checks if two words can be obtained one from the other by permutating the letters. I wrote the code as you can see below and I struggled quite a long time to find out why the program is crashing, and at some point I had the idea to change the fundametal type of these variables from unsigned int (unsigned int code = 0, i, j, counter = 0, ok = 1;) to integer (int code = 0, i, j, counter = 0, ok = 1;) and now it works properly but I don't know what changed so that now it works. I know (please correct me if I'm wrong) that unsigned int goes from 0 (including 0) to a very large number. All the variables were not going under 0, so I don't know why it didin't work in the unsigned int version and how the fundamental type changing solved the crash.
#include<iostream>
#include<string.h>
using namespace std;
int main()
{ char word1[50], word2[50];
unsigned int code = 0, i, j, counter = 0, ok = 1;
cout << "Type in the first word and then press ENTER:";
cin.getline(word1, 50);
cout << "Type in the second word and then press ENTER:";
cin.getline(word2, 50);
cout << endl;
if (strlen(word1) == strlen(word2)) //If the two words don't have the same lenght, it's impossible to obtain one word of the other by permutating it's letters.
{ for (i = 0; word1[i]; i++) /*This nested FOR will generate a number in the code variable. The first digit will indicate how many times will the letter word1[0] be found in word2,
the second digit will indicate how many times will the letter word1[1] be found in word2 and so on until the end of word1*/
{ counter = 0;
for (j = 0; word2[j]; j++)
if (word1[i] == word2[j])
counter += 1;
code = code * 10 + counter;
}
i = strlen(word1) - 1;
while (i >= 0 && ok) /*In this loop we are checking if the code is valable also for the word1 itself. If it is, it means that the words can be obtained one of the other by permutating the letters*/
{ counter = 0;
for (j = strlen(word1) - 1; j >= 0; j--)
if (word1[i] == word1[j])
counter++;
if (counter == code % 10)
ok = 1;
else
ok = 0;
code = code / 10;
i--;
}
if (ok)
cout << "Yes, the words can be obtained one of the other by permutating the letters.";
else
cout << "No, the words can not be obtained one of the other by permutating the letters.";
}
else
cout << "No, the words can not be obtained one of the other by permutating the letters.";
cin.get();
}
Part of your code goes:
while (i >= 0 && ok) { /* ...stuff here... */ --i; }
With an unsigned, if i is 0 and you decrement it, it will become the maximum unsigned value. As a result, i is always greater than or equal to 0 and the while loop keeps executing.
My guess is that is what is happening, and then, when you access word[i] you are accessing outside of the bounds of the array and crashing.
the problem is probably from the following code:
for (j = strlen(word1) - 1; j >= 0; j--)
because you defined j as unsigned int the for loop goes on for ever and never breaks.
Beginners mistake: Consider that if i is an unsigned int, i >= 0 will always be true. It cannot be false. If you set i to 0 and then subtract 1, you will get a very large positive number.
If your compiler didn't give you a warning, ask someone to show you how to turn more warnings on.
Related
I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<double> x(10);
for (unsigned int i = 9; i >= 0; i--)
{
cout << "i= " << i << endl;
x[i] = 1.0;
}
cout << "x0= " << x[0] << endl;
return 0;
}
I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
Thank you very much!
The problem here is that an unsigned integer is never negative.
Therefore, the loop-test:
i >= 0
will always be true. Thus you get an infinite loop.
When it drops below zero, it wraps around to the largest value unsigned value.
Thus, you will also be accessing x[i] out-of-bounds.
This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.
Thus, if you want to use unsigned integers, you can try one of the following possibilities:
for (unsigned int i = 9; i-- != 0; )
and
for (unsigned int i = 9; i != -1; i--)
These two were suggested by GManNickG and AndreyT from the comments.
And here's my original 3 versions:
for (unsigned int i = 9; i != (unsigned)0 - 1; i--)
or
for (unsigned int i = 9; i != ~(unsigned)0; i--)
or
for (unsigned int i = 9; i != UINT_MAX; i--)
The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.
Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.
In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).
The problem is here:
for (unsigned int i = 9; i >= 0; i--)
You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).
As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
My preferred method for a reverse loop with an index is this:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
and that is why because it maps most closely to the normal loop equivalent:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}
If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:
auto& my_element = my_vector[i - 1];
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 8 years ago.
Improve this question
I have seen this, but this is not what I am looking for.
The problem is same that is to find the largest palindrome which is the product of two three digit numbers.
Since my program was not working so I made a little change, instead of finding the largest palindrome which is the product of two three digit numbers I have written the program to find the largest palindrome which is the product of two two digit numbers.
Kindly see the program:
#include <iostream>
using namespace std;
int main() {
int i, j, n, s, m, w;
for (i = 99; i > 9; i--) {
for (j = 99; j > 9; j--)
n = i * j;
s = n;
while (n != 0) {
w = 0;
m = n % 10;
w = w * 10 + m;
n = n / 10;
}
if (s == w)
cout << s << endl;
break;
}
return 0;
}
The problem with this program is that it is neither showing any error nor giving any result.
So kindly help me to find the problem in my program.
Right now you are missing the curly braces for the j-loop. The current code is doing 99! * i.
Then you would have to focus on storing the largest palindrome value instead of just printing all those values to the screen (this is considering your implementation, it is not the most efficient one by any means).
Some modified version of your code:
#include <iostream>
using namespace std;
int main() {
int max_product = 0;
for (int i = 99; i > 9; i--) {
for (int j = i; j > 9; j--) {
int product = i * j;
if (product < max_product)
break;
int number = product;
int reverse = 0;
while (number != 0) {
reverse = reverse * 10 + number % 10;
number /= 10;
}
if (product == reverse && product > max_product) {
max_product = product;
}
}
}
cout << "Solution: " << max_product << endl;
return 0;
}
You have various problems:
Need one more pair of {, }. After the for-loop of j. The only instruction the for-loop of j is executing is: n = i * j; with the braces the rest of the instruction (testing if it's a palindrome) are out of the loop.
the variable w the reverse of the number to test for palindrome is reset his value to 0 in every execution of while (n != 0) loop resulting in incorrect reverse value (and never find the palindrome).
The max palindrome product of 2 two digits number don't have to be the first one found with this 2 for-loop, eg: suppose that there is 2 valid solutions i = 98, j = 2 and i = 70, j = 65 in this case i*j would be in first solution = 196 in the second = 4550 and when you found the first you could not stop the search. In your code using the break don't do what I think you are waiting for (stop the search), only stop the search with the actual i value.
Some notes about the modified code:
The two for-loop don't need to be from 99..9, in this case you are testing a lot of product two times (eg: 98*99, are testing when i == 98 and j == 99 and i == 99 and j == 98), you could restrict j to be always less or equal to i.
Using max_product to maintain the maximum palindrome product found. And use that info in the inner loop (if (product < max_product)) for early exit when no better solution could be found.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
How can I generate all combinations of n elements in groups of k?
For example, takig "abcd" in groups of 3, from [aaa] to [ddd]?
EDIT: What I've "accomplished" so far:
int main (int argc, char * argvc[]) {
int tComb = 0, array[7] = { 48 , 48 , 48 , 48 , 48 , 48 , 48 };
while ( tComb < atoi(argvc[1]) ) {
for (int i = 6 ; i>0 ; i--) {
if (array[i] == 58)
array[i] = 65;
if (array[i] == 91)
array[i] = 97;
if (array[i] == 123){
array[i] = 48;
array[i-1]++;
}
}
std::cout << "Current Combination: ";
std::cout << array;
std::cout << "\n";
tComb++;
array[6]++;
}
}
It'll try and generate backward the latest combination of alphanumeric characters, but it's hardcoded and won't work well.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned powu(unsigned base, unsigned exp){
unsigned result = 1;
while(exp > 0){
if(exp & 1)
result *= base;
base = base * base;
exp >>=1;
}
return result;
}
int main(int argc, char *argv[]){
if(argc != 3){
fprintf(stderr, "Usage : RepeatedPermutation abcd 3\n");
return -1;
}
char *list = argv[1];
unsigned gp_len = atoi(argv[2]);
unsigned list_len = strlen(list);
char *gp = calloc(gp_len+1, sizeof(char));
int total_n = powu(list_len, gp_len);
int i, j;
for(i=0;i<total_n;++i){
int n = i;
for(j=0;j<gp_len;++j){
gp[gp_len -j -1] = list[n % list_len];
n /= list_len;
}
printf("[%s]\n", gp);
}
free(gp);
return 0;
}
Am not sure but i think this is the answer to your question. If you want three groups than you should have 3 different loops.Its pretty simple when you see the output of this program.
You just need to increment the value of what ever you want to generate there possible combination.
The below Code will generate all possible combination of "abcd" in groups of 3, from [aaa] to [ddd].
int main()
{
char ch1;
char ch2;
char ch3;
for(ch1='a';ch1<='d';ch1++)
{
for(ch2='a';ch2<='d';ch2++)
{
for(ch3='a';ch3<='d';ch3++)
{
printf("%c %c %c\n",ch1,ch2,ch3);
}
printf("\n"); //just to have clean and understandable output
}
printf("\n\n\n"); //just to have clean and understandable output
}
return 0;
}
One method to generate all the combinations is to treat this as a number counting program.
The Counting Algorithm
Let's take the case of "digits": a, b, c, and d.
The first number is: aaaa. Much like decimal: 0000.
The second number is: aaab. Decimal: 0001.
The third number is: aaac, decimal: 0002.
The fourth number is: aaad, decimal: 0003.
This process is known as incrementing, e.g. adding a constant value each time.
Now comes the tricky part, incrementing the last digit. According to number counting rules, when the last digit is reached, the last digit is replaced by the first and the digit in the next column is replaced. This is equivalent of a decimal number incrementing from 09 to 10.
So in the example above, the next number in the sequence is: aaba.
This is known as carry, as you are carrying the overflow to the next digit.
Converting Algorithm to Code
Looks like there is a loop to count from first digit to last digit:
#define MAXIMUM_DIGIT_POSITIONS 4
const char FIRST_CHAR = 'a';
const char LAST_CHAR = 'd';
std::vector<char> number(MAXIMUM_DIGIT_POSITIONS); // Reserve some slots.
void Print_Number(const std::vector<char>& number);
int main(void)
{
// Initialize the number
int position = 0;
for (position = 0; position < MAXIMUM_DIGIT_POSITIONS; ++position)
{
number.push_back(FIRST_CHAR);
}
Print_Number(number);
// Loop: incrementing
position = MAXIMUM_DIGIT_POSITIONS - 1; // Because arrays are zero based indexing
while (number[position] < LAST_CHAR)
{
number[position] = number[position] + 1; // Increment to next digit, same position.
Print_Number(number);
}
// Pause before closing
std::cout << "Paused. Press ENTER to close.\n";
std::cin.ignore(100000, '\n');
return EXIT_SUCCESS;
}
void Print_Number(const std::vector<char>& number)
{
for (std::vector<char>::const_iter iter = number.begin();
iter != number.end();
++iter)
{
std::cout << *iter;
}
cout << "\n";
}
Handling Carry
The above program demonstrates counting in a single column. But how to handle the incrementing of the last digit?
Looks like we need to increment the digit in the previous position.
Looking ahead, the value in the previous column will be incremented, until it too, needs to be increment. Thus the carry will be propagate to the previous column. Looks like another loop:
// Loop: number of positions
int propagation_position = position - 1;
while (propagation_position >= 0)
{
while (number[position] < LAST_CHAR)
{
number[position] = number[position] + 1; // Increment to next digit, same position.
Print_Number(number);
}
// Propagate the carry.
while (propagation_position >= 0)
{
if (number[propagation_position] != LAST_CHAR)
{
++number[propagation_position];
number[propagation_position + 1] = FIRST_CHAR;
break;
}
--propagation_position;
}
position = 0;
}
The above new fragment has an outer while loop and a second inner while loop. The outer while loop controls the digit position. The second inner while loop handles the carry.
The whole program is designed so that you can adjust the number of digit positions and the number of digits in the sequence.
Summary
The brute force method for printing all the combinations is like counting numbers. The same principles apply: when the last digit is incremented, it is replaced by the first digit and the digit of the next column is incremented. This is repeated until all positions have been counted.
Walk through the above code with debugger or pen and paper to find any defects and understand the algorithm.
After you understand the algorithm, search your favorite C++ reference for "c++ combination permutation algorithm".
I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<double> x(10);
for (unsigned int i = 9; i >= 0; i--)
{
cout << "i= " << i << endl;
x[i] = 1.0;
}
cout << "x0= " << x[0] << endl;
return 0;
}
I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
Thank you very much!
The problem here is that an unsigned integer is never negative.
Therefore, the loop-test:
i >= 0
will always be true. Thus you get an infinite loop.
When it drops below zero, it wraps around to the largest value unsigned value.
Thus, you will also be accessing x[i] out-of-bounds.
This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.
Thus, if you want to use unsigned integers, you can try one of the following possibilities:
for (unsigned int i = 9; i-- != 0; )
and
for (unsigned int i = 9; i != -1; i--)
These two were suggested by GManNickG and AndreyT from the comments.
And here's my original 3 versions:
for (unsigned int i = 9; i != (unsigned)0 - 1; i--)
or
for (unsigned int i = 9; i != ~(unsigned)0; i--)
or
for (unsigned int i = 9; i != UINT_MAX; i--)
The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.
Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.
In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).
The problem is here:
for (unsigned int i = 9; i >= 0; i--)
You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).
As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
My preferred method for a reverse loop with an index is this:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
and that is why because it maps most closely to the normal loop equivalent:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}
If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:
auto& my_element = my_vector[i - 1];
I'm working on Euler Problem 14:
http://projecteuler.net/index.php?section=problems&id=14
I figured the best way would be to create a vector of numbers that kept track of how big the series was for that number... for example from 5 there are 6 steps to 1, so if ever reach the number 5 in a series, I know I have 6 steps to go and I have no need to calculate those steps. With this idea I coded up the following:
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
int main()
{
vector<int> sizes(1);
sizes.push_back(1);
sizes.push_back(2);
int series, largest = 0, j;
for (int i = 3; i <= 1000000; i++)
{
series = 0;
j = i;
while (j > (sizes.size()-1))
{
if (j%2)
{
j=(3*j+1)/2;
series+=2;
}
else
{
j=j/2;
series++;
}
}
series+=sizes[j];
sizes.push_back(series);
if (series>largest)
largest=series;
cout << setw(7) << right << i << "::" << setw(5) << right << series << endl;
}
cout << largest << endl;
return 0;
}
It seems to work relatively well for smaller numbers but this specific program stalls at the number 113382. Can anyone explain to me how I would go about figuring out why it freezes at this number?
Is there some way I could modify my algorithim to be better? I realize that I am creating duplicates with the current way I'm doing it:
for example, the series of 3 is 3,10,5,16,8,4,2,1. So I already figured out the sizes for 10,5,16,8,4,2,1 but I will duplicate those solutions later.
Thanks for your help!
Have you ruled out integer overflow? Can you guarantee that the result of (3*j+1)/2 will always fit into an int?
Does the result change if you switch to a larger data type?
EDIT: The last forum post at http://forums.sun.com/thread.jspa?threadID=5427293 seems to confirm this. I found this by googling for 113382 3n+1.
I think you are severely overcomplicating things. Why are you even using vectors for this?
Your problem, I think, is overflow. Use unsigned ints everywhere.
Here's a working code that's much simpler and that works (it doesn't work with signed ints however).
int main()
{
unsigned int maxTerms = 0;
unsigned int longest = 0;
for (unsigned int i = 3; i <= 1000000; ++i)
{
unsigned int tempTerms = 1;
unsigned int j = i;
while (j != 1)
{
++tempTerms;
if (tempTerms > maxTerms)
{
maxTerms = tempTerms;
longest = i;
}
if (j % 2 == 0)
{
j /= 2;
}
else
{
j = 3*j + 1;
}
}
}
printf("%d %d\n", maxTerms, longest);
return 0;
}
Optimize from there if you really want to.
When i = 113383, your j overflows and becomes negative (thus never exiting the "while" loop).
I had to use "unsigned long int" for this problem.
The problem is overflow. Just because the sequence starts below 1 million does not mean that it cannot go above 1 million later. In this particular case, it overflows and goes negative resulting in your code going into an infinite loop. I changed your code to use "long long" and this makes it work.
But how did I find this out? I compiled your code and then ran it in a debugger. I paused the program execution while it was in the loop and inspected the variables. There I found that j was negative. That pretty much told me all I needed to know. To be sure, I added a cout << j; as well as an assert(j > 0) and confirmed that j was overflowing.
I would try using a large array rather than a vector, then you will be able to avoid those duplicates you mention as for every number you calculate you can check if it's in the array, and if not, add it. It's probably actually more memory efficient that way too. Also, you might want to try using unsigned long as it's not clear at first glance how large these numbers will get.
i stored the length of the chain for every number in an array.. and during brute force whenever i got a number less than that being evaluated for, i just added the chain length for that lower number and broke out of the loop.
For example, i already know the Collatz sequence for 10 is 7 lengths long.
now when i'm evaluating for 13, i get 40, then 20, then 10.. which i have already evaluated. so the total count is 3 + 7.
the result on my machine (for upto 1 million) was 0.2 secs. with pure brute force that was 5 seconds.