R, 182 110 107 86 bytes
No longer the longest answer (thanks, Racket), and in fact shorter than the Python solution (a rare treat)! An anonymous function that takes two integers as input.
function(a,b)sum((s=function(x)abs(x)%%10^(99:1)%/%(e=10^(98:0))*e)(a)*s(b))*sign(a*b)
Here's how it works.
The zipper multiplication involves splitting the input numbers into their constituent digits.We take the absolute value of number and carry out modulo for descending powers of 10:
abs(x) %% 10^(99:1)
So here we're taking one number, x
, and applying modulo with 99 other numbers (10^99
through 10^1
). R implicitly repeats x
99 times, returning a vector (list) with 99 elements. (x %% 10^99
, x %% 10^98
, x %% 10^97
, etc.)
We use 10^99
through 10^1
. A more efficient implementation would use the value of number of digits in the longest number (check the edit history of this post; previous versions did this), but simply taking 99..1
uses fewer bytes.
For x = 1276
this gives us
1276 1276 1276 ... 1276 276 76 6
Next, we use integer division by descending powers of 10 to round out the numbers:
abs(x) %% 10^(99:1) %/% 10^(98:0)
This yields
0 0 0 ... 1 2 7 6
which is exactly the representation we want. In the code, we end up wanting to use 10^(98:0)
again later, so we assign it to a variable:
abs(x) %% 10^(99:1) %/% (e = 10^(98:0))
(Wrapping an expression in parentheses in R generally evaluates the expression (in this case, assigning the value of 10^(98:0)
to e
), and then also returns the output of the expression, allowing us to embed variable assignments within other calculations.)
Next, we perform pairwise multiplication of the digits in the input. The output is then padded to two digits and concatenated. The padding to two digits and concatenating is equivalent to multiplying each number by 10^n
, where n
is the distance from the right edge, and then summing all the numbers.
A = 0 0 1 2 7 6
B = 9 9 3 0 2 4
-> 0 0 3 0 14 24
-> 00 00 03 00 14 24
-> 0*10^6 + 0*10^5 + 3*10^4 + 0*10^3 + 14*10^2 + 24*10^1
= 000003001424
Notably, because multiplication is commutative, we can perform the multiplication by 10^n
before we multiply A by B. So, we take our earlier calculation and multiply by 10^(98:0)
:
abs(x) %% 10^(99:1) %/% 10^(98:0) * 10^(98:0)
which is equivalent to
abs(x) %% 10^(99:1) %/% (e = 10^(98:0)) * e
After applying this to A, we would then want to repeat this whole operation on B. But that takes precious bytes, so we define a function so we only have to write it once:
s = function(x) abs(x) %% 10^(99:1) %/% (e=10^(98:0)) * e
We do our embedding-in-parentheses trick to allow us to define and apply a function at the same time, to call this function on A and B and multiply them together. (We could have defined it on a separate line, but because we're eventually going to put all of this into an anonymous function, if we have more than one line of code then everything needs to be wrapped in curly braces, which costs valuable bytes.)
(s = function(x) abs(x) %% 10^(99:1) %/% (e=10^(98:0)) * e)(a) * s(b)
And we take the sum of all of this, and we're nearly finished:
sum((s = function(x) abs(x) %% 10^(99:1) %/% (e=10^(98:0)) * e)(a) * s(b))
The only thing to consider now is the sign of the input. We want to follow regular multiplication rules, so if one and only one of A and B is negative, the output is negative. We use the function sign
which returns 1
when given a positive number and -1
when given a negative number, to output a coefficient that we multiply our entire calculation by:
sum((s = function(x) abs(x) %% 10^(99:1) %/% (e=10^(98:0)) * e)(a) * s(b)) * sign(a * b)
Finally, the whole thing is wrapped into an anonymous function that takes a
and b
as input:
function(a, b) sum((s = function(x) abs(x) %% 10^(99:1) %/% (e=10^(98:0)) * e)(a) * s(b)) * sign(a * b)
Remove the whitespace and it's 86 bytes.