Skip to content

Commit ae12235

Browse files
committed
Refactoring
1 parent ccdf261 commit ae12235

File tree

15 files changed

+477
-299
lines changed

15 files changed

+477
-299
lines changed

src/math/average.test.ts

Lines changed: 60 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,67 @@
1-
import { assertEquals } from 'https://deno.land/std@0.203.0/assert/assert_equals.ts'
2-
import average from "./average.ts"
1+
import { assertEquals } from 'https://deno.land/std@0.203.0/assert/assert_equals.ts';
2+
import average from './average.ts';
33

44
Deno.test(
5-
'Calculate average value of number array.',
6-
async (test) => {
7-
await test.step({
8-
name: 'Empty array []',
9-
fn: () => {
10-
assertEquals(
11-
average([]),
12-
0
13-
)
14-
}
15-
})
5+
'Calculate average value of number array.',
6+
async (test) => {
7+
await test.step({
8+
name: 'Empty array []',
9+
fn: () => {
10+
assertEquals(
11+
average([]),
12+
0,
13+
);
14+
},
15+
});
1616

17-
await test.step({
18-
name: 'Array with [0]',
19-
fn: () => {
20-
assertEquals(
21-
average([0]),
22-
0
23-
)
24-
}
25-
})
17+
await test.step({
18+
name: 'Array with [0]',
19+
fn: () => {
20+
assertEquals(
21+
average([0]),
22+
0,
23+
);
24+
},
25+
});
2626

27-
await test.step({
28-
name: 'Array with [1]',
29-
fn: () => {
30-
assertEquals(
31-
average([1]),
32-
1
33-
)
34-
}
35-
})
27+
await test.step({
28+
name: 'Array with [1]',
29+
fn: () => {
30+
assertEquals(
31+
average([1]),
32+
1,
33+
);
34+
},
35+
});
3636

37-
await test.step({
38-
name: 'Array with even amount of numbers [7, 2, 6, 13]',
39-
fn: () => {
40-
assertEquals(
41-
average([7, 2, 6, 13]),
42-
7
43-
)
44-
}
45-
})
37+
await test.step({
38+
name: 'Array with even amount of numbers [7, 2, 6, 13]',
39+
fn: () => {
40+
assertEquals(
41+
average([7, 2, 6, 13]),
42+
7,
43+
);
44+
},
45+
});
4646

47-
await test.step({
48-
name: 'Array with odd amount of numbers [7, 2, 6, 13, 27]',
49-
fn: () => {
50-
assertEquals(
51-
average([7, 2, 6, 13, 27]),
52-
11
53-
)
54-
}
55-
})
47+
await test.step({
48+
name: 'Array with odd amount of numbers [7, 2, 6, 13, 27]',
49+
fn: () => {
50+
assertEquals(
51+
average([7, 2, 6, 13, 27]),
52+
11,
53+
);
54+
},
55+
});
5656

57-
await test.step({
58-
name: 'Array with negative numbers [-7, 2, 6, -13, 27]',
59-
fn: () => {
60-
assertEquals(
61-
average([-7, 2, 6, -13, 27]),
62-
3
63-
)
64-
}
65-
})
66-
}
67-
);
68-
57+
await test.step({
58+
name: 'Array with negative numbers [-7, 2, 6, -13, 27]',
59+
fn: () => {
60+
assertEquals(
61+
average([-7, 2, 6, -13, 27]),
62+
3,
63+
);
64+
},
65+
});
66+
},
67+
);

src/math/average.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
* @returns number, the average amount from the number array
77
*/
88
export default function average(list : number[]) : number {
9-
return list.reduce((last, current) => last + current, 0) / list.length || 0;
9+
return list.reduce((last, current) => last + current, 0) / list.length || 0;
1010
}

src/math/evaluate/evaluate.ts

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/* A Javascript program to evaluate a given
2+
expression where tokens
3+
are separated by space.
4+
*/
5+
6+
function evaluate(expression : string) : number | undefined {
7+
const tokens = expression.split('');
8+
9+
// Stack for numbers: 'values'
10+
const values : number[] = [];
11+
12+
// Stack for Operators: 'ops'
13+
const ops = [];
14+
15+
for (let i = 0; i < tokens.length; i++) {
16+
// Current token is a whitespace, skip it
17+
if (tokens[i] === ' ') {
18+
continue;
19+
}
20+
21+
// Current token is a number,
22+
// push it to stack for numbers
23+
if (tokens[i] >= '0' && tokens[i] <= '9') {
24+
let sbuf = '';
25+
26+
// There may be more than
27+
// one digits in number
28+
while (
29+
i < tokens.length &&
30+
tokens[i] >= '0' &&
31+
tokens[i] <= '9'
32+
) {
33+
sbuf = sbuf + tokens[i++];
34+
}
35+
values.push(parseInt(sbuf, 10));
36+
37+
// Right now the i points to
38+
// the character next to the digit,
39+
// since the for loop also increases
40+
// the i, we would skip one
41+
// token position; we need to
42+
// decrease the value of i by 1 to
43+
// correct the offset.
44+
i--;
45+
} // Current token is an opening
46+
// brace, push it to 'ops'
47+
else if (tokens[i] === '(') {
48+
ops.push(tokens[i]);
49+
} // Closing brace encountered,
50+
// solve entire brace
51+
else if (tokens[i] === ')') {
52+
while (ops[ops.length - 1] !== '(') {
53+
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
54+
}
55+
ops.pop();
56+
} // Current token is an operator.
57+
else if (
58+
tokens[i] === '+' ||
59+
tokens[i] === '-' ||
60+
tokens[i] === '*' ||
61+
tokens[i] === '/'
62+
) {
63+
// While top of 'ops' has same
64+
// or greater precedence to current
65+
// token, which is an operator.
66+
// Apply operator on top of 'ops'
67+
// to top two elements in values stack
68+
while (
69+
ops.length > 0 &&
70+
hasPrecedence(tokens[i], ops[ops.length - 1])
71+
) {
72+
values.push(applyOp(ops.pop() ?? '', values.pop(), values.pop()));
73+
}
74+
75+
// Push current token to 'ops'.
76+
ops.push(tokens[i]);
77+
}
78+
}
79+
80+
// Entire expression has been
81+
// parsed at this point, apply remaining
82+
// ops to remaining values
83+
while (ops.length > 0) {
84+
values.push(applyOp(ops.pop() ?? '', values.pop() ?? 0, values.pop() ?? 0));
85+
}
86+
87+
// Top of 'values' contains
88+
// result, return it
89+
return values.pop();
90+
}
91+
92+
// Returns true if 'op2' has
93+
// higher or same precedence as 'op1',
94+
// otherwise returns false.
95+
function hasPrecedence(op1 : string, op2 : string) : boolean {
96+
if (op2 === '(' || op2 === ')') {
97+
return false;
98+
}
99+
if (
100+
(op1 === '*' || op1 === '/') &&
101+
(op2 === '+' || op2 === '-')
102+
) {
103+
return false;
104+
} else {
105+
return true;
106+
}
107+
}
108+
109+
// A utility method to apply an
110+
// operator 'op' on operands 'a'
111+
// and 'b'. Return the result.
112+
function applyOp(op : string, b : number, a : number) : number {
113+
switch (op) {
114+
case '+':
115+
return a + b;
116+
case '-':
117+
return a - b;
118+
case '*':
119+
return a * b;
120+
case '/':
121+
if (b === 0) {
122+
throw new Error('Cannot divide by zero');
123+
}
124+
return a / b
125+
}
126+
return 0;
127+
}

src/math/evaluate/mod.ts

Whitespace-only changes.

src/math/evaluate/tokens.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { valuesFromObject } from '../../object/mod.ts';
2+
import { ValuesFromObject } from '../../type/mod.ts';
3+
4+
/**
5+
* This object contains all tokens.
6+
*/
7+
const tokens = {
8+
PLUS: '+',
9+
MINUS: '-',
10+
MULTIPLY: '*',
11+
DIVIDE: '/',
12+
POWER: '^',
13+
CAPTURE_START: '(',
14+
CAPTURE_END: ')',
15+
} as const;
16+
17+
export default tokens;
18+
19+
/**
20+
* This array gets generated from the values of {@linkcode tokens}.
21+
*/
22+
export const tokenValues = valuesFromObject(tokens)
23+
24+
/**
25+
* This type gets generated from the values of {@linkcode tokens}.
26+
*/
27+
export type Token = ValuesFromObject<typeof tokens>;

0 commit comments

Comments
 (0)