Skip to content

Commit 67c5777

Browse files
authored
Merge branch 'master' into fix/typo
2 parents 0adaac7 + 19aa6fa commit 67c5777

File tree

8 files changed

+192
-25
lines changed

8 files changed

+192
-25
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules
22
.idea
33
coverage
4+
.vscode

README.md

+17-16
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,22 @@
33
[![Build Status](https://travis-ci.org/trekhleb/javascript-algorithms.svg?branch=master)](https://travis-ci.org/trekhleb/javascript-algorithms)
44
[![codecov](https://codecov.io/gh/trekhleb/javascript-algorithms/branch/master/graph/badge.svg)](https://codecov.io/gh/trekhleb/javascript-algorithms)
55

6-
This repository contains JavaScript based examples of many
6+
This repository contains JavaScript based examples of many
77
popular algorithms and data structures.
88

99
Each algorithm and data structure has its own separate README
1010
with related explanations and links for further reading (including ones
1111
to YouTube videos).
1212

13-
_Read this in other languages:_
13+
_Read this in other languages:_
1414
[简体中文](https://github.com/trekhleb/javascript-algorithms/blob/master/README.zh-CN.md),
1515
[繁體中文](https://github.com/trekhleb/javascript-algorithms/blob/master/README.zh-TW.md)
1616

1717
## Data Structures
1818

1919
A data structure is a particular way of organizing and storing data in a computer so that it can
20-
be accessed and modified efficiently. More precisely, a data structure is a collection of data
21-
values, the relationships among them, and the functions or operations that can be applied to
20+
be accessed and modified efficiently. More precisely, a data structure is a collection of data
21+
values, the relationships among them, and the functions or operations that can be applied to
2222
the data.
2323

2424
* [Linked List](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/linked-list)
@@ -53,13 +53,14 @@ a set of rules that precisely define a sequence of operations.
5353
* [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition)
5454
* [Sieve of Eratosthenes](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/sieve-of-eratosthenes) - finding all prime numbers up to any given limit
5555
* [Is Power of Two](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/is-power-of-two) - check if the number is power of two (naive and bitwise algorithms)
56+
* [Liu Hui π Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/liu-hui) - approximate π calculations based on N-gons
5657
* **Sets**
5758
* [Cartesian Product](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/cartesian-product) - product of multiple sets
5859
* [Power Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/power-set) - all subsets of a set
5960
* [Permutations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (with and without repetitions)
6061
* [Combinations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (with and without repetitions)
6162
* [Fisher–Yates Shuffle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/fisher-yates) - random permutation of a finite sequence
62-
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS)
63+
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS)
6364
* [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence)
6465
* [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS)
6566
* [Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones
@@ -105,11 +106,11 @@ a set of rules that precisely define a sequence of operations.
105106
* [Tower of Hanoi](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower)
106107
* [N-Queens Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens)
107108
* [Knight's Tour](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour)
108-
109+
109110
### Algorithms by Paradigm
110111

111-
An algorithmic paradigm is a generic method or approach which underlies the design of a class
112-
of algorithms. It is an abstraction higher than the notion of an algorithm, just as an
112+
An algorithmic paradigm is a generic method or approach which underlies the design of a class
113+
of algorithms. It is an abstraction higher than the notion of an algorithm, just as an
113114
algorithm is an abstraction higher than a computer program.
114115

115116
* **Brute Force** - look at all the possibilities and selects the best solution
@@ -142,7 +143,7 @@ algorithm is an abstraction higher than a computer program.
142143
* [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray)
143144
* [Bellman-Ford Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices
144145
* **Backtracking** - similarly to brute force, try to generate all possible solutions, but each time you generate next solution you test
145-
if it satisfies all conditions, and only then continue generating subsequent solutions. Otherwise, backtrack, and go on a
146+
if it satisfies all conditions, and only then continue generating subsequent solutions. Otherwise, backtrack, and go on a
146147
different path of finding a solution. Normally the DFS traversal of state-space is being used.
147148
* [Hamiltonian Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once
148149
* [N-Queens Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens)
@@ -188,13 +189,13 @@ npm test -- -t 'playground'
188189
[▶ Data Structures and Algorithms on YouTube](https://www.youtube.com/playlist?list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
189190

190191
### Big O Notation
191-
192+
192193
Order of growth of algorithms specified in Big O notation.
193-
194-
![Big O graphs](https://github.com/trekhleb/javascript-algorithms/blob/master/assets/big-o-graph.png?raw=true)
194+
195+
![Big O graphs](./assets/big-o-graph.png)
195196

196197
Source: [Big O Cheat Sheet](http://bigocheatsheet.com/).
197-
198+
198199
Below is the list of some of the most used Big O notations and their performance comparisons against different sizes of the input data.
199200

200201
| Big O Notation | Computations for 10 elements | Computations for 100 elements | Computations for 1000 elements |
@@ -208,12 +209,12 @@ Below is the list of some of the most used Big O notations and their performance
208209
| **O(N!)** | 3628800 | 9.3e+157 | 4.02e+2567 |
209210

210211
### Data Structure Operations Complexity
211-
212+
212213
| Data Structure | Access | Search | Insertion | Deletion | Comments |
213-
| ----------------------- | :-------: | :-------: | :-------: | :-------: | :-------- |
214+
| ----------------------- | :-------: | :-------: | :-------: | :-------: | :-------- |
214215
| **Array** | 1 | n | n | n | |
215216
| **Stack** | n | n | 1 | 1 | |
216-
| **Queue** | n | n | 1 | 1 | |
217+
| **Queue** | n | n | 1 | 1 | |
217218
| **Linked List** | n | n | 1 | 1 | |
218219
| **Hash Table** | - | n | n | n | In case of perfect hash function costs would be O(1) |
219220
| **Binary Search Tree** | n | n | n | n | In case of balanced tree costs would be O(log(n)) |

README.zh-CN.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ npm test -- -t 'playground'
170170

171171
大O符号中指定的算法的增长顺序。
172172

173-
![Big O graphs](https://github.com/trekhleb/javascript-algorithms/blob/master/assets/big-o-graph.png?raw=true)
173+
![Big O graphs](./assets/big-o-graph.png)
174174

175175
源: [Big O Cheat Sheet](http://bigocheatsheet.com/).
176176

README.zh-TW.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ _Read this in other languages:_
4747
* [排列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (有/無重複)
4848
* [组合](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (有/無重複)
4949
* [洗牌算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/fisher-yates) - 隨機置換一有限序列
50-
* [最長共同子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS)
50+
* [最長共同子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS)
5151
* [最長遞增子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence)
5252
* [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS)
5353
* [背包問題](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones
@@ -90,7 +90,7 @@ _Read this in other languages:_
9090
* [河內塔](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower)
9191
* [N-皇后問題](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens)
9292
* [騎士走棋盤](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour)
93-
93+
9494
### 演算法範型
9595

9696
演算法的範型是一個泛用方法或設計一類底層演算法的方式。它是一個比演算法的概念更高階的抽象化,就像是演算法是比電腦程式更高階的抽象化。
@@ -166,11 +166,11 @@ npm test -- -t 'playground'
166166
### 大 O 標記
167167

168168
特別用大 O 標記演算法增長度的排序。
169-
170-
![Big O 表](https://github.com/trekhleb/javascript-algorithms/blob/master/assets/big-o-graph.png?raw=true)
169+
170+
![Big O 表](./assets/big-o-graph.png)
171171

172172
資料來源: [Big O Cheat Sheet](http://bigocheatsheet.com/).
173-
173+
174174
下列列出幾個常用的 Big O 標記以及其不同大小資料量輸入後的運算效能比較。
175175

176176
| Big O 標記 | 10個資料量需花費的時間 | 100個資料量需花費的時間 | 1000個資料量需花費的時間 |
@@ -184,12 +184,12 @@ npm test -- -t 'playground'
184184
| **O(N!)** | 3628800 | 9.3e+157 | 4.02e+2567 |
185185

186186
### 資料結構運作複雜度
187-
187+
188188
| 資料結構 | 存取 | 搜尋 | 插入 | 刪除 |
189-
| ----------------------- | :-------: | :-------: | :-------: | :-------: |
189+
| ----------------------- | :-------: | :-------: | :-------: | :-------: |
190190
| **陣列** | 1 | n | n | n |
191191
| **堆疊** | n | n | 1 | 1 |
192-
| **貯列** | n | n | 1 | 1 |
192+
| **貯列** | n | n | 1 | 1 |
193193
| **鏈結串列** | n | n | 1 | 1 |
194194
| **雜湊表** | - | n | n | n |
195195
| **二元搜尋樹** | n | n | n | n |

assets/big-o-graph.png

-28.6 KB
Loading

src/algorithms/math/liu-hui/README.md

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Liu Hui's π Algorithm
2+
3+
Liu Hui remarked in his commentary to The Nine Chapters on the Mathematical Art,
4+
that the ratio of the circumference of an inscribed hexagon to the diameter of
5+
the circle was `three`, hence `π` must be greater than three. He went on to provide
6+
a detailed step-by-step description of an iterative algorithm to calculate `π` to
7+
any required accuracy based on bisecting polygons; he calculated `π` to
8+
between `3.141024` and `3.142708` with a 96-gon; he suggested that `3.14` was
9+
a good enough approximation, and expressed `π` as `157/50`; he admitted that
10+
this number was a bit small. Later he invented an ingenious quick method to
11+
improve on it, and obtained `π ≈ 3.1416` with only a 96-gon, with an accuracy
12+
comparable to that from a 1536-gon. His most important contribution in this
13+
area was his simple iterative `π` algorithm.
14+
15+
## Area of a circle
16+
17+
Liu Hui argued:
18+
19+
> Multiply one side of a hexagon by the radius (of its
20+
circumcircle), then multiply this by three, to yield the
21+
area of a dodecagon; if we cut a hexagon into a
22+
dodecagon, multiply its side by its radius, then again
23+
multiply by six, we get the area of a 24-gon; the finer
24+
we cut, the smaller the loss with respect to the area
25+
of circle, thus with further cut after cut, the area of
26+
the resulting polygon will coincide and become one with
27+
the circle; there will be no loss
28+
29+
![Liu Hui](https://upload.wikimedia.org/wikipedia/commons/6/69/Cutcircle2.svg)
30+
31+
Liu Hui's method of calculating the area of a circle.
32+
33+
Further, Liu Hui proved that the area of a circle is half of its circumference
34+
multiplied by its radius. He said:
35+
36+
> Between a polygon and a circle, there is excess radius. Multiply the excess
37+
radius by a side of the polygon. The resulting area exceeds the boundary of
38+
the circle
39+
40+
In the diagram `d = excess radius`. Multiplying `d` by one side results in
41+
oblong `ABCD` which exceeds the boundary of the circle. If a side of the polygon
42+
is small (i.e. there is a very large number of sides), then the excess radius
43+
will be small, hence excess area will be small.
44+
45+
> Multiply the side of a polygon by its radius, and the area doubles;
46+
hence multiply half the circumference by the radius to yield the area of circle.
47+
48+
![Liu Hui](https://upload.wikimedia.org/wikipedia/commons/9/95/Cutcircle.svg)
49+
50+
The area within a circle is equal to the radius multiplied by half the
51+
circumference, or `A = r x C/2 = r x r x π`.
52+
53+
## Iterative algorithm
54+
55+
Liu Hui began with an inscribed hexagon. Let `M` be the length of one side `AB` of
56+
hexagon, `r` is the radius of circle.
57+
58+
![Liu Hui](https://upload.wikimedia.org/wikipedia/commons/4/46/Liuhui_geyuanshu.svg)
59+
60+
Bisect `AB` with line `OPC`, `AC` becomes one side of dodecagon (12-gon), let
61+
its length be `m`. Let the length of `PC` be `j` and the length of `OP` be `G`.
62+
63+
`AOP`, `APC` are two right angle triangles. Liu Hui used
64+
the [Gou Gu](https://en.wikipedia.org/wiki/Pythagorean_theorem) (Pythagorean theorem)
65+
theorem repetitively:
66+
67+
![](https://wikimedia.org/api/rest_v1/media/math/render/svg/dbfc192c78539c3901c7bad470302ededb76f813)
68+
69+
![](https://wikimedia.org/api/rest_v1/media/math/render/svg/ccd12a402367c2d6614c88e75006d50bfc3a9929)
70+
71+
![](https://wikimedia.org/api/rest_v1/media/math/render/svg/65d77869fc02c302d2d46d45f75ad7e79ae524fb)
72+
73+
![](https://wikimedia.org/api/rest_v1/media/math/render/svg/a7a0d0d7f505a0f434e5dd80c2fef6d2b30d6100)
74+
75+
![](https://wikimedia.org/api/rest_v1/media/math/render/svg/c31b9acf38f9d1a248d4023c3bf286bd03007f37)
76+
77+
![](https://wikimedia.org/api/rest_v1/media/math/render/svg/0dee798efb0b1e3e64d6b3542106cb3ecaa4a383)
78+
79+
![](https://wikimedia.org/api/rest_v1/media/math/render/svg/3ffeafe88d2983b364ad3442746063e3207fe842)
80+
81+
82+
From here, there is now a technique to determine `m` from `M`, which gives the
83+
side length for a polygon with twice the number of edges. Starting with a
84+
hexagon, Liu Hui could determine the side length of a dodecagon using this
85+
formula. Then continue repetitively to determine the side length of a
86+
24-gon given the side length of a dodecagon. He could do this recursively as
87+
many times as necessary. Knowing how to determine the area of these polygons,
88+
Liu Hui could then approximate `π`.
89+
90+
## References
91+
92+
- [Wikipedia](https://en.wikipedia.org/wiki/Liu_Hui%27s_%CF%80_algorithm)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import liuHui from '../liuHui';
2+
3+
describe('liuHui', () => {
4+
it('should calculate π based on 12-gon', () => {
5+
expect(liuHui(1)).toBe(3);
6+
});
7+
8+
it('should calculate π based on 24-gon', () => {
9+
expect(liuHui(2)).toBe(3.105828541230249);
10+
});
11+
12+
it('should calculate π based on 6144-gon', () => {
13+
expect(liuHui(10)).toBe(3.1415921059992717);
14+
});
15+
16+
it('should calculate π based on 201326592-gon', () => {
17+
expect(liuHui(25)).toBe(3.141592653589793);
18+
});
19+
});

src/algorithms/math/liu-hui/liuHui.js

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Let circleRadius is the radius of circle.
3+
* circleRadius is also the side length of the inscribed hexagon
4+
*/
5+
const circleRadius = 1;
6+
7+
/**
8+
* @param {number} sideLength
9+
* @param {number} splitCounter
10+
* @return {number}
11+
*/
12+
function getNGonSideLength(sideLength, splitCounter) {
13+
if (splitCounter <= 0) {
14+
return sideLength;
15+
}
16+
17+
const halfSide = sideLength / 2;
18+
19+
// Liu Hui used the Gou Gu (Pythagorean theorem) theorem repetitively.
20+
const perpendicular = Math.sqrt((circleRadius ** 2) - (halfSide ** 2));
21+
const excessRadius = circleRadius - perpendicular;
22+
const splitSideLength = Math.sqrt((excessRadius ** 2) + (halfSide ** 2));
23+
24+
return getNGonSideLength(splitSideLength, splitCounter - 1);
25+
}
26+
27+
/**
28+
* @param {number} splitCount
29+
* @return {number}
30+
*/
31+
function getNGonSideCount(splitCount) {
32+
// Liu Hui began with an inscribed hexagon (6-gon).
33+
const hexagonSidesCount = 6;
34+
35+
// On every split iteration we make N-gons: 6-gon, 12-gon, 24-gon, 48-gon and so on.
36+
return hexagonSidesCount * (splitCount ? 2 ** splitCount : 1);
37+
}
38+
39+
/**
40+
* Calculate the π value using Liu Hui's π algorithm
41+
*
42+
* @param {number} splitCount - number of times we're going to split 6-gon.
43+
* On each split we will receive 12-gon, 24-gon and so on.
44+
* @return {number}
45+
*/
46+
export default function liuHui(splitCount = 1) {
47+
const nGonSideLength = getNGonSideLength(circleRadius, splitCount - 1);
48+
const nGonSideCount = getNGonSideCount(splitCount - 1);
49+
const nGonPerimeter = nGonSideLength * nGonSideCount;
50+
const approximateCircleArea = (nGonPerimeter / 2) * circleRadius;
51+
52+
// Return approximate value of pi.
53+
return approximateCircleArea / (circleRadius ** 2);
54+
}

0 commit comments

Comments
 (0)