Created
February 28, 2018 00:17
-
-
Save loganzartman/cd4254d48cc75c4f28832d650a51f44c to your computer and use it in GitHub Desktop.
Note: run `npm install long` in the same directory before using
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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