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
Examples

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}");
        }
    }
}
Program to pretty print the arithmentic operations