luhn algorithm and 'digit manipulation' in C++ - c++

In generating the 'check digit' in Luhn's algorithm
The check digit (x) is obtained by computing the sum of digits then computing 9 times that value modulo 10 (in equation form, (67 * 9
mod 10)). In algorithm form: Compute the sum of the digits (67).
Multiply by 9 (603). The last digit, 3, is the check digit.
Natural instincts point towards taking an id as a string to make individual digit operation easier. But there seems to be no way to extract a digit at a time through stringstream since there's no delimiter(as far as I can tell). So the process turns into a cumbersome conversion of individual characters to ints...
There's modulus for each digit approach as well, which also takes a bit of work.
I guess what I'm getting at is that I feel maybe I'm overlooking a more elegant way taking an input and operating on the input as if they were single digit inputs.

Use modular arithmetic to simply the equation like following :-
checkdigit = (sum_digits*9)%10
= ((sum_digits)%10*9)%10
Now sum_digits%10 is very simple to evaluate using strings.
C++ implementation :-
#include<iostream>
using namespace std;
int main() {
char* str = new char[100];
cout<<"Enter the String: ";
cin>>str;
int val = 0;
for(int i=0;str[i]!=0;i++) {
val = (val+str[i]-'0')%10;
}
val = (val*9)%10;
cout<<"Checkdigit("<<str<<") = "<<val;
return 0;
}

Stringstream has to calculate all digits and then convert each digit to a char by adding '0'. You'd have to subtract '0' again to get the digit values back. You'd be better off using the modulo approach directly.

Related

How to sort non-numeric strings by converting them to integers? Is there a way to convert strings to unique integers while being ordered?

I am trying to convert strings to integers and sort them based on the integer value. These values should be unique to the string, no other string should be able to produce the same value. And if a string1 is bigger than string2, its integer value should be greater. Ex: since "orange" > "apple", "orange" should have a greater integer value. How can I do this?
I know there are an infinite number of possibilities between just 'a' and 'b' but I am not trying to fit every single possibility into a number. I am just trying to possibly sort, let say 1 million values, not an infinite amount.
I was able to get the values to be unique using the following:
long int order = 0;
for (auto letter : word)
order = order * 26 + letter - 'a' + 1;
return order;
but this obviously does not work since the value for "apple" will be greater than the value for "z".
This is not a homework assignment or a puzzle, this is something I thought of myself. Your help is appreciated, thank you!
You are almost there ... just a minor tweaks are needed:
you are multiplying by 26
however you have letters (a..z) and empty space so you should multiply by 27 instead !!!
Add zeropading
in order to make starting letter the most significant digit you should zeropad/align the strings to common length... if you are using 32bit integers then max size of string is:
floor(log27(2^32)) = 6
floor(32/log2(27)) = 6
Here small example:
int lexhash(char *s)
{
int i,h;
for (h=0,i=0;i<6;i++) // process string
{
if (s[i]==0) break;
h*=27;
h+=s[i]-'a'+1;
}
for (;i<6;i++) h*=27; // zeropad missing letters
return h;
}
returning these:
14348907 a
28697814 b
43046721 c
373071582 z
15470838 abc
358171551 xyz
23175774 apple
224829626 orange
ordered by hash:
14348907 a
15470838 abc
23175774 apple
28697814 b
43046721 c
224829626 orange
358171551 xyz
373071582 z
This will handle all lowercase a..z strings up to 6 characters length which is:
26^6 + 26^5 +26^4 + 26^3 + 26^2 + 26^1 = 321272406 possibilities
For more just use bigger bitwidth for the hash. Do not forget to use unsigned type if you use the highest bit of it too (not the case for 32bit)
You can use position of char:
std::string s("apple");
int result = 0;
for (size_t i = 0; i < s.size(); ++i)
result += (s[i] - 'a') * static_cast<int>(i + 1);
return result;
By the way, you are trying to get something very similar to hash function.

pigeon hole / multiple numbers

input : integer ( i'll call it N ) and (1 <= N <= 5,000,000 )
output : integer, multiple of N and only contains 0,7
Ex.
Q1 input : 1 -> output : 7 ( 7 mod 1 == 0 )
Q2 input : 2 -> output : 70 ( 70 mod 2 == 0 )
#include <string>
#include <iostream>
using namespace std;
typedef long long ll;
int remaind(string num, ll m)
{
ll mod = 0;
for (int i = 0; i < num.size(); i++) {
int digit = num[i] - '0';
mod = mod * 10 + digit;
mod = mod % m;
}
return mod;
}
int main()
{
int n;
string ans;
cin >> n;
ans.append(n, '7');
for (int i = ans.length() - 1; i >= 0; i--)
{
if (remaind(ans, n) == 0)
{
cout << ans;
return 0;
}
ans.at(i) = '0';
}
return 0;
}
is there a way to lessen the time complexity?
i just tried very hard and it takes little bit more time to run while n is more than 1000000
ps. changed code
ps2. changed code again because of wrong code
ps3. optimize code again
ps4. rewrite post
Your approach is wrong, let's say you divide "70" by 5. Then you result will be 2 which is not right (just analyze your code to see why that happens).
You can really base your search upon numbers like 77777770000000, but think more about that - which numbers you need to add zeros and which numbers you do not.
Next, do not use strings! Think of reminder for a * b if you know reminder of a and reminder of b. When you program it, be careful with integer size, use 64 bit integers.
Now, what about a + b?
Finally, find reminders for numbers 10, 100, 1000, 10000, etc (once again, do not use strings and still try to find reminder for any power of 10).
Well, if you do all that, you'll be able to easily solve the whole problem.
May I recommend any of the boost::bignum integer classes?
I suspect uint1024_t (or whatever... they also have 128, 256, and 512, bit ints already typedefed, and you can declare your own easily enough) will meet your needs, allowing you to perform a single %, rather than one per iteration. This may outweigh the performance lost when using bignum vs c++'s built-in ints.
2^1024 ~= 1.8e+308. Enough to represent any 308 digit number. That's probably excessive.
2^512 ~= 1.34e+154. Good for any 154 digit number.
etc.
I suspect you should first write a loop that went through n = 4e+6 -> 5e+6 and wrote out which string got the longest, then size your uint*_t appropriately. If that longest string length is more than 308 characters, you could just whip up your own:
typedef number<cpp_int_backend<LENGTH, LENGTH, unsigned_magnitude, unchecked, void> > myReallyUnsignedBigInt;
The modulo operator is probably the most expensive operation in that inner loop. Performing once per iteration on the outer loop rather than at the inner loop (O(n) vs O(n^2)) should save you quite a bit of time.
Will that plus the whole "not going to and from strings" thing pay for bignum's overhead? You'll have to try it and see.

Can't understand the proof behind the use of this map<> method

Drazil is playing a math game with Varda.
Let's define for positive integer x as a product of factorials of its
digits. For example, f(135) = 1! * 3! * 5! = 720.
First, they choose a decimal number a consisting of n digits that
contains at least one digit larger than 1. This number may possibly
start with leading zeroes. Then they should find maximum positive
number x satisfying following two conditions:
x doesn't contain neither digit 0 nor digit 1.
= f(x) = f(a)
Help friends find such number.
Input The first line contains an integer n (1 ≤ n ≤ 15) — the number
of digits in a.
The second line contains n digits of a. There is at least one digit in
a that is larger than 1. Number a may possibly contain leading zeroes.
Output Output a maximum possible integer satisfying the conditions
above. There should be no zeroes and ones in this number decimal
representation.
Examples
input
4
1234
output
33222
input
3
555
output
555
Here is the solution,
#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
int main()
{
map<char, string> mp;
mp['0'] = mp['1'] = "";
mp['2'] = "2";
mp['3'] = "3";
mp['4'] = "223";
mp['5'] = "5";
mp['6'] = "35";
mp['7'] = "7";
mp['8'] = "2227";
mp['9'] = "2337";
int n;
string str;
cin>>n>>str;
string res;
for(int i = 0; i < str.size(); ++i)
res += mp[str[i]];
sort(res.rbegin(), res.rend());
cout<<res;
return 0;
}
I'd like if someone explains the reason why were the digits transformed into other form of digits rather than just with some way to compute the number with..sadly brute force would give a TLE(Time limit exceeded) in this question cause of the 15 digit thing so that's a big number to brute force to,so I kindly hope that someone can explain the "proof" below, cause idk what theory says that these numbers can be transformed to those numbers for example 4 to 223 and stuff.
Thanks in advance.
Picture: What the proof says
The theory behind these transformations is the following (Ill use 4 as an example):
4! = 3! * 2! * 2!
A longer sequence of digits will always produce a larger number than a shorter sequence (at least for positive integers). Thus this code produces a longer sequence where possible. With the above example we get:
4! = 3! * 4
We can't reduce the 3! any further, since 3 is a prime. 4 on the other hand is simply 2²:
4 = 2² = 2! * 2!
Thus we have found the optimal replacement for 4 in the number-sequence as "322". This can be done for all numbers, but prime-numbers aren't factorisable and will thus always be the best replacement available for them self.
And thanks to the fact that we're using prime factorization we also know that we have the only (and longest possible) string of digits that can replace a certain digit.

Why is this loop outputting 0 every time to sqdNumber_result?

I am trying to find the sum of each digit in an integer squared, and for any integer that is input to sqdnumber, it outputs 0 to sqdNumber_result, and I can't figure out why.
Also, this is through edX, but I have been stuck for a week or so on this problem, and I have looked at a lot of different topics, but haven't found anything of use to me.
I used codeblocks to write this, but the system testing it uses codeboard
void squaredSum(int sqdnumber,int &sqdNumber_result) {
for (int i=1; i>1; i++){
if (sqdnumber >= ((10^(i-1))-1)){
int rem = (sqdnumber % (10^i));
int rem1 = (sqdnumber % (10^(i-1)));
int temp = (rem - rem1);
sqdNumber_result = sqdNumber_result + (temp^2);
}
else{
break;
}
}
}
I am new to coding, and just learning to do loops in C++.
This is the first iteration of the loop I have gotten their system to actually give me an output for it(I've written and rewritten it 20 or so times), but it isn't giving me an output that makes sense.
I wouldn't ask but I am at my wit's end.
In C++, ^ is the xor operator, not the nth power. for that, you should use pow.
The for statement does not loop. The condition is false the first iteration
There are two issues:
for (int i=1; i>1; i++){
This loop will not loop at all, since the condition i>1 is never met.
The second issue is the usage of ^ to do a power operation. The ^ in C++ is not a power operator, it is the exclusive-or operator.
So the answer at first glance would be to use the std::pow function to compute powers. However there can be drawbacks using it if the exponent is an integer. The reason is that pow is not guaranteed to work perfectly for integer powers.
See this as to dangers of using pow() for integral exponents
It is advised to just use a simple array of values with the powers of 10 and doing a lookup.
you said you were new to C++ so I tried to get a solution without using the for loop and tried to make it as simple as I could.
Let me know if this was any help.
//Code to calculate the sum of each digit squared//
#include<iostream>
using namespace std;
int main ()
{
int integer1,integer2,sum, square;
cout<<"Please enter two integers"<<endl;
cin>>integer1>>integer2 ;
cout<<"The sum of your integers is"<<" "<<endl;
sum = (integer1+integer2);
cout<<sum<<endl;
cout<<"The square of your sum is"<<" "<<endl;
square = (sum*sum);
cout<<square<<endl;
return 0;
}

Efficient Exponentiation For HUGE Numbers (I'm Talking Googols)

I am in the midst of solving a simple combination problem whose solution is 2^(n-1).
The only problem is 1 <= n <= 2^31 -1 (max value for signed 32 bit integer)
I tried using Java's BigInteger class but It times out for numbers 2^31/10^4 and greater, so that clearly doesn't work out.
Furthermore, I am limited to using only built-in classes for Java or C++.
Knowing I require speed, I chose to build a class in C++ which does arithmetic on strings.
Now, when I do multiplication, my program multiplies similarly to how we multiply on paper for efficiency (as opposed to repeatedly adding the strings).
But even with that in place, I can't multiply 2 by itself 2^31 - 1 times, it is just not efficient enough.
So I started reading texts on the problem and I came to the solution of...
2^n = 2^(n/2) * 2^(n/2) * 2^(n%2) (where / denotes integer division and % denotes modulus)
This means I can solve exponentiation in a logarithmic number of multiplications. But to me, I can't get around how to apply this method to my code? How do I choose a lower bound and what is the most efficient way to keep track of the various numbers that I need for my final multiplication?
If anyone has any knowledge on how to solve this problem, please elaborate (example code is appreciated).
UPDATE
Thanks to everyone for all your help! Clearly this problem is meant to be solved in a realistic way, but I did manage to outperform java.math.BigInteger with a power function that only performs ceil(log2(n)) iterations.
If anyone is interested in the code I've produced, here it is...
using namespace std;
bool m_greater_or_equal (string & a, string & b){ //is a greater than or equal to b?
if (a.length()!=b.length()){
return a.length()>b.length();
}
for (int i = 0;i<a.length();i++){
if (a[i]!=b[i]){
return a[i]>b[i];
}
}
return true;
}
string add (string& a, string& b){
if (!m_greater_or_equal(a,b)) return add(b,a);
string x = string(a.rbegin(),a.rend());
string y = string(b.rbegin(),b.rend());
string result = "";
for (int i = 0;i<x.length()-y.length()+1;i++){
y.push_back('0');
}
int carry = 0;
for (int i =0;i<x.length();i++){
char c = x[i]+y[i]+carry-'0'-'0';
carry = c/10;
c%=10;
result.push_back(c+'0');
}
if (carry==1) result.push_back('1');
return string(result.rbegin(),result.rend());
}
string multiply (string&a, string&b){
string row = b, tmp;
string result = "0";
for (int i = a.length()-1;i>=0;i--){
for (int j= 0;j<(a[i]-'0');j++){
tmp = add(result,row);
result = tmp;
}
row.push_back('0');
}
return result;
}
int counter = 0;
string m_pow (string&a, int exp){
counter++;
if(exp==1){
return a;
}
if (exp==0){
return "1";
}
string p = m_pow(a,exp/2);
string res;
if (exp%2==0){
res = "1"; //a^exp%2 is a^0 = 1
} else {
res = a; //a^exp%2 is a^1 = a
}
string x = multiply(p,p);
return multiply(x,res);
//return multiply(multiply(p,p),res); Doesn't work because multiply(p,p) is not const
}
int main(){
string x ="2";
cout<<m_pow(x,5000)<<endl<<endl;
cout<<counter<<endl;
return 0;
}
As mentioned by #Oli's answer, this is not a question of computing 2^n as that's trivially just a 1 followed by 0s in binary.
But since you want to print them out in decimal, this becomes a question of how to convert from binary to decimal for very large numbers.
My answer to that is that it's not realistic. (I hope this question just stems from curiosity.)
You mention trying to compute 2^(2^31 - 1) and printing that out in decimal. That number is 646,456,993 digits long.
Java BigInteger can't do it. It's meant for small numbers and uses O(n^2) algorithms.
As mentioned in the comments, there are no built-in BigNum libraries in C++.
Even Mathematica can't handle it: General::ovfl : Overflow occurred in computation.
Your best bet is to use the GMP library.
If you're just interested in seeing part of the answer:
2^(2^31 - 1) = 2^2147483647 =
880806525841981676603746574895920 ... 7925005662562914027527972323328
(total: 646,456,993 digits)
This was done using a close-sourced library and took roughly 37 seconds and 3.2 GB of memory on a Core i7 2600K # 4.4 GHz including the time needed to write all 646 million digits to a massive text file.
(It took notepad longer to open the file than needed to compute it.)
Now to answer your question of how to actually compute such a power in the general case, #dasblinkenlight has the answer to that which is a variant of Exponentiation by Squaring.
Converting from binary to decimal for large numbers is a much harder task. The standard algorithm here is Divide-and-Conquer conversion.
I do not recommend you try to implement the latter - as it's far beyond the scope of starting programmers. (and is also somewhat math-intensive)
You don't need to do any multiplication at all. 2^(n-1) is just 1 << (n-1), i.e. 1 followed by (n-1) zeros (in binary).
The easiest way to apply this method in your code is to apply it the most direct way - recursively. It works for any number a, not only for 2, so I wrote code that takes a as a parameter to make it more interesting:
MyBigInt pow(MyBigInt a, int p) {
if (!p) return MyBigInt.One;
MyBigInt halfPower = pow(a, p/2);
MyBigInt res = (p%2 == 0) ? MyBigInt.One : a;
return res * halfPower * halfPower;
}