Skip to content

Commit

Permalink
Improve calc speed inside @nth
Browse files Browse the repository at this point in the history
  • Loading branch information
yuanchuan committed Dec 18, 2023
1 parent 7b0cf9b commit de1e4e3
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 32 deletions.
60 changes: 60 additions & 0 deletions src/parser/parse-linear-expr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { scan, iterator } from './tokenizer.js';

/* an +/- b */
export default function parse(input) {
let iter = iterator(scan(input));
let a = [], b = [], op, error;
while (iter.next()) {
let { prev, curr, next } = iter.get();
let v = curr.value;
if (curr.isSymbol()) {
if (v === '+' || v === '-') {
op = v;
} else {
error = 'Unexpected ' + curr.value;
break;
}
}
else if (curr.isNumber()) {
if ((a.length || b.length) && !op) {
error = 'Syntax error';
break;
}
v = withOp(Number(v), op);
op = null;
if (next && next.value === 'n') {
a.push(v);
iter.next();
continue;
} else {
b.push(v);
}
}
else if (v === 'n') {
if ((a.length || b.length) && !op) {
error = 'Syntax error';
break;
}
a.push(withOp(1, op));
op = null;
}
else if (!curr.isSpace()) {
error = 'Unexpected ' + v;
break;
}
}
if (error) {
return { a: 0, b: 0, error }
}
return { a: sum(a), b: sum(b) };
}

function withOp(num, op) {
if (op === '+') return num;
if (op === '-') return -1 * num;
return num;
}

function sum(list) {
return list.reduce((a, b) => a + b, 0);
}
79 changes: 47 additions & 32 deletions src/selector.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import calc from './calc.js';
import parse_linear_expr from './parser/parse-linear-expr.js';

const literal = {
even: n => !(n % 2),
odd: n => !!(n % 2),
};
function odd(n) {
return n % 2;
}

/**
* TODO: optimization
*/
function nth(input, curr, max) {
for (let i = 0; i <= max; ++i) {
if (calc(input, { n: i }) == curr) {
return true;
}
}
function even(n) {
return !odd(n);
}

function get_selector(offset) {
Expand All @@ -30,42 +23,64 @@ function get_selector(offset) {
return selector;
}

function compare(rule, value) {
if (rule === 'even') {
return even(value);
}
if (rule === 'odd') {
return odd(value);
}
if (rule == 'n') {
return true;
}
let { a, b, error } = parse_linear_expr(rule);
if (error) {
return false;
}
if (a === 0) {
return value === b;
} else {
let result = (value - b) / a;
return result >= 0 && Number.isInteger(result);
}
}

export default {

at({ x, y }) {
return (x1, y1) => (x == x1 && y == y1);
},

nth({ count, grid }) {
return (...exprs) => exprs.some(expr =>
literal[expr]
? literal[expr](count)
: nth(expr, count, grid.count)
);
return (...exprs) => {
for (let expr of exprs) {
if (compare(expr, count)) return true;
}
}
},

row({ y, grid }) {
return (...exprs) => exprs.some(expr =>
literal[expr]
? literal[expr](y)
: nth(expr, y, grid.y)
);
return (...exprs) => {
for (let expr of exprs) {
if (compare(expr, y)) return true;
}
};
},

col({ x, grid }) {
return (...exprs) => exprs.some(expr =>
literal[expr]
? literal[expr](x)
: nth(expr, x, grid.x)
);
return (...exprs) => {
for (let expr of exprs) {
if (compare(expr, x)) return true;
}
};
},

even({ count, grid, x, y }) {
return arg => literal.odd(x + y);
even({ x, y }) {
return _ => odd(x + y);
},

odd({ count, grid, x, y}) {
return arg => literal.even(x + y);
odd({ x, y}) {
return _ => even(x + y);
},

random({ random, count, x, y, grid }) {
Expand Down
19 changes: 19 additions & 0 deletions test/parse-linear-expr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import test from 'ava';

import parse from '../src/parser/parse-linear-expr.js';
import compare from './_compare.js';
compare.use(parse);

test('linear expression', t => {

compare(t, '2n + 3', { a: 2, b: 3 });
compare(t, '2n - 3', { a: 2, b: -3 });
compare(t, '2n', { a: 2, b: 0 });
compare(t, '2n 3', { a: 0, b: 0, error: 'Syntax error' });
compare(t, '2n * 3', { a: 0, b: 0, error: 'Unexpected *' });
compare(t, '2', { a: 0, b: 2 });
compare(t, '-10n + 3', { a: -10, b: 3 });
compare(t, '2n + 3n + 5', { a: 5, b: 5 });
compare(t, '', { a: 0, b: 0 });

});

0 comments on commit de1e4e3

Please sign in to comment.