Skip to content

Instantly share code, notes, and snippets.

@loganzartman
Created February 28, 2018 00:17
Show Gist options
  • Save loganzartman/cd4254d48cc75c4f28832d650a51f44c to your computer and use it in GitHub Desktop.
Save loganzartman/cd4254d48cc75c4f28832d650a51f44c to your computer and use it in GitHub Desktop.
Note: run `npm install long` in the same directory before using
const long = require("long");
const execSync = require("child_process").execSync;
const fs = require("fs");
const N = 5, M = 40, UNTIL_FAIL = true;
const MAX64 = long.MAX_VALUE;
const MIN64 = long.MIN_VALUE;
const BIN = {
"+": function(a,b) {return a.add(b)},
"-": function(a,b) {return b.sub(a)},
"t": function(a,b) {return a.mul(b)}
};
const VARS = ["x","y","z"];
var testCount;
Array.prototype.includes = function(x) {
return this.indexOf(x) >= 0;
}
function main() {
/*testCount = 0;
for (var i=0; i<M || UNTIL_FAIL; i++) {
var expr = buildExpression(~~(Math.random()*100+2));
// console.log(expr.join(" "));
if (!testExpr(expr))
break;
}*/
//TODO
var expr = buildExpression(100);
var vals = {
x: long.fromValue(1),
y: long.fromValue(10),
z: long.fromValue(32)
};
console.log(expr.join(" "));
console.log("Expected: " + eval(expr, vals));
}
function testExpr(expr) {
compile(expr);
var vars = {x:0, y:0, z:0};
var result = true;
var expected;
for (var i=0; i<N; i++) {
testCount++;
vars.x = coolrand();
vars.y = coolrand();
vars.z = coolrand();
// console.log(vars);
expected = eval(expr, vars);
var out = run(expected, vars);
if (!out) {
result = false;
break;
}
}
if (!result) {
var varstr = Object.keys(vars).map(function(v) {return v + "=" + vars[v]}).join(",");
console.log("FAIL -- expr: %s\n\tvars: %s\n\texpect: %s",expr.join(" "),varstr,expected);
return false;
}
else {
console.log("pass -- (%s) expr: %s",testCount,expr.join(" "));
return true;
}
}
function run(expected, vars) {
try {
var varstr = VARS.map(function(v) {return vars[v]}).join(" ");
var args = expected.toString() + " " + varstr;
execSync("./test_program " + args);
return true;
}
catch (e) {
return false;
}
}
function compile(expr) {
fs.truncateSync("test.in", 0);
fs.writeFileSync("test.in", expr.join(" ") + "\n");
execSync("make test");
}
function buildExpression(maxlen) {
if (typeof maxlen === "undefined")
maxlen = 24;
var result = [];
var stacksize = 0;
for (var i=0; i<maxlen; i++) {
if (stacksize <= 1) {
result.push(makeOperand());
stacksize++;
continue;
}
switch (~~(Math.random()*3)) {
case 0:
result.push(makeOperand());
stacksize++;
break;
case 1:
result.push(makeOperator());
stacksize--;
break;
case 2:
result.push("n");
break;
}
}
while (stacksize > 1) {
result.push(makeOperator());
stacksize--;
}
return result;
}
function eval(rpn, vals) {
var ops = Object.keys(BIN);
var stack = [];
rpn.forEach(function(token) {
if (ops.includes(token)) {
var a = stack.pop();
var b = stack.pop();
var c = wrap(BIN[token](a,b));
stack.push(c);
}
else if (token == "n") {
var a = stack.pop();
stack.push(a.neg());
}
else if (VARS.includes(token)) {
stack.push(vals[token]);
}
else {
stack.push(long.fromValue(token));
}
});
if (stack.length !== 1)
throw new Error("bad expression");
return stack.pop();
}
function makeOperand() {
switch (~~(Math.random()*2)) {
case 0:
return VARS[~~(Math.random()*VARS.length)];
break;
case 1:
return coolrand();
break;
}
}
function makeOperator() {
var arr = Object.keys(BIN);
return arr[~~(Math.random()*arr.length)];
}
function wrap(b) {
var diff = MAX64.sub(MIN64);
if (b.lt(MIN64))
return MAX64.add(b.mod(diff).sub(MIN64).sub(1));
if (b.gt(MAX64))
return MIN64.add(b.mod(diff).sub(MAX64).sub(1));
return b;
}
function coolrand() {
var arr = [
MAX64,
MIN64,
long.fromValue(0),
rand(10,0),
rand(100,0),
rand(10,-10),
rand(10000,-10000),
rand64()
];
return arr[~~(Math.random()*arr.length)];
}
function rand(hi, lo) {
if (typeof lo === "undefined")
lo = 0;
hi = long.fromValue(hi);
lo = long.fromValue(lo);
var diff = hi.sub(lo);
return lo.add(~~(Math.random()*diff.toNumber()));
}
function rand64() {
return new long(Math.random()*(Math.pow(2,32)-1), Math.random()*(Math.pow(2,32)-1));
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment