Converting int to roman numerals, only end if zero entered [duplicate] - c++

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 6 years ago.
I need to convert int to Roman numerals, my code is failing to compile with mingw using
C:\code>g++ -Wall -o rome_to_int rome_to_int.cpp
C:\Users\vm1\AppData\Local\Temp\ccSvDFll.o:task2.cpp:(.text+0x1278): undefined r
eference to `get_int_ref_checked()'
collect2.exe: error: ld returned 1 exit status
Now as part of the code, it must keep asking for input, converting that input untill zero is entered. Once Zero has been entered then it can exit.
I must use code from a privius question which covers the continuing untill which is found in the get_int_ref_checked, I can assume ONLY integers will be entered and nothing else, no doubles nor string of words.
I'm not sure what else to check.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int get_int_ref_checked();
string int_to_ROMAN();
/**
Turns the number from 1 to 9
*/
string digit_name(int digit)
{
if (digit == 1) return "I";
if (digit == 2) return "II";
if (digit == 3) return "III";
if (digit == 4) return "IV";
if (digit == 5) return "V";
if (digit == 6) return "VI";
if (digit == 7) return "VII";
if (digit == 8) return "VIII";
if (digit == 9) return "IX";
return "";
}
/**
Turns the number 10, 20, 30, 40, 50, 60, 70, 80, 90
*/
string ten_name(int n)
{
if (n == 1) return "X";
if (n == 2) return "XX";
if (n == 3) return "XXX";
if (n == 4) return "XL";
if (n == 5) return "L";
if (n == 6) return "LX";
if (n == 7) return "LXX";
if (n == 8) return "LXXX";
if (n == 9) return "XC";
return "";
}
/**
Turns the number 100, 200, 300, 400, 500, 600, 700, 800, 900
*/
string hun_name(int n)
{
if (n == 1) return "C";
if (n == 2) return "CC";
if (n == 3) return "CCC";
if (n == 4) return "CD";
if (n == 5) return "D";
if (n == 6) return "DC";
if (n == 7) return "DCC";
if (n == 8) return "DCCC";
if (n == 9) return "CM";
return "";
}
/**
Turns the number 1000, 2000, 3000
*/
string thou_name(int n)
{
if (n == 1) return "M";
if (n == 2) return "MM";
if (n == 3) return "MMM";
return "";
}
string int_to_ROMAN(int n)
{
int part = n; // The part that still needs to be converted
string roman; // The return value
if (part >= 1000)
{
roman = thou_name(part / 1000);
part = part % 1000;
}
if (part >= 100)
{
roman = roman + hun_name(part/100);
part = part % 100;
}
if (part >= 10)
{
roman = roman + ten_name(part/10);
part = part % 10;
}
if (part > 0)
{
roman = roman + digit_name(part);
}
return roman;
}
int main()
{
int n;
string r;
n = get_int_ref_checked();
if (n == 0)
{
cout<< "The intput is ZERO! ";
}
if(n > 0)
{
cout<< "The convert is " << int_to_ROMAN(n);
}
return 0;
}
void get_int_ref_checked(int& n) {
for(;;) // infinite loop
{
cout<< "Please enter an integer\n";
std::string inp;
std::stringstream ss;
ss << inp;
if( !(ss >> n) || n >= 4000 || n <= 0)
{
cout << "Error enter a number n: 0 < n < 4000: \n";
}
}
}

You are forward declaring the function int get_int_ref_checked() but there is no implementation, as int get_int_ref_checked(int& n) is another function, which is not being forward declared and so results in the error your seeing.

Related

Is there a way to store INT and strings in the same array?

I'm not sure how parsing works, nor have I been able to do it in C++.
I've created an algorithm that converts decimals to hexadecimals. The algorithm right now still outputs values bigger than 9, like 10 instead of A. The following function was supposed to deal with the issue but when I run it through, I can't store the normal 1-9 values with the As and Bs in the same array, which means I can't output them. I've been stuck on this for 2 days.
string hexValues(int remainder)
{
string A = "A";
string B = "B";
string C = "C";
string D = "D";
string E = "E";
string F = "F";
if (remainder == 10)
{
return A;
}
else if (remainder == 11)
{
return B;
}
else if (remainder == 12)
{
return C;
}
else if (remainder == 13)
{
return D;
}
else if (remainder == 14)
{
return E;
}
else if (remainder == 15)
{
return F;
}
}
hexMod = userDecNumber4Hex % 16;
if (hexMod > 9)
{
hexadecimalAnswer[y] = hexValues(hexMod);
}
else
{
hexadecimalAnswer[y] = hexMod;
}
while (userDecNumber4Hex != 0)
{
if (userDecNumber4Hex % 16 != 0)
{
hexMod = userDecNumber4Hex % 16;
if (hexMod > 9)
{
hexadecimalAnswer[y] = hexValues(hexMod);
}
else
{
hexadecimalAnswer[y] = hexMod;
}
userDecNumber4Hex = (userDecNumber4Hex-hexMod)/ 16;
y += 1;
}
else if (userDecNumber4Hex % 16 == 0)
{
userDecNumber4Hex = userDecNumber4Hex / 16;
if (userDecNumber4Hex > 9)
{
hexadecimalAnswer[y] = userDecNumber4Hex;
}
}
}
the code is long so i wasn't really sure what to post but there are multiple arrays- but its just one of them that i need to have store the values getting from the hexValues function, while it already has int values
Since the integers in your hexadecimal number are only going to range between 0 and 9, you can store them as characters. At the same time, you can store A-F as characters as well.
Therefore, instead return characters as the face values.
char hexValues (int remainder)
{
if (remainder < 10)
return '0' + remainder;
else
return 'A' + (remainder - 10);
}
For full conversion, here's a good excuse to use Recursion:
string decToHex (int n)
{
if (n < 16)
{
string s (1, decToHex (n));
return s;
}
else
return decToHex (n / 16) + hexValues (n % 16);
}

How to compare extracted digits in C++

I'm trying to implement the Bulls & Cows game and I have a logic problem. I am explicitly checking if each digit is either equal to a digit in the corresponding index (bulls) or at other indexes (cows). The value that I check with (4321) should yield "0 bulls and 4 cows" but it instead gives me "0 bulls and 3 cows.
Here is my code (and I apologize for the code repetition. I am also wondering if anyone has recommendations to make this code smaller):
#include <iostream>
#include <vector>
using namespace std;
int main() {
int guessValue = 1234;
int guess;
int bulls = 0;
int cows = 0;
cout << "Enter a 4 digit guess: ";
cin >> guess;
int firstValue = (guess % 10000) / 1000;
int secondValue = (guess % 1000) / 100;
int thirdValue = (guess % 100) / 10;
int fourthValue = guess % 10;
if (firstValue == ((guessValue % 10000) / 1000)) {bulls += 1;}
else if(firstValue == ((guessValue % 1000) / 100) ||
firstValue == ((guessValue % 100) / 10) ||
firstValue == (guess % 10))
{cows += 1;}
if (secondValue == ((guessValue % 1000) / 100)) {bulls += 1;}
else if (secondValue == ((guessValue % 10000) / 1000) ||
secondValue == ((guessValue % 100) / 10) ||
secondValue == (guess % 10))
{cows += 1;}
if (thirdValue == ((guessValue % 100) / 10)) {bulls += 1;}
else if (thirdValue == ((guessValue % 10000) / 1000) ||
thirdValue == ((guessValue % 1000) / 100) ||
thirdValue == (guess % 10))
{cows += 1;}
if (fourthValue == (guessValue % 10)) {bulls += 1;}
else if (fourthValue == ((guessValue % 10000) / 1000) ||
fourthValue == ((guessValue % 1000) / 100) ||
fourthValue == (guessValue % 100) / 10)
{cows += 1;}
cout << bulls << " bulls and " << cows << " cows" << endl;
}
I am also wondering if anyone has recommendations to make this code smaller
First of all use std::vector to keep separate digits:
std::vector<int> split( int v )
{
std::vector<int> r;
while( v ) {
r.push_back( v % 10 );
v /= 10;
}
return r;
}
Second, use standard algo std::count_if:
auto bulls = std::count_if( guessv.begin(), guessv.end(),
[it = targetv.begin()]( int i ) mutable
{ return i == *it++; } );
auto cows = std::count_if( guessv.begin(), guessv.end(),
[s = std::set<int>{ targetv.begin(), targetv.end() }]( int i )
{ return s.count( i ); } );
second one is actually counts cows and bulls, so it needs to be adjusted:
cows -= bulls;
live example
2 concepts that absolutely you need to master: loops and functions. First create some helpful functions.
These are the functions you could built your program upon:
int get_digit(int number, int order)
with example test cases:
get_digit(7895, 0) == 5
get_digit(7895, 1) == 9
get_digit(7895, 2) == 8
get_digit(7895, 3) == 7
then:
bool has_digit(int number, int digit)
with example test cases:
has_digit(7895, 1) == false
has_digit(7895, 8) == true
has_digit(7895, 5) == true
has_digit(7895, 0) == false
has_digit(7000, 0) == true
then:
bool matches_digit(int a, int b, int order)
with test cases:
matches_digit(1239, 4269, 0) == true
matches_digit(1239, 4269, 1) == false
matches_digit(1239, 4269, 2) == true
matches_digit(1239, 4269, 2) == false
and finally:
int get_cow(int a, int b)
int get_bull(int a, int b)
int main()
This is a top-down design, bottom-up implementation approach. First you think of the big picture and figure out what small pieces you need (functions) and then start implementing from the smallest most independent functions and step by step combine then into higher functions until you reach main.
This is my solution and it works. Basically I had to create a function to extract each digit and store them into a vector that can be applied to both the model and the guess. Then I used the find() method of the <algorithm> library to see if the digits exist in the guess vector and if yes, at which position compared to the model vector. Same position equals 1 bull and different position equals 1 cow. I am going to add more to this program, such as generating the model randomly and looping the program after each round so the user doesn't have to restart the game.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> getDigits(int modelValue) {
vector<int> vectorValue;
int extractedDigit = 0;
int modulant = 10000;
int divisor = 1000;
for (int i = 0; i < 4; i++) {
extractedDigit = (modelValue % modulant) / divisor;
vectorValue.push_back(extractedDigit);
modulant /= 10;
divisor /= 10;
}return vectorValue;
}
int main() {
int model = 1234;
int guess = 0000;
int bulls = 0;
int cows = 0;
int counter = 1;
cout << "Enter a value to guess: ";
cin >> guess;
vector<int> modelVector = getDigits(model);
vector<int> guessVector = getDigits(guess);
for (int i = 0; i < 4; i++) {
if (find(modelVector.begin(), modelVector.end(), guessVector[i]) != modelVector.end()) {
if (modelVector[i] == guessVector[i]) {bulls += 1;}
else { cows += 1; }
}
}cout << "There are " << bulls << " bulls and " << cows << " cows"<< endl;
}

Optimization of recursion in C++

I have a recursive function. And I want to optimize it as less as 10 sec. Higher use of Memory is not an issue.
Currently, it takes around 85 sec on Linux and three times more on Mac.
I could not understand in what way I can proceed?
Here is code:
using namespace std;
double get_wall_time(){
struct timeval time;
if (gettimeofday(&time,NULL)){
// Handle error
return 0;
}
return (double)time.tv_sec + (double)time.tv_usec * .000001;
}
int fun(long long n) {
if (n < 0) {
cout << "Please enter valid number";
return 0;
}
else if (n == 0 || n == 1)
return 1;
else if (n % 2 == 0)
return fun(n / 2);
else if (n % 2 == 1)
return fun(n / 2) + fun(n / 2 - 1);
else
return 0;
}
int main() {
double begin = get_wall_time();
cout << fun(123456789012345678) << std::endl;
double end = get_wall_time();
cout << "Time elapsed : " << double(end - begin);
return 0;
}
EDIT:
If n is even, return f(n/2)
If n is odd, return f(n/2)+f(n/2-1)
I would memoize the results using a std::map, like so:
std::map<long long, int>fun_results;
int fun(long long n) {
try {
return fun_results.at(n);
} catch(const std::out_of_range&) {
if (n < 0) {
cout << "Please enter valid number";
return 0;
}
else if (n == 0 || n == 1)
return fun_results[n] = 1;
else if (n % 2 == 0)
return fun_results[n] = fun(n / 2);
else if (n % 2 == 1)
return fun_results[n] = fun(n / 2) + fun(n / 2 - 1);
else
return 0;
}
}
Result:
1332403
Time elapsed : 0.000710011

How should I approach a credit card number validation algorithm?

I'm writing a program to validate credit card numbers and I have to use Luhn's Algorithm. Let me say beforehand, that I have just started to learn to program (we covered loops like last week), so there a lot of things I am unfamiliar with. I am having trouble with one of my functions that checks the arithmetic. Basically, it has to double every second digit from right to left and add everything together. But if you double a number, like 5, and you get 10, then you will have to add 1+0=1 to the total sum instead of 10. That's the part I'm stuck on. How can I put that in a program?
Sample code so far:
int
doubleEvenSum(string creditCardNumber) {
int evenSum;
int countPosition;
int doublePosition;
int length;
length = creditCardNumber.length ();
countPosition = creditCardNumber.at(length - 2);
evenSum = 0;
while(countPosition>0) {
if ((2 * countPosition) < 10) {
doublePosition = 2 * countPosition;
}
else if ((2 * countPosition) > 9) {
???
}
evenSum = evenSum + doublePosition;
}
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/*
return the Luhn (MOD10) checksum for a sequence of digits.
-1 is returned on error (a non-digit was in the sequence
*/
int mod10( char const* s)
{
int len = strlen(s);
int sum = 0;
int dbl = 0;
while (len) {
char digit;
int val;
--len;
digit = s[len];
if (!isdigit( (unsigned char) digit)) return -1; // non digit in the sequence
val = digit - '0'; // convert character to numeric value
if (dbl) {
// double the value
val *= 2;
// if the result is double-digits, add the digits together
if (val > 9) {
val = val - 10;
val = val + 1;
}
}
dbl = !dbl; // only double value every other time
sum += val;
}
return sum % 10;
}
Here is a different algorithm. I cut/pasted from a C# example; the second link discusses a number of optimization for Luhn.
Please study this example, and please run it through the debugger to study how the code behaves as it's executing. Understanding how code actually runs (as opposed to how you think it will run when you write it) is an essential skill. IMHO....
/*
* Validate credit card with Luhn Algorithm
*
* REFERENCES:
* - http://jlcoady.net/c-sharp/credit-card-validation-in-c-sharp
* - http://orb-of-knowledge.blogspot.com/2009/08/extremely-fast-luhn-function-for-c.html
*/
#include <stdio.h> // printf(), scanf(), etc
#include <string.h> // strlen (), etc
#include <ctype.h> // isdigit(), etc
#if !defined(FALSE)
#define FALSE 0
#define TRUE ~FALSE
#endif
/*
* type definitions (should go in separate header)
*/
enum CardType {
MASTERCARD=1, BANKCARD=2, VISA=3, AMEX=4, DISCOVER=5, DINERS=6, JCB=7
};
/*
* function prototypes (should also go in header)
*/
int luhn (int number[], int len);
bool validate (CardType cardType, char *cardNumber);
/*
* program main
*/
int
main (int argc, char *argv[])
{
char cc_number[80];
int cc_type;
for ( ;; ) {
printf ("Enter a credit card number and type (1, 2, 3, 4, 5. 6 or 7):\n");
printf (" MASTERCARD=1, BANKCARD=2, VISA=3, AMEX=4, DISCOVER=5, DINERS=6, JCB=7\n");
int iret = scanf ("%s %d", cc_number, &cc_type);
if (iret == 2)
break;
else
printf ("Incorrect input: please enter a valid CC# and CC type\n");
}
if (validate ((CardType)cc_type, cc_number))
printf ("Valid\n");
else
printf ("Invalid card type/number\n");
return 0;
}
/*
* validate card#
*/
bool
validate (CardType cardType, char *cardNumber)
{
// 16 or fewer digits?
int len = strlen(cardNumber);
if (strlen (cardNumber) > 16)
return false;
// number to validate
int number[16];
for(int i = 0; i < (int)strlen (cardNumber); i++) {
if(!isdigit(cardNumber[i]))
return FALSE;
number[i] = cardNumber[i] - '0';
}
// Validate based on card type, first if tests length, second tests prefix
switch(cardType) {
case MASTERCARD:
if(len != 16)
return FALSE;
if(number[0] != 5 || number[1] == 0 || number[1] > 5)
return FALSE;
break;
case BANKCARD:
if(len != 16)
return FALSE;
if(number[0] != 5 || number[1] != 6 || number[2] > 1)
return FALSE;
break;
case VISA:
if(len != 16 && len != 13)
return FALSE;
if(number[0] != 4)
return FALSE;
break;
case AMEX:
if(len != 15)
return FALSE;
if(number[0] != 3 || (number[1] != 4 && number[1] != 7))
return FALSE;
break;
case DISCOVER:
if(len != 16)
return FALSE;
if(number[0] != 6 || number[1] != 0 || number[2] != 1 || number[3] != 1)
return FALSE;
break;
case DINERS:
if(len != 14)
return FALSE;
if(number[0] != 3 || (number[1] != 0 && number[1] != 6 && number[1] != 8) || number[1] == 0 && number[2] > 5)
return FALSE;
break;
case JCB:
if(len != 16 && len != 15)
return FALSE;
if(number[0] != 3 || number[1] != 5)
return FALSE;
break;
default:
return FALSE;
}
int sum = luhn (number, len);
return (sum % 10 == 0);
}
// Use Luhn Algorithm to validate
int luhn (int number[], int len)
{
int sum = 0;
for(int i = len - 1; i >= 0; i--)
{
if(i % 2 == len % 2)
{
int n = number[i] * 2;
sum += (n / 10) + (n % 10);
}
else
sum += number[i];
}
return sum;
}
int luhnCardValidator(char cardNumbers[]) {
int sum = 0, nxtDigit, i;
for (i = 0; cardNumbers[i] != NULL_TERMINATOR ; i++) {
nxtDigit = cardNumbers[i] - START_OF_ASCII_NUMERIC;
if (i % 2 == 0)
nxtDigit = (nxtDigit > 4) ? (nxtDigit * 2 - 10) + 1 : nxtDigit * 2;
sum += nxtDigit;
}
return (sum % 10);
}
This:
... (nxtDigit > 4) ? (nxtDigit * 2 - 10) + 1 : ...
is the clever bit. If the digit is greater than 4, then the doubling will be 10 or more. In that case, you take the doubled number and subtract 10 which will give you the ones-digit then you add 1 (the tens-digit).
Just subtract 9 from the double of the number then you will equivalent of the sum of the digits.
For ex.
7= 7*2 = 14 = 1+4 = 5 OR 14-9 = 5
This is more efficient than writing code for adding both digits.

I keep getting a 'no match for call to' error

#include <iostream>
#include <string>
using namespace std;
// Turns a digit between 1 and 9 into its english name
// Turn a number into its english name
string int_name(int n)
{
string digit_name;
{
if (n == 1) return "one";
else if (n == 2) return "two";
else if (n == 3) return "three";
else if (n == 4) return "four";
else if (n == 5) return "five";
else if (n == 6) return "six";
else if (n == 7) return "seven";
else if (n == 8) return "eight";
else if (n == 9) return "nine";
return "";
}
string teen_name;
{
if (n == 10) return "ten";
else if (n == 11) return "eleven";
else if (n == 12) return "twelve";
else if (n == 13) return "thirteen";
else if (n == 14) return "fourteen";
else if (n == 14) return "fourteen";
else if (n == 15) return "fifteen";
else if (n == 16) return "sixteen";
else if (n == 17) return "seventeen";
else if (n == 18) return "eighteen";
else if (n == 19) return "nineteen";
return "";
}
string tens_name;
{
if (n == 2) return "twenty";
else if (n == 3) return "thirty";
else if (n == 4) return "forty";
else if (n == 5) return "fifty";
else if (n == 6) return "sixty";
else if (n == 7) return "seventy";
else if (n == 8) return "eighty";
else if (n == 9) return "ninety";
return "";
}
int c = n; // the part that still needs to be converted
string r; // the return value
if (c >= 1000)
{
r = int_name(c / 1000) + " thousand";
c = c % 1000;
}
if (c >= 100)
{
r = r + " " + digit_name(c / 100) + " hundred";
c = c % 100;
}
if (c >= 20)
{
r = r + " " + tens_name(c /10);
c = c % 10;
}
if (c >= 10)
{
r = r + " " + teen_name(c);
c = 0;
}
if (c > 0)
r = r + " " + digit_name(c);
return r;
}
int main()
{
int n;
cout << endl << endl;
cout << "Please enter a positive integer: ";
cin >> n;
cout << endl;
cout << int_name(n);
cout << endl << endl;
return 0;
}
I Keep getting this Error code:
intname2.cpp: In function âstd::string
int_name(int)â:
intname2.cpp:74: error: no match for
call to â(std::string) (int)â
intname2.cpp:80: error: no match for
call to â(std::string) (int)â
intname2.cpp:86: error: no match for
call to â(std::string) (int&)â
intname2.cpp:91: error: no match for
call to â(std::string) (int&)â
You are using digit_name, teen_name, etc as functions, when they are defined as variables. If you want to use them like that, you need to define them before your int_name function like this:
string digit_name(int n)
{
if (n == 1) return "one";
else if (n == 2) return "two";
else if (n == 3) return "three";
else if (n == 4) return "four";
else if (n == 5) return "five";
else if (n == 6) return "six";
else if (n == 7) return "seven";
else if (n == 8) return "eight";
else if (n == 9) return "nine";
return "";
}
Timothy, it looks like you're confused about the requirements of the assignment. Please make sure you understand the requirements, because at this stage it doesn't look like you know what's expected of you. You're trying to move the body of one function into the body of another function and that's simply not possible to do.
Please post the exact words that your teacher used in order for us to give you proper advice on the question.
Here are some tips for you:
If your teacher has covered switch statements then use switch statements.
Check if your teacher is not asking you to do function declarations.
Check if your teacher is not asking you to put the functions in libraries (a header file and source file).
OK scrap the tips... given your teacher's requirements I think it might look a little bit like this:
string int_name(int n)
{
int c = n; // the part that still needs to be converted
string r; // the return value
if (c >= 1000)
{
r = int_name(c / 1000) + " thousand";
c = c % 1000;
}
if (c >= 100)
{
// If you have covered switch statements then it will look like this
string digitName;
switch(c/100) // <- instead of calling digit_name(c/100), we call switch(c/100)
{
case 1:
// assign the digit name
digitName = "one";
break;
case 2:
//... fill here with your own code
break;
case 3:
//... fill here with your own code
break;
// write all the cases through 9
default:
digitName = "";
break;
}
// in the result string use the digitName variable
// instead of calling the digit_name function
r = r + " " + digitName + " hundred";
c = c % 100;
}
if (c >= 20)
{
r = r + " " + tens_name(c /10);
c = c % 10;
}
if (c >= 10)
{
r = r + " " + teen_name(c);
c = 0;
}
if (c > 0)
r = r + " " + digit_name(c);
return r;
}
Note that I'm using a switch statement, but if you your teacher hasn't shown you switch statements yet, then you can still use if/else statements:
string int_name(int n)
{
int c = n; // the part that still needs to be converted
string r; // the return value
if (c >= 1000)
{
r = int_name(c / 1000) + " thousand";
c = c % 1000;
}
if (c >= 100)
{
// declare a digitName
string digitName;
// declare a temporary value
int temp = c/100;
if(1 == temp)
{
// assign the digit name
digitName = "one";
}
else if( 2 == temp )
{
digitName = "two";
}
else if( 3 == temp )
{
// fill in the rest
}
else if( 4 == temp )
{
// fill in the rest
}
// write all the other else if statements
else
{
digitName = "":
}
// in the result string use the digitName variable
// instead of calling the digit_name function
r = r + " " + digitName + " hundred";
c = c % 100;
}
if (c >= 20)
{
r = r + " " + tens_name(c /10);
c = c % 10;
}
if (c >= 10)
{
r = r + " " + teen_name(c);
c = 0;
}
if (c > 0)
r = r + " " + digit_name(c);
return r;
}
You're going to have to take the first example with digit_name and apply it to tens_name and teen_name functions.
WARNING:
In reality you don't want to repeat the same code and clutter a single function with a bunch of code that could be in its own function. You ALWAYS want to break out repeating code into functions... if she's asking you to repeat code when you can use functions then you should be concerned. Ask your teacher if this is what she REALLY wants you to do!