Last active
August 20, 2022 03:16
-
-
Save anhdiepmmk/de032bdc34cc9f5b354a0d86c6bc466f to your computer and use it in GitHub Desktop.
simple calculator
This file contains 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
function combine(a, b, operator) { | |
if (operator === 'x') { | |
return a * b; | |
} | |
if (operator === '/') { | |
return a / b; | |
} | |
if (operator === '+') { | |
return a + b; | |
} | |
if (operator === '-') { | |
return a - b; | |
} | |
throw new Error(`Invalid operator: ${operator}`); | |
} | |
function removeNullElements(elements) { | |
while (elements.includes(null)) { | |
const index = elements.findIndex((element) => element === null); | |
elements.splice(index, 1); | |
} | |
} | |
function compact(originalElements, operator) { | |
const elements = originalElements; | |
while (elements.includes(operator)) { | |
const index = elements.findIndex((element) => element === operator); | |
const leftIndex = index - 1; | |
const rightIndex = index + 1; | |
const leftValue = parseFloat(elements[leftIndex]); | |
const rightValue = parseFloat(elements[rightIndex]); | |
// update operator to new value | |
elements[index] = combine(leftValue, rightValue, operator); | |
// mark to delete | |
elements[leftIndex] = null; | |
elements[rightIndex] = null; | |
removeNullElements(elements); | |
} | |
} | |
function calculate(elements) { | |
compact(elements, 'x'); | |
compact(elements, '/'); | |
compact(elements, '+'); | |
compact(elements, '-'); | |
if (elements.length > 1) { | |
throw new Error( | |
`there are some invalid elements ${JSON.stringify(elements)}`, | |
); | |
} | |
return elements[0]; | |
} | |
function convertElements2String(elements) { | |
return elements.join(' '); | |
} |
This file contains 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 caculatorService = require('./calculator'); | |
describe('calculate', () => { | |
test('given invalid elements then throw an error', () => { | |
expect(() => caculatorService.calculate([1, 2, 1])).toThrowError( | |
new Error(`there are some invalid elements ${JSON.stringify([1, 2, 1])}`), | |
); | |
}); | |
describe('simple', () => { | |
test('should return 2', () => { | |
expect(caculatorService.calculate([1, '+', 1])).toBe(2); | |
}); | |
test('should return 0', () => { | |
expect(caculatorService.calculate([1, '-', 1])).toBe(0); | |
}); | |
test('should return 4', () => { | |
expect(caculatorService.calculate([2, 'x', 2])).toBe(4); | |
}); | |
test('should return 0.5', () => { | |
expect(caculatorService.calculate([1, '/', 2])).toBe(0.5); | |
}); | |
}); | |
describe('priority', () => { | |
test('should return 21', () => { | |
expect(caculatorService.calculate([3, '+', 3, 'x', 6])).toBe(21); | |
}); | |
test('should return 31', () => { | |
expect(caculatorService.calculate([3, '+', 4, 'x', 7])).toBe(31); | |
}); | |
test('should return 26', () => { | |
expect(caculatorService.calculate([6, '+', 4, 'x', 5])).toBe(26); | |
}); | |
test('should return 10', () => { | |
expect(caculatorService.calculate([5, 'x', 6, '/', 3])).toBe(10); | |
}); | |
}); | |
}); | |
describe('combine', () => { | |
test('should return a value', () => { | |
expect(caculatorService.combine(1, 2, '+')).toBe(3); | |
expect(caculatorService.combine(2, 2, '-')).toBe(0); | |
expect(caculatorService.combine(3, 2, 'x')).toBe(6); | |
expect(caculatorService.combine(1, 2, '/')).toBe(0.5); | |
}); | |
test('given invalid operator then throw an error', () => { | |
expect(() => caculatorService.combine(1, 2, '*')).toThrowError( | |
new Error('Invalid operator: *'), | |
); | |
}); | |
}); |
This file contains 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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Document</title> | |
<style> | |
#result { | |
border: 1px solid rebeccapurple; | |
height: 2rem; | |
border-radius: 1px; | |
} | |
</style> | |
</head> | |
<body> | |
<div> | |
<div id="result"></div> | |
<div> | |
<button class="numbers">1</button> | |
<button class="numbers">2</button> | |
<button class="numbers">3</button> | |
<button class="numbers">4</button> | |
<button class="numbers">5</button> | |
</div> | |
<div> | |
<button class="numbers">6</button> | |
<button class="numbers">7</button> | |
<button class="numbers">8</button> | |
<button class="numbers">9</button> | |
<button class="numbers">0</button> | |
</div> | |
<div> | |
<button class="operators">+</button> | |
<button class="operators">-</button> | |
<button class="operators">x</button> | |
<button class="operators">/</button> | |
<button id="backspace">backspace</button> | |
<button id="clear">clear</button> | |
<button id="enter">=</button> | |
</div> | |
</div> | |
<script type="text/javascript" src="calculator.js"></script> | |
<script type="text/javascript" src="main.js"></script> | |
</body> | |
</html> |
This file contains 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
module.exports = { | |
testEnvironment: "jsdom", | |
}; |
This file contains 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 OPERATORS = ['+', '-', 'x', '/']; | |
const btnNumbers = document.getElementsByClassName('numbers'); | |
const btnOperators = document.getElementsByClassName('operators'); | |
const divResult = document.getElementById('result'); | |
// ['3', '+', '4.1'] | |
const inputs = []; | |
for (const btnNumber of btnNumbers) { | |
btnNumber.addEventListener('click', (event) => { | |
const lastElement = inputs.at(-1); | |
if (lastElement === undefined || OPERATORS.includes(lastElement)) { | |
// insert new element | |
inputs.push(event.target.textContent); | |
} else { | |
// merge with last element | |
inputs[inputs.length - 1] = | |
`${lastElement}${event.target.textContent}` | |
} | |
divResult.innerText = convertElements2String(inputs); | |
}); | |
} | |
for (const btnOperator of btnOperators) { | |
btnOperator.addEventListener('click', (event) => { | |
const lastElement = inputs.at(-1); | |
if (lastElement !== undefined && !OPERATORS.includes(lastElement)) { | |
inputs.push(event.target.textContent); | |
divResult.innerText = convertElements2String(inputs); | |
} | |
}); | |
} | |
document.getElementById('enter').addEventListener('click', (event) => { | |
const lastElement = inputs.at(-1); | |
if (lastElement !== undefined && !OPERATORS.includes(lastElement)) { | |
const result = calculate(inputs); | |
// remove all elements | |
inputs.length = 0; | |
divResult.innerText = result; | |
} | |
}); | |
document.getElementById('backspace').addEventListener('click', () => { | |
const lastElement = inputs.at(-1); | |
if (lastElement !== undefined) { | |
if (OPERATORS.includes(lastElement)) { | |
inputs.pop(); | |
} else { | |
// remove last charater | |
const updatedLastElement = lastElement.slice(0, -1); | |
if (updatedLastElement === '') { | |
inputs.pop(); | |
} else { | |
inputs[inputs.length - 1] = updatedLastElement; | |
} | |
} | |
divResult.innerText = convertElements2String(inputs); | |
} | |
}); | |
document.getElementById('clear').addEventListener('click', () => { | |
// remove all elements | |
inputs.length = 0; | |
divResult.innerText = convertElements2String(inputs); | |
}); | |
document.getElementById('point').addEventListener('click', () => { | |
const lastElement = inputs.at(-1); | |
if (lastElement !== undefined && !OPERATORS.includes(lastElement) && !`${lastElement}`.includes('.')) { | |
// append point (.) | |
inputs[inputs.length - 1] = | |
`${lastElement}.`; | |
divResult.innerText = convertElements2String(inputs); | |
} | |
}); |
This file contains 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
describe("do some thing", () => { | |
it("should abc", () => { | |
document.body.innerHTML = "<div>hello world</div>"; | |
expect(document.body.innerHTML).toBe("<div>hello world</div>"); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment