Skip to content

Instantly share code, notes, and snippets.

@breeko
Created July 22, 2018 02:54
Show Gist options
  • Save breeko/e3a35d26d52d96a52fe24c348eb25c0e to your computer and use it in GitHub Desktop.
Save breeko/e3a35d26d52d96a52fe24c348eb25c0e to your computer and use it in GitHub Desktop.
getDisplay and evaluate for OpenCalc
getDisplay(): string {
if (this.queue.length === 0) {
return ' '
}
return this.queue.map(x => (
x.operationType == OperationType.Constant &&
!x.operationArgs.has(OperationArgs.PrintAsString)) ?
numberWithCommas(x.stringVal, false) :
x.stringVal).join(' ')
}
evaluate(numbers: Array<Operation>, ops: Array<Operation>, acc: ?number): ?number {
if (ops.length === 0) {
return acc;
}
let zippedOps: Array<[number,number,Operation]> = zipWithIndexTwice(ops); // e.g. 1 + 2 + 3 => returns (0, 0, +) (0, 0, -)
let numUnary: number = 0;
for (let idx = 0; idx < zippedOps.length; idx++) {
// adjust for unary ops
// e.g. sin cos 1 =>
// zippedOps = ((0, 0, sin), (1, 1, cos)) numbers = (1)
// adjustedZippedOps = ((0, 0, sin), (1, 0 cos))
zippedOps[idx][1] -= numUnary;
if (zippedOps[idx][2].operationSubType === OperationSubType.UnaryOp) {
numUnary += 1;
}
}
let maxPriority: [number,number,Operation] = zippedOps.reduce(function(a, b) {
if (a[2].operationSubType === OperationSubType.UnaryOp) {
// right to left on unary ops two unary ops
// e.g. sin cos 1, evaluate cos(1) first
return a[2].priority > b[2].priority ? a : b;
}
return a[2].priority >= b[2].priority ? a : b;});
const opIdx: number = maxPriority[0];
const numIdx: number = maxPriority[1];
const op: Operation = maxPriority[2];
const num1: ?Operation = numbers[numIdx];
const num2: ?Operation = numbers[numIdx + 1];
let head: Array<Operation> = numbers.slice(0, numIdx);
let tail: Array<Operation> = numbers.slice(numIdx, numbers.length);
let evaluatedNumber: boolean = false;
if (num1) {
if (op.operationSubType === OperationSubType.BackwardUnaryOp) {
if (isNaN(num1.val)) {
throw 'Number too long';
}
acc = op.val(num1.val);
tail = numbers.slice(numIdx + 1, numbers.length);
evaluatedNumber = true;
} else if (isInArray(op.operationSubType, Array(OperationSubType.UnaryOp, OperationSubType.BackwardUnaryOp))) {
acc = op.val(num1.val);
tail = numbers.slice(numIdx + 1, numbers.length);
evaluatedNumber = true;
} else if (op.operationSubType === OperationSubType.BinaryOp) {
if (num2) {
if (isNaN(num2.val)) {
throw 'Number too long';
}
acc = op.val(num1.val, num2.val);
tail = numbers.slice(numIdx + 2, numbers.length);
evaluatedNumber = true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment