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

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.

Related

I'm trying to encrypt a message for my homework assignment

The gist of it is that every letter from a-z needs to be encrypted into a number.
For example a will turn to "1", b into "2" all the way to z="26". Then I have to guess the number of possible outcomes for every encryption. For example 25114 can be 6 different thing. It can be BEAN,BEAAD,YAAD,YAN,YKD,BEKD.
My question is "How do I do this" ?
I've tried using if but it keeps printing "1" as an output every time.
#include <iostream>
using namespace std;
int main()
{
int a1,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;
cout<<"vnesi kod"<<endl;
cin>>a1;
if (a)
{
cout<<"1"<<endl;
}
else if (b)
{
cout<<"2"endl;
}
return 0;
}
Since this is a homework problem, I just give you some pseudo-code on how to solve this. You will still have to implement it yourself.
Let us assume you get a number as input existing out of n digits: a1a2a3 ... an
Since the alphabet contains 26 letters, we want to split this number into groups of 1 or 2 digits and if we have a group of two digits, you have to check if the number is smaller than 27. The quickest way to do this is to make use of a recursive function. It is not the cleanest, but the quickest. Let us assume the recursive function is called decode.
It is very easy to understand why a recursive function is needed. If we want to decode the number 25114. There are two paths we need to take, groups of 1 and groups of 2:
group of 1: translate the last digit 4 into "D", and decode the remaining number 2511
group of 2: check if the last two digits are smaller than 27, translate the last two digits 14 into N and decode the remaining number 251
In pseudo-code this looks like this:
# function decode
# input: the number n to decode
# a postfix string p representing the decoded part
function decode(n, p) {
# end condition: If the number is ZERO, I have decoded the full number
# only print and return
if (n == 0) { print p; return }
# group of 1: use integer division to extract the
# last digit as n%10 and
# remainder to decode is n/10
decode(n/10, concat(translate(n%10),p) )
# group of 2: use integer division to extract the
# last two digits as n%100 and
# remainder to decode is n/100
# This does not need to run if n < 10 or if n%100 > 26
if (n > 9 && n%100 <= 26) { decode(n/100, concat(translate(n%100),p) ) }
}
The function concat concatenates two strings: concat("AA","BB") returns "AABB"
The function translate(n) converts a number n into its corresponding alphabetic character. This can be written as sprintf("%c",64+n)
As is mentioned in the comments, this is not a very efficient method. This is because we do the same work over and over. If the input reads 25114, we will do the following steps in order:
step 1: translate(4), decode _2511_
step 1.1: translate(1), decode _251_
step 1.1.1: ...
step 1.2: translate(11), decode _25_
step 1.2.1: ...
step 2: translate(14), decode _251_
as you see, we have to decode 251 twice (in step 1.1 and step 2). This is very inefficient as we do everything more than ones.
To improve this, you can keep track of what you have done so far in a lookup table
Check out the ASCII table http://www.asciitable.com/ . I have had something like this similar for my homework as well. since 'a' = 97 and 'z' = 122, you could subtract the desired character from 96 to get the preferred value from the casted character.
For example:
int letterNum {(int)'a' - 97 + 1}; // 1
int letterNum {(int)'z' - 97 + 1}; // 26

Cross sum calculation, Can anyone explain the code please?

i'm going to learn C++ at the very beginning and struggling with some challenges from university.
The task was to calculate the cross sum and to use modulo and divided operators only.
I have the solution below, but do not understand the mechanism..
Maybe anyone could provide some advice, or help to understand, whats going on.
I tried to figure out how the modulo operator works, and go through the code step by step, but still dont understand why theres need of the while statement.
#include <iostream>
using namespace std;
int main()
{
int input;
int crossSum = 0;
cout << "Number please: " << endl;
cin >> input;
while (input != 0)
{
crossSum = crossSum + input % 10;
input = input / 10;
}
cout << crossSum << endl;
system ("pause");
return 0;
}
Lets say my input number is 27. cross sum is 9
frist step: crossSum = crossSum + (input'27' % 10 ) // 0 + (modulo10 of 27 = 7) = 7
next step: input = input '27' / 10 // (27 / 10) = 2.7; Integer=2 ?
how to bring them together, and what does the while loop do? Thanks for help.
Just in case you're not sure:
The modulo operator, or %, divides the number to its left by the number to its right (its operands), and gives the remainder. As an example, 49 % 5 = 4.
Anyway,
The while loop takes a conditional statement, and will do the code in the following brackets over and over until that statement becomes false. In your code, while the input is not equal to zero, do some stuff.
To bring all of this together, every loop, you modulo your input by 10 - this will always return the last digit of a given Base-10 number. You add this onto a running sum (crossSum), and then divide the number by 10, basically moving the digits over by one space. The while loop makes sure that you do this until the number is done - for example, if the input is 104323959134, it has to loop 12 times until it's got all of the digits.
It seems that you are adding the digits present in the input number. Let's go through it with the help of an example, let input = 154.
Iteration1
crossSum= 0 + 154%10 = 4
Input = 154/10= 15
Iteration2
crossSum = 4 + 15%10 = 9
Input = 15/10 = 1
Iteration3
crossSum = 9 + 1%10 = 10
Input = 1/10 = 0
Now the while loop will not be executed since input = 0. Keep a habit of dry running through your code.
#include <iostream>
using namespace std;
int main()
{
int input;
int crossSum = 0;
cout << "Number please: " << endl;
cin >> input;
while (input != 0) // while your input is not 0
{
// means that when you have 123 and want to have the crosssum
// you first add 3 then 2 then 1
// mod 10 just gives you the most right digit
// example: 123 % 10 => 3
// 541 % 10 => 1 etc.
// crosssum means: crosssum(123) = 1 + 2 + 3
// so you need a mechanism to extract each digit
crossSum = crossSum + input % 10; // you add the LAST digit to your crosssum
// to make the number smaller (or move all digits one to the right)
// you divide it by 10 at some point the number will be 0 and the iteration
// will stop then.
input = input / 10;
}
cout << crossSum << endl;
system ("pause");
return 0;
}
but still dont understand why theres need of the while statement
Actually, there isn't need (in literal sense) for, number of digits being representable is limited.
Lets consider signed char instead of int: maximum number gets 127 then (8-bit char provided). So you could do:
crossSum = number % 10 + number / 10 % 10 + number / 100;
Same for int, but as that number is larger, you'd need 10 summands (32-bit int provided)... And: You'd always calculate the 10 summands, even for number 1, where actually all nine upper summands are equal to 0 anyway.
The while loop simplifies the matter: As long as there are yet digits left, the number is unequal to 0, so you continue, and as soon as no digits are left (number == 0), you stop iteration:
123 -> 12 -> 1 -> 0 // iteration stops, even if data type is able
^ ^ ^ // to store more digits
Marked digits form the summands for the cross sum.
Be aware that integer division always drops the decimal places, wheras modulo operation delivers the remainder, just as in your very first math lessons in school:
7 / 3 = 2, remainder 1
So % 10 will give you exactly the last (base 10) digit (the least significant one), and / 10 will drop this digit afterwards, to go on with next digit in next iteration.
You even could calculate the cross sum according to different bases (e. g. 16; base 2 would give you the number of 1-bits in binary representation).
Loop is used when we want to repeat some statements until a condition is true.
In your program, the following statements are repeated till the input becomes 0.
Retrieve the last digit of the input. (int digit = input % 10;)
Add the above retrieved digit to crosssum. (crosssum = crosssum + digit;)
Remove the last digit from the input. (input = input / 10;)
The above statements are repeated till the input becomes zero by repeatedly dividing it by 10. And all the digits in input are added to crosssum.
Hence, the variable crosssum is the sum of the digits of the variable input.

How to start on this C interview code test?

I got a really interesting question at a company, and I can't seem to find an answer at all.
#include <cstdio>
int main()
{
int num = 123456789;
int res = 0;
for (int i = 0; i<111111111; i++)
{
res=(res+num)%1000000000;
}
printf("06 %09d", res);
return 0;
}
I should declare num so the output is my mobile number, 305089171.
Any idea how to do that?
So to solve the problem we begin with units digit.
We need 1 at units digit so make num = 1.
Now we have res as 111111111.
Now we need 7 at tens digits. So we make num = (7 - 1(tens digit in step 2)) 1 = 61. (Also note that multiplying digit at tens place will only affect digts to left of it).
Now we have res as 777777771.
Now we need 1 at hundreds place. So if we make num = 461 (since 7+4 = 1)
and so on.
The mathematical reasoning I could think of is when you multiply a number by 111111111, digits at say tens place will only affect digits to left of it and not the digits to right of it.
Here is the value you need to put in num:
254197461
I got it by adding additional numbers one by one to num, i let you check what happens yourself.
I have no mathemacital explaination to that, but try putting numbers one by one into num and you may understand:.
1 / 61 / 461 / 7461...

luhn algorithm and 'digit manipulation' in 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.

Verifying 116725 = 116 * 725 or not? C/C++ [closed]

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 10 years ago.
Question: input an int number ex: ABCD, verify that is ABCD = AB*CD or not
(note that we don't how many digits this number got, just know it is an positive integer
and yes, it the number of digits is odd we can conclude result is No, immediately by... eye lol)
for example:
Enter a number: 88
Output: No
Enter a number: 12600
Output: No
Enter a number: 116725
Output: Yes, 116 * 725 = 116725 (**this is just example,
not actual result, just help to understand how output look like**)
Problem is that, you can't use array, jump and bitwise in order to solve this. Yes, if we can use array then not much to say, put input number in an array, check first half multiply other half....bla..bla... I need help with IDEA without using array to solve this problem, right now I'm stuck! Thank you guy very much!
Your program can safely output No for every input. Proof:
You are looking for integers A and B such that A*B = A*10^k + B, with A and B > 0 and B < 10^k.
If A*B = A*10^k + B, then B = 10^k + B/A > 10^k. But B had to be less than 10^k, so this is a contradiction. Therefore no such A and B exist.
A longer proof:
You are looking for integers A and B such that A*B = A*10^k + B, with A and B > 0 and B < 10^k.
Subtract B from both sides to get (A-1)*B = A*10^k.
Since A is a factor in the right hand side it is also a factor in the left hand side. But A and A-1 are coprime, so A must divide B. So, B = n*A for some integer n.
Now we have A*B = A*10^k + n*A, or A*B = (10^k + n)*A. Since A > 0 we can divide both sides by A to get B = 10^k+n. But this is impossible since B was supposed to be less than 10^k!
A little hint to your 6 digits number:
to get last 3 digits use % 1000
to get first 3 digits use (int) X/1000.
Notice that 1000 == 10^3.
Write a program that asks for the input and then prints "No".
Done.
It's not too clear what you're trying to do. ABCD == AB*CD suggests
four digit numbers. For a four digit number x, a test for the above
would be x == (x / 100) * (x % 100). For a six digit number, replace
100 with 1000, and more generally, for an n digit number, where
n is even, use 10^(n/2). If n is odd, however, I'm not sure what you're looking for, and the last example you give doesn't meet the criteria you mention; if you can permutate the digits in each half, the problem then becomes more complex.
You can read a string, split it in the middle and convert the both parts to an int.
You could also read an int, calculate the number of digits (writing your own loop or using the log function) and split the int after the calculated number of digits.
You can also write a loop that is taking an int ABCD, splitting it into ABC and D and moving the digits from ABC to D while the both have not the same number of digits (you do not need to calculate the number of digits here, there is a quite easy comparison you can do).
To get the number of digits, count how many times you had to divide the number by 10 until it gets smaller than 1.
For 116725, you would need to divide by 10 six times. After that you can print no if the number is odd or calculate the result like James Kanze and ProblemFactory described.
Here's a complete "C/C++" solution:
#include <stdio.h>
int main(void) {
while (fgetc(stdin) != '\n');
return puts("No.");
}