This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 11 years ago.
I am getting a wrong answer when I wrote a code to solve Prob 17 in Project Euler.
I am outputting every string to make the count more clear.
The link is posted here: http://codepad.org/wE54t7Qi
Can someone help me to determine where the problem is?
map<long int, string> CharNumberValue;
int main()
{
CharNumberValue[0] ="zero";
CharNumberValue[1] ="one";
CharNumberValue[2] ="two";
CharNumberValue[3] ="three";
CharNumberValue[4] ="four";
CharNumberValue[5] ="five";
CharNumberValue[6] ="six";
CharNumberValue[7] ="seven";
CharNumberValue[8] ="eight";
CharNumberValue[9] ="nine";
CharNumberValue[10] ="ten";
CharNumberValue[11] ="eleven";
CharNumberValue[12] ="twelve";
CharNumberValue[13] ="thirteen";
CharNumberValue[14] ="fourteen";
CharNumberValue[15] ="fifteen";
CharNumberValue[16] ="sixteen";
CharNumberValue[17] ="seventeen";
CharNumberValue[18] ="eighteen";
CharNumberValue[19] ="nineteen";
CharNumberValue[20] ="twenty";
CharNumberValue[30] ="thirty";
CharNumberValue[40] ="forty";
CharNumberValue[50] ="fifty";
CharNumberValue[60] ="sixty";
CharNumberValue[70] ="seventy";
CharNumberValue[80] ="eighty";
CharNumberValue[90] ="ninety";
CharNumberValue[100] ="hundred";//Sameer,remember 100 is one hundred
CharNumberValue[1000] ="thousand";//Sameer,remember 1000 is one thousand
long int count = 0;
string printword ="";
for(int i=1; i< 1000; i++)
{
if(i<=100)
{
int ten = (i/10)*10;
int unit = i%10;
map<long int, string>:: iterator it = CharNumberValue.find(i);
map<long int, string>:: iterator it1 = CharNumberValue.find(unit);
map<long int, string>:: iterator it2 = CharNumberValue.find(ten);
if(i<10)
{
count += it1->second.length();
printword = it1->second;
cout<<printword<<endl;
}
if(i>=10 && i<=20)
{
count += it->second.length();//These are unique
printword = it->second;
cout<<printword<<endl;
}
if(i>20 && i<=100)
{
count += it2->second.length();
printword = it2->second ;
if ((i != 30)&&(i != 40)&&(i != 50)&&(i != 60)&&(i != 70)&&(i != 80)&&(i!= 90)&&(i!= 100))
{
count += it1->second.length();
printword = it2->second + " " + it1->second ;
}
cout<<printword<<endl;
}
}
if(i>100 && i<1000)
{
int hun = i/100;
int ten=i%100;
int mten = (ten/10)*10;//modified ten
int unit = ten%10;
map<long int, string>:: iterator it = CharNumberValue.find(unit);
map<long int, string>:: iterator it1 = CharNumberValue.find(mten);
map<long int, string>:: iterator it2 = CharNumberValue.find(ten);
map<long int, string>:: iterator it3 = CharNumberValue.find(hun);
int counttemp = CharNumberValue[100].length();
count += it3->second.length() + CharNumberValue[100].length();
printword = it3->second + " " + CharNumberValue[100];
if((i != 200)&&(i != 300)&&(i != 400)&&(i != 500)&&(i != 600)&&(i != 700)&&(i != 800)&&(i != 900))
{
if( ten<=20)
{
count += 3/*for and */+ it2->second.length() ;//These are unique
printword = it3->second + " " + CharNumberValue[100] + " and " + it2->second ;
cout<<printword<<endl;
}
if(ten>20 && ten<=99)
{
count += 3/*for and */+ it1->second.length();
printword = it3->second + " " + CharNumberValue[100] + " and " + it1->second;
if ((ten != 30)&&(ten != 40)&&(ten != 50)&&(ten != 60)&&(ten != 70)&&(ten != 80)&&(ten!= 90)&&(ten!= 100))
{
count += it->second.length();
printword = it3->second + " " + CharNumberValue[100] + " and " + it1->second +" "+ it->second ;
}
cout<<printword<<endl;
}
}
else
{
cout<<printword<<endl;
}
}
}
count += 11;//for one thousand
cout<< count;
return 0;
}
You're outputting "hundred" instead of "one hundred".
You can simplify most of the tests containing enumeration of cases :
if ((i != 30)&&(i != 40)&&(i != 50)&&(i != 60)&&(i != 70)&&(i != 80)&&(i!= 90)&&(i!= 100))
As (i>20 && i<=100), you can just check if i is a multiple of 10 (using variable unit for instance)
if((i != 200)&&(i != 300)&&(i != 400)&&(i != 500)&&(i != 600)&&(i != 700)&&(i != 800)&&(i != 900))
As (i>100 && i<1000), you can just check if i is a multiple of 100
if ((ten != 30)&&(ten != 40)&&(ten != 50)&&(ten != 60)&&(ten != 70)&&(ten != 80)&&(ten!= 90)&&(ten!= 100))
As (ten>20 && ten<=99), you can just check if ten is a multiple of 10.
More generally, the shorter your code is, the easier it will be to find a mistake. This includes removing useless tests (a few of the conditions above were useless because of the bounds of the variables), removing duplicate code, etc.
Related
I am working on vector of strings and map of strings and int to print a histogram.
What I need to do now is to return a count of strings, from the most frequent to the less frequent elements. This is the part of my code where I am having issues so far:
string histogram( const vector<string> &v) {
string st = "";
map<vector<string>, int> h;
for(auto ite = v.begin(); ite!= v.end(); ite++ ) {
if(h.find(v) == h.end()) {
h[v] = 1;
} else {
h[v]++;
}
}
for (auto it: h) {
st += "[" + it.first + ":" + it.second + "]";
}
return st;
}
The error I keep getting is related to this line:
st += "[" + it.first + ":" + it.second + "]";
I have been checking online how to fix this error or what I am missing for I still can't see exactly how to work with the operator for the strings.
I am trying to create a program that will take in an expression (example: "10*2+1") and solve it. My code is:
#include <iostream>
#include <string>
#include <vector>
void calculateString(std::string str);
int main() {
calculateString("10*2+2");
system("pause");
}
void calculateString(std::string str) {
int total = 0;
std::string temp1 = "";
std::string temp2 = "";
std::string add = "";
std::string *ray = new std::string[str.length()];
std::vector<int> newRay;
for (int i = 0; i < str.length(); i++) {
if (str.at(i) != '*' && str.at(i) != '/' && str.at(i) != '+' && str.at(i) != '-') {
add += str.at(i);
}
else {
ray[i] = add;
std::cout << ray[i] << "\n";
add = "";
}
}
for (int i = 0; i < str.length(); i++) {
if (ray[i].compare("*")) {
total = atoi(ray[i - 1].c_str()) * atoi(ray[i + 1].c_str());
newRay.push_back(total);
}
}
for (int i = 0; i < str.length(); i++) {
if (ray[i] == "+") {
newRay.push_back(atoi(ray[i - 1].c_str()) + atoi(ray[i + 1].c_str()));
}
}
for (int i = 0; i < newRay.size(); i++) {
std::cout << newRay[i] << "\n";
total += newRay[i];
}
std::cout << str << "=" << total << "\n";
}
However, whenever I run this I keep running into an access violation error that reads:
Exception thrown at 0x0F1CD4A0 (ucrtbased.dll) in CalcString.exe:
0xC0000005: Access violation reading location 0x01BE0FEE.
And it points to line 34 which is this:
total = atoi(ray[i - 1].c_str()) * atoi(ray[i + 1].c_str());
which is basically calculating the multiplication part of the expression then storing the asnwer in one variable. I have tried everything from changing my array to a vector to trying to rewrite all the methods and nothing seems to work. Please help
In
if (ray[i].compare("*"))
compare is misused. According to cppreference compare returns < 0 for smaller than, 0 for equal or > 0 for larger. As an if condition, 0 is false and everything else is true, so this resolves to
if (ray[i] != "*")
Probably the opposite of what is desired.
This allows entry into the if's body when ray[0] is "10" and i is 0, resulting in
total = atoi(ray[0 - 1].c_str()) * atoi(ray[0 + 1].c_str());
or
total = atoi(ray[-1].c_str()) * atoi(ray[1].c_str());
and accessing negative array indexes is undefined behaviour. Looks like it manifested as a crash in this case.
Solution:
All we care about is equality in this case so we can get away with
if (ray[i] == "*")
just as was done for
if (ray[i] == "+")
I also recommend a check to ensure an operator is never the first element of ray.
I am trying to go through my map of patient IDs, find the sequential ones that match, and find the difference squared for each pair of results (for the same patient). However I am having some trouble with the "itid" iterator in the line, "for (itid = nx; itid != mymap.end(); itid++) {" and I'm not sure why. When I take out the code with "itid" it works just fine. I am a programming beginner, so any advice would be greatly appreciated!
map <int,struct testInfo> mymap;
map <int,struct testInfo>:: iterator it;
pair<map<int,struct testInfo>::iterator,bool> ret;
map <int,struct testInfo>:: iterator itid;
int arraySize = 10000;
double diffsq[arraySize];
int count = 1;
for ( it=mymap.begin() ; it != mymap.end(); it++ ) {
auto nx = next(it);
//comparing each patientID to the next patientID
if ((it->second.patientID == nx->second.patientID) && it->second.patientID != 0) {
for (itid = nx; itid != mymap.end(); itid++) {
if ((it->second.patientID == itid->second.patientID) && it->second.patientID != 0) {
diffsq[count] = pow((it->second.result - itid->second.result), 2);
count++;
} else
itid = mymap.end();
}
}
}
I think it is because the next give a constant iterator and itid is not constant... try it in same way as you have done auto nx try same for itid.
auto itid = nx inside the for loop.
I want to identify which ones and how many values are duplicate in a linked list that was user's input. And this is the code I wrote for it:
int count;
int compare, compare2;
for (p = first; p != NULL; p = p->next){
compare = p->num;
for (j = first; j != NULL; j = j->next){
if (compare == j->num){
compare2 = j->num;
count++;
}
}
if (count > 1){
cout << "There are at least 2 identical values of: " << compare2 << " that repeat for: " << count << "times" << endl;
}
}
Basically the idea of it was that I take the first element in the first loop and compare it to all the elements in the second loop and count if there are cases of them being similar, and print the result after - then I take next element and so on.
However the output is all the elements and it doesn't count correctly either. I'm just lost at how to adjust it.
I tried using the same p variable in both loops as it is the same list I want to loop, but then the .exe failed as soon as I'd finished input.
I saw a few examples around where there was function for deleting duplicate values, but the comparison part run through with while loop, and I'm just wondering - what am I doing wrong on this one?!
Your O(N*N) approach :
// Pick an element
for (p = first; p != NULL && p->next !=NULL ; p = p->next)
{ // Compare it with remaining elements
for (j = p->next ; j != NULL; j = j->next)
{
if ( p->num == j->num)
{
count++;
}
if( cout > 1 )
{
std::cout << p->num << " occurs "<< count << times << '\n' ;
}
}
Its better to use a HashMap to solve this is O(N) time with N extra space
std::unordered_map<int, int> m ;
for( p = first; p != NULL ; p = p->next )
{
m[ p->num ]++;
}
for (const auto &pair : m )
{
if( pair.second > 1 )
std::cout << pair.first << ": " << pair.second << '\n';
}
Your logic is flawed since both p and j iterate over the entire list. When p == j, the values are bound to match.
Change the block
if (compare == j->num){
compare2 = j->num;
count++;
}
to
if (p != j && compare == j->num){
compare2 = j->num;
count++;
}
Also, you don't need the line
compare2 = j->num;
since compare2 will be equal to compare.
You can reduce the number of tests by changing the inner for loop a bit. Then, you won't need the p != j bit either.
for (j = p->next; j != NULL; j = j->next){
if (compare == j->num){
count++;
}
}
The problem is that you don't exclude element you compare to (compare). So for every element it found at least one duplicate - itself!
Try to compare element in inner loop only followed by current (p).
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
So, there are ways to do this, and/or optimize this. Stupid that I am, I immediately wants to implement a recursive function, which later caused a segmentation fault, and then I tried to adopt dynamic programming, and it seemed to work, but somehow I got Wrong answer.
Problem Here
So here's my code, and I think it's pretty self-explanatory.
#include <iostream>
using namespace std;
int cycleLength(long long int);
int cycleLengthResult[1000000];
int main(int argc, char *argv[])
{
int i = 0, j = 0, cur = 0, max = 0;
while ( cin >> i >> j )
{
if ( i > j ) //swap to ensure i <= j
{
int s = i;
i = j;
j = s;
}
for ( int k = i ; k <= j ; ++ k )
{
cur = cycleLength(k);
if (cur > max) max = cur;
}
cout << i << " " << j << " " << max << endl;
max = 0;
}
}
int cycleLength(long long int arg)
{
if ( arg > 1000000 ) //if out of array bound, then don't memorize, just calculate
{
if (arg % 2 == 0)
{
return 1 + cycleLength(arg/2);
}
else
{
return 1 + cycleLength(arg*3+1);
}
}
if (!cycleLengthResult[arg-1]) //if result for arg doesn't exist then....
{
int valueForArg = 0;
if (arg == 1)
{
valueForArg = 1;
}
else if (arg % 2 == 0)
{
valueForArg = 1 + cycleLength(arg/2);
}
else
{
valueForArg = 1 + cycleLength(arg*3+1);
}
cycleLengthResult[arg-1] = valueForArg;
}
return cycleLengthResult[arg-1];
}
I passed all the sample inputs, and also (1, 1000000) for speed test. But it seemed that it's not the problem.
I want to fix my code, and not change the methodology used, of course, I can just not use recursive, and use a loop instead in main, which wouldn't overflow. But it's fun.
Read the statement carefully:
The integers i and j must appear in the output in the same order in which they appeared in the input
So save them after reading and print the saved values.