Outline of problem:
Please note I will abuse the life out of ^ and use it as a power symbol, despite the caret symbol being the bitwise
lets keep in mind that (a^b)%c = (a%c)^b % c.
I want to know lastDigit.
lastDigit = x^y^z % 10 = (x%10 ^ y ^ z) % 10.
p[x % 10] has the pattern of repetition of powers of x. A pattern can have a length of 1, 2 or 4.
If the pattern had a length of 4, then lastDigit = p[x][(y^z % 4)] = p[x][(y%4)^z %4]
If our problem was not for x,y,z but for x0,x1,x2...xn:
lastDigit
= p[x0][(x1 ^ x2 ... ^ xn-1 ^ xn) %4]
= p[x0][((x1 ^ x2 ... ^ xn-1)%4 ^ xn) %4]
And I think teh recursive nature is apparent now:
I will use the number 4 for remainder because it is the smallest number that can divide 1, 2 and 4, for which patterns are also relatively easy to find.
const p = [
[ 0 ], // 0^1=0, 0^2=0 ...
[ 1 ], // 1^1=1, 1^2=1 ...
[ 2,4,8,6 ], // 2^1=2, 2^2=4 ...
[ 3,9,7,1 ], // 3^1=3, 3^2=9 ...
[ 4,6 ],
[ 5 ],
[ 6 ],
[ 7,9,3,1 ],
[ 8,4,2,6 ],
[ 9,1 ]
];
//returns x^y % 4
function powMod4(x, y) {
switch (x % 4) {
case 0:
return 0;
case 1:
return 1;
case 2:
return y == 1 ? 2 : 0;
case 3:
return (y % 2) == 0 ? 1 : 3;
}
}
function foo(arr) {
arr = arr.map((it, i, list) => {
if (i + 1 < list.length && list[i + 1] === 0) {
return 1;
} else {
return it;
}
}).filter(x => x !== 0);
let firstElem = arr[0] % 10;
let l = p[firstElem].length
let resp = arr.slice(1).reduce((acc, v) => {
if (acc === undefined) {
return v
}
let rem = powMod4(acc, v);
//console.log(v, acc, " => ", rem);
return rem;
}, undefined);
return p[firstElem][(resp + l - 1) % l];
}
function test(arr, expected) {
let resp = foo(arr);
console.log(arr.join("^"), resp, resp == expected ? "ok" : "FAIL")
}
test([3, 4, 5], 1)
test([2, 2, 2, 2], 6)
test([4, 13, 16], 4)
test([3,5,7,10], 3)
test([41,42,43], 1)
test([7,6,21], 1)
test([2,2,2,0], 4)
So all I did is, I dropped the LD function. Instead, I am trying to find x1^x2...^xn % p[x0].length. In contrast, you were trying to find x1^x2...^xn % 10