## UVA Problem 10106 – Product Solution (Lattice Multiplication)

UVA Problem 10106 – Product Solution:

Solving Technique:

This problem is quite simple. Given two very large integers multiply them and print them. By large I mean almost 251 characters long for this problem. So string or character array must be used.

This problem can solved in many ways Big Integer, FFT, Grade School etc. But I have implemented lattice multiplication / Chinese multiplication to solve this problem.

Code Explanation:

The code below requires quite a bit of polish to understand easily ( A lot other post require the same. Maybe I will update this post sometimes in future or not. ).

This code is not quite space efficient. I have used several arrays to make it easy to understand but all of the tasks below can be done using the large array. Also the running time can further be improved to $O(m*n)$ instead of $O(n^2)$. Where, m and n are length of two arrays and they may not be equal in size.

I have provided some graphical representations below to make it easier to understand.

This is an example of how the multiplication works in this code. As mentioned above the process can be sped up using rectangular matrix instead of square if the length is not equal.

This is a representation of how the table / square matrix is filled for further processing.

Multiplication starts with the last character of string 1 and proceeds to first character. For string 2 multiplication starts from the first character till last character. This way each character from string 1 and string 2 is first converted to a digit, then they are multiplied. If the result is two digits it is divided by 10.

The remainder is written as the lower left portion ( indicated by lower in the structure ) and the quotient is written as the upper left portion ( indicated by upper in the structure ).

This is graphical representation of how the structure is traversed. If you have trouble understanding how the recursive function traversing the structure, then take a look at UVA problem 264 – Count the Cantor Solution. The traversal is somewhat similar to that and I have provided explanation int that post.

Rest is explained in the code comments.

Important:  Be sure to add or print a new line after each output unless otherwise specified. The outputs should match exactly because sometimes even a space character causes the answer to be marked as wrong answer. Please compile with c++ compiler as some of my codes are in c and some in c++.

More Inputs of This Problem on uDebug.

Input:

12
12
2
222222222222222222222222

Output:

144
444444444444444444444444

### Code:

/**
* Author:    Asif Ahmed
* Site:      https://quickgrid.wordpress.com
* Problem:   Lattice Multiplication.
* Technique: High precision large number multiplication.
*            Structure array representing upper left and
*            and lower right corner in single cell.
*/

#include<stdio.h>
#include<string.h>

#define M 260

int N;

// Assuming both strings are of same length.
struct multiplicationTable{
int upper;
int lower;
};
struct multiplicationTable node[M][M];

static char string1[M];
static char string2[M];

// stores the diagonal sums;
int sum;

// decides whether to get the upper or lower
// value based on even or odd.
int m;

int recursiveAdder( int i, int j ){

// Termination condition.
if( j < 0 || i >= N )
return sum;

int val;

// Whether to get the upper left corner or
// the lower right corner.
if( m % 2 ){
val = node[i][j].upper;
j = j - 1;
}
else{
val = node[i][j].lower;
i = i + 1;
}
++m;

// store the sum of the whole diagonal.
sum = sum + val;

// recursively visit all row ans column
// diagonally ( at least on pen and paper format ).
// actually moves more like the snake in the snakes game.

return sum;
}

// Debug.
// Print the matrix showing the multiplications.
// Please note left and right directions may be different.
void printMultiplicationMatrix(){

printf("\n\n");
for( int i = 0; i < N; ++i ){
for( int j = N - 1; j >= 0; --j )
printf("%d,%d, ", node[i][j].upper, node[i][j].lower );
printf("\n");
}

}

int main(){

//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);

while( gets(string1) ){
gets(string2);

int len1 = strlen(string1);
int len2 = strlen(string2);

// Fix length if both string are not equal size.
if( len1 > len2 ){
N = len1;

int shiftWidth = len1 - len2;

for( int i = len1 - 1; i >= 0; --i )
string2[i + shiftWidth] = string2[i];

for(int j = 0; j < shiftWidth; ++j)
string2[j] = '0';

}
else if(len2 > len1){
N = len2;

int shiftWidth = len2 - len1;

for( int i = len2 - 1; i >= 0; --i )
string1[i + shiftWidth] = string1[i];

for(int j = 0; j < shiftWidth; ++j)
string1[j] = '0';

}
else N = len1;

//printf("%s \n%s \n", string1, string2);

int k = N - 1;

// Multiply the numbers digit by digit and set in the lattice.
for( int i = 0; string2[i]; ++i ){
for( int j = 0; string2[j]; ++j ){

int num1 = string1[k] - '0';
int num2 = string2[j] - '0';

int multiply = num1 * num2;

node[j][k].upper = multiply / 10;
node[j][k].lower = multiply % 10;

}
--k;
}

//printMultiplicationMatrix();

// Lattice is divided into two parts upper left half and
// lower right half.

// result of upper half
int upperHalfResult[N];

int i = N - 1;
for(; i >= 0; --i){
sum = 0;
m = 1;
}

// result of upper half
int lowerHalfResult[N];

i = 0;
for(; i < N; ++i){
sum = 0;
m = 0;
lowerHalfResult[i] = recursiveAdder(i, N - 1);
}

// Combine upper and lower left half to a single array to fix addition
// problems.
int combinedRawResult[N + N];
i = 0;
for(; i < N; ++i )
combinedRawResult[i] = upperHalfResult[i];
for(k = 0; i < N + N; ++i, ++k )
combinedRawResult[i] = lowerHalfResult[k];

// If a cell has more than 9 then it should be added to the next cell.
for( int i = N + N - 1; i >= 0; --i ){

if( combinedRawResult[i] > 9 ){
combinedRawResult[i - 1] = combinedRawResult[i - 1] + combinedRawResult[i] / 10;
combinedRawResult[i] = combinedRawResult[i] % 10;
}

}

for(i = 0; i < N + N; ++i)
if(combinedRawResult[i]) break;

// print if the result can be printed or its zero.
bool zero = true;
for(; i < N + N; ++i){
printf("%d", combinedRawResult[i]);
zero = false;
}

// If the result is zero.
if( zero )
printf("0");

printf("\n");

}

return 0;
}