Introduction
Code calculator computing expressions with very long numbers. Your task is to write the core part of this calculator. Given two numbers and the requested operation, you are to compute the result and print it in the form specified below. With addition and subtraction, the numbers are written below each other. Multiplication is a little bit more complex: first of all, we make a partial result for every digit of one of the numbers, and then sum the results together.
Input:
4
12345+67890
324-111
325*4405
1234*4
Output:
12345
+67890
------
80235
324
-111
----
213
325
*4405
-----
1625
0
1300
1300
-------
1431625
1234
*4
----
4936
Code
The approach followed is to perform addition, subtraction using the string one digit at a time, from right to left and keeping track of carry and borrow. In terms of multiplication, it's involved by multiplying each digit and shifting one right and continue addition. The below logic is self explanatory and defines the printing logic by finding the max length of any line.
using System;
using System.Linq;
using System.Text;
namespace Competitive
{
internal class Program
{
public static void Main()
{
var t = int.Parse(Console.ReadLine() ?? "0");
while (t-- > 0)
{
Console.WriteLine(Calculate(Console.ReadLine()));
}
}
private static string Calculate(string input)
{
Console.WriteLine();
var op = FindOperation(input);
switch (op)
{
case '+':
var numberArr = input.Split('+');
return PerformAdd(numberArr[0], numberArr[1]);
case '-':
numberArr = input.Split('-');
return PerformSub(numberArr[0], numberArr[1]);
case '*':
numberArr = input.Split('*');
return PerformMul(numberArr[0], numberArr[1]);
default:
throw new Exception($"No operator found in {input}");
}
}
private static string PerformMul(string a, string b)
{
var sb = new StringBuilder();
var n = a.Length;
var m = b.Length;
var mulDigit = new string[m];
var mnMax = Math.Max(n, m + 1);
var zero = "";
var finalMul = "";
for (var j = m - 1; j > -1; j--)
{
mulDigit[j] = MulOp(a, b[j].ToString(), n);
finalMul = string.IsNullOrEmpty(finalMul)
? mulDigit[j]
: PerformAdd(mulDigit[j] + zero, finalMul, true);
zero += "0";
}
var k = finalMul.Length;
var maxLength = Math.Max(mnMax, k);
sb.AppendLine(new string(' ', maxLength - n) + a);
sb.AppendLine(new string(' ', maxLength - m - 1) + "*" + b);
sb.AppendLine(new string(' ', maxLength - mnMax) + new string('-', mnMax));
for (var j = m - 1; j > -1; j--)
{
var digitMul = (string.IsNullOrEmpty(mulDigit[j]) ? "0" : mulDigit[j]);
var endSpaceCount = m - 1 - j;
sb.AppendLine(
new string(' ', maxLength - digitMul.Length - endSpaceCount) +
digitMul +
new string(' ', endSpaceCount));
}
if (mulDigit.Length > 1)
{
sb.AppendLine(new string('-', maxLength));
sb.AppendLine(new string(' ', maxLength - k) + finalMul);
}
return sb.ToString();
}
private static string MulOp(string a, string b, int n)
{
var carry = 0;
var c = "";
var bVal = int.Parse(b);
for (int i = n - 1; i > -1; i--)
{
var aVal = int.Parse(a[i].ToString()) * bVal + carry;
carry = aVal / 10;
aVal %= 10;
c += aVal;
}
if (carry > 0)
{
c += carry;
}
return new string(c.TrimEnd('0').Reverse().ToArray());
}
private static string PerformSub(string a, string b)
{
var sb = new StringBuilder();
var n = a.Length;
var m = b.Length;
var diff = n >= m ? SubOp(a, b, m, n) : "-" + SubOp(b, a, n, m);
var k = diff.Length;
var maxLength = Math.Max(Math.Max(n, m + 1), k);
sb.AppendLine(new string(' ', maxLength - n) + a);
sb.AppendLine(new string(' ', maxLength - m - 1) + "-" + b);
sb.AppendLine(new string('-', maxLength));
sb.AppendLine(new string(' ', maxLength - k) + diff);
return sb.ToString();
}
private static string SubOp(string a, string b, int m, int n)
{
var c = string.Empty;
var borrow = 0;
var j = m - 1;
for (var i = n - 1; i > -1; i--)
{
var val = int.Parse(a[i].ToString()) - borrow;
if (j > -1)
{
var bVal = int.Parse(b[j].ToString());
if (bVal > val)
{
borrow = 1;
val = val + 10 - bVal;
}
else
{
val -= bVal;
borrow = 0;
}
j--;
}
else
{
borrow = 0;
}
c += val;
}
c = c.TrimEnd('0');
return new string(c.Reverse().ToArray());
}
private static string PerformAdd(string a, string b, bool resultOnly = false)
{
var sb = new StringBuilder();
var n = a.Length;
var m = b.Length;
var sum = n >= m ? AddOp(a, b, m, n) : AddOp(b, a, n, m);
var k = sum.Length;
var maxLength = Math.Max(Math.Max(n, m + 1), k);
sb.AppendLine(new string(' ', maxLength - n) + a);
sb.AppendLine(new string(' ', maxLength - m - 1) + "+" + b);
sb.AppendLine(new string('-', maxLength));
sb.AppendLine(new string(' ', maxLength - k) + sum);
return resultOnly ? sum : sb.ToString();
}
private static string AddOp(string a, string b, int m, int n)
{
var c = string.Empty;
var carry = 0;
var j = m - 1;
for (var i = n - 1; i > -1; i--)
{
var val = int.Parse(a[i].ToString()) + carry;
if (j > -1)
{
val += int.Parse(b[j].ToString());
j--;
}
carry = val / 10;
val %= 10;
c += val;
}
if (carry > 0)
{
c += carry;
}
return new string(c.Reverse().ToArray());
}
private static char FindOperation(string input)
{
foreach (var letter in input.Where(letter => !char.IsDigit(letter)))
{
return letter;
}
throw new Exception($"No operator found in {input}");
}
}
}