Published
Edited
Dec 22, 2021
Insert cell
Insert cell
Insert cell
min = 193651
Insert cell
max = 649729
Insert cell
Insert cell
fits = (part2 = false) => num => {
let digit = 0;
let rightDigit = 11;
let digitRun = 0;
let runOfTwo = false;
let consecutiveDigits = false;

while (true) {
digit = num % 10;
num = Math.floor(num / 10);
if (digit > rightDigit) {
return false;
}
if (digit === rightDigit) {
digitRun++;
consecutiveDigits = true;
} else {
if (digitRun === 2) {
runOfTwo = true;
}
digitRun = 1;
}
rightDigit = digit;
if (num === 0) {
break;
}
}
if (digitRun === 2) {
runOfTwo = true;
}
return part2 ? runOfTwo : consecutiveDigits;
}
Insert cell
fits(true)(123446)
Insert cell
fits(true)(123456)
Insert cell
Insert cell
numCandidates = range(min, max + 1).filter(fits(false)).length
Insert cell
numPart2Candidates = range(min, max + 1).filter(fits(1)).length
Insert cell
Insert cell
binaryen = require("binaryen@100")
Insert cell
buildModule = () => {
const module = new binaryen.Module();
//module.autoDrop(); // automatically pops values off the stack if they aren't last in a block

module.addFunction(
"fits",
binaryen.i32,
binaryen.i32,
// 1 digit 2 prevDigit 3 digitRun 4 runOfTwo
[binaryen.i32, binaryen.i32, binaryen.i32, binaryen.i32],

module.block(null, [
// prevDigit = 11
module.local.set(2, module.i32.const(11)),

module.block('afterLoop', [
module.loop(
'loop',
module.block(null, [
// digit = num % 10;
module.local.set(
1,
module.i32.rem_s(
module.local.get(0, binaryen.i32),
module.i32.const(10)
)
),
// if num == 0: return runOfTwo
module.if(
module.i32.eqz(module.local.get(0, binaryen.i32)),
module.break('afterLoop')
),

// num = num / 10;
module.local.set(
0,
module.i32.div_s(
module.local.get(0, binaryen.i32),
module.i32.const(10)
)
),

// if digit > prevDigit: return False
module.if(
module.i32.gt_s(
module.local.get(1, binaryen.i32),
module.local.get(2, binaryen.i32)
),
module.return(module.i32.const(0))
),

// if digit == prevDigit:
// digitRun++;
// else:
// if digitRun == 2:
// runOfTwo = 1
// digitRun = 1
module.if(
module.i32.eq(
module.local.get(1, binaryen.i32),
module.local.get(2, binaryen.i32)
),
module.local.set(
3,
module.i32.add(
module.local.get(3, binaryen.i32),
module.i32.const(1)
)
),
module.block(null, [
module.if(
module.i32.eq(
module.local.get(3, binaryen.i32),
module.i32.const(2)
),
module.local.set(4, module.i32.const(1))
),
module.local.set(3, module.i32.const(1))
])
),

// prevDigit = digit
module.local.set(2, module.local.get(1, binaryen.i32)),

module.break('loop')
])
)
]),
module.if(
module.i32.eq(module.local.get(3, binaryen.i32), module.i32.const(2)),
module.return(module.i32.const(1))
),

module.return(module.local.get(4, binaryen.i32))
])
);
module.addFunctionExport("fits", "fits");

return module;
}
Insert cell
constructModule = module => {
if (!module.validate()) throw new Error("validation error");
var wasmData = module.emitBinary();
var compiled = new WebAssembly.Module(wasmData);
return new WebAssembly.Instance(compiled);
}
Insert cell
constructModuleOptimized = module => {
if (!module.validate()) throw new Error("validation error");
module.optimize();
var wasmData = module.emitBinary();
var compiled = new WebAssembly.Module(wasmData);
return new WebAssembly.Instance(compiled);
}
Insert cell
wasmFits = {
const m = constructModule(buildModule());
return m.exports.fits;
}
Insert cell
wasmFitsOptimized = {
const m = constructModuleOptimized(buildModule());
return m.exports.fits;
}
Insert cell
range(min, max + 1).filter(wasmFits).length
Insert cell
Insert cell
{
const testMin = min;
const testMax = max;

let t0;
t0 = performance.now();
const soln1 = range(testMin, testMax).filter(wasmFits).length;
const wasmTime = performance.now() - t0;

t0 = performance.now();
const soln2 = range(testMin, testMax).filter(wasmFitsOptimized).length;
const optWasmTime = performance.now() - t0;

return { wasmTime, optWasmTime };
}
Insert cell
{
const m = buildModule();
return m.emitText();
}
Insert cell
{
const m = buildModule();
m.optimize();
return m.emitText();
}
Insert cell
module
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more