Roman numbers to decimal numbers, getting garbage value - c++

I have to create a program for converting Roman numerals to decimal numbers for which I'm getting garbage value as an output.
The fact is I have double checked my logic and it seems to be correct.
How can I correct it?
Here's my code:
#include<iostream>
#include<cstring>
using namespace std;
class RomanType
{
char str[10];
int d;
public:
void accept()
{
cout<<"Enter Roman No. in capitals:"<<endl;
cin>>str;
convert(str);
}
void convert(char str1[10])
{
int j=0;
for(j=0;j<strlen(str1);j++)
{
if( str1[j]=='I')
{
if(str1[j+1]=='V' || str1[j+1]=='X')
{
d=d-1;
cout<<j<<endl;
}
else
{
d=d+1;
cout<<d<<endl;
}
}
if ( str1[j]=='V')
d=d+5;
if(str1[j]=='X')
{
if(str1[j+1]=='L' || str1[j+1]=='C')
d=d-10;
else
d=d+10;
}
if(str1[j]=='L')
d=d+50;
if( str1[j]=='C')
{
if(str1[j+1]=='D' || str1[j+1]=='M')
d=d-100;
else
d=d+100;
}
if(str1[j]=='D')
d=d+500;
if(str1[j]=='M')
d=d+1000;
}
}
void display()
{
cout<<"It's decimal equivalent is="<<d<<endl;
}
};
main()
{
RomanType obj;
obj.accept();
obj.display();
}

Few points:
Don't directly jump to parsing high value romans. Start with I, V, and X only (i.e. target 1 to 10 first, then 11 to 20, then 21 to 39, 40 to 99, 100 to 499 etc.)
Don't assume that if I is given, it is given before or after V or X. It may be given for itself (eg. II - you else part assumes something).
Assign value of d with zero
Do step debugging, watch value of d and other variables. If debugger isn't good or available, do output the values on each step/iteration.
[Add] You need not to pass str to function convert, since they belong to same class, and convert can/would read the same content.

You didn't initialize d to 0
in convert put d=0 at the start

You didn't initialize d to 0. Please add this at the top of your convert function:
void convert(char str1[10])
{
int j=0;
d = 0;
. . .

OK guys thanks for the help. It's solved now. I had done a blunder and that was initialised d again in convert(), so that had made it as a local variable. See the comments:
#include<iostream>
#include<cstring>
using namespace std;
class RomanType
{
char str[10];
int d;
public:
void accept() // UNNECESSARILY NOT PASSING ANY STRING
{
cout<<"Enter Roman No. in capitals:"<<endl;
cin>>str;
convert();
}
void convert()
{
d=0;// PREVIOUSLY WRIITEN int d=0; so that was the mistake. Yay! it's solved :D
for(int j=0;j<10;j++)
{
if( str[j]=='I')
{
if(str[j+1]=='V' || str[j+1]=='X')
{
d=d-1;
// cout<<d<<endl;
}
else
{
d=d+1;
//cout<<d<<endl;
}
}
else if ( str[j]=='V')
d=d+5;
else if(str[j]=='X')
{
if(str[j+1]=='L' || str[j+1]=='C')
d=d-10;
else
d=d+10;
}
else if(str[j]=='L')
d=d+50;
else if( str[j]=='C')
{
if(str[j+1]=='D' || str[j+1]=='M')
d=d-100;
else
d=d+100;
}
else if(str[j]=='D')
d=d+500;
else if(str[j]=='M')
d=d+1000;
}
}
void display()
{
cout<<"It's decimal equivalent is="<<d<<endl;
}
};
main()
{
RomanType obj;
obj.accept();
obj.display();
}

Related

Similar solutions but different answers

I am facing difficulty while solving a problem where we have to check whether a string is a subsequence of another string or not.
A man with name M is allowed to marry a woman with name W, only if M is a subsequence of W or W is a subsequence of M.
A is said to be a subsequence of B if A can be obtained by deleting some elements of B without changing the order of the remaining elements.
Example -
john and johanna will give "YES" as output
kayla and jayla will give "NO" as output
johanna and john will give "YES" as output
My code is :
#include <iostream>
#include<string>
using namespace std;
bool checksub(string a, string b)
{
int pos=0;
for(int i=0; i<a.size(); i++)
{
int flag=0;
for(int j=pos; j<b.size(); j++)
{
if(b[j]==a[i])
{
flag=1;
pos=j;
break;
}
}
if(flag==0)
{
return false;
}
}
return true;
}
int main() {
// your code goes here
int t;
cin>>t;
while(t--)
{
string a,b;
cin>>a>>b;
if(a.size()==b.size())
{
if(a==b)
{
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;}
}
else if(a.size()>b.size()){
if(checksub(b,a))
{
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}else{
if(checksub(a,b))
{
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
}
return 0;
}
The editorial of the question uses a similar approach. Can anybody tell me what's wrong with my code?
The editorial solution is given below :
#include <cstdio>
char M[25005], W[25005];
bool contains(const char *A, const char *B){
while(*A){
if(*B==*A)
B++;
A++;
}
return !*B;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%s %s", M, W);
puts(contains(M, W) || contains(W, M) ? "YES" : "NO");
}
return 0;
}
Link to the problem: https://www.codechef.com/problems/NAME2
Your code produces the wrong result with input AA BAB because it fails to account for the fact that you need to have two A in the second string.
You might be able to fix it by changing pos=j; to pos=j+1; but I'm not certain.
There really is no similarity between your code and the editoral code however. Even with my suggested fix (if it does work) your code is clearly less efficient than the editorial code because it scans the input strings repeatedly.
Got the correct answer just by changing pos=j+1 instead of pos=j. Then code will become similar to the pseudocode in the editorial. Thanks, everybody for answering.

Getting wrong answer in a DP problem although implementation looks correct

I was trying to solve Reduce String on codechef which says
Give a string s of length l, and a set S of n sample string(s). We do reduce the string s using the set S by this way:
Wherever Si appears as a consecutive substring of the string s, you can delete (or not) it.
After each deletion, you will get a new string s by joining the part to the left and to the right of the deleted substring.
I wrote a recursive function as follows:-
Basically what i am doing in my code is either don't delete the character or delete it if it is part of any substring but it is giving wrong answer.
#include <bits/stdc++.h>
using namespace std;
#define mx 255
int dp[mx];
unordered_map<string,int> sol;
void init(int n)
{
for(int i=0;i<n;i++)
{
dp[i]=-1;
}
}
int solve(string str,int low,int high,vector<string> smp)
{
if(low>high)
{
return 0;
}
if(dp[low]!=-1)
{
return dp[low];
}
int ans=1+solve(str,low+1,high,smp);
for(int i=low;i<high;i++)
{
string tem=str.substr(low,i-low+1);
for(int j=0;j<smp.size();j++)
{
cout<<"low i high str"<<low<<" "<<i<<" "<<high<<" "<<smp[j]<<" "<<tem<<endl;
if(tem.compare(smp[j])==0)
{
ans=min(ans,solve(str,i+1,high,smp));
}
}
}
return dp[low]=ans;
}
signed main()
{
sol.clear();
string str;
vector<string> smp;
int n;
cin>>str;
cin>>n;
for(int i=0;i<n;i++)
{
string tem;
cin>>tem;
smp.push_back(tem);
}
int len=str.length();
init(len+1);
cout<<solve(str,0,len-1,smp)<<endl;
return 0;
}
PS:
link to the question
This question is toughest(seen so far) and most beautiful(again seen so far) question based on DP ON INTERVALS.
The initial code would definitely not work since it only considers single pass on the string and would not consider remaining string after deleting the patterns again and again.
There are 3 cases:-
Case 1 Either character is not deleted.
Case 2It is deleted as a part of contiguous substring.
Case 3It is deleted as a part of subsequence that matches any word given in the set of patterns and everything that is not part of that subsequence is deleted first as a substring(which again belongs to set of words).
The third part is the most tricky and requires enough thinking and is even tougher to implement too.
So for every substring we need to check whether this substring can be completely destroyed or not.
The function compute_full_recur() is the function that ensures that whether substring can be deleted either in Case 2 or Case 3.
The function compute_full takes care of Case 1.And finally this code will not run on codechef link since all the function are recursive with memoization but to verify the code is working i Have run it on Problem Reducto of Hackerrank which is exact similar with lower constraints.Download test cases and then run on test cases on your PC for verifying.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
#define mx 252
#define nx 40
bool full[mx][mx],vis[mx][mx],full_recur[mx][mx][nx][nx];
int ans[mx];
void init()
{
for(int i=0;i<mx;i++)
{
for(int j=0;j<mx;j++)
{
full[i][j]=false,vis[i][j]=false;
}
}
for(int i=0;i<mx;i++)
{
ans[i]=-1;
}
for(int i=0;i<mx;i++)
{
for(int j=0;j<mx;j++)
{
for(int k=0;k<nx;k++)
{
for(int l=0;l<nx;l++)
{
full_recur[i][j][k][l]=false;
}
}
}
}
}
bool compute_full_recur(string str,int low,int high,vector<string> pat,int idx,int len)
{
if(low>high&&len==pat[idx].length())
{
return true;
}
if(low>high&&len<pat[idx].length())
{
full_recur[low][high][idx][len]=false;
return false;
}
if(str[low]==pat[idx][len]&&compute_full_recur(str,low+1,high,pat,idx,len+1))
{
return full_recur[low][high][idx][len]=true;
}
for(int i=low+1;i<=high;i++)
{
if(str[low]==pat[idx][len]&&full[low+1][i]&&compute_full_recur(str,i+1,high,pat,idx,len+1))
{
return full_recur[low][high][idx][len]=true;
}
}
full_recur[low][high][idx][len]=false;
return false;
}
void compute_full(string str,int low,int high,vector<string> pats)
{
if(low>high)
{
return;
}
if(vis[low][high])
{
return;
}
vis[low][high]=true;
compute_full(str,low+1,high,pats);
compute_full(str,low,high-1,pats);
for(int i=0;i<pats.size();i++)
{
if(!full[low][high])
full[low][high]=compute_full_recur(str,low,high,pats,i,0);
}
}
int compute_ans(string str,int low,int high)
{
if(low>high)
{
return 0;
}
if(ans[low]!=-1)
{
return ans[low];
}
int sol=1+compute_ans(str,low+1,high);
for(int i=low+1;i<=high;i++)
{
if(full[low][i]==true)
{
sol=min(sol,compute_ans(str,i+1,high));
}
}
return ans[low]=sol;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
string str;
int n;
vector<string> pats;
cin>>n>>str;
for(int i=0;i<n;i++)
{
string tem;
cin>>tem;
pats.push_back(tem);
}
init();
compute_full(str,0,str.length()-1,pats);
cout<<compute_ans(str,0,str.length()-1)<<endl;
}
return 0;
}

My operator overload isn't returning in my int main?

I'm trying to make a code that adds 2 octal numbers and then converts the sum to decimal using operator overloading. However, whenever I try and use my convert operator($), I get "$num1 was not declared in this scope". can anyone help me?
Note: I know some of the things can be changed for simplicity but it has to be this way because that's the way my teacher wants it. My main problem is calling the operator in the main. Thanks!
#include <iostream>
#include <math.h>
#include <algorithm>//reverse
#include <vector>
using namespace std;
int gnum=0;
class Oct{
private:
int number;//Base 10
vector <int> octnum;//separated out number
public:
Oct();
void input();//input 457
void setNum(int);//sending setNum a base 10 number(457)
void operator+ (Oct);//if(sum>7)sum-8
int operator$ ();//converts sum to base 10
void display();
vector <int> octSum;//vector of added numbers
};
Oct::Oct()
{
number = 0;
octnum.push_back(0);
}
void Oct::input()
{
cout<<"Enter your number: ";
cin>>number;
gnum = number;
}
void Oct::setNum(int num)
{
while(num!=0)
{
octnum.push_back(num%10);
num=num/10;
}
octnum.push_back(0);
if(octnum[0]==0)
{
octnum.erase(octnum.begin());
}
}
void Oct::display()
{
for(int i = 0;i<octSum.size();i++)
{
cout<<octSum[i];
}
cout<<endl;
}
void Oct::operator+ (Oct num2)
{
int carry = 0;
int add = 0;
for(int i = 0;i<octnum.size();i++)
{
add = octnum[i]+num2.octnum[i]+carry;
if(add>7)
{
add=add-8;
carry = 1;
}
else
{
carry = 0;
}
octSum.push_back(add);
}
}
int Oct::operator$ ()
{
for(int i = 0;i<octSum.size();i++)
{
octSum[i]=octSum[i]*int(pow(8,i)+0.5);
}
reverse(octSum.begin(),octSum.end());
int sum = 0;
for(int i = 0;i<octSum.size();i++)
{
sum = sum + octSum[i]*int(pow(10,octSum.size()-1-i)+0.5);
}
return sum;
}
int main()
{
Oct num1,num2;
num1.input();
num1.setNum(gnum);
num2.input();
num2.setNum(gnum);
num1+num2;
int j = $num1;
num1.display();
return(0);
}
$ is not an operator in C++. It is just a character without any specific meaning. Whether it is supported as physical character in the source code is implementation-defined and it is also implementation-defined whether it will be parsed as part of an identifier. If it is parsed as part of an identifier, it will become part of the token, the same way as characters a to z do.
Apparently your compiler is supporting $ as source file character and as character in identifiers and therefore you are not overloading an operator, you are defining a normal member function with the name operator$ and you are referencing an identifier $num1 in main that has not been declared beforehand.
You cannot invent new operators.

How to not show the null character while inserting a character into a 2d string?

I was making a pretty simple Battleship game for my school project (I HAVE to use Turbo C++) and i ran into a problem. I'm basically using a 5x5 2D string as my board and hiding a "ship" in it. What I'm trying to do is that whenever the user makes a wrong guess, I want to replace the "O" in the board with an "X", but when i do that, the "O" in the next block gets replaced by a "/0" and shows as a blank space in the output. How do I fix that?
Here's the code:
#include<conio.h>
#include<iostream.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<stdio.h>
//A function to initialize the board
void start_board(char a[5][5])
{
for(int i=0;i<5;i++)
{ for(int j=0;j<5;j++)
{ strcpy(&a[i][j],"O");
}
}
}
//A function to display the board
void display_board(char a[5][5])
{ for(int i=0;i<5;i++)
{ for(int j=0;j<5;j++)
{ cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
class board
{ public:
char board[5][5];
void start()
{ start_board(board);
}
void display()
{ display_board(board);
}
};
class ship
{ public:
int ship_row, ship_col;
ship()//CONSTRUCTOR FOR PUTTING COORDINATES OF SHIP
{ randomize();
ship_row= random(5);
ship_col=random(5);
cout<<ship_row<<endl<<ship_col;
}
};
class guess: public board, public ship
{ public:
int guess_row,guess_col;
char vboard[5][5];
guess()
{ start_board(vboard);
}
void takeguess();
};
void guess:: takeguess()
{ int count=0;
while(count<3)
{
cout<<endl;
cout<<"Guess a row ";
cin>>guess_row;
cout<<"Guess a column ";
cin>>guess_col;
if(guess_row==ship_row && guess_col==ship_col)
{ cout<<"Congratulations! You sank the battleship!";
break;
}
else if(guess_row>4 || guess_col>4)
{ cout<<"invalid guess";
}
else
{ clrscr();
cout<<"Incorrect Guess!"<<endl;
strcpy(&vboard[guess_row][guess_col],"X");
display_board(vboard);
count+=1;
}
if(count==3)
{ cout<<"GAME OVER!";
}
}
}
void main()
{ clrscr();
board b;
b.start();
b.display();
guess g;
g.takeguess();
getch();
}
For example, If the user guesses 0,2, and that isn't the ship's location the output will show:
OOX O
OOOOO
OOOOO
OOOOO
OOOOO
Sorry for the messy code(it isn't complete) and any mistakes i made while writing this post, it's my first time using stackoverflow. Thank You for your help!
Don't use strcpy!! You're not copying a string, you're setting the value of a single character in the string, so use the right tool for the job.
vboard[guess_row][guess_col] = 'X';
This is because "X" is actual 2 characters 'X' and '\0' so your strcpy hits 2 cells in your array

Peculiar behavior while recursively calling function in C++ and getting two different outputs for the same code with only an extra line with "cout"

#include <iostream>
#include <vector>
#define MAXX 1000
using namespace std;
int number[MAXX], digits=0;
int adjust(int i)
{
if(number[i]<9)
{
cout<<"i = "<<i<<" "; //PROBLEM
(number[i])++;
return i;
}
number[i]=0;
adjust(i-1);
}
void makePalindrome(int head,int tail)
{
int revert;
if(head>tail)
return;
if(number[head]==number[tail])
{
makePalindrome(head+1,tail-1);
}
if(number[tail]<number[head])
{
number[tail]=number[head];
makePalindrome(head+1,tail-1);
}
if (number[tail]>number[head])
{
number[tail]=number[head];
revert=adjust(tail-1);
if(revert<=head)
{
makePalindrome(revert,digits-revert-1);
}
else
{
makePalindrome(head+1,tail-1);
}
}
}
int main(int argc, char const *argv[])
{
long long int num,num_copy;
int head,tail;
int number_reverse[MAXX];
cout<<"Enter the number whose next greater palindrome you want to find" <<endl;
cin>>num;
num_copy=num;
while(num_copy>0)
{
number_reverse[digits]=num_copy%10;
digits++;
num_copy=num_copy/10;
}
//cout<<"Digits = "<<digits<<"\n";
for (int i = digits-1; i >=0; --i)
{
number[digits-i-1]=number_reverse[i];
//cout<<number[digits-i-1]<<" ";
}
head=0; tail=digits-1;
makePalindrome(head,tail);
cout<<"Answer : ";
for (int i = 0; i < digits; ++i)
{
cout<<number[i];
}
cout<<"\n";
return 0;
}
When I am running with an input : 94187978322, it is giving two different answers with and without a "cout" line (line with comment "PROBLEM").
Here's the output:
ishivendra:code shivendraagrawal$ g++ next_palindrome.cpp
ishivendra:code shivendraagrawal$ ./a.out
Enter the number whose next greater palindrome you want to find
94187978322
Answer : 94188078149
ishivendra:code shivendraagrawal$ g++ next_palindrome.cpp
ishivendra:code shivendraagrawal$ ./a.out
Enter the number whose next greater palindrome you want to find
94187978322
i = 7 i = 6 i = 4 Answer : 94188088149
The second output is the desired output. Can you point out the cause of this difference and incorrectness for the first one ?
I figured half of it out, it was a logical error.
I should have written return adjust(i-1).
I still don't know the cause for the peculiarity (There was no compilation or runtime error) but at least my code is running as desired now.