How to change a number's digits in a recursive function? C++ - c++

I have to input a number n, an a digit and a b digit and output the number n with all the a digits in it replaced by a b one. For example:
Input:
n = 1561525
a = 5
b = 9
Output:
n = 1961929
Should be recursive ! I didn't post any code as I've done it in a non-recursive way but apparently it's not even close to what I need.
Thanks for the help !

Check this, it works but maybe it is to much C
int convert(int num, int a, int b)
{
if( num )
{
int res = convert(num/10,a,b);
int t = num%10;
res *=10;
t = t == a ? b:t;
res = res + t;
return res;
}
return 0;
}
Divide by 10 the initial number, until nothing left of it, and then construct it again replacing a with b.

To make things easier, you can convert the number into a string (a char[] in C++). Then, it's a simple matter of iterating over it and checking at each step if the number we want to replace was found in the current position. For a possible solution, here's an implementation of the algorithm in Python - one of the nice things of the language is that it reads almost as pseudocode, and it should be relatively simple to port to C++:
def aux(n, a, b, i):
if i == len(n):
return ''
elif n[i] == a:
return b + aux(n, a, b, i+1)
else:
return n[i] + aux(n, a, b, i+1)
def change(n, a, b):
return int(aux(str(n), str(a), str(b), 0))
It works as expected:
change(1561525, 5, 9)
=> 1961929

So the easiest and safest way I can think of, is by using std::replace:
int replace(int num, int d1, int d2) {
string s = std::to_string(num); // convert to string
std::replace( s.begin(), s.end(), d1+'0', d2+'0'); // call std::replace
return atoi( s.c_str() ); // return the int
}
Now if you really have to use recursion (there is no need for it here), here's one possible solution:
using std::string;
// recursive function, accepts a string, current index, c2 replaces c1
string replace_rec (string s, unsigned index, char c1, char c2) {
// check if the it's still a valid index
if (index < s.size()) {
// if this is a char to be converted, do so
if (s[index] == c1)
s[index] = c2;
// call itself but with an updated string and incremented index
replace_rec(s, index+1, c1, c2);
}
// the last call will result in the string with all chars checked. return it
return s;
}
// call this function with input, the num to be replaced and what with
int replace(int num, int d1, int d2) {
string s = std::to_string(num); // convert to string
// convert the result back to int and return it.
return atoi( replace_rec(s, 0, d1+'0', d2+'0').c_str() );
}
In any case, you can call your replace() function like this:
int main(){
cout << replace (4578, 4, 9); // output: 9578
cin.get();
}

Related

C++ algorithmic code won't compile correctly

I'm doing this code for a project to evaluate an algorithmic equation, if it doesn't have a "a" in the string of the algorithmic equation I'm given, I'm supposed to return the value and return false. If it does have "a" I'm supposed to return value = 0 and return true. This is all being done a in a bool function.
#include <string>
#include <sstream>
bool Evaluate(const string& expression, int& value){
int a;
int b;
int c;
int d;
int e;
string valueA;
string valueB;
string valueC;
string valueD;
string valueE;
int y;
int z;
unsigned int i;
stringstream x;
int szz;
string alg;
if(!expression.find('a')) {
szz = expression.size();
alg = expression.copy(0, szz);
for (i = 0; i <= szz; ++i) {
alg.find_first_of('*/%');
if (isdigit(alg[i] - '*')) {
a = alg.find('*');
y = a - 1;
z = a + 1;
valueA = alg.substr(y, z);
a = stoi(valueA);
x << a;
valueA = x.str();
alg.replace(y, 2, valueA);
}
if (isdigit(alg[i] - '/')) {
b = alg.find('/');
y = b - 1;
z = b + 1;
valueB = alg.substr(y, z);
b = stoi(valueB);
x << b;
valueB = x.str();
alg.replace(y, 2, valueB);
}
value = stoi(alg);
return false;
}
else{
value = 0;
return true;
}
}
I'm expecting to get the correct values and the correct true/false. Currently if there's an a in the equation I get the result correct as 0, but not the evaluate result (true/false). The opposite happens if there's no a in the equation, I get the evaluate result correct as false but not the actual correct value.
Your algorithm does a lot more than what you write. The goal, apparently, is not to look for a but rather to evaluate entire math expressions.
Furthermore, your algorithm is flawed in many ways, I just point out some here:
The if in
string alg;
if(!alg.find('a')) {
is always true since there never is an 'a' in alg since alg is created empty just the line before.
This does just copy an entire string
szz = expression.size();
alg = expression.copy(0, szz);
and is 100% equivalent to string alg = expression;
You don't need a for loop in
for (i = 0; i <= szz; ++i) {
alg.find_first_of('*/%');
since the find_first_of does what it advertises and already loops over the string itself.
You just discard the return value of alg.find_first_of('*/%');. You want to write int operator_position = alg.find_first_of('*/%');, then you know that at alg[operator_position] there is one of */%.
You have several lines of this type
isdigit(alg[i] - '*')
but it appears to be obvious to me that this is very much not what you want. From the logic of your code, I understand you need to know if a sub-string in alg is a digit (or still an expression containing +-*/%). Your statement only acts on a single char
Other potential problems.
You actual problem you describe can be solved easily:
bool Evaluate(const string& expression, int& value){
if (expression.find('a')!=string::npos) {
// whatever it means to "contain the value" ????
return false;
}
value = 0;
return true;
}
But this will serve no reasonable purpose and I am sure you are really just mis-representing the actual problem posed....
Here is what I would infer as an actual related problem and algorithm: Q: evaluate math expressions from a string and return the answer. Thus, "2*6+4-6/2" should return 13. If you want to achieve this, you need iterative function calling of Evaluate and I would propose double Evaluate(const string& expression):
you evaluate if your string contains any of +- if yes, you iteratively evaluate the two independent parts (using expression.substr(start,length)) proceeding as well as preceeding the operator_position (see above for a hint). You then either add or subtract the two results depending on + or -. You return the result.
(else) you evaluate if your string contains any of */% and if yes, you iteratively evaluate the two independent sub-strings proceeding and preceeding the operator_position. You either multiply, divide or modulo the two values and return the result.
if none of the two above, then the remaining expression must be a number and you convert the string into a double (std::stod(expression)) and return it.
This iterative algorithm will magically correctly evaluate any math expression.

Is it possible to add multiple integers by user input?

Very new to "backend" and trying out this reddit challenge that I saw at r/dailyprogrammer
Challenge:
Assign every lowercase letter a value, from 1 for a to 26 for z. Given a string of lowercase letters, find the sum of the values of the letters in the string.
I specifically want to do it like this but is it possible? How can a user input a word that would then add the int I've listed here so that the total sum of the word would show.
int main()
{
int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
a=1;
b=2;
c=3;
d=4;
e=5;
f=6;
g=7;
h=8;
i=9;
j=10;
k=11;
l=12;
m=13;
n=14;
o=15;
p=16;
q=17;
r=18;
s=19;
t=20;
u=21;
v=22;
w=23;
x=24;
y=25;
z=26;
This is pretty much one function call in C++
std::string example = "example";
std::cout << std::accumulate(example.begin(), example.end(), 0,
[](int sum, char c) { return sum + (c - 'a' + 1); }
);
std::accumulate adds things in a collection. Usually, it just uses '+' but in this case I use a custom adder [](int sum, char c) { return sum + (c - 'a' + 1); }. This adds not the ASCII value of c, but (c - 'a' + 1). If c=='a', then c-'a'==0 and (c - 'a' + 1)==1
ok , so , this is my code and it's working ... explanation -- >
we know storing a charachter in a int variable will store the ASCII value , the ASCII value of a is 97 , b is 98 so on .... subtracting 96 from each letter's ascii value will give the number you want -->
if you are still confused about the ascii table then go look it up at the google you'll understand
#include <iostream>
#include <string>
using namespace std;
int main(){
string str ;
cin >> str;
int value = 0;
for(int i=0 ; i<str.length() ; i++){
int v = str[i] - 96;
value += v;
}
cout << value;
return 0;
}
make use of the std::map<char,int>
int main(void)
{
std::map<std::string,int> list;
char letter = 'a';
int val = 1;
while(val <= 26)
{
list.insert(std::make_pair(letter,val));
letter++;
val++;
}
}
You're confusing the concept of strings and characters with a variable's name.
// a is the variable name, this is information for the programmer
int a = 1;
// 'a' here is the actual letter a, things can actually be done with this in the program
char theLetterA = 'a';
Combine this concept with std::cin so that you can read data from the user and you are on your way to figuring this out.
See:
https://www.cplusplus.com/doc/tutorial/basic_io/
https://www.w3schools.com/cpp/cpp_data_types_char.asp
https://www.w3schools.com/cpp/cpp_data_types.asp

How can I keep only non-zero digits from an integer?

I am currently using the code below that removes all digits equal to zero from an integer.
int removeZeros(int candid)
{
int output = 0;
string s(itoa(candid));
for (int i = s.size(); i != 0; --i)
{
if (s[i] != '0') output = output * 10 + atoi(s[i]);
}
return output;
}
The expected output for e.g. 102304 would be 1234.
Is there a more compact way of doing this by directly working on the integer, that is, not string representation? Is it actually going to be faster?
Here's a way to do it without strings and buffers.
I've only tested this with positive numbers. To make this work with negative numbers is an exercise left up to you.
int removeZeros(int x)
{
int result = 0;
int multiplier = 1;
while (x > 0)
{
int digit = x % 10;
if (digit != 0)
{
int val = digit * multiplier;
result += val;
multiplier *= 10;
}
x = x / 10;
}
return result;
}
For maintainability, I would suggest, don't work directly on the numeric value. You can express your requirements in a very straightforward way using string manipulations, and while it's true that it will likely perform slower than number manipulations, I expect either to be fast enough that you don't have to worry about the performance unless it's in an extremely tight loop.
int removeZeros(int n) {
auto s = std::to_string(n);
s.erase(std::remove(s.begin(), s.end(), '0'), s.end());
return std::stoi(s);
}
As a bonus, this simpler implementation handles negative numbers correctly. For zero, it throws std::invalid_argument, because removing all zeros from 0 doesn't produce a number.
You could try something like this:
template<typename T> T nozeros( T const & z )
{
return z==0 ? 0 : (z%10?10:1)*nozeros(z/10)+(z%10);
}
If you want to take your processing one step further you can do a nice tail recursion , no need for a helper function:
template<typename T> inline T pow10(T p, T res=1)
{
return p==0 ? res : pow10(--p,res*10);
}
template<typename T> T nozeros( T const & z , T const & r=0, T const & zp =0)
{
static int digit =-1;
return not ( z ^ r ) ? digit=-1, zp : nozeros(z/10,z%10, r ? r*pow10(++digit)+zp : zp);
}
Here is how this will work with input 32040
Ret, z, r, zp, digits
-,32040,0,0, -1
-,3204,0,0, -1
-,320,4,0,0, -1
-,32,0,4,4, 0
-,3,2,4, 0
-,0,3,24, 1
-,0,0,324, 2
324,-,-,-, -1
Integer calculations are always faster than actually transforming your integer to string, making comparisons on strings, and looking up strings to turn them back to integers.
The cool thing is that if you try to pass floats you get nice compile time errors.
I claim this to be slightly faster than other solutions as it makes less conditional evaluations which will make it behave better with CPU branch prediction.
int number = 9042100;
stringstream strm;
strm << number;
string str = strm.str();
str.erase(remove(str.begin(), str.end(), '0'), str.end());
number = atoi(str.c_str());
No string representation is used here. I can't say anything about the speed though.
int removezeroes(int candid)
{
int x, y = 0, n = 0;
// I did this to reverse the number as my next loop
// reverses the number while removing zeroes.
while (candid>0)
{
x = candid%10;
n = n *10 + x;
candid /=10;
}
candid = n;
while (candid>0)
{
x = candid%10;
if (x != 0)
y = y*10 + x;
candid /=10;
}
return y;
}
If C++11 is available, I do like this with lambda function:
int removeZeros(int candid){
std::string s=std::to_string(candid);
std::string output;
std::for_each(s.begin(), s.end(), [&](char& c){ if (c != '0') output += c;});
return std::stoi(output);
}
A fixed implementation of g24l recursive solution:
template<typename T> T nozeros(T const & z)
{
if (z == 0) return 0;
if (z % 10 == 0) return nozeros(z / 10);
else return (z % 10) + ( nozeros(z / 10) * 10);
}

What parameters this formula takes when in "accumulate"?

This code is copied from another user question and I`m curious how accumulate works here.
I get the correct result from this code, but would like to know what parameters lcm takes when in "accumulate". The init as A and the sum of the range as b? Please help
#include <numeric>
int gcd(int a, int b)
{
for (;;)
{
if (a == 0) return b;
b %= a;
if (b == 0) return a;
a %= b;
}
}
int lcm(int a, int b)
{
int temp = gcd(a, b);
return temp ? (a / temp * b) : 0;
}
int main()
{
int arr[] = { 5, 7, 9, 12 };
int result = std::accumulate(arr, arr + 4, 1, lcm);
std::cout << result << '\n';
}
The first argument that lcm will take is the accumulated value so far (which starts at 1, the third argument of std::accumulate), and the second argument will be an element in arr. Next, whatever lcm returns is passed as the first argument and the next element in arr as the second.
See a reference for more details.
You could easily write a and b to the standard output inside lcm to see what's happening.

Sorting std::strings with numbers in them?

I'm currently sorting by the std::string < operator. The problem with it is that:
30 < 9. The 30 shows up before the 9 since 3 < 9, Windows 9x had this issue to. How could I go about sorting them numerically so that "30 Foxes" shows up after "9 dogs". I should also add that I'm using utf 8 encoding.
Thanks
You can create a custom comparison function to use with std::sort. This function would have to check if the string begins with a numeric value. If it does, convert the numeric part of each string to an int using some mechanism like a stringstream. Then compare the two integer values. If the values compare equally, compare the non-numeric part of the strings lexicographically. Otherwise, if the strings don't contain a numeric part, simply compare the two strings lexicographically as normal.
Basically, something like the following (untested) comparison function:
bool is_not_digit(char c)
{
return !std::isdigit(c);
}
bool numeric_string_compare(const std::string& s1, const std::string& s2)
{
// handle empty strings...
std::string::const_iterator it1 = s1.begin(), it2 = s2.begin();
if (std::isdigit(s1[0]) && std::isdigit(s2[0])) {
int n1, n2;
std::stringstream ss(s1);
ss >> n1;
ss.clear();
ss.str(s2);
ss >> n2;
if (n1 != n2) return n1 < n2;
it1 = std::find_if(s1.begin(), s1.end(), is_not_digit);
it2 = std::find_if(s2.begin(), s2.end(), is_not_digit);
}
return std::lexicographical_compare(it1, s1.end(), it2, s2.end());
}
And then...
std::sort(string_array.begin(), string_array.end(), numeric_string_compare);
EDIT: Of course, this algorithm is only useful if you're sorting strings where the numeric portion appears at the beginning of the string. If you're dealing with strings where the numeric portion can appear anywhere in the string, then you need a more sophisticated algorithm. See http://www.davekoelle.com/alphanum.html for more information.
If you are targeting Windows (XP+) and can afford to convert your strings to utf-16, you can use the StrCmpLogicalW function from Shlwapi. See msdn for details.
Otherwise, ICU provides this functionality in its collators. See UCOL_NUMERIC_COLLATION.
Here's a version that doesn't convert to integer and thus works for long strings of digits regardless of sizeof(int).
#include <cctype>
#include <cstddef>
#include <cstring>
#include <string>
int numcmp(const char *a, const char *aend, const char *b, const char *bend)
{
for (;;) {
if (a == aend) {
if (b == bend)
return 0;
return -1;
}
if (b == bend)
return 1;
if (*a == *b) {
++a, ++b;
continue;
}
if (!isdigit((unsigned char) *a) || !isdigit((unsigned char) *b))
return *a - *b;
// skip leading zeros in both strings
while (*a == '0' && ++a != aend)
;
while (*b == '0' && ++b != aend)
;
// skip to end of the consecutive digits
const char *aa = a;
while (a != aend && isdigit((unsigned char) *a))
++a;
std::ptrdiff_t alen = a - aa;
const char *bb = b;
while (b != bend && isdigit((unsigned char) *b))
++b;
std::ptrdiff_t blen = b - bb;
if (alen != blen)
return alen - blen;
// same number of consecutive digits in both strings
while (aa != a) {
if (*aa != *bb)
return *aa - *bb;
++aa, ++bb;
}
}
}
int numcmp(const std::string& a, const std::string& b)
{
return numcmp(a.data(), a.data() + a.size(),
b.data(), b.data() + b.size());
}
int numcmp(const char *a, const char *b)
{
return numcmp(a, a + strlen(a), b, b + strlen(b));
}
This what worked for me (assuming no leading zeroes), i.e. the idea is that phonetic compare can be applied just to numbers with same number of digits.
auto numeric_str_cmp = [](const std::string& a, const std::string& b) -> bool {
return (a.size() < b.size()) || (a.size() == b.size() && a < b);
};
std::sort(numeric_strings.begin(), numeric_strings.end(), numeric_str_cmp);