Skip to content

Instantly share code, notes, and snippets.

@Beraliv
Last active January 17, 2018 21:36
Show Gist options
  • Save Beraliv/a5f2889d08bb4fb675ffc268dfd952a2 to your computer and use it in GitHub Desktop.
Save Beraliv/a5f2889d08bb4fb675ffc268dfd952a2 to your computer and use it in GitHub Desktop.
Task 62. UniLecs. Functional-like. Added BigInteger.
const BigInteger = value => {
const normalise = n => {
if ((n | 0) === 0) {
return '0';
}
n = n.toString().split('');
while (+n[0] === 0) {
n.splice(0, 1);
}
return n.join('');
};
return {
value: normalise(value),
sub(bi) {
// substract result can be positive only
let a = this.value, b = bi.value;
if ((a | 0) === 0 || (b | 0) === 0) {
return BigInteger(0);
}
if (this.eq(bi)) {
return BigInteger(0);
}
a = a.split('').reverse();
b = b.split('').reverse();
let result = Array(Math.max(a.length, b.length)).fill(0);
for (let i = 0; +a[i] >= 0 || +b[i] >= 0; i++) {
let diff = (+a[i] || 0) - (+b[i] || 0);
if (diff + result[i] >= 0) {
result[i] += diff;
}
else {
result[i] += diff + 10;
// no check as a >= b
result[i + 1] = -1;
}
}
return BigInteger(result.reverse().join(''));
},
mul(bi) {
// solution is extracted from https://goo.gl/obVaWP
let a = this.value, b = bi.value;
if ((a | 0) === 0 || (b | 0) === 0) {
return BigInteger(0);
}
a = a.split('').reverse();
b = b.split('').reverse();
let result = [];
for (let i = 0; a[i] >= 0; i++) {
for (let j = 0; b[j] >= 0; j++) {
if (!result[i + j]) {
result[i + j] = 0;
}
result[i + j] += a[i] * b[j];
}
}
for (let i = 0; result[i] >= 0; i++) {
if (result[i] >= 10) {
if (!result[i + 1]) {
result[i + 1] = 0;
}
result[i + 1] += parseInt(result[i] / 10);
result[i] %= 10;
}
}
return BigInteger(result.reverse().join(''));
},
div(bi) {
if (bi.gt(this)) {
return BigInteger(0);
}
if (bi.eq(this)) {
return BigInteger(1);
}
let a = this.value, b = bi.value;
let length = b.length;
let results = [];
let chunk = a.slice(0, length);
let endIndex = length;
while (true) {
if (endIndex > a.length) {
break;
}
if (BigInteger(b).gt(BigInteger(chunk)) && endIndex < a.length) {
// console.log(`chunk.length <= b.length && chunk < b: ${chunk.length} <= ${b.length} && ${chunk} < ${b}`)
chunk = chunk + a[endIndex];
// console.log(`a[endIndex]: a[${endIndex}] = ${a[endIndex]}`);
endIndex++;
results.push(0);
}
// TODO: to optimise with binary search
let i = 1;
for (; i < 10; i++) {
if (BigInteger(b).mul(BigInteger(i)).gt(BigInteger(chunk))) {
// console.log(`chunk / b = i - 1: ${chunk} / ${b} = ${i - 1}`)
break;
}
}
results.push(i - 1);
chunk = BigInteger(chunk).sub(BigInteger(b).mul(BigInteger(i - 1))).value;
// console.log(chunk);
if (endIndex < a.length) {
chunk = chunk + a[endIndex];
}
endIndex++;
}
let result = results.join('');
return BigInteger(result);
},
mod(bi) {
return BigInteger(this.sub(this.div(bi).mul(bi)));
},
gt(bi) {
// compare only positive numbers
let a = this.value, b = bi.value;
a = a.split('');
b = b.split('');
return a.length > b.length
|| (a.length === b.length && a > b);
},
eq(bi) { return this.value === bi.value; },
toString() { return this.value; },
};
};
const BIG_ZERO = BigInteger(0);
const BIG_ONE = BigInteger(1);
// check if n is valid for certain m
const check = (n, m) => Array(m - 3).fill(0)
// iterate from m-1 to 2
.map((_, i) => BigInteger(m - i - 1))
// checks if for all i, n % i === i - 1
.filter(i => !n.mod(i).eq(i.sub(BIG_ONE)))
.length === 0;
const count = (() => {
// greatest common divisor
const gcd = (m, n) => m.gt(n)
? gcd(n, m)
: m.gt(BIG_ZERO)
? gcd(m, n.mod(m))
: n;
// least common multiplier
// = m / gcd(m, n) * n
const lcm = (m, n) => m
.div(gcd(m, n))
.mul(n);
// upper bound for the value
// p is from 1 to 1000
const upper = p => Array(p).fill(0)
// iterates from 1 to p
.map((_, i) => BigInteger(i + 1))
.reduce(lcm, BigInteger(1));
// m is from 1 to 1000
return (m) => {
if (m <= 0) {
throw new Error('The number should be positive (greater than zero)');
}
return m < 3
? '1'
: upper(m).sub(BIG_ONE).value;
};
})();
for (let i = 1; i < 100; i++) {
console.log(i, count(i));
}
@Beraliv
Copy link
Author

Beraliv commented Jan 17, 2018

For now the maximum calculated number is 52.
The maximum correct value is 40.
The expected value is 219060189739591159, but had 219060189739591199.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment