https://github.com/halimath/calculator-kata
A coding kata for building a simple calculator for very long mathematical terms
https://github.com/halimath/calculator-kata
Last synced: about 1 year ago
JSON representation
A coding kata for building a simple calculator for very long mathematical terms
- Host: GitHub
- URL: https://github.com/halimath/calculator-kata
- Owner: halimath
- Created: 2024-02-08T08:10:33.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-02-29T14:49:22.000Z (over 2 years ago)
- Last Synced: 2025-01-22T03:27:46.076Z (over 1 year ago)
- Language: Go
- Size: 6.24 MB
- Stars: 0
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Calculator Kata
Write a calculator that reads mathematical terms containing
floating point numbers, +, -, * and / as well as parenthesis.
Calculate the result by applying the "usual" mathematical rules:
* operators are used in _infix notation_: `2 + 3`
* multiply/div have higher precedence then add/sub
* parenthesis have higher precedence then operators
* numbers can contain a mix of integers and floating point numbers
* calculation should follow mathematical rules, i.e. `2 / 0` is an error and not
something like `NaN` or `-Inf`
The calculator should
* calculate the result of a single mathematical expression (no matter how long)
* print the result in a human readable style
* report any error and refuse the calculation (error reporting style doesn't matter)
* handle arbitrary long terms (i.e. tens of megabytes of input) well (i.e. in
terms of memory usage as well as running time)
# Specification of the input language
The calculator processes input that is read as `UTF-8` encoded characters. A
formal specification of the input language is defined by the following [EBNF]:
```ebnf
(* An expression defines the start of the production. *)
expr = number (* A bare number is a valid expression*)
| ( expr, S, operator, S, number ) (* left-recursive operator chained expression *)
| ( "(" S, expr, S, ")" ); (* parenthesis surround an expression *)
(* The list of available operators. *)
operator = "+" | "-" | "*" | "/";
(* Definition of a number - either 0.xyz or abc.xyz *)
number = zero_fraction
| non_zero_fraction;
non_zero_fraction = non_zero_digit { digit } { "." digit { digit } };
zero_fraction = "0" { "." digit { digit } };
non_zero_digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
digit = "0" | non_zero_digit;
(* Any whitespace used as a separator including none. *)
S = "" | { " " | "\n" | "\t" | "\r" | "\f" | "\b" } ;
```
Note that expressions in parenthesis can also contain parenthesis.
[EBNF]: https://en.wikipedia.org/wiki/Extended_Backus–Naur_form
## Examples
The following lines are all valid input sequences:
```
0
0.123
807.1328
17 * 19
(21 - 3) * 8
```
# Implementation Restrictions
* Only use the standard library for the production code; do not rely on external
libraries (except for testing/benchmarking)
* Apply an appropriate structure (i.e. packages, types, ...)
* Write _idiomatic_ code
* Write unit tests to
# Testcases
A couple of test files with increasing sizes are provided in [`testdata`](./testdata).
The file names roughly tell the file's sizes. You can use them for functional
as well as for benchmark tests.
The results are
* `testdata/1k` -> 248253190541.03891
* `testdata/10k` -> 214512826488689376
* `testdata/100k` -> 481585283158357967896576
* `testdata/1m` -> 830415166156152287340265472
* `testdata/10m` -> 6780466519056739908798922614519103488