├── .gitattributes ├── chapters ├── principles_of_code │ ├── choosing_a_language │ │ └── compiled │ │ │ ├── makefiles.md │ │ │ ├── FORTRAN.md │ │ │ └── compiled.md │ ├── clone.png │ ├── fork.png │ ├── notation │ │ └── cplot.png │ ├── building_blocks │ │ ├── and.jpg │ │ ├── nand.jpg │ │ ├── nor.jpg │ │ ├── not.jpg │ │ ├── or.jpg │ │ ├── xor.jpg │ │ ├── building_blocks.md │ │ ├── stacks.md │ │ ├── classes.md │ │ ├── loops.md │ │ └── functions.md │ └── principles_of_code.md ├── FFT │ ├── res │ │ ├── fft.png │ │ ├── sinusoid.png │ │ ├── FT_example.png │ │ ├── radix-2screen.jpg │ │ ├── radix-8screen.jpg │ │ ├── butterfly_diagram.png │ │ └── radix-2screen_positive.jpg │ └── code │ │ ├── hs │ │ └── fft.hs │ │ ├── python │ │ └── fft.py │ │ ├── c │ │ └── fft.c │ │ └── julia │ │ └── fft.jl ├── monte_carlo │ ├── res │ │ ├── 31.png │ │ ├── 13311.png │ │ ├── 195583.png │ │ ├── monte_carlo.gif │ │ └── square_circle.png │ └── code │ │ ├── haskell │ │ └── monteCarlo.hs │ │ ├── rust │ │ └── monte_carlo.rs │ │ ├── go │ │ └── monteCarlo.go │ │ ├── d │ │ └── monte_carlo.d │ │ ├── c │ │ └── monte_carlo.c │ │ ├── julia │ │ └── monte_carlo.jl │ │ └── java │ │ └── MonteCarlo.java ├── taylor │ ├── function_sum.png │ └── taylor_series.md ├── codeblock.txt ├── tree_traversal │ ├── res │ │ ├── 3-tree.png │ │ ├── DFS_in.png │ │ ├── DFS_pre.png │ │ ├── BFS_simple.png │ │ ├── DFS_post.png │ │ └── binary_tree.png │ └── code │ │ ├── scratch │ │ └── scratch_tree.png │ │ ├── cs │ │ └── Program.cs │ │ ├── java │ │ └── MainClass.java │ │ ├── rust │ │ └── tree.rs │ │ ├── javascript │ │ └── tree.js │ │ ├── python │ │ └── Tree_example.py │ │ ├── haskell │ │ └── TreeTraversal.hs │ │ ├── pseudo │ │ └── Tree.pseudo │ │ ├── ocaml │ │ └── tree.ml │ │ ├── c++ │ │ └── tree_example.cpp │ │ ├── c │ │ ├── utility.h │ │ └── tree_traversal.c │ │ └── julia │ │ └── Tree.jl ├── euclidean_algorithm │ ├── res │ │ ├── modulus.png │ │ └── subtraction.png │ └── code │ │ ├── java │ │ ├── MainClass.java │ │ └── EuclideanAlgo.java │ │ ├── clojure │ │ └── euclidean_example.clj │ │ ├── python │ │ └── euclidean_example.py │ │ ├── pseudo │ │ └── euclidean.pseudo │ │ ├── cs │ │ ├── Program.cs │ │ └── EuclideanAlgorithm.cs │ │ ├── ocaml │ │ └── euclidean_example.ml │ │ ├── javascript │ │ └── euclidean_example.js │ │ ├── haskell │ │ └── euclidean_example.hs │ │ ├── go │ │ └── euclidean.go │ │ ├── rust │ │ └── euclidean_example.rs │ │ ├── c │ │ └── euclidean_example.c │ │ └── c++ │ │ └── euclidean.cpp ├── differential_equations │ ├── runge_kutta │ │ └── runge_kutta.md │ ├── euler │ │ ├── res │ │ │ ├── error.png │ │ │ └── instability.png │ │ ├── code │ │ │ ├── elm │ │ │ │ └── elm-package.json │ │ │ ├── c │ │ │ │ └── euler.c │ │ │ ├── julia │ │ │ │ └── euler.jl │ │ │ └── c++ │ │ │ │ └── euler.cpp │ │ └── backward_euler.md │ └── differential_equations.md ├── data_compression │ └── huffman │ │ ├── res │ │ └── huffman_tree.png │ │ └── code │ │ ├── cs │ │ └── Program.cs │ │ ├── haskell │ │ └── huffman.hs │ │ └── javascript │ │ └── huffman.js ├── physics_solvers │ ├── verlet │ │ └── code │ │ │ ├── labview │ │ │ └── verlet_labview.png │ │ │ ├── scratch │ │ │ └── verlet_scratch.png │ │ │ ├── rust │ │ │ └── verlet.rs │ │ │ ├── javascript │ │ │ └── verlet.js │ │ │ ├── matlab │ │ │ └── verlet.m │ │ │ ├── haskell │ │ │ └── verlet.hs │ │ │ ├── julia │ │ │ └── verlet.jl │ │ │ ├── c │ │ │ └── verlet.c │ │ │ ├── java │ │ │ └── verlet.java │ │ │ ├── python │ │ │ └── verlet.py │ │ │ └── c++ │ │ │ └── verlet.cpp │ ├── physics_solvers.md │ ├── barnes_hut.md │ └── quantum │ │ └── split-op │ │ └── code │ │ └── julia │ │ └── split_op.jl ├── convolutions │ └── code │ │ ├── haskell │ │ └── convolution.hs │ │ ├── julia │ │ └── conv.jl │ │ └── c │ │ ├── fft.h │ │ └── convolutions.c ├── sorting_searching │ ├── bubble │ │ ├── code │ │ │ ├── haskell │ │ │ │ └── bubbleSort.hs │ │ │ ├── js │ │ │ │ └── bubble.js │ │ │ ├── julia │ │ │ │ └── bubble.jl │ │ │ ├── python │ │ │ │ └── bubblesort.py │ │ │ ├── swift │ │ │ │ └── bubblesort.swift │ │ │ ├── go │ │ │ │ └── bubbleSort.go │ │ │ ├── matlab │ │ │ │ └── bubblesort.m │ │ │ ├── racket │ │ │ │ └── bubbleSort.rkt │ │ │ ├── cs │ │ │ │ ├── Program.cs │ │ │ │ └── BubbleSort.cs │ │ │ ├── d │ │ │ │ └── bubble_sort.d │ │ │ ├── java │ │ │ │ └── bubble.java │ │ │ ├── rust │ │ │ │ └── bubble_sort.rs │ │ │ ├── c │ │ │ │ └── bubble_sort.c │ │ │ └── c++ │ │ │ │ └── bubblesort.cpp │ │ └── bubble_sort.md │ ├── bogo │ │ ├── code │ │ │ ├── clojure │ │ │ │ └── bogo.clj │ │ │ ├── python │ │ │ │ └── bogo.py │ │ │ ├── julia │ │ │ │ └── bogo.jl │ │ │ ├── js │ │ │ │ └── bogo.js │ │ │ ├── rust │ │ │ │ └── bogosort.rs │ │ │ ├── matlab │ │ │ │ └── bogosort.m │ │ │ ├── cs │ │ │ │ ├── Program.cs │ │ │ │ └── BogoSort.cs │ │ │ ├── swift │ │ │ │ └── bogosort.swift │ │ │ ├── haskell │ │ │ │ └── bogoSort.hs │ │ │ ├── c │ │ │ │ └── bogo_sort.c │ │ │ ├── c++ │ │ │ │ └── bogosort.cpp │ │ │ └── java │ │ │ │ └── bogo.java │ │ └── bogo_sort.md │ └── sorting_searching.md ├── decision_problems │ ├── stable_marriage │ │ ├── code │ │ │ ├── cs │ │ │ │ ├── ListExtensions.cs │ │ │ │ ├── GaleShapleyAlgorithm.cs │ │ │ │ ├── Person.cs │ │ │ │ └── Program.cs │ │ │ ├── haskell │ │ │ │ └── stableMarriage.hs │ │ │ ├── javascript │ │ │ │ └── stable-marriage.js │ │ │ └── julia │ │ │ │ └── stable_marriage.jl │ │ └── stable_marriage.md │ └── decision_problems.md ├── matrix_methods │ ├── thomas │ │ ├── code │ │ │ └── julia │ │ │ │ └── thomas.jl │ │ └── thomas.md │ ├── matrix_methods.md │ └── gaussian_elimination │ │ └── code │ │ └── julia │ │ └── gaussian_elimination.jl ├── math.md ├── differential_equations.md ├── computational_geometry │ ├── gift_wrapping │ │ ├── chan │ │ │ └── chans.md │ │ ├── jarvis_march │ │ │ ├── code │ │ │ │ ├── haskell │ │ │ │ │ └── jarvisMarch.hs │ │ │ │ ├── javascript │ │ │ │ │ └── jarvis-march.js │ │ │ │ ├── cs │ │ │ │ │ ├── Program.cs │ │ │ │ │ └── JarvisMarch.cs │ │ │ │ ├── julia │ │ │ │ │ └── jarvis.jl │ │ │ │ ├── c │ │ │ │ │ └── jarvis_march.c │ │ │ │ └── jarvis.jl │ │ │ └── jarvis_march.md │ │ ├── graham_scan │ │ │ └── code │ │ │ │ ├── haskell │ │ │ │ └── grahamScan.hs │ │ │ │ ├── javascript │ │ │ │ └── graham-scan.js │ │ │ │ ├── julia │ │ │ │ └── graham.jl │ │ │ │ └── c │ │ │ │ └── graham.c │ │ └── gift_wrapping.md │ └── computational_geometry.md ├── multiplication │ └── multiplication.md └── QI │ └── QI.md ├── .clang-format ├── CONTRIBUTORS.md ├── styles └── website.css ├── book_ace.json ├── literature.bib ├── update_site.sh ├── LICENSE.md ├── .editorconfig ├── book.json ├── README.md └── TODO.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Force all text files to have LF line endings 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /chapters/principles_of_code/choosing_a_language/compiled/makefiles.md: -------------------------------------------------------------------------------- 1 | ## Makefiles 2 | 3 | COMING SOON! 4 | -------------------------------------------------------------------------------- /chapters/FFT/res/fft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/FFT/res/fft.png -------------------------------------------------------------------------------- /chapters/FFT/res/sinusoid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/FFT/res/sinusoid.png -------------------------------------------------------------------------------- /chapters/FFT/res/FT_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/FFT/res/FT_example.png -------------------------------------------------------------------------------- /chapters/monte_carlo/res/31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/monte_carlo/res/31.png -------------------------------------------------------------------------------- /chapters/taylor/function_sum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/taylor/function_sum.png -------------------------------------------------------------------------------- /chapters/FFT/res/radix-2screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/FFT/res/radix-2screen.jpg -------------------------------------------------------------------------------- /chapters/FFT/res/radix-8screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/FFT/res/radix-8screen.jpg -------------------------------------------------------------------------------- /chapters/monte_carlo/res/13311.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/monte_carlo/res/13311.png -------------------------------------------------------------------------------- /chapters/codeblock.txt: -------------------------------------------------------------------------------- 1 | {% method %} 2 | {% sample lang="jl" %} 3 | [import:1-17, lang:"julia"](code/julia/conv.jl) 4 | {% endmethod %} 5 | 6 | -------------------------------------------------------------------------------- /chapters/monte_carlo/res/195583.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/monte_carlo/res/195583.png -------------------------------------------------------------------------------- /chapters/principles_of_code/clone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/principles_of_code/clone.png -------------------------------------------------------------------------------- /chapters/principles_of_code/fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/principles_of_code/fork.png -------------------------------------------------------------------------------- /chapters/FFT/res/butterfly_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/FFT/res/butterfly_diagram.png -------------------------------------------------------------------------------- /chapters/principles_of_code/choosing_a_language/compiled/FORTRAN.md: -------------------------------------------------------------------------------- 1 | ### FORTRAN 2 | 3 | Alright, so here's the thing about Fortran. It's old. 4 | -------------------------------------------------------------------------------- /chapters/tree_traversal/res/3-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/tree_traversal/res/3-tree.png -------------------------------------------------------------------------------- /chapters/tree_traversal/res/DFS_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/tree_traversal/res/DFS_in.png -------------------------------------------------------------------------------- /chapters/tree_traversal/res/DFS_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/tree_traversal/res/DFS_pre.png -------------------------------------------------------------------------------- /chapters/monte_carlo/res/monte_carlo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/monte_carlo/res/monte_carlo.gif -------------------------------------------------------------------------------- /chapters/monte_carlo/res/square_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/monte_carlo/res/square_circle.png -------------------------------------------------------------------------------- /chapters/tree_traversal/res/BFS_simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/tree_traversal/res/BFS_simple.png -------------------------------------------------------------------------------- /chapters/tree_traversal/res/DFS_post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/tree_traversal/res/DFS_post.png -------------------------------------------------------------------------------- /chapters/FFT/res/radix-2screen_positive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/FFT/res/radix-2screen_positive.jpg -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/res/modulus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/euclidean_algorithm/res/modulus.png -------------------------------------------------------------------------------- /chapters/tree_traversal/res/binary_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/tree_traversal/res/binary_tree.png -------------------------------------------------------------------------------- /chapters/principles_of_code/notation/cplot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/principles_of_code/notation/cplot.png -------------------------------------------------------------------------------- /chapters/differential_equations/runge_kutta/runge_kutta.md: -------------------------------------------------------------------------------- 1 | ##### Dependencies 2 | * [Euler Methods](euler.md) 3 | 4 | # Runge Kutta Methods 5 | 6 | COMING SOON! 7 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/res/subtraction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/euclidean_algorithm/res/subtraction.png -------------------------------------------------------------------------------- /chapters/differential_equations/euler/res/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/differential_equations/euler/res/error.png -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/and.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/principles_of_code/building_blocks/and.jpg -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/nand.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/principles_of_code/building_blocks/nand.jpg -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/nor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/principles_of_code/building_blocks/nor.jpg -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/not.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/principles_of_code/building_blocks/not.jpg -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/or.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/principles_of_code/building_blocks/or.jpg -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/xor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/principles_of_code/building_blocks/xor.jpg -------------------------------------------------------------------------------- /chapters/data_compression/huffman/res/huffman_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/data_compression/huffman/res/huffman_tree.png -------------------------------------------------------------------------------- /chapters/tree_traversal/code/scratch/scratch_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/tree_traversal/code/scratch/scratch_tree.png -------------------------------------------------------------------------------- /chapters/differential_equations/euler/res/instability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/differential_equations/euler/res/instability.png -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/labview/verlet_labview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/physics_solvers/verlet/code/labview/verlet_labview.png -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/scratch/verlet_scratch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/algorithm-archive/master/chapters/physics_solvers/verlet/code/scratch/verlet_scratch.png -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | 3 | AlignAfterOpenBracket: AlwaysBreak 4 | AlwaysBreakTemplateDeclarations: true 5 | BinPackArguments: false 6 | BinPackParameters: false 7 | PointerAlignment: Left 8 | -------------------------------------------------------------------------------- /chapters/convolutions/code/haskell/convolution.hs: -------------------------------------------------------------------------------- 1 | import Data.List (tails) 2 | 3 | convolution :: (Num a) => [a] -> [a] -> [a] 4 | convolution x = map (sum . zipWith (*) (reverse x)) . spread 5 | where spread = init . tails . (replicate (length x - 1) 0 ++) 6 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/haskell/bubbleSort.hs: -------------------------------------------------------------------------------- 1 | bubbleSort :: (Ord a) => [a] -> [a] 2 | bubbleSort x = (!!length x) $ iterate bubble x 3 | where bubble (x:y:r) 4 | | x <= y = x : bubble (y:r) 5 | | otherwise = y : bubble (x:r) 6 | bubble x = x 7 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | James Schloss 2 | Nicole Mazzuca 3 | Marius Becker 4 | Gathros 5 | Jeremie Gillet (- Jie -) 6 | Salim Khatib 7 | Hitesh C 8 | Shaurya 9 | Maxime Dherbécourt 10 | Jess 3Jane 11 | Pen Pal 12 | Chinmaya Mahesh 13 | Unlambder 14 | Kjetil Johannessen 15 | CDsigma 16 | DominikRafacz 17 | -------------------------------------------------------------------------------- /styles/website.css: -------------------------------------------------------------------------------- 1 | .book .book-body .page-wrapper .page-inner section.normal .hljs-meta-keyword { 2 | color: #8959a8; 3 | } 4 | 5 | .book .book-body .page-wrapper .page-inner section.normal .hljs-meta-string { 6 | color: #718c00; 7 | } 8 | 9 | .book .book-body .page-wrapper { 10 | margin-bottom: 12em; 11 | } 12 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/js/bubble.js: -------------------------------------------------------------------------------- 1 | function bubbleSort(arr) { 2 | for (let r = arr.length -1; r > 0; r--) { 3 | for (let i = 0; i < r; i++) { 4 | if (arr[i] > arr[i + 1]) { 5 | let tmp = arr[i]; 6 | arr[i] = arr[i + 1]; 7 | arr[i + 1] = tmp; 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapters/differential_equations/differential_equations.md: -------------------------------------------------------------------------------- 1 | ### Differential Equations 2 | 3 | Differential equations lie at the heart of many different systems in physics, economics, biology, chemistry, and many other areas of research and engineering. 4 | Here, we discuss many different methods to solve particular sets of differential equations. 5 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/clojure/bogo.clj: -------------------------------------------------------------------------------- 1 | ;; earthfail 2 | (defn is-sorted [col func] 3 | "return true of col is sorted in respect to func role 4 | like <,>,<=,>=" 5 | (apply func col)) 6 | 7 | (defn bogo-sort [col func] 8 | "shuffle the collection untill it is sorted" 9 | (if (is-sorted col func) 10 | col 11 | (shuffle col))) 12 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/java/MainClass.java: -------------------------------------------------------------------------------- 1 | //submitted by lolatomroflsinnlos, modified by xam4lor 2 | public class MainClass { 3 | public static void main(String[] args) { 4 | System.out.println("Euclidean Algorithm :"); 5 | System.out.println(EuclideanAlgo.euclidMod(64 * 67, 64 * 81)); 6 | System.out.println(EuclideanAlgo.euclidSub(128 * 12, 128 * 77) + "\n"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/python/bogo.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | def is_sorted(a): 5 | for i in range(len(a)-1): 6 | if a[i+1] < a[i]: 7 | return False 8 | return True 9 | 10 | def bogo_sort(a): 11 | while not is_sorted(a): 12 | random.shuffle(a) 13 | 14 | def main(): 15 | a = [1., 3, 2, 4] 16 | bogo_sort(a) 17 | print(a) 18 | 19 | main() 20 | 21 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/julia/bubble.jl: -------------------------------------------------------------------------------- 1 | function bubble_sort(a::Vector{Float64}) 2 | n = length(a) 3 | for i = 1:n 4 | for j = 1:n-1 5 | if(a[j] < a[j+1]) 6 | a[j], a[j+1] = a[j+1], a[j] 7 | end 8 | end 9 | end 10 | end 11 | 12 | 13 | function main() 14 | a = [1., 3, 2, 4, 5, 10, 50, 7, 1.5, 0.3] 15 | bubble_sort(a) 16 | println(a) 17 | end 18 | 19 | main() 20 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/julia/bogo.jl: -------------------------------------------------------------------------------- 1 | function is_sorted(a::Vector{Float64}) 2 | for i = 1:length(a)-1 3 | if (a[i+1] > a[i]) 4 | return false 5 | end 6 | end 7 | return true 8 | end 9 | 10 | function bogo_sort(a::Vector{Float64}) 11 | while(!is_sorted(a)) 12 | shuffle!(a) 13 | end 14 | end 15 | 16 | function main() 17 | a = [1., 3, 2,4] 18 | bogo_sort(a) 19 | println(a) 20 | end 21 | 22 | main() 23 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/clojure/euclidean_example.clj: -------------------------------------------------------------------------------- 1 | ;; earthfail 2 | (defn euclid-sub [a b] 3 | (loop [i (Math/abs a) j (Math/abs b)] 4 | (if (= i j) 5 | i 6 | (if (> i j) 7 | (recur (- i j) j) 8 | (recur i (- j i)))))) 9 | (defn euclid-mod [a b] 10 | (loop [i (Math/abs a) j (Math/abs b)] 11 | (if (zero? j) 12 | i 13 | (recur j (% i j))))) 14 | 15 | (print 16 | (euclid-sub (* 64 67) 17 | (* 64 81)) 18 | (euclid-mod (* 128 12) 19 | (* 128 77))) 20 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/python/euclidean_example.py: -------------------------------------------------------------------------------- 1 | def euclid_mod(a, b): 2 | 3 | a = abs(a) 4 | b = abs(b) 5 | 6 | while b > 0: 7 | a, b = b, a % b 8 | 9 | return a 10 | 11 | def euclid_sub(a, b): 12 | 13 | a = abs(a) 14 | b = abs(b) 15 | 16 | while a != b: 17 | if a > b: 18 | a = a - b 19 | else: 20 | b = b - a 21 | 22 | return a 23 | 24 | def main(): 25 | print(euclid_mod(64 * 67, 64 * 81)) 26 | print(euclid_sub(128 * 12, 128 * 77)) 27 | 28 | main() 29 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/python/bubblesort.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | def bubble_sort(array): 5 | len_array = len(array) 6 | for i in range(len_array): 7 | for j in range(len_array - i - 1): 8 | if(array[j] > array[j+1]): 9 | array[j], array[j+1] = array[j+1], array[j] #swap elements in the list 10 | 11 | def main(): 12 | number = [random.randint(0, 1000) for _ in range(10)] 13 | print("Before Sorting {}".format(number)) 14 | bubble_sort(number) 15 | print("After Sorting {}".format(number)) 16 | 17 | main() 18 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/pseudo/euclidean.pseudo: -------------------------------------------------------------------------------- 1 | # This has not been implemented in your chosen language, so here's pseudocode 2 | function euclid_sub(Int a, Int b){ 3 | while (a != b){ 4 | if (a > b){ 5 | a = a - b 6 | } 7 | else 8 | b = b - a 9 | } 10 | } 11 | } 12 | 13 | # This has not been implemented in your chosen language, so here's pseudocode 14 | function euclid_mod(Int a, Int b){ 15 | Int temp 16 | while (b != 0){ 17 | temp = b 18 | b = a%b 19 | a = temp 20 | } 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /chapters/monte_carlo/code/haskell/monteCarlo.hs: -------------------------------------------------------------------------------- 1 | import System.Random 2 | 3 | monteCarloPi :: RandomGen g => g -> Int -> Float 4 | monteCarloPi g n = count $ filter inCircle $ makePairs 5 | where makePairs = take n $ toPair (randomRs (0, 1) g :: [Float]) 6 | toPair (x:y:rest) = (x, y) : toPair rest 7 | inCircle (x, y) = x^2 + y^2 < 1 8 | count l = 4 * fromIntegral (length l) / fromIntegral n 9 | 10 | main = do 11 | g <- newStdGen 12 | let p = monteCarloPi g 100000 13 | putStrLn $ "Estimated pi: " ++ show p 14 | putStrLn $ "Percent error: " ++ show (100 * abs (pi - p) / pi) 15 | -------------------------------------------------------------------------------- /chapters/convolutions/code/julia/conv.jl: -------------------------------------------------------------------------------- 1 | function conv(signal1::Vector{Complex}, signal2::Vector{Complex}) 2 | n = length(signal1) + length(signal2) 3 | out = Vector{Complex}(n) 4 | sum = 0 5 | 6 | for i = 0:n 7 | for j = 0:i 8 | if(j < length(signal1)) 9 | sum += signal1[j] * signal2[i-j] 10 | end 11 | end 12 | out[i] = sum 13 | sum = 0 14 | end 15 | 16 | return out 17 | end 18 | 19 | function conv_fft(signal1::Vector{Complex}, signal2::Vector{Complex}) 20 | return ifft(fft(signal1).*fft(signal2)) 21 | end 22 | 23 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/js/bogo.js: -------------------------------------------------------------------------------- 1 | function isSorted(arr) { 2 | for (let i = 0; i < arr.length - 1; i++) { 3 | if (arr[i] > arr[i + 1]) { 4 | return false; 5 | } 6 | } 7 | 8 | return true; 9 | } 10 | 11 | // The shuffle() function can be found in code/js/bogo.js 12 | function bogoSort(arr) { 13 | while (!isSorted(arr)) { 14 | shuffle(arr); 15 | } 16 | } 17 | 18 | function shuffle(arr) { 19 | for (let r = arr.length -1; r > 0; r--) { 20 | let i = Math.floor(Math.random() * r); 21 | let tmp = arr[i]; 22 | arr[i] = arr[r]; 23 | arr[r] = tmp; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /chapters/decision_problems/stable_marriage/code/cs/ListExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace StableMarriageProblem 5 | { 6 | public static class ListExtensions 7 | { 8 | public static IList Shuffle(this IList list, Random rng) 9 | { 10 | for (var i = 0; i < list.Count; i++) 11 | { 12 | var j = rng.Next(i, list.Count); 13 | var tmp = list[i]; 14 | list[i] = list[j]; 15 | list[j] = tmp; 16 | } 17 | return list; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/swift/bubblesort.swift: -------------------------------------------------------------------------------- 1 | func bubbleSort(sortArray: inout [Int]) -> [Int] { 2 | 3 | for i in (1.. sortArray[j+1] { 6 | let temp = sortArray[j] 7 | sortArray[j] = sortArray[j + 1] 8 | sortArray[j + 1] = temp 9 | } 10 | } 11 | } 12 | 13 | return sortArray 14 | } 15 | 16 | func main() { 17 | var testArray = [4,5,123,759,-132,8940,24,34,-5] 18 | print(bubbleSort(sortArray: &testArray)) 19 | } 20 | 21 | main() 22 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/cs/Program.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) 2 | using System; 3 | 4 | namespace EuclideanAlgorithm 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | Console.WriteLine("EuclideanAlgorithm"); 11 | var euclideanAlgorithm = new EuclideanAlgorithm(); 12 | int check = euclideanAlgorithm.EuclidMod(64 * 67, 64 * 81); 13 | int check2 = euclideanAlgorithm.EuclidSub(128 * 12, 128 * 77); 14 | 15 | Console.WriteLine(check); 16 | Console.WriteLine(check2); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/ocaml/euclidean_example.ml: -------------------------------------------------------------------------------- 1 | (* contributed by Nicole Mazzuca (ubsan) *) 2 | 3 | let euclid_mod a b = 4 | let rec inner a = function 5 | | 0 -> a 6 | | b -> inner b (a mod b) 7 | in (inner (abs a) (abs b)) 8 | 9 | let euclid_sub a b = 10 | let rec inner a b = 11 | if a = b then 12 | a 13 | else if a < b then 14 | inner a (b - a) 15 | else 16 | inner (a - b) b 17 | in (inner (abs a) (abs b)) 18 | 19 | let chk1 = euclid_mod (64 * 67) (64 * 81) 20 | let chk2 = euclid_sub (128 * 12) (128 * 77) 21 | let () = 22 | chk1 |> print_int |> print_newline; 23 | chk2 |> print_int |> print_newline 24 | 25 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/javascript/euclidean_example.js: -------------------------------------------------------------------------------- 1 | function euclid_mod(a, b){ 2 | a = Math.abs(a); 3 | b = Math.abs(b); 4 | 5 | var temp; 6 | while (b != 0){ 7 | temp = b; 8 | b = a%b; 9 | a = temp; 10 | } 11 | 12 | return a; 13 | } 14 | 15 | function euclid_sub(a, b){ 16 | a = Math.abs(a); 17 | b = Math.abs(b); 18 | 19 | while (a != b){ 20 | if (a > b){ 21 | a = a - b; 22 | } 23 | else{ 24 | b = b - a; 25 | } 26 | } 27 | 28 | return a; 29 | } 30 | 31 | console.log(euclid_mod(64*67, 64*81)); 32 | console.log(euclid_sub(128*12, 128*77)); 33 | -------------------------------------------------------------------------------- /chapters/matrix_methods/thomas/code/julia/thomas.jl: -------------------------------------------------------------------------------- 1 | function(a::Vector{Float64}, b::Vector{Float64}, c::Vector{Float64}, 2 | d::Vector{Float64}, soln::Vector{Float64}) 3 | # Setting initial elements 4 | c[0] = c[0] / b[0] 5 | d[0] = d[0] / b[0] 6 | 7 | for i = 1:n 8 | # Scale factor is for c and d 9 | scale = 1 / (b[i] - c[i-1]*a[i]) 10 | c[i] = c[i] * scale 11 | d[i] = (d[i] - a[i] * d[i-1]) * scale 12 | end 13 | 14 | # Set the last solution for back-substitution 15 | soln[n-1] = d[n-1] 16 | 17 | # Back-substitution 18 | for i = n-2:0 19 | soln[i] = d[i] - c[i] * soln[i+1] 20 | end 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/rust/bogosort.rs: -------------------------------------------------------------------------------- 1 | // Submitted by jess 3jane 2 | 3 | extern crate rand; 4 | 5 | use rand::{thread_rng, Rng}; 6 | 7 | fn is_sorted(arr : &[i32]) -> bool { 8 | for i in 1..arr.len() { 9 | if arr[i-1] > arr[i] { 10 | return false; 11 | } 12 | } 13 | true 14 | } 15 | 16 | fn bogo_sort(arr : &mut [i32]) { 17 | while !is_sorted(arr) { 18 | thread_rng().shuffle(arr); 19 | } 20 | } 21 | 22 | fn main() { 23 | let mut v = vec![1, 2, 3, 4, 5]; 24 | thread_rng().shuffle(&mut v); 25 | println!("Original array: {:?}", v); 26 | bogo_sort(&mut v); 27 | println!("Sorted array: {:?}", v); 28 | } 29 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/go/bubbleSort.go: -------------------------------------------------------------------------------- 1 | // Submitted by Chinmaya Mahesh (chin123) 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func bubbleSort(array []int) { 8 | n := len(array) 9 | for i := 0; i < n-1; i++ { 10 | swapped := false 11 | for j := 0; j < n-i-1; j++ { 12 | if array[j] > array[j+1] { 13 | array[j], array[j+1] = array[j+1], array[j] 14 | swapped = true 15 | } 16 | } 17 | if !swapped { 18 | break 19 | } 20 | } 21 | } 22 | 23 | func main() { 24 | array := [10]int{1, 45, 756, 4569, 56, 3, 8, 5, -10, -4} 25 | fmt.Println("Unsorted array:", array) 26 | 27 | bubbleSort(array[:]) 28 | 29 | fmt.Println("Sorted array:", array) 30 | } 31 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/matlab/bubblesort.m: -------------------------------------------------------------------------------- 1 | function main() 2 | array = floor( rand(1,7)*100 ); 3 | disp('Before Sorting:') 4 | disp(array) 5 | 6 | array = bubble_sort(array); 7 | disp('After Sorting') 8 | disp(array) 9 | end 10 | 11 | function sorted_array = bubble_sort(array) 12 | for i=1:length(array) 13 | for j=1:length(array)-i 14 | if array(j) > array(j+1) 15 | % swap elements in the list 16 | temp = array(j); 17 | array(j) = array(j+1); 18 | array(j+1) = temp; 19 | end 20 | end 21 | end 22 | sorted_array = array 23 | end 24 | 25 | 26 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/java/EuclideanAlgo.java: -------------------------------------------------------------------------------- 1 | // submitted by lolatomroflsinnlos, modified by xam4lor 2 | public class EuclideanAlgo { 3 | public static int euclidSub(int a, int b) { 4 | a = Math.abs(a); 5 | b = Math.abs(b); 6 | 7 | while (a != b) { 8 | if (a > b) { 9 | a -= b; 10 | } else { 11 | b -= a; 12 | } 13 | } 14 | 15 | return a; 16 | } 17 | 18 | public static int euclidMod(int a, int b) { 19 | while (b != 0) { 20 | int tmp = b; 21 | b = a % b; 22 | a = tmp; 23 | } 24 | 25 | return a; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/haskell/euclidean_example.hs: -------------------------------------------------------------------------------- 1 | -- contributed by Nicole Mazzuca (ubsan) 2 | 3 | euclidSub :: Integer -> Integer -> Integer 4 | euclidSub a b = inner (abs a) (abs b) where 5 | inner a b = 6 | if a == b then 7 | a 8 | else if a < b then 9 | euclidSub a (b - a) 10 | else 11 | euclidSub (a - b) b 12 | 13 | euclidMod :: Integer -> Integer -> Integer 14 | euclidMod a b = inner (abs a) (abs b) where 15 | inner a 0 = a 16 | inner a b = inner b (a `mod` b) 17 | 18 | main :: IO () 19 | main = do 20 | let chk1 = euclidMod (64 * 67) (64 * 81) 21 | chk2 = euclidSub (128 * 12) (128 * 77) 22 | putStrLn (show chk1) 23 | putStrLn (show chk2) 24 | return () 25 | 26 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/go/euclidean.go: -------------------------------------------------------------------------------- 1 | // Submitted by Chinmaya Mahesh (chin123) 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func abs(a int) int { 8 | if a < 0 { 9 | a = -a 10 | } 11 | return a 12 | } 13 | 14 | func euclidMod(a, b int) int { 15 | a = abs(a) 16 | b = abs(b) 17 | 18 | for b != 0 { 19 | a, b = b, a%b 20 | } 21 | 22 | return a 23 | } 24 | 25 | func euclidSub(a, b int) int { 26 | a = abs(a) 27 | b = abs(b) 28 | 29 | for a != b { 30 | if a > b { 31 | a -= b 32 | } else { 33 | b -= a 34 | } 35 | } 36 | 37 | return a 38 | } 39 | 40 | func main() { 41 | check1 := euclidMod(64*67, 64*81) 42 | check2 := euclidSub(128*12, 128*77) 43 | 44 | fmt.Println(check1) 45 | fmt.Println(check2) 46 | } 47 | -------------------------------------------------------------------------------- /chapters/monte_carlo/code/rust/monte_carlo.rs: -------------------------------------------------------------------------------- 1 | // Submitted by jess 3jane 2 | 3 | extern crate rand; 4 | 5 | use std::f64::consts::PI; 6 | 7 | fn in_circle(x: f64, y: f64, radius: f64) -> bool { 8 | x * x + y * y < radius * radius 9 | } 10 | 11 | fn monte_carlo(n: i64) -> f64 { 12 | let mut count = 0; 13 | 14 | for _ in 0..n { 15 | let x = rand::random(); 16 | let y = rand::random(); 17 | if in_circle(x, y, 1.0) { 18 | count += 1; 19 | } 20 | } 21 | 22 | // return our pi estimate 23 | (4 * count) as f64 / n as f64 24 | } 25 | 26 | fn main() { 27 | let pi_estimate = monte_carlo(10000000); 28 | 29 | println!("Percent error is {:.3}%", (100.0 * (PI - pi_estimate) / PI)); 30 | } 31 | -------------------------------------------------------------------------------- /book_ace.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "plugins": ["mathjax", "bibtex-cite", "creativecommons", "wordcount", "theme-api", "include-codeblock", "ace"], 4 | "lunr": { 5 | "maxIndexSize": 1000000000 6 | }, 7 | "pluginsConfig": { 8 | "theme-api": { 9 | "languages": [ 10 | { 11 | "lang": "pseudo", 12 | "name": "Pseudocode", 13 | "default": true 14 | }, 15 | { 16 | "lang": "jl", 17 | "name": "julia" 18 | }, 19 | { 20 | "lang": "cs", 21 | "name": "C#" 22 | }, 23 | { 24 | "lang": "c", 25 | "name": "C" 26 | } 27 | ], 28 | "split": true 29 | }, 30 | "include-codeblock": { 31 | "template": "ace", 32 | "unindent": true, 33 | "theme": "coffee" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /chapters/math.md: -------------------------------------------------------------------------------- 1 | 4 | $$ 5 | \newcommand{\d}{\mathrm{d}} 6 | \newcommand{\bff}{\boldsymbol{f}} 7 | \newcommand{\bfg}{\boldsymbol{g}} 8 | \newcommand{\bfp}{\boldsymbol{p}} 9 | \newcommand{\bfq}{\boldsymbol{q}} 10 | \newcommand{\bfx}{\boldsymbol{x}} 11 | \newcommand{\bfu}{\boldsymbol{u}} 12 | \newcommand{\bfv}{\boldsymbol{v}} 13 | \newcommand{\bfA}{\boldsymbol{A}} 14 | \newcommand{\bfB}{\boldsymbol{B}} 15 | \newcommand{\bfC}{\boldsymbol{C}} 16 | \newcommand{\bfM}{\boldsymbol{M}} 17 | \newcommand{\bfJ}{\boldsymbol{J}} 18 | \newcommand{\bfR}{\boldsymbol{R}} 19 | \newcommand{\bfT}{\boldsymbol{T}} 20 | \newcommand{\bfomega}{\boldsymbol{\omega}} 21 | \newcommand{\bftau}{\boldsymbol{\tau}} 22 | $$ 23 | 24 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/matlab/bogosort.m: -------------------------------------------------------------------------------- 1 | function main() 2 | array = floor( rand(1,7)*100 ); 3 | disp('Before Sorting:') 4 | disp(array) 5 | 6 | array = bogo_sort(array); 7 | disp('After Sorting') 8 | disp(array) 9 | end 10 | 11 | function retval = is_sorted(array) 12 | for i=1:length(array)-1 13 | if array(i) > array(i+1) 14 | retval = false; 15 | return 16 | end 17 | end 18 | retval = true; 19 | end 20 | 21 | function sorted_array = bogo_sort(array) 22 | while ~is_sorted(array) 23 | % create a list of random permutation indices 24 | i = randperm(length(array)); 25 | array = array(i); 26 | end 27 | sorted_array = array; 28 | end 29 | 30 | 31 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/racket/bubbleSort.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (provide bubbleSort) 4 | 5 | 6 | (define bubbleSort 7 | (case-lambda [(l) (bubbleSort l (length l))] 8 | [(l n) (if (= n 1) 9 | l 10 | (bubbleSort (pass l 0 n) (- n 1)))])) 11 | 12 | ; a single pass, if this is the nth pass, then we know that the (n - 1) last elements are already sorted 13 | (define (pass l counter n) 14 | (let ([x (first l)] 15 | [y (second l)] 16 | [r (drop l 2)]) 17 | (cond [(= (- n counter) 2) (cons (min x y) (cons (max x y) r))] 18 | [(cons (min x y) (pass (cons (max x y) r) (+ counter 1) n))]))) 19 | 20 | 21 | ((lambda (x) (display (bubbleSort x))) (read)) 22 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/rust/euclidean_example.rs: -------------------------------------------------------------------------------- 1 | // contributed by Nicole Mazzuca (ubsan) 2 | 3 | fn euclid_sub(mut a: i64, mut b: i64) -> i64 { 4 | a = a.abs(); 5 | b = b.abs(); 6 | while a != b { 7 | if a < b { 8 | b -= a; 9 | } else { 10 | a -= b; 11 | } 12 | } 13 | 14 | a 15 | } 16 | 17 | fn euclid_rem(mut a: i64, mut b: i64) -> i64 { 18 | a = a.abs(); 19 | b = b.abs(); 20 | while b != 0 { 21 | let tmp = b; 22 | b = a % b; 23 | a = tmp; 24 | } 25 | 26 | a 27 | } 28 | 29 | fn main() { 30 | let chk1 = euclid_rem(64 * 67, 64 * 81); 31 | let chk2 = euclid_sub(128 * 12, 128 * 77); 32 | println!("{}", chk1); 33 | println!("{}", chk2); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /chapters/differential_equations/euler/code/elm/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "CallumJHays/elm-sliders": "1.0.1 <= v < 2.0.0", 12 | "elm-lang/core": "5.1.1 <= v < 6.0.0", 13 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/mouse": "1.0.1 <= v < 2.0.0", 15 | "elm-lang/svg": "2.0.0 <= v < 3.0.0", 16 | "elm-lang/window": "1.0.1 <= v < 2.0.0", 17 | "rtfeldman/hex": "1.0.0 <= v < 2.0.0" 18 | }, 19 | "elm-version": "0.18.0 <= v < 0.19.0" 20 | } 21 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/c/euclidean_example.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int euclid_mod(int a, int b) { 5 | a = abs(a); 6 | b = abs(b); 7 | 8 | while (b != 0) { 9 | int temp = b; 10 | b = a % b; 11 | a = temp; 12 | } 13 | 14 | return a; 15 | } 16 | 17 | int euclid_sub(int a, int b) { 18 | a = abs(a); 19 | b = abs(b); 20 | 21 | while (a != b) { 22 | if (a > b) { 23 | a -= b; 24 | } else { 25 | b -= a; 26 | } 27 | } 28 | 29 | return a; 30 | } 31 | 32 | int main() { 33 | int check1 = euclid_mod(64 * 67, 64 * 81); 34 | int check2 = euclid_sub(128 * 12, 128 * 77); 35 | 36 | printf("%d\n", check1); 37 | printf("%d\n", check2); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /chapters/differential_equations.md: -------------------------------------------------------------------------------- 1 | 4 | $$ 5 | \newcommand{\d}{\mathrm{d}} 6 | \newcommand{\bff}{\boldsymbol{f}} 7 | \newcommand{\bfg}{\boldsymbol{g}} 8 | \newcommand{\bfp}{\boldsymbol{p}} 9 | \newcommand{\bfq}{\boldsymbol{q}} 10 | \newcommand{\bfx}{\boldsymbol{x}} 11 | \newcommand{\bfu}{\boldsymbol{u}} 12 | \newcommand{\bfv}{\boldsymbol{v}} 13 | \newcommand{\bfA}{\boldsymbol{A}} 14 | \newcommand{\bfB}{\boldsymbol{B}} 15 | \newcommand{\bfC}{\boldsymbol{C}} 16 | \newcommand{\bfM}{\boldsymbol{M}} 17 | \newcommand{\bfJ}{\boldsymbol{J}} 18 | \newcommand{\bfR}{\boldsymbol{R}} 19 | \newcommand{\bfT}{\boldsymbol{T}} 20 | \newcommand{\bfomega}{\boldsymbol{\omega}} 21 | \newcommand{\bftau}{\boldsymbol{\tau}} 22 | $$ 23 | 24 | # Differential Equations 25 | 26 | MORE TO COME! 27 | -------------------------------------------------------------------------------- /chapters/monte_carlo/code/go/monteCarlo.go: -------------------------------------------------------------------------------- 1 | // Submitted by Chinmaya Mahesh (chin123) 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "math" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | func inCircle(x, y float64) bool { 13 | return x*x+y*y < 1.0 // the radius of an unit circle is 1.0 14 | } 15 | 16 | func monteCarlo(samples int) { 17 | count := 0 18 | s := rand.NewSource(time.Now().UnixNano()) 19 | r := rand.New(s) 20 | 21 | for i := 0; i < samples; i++ { 22 | x, y := r.Float64(), r.Float64() 23 | 24 | if inCircle(x, y) { 25 | count += 1 26 | } 27 | } 28 | 29 | estimate := 4.0 * float64(count) / float64(samples) 30 | 31 | fmt.Println("The estimate of pi is", estimate) 32 | fmt.Printf("Which has an error of %f%%\n", 100*math.Abs(math.Pi-estimate)/math.Pi) 33 | } 34 | 35 | func main() { 36 | monteCarlo(10000000) 37 | } 38 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/cs/Program.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace BogoSort 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | Console.WriteLine("BogoSort"); 12 | var listBogo = new List() { 1, 2, 6, 4, 9, 54, 3, 2, 7, 15 }; 13 | Console.Write("unsorted: "); 14 | foreach (var number in listBogo) 15 | Console.Write(number + " "); 16 | Console.WriteLine(); 17 | listBogo = BogoSort.RunBogoSort(listBogo); 18 | Console.Write("sorted: "); 19 | foreach (var number in listBogo) 20 | Console.Write(number + " "); 21 | Console.WriteLine(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/chan/chans.md: -------------------------------------------------------------------------------- 1 | 4 | $$ 5 | \newcommand{\d}{\mathrm{d}} 6 | \newcommand{\bff}{\boldsymbol{f}} 7 | \newcommand{\bfg}{\boldsymbol{g}} 8 | \newcommand{\bfp}{\boldsymbol{p}} 9 | \newcommand{\bfq}{\boldsymbol{q}} 10 | \newcommand{\bfx}{\boldsymbol{x}} 11 | \newcommand{\bfu}{\boldsymbol{u}} 12 | \newcommand{\bfv}{\boldsymbol{v}} 13 | \newcommand{\bfA}{\boldsymbol{A}} 14 | \newcommand{\bfB}{\boldsymbol{B}} 15 | \newcommand{\bfC}{\boldsymbol{C}} 16 | \newcommand{\bfM}{\boldsymbol{M}} 17 | \newcommand{\bfJ}{\boldsymbol{J}} 18 | \newcommand{\bfR}{\boldsymbol{R}} 19 | \newcommand{\bfT}{\boldsymbol{T}} 20 | \newcommand{\bfomega}{\boldsymbol{\omega}} 21 | \newcommand{\bftau}{\boldsymbol{\tau}} 22 | $$ 23 | 24 | # Chan's Algorithm 25 | 26 | COMING SOON! 27 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/cs/Program.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace BubbleSort 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | Console.WriteLine("BubbleSort"); 12 | var listBubble = new List() { 1, 2, 6, 4, 9, 54, 3, 2, 7, 15 }; 13 | Console.Write("unsorted: "); 14 | foreach (var number in listBubble) 15 | Console.Write(number + " "); 16 | Console.WriteLine(); 17 | listBubble = BubbleSort.RunBubbleSort(listBubble); 18 | Console.Write("sorted: "); 19 | foreach (var number in listBubble) 20 | Console.Write(number + " "); 21 | Console.WriteLine(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /chapters/monte_carlo/code/d/monte_carlo.d: -------------------------------------------------------------------------------- 1 | ///Returns true if a point (x, y) is in the circle with radius r 2 | bool inCircle(real x, real y) 3 | { 4 | return x ^^ 2 + y ^^ 2 < 1.0; 5 | } 6 | 7 | ///Calculate pi using monte carlo 8 | real monteCarloPI(ulong n) 9 | { 10 | import std.algorithm : count; 11 | import std.random : uniform01; 12 | import std.range : generate, take; 13 | import std.typecons : tuple; 14 | 15 | auto piCount = generate(() => tuple!("x", "y")(uniform01, uniform01)) 16 | .take(n) 17 | .count!(a => inCircle(a.x, a.y)); 18 | return piCount * 4.0 / n; 19 | } 20 | 21 | void main() 22 | { 23 | import std.math : abs, PI; 24 | import std.stdio : writeln; 25 | 26 | auto p = monteCarloPI(100_000); 27 | writeln("Estimated pi: ", p); 28 | writeln("Percent error: ", abs(p - PI) * 100 / PI); 29 | } 30 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/cs/BubbleSort.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace BubbleSort 6 | { 7 | public static class BubbleSort 8 | { 9 | public static List RunBubbleSort(List list) where T : IComparable 10 | { 11 | var length = list.Count; 12 | 13 | for (int i = 0; i < length; i++) 14 | { 15 | for (int j = 1; j < length; j++) 16 | { 17 | if (list[j - 1].CompareTo(list[j]) > 0) 18 | { 19 | var temp = list[j - 1]; 20 | list[j - 1] = list[j]; 21 | list[j] = temp; 22 | } 23 | } 24 | } 25 | 26 | return list; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/swift/bogosort.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | 4 | func isSorted(inputArray: [Int]) -> Bool { 5 | 6 | for i in 0.. inputArray[i+1] { 8 | return false 9 | } 10 | } 11 | 12 | return true 13 | } 14 | 15 | 16 | 17 | func shuffle(inputArray: inout [Int]) -> [Int] { 18 | 19 | var shuffledArray = [Int]() 20 | 21 | for _ in 0.. [Int] { 33 | 34 | while(!isSorted(inputArray: sortArray)) { 35 | sortArray = shuffle(inputArray: &sortArray) 36 | } 37 | 38 | return sortArray 39 | } 40 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/jarvis_march/code/haskell/jarvisMarch.hs: -------------------------------------------------------------------------------- 1 | import Data.List (sort, maximumBy) 2 | import Data.Function (on) 3 | 4 | type Point = (Double, Double) 5 | 6 | angle :: Point -> Point -> Point -> Double 7 | angle a@(xa, ya) b@(xb, yb) c@(xc, yc) 8 | | a==b || c==b = 0 9 | | theta<0 = theta+2*pi 10 | | otherwise = theta 11 | where thetaA = atan2 (ya-yb) (xa-xb) 12 | thetaC = atan2 (yc-yb) (xc-xb) 13 | theta = thetaC - thetaA 14 | 15 | jarvisMarch :: [Point] -> [Point] 16 | jarvisMarch [] = [] 17 | jarvisMarch pts = p0 : wrap (x, y-1) p0 18 | where p0@(x, y)= minimum pts 19 | wrap p1 p2 20 | | pm == p0 = [] 21 | | otherwise = pm : wrap p2 pm 22 | where pm = maximumBy (compare `on` angle p1 p2) pts 23 | 24 | main = do 25 | let pts = filter (\(x,y) -> x^2+y^2<=5^2) [(x,y)|x<-[-5..5], y<-[-5..5]] 26 | print $ jarvisMarch pts 27 | -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/c++/euclidean.cpp: -------------------------------------------------------------------------------- 1 | // originally contributed by James Schloss (Leios) 2 | // restyled by Nicole Mazzuca (ubsan) 3 | #include 4 | #include 5 | #include 6 | 7 | // Euclidean algorithm using modulus 8 | int euclid_mod(int a, int b) { 9 | a = std::abs(a); 10 | b = std::abs(b); 11 | 12 | while (b != 0) { 13 | a = std::exchange(b, a % b); 14 | } 15 | 16 | return a; 17 | } 18 | 19 | // Euclidean algorithm with subtraction 20 | int euclid_sub(int a, int b) { 21 | a = std::abs(a); 22 | b = std::abs(b); 23 | 24 | while (a != b) { 25 | if (a > b) { 26 | a -= b; 27 | } else { 28 | b -= a; 29 | } 30 | } 31 | 32 | return a; 33 | } 34 | 35 | int main() { 36 | auto check1 = euclid_mod(64 * 67, 64 * 81); 37 | auto check2 = euclid_sub(128 * 12, 128 * 77); 38 | 39 | std::cout << check1 << '\n'; 40 | std::cout << check2 << '\n'; 41 | } 42 | -------------------------------------------------------------------------------- /chapters/FFT/code/hs/fft.hs: -------------------------------------------------------------------------------- 1 | import Data.Complex 2 | import Data.Array 3 | import Data.Ratio 4 | import qualified Data.Map as M 5 | 6 | fft :: [Complex Double] -> [Complex Double] 7 | fft x = let n = length x 8 | i = 0 :+ 1 9 | w = M.fromList [(k%n, exp ((-2)*pi*i*(fromIntegral k)/(fromIntegral n)) ) | k<-[0..n-1]] 10 | arr = fft' n w (listArray (0,n-1) x) 11 | in [arr!k | k<-[0..n-1]] 12 | where 13 | fft' 1 _ x = x 14 | fft' n w x = let n2 = div n 2 15 | e = fft' n2 w (listArray (0, n2-1) [x!k | k<-[0,2..n-1]]) 16 | o = fft' n2 w (listArray (0, n2-1) [x!k | k<-[1,3..n-1]]) 17 | in array (0, n-1) $ concat [[(k, e!k + o!k * w M.!(k%n)), 18 | (k + n2, e!k - o!k * w M.!(k%n))] 19 | | k <- [0..n2-1]] 20 | 21 | main = do 22 | print $ fft [0,1,2,3] 23 | -------------------------------------------------------------------------------- /literature.bib: -------------------------------------------------------------------------------- 1 | @article{ct1965, 2 | title={An algorithm for the machine calculation of complex Fourier series}, 3 | author={Cooley, James W and Tukey, John W}, 4 | journal={Mathematics of computation}, 5 | volume={19}, 6 | number={90}, 7 | pages={297--301}, 8 | year={1965}, 9 | publisher={JSTOR} 10 | } 11 | 12 | @article{jm1973, 13 | title={On the identification of the convex hull of a finite set of points in the plane}, 14 | author={Jarvis, Ray A}, 15 | journal={Information processing letters}, 16 | volume={2}, 17 | number={1}, 18 | pages={18--21}, 19 | year={1973}, 20 | publisher={Elsevier} 21 | } 22 | 23 | @article{gs1972, 24 | title={An efficient algorithm for determining the convex hull of a finite planar set}, 25 | author={Graham, Ronald L}, 26 | journal={Information processing letters}, 27 | volume={1}, 28 | number={4}, 29 | pages={132--133}, 30 | year={1972}, 31 | publisher={Elsevier} 32 | } 33 | 34 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/haskell/bogoSort.hs: -------------------------------------------------------------------------------- 1 | import System.Random 2 | import qualified Data.Map as M 3 | import Data.Map ((!)) 4 | 5 | fisherYates :: RandomGen g => [a] -> g -> ([a], g) 6 | fisherYates a gen = shuffle 1 gen m 7 | where m = M.fromList $ zip [1..] a 8 | shuffle i g k 9 | | i == M.size m = (M.elems k, g) 10 | | otherwise = let (j, g') = randomR (i, M.size m) g 11 | k' = M.insert i (k!j) $ M.insert j (k!i) k 12 | in shuffle (i+1) g' k' 13 | 14 | isSorted :: Ord a => [a] -> Bool 15 | isSorted = all (uncurry (<=)) . (zip <*> tail) 16 | 17 | bogoSort :: (Ord a, RandomGen g) => g -> [a] -> [a] 18 | bogoSort g a = fst $ head $ 19 | filter (isSorted . fst) $ 20 | iterate (uncurry fisherYates) (a, g) 21 | 22 | main = do 23 | g <- newStdGen 24 | print $ bogoSort g [9, 4, 3, 2, 5, 8, 6, 1, 7] 25 | -------------------------------------------------------------------------------- /chapters/monte_carlo/code/c/monte_carlo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | bool in_circle(double x, double y, double radius) { 8 | return x * x + y * y < radius * radius; 9 | } 10 | 11 | void monte_carlo(int samples, double radius) { 12 | int count = 0; 13 | 14 | for (int i = 0; i < samples; ++i) { 15 | double x = (double)rand() * 2.0 / RAND_MAX - 1.0; 16 | double y = (double)rand() * 2.0 / RAND_MAX - 1.0; 17 | 18 | if (in_circle(x, y, radius)) { 19 | count += 1; 20 | } 21 | } 22 | 23 | double estimate = 4.0 * count / (samples * radius * radius); 24 | 25 | printf("The estimate of pi is %f\n", estimate); 26 | printf("Which has an error of %0.2f%\n", 100 * (M_PI - estimate) / M_PI); 27 | } 28 | 29 | int main() { 30 | srand(time(NULL)); 31 | 32 | monte_carlo(1000000, 1.0); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/building_blocks.md: -------------------------------------------------------------------------------- 1 | ## Building Blocks 2 | 3 | When it comes to programming, there are certain features that will be used again and again, so it's a good idea to mention how these features work and where they are used. 4 | This section attempts to explain anything that might confuse beginner programmers; however, it is not meant as an exhaustive list of every tool available in the coding toolbox. 5 | Instead, it's meant to provide an accessible understanding of the data structures used throughout this text and the pseudocode that will be used to express these structures. 6 | 7 | It's worth pointing out that algorithms and data stuctures almost always go hand-in-hand. 8 | There are many different ways to climb a mountain, but depending on the mountain you need to climb, you might need different tools. 9 | Similarly, many different algorithms do similar tasks; however, with the right data structures, some algorithms become much more efficient than others. 10 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/graham_scan/code/haskell/grahamScan.hs: -------------------------------------------------------------------------------- 1 | import Data.List (sortOn, minimumBy) 2 | import Data.Function (on) 3 | 4 | type Point = (Double, Double) 5 | 6 | ccw :: Point -> Point -> Point -> Double 7 | ccw (xa, ya) (xb, yb) (xc, yc) = (xb - xa) * (yc - ya) - (yb - ya) * (xc - xa) 8 | 9 | grahamScan :: [Point] -> [Point] 10 | grahamScan [] = [] 11 | grahamScan pts = wrap sortedPts [p0] 12 | where p0@(x, y)= minimumBy (compare `on` snd) pts 13 | sortedPts = sortOn (\(px, py) -> atan2 (py-y) (px-x) ) $ filter (/=p0) pts 14 | wrap [] ps = ps 15 | wrap (s:ss) [p] = wrap ss [s, p] 16 | wrap (s:ss) (p1:p2:ps) 17 | | ccw s p1 p2 > 0 = wrap (s:ss) (p2:ps) 18 | | otherwise = wrap ss (s:p1:p2:ps) 19 | 20 | main = do 21 | -- We build the set of points of integer coordinates within a circle of radius 5 22 | let pts = [(x,y) | x<-[-5..5], y<-[-5..5], x^2+y^2<=5^2] 23 | -- And extract the convex hull 24 | print $ grahamScan pts 25 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/d/bubble_sort.d: -------------------------------------------------------------------------------- 1 | import std.range : hasAssignableElements, isRandomAccessRange, hasLength; 2 | 3 | void bubbleSort(R)(ref R range) 4 | if (isRandomAccessRange!R && hasAssignableElements!R && hasLength!R) 5 | { 6 | import std.algorithm : swap; 7 | 8 | foreach (i; 0 .. range.length) { 9 | bool isSorted = true; 10 | foreach (j; 0 .. range.length - 1) 11 | if (range[j + 1] < range[j]) { 12 | swap(range[j + 1], range[j]); 13 | isSorted = false; 14 | } 15 | if (isSorted) 16 | return; 17 | } 18 | } 19 | 20 | void main() @safe 21 | { 22 | import std.stdio : writefln; 23 | import std.range : generate, take; 24 | import std.array : array; 25 | import std.random : uniform01; 26 | 27 | auto input = generate!(() => uniform01!float).take(10).array; 28 | writefln!"before sorting:\n%s"(input); 29 | bubbleSort(input); 30 | writefln!"after sorting:\n%s"(input); 31 | } 32 | -------------------------------------------------------------------------------- /chapters/data_compression/huffman/code/cs/Program.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp), thanks to gustorn for the help 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace HuffmanCoding 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | var huffmanCoding = new HuffmanCoding(); 12 | 13 | var result = huffmanCoding.Encode("bibbity bobbity"); 14 | // The bitStrings are just strings and provide no compression. Look in HuffmanCoding.cs for explanation. 15 | // Print dictionary. 16 | foreach (var entry in result.Dictionary) 17 | System.Console.WriteLine($"{entry.Key} {entry.Value}"); 18 | // Print BitString. 19 | System.Console.WriteLine($"{result.BitString} count: {result.BitString.Length}"); 20 | 21 | var originalString = huffmanCoding.Decode(result); 22 | System.Console.WriteLine(originalString); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /chapters/convolutions/code/c/fft.h: -------------------------------------------------------------------------------- 1 | #ifndef FFT_H 2 | #define FFT_H 3 | 4 | #include 5 | #include 6 | 7 | void fft(double complex *X, size_t N) { 8 | if (N >= 2) { 9 | double complex tmp [N / 2]; 10 | for (size_t i = 0; i < N / 2; ++i) { 11 | tmp[i] = X[2 * i + 1]; 12 | X[i] = X[2 * i]; 13 | } 14 | 15 | for (size_t i = 0; i < N / 2; ++i) { 16 | X[i + N / 2] = tmp[i]; 17 | } 18 | 19 | fft(X, N / 2); 20 | fft(X + N / 2, N / 2); 21 | 22 | for (size_t i = 0; i < N / 2; ++i) { 23 | X[i + N/2] = X[i] - cexp(-2.0 * I * M_PI * i / N) * X[i + N / 2]; 24 | X[i] -= (X[i + N / 2] - X[i]); 25 | } 26 | } 27 | } 28 | 29 | void ifft(double complex *x, size_t n) { 30 | for (size_t i = 0; i < n; ++i) { 31 | x[i] = conj(x[i]); 32 | } 33 | 34 | fft(x, n); 35 | 36 | for (size_t i = 0; i < n; ++i) { 37 | x[i] = conj(x[i]) / n; 38 | } 39 | } 40 | 41 | #endif //FFT_H 42 | -------------------------------------------------------------------------------- /chapters/monte_carlo/code/julia/monte_carlo.jl: -------------------------------------------------------------------------------- 1 | # function to determine whether an x, y point is in the unit circle 2 | function in_circle(x_pos::Float64, y_pos::Float64) 3 | 4 | # Setting radius to 1 for unit circle 5 | radius = 1 6 | return x_pos^2 + y_pos^2 < radius^2 7 | end 8 | 9 | # function to integrate a unit circle to find pi via monte_carlo 10 | function monte_carlo(n::Int64) 11 | 12 | pi_count = 0 13 | for i = 1:n 14 | point_x = rand() 15 | point_y = rand() 16 | 17 | if (in_circle(point_x, point_y)) 18 | pi_count += 1 19 | end 20 | end 21 | 22 | # This is using a quarter of the unit sphere in a 1x1 box. 23 | # The formula is pi = (box_length^2 / radius^2) * (pi_count / n), but we 24 | # are only using the upper quadrant and the unit circle, so we can use 25 | # 4*pi_count/n instead 26 | pi_estimate = 4*pi_count/n 27 | println("Percent error is: ", signif(100*(pi - pi_estimate)/pi, 3), " %") 28 | end 29 | 30 | monte_carlo(10000000) 31 | -------------------------------------------------------------------------------- /chapters/differential_equations/euler/code/c/euler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void solve_euler(double timestep, double *result, size_t n) { 5 | if (n != 0) { 6 | result[0] = 1; 7 | for (size_t i = 1; i < n; ++i) { 8 | result[i] = result[i-1] - 3.0 * result[i-1] * timestep; 9 | } 10 | } 11 | } 12 | 13 | int check_result(double *result, size_t n, double threshold, double timestep) { 14 | int is_approx = 1; 15 | for (size_t i = 0; i < n; ++i) { 16 | double solution = exp(-3.0 * i * timestep); 17 | if (fabs(result[i] - solution) > threshold) { 18 | printf("%f %f\n", result[i], solution); 19 | is_approx = 0; 20 | } 21 | } 22 | 23 | return is_approx; 24 | } 25 | 26 | int main() { 27 | double result[100]; 28 | double threshold = 0.01; 29 | double timestep = 0.01; 30 | 31 | solve_euler(timestep, result, 100); 32 | printf("%d\n", check_result(result, 100, threshold, timestep)); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/java/bubble.java: -------------------------------------------------------------------------------- 1 | public class Bubble { 2 | static void bubbleSort(int[] arr) { 3 | for (int r = arr.length - 1; r > 0; r--) { 4 | for (int i = 0; i < r; i++) { 5 | if(arr[i] > arr[i + 1]) { 6 | int tmp = arr[i]; 7 | arr[i] = arr[i + 1]; 8 | arr[i + 1] = tmp; 9 | } 10 | } 11 | } 12 | } 13 | 14 | 15 | // main function (for testing) 16 | public static void main(String[] args) { 17 | int[] test = new int[]{20, -3, 50, 1, -6, 59}; 18 | 19 | System.out.println("Unsorted array :"); 20 | for (int i = 0; i < test.length; i++) { 21 | System.out.print(test[i] + " "); 22 | } 23 | 24 | bubbleSort(test); 25 | 26 | System.out.println("\n\nSorted array :"); 27 | for (int i = 0; i < test.length; i++) { 28 | System.out.print(test[i] + " "); 29 | } 30 | System.out.println(""); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /chapters/physics_solvers/physics_solvers.md: -------------------------------------------------------------------------------- 1 | ### Physics Solvers 2 | 3 | There are certain algorithms that have been uniquely created to solve particular physical systems. 4 | For example, the kinematic equation can be solved with Verlet integration and also with more general differential equation solvers. 5 | In this section, we will place all algorithms and methods that are *specific* to physics and cannot be used in any other area. 6 | It's worth noting that many algorithms used throughout the Archive can also be used to solve physics equations and physics lends itself more readily to computational methods than many other areas of scientific research, such as biology or chemistry. 7 | 8 | In the future, we may also place several unique physical systems along with different methods to solve these systems. 9 | For example, there are many different ways to solve the Schrodinger equation, heat equation, kinematic equation and several other systems that are unique to physics and there are benefits and drawbacks for solving certain physical systems in certain ways. 10 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/rust/bubble_sort.rs: -------------------------------------------------------------------------------- 1 | extern crate rand; // External crate that provides random number generation tools 2 | 3 | use rand::{thread_rng, Rng}; // Used for random number generation 4 | use rand::distributions::Uniform; // Used for a uniform distribution 5 | 6 | fn bubble_sort(a: &mut [u32]) { 7 | let n = a.len(); 8 | 9 | for _ in 0..n { 10 | for j in 1..n { 11 | if a[j - 1] > a[j] { 12 | a.swap(j, j - 1); 13 | } 14 | } 15 | } 16 | } 17 | 18 | fn main() { 19 | let mut rng = thread_rng(); // Create random number generator 20 | let num_range = Uniform::new_inclusive(0, 10000); // Obtain uniform distribution of range [0, 10000] 21 | let mut rand_vec: Vec = rng.sample_iter(&num_range).take(10).collect(); 22 | // Generates random values over that range, take 10 values from it and collect in vector 23 | 24 | println!("Before sorting: {:?}", rand_vec); 25 | bubble_sort(&mut rand_vec); 26 | println!("After sorting: {:?}", rand_vec); 27 | } -------------------------------------------------------------------------------- /chapters/euclidean_algorithm/code/cs/EuclideanAlgorithm.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) 2 | using System; 3 | 4 | namespace EuclideanAlgorithm 5 | { 6 | public class EuclideanAlgorithm 7 | { 8 | public int EuclidSub(int a, int b) 9 | { 10 | // Math.Abs for negative number support 11 | a = Math.Abs(a); 12 | b = Math.Abs(b); 13 | 14 | while (a != b) 15 | { 16 | if (a > b) 17 | a = a - b; 18 | else 19 | b = b - a; 20 | } 21 | 22 | return a; 23 | } 24 | 25 | public int EuclidMod(int a, int b) 26 | { 27 | // Math.Abs for negative number support 28 | a = Math.Abs(a); 29 | b = Math.Abs(b); 30 | 31 | while (b != 0) 32 | { 33 | var temp = b; 34 | b = a % b; 35 | a = temp; 36 | } 37 | 38 | return a; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/c/bubble_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void bubble_sort(int *array, size_t n) { 5 | int swapped = 0; 6 | for (size_t i = 0; i < n - 1; ++i) { 7 | swapped = 0; 8 | for (size_t j = 0; j < n - i - 1; ++j) { 9 | if (array[j] > array[j + 1]) { 10 | int tmp = array[j]; 11 | array[j] = array[j + 1]; 12 | array[j + 1] = tmp; 13 | 14 | swapped = 1; 15 | } 16 | } 17 | 18 | if (!swapped) { 19 | break; 20 | } 21 | } 22 | } 23 | 24 | int main() { 25 | int array[10] = {1, 45, 756, 4569, 56, 3, 8, 5, -10, -4}; 26 | 27 | printf("Unsorted array:\n"); 28 | for (size_t i = 0; i < 10; ++i) { 29 | printf("%d ", array[i]); 30 | } 31 | printf("\n\n"); 32 | 33 | bubble_sort(array, 10); 34 | 35 | printf("Sorted array:\n"); 36 | for (size_t i = 0; i < 10; ++i) { 37 | printf("%d ", array[i]); 38 | } 39 | printf("\n"); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /update_site.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ $# -ge 1 ]; then 4 | if [ $# -eq 2 ]; then 5 | out_dir="$2" 6 | else 7 | if [ -z ${AAA_DIR+x} ]; then 8 | echo "No output directory specified" 9 | exit 1 10 | fi 11 | out_dir="$AAA_DIR" 12 | fi 13 | 14 | if [[ ! -d "$out_dir" ]]; then 15 | echo "$out_dir is not a directory" 16 | exit 1 17 | fi 18 | 19 | gitbook build . /tmp/algorithm-archivists.github.io 20 | 21 | if [ $? -ne 0 ]; then 22 | echo "Failed to build the book" 23 | exit 1 24 | fi 25 | 26 | cd "$out_dir" 27 | git reset --hard && \ 28 | git clean -dfx && \ 29 | git pull origin master 30 | 31 | if [ $? -ne 0 ]; then 32 | echo "Failed to prepare repository" 33 | exit 1 34 | fi 35 | 36 | cp -r /tmp/algorithm-archivists.github.io/* . 37 | rm -r /tmp/algorithm-archivists.github.io 38 | git add . 39 | git commit -m "$1" 40 | git push origin master 41 | 42 | else 43 | echo "No commit message specified" 44 | fi 45 | -------------------------------------------------------------------------------- /chapters/physics_solvers/barnes_hut.md: -------------------------------------------------------------------------------- 1 | ##### Dependencies 2 | * [Verlet Integration](verlet.md) 3 | 4 | # Barnes Hut Algorithm 5 | 6 | The Barnes-Hut algorithm divides space into an octree in order to cut computational time without losing much precision in n-body simulations. If you want to learn more soon, bug me about it! 7 | 8 | TODO 9 | 10 | 11 | 14 | $$ 15 | \newcommand{\d}{\mathrm{d}} 16 | \newcommand{\bff}{\boldsymbol{f}} 17 | \newcommand{\bfg}{\boldsymbol{g}} 18 | \newcommand{\bfp}{\boldsymbol{p}} 19 | \newcommand{\bfq}{\boldsymbol{q}} 20 | \newcommand{\bfx}{\boldsymbol{x}} 21 | \newcommand{\bfu}{\boldsymbol{u}} 22 | \newcommand{\bfv}{\boldsymbol{v}} 23 | \newcommand{\bfA}{\boldsymbol{A}} 24 | \newcommand{\bfB}{\boldsymbol{B}} 25 | \newcommand{\bfC}{\boldsymbol{C}} 26 | \newcommand{\bfM}{\boldsymbol{M}} 27 | \newcommand{\bfJ}{\boldsymbol{J}} 28 | \newcommand{\bfR}{\boldsymbol{R}} 29 | \newcommand{\bfT}{\boldsymbol{T}} 30 | \newcommand{\bfomega}{\boldsymbol{\omega}} 31 | \newcommand{\bftau}{\boldsymbol{\tau}} 32 | $$ 33 | 34 | -------------------------------------------------------------------------------- /chapters/monte_carlo/code/java/MonteCarlo.java: -------------------------------------------------------------------------------- 1 | //submitted by DominikRafacz 2 | import java.util.Random; 3 | 4 | public class MonteCarlo { 5 | 6 | public static void main(String[] args) { 7 | monteCarlo(10_000_000); 8 | } 9 | 10 | //function to check whether point (x,y) is in unit circle 11 | private static boolean inCircle(double x, double y) { 12 | return x * x + y * y < 1; 13 | } 14 | 15 | //function to calculate estimation of pi 16 | public static void monteCarlo(int samples) { 17 | int piCount = 0; 18 | 19 | Random random = new Random(); 20 | 21 | for (int i = 0; i < samples; i++) { 22 | double x = random.nextDouble(); 23 | double y = random.nextDouble(); 24 | if (inCircle(x, y)) { 25 | piCount++; 26 | } 27 | } 28 | 29 | double estimation = 4.0 * piCount / samples; 30 | 31 | System.out.println("Estimated pi value: " + estimation); 32 | System.out.printf("Percent error: %.4f%%", 33 | 100 * (Math.PI - estimation) / Math.PI); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2017 James Schloss et. al 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /chapters/differential_equations/euler/code/julia/euler.jl: -------------------------------------------------------------------------------- 1 | function solve_euler(timestep::Float64, n::Int64) 2 | euler_result = Vector{Float64}(n) 3 | 4 | # Setting the initial condition 5 | euler_result[1] = 1; 6 | for i = 2:length(euler_result) 7 | euler_result[i] = euler_result[i-1] - 3.0*euler_result[i-1]*timestep 8 | end 9 | return euler_result 10 | end 11 | 12 | function check_result(euler_result::Vector{Float64}, threshold::Float64, 13 | timestep::Float64) 14 | is_approx = true 15 | 16 | for i = 1:length(euler_result) 17 | time = (i - 1)*timestep 18 | solution = exp(-3*time); 19 | if (abs(euler_result[i] - solution) > threshold) 20 | println(euler_result[i], solution) 21 | is_approx = false 22 | end 23 | end 24 | 25 | return is_approx 26 | end 27 | 28 | function main() 29 | timestep = 0.01 30 | n = 100 31 | threshold = 0.01 32 | 33 | euler_result = solve_euler(timestep,n) 34 | is_approx = check_result(euler_result, threshold, timestep) 35 | 36 | println(is_approx) 37 | end 38 | 39 | main() 40 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/c/bogo_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | bool is_sorted(int *array, size_t n) { 7 | while (--n >= 1) { 8 | if (array[n] < array[n - 1]) { 9 | return false; 10 | } 11 | } 12 | 13 | return true; 14 | } 15 | 16 | void shuffle(int *array, size_t n) { 17 | for (size_t i = 0; i < n; ++i) { 18 | int t = array[i]; 19 | int r = rand() % n; 20 | array[i] = array[r]; 21 | array[r] = t; 22 | } 23 | } 24 | 25 | void bogo_sort(int *array, size_t n) { 26 | while (!is_sorted(array, n)) { 27 | shuffle(array, n); 28 | } 29 | } 30 | 31 | int main() { 32 | int array[10] = {1, 3654, 78, 654, -234, -12, 4, 3, -6, -100}; 33 | 34 | printf("Unsorted array:\n"); 35 | for (int i = 0; i < 10; ++i) { 36 | printf("%d ", array[i]); 37 | } 38 | printf("\n\n"); 39 | 40 | bogo_sort(array, 10); 41 | 42 | printf("Sorted array:\n"); 43 | for (int i = 0; i < 10; ++i) { 44 | printf("%d ", array[i]); 45 | } 46 | printf("\n"); 47 | } 48 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/jarvis_march/code/javascript/jarvis-march.js: -------------------------------------------------------------------------------- 1 | function jarvisMarch(points) { 2 | const hull = []; 3 | 4 | let pointOnHull = points.reduce((leftmost, current) => leftmost.x < current.x ? leftmost : current); 5 | do { 6 | hull.push(pointOnHull); 7 | pointOnHull = points.reduce(chooseNextPointOnHull(pointOnHull)); 8 | } while (pointOnHull !== hull[0]); 9 | 10 | return hull; 11 | } 12 | 13 | function chooseNextPointOnHull(currentPoint) { 14 | return function (nextPoint, candidate) { 15 | if (nextPoint === currentPoint || isLeftOf({ a: currentPoint, b: nextPoint }, candidate)) { 16 | return candidate; 17 | } 18 | return nextPoint; 19 | } 20 | } 21 | 22 | function isLeftOf({ a, b }, p) { 23 | return (b.x - a.x) * (p.y - a.y) > (p.x - a.x) * (b.y - a.y); 24 | } 25 | 26 | const points = [ 27 | { x: 1, y: 3 }, 28 | { x: 2, y: 4 }, 29 | { x: 4, y: 0 }, 30 | { x: 1, y: 0 }, 31 | { x: 0, y: 2 }, 32 | { x: 2, y: 2 }, 33 | { x: 3, y: 4 }, 34 | { x: 3, y: 1 }, 35 | ]; 36 | 37 | const convexHull = jarvisMarch(points); 38 | convexHull.forEach(p => console.log(`(${p.x}, ${p.y})`)); 39 | 40 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/cs/Program.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) 2 | using System; 3 | 4 | namespace TreeTraversal 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | Console.WriteLine("TreeTraversal"); 11 | var tree = new Tree(3, 3); 12 | Console.WriteLine("DFSRecursive:"); 13 | tree.DFSRecursive(); 14 | Console.WriteLine("DFSStack:"); 15 | tree.DFSStack(); 16 | Console.WriteLine("BFSQueue:"); 17 | tree.BFSQueue(); 18 | Console.WriteLine("DFSRecursivePostorder"); 19 | tree.DFSRecursivePostorder(); 20 | // Uncommenting the following 2 lines will result in an exception thrown because at least one Node of the Tree has more than 2 children and therefor a DFSRecursiveInorderBinary doesn't work. 21 | // Console.WriteLine("DFSRecursiveInorder (fail)"); 22 | // tree.DFSRecursiveInorderBinary(); 23 | tree = new Tree(3, 2); 24 | Console.WriteLine("DFSRecursiveInorder (succeed)"); 25 | tree.DFSRecursiveInorderBinary(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/rust/verlet.rs: -------------------------------------------------------------------------------- 1 | fn verlet(mut pos: f64, acc: f64, dt: f64) { 2 | let mut prev_pos = pos; 3 | let mut time = 0.0; 4 | 5 | while pos > 0.0 { 6 | time += dt; 7 | let temp_pos = pos; 8 | pos = pos * 2.0 - prev_pos + acc * dt * dt; 9 | prev_pos = temp_pos; 10 | } 11 | 12 | println!("{}", time); 13 | } 14 | 15 | fn stormer_verlet(mut pos: f64, acc: f64, dt: f64) { 16 | let mut prev_pos = pos; 17 | let mut time = 0.0; 18 | 19 | while pos > 0.0 { 20 | time += dt; 21 | let temp_pos = pos; 22 | pos = pos * 2.0 - prev_pos + acc * dt * dt; 23 | prev_pos = temp_pos; 24 | } 25 | 26 | println!("{}", time); 27 | } 28 | 29 | fn velocity_verlet(mut pos: f64, acc: f64, dt: f64) { 30 | let mut time = 0.0; 31 | let mut vel = 0.0; 32 | 33 | while pos > 0.0 { 34 | time += dt; 35 | pos += vel * dt + 0.5 * acc * dt * dt; 36 | vel += acc * dt; 37 | } 38 | 39 | println!("{}", time); 40 | } 41 | 42 | fn main() { 43 | verlet(5.0, -10.0, 0.01); 44 | stormer_verlet(5.0, -10.0, 0.01); 45 | velocity_verlet(5.0, -10.0, 0.01); 46 | } 47 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/java/MainClass.java: -------------------------------------------------------------------------------- 1 | //submitted by xam4lor 2 | public class MainClass { 3 | public static void main(String[] args) { 4 | System.out.println("Creating Tree"); 5 | Tree tree = new Tree(3, 3); 6 | 7 | System.out.println("Using recursive DFS :"); 8 | tree.dfsRecursive(); 9 | 10 | System.out.println("Using stack-based DFS :"); 11 | tree.dfsStack(); 12 | 13 | System.out.println("Using queue-based BFS :"); 14 | tree.bfsQueue(); 15 | 16 | System.out.println("Using post-order recursive DFS :"); 17 | tree.dfsRecursivePostOrder(); 18 | 19 | 20 | // Uncommenting the following 2 lines will result in an exception thrown because at least one Node of the Tree has more than 2 children and therefor a DFSRecursiveInorderBinary doesn't work. 21 | System.out.println("Using in-order binary recursive DFS : (fail)"); 22 | tree.dfsRecursiveInOrderBinary(); 23 | 24 | tree = new Tree(3, 2); 25 | System.out.println("Using in-order binary recursive DFS : (suceed)"); 26 | tree.dfsRecursiveInOrderBinary(); 27 | 28 | 29 | System.out.println(""); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/jarvis_march/code/cs/Program.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) with great help by gustorn 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace JarvisMarch 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | System.Console.WriteLine("JarvisMarch"); 12 | // Example list of points. 13 | // The points are represented by vectors here, but that doesn't really matter. 14 | var points = new List() 15 | { 16 | new Vector(1, 3), 17 | new Vector(2, 4), 18 | new Vector(4, 0), 19 | new Vector(1, 0), 20 | new Vector(0, 2), 21 | new Vector(2, 2), 22 | new Vector(3, 4), 23 | new Vector(3, 1), 24 | }; 25 | var jarvisMarch = new JarvisMarch(); 26 | var giftWrap = jarvisMarch.Run(points); 27 | 28 | // Print the points of the gift wrap. 29 | foreach (var point in giftWrap) 30 | System.Console.WriteLine($"{point.x}, {point.y}"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/javascript/verlet.js: -------------------------------------------------------------------------------- 1 | function verlet(pos, acc, dt){ 2 | 3 | var prev_pos, temp_pos, time; 4 | prev_pos = pos; 5 | time = 0; 6 | 7 | while (pos > 0){ 8 | time += dt; 9 | temp_pos = pos; 10 | pos = pos*2 - prev_pos + acc * dt * dt; 11 | prev_pos = temp_pos; 12 | } 13 | 14 | return time; 15 | 16 | } 17 | 18 | function stormer_verlet(pos, acc, dt){ 19 | 20 | var prev_pos, temp_pos, time, vel; 21 | prev_pos = pos; 22 | vel = 0; 23 | time = 0; 24 | while (pos > 0){ 25 | time += dt; 26 | temp_pos = pos; 27 | pos = pos*2 - prev_pos + acc * dt * dt; 28 | prev_pos = temp_pos; 29 | 30 | vel += acc*dt; 31 | } 32 | 33 | return time; 34 | 35 | } 36 | 37 | function velocity_verlet(pos, acc, dt){ 38 | 39 | var time, vel; 40 | vel = 0; 41 | time = 0; 42 | while (pos > 0){ 43 | time += dt; 44 | pos += vel*dt + 0.5*acc * dt * dt; 45 | vel += acc*dt; 46 | } 47 | 48 | return time; 49 | 50 | } 51 | 52 | console.log(verlet(5.0, -10, 0.01)); 53 | console.log(stormer_verlet(5.0, -10, 0.01)); 54 | console.log(velocity_verlet(5.0, -10, 0.01)); 55 | 56 | -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/matlab/verlet.m: -------------------------------------------------------------------------------- 1 | % Submitted by P. Mekhail 2 | % Parameters to change 3 | n = 400; % Number of steps 4 | x0 = 5; % Ball starting height(in metres) 5 | v0 = 0; % Ball starting velocity (+ive is up) 6 | dt = 0.01; % Time step (in seconds) 7 | eff = 0.4; % Ball efficency when bouncing 8 | A = @(x) -10; % Acceleration as a function of position 9 | bounce = 1; % Do you want the ball to bounce? 10 | 11 | % Making position and time vectors 12 | x = zeros(n,1); 13 | t = 0:dt:n*dt-dt; 14 | 15 | % Setting the initial conditions 16 | x(1) = x0; 17 | x(2) = x0 + v0*dt + 0.5*A(x0)*dt^2; 18 | 19 | % Runnin Verlet Integration 20 | for i = 2:n-1 21 | xnew = 2*x(i)-x(i-1)+A(x(i))*dt^2; 22 | if bounce 23 | if xnew > 0 24 | % If you haven't hit the ground keep going 25 | x(i+1) = xnew; 26 | else 27 | % If you have calculated velocity and invert its sign 28 | v = sqrt(eff)*(xnew-x(i-1))/(2*dt); 29 | x(i+1) = x(i) - v*dt + 0.5*A(x(i))*dt^2; 30 | end 31 | else 32 | x(i+1) = xnew; 33 | end 34 | end 35 | plot(t,x) 36 | title('Ball''s Trajectory') 37 | xlabel('Time (s)'); ylabel('Height (m)'); 38 | 39 | -------------------------------------------------------------------------------- /chapters/differential_equations/euler/backward_euler.md: -------------------------------------------------------------------------------- 1 | ### Backward Euler Method 2 | 3 | Unlike the forward Euler Method above, the backward Euler Method is an *implicit method*, which means that it results in a system of equations to solve. Luckily, we know how to solve systems of equations (*hint*: [Thomas Algorithm](../../computational_mathematics/matrix_methods/thomas/thomas.md), [Gaussian Elimination](../../computational_mathematics/matrix_methods/gaussian_elimination/gaussian_elimination.md)) 4 | 5 | MORE TO COME!!! 6 | 7 | 8 | 11 | $$ 12 | \newcommand{\d}{\mathrm{d}} 13 | \newcommand{\bff}{\boldsymbol{f}} 14 | \newcommand{\bfg}{\boldsymbol{g}} 15 | \newcommand{\bfp}{\boldsymbol{p}} 16 | \newcommand{\bfq}{\boldsymbol{q}} 17 | \newcommand{\bfx}{\boldsymbol{x}} 18 | \newcommand{\bfu}{\boldsymbol{u}} 19 | \newcommand{\bfv}{\boldsymbol{v}} 20 | \newcommand{\bfA}{\boldsymbol{A}} 21 | \newcommand{\bfB}{\boldsymbol{B}} 22 | \newcommand{\bfC}{\boldsymbol{C}} 23 | \newcommand{\bfM}{\boldsymbol{M}} 24 | \newcommand{\bfJ}{\boldsymbol{J}} 25 | \newcommand{\bfR}{\boldsymbol{R}} 26 | \newcommand{\bfT}{\boldsymbol{T}} 27 | \newcommand{\bfomega}{\boldsymbol{\omega}} 28 | \newcommand{\bftau}{\boldsymbol{\tau}} 29 | $$ 30 | 31 | -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/haskell/verlet.hs: -------------------------------------------------------------------------------- 1 | -- submitted by Jie 2 | type Position = [Double] 3 | type Speed = [Double] 4 | type Time = Double 5 | type Particle = (Position, Speed, Acceleration, Time) 6 | type Acceleration = [Double] 7 | 8 | verletStep :: (Particle -> Acceleration) 9 | -> Time 10 | -> Particle 11 | -> Particle 12 | -> Particle 13 | verletStep acc dt (xOld, _, aOld, _) (x, v, a, t) = (x', v', a', t+dt) 14 | where 15 | x' = zipWith3 (\xOld x a -> 2*x - xOld + a*dt^2 ) xOld x a 16 | v' = zipWith3 (\v a aOld -> v + 0.5*(aOld + a)*dt) v a aOld 17 | a' = acc (x', v', [], t+dt) 18 | 19 | trajectory :: (Particle -> Acceleration) 20 | -> Time 21 | -> Particle 22 | -> [Particle] 23 | trajectory acc dt p0@(x, v, a, t0) = t 24 | where 25 | t = p0 : p1 : zipWith (verletStep acc dt) t (tail t) 26 | p1 = (x', v', acc (x', v', [], t0+dt), t0+dt) 27 | x' = zipWith3 (\x v a -> x + v*dt + 0.5*a*dt^2 ) x v a 28 | v' = zipWith (\v a -> v + a*dt) v a 29 | 30 | freeFall :: Particle 31 | freeFall = last $ takeWhile (\([x],_,_,_) -> x > 0) $ trajectory acc dt p0 32 | where 33 | p0 = ([5], [0], [-10], 0) 34 | dt = 0.001 35 | acc _ = [-10] 36 | 37 | -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/julia/verlet.jl: -------------------------------------------------------------------------------- 1 | function verlet(pos::Float64, acc::Float64, dt::Float64) 2 | prev_pos = pos 3 | time = 0.0 4 | 5 | while (pos > 0) 6 | time += dt 7 | temp_pos = pos 8 | pos = pos * 2 - prev_pos + acc * dt * dt 9 | prev_pos = temp_pos 10 | end 11 | 12 | println(time) 13 | end 14 | 15 | function stormer_verlet(pos::Float64, acc::Float64, dt::Float64) 16 | prev_pos = pos 17 | time = 0.0 18 | vel = 0.0 19 | 20 | while (pos > 0.0) 21 | time += dt 22 | temp_pos = pos 23 | pos = pos * 2 - prev_pos + acc * dt * dt 24 | prev_pos = temp_pos 25 | 26 | # Because acceleration is constant, velocity is straightforward 27 | vel += acc*dt 28 | end 29 | 30 | println(time) 31 | end 32 | 33 | function velocity_verlet(pos::Float64, acc::Float64, dt::Float64) 34 | prev_pos = pos 35 | time = 0.0 36 | vel = 0.0 37 | 38 | while (pos > 0.0) 39 | time += dt 40 | pos += vel * dt + 0.5 * acc * dt * dt; 41 | vel += acc * dt; 42 | end 43 | 44 | println(time) 45 | end 46 | 47 | function main() 48 | verlet(5.0, -10.0, 0.01); 49 | stormer_verlet(5.0, -10.0, 0.01); 50 | velocity_verlet(5.0, -10.0, 0.01); 51 | end 52 | 53 | main() 54 | -------------------------------------------------------------------------------- /chapters/FFT/code/python/fft.py: -------------------------------------------------------------------------------- 1 | from random import random 2 | from cmath import exp, pi 3 | from math import log2 4 | 5 | def cooley_tukey(X): 6 | N = len(X) 7 | if N <= 1: 8 | return X 9 | even = cooley_tukey(X[0::2]) 10 | odd = cooley_tukey(X[1::2]) 11 | 12 | temp = [i for i in range(N)] 13 | for k in range(N//2): 14 | temp[k] = even[k] + exp(-2j*pi*k/N) * odd[k] 15 | temp[k+N//2] = even[k] - exp(-2j*pi*k/N)*odd[k] 16 | return temp 17 | 18 | def bitReverse(X): 19 | N = len(X) 20 | temp = [i for i in range(N)] 21 | for k in range(N): 22 | b = sum(1<<(int(log2(N))-1-i) for i in range(int(log2(N))) if k>>i&1) 23 | temp[k] = X[b] 24 | temp[b] = X[k] 25 | return temp 26 | 27 | def iterative_cooley_tukey(X): 28 | N = len(X) 29 | 30 | X = bitReverse(X) 31 | 32 | for i in range(1, int(log2(N)) + 1): 33 | stride = 2**i 34 | w = exp(-2j*pi/stride) 35 | for j in range(0, N, stride): 36 | v = 1 37 | for k in range(stride//2): 38 | X[k + j + stride//2] = X[k + j] - v*X[k + j + stride//2]; 39 | X[k + j] -= (X[k + j + stride//2] - X[k + j]); 40 | v *= w; 41 | return X 42 | 43 | X = [] 44 | 45 | for i in range(64): 46 | X.append(random()) 47 | 48 | Y = cooley_tukey(X) 49 | Z = iterative_cooley_tukey(X) 50 | 51 | print(all(abs([Y[i] - Z[i] for i in range(64)][j]) < 1 for j in range(64))) 52 | -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/c/verlet.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void verlet(double pos, double acc, double dt) { 4 | double prev_pos, temp_pos, time; 5 | prev_pos = pos; 6 | time = 0; 7 | 8 | while (pos > 0) { 9 | time += dt; 10 | temp_pos = pos; 11 | pos = pos * 2 - prev_pos + acc * dt * dt; 12 | prev_pos = temp_pos; 13 | } 14 | 15 | printf("%f\n", time); 16 | } 17 | 18 | void stormer_verlet(double pos, double acc, double dt) { 19 | double prev_pos, temp_pos, time, vel; 20 | prev_pos = pos; 21 | vel = 0; 22 | time = 0; 23 | while (pos > 0) { 24 | time += dt; 25 | temp_pos = pos; 26 | pos = pos * 2 - prev_pos + acc * dt * dt; 27 | prev_pos = temp_pos; 28 | 29 | vel += acc * dt; 30 | } 31 | 32 | printf("%f\n", time); 33 | } 34 | 35 | void velocity_verlet(double pos, double acc, double dt) { 36 | double time, vel; 37 | vel = 0; 38 | time = 0; 39 | while (pos > 0) { 40 | time += dt; 41 | pos += vel * dt + 0.5 * acc * dt * dt; 42 | vel += acc * dt; 43 | } 44 | 45 | printf("%f\n", time); 46 | } 47 | 48 | int main() { 49 | verlet(5.0, -10, 0.01); 50 | stormer_verlet(5.0, -10, 0.01); 51 | velocity_verlet(5.0, -10, 0.01); 52 | 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /chapters/decision_problems/stable_marriage/code/haskell/stableMarriage.hs: -------------------------------------------------------------------------------- 1 | import Data.Map as M (Map, (!)) 2 | import qualified Data.Map as M 3 | import Data.List (elemIndex) 4 | import Control.Monad.State 5 | 6 | stableMatching :: (Ord a, Ord b) => [(a, [b])] -> [(b, [a])] -> [(a, b)] 7 | stableMatching men women = evalState (propose (M.fromList women) men) M.empty 8 | 9 | propose :: (Ord a, Ord b) => Map b [a] -> 10 | [(a, [b])] -> 11 | State (Map b (a, [b])) [(a, b)] 12 | propose _ [] = get >>= return . map (\(w, (m,_)) -> (m, w)) . M.assocs 13 | propose women ((man, pref):bachelors) = do 14 | let theOne = head pref 15 | couples <- get 16 | case M.lookup theOne couples of 17 | Nothing -> do 18 | modify $ M.insert theOne (man, (tail pref)) 19 | propose women bachelors 20 | Just (boyfriend, planB) -> do 21 | let rank x = elemIndex x (women!theOne) 22 | if rank boyfriend < rank man 23 | then propose women $ (man, tail pref): bachelors 24 | else do 25 | modify $ M.insert theOne (man, (tail pref)) . M.delete theOne 26 | propose women $ (boyfriend, planB): bachelors 27 | 28 | main = do 29 | let aPref = [('A',"YXZ"), ('B',"ZYX"),('C', "XZY")] 30 | bPref = [('X',"BAC"), ('Y',"CBA"),('Z', "ACB")] 31 | print $ stableMatching aPref bPref 32 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/c++/bogosort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using std::begin; 8 | using std::end; 9 | 10 | template 11 | std::vector generate_input(std::size_t size, Rng& rng) { 12 | auto dist = std::uniform_real_distribution<>(0.0, 1.0); 13 | 14 | auto ret = std::vector(); 15 | std::generate_n(std::back_inserter(ret), size, 16 | [&rng, &dist] { return dist(rng); }); 17 | 18 | return ret; 19 | } 20 | 21 | template 22 | void print_range(std::ostream& os, Iter const first, Iter const last) { 23 | os << '{'; 24 | 25 | if (first != last) { 26 | os << *first; 27 | std::for_each(first + 1, last, [&os] (double d) { os << ", " << *it; }); 28 | } 29 | 30 | os << "}\n"; 31 | } 32 | 33 | template 34 | void bogo_sort(Iter const first, Iter const last, Rng& rng) { 35 | while (not std::is_sorted(first, last)) { 36 | std::shuffle(first, last, rng); 37 | } 38 | } 39 | 40 | int main() { 41 | std::random_device random_device; 42 | auto rng = std::mt19937(random_device()); 43 | 44 | auto input = generate_input(5, rng); 45 | 46 | print_range(std::cout, begin(input), end(input)); 47 | 48 | bogo_sort(begin(input), end(input), rng); 49 | 50 | print_range(std::cout, begin(input), end(input)); 51 | } 52 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/java/bogo.java: -------------------------------------------------------------------------------- 1 | public class Bogo { 2 | // The shuffle() function can be found in code/java/bogo.java 3 | static void bogoSort(int[] arr) { 4 | while(!isSorted(arr)) { 5 | shuffle(arr); 6 | } 7 | } 8 | 9 | static boolean isSorted(int[] arr) { 10 | for (int i = 0; i < arr.length - 1; i++) { 11 | if(arr[i] > arr[i + 1]) { 12 | return false; 13 | } 14 | } 15 | 16 | return true; 17 | } 18 | 19 | static void shuffle(int[] arr) { 20 | for (int r = arr.length - 1; r > 0; r--) { 21 | int i = (int) Math.floor(Math.random() * r); 22 | int tmp = arr[i]; 23 | arr[i] = arr[r]; 24 | arr[r] = tmp; 25 | } 26 | } 27 | 28 | 29 | // main function (for testing) 30 | public static void main(String[] args) { 31 | int[] test = new int[]{20, -3, 50, 1, -6, 59}; 32 | 33 | System.out.println("Unsorted array :"); 34 | for (int i = 0; i < test.length; i++) { 35 | System.out.print(test[i] + " "); 36 | } 37 | 38 | 39 | bogoSort(test); 40 | 41 | 42 | System.out.println("\n\nSorted array :"); 43 | for (int i = 0; i < test.length; i++) { 44 | System.out.print(test[i] + " "); 45 | } 46 | System.out.println(""); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/rust/tree.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | #[derive(Debug)] 4 | struct Node { 5 | children: Vec, 6 | value: u64, 7 | } 8 | 9 | fn dfs_recursive(n: &Node) { 10 | println!("{}", n.value); 11 | 12 | for child in &n.children { 13 | dfs_recursive(child); 14 | } 15 | } 16 | 17 | fn dfs_stack(n: &Node) { 18 | let mut stack = vec![n]; 19 | 20 | while let Some(current) = stack.pop() { 21 | println!("{}", current.value); 22 | stack.extend(¤t.children); 23 | } 24 | } 25 | 26 | fn bfs_queue(n: &Node){ 27 | let mut queue = VecDeque::new(); 28 | queue.push_back(n); 29 | 30 | while let Some(current) = queue.pop_front() { 31 | println!("{}", current.value); 32 | queue.extend(¤t.children); 33 | } 34 | } 35 | 36 | fn create_tree(num_row: u64, num_child: u64) -> Node { 37 | if num_row == 0 { 38 | return Node { children: vec![], value: 0 }; 39 | } 40 | 41 | let children = (0..num_child) 42 | .map(|_| create_tree(num_row - 1, num_child)) 43 | .collect(); 44 | 45 | Node { children, value: num_row } 46 | } 47 | 48 | fn main() { 49 | let root = create_tree(3,3); 50 | println!("Recursive DFS:"); 51 | dfs_recursive(&root); 52 | println!("Stack DFS:"); 53 | dfs_stack(&root); 54 | println!("Queue BFS:"); 55 | bfs_queue(&root); 56 | } 57 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | # Base for all text files 4 | [*] 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | end_of_line = lf 8 | 9 | # C 10 | [*.c] 11 | indent_style = space 12 | indent_size = 4 13 | 14 | # Clojure 15 | [*.clj] 16 | indent_style = space 17 | indent_size = 2 18 | 19 | # C++ 20 | [*.cpp] 21 | indent_style = space 22 | indent_size = 2 23 | 24 | # C# 25 | [*.cs] 26 | indent_style = space 27 | indent_size = 4 28 | 29 | # CSS 30 | [*.css] 31 | indent_style = space 32 | indent_size = 2 33 | 34 | # D 35 | [*.d] 36 | indent_style = space 37 | indent_size = 4 38 | 39 | # Elm 40 | [*.elm] 41 | indent_style = space 42 | indent_size = 2 43 | 44 | # Go 45 | [*.go] 46 | indent_style = tab 47 | 48 | # Haskell 49 | [*.hs] 50 | indent_style = space 51 | indent_size = 2 52 | 53 | # HTML 54 | [*.html] 55 | indent_style = space 56 | indent_size = 2 57 | 58 | # Java 59 | [*.java] 60 | indent_style = space 61 | indent_size = 4 62 | 63 | # Julia 64 | [*.jl] 65 | indent_style = space 66 | indent_size = 4 67 | 68 | # JavaScript 69 | [*.js] 70 | indent_style = space 71 | indent_size = 2 72 | 73 | # Markdown 74 | [*.md] 75 | indent_style = space 76 | indent_size = 2 77 | 78 | # OCAML 79 | [*.ml] 80 | indent_style = space 81 | indent_size = 2 82 | 83 | # Python 84 | [*.py] 85 | indent_style = space 86 | indent_size = 4 87 | 88 | # Rust 89 | [*.rs] 90 | indent_style = space 91 | indent_size = 4 92 | -------------------------------------------------------------------------------- /chapters/computational_geometry/computational_geometry.md: -------------------------------------------------------------------------------- 1 | # Computational Geometry 2 | When it comes to the different sectors of computational mathematics, there are none that bring me more joy than computational geometry. 3 | In some sense, it is the foundation for almost every area of automatically generated two and three dimensional graphics. 4 | If you have time to spend poring through some interesting research, I would definitely recommend going to the [arXiv.org section for computational geometry](https://arxiv.org/list/cs.CG/recent). 5 | We will add more to this section as the Archive evolves, so let me know of any algorithms that you would like to cover in the future! 6 | 7 | 10 | $$ 11 | \newcommand{\d}{\mathrm{d}} 12 | \newcommand{\bff}{\boldsymbol{f}} 13 | \newcommand{\bfg}{\boldsymbol{g}} 14 | \newcommand{\bfp}{\boldsymbol{p}} 15 | \newcommand{\bfq}{\boldsymbol{q}} 16 | \newcommand{\bfx}{\boldsymbol{x}} 17 | \newcommand{\bfu}{\boldsymbol{u}} 18 | \newcommand{\bfv}{\boldsymbol{v}} 19 | \newcommand{\bfA}{\boldsymbol{A}} 20 | \newcommand{\bfB}{\boldsymbol{B}} 21 | \newcommand{\bfC}{\boldsymbol{C}} 22 | \newcommand{\bfM}{\boldsymbol{M}} 23 | \newcommand{\bfJ}{\boldsymbol{J}} 24 | \newcommand{\bfR}{\boldsymbol{R}} 25 | \newcommand{\bfT}{\boldsymbol{T}} 26 | \newcommand{\bfomega}{\boldsymbol{\omega}} 27 | \newcommand{\bftau}{\boldsymbol{\tau}} 28 | $$ 29 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/javascript/tree.js: -------------------------------------------------------------------------------- 1 | function createTree(rows, children) { 2 | if (rows === 0) { 3 | return { id: rows, children: [] }; 4 | } 5 | 6 | return { 7 | id: rows, 8 | children: [...Array(children).keys()].map(() => createTree(rows - 1, children)) 9 | }; 10 | } 11 | 12 | function dfsPreorder(tree) { 13 | console.log(tree.id); 14 | tree.children.forEach(dfsPreorder); 15 | } 16 | 17 | function dfsPostorder(tree) { 18 | tree.children.forEach(dfsPostorder); 19 | console.log(tree.id); 20 | } 21 | 22 | function dfsInorder(tree) { 23 | if (!tree) { 24 | return; 25 | } 26 | 27 | if (tree.children.length > 2) { 28 | throw new Error("Postorder traversal is only valid for binary trees"); 29 | } 30 | 31 | dfsInorder(tree.children[0]); 32 | console.log(tree.id); 33 | dfsInorder(tree.children[1]); 34 | } 35 | 36 | function dfsIterative(tree) { 37 | const stack = [tree]; 38 | while (stack.length > 0) { 39 | const current = stack.pop(); 40 | console.log(current.id); 41 | stack.push(...current.children); 42 | } 43 | } 44 | 45 | function bfs(tree) { 46 | const queue = [tree]; 47 | while (queue.length > 0) { 48 | const current = queue.shift(); 49 | console.log(current.id); 50 | queue.push(...current.children); 51 | } 52 | } 53 | 54 | const root = createTree(3, 3); 55 | dfsPreorder(root); 56 | dfsPostorder(root); 57 | dfsIterative(root); 58 | bfs(root); 59 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/python/Tree_example.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | 3 | def __init__(self): 4 | self.data = None 5 | self.children = [] 6 | 7 | def create_tree(node, num_row, num_child): 8 | node.data = num_row 9 | 10 | if num_row > 0: 11 | for i in range(num_child): 12 | child = create_tree(Node(), num_row-1, num_child) 13 | node.children.append(child) 14 | 15 | return node 16 | 17 | def DFS_recursive(node): 18 | if len(node.children) > 0: 19 | print(node.data) 20 | 21 | for child in node.children: 22 | DFS_recursive(child) 23 | 24 | def DFS_stack(node): 25 | stack = [] 26 | stack.append(node) 27 | 28 | temp = None 29 | 30 | while len(stack) > 0: 31 | print(stack[-1].data) 32 | temp = stack.pop() 33 | 34 | for child in temp.children: 35 | stack.append(child) 36 | 37 | def BFS_queue(node): 38 | queue = [] 39 | queue.append(node) 40 | 41 | temp = None 42 | 43 | while len(queue) > 0: 44 | print(queue[0].data) 45 | temp = queue.pop(0) 46 | 47 | for child in temp.children: 48 | queue.append(child) 49 | 50 | def main(): 51 | tree = create_tree(Node(), 3, 3) 52 | 53 | print("Recursive:") 54 | DFS_recursive(tree) 55 | 56 | print("Stack:") 57 | DFS_stack(tree) 58 | 59 | print("Queue:") 60 | BFS_queue(tree) 61 | 62 | main() 63 | 64 | -------------------------------------------------------------------------------- /chapters/decision_problems/stable_marriage/code/cs/GaleShapleyAlgorithm.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) with great help by gustorn and Marius Becker 2 | using System.Collections.Generic; 3 | 4 | namespace StableMarriageProblem 5 | { 6 | public static class GaleShapleyAlgorithm 7 | where TFollow : Person 8 | where TLead : Person 9 | { 10 | public static void RunGaleShapleyAlgorithm(List follows, List leads) 11 | { 12 | // All follows are lonely. 13 | var lonelyFollows = new List(follows); 14 | 15 | // Carry on until there are no lonely follows anymore. 16 | while (lonelyFollows.Count > 0) 17 | { 18 | // Let every lonely follow propose to their current top choice. 19 | foreach (var lonelyFollow in lonelyFollows) 20 | { 21 | lonelyFollow.ProposeToNext(); 22 | } 23 | 24 | // Look which follows have a partner now and which don't. 25 | var newLonelyFollows = new List(); 26 | foreach (var follow in follows) 27 | { 28 | if (follow.Partner == null) 29 | newLonelyFollows.Add(follow); 30 | } 31 | lonelyFollows = newLonelyFollows; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/graham_scan/code/javascript/graham-scan.js: -------------------------------------------------------------------------------- 1 | function grahamScan(points) { 2 | // First, sort the points so the one with the lowest y-coordinate comes first (the pivot) 3 | points = [...points].sort((a, b) => (a.y - b.y)); 4 | const pivot = points[0]; 5 | 6 | // Then sort all remaining points based on the angle between the pivot and itself 7 | const hull = points.slice(1).sort((a, b) => polarAngle(a, pivot) - polarAngle(b, pivot)); 8 | 9 | // The pivot is always on the hull 10 | hull.unshift(pivot); 11 | 12 | let n = hull.length; 13 | let m = 1; 14 | for (let i = 2; i < n; i++) { 15 | while (ccw(hull[m - 1], hull[m], hull[i]) <= 0) { 16 | if (m > 1) { 17 | m -= 1; 18 | } else if (m === i) { 19 | break; 20 | } else { 21 | i += 1; 22 | } 23 | } 24 | 25 | m += 1; 26 | [hull[i], hull[m]] = [hull[m], hull[i]]; 27 | } 28 | 29 | return hull.slice(0, m + 1); 30 | } 31 | 32 | function polarAngle(a, b) { 33 | return Math.atan2(a.y - b.y, a.x - b.x); 34 | } 35 | 36 | function ccw(a, b, c) { 37 | return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); 38 | } 39 | 40 | const points = [ 41 | { x: 1, y: 3 }, 42 | { x: 2, y: 4 }, 43 | { x: 4, y: 0 }, 44 | { x: 1, y: 0 }, 45 | { x: 0, y: 2 }, 46 | { x: 2, y: 2 }, 47 | { x: 3, y: 4 }, 48 | { x: 3, y: 1 }, 49 | ]; 50 | 51 | const convexHull = grahamScan(points); 52 | convexHull.forEach(p => console.log(`(${p.x}, ${p.y})`)); 53 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/gift_wrapping.md: -------------------------------------------------------------------------------- 1 | # Gift Wrapping 2 | If given a "gift", here defined as a random distribution of points in two or three dimensions, gift-wrapping algorithms allow programmers to find its convex hull -- the smallest convex shape that holds all interior points. 3 | This is one of the many cases where the leap from two to three dimensions leads to an incredibly more complicated code. 4 | That said, there is a rich history of algorithms to solve this problem. 5 | 6 | To be fair, only the Jarvis March is classified as *the* gift wrapping algorithm; however, it's a neat name to give algorithms that solve for the convex hull of a distribution of points. 7 | Strictly speaking, though, the term is not entirely accurate for all convex hull methods. 8 | 9 | 12 | $$ 13 | \newcommand{\d}{\mathrm{d}} 14 | \newcommand{\bff}{\boldsymbol{f}} 15 | \newcommand{\bfg}{\boldsymbol{g}} 16 | \newcommand{\bfp}{\boldsymbol{p}} 17 | \newcommand{\bfq}{\boldsymbol{q}} 18 | \newcommand{\bfx}{\boldsymbol{x}} 19 | \newcommand{\bfu}{\boldsymbol{u}} 20 | \newcommand{\bfv}{\boldsymbol{v}} 21 | \newcommand{\bfA}{\boldsymbol{A}} 22 | \newcommand{\bfB}{\boldsymbol{B}} 23 | \newcommand{\bfC}{\boldsymbol{C}} 24 | \newcommand{\bfM}{\boldsymbol{M}} 25 | \newcommand{\bfJ}{\boldsymbol{J}} 26 | \newcommand{\bfR}{\boldsymbol{R}} 27 | \newcommand{\bfT}{\boldsymbol{T}} 28 | \newcommand{\bfomega}{\boldsymbol{\omega}} 29 | \newcommand{\bftau}{\boldsymbol{\tau}} 30 | $$ 31 | 32 | -------------------------------------------------------------------------------- /chapters/decision_problems/decision_problems.md: -------------------------------------------------------------------------------- 1 | # Decision Problems 2 | I'll be honest here: I am not sure what section to put these problems in, so for now, they are in *Computational Mathematics*, but that may change in the near future. 3 | I'm also not sure whether we can classify these problems as *decision problems* at all; however, everything in this section is related to making informed decisions when assigning inputs to appropriate outputs. 4 | For example, the Hungarian algorithm reads in a bunch of inputs (candidates for certain jobs or positions) and assigns each input to an output task while minimizing the cost associated with all inputs performing their designated task. 5 | 6 | Overall, these problems come up all over the place and are certainly worth studying in their own right! 7 | 8 | 9 | 12 | $$ 13 | \newcommand{\d}{\mathrm{d}} 14 | \newcommand{\bff}{\boldsymbol{f}} 15 | \newcommand{\bfg}{\boldsymbol{g}} 16 | \newcommand{\bfp}{\boldsymbol{p}} 17 | \newcommand{\bfq}{\boldsymbol{q}} 18 | \newcommand{\bfx}{\boldsymbol{x}} 19 | \newcommand{\bfu}{\boldsymbol{u}} 20 | \newcommand{\bfv}{\boldsymbol{v}} 21 | \newcommand{\bfA}{\boldsymbol{A}} 22 | \newcommand{\bfB}{\boldsymbol{B}} 23 | \newcommand{\bfC}{\boldsymbol{C}} 24 | \newcommand{\bfM}{\boldsymbol{M}} 25 | \newcommand{\bfJ}{\boldsymbol{J}} 26 | \newcommand{\bfR}{\boldsymbol{R}} 27 | \newcommand{\bfT}{\boldsymbol{T}} 28 | \newcommand{\bfomega}{\boldsymbol{\omega}} 29 | \newcommand{\bftau}{\boldsymbol{\tau}} 30 | $$ 31 | 32 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/code/cs/BogoSort.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace BogoSort 6 | { 7 | public static class BogoSort 8 | { 9 | public static List RunBogoSort(List list) where T : IComparable 10 | { 11 | while (!IsSorted(list)) 12 | list = Shuffle(list, new Random()); 13 | 14 | return list; 15 | } 16 | 17 | private static bool IsSorted(List list) where T : IComparable 18 | { 19 | var sorted = true; 20 | 21 | for (int i = 0; i < list.Count - 1; i++) 22 | { 23 | if (!(0 >= list[i].CompareTo(list[i + 1]))) 24 | sorted = false; 25 | } 26 | if (!sorted) 27 | { 28 | sorted = true; 29 | for (int i = 0; i < list.Count - 1; i++) 30 | { 31 | if (!(0 <= list[i].CompareTo(list[i + 1]))) 32 | sorted = false; 33 | } 34 | } 35 | 36 | return sorted; 37 | } 38 | 39 | private static List Shuffle(List list, Random random) 40 | { 41 | for (int i = list.Count - 1; i > 0; i--) 42 | { 43 | var j = random.Next(0, i); 44 | var temp = list[i]; 45 | list[i] = list[j]; 46 | list[j] = temp; 47 | } 48 | return list; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/haskell/TreeTraversal.hs: -------------------------------------------------------------------------------- 1 | data Tree a = Node { node :: a 2 | , forest :: [Tree a] 3 | } deriving (Show) 4 | 5 | dfs :: Tree a -> [a] 6 | dfs (Node x ts) = x : concatMap dfs ts 7 | 8 | dfsPostOrder :: Tree a -> [a] 9 | dfsPostOrder (Node x ts) = concatMap dfsPostOrder ts ++ [x] 10 | 11 | dfsInOrder :: Tree a -> [a] -- For binary trees only 12 | dfsInOrder (Node x []) = [x] 13 | dfsInOrder (Node x [l]) = dfsInOrder l ++ [x] -- Single branch assumed to be left 14 | dfsInOrder (Node x [l, r]) = dfsInOrder l ++ [x] ++ dfsInOrder r 15 | dfsInOrder _ = error "Not a binary tree" 16 | 17 | bfs :: Tree a -> [a] 18 | bfs (Node x ts) = x : go ts 19 | where go [] = [] 20 | go ts = map node ts ++ go (concatMap forest ts) 21 | 22 | toBin :: Tree a -> Tree a 23 | toBin (Node x ts) = Node x (map toBin $ take 2 ts) 24 | 25 | main = do 26 | print $ dfs testTree 27 | print $ dfsPostOrder testTree 28 | print $ dfsInOrder $ toBin testTree 29 | print $ bfs testTree 30 | 31 | testTree :: Tree Int 32 | testTree = Node 1 [ Node 2 [ Node 3 [] 33 | , Node 4 [ Node 5 []] 34 | ] 35 | , Node 6 [ Node 7 [] 36 | , Node 8 [ Node 9 [ Node 10 [ Node 11 []] 37 | , Node 12 [] 38 | ] 39 | ] 40 | , Node 13 [ Node 14 []] 41 | ] 42 | , Node 15 [] 43 | ] 44 | -------------------------------------------------------------------------------- /chapters/matrix_methods/matrix_methods.md: -------------------------------------------------------------------------------- 1 | # Matrix Methods 2 | 3 | Mathematics is the foundation for many areas of science and engineering, and it is not uncommon for these applications to require the manipulation of large matrices. Though these applications are not mathematics, they use mathematics in everything they do and the methods to manipulate matrices are certainly mathematical. For this reason, I feel we should tour many methods used to manipulate matrices into any usable form. For the most part, we can divide the mathematical matrix methods into the following categories: 4 | 5 | 1. Diagonalization / Finding the Eigenvalues 6 | 2. Creating upper and lower diagonal matrices 7 | 3. Solving systems of Equations 8 | 9 | There are certainly more methods out there, so don't be offended if I have failed to list one of your favorite types of algorithms. We'll be filling more in as we go along! 10 | 11 | 12 | 15 | $$ 16 | \newcommand{\d}{\mathrm{d}} 17 | \newcommand{\bff}{\boldsymbol{f}} 18 | \newcommand{\bfg}{\boldsymbol{g}} 19 | \newcommand{\bfp}{\boldsymbol{p}} 20 | \newcommand{\bfq}{\boldsymbol{q}} 21 | \newcommand{\bfx}{\boldsymbol{x}} 22 | \newcommand{\bfu}{\boldsymbol{u}} 23 | \newcommand{\bfv}{\boldsymbol{v}} 24 | \newcommand{\bfA}{\boldsymbol{A}} 25 | \newcommand{\bfB}{\boldsymbol{B}} 26 | \newcommand{\bfC}{\boldsymbol{C}} 27 | \newcommand{\bfM}{\boldsymbol{M}} 28 | \newcommand{\bfJ}{\boldsymbol{J}} 29 | \newcommand{\bfR}{\boldsymbol{R}} 30 | \newcommand{\bfT}{\boldsymbol{T}} 31 | \newcommand{\bfomega}{\boldsymbol{\omega}} 32 | \newcommand{\bftau}{\boldsymbol{\tau}} 33 | $$ 34 | 35 | -------------------------------------------------------------------------------- /chapters/decision_problems/stable_marriage/code/cs/Person.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) with great help by gustorn and Marius Becker 2 | using System.Collections.Generic; 3 | 4 | namespace StableMarriageProblem 5 | { 6 | public class Person 7 | where TSelf : Person 8 | where TPref : Person 9 | { 10 | public string Name { get; set; } 11 | public TPref Partner { get; set; } 12 | public IList Choices { get; set; } 13 | // CurrentTopChoice equals the Choice in Choices that is the TopChoice, 14 | // if already tried women are not counted. 15 | public int CurrentTopChoiceIndex { get; set; } = 0; 16 | 17 | public Person(string name) => Name = name; 18 | 19 | public void ProposeToNext() 20 | { 21 | var interest = GetNextTopChoice(); 22 | 23 | // If the interest has no partner or prefers this person, 24 | // change interest's partner to this person. 25 | if (interest.Partner == null || 26 | interest.Choices.IndexOf(this as TSelf) < interest.Choices.IndexOf(interest.Partner)) 27 | { 28 | // Should the interest already have a partner, set the partner 29 | // of the interest's partner to null. 30 | if (interest.Partner != null) 31 | interest.Partner.Partner = null; 32 | interest.Partner = this as TSelf; 33 | Partner = interest; 34 | } 35 | } 36 | 37 | private TPref GetNextTopChoice() => Choices[CurrentTopChoiceIndex++]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/stacks.md: -------------------------------------------------------------------------------- 1 | ### Stacks and Queues 2 | 3 | Stacks and Queues are two sides of the same coin in computer science. They are both simple data structures that hold multiple elements, but allow you to use a single element at a time. The biggest difference between the two structures is the order in which you can access the elements in the data structure. 4 | 5 | In *stacks*, data follows *Last In, First Out* (LIFO), which basically means that whichever element you put in last will be the first element you take out. It acts exactly like a stack in real life. If you put a book on a stack of other books, the first book you will look at when sifting through the stack will be the book you just put on the stack. 6 | 7 | In *Queues*, data follows *First In, First Out* (FIFO), which means that whichever element you put in first will be the first element you take out. Imagine a queue of people. It would be unfair if the first person in line for groceries were not the first person to receive attention once the attendant finally shows up. 8 | 9 | For the most part, though, queues and stacks are treated the same way. There must be a way to: 10 | 1. look at the first element (`top()`) 11 | 2. to remove the first element (`pop()`) 12 | 3. to push elements onto the data structure (`push()`) 13 | 14 | The notation for this depends on the language you are using. Queues, for example, will often use `dequeue()` instead of `pop()` and `front()` instead of `top()`. You will see the language-specific details in the source code under the algorithms in this book, so for now it's simply important to know what stacks and queues are and how to access elements held within them. 15 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/graham_scan/code/julia/graham.jl: -------------------------------------------------------------------------------- 1 | type Point 2 | x::Float64 3 | y::Float64 4 | end 5 | 6 | function ccw(a::Point, b::Point, c::Point) 7 | return ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)) 8 | end 9 | 10 | function graham_scan(points::Vector{Point}) 11 | N = length(points) 12 | 13 | # Place the lowest point at the start of the array 14 | sort!(points, by = item -> item.y) 15 | 16 | # Sort all other points according to angle with that point 17 | other_points = sort(points[2:end], by = item -> atan2(item.y - points[1].y, 18 | item.x - points[1].x)) 19 | 20 | # Place points sorted by angle back into points vector 21 | for i in 1:length(other_points) 22 | points[i+1] = other_points[i] 23 | end 24 | 25 | # M will be the point on the hull 26 | M = 2 27 | i = 3 28 | for i = 1:N 29 | while (ccw(points[M-1], points[M], points[i]) <= 0) 30 | if (M > 2) 31 | M -= 1 32 | # All points are collinear 33 | elseif (i == N) 34 | break 35 | else 36 | i += 1 37 | end 38 | end 39 | 40 | # ccw point found, updating hull and swapping points 41 | M += 1 42 | points[i], points[M] = points[M], points[i] 43 | end 44 | 45 | return points[1:M] 46 | end 47 | 48 | function main() 49 | # This hull is just a simple test so we know what the output should be 50 | points = [Point(2,1.9), Point(1, 1), Point(2, 4), Point(3, 1), Point(2, 0)] 51 | hull = graham_scan(points) 52 | println(hull) 53 | end 54 | 55 | main() 56 | 57 | -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/classes.md: -------------------------------------------------------------------------------- 1 | ### Classes and Structs 2 | 3 | A while ago, one of my friends asked me the purpose of classes in programming. 4 | No matter what I did or how I tried to reason with him, I could not convince him that classes were useful and necessary programming constructs. 5 | To put it simply, classes are data types that allow programmers to store multiple data types within them. 6 | That said, depending on the language, classes might look slightly different. 7 | For example, Julia forgoes classes altogether and simply allows programmers to define a type of types. 8 | I am personally a fan of this approach and will be using it the bulk psuedocode for this text: 9 | 10 | ```julia 11 | type Human 12 | Height::Float64 13 | Weight::Float64 14 | Popularity::Float64 15 | end 16 | ``` 17 | 18 | Now, here's where things get a little sticky. 19 | The truth is that there is a philosophical difference between how languages implement classes (among other things), which basically boils down to whether languages allow functions to be held within data types or not. 20 | *Functional* programming languages argue that functions should always act on data types. 21 | *Object-Oriented* languages argue that certain data types (like Human, above), should be able to *do* things, so it makes sense to put functions within classes. 22 | There is merit to both of these arguments, so it's best to go with whatever you feel comfortable with. 23 | 24 | In the case of object-oriented languages, classes have an additional layer of complexity associated with them that should definitely be discussed. 25 | That said, I would like to forgo that discussion at this time and come back to it in the near future. 26 | Please bug me if you think I might have forgotten! 27 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/jarvis_march/code/julia/jarvis.jl: -------------------------------------------------------------------------------- 1 | struct Pos 2 | x::Float64 3 | y::Float64 4 | end 5 | 6 | function jarvis_cross(point1::Pos, point2::Pos, point3::Pos) 7 | vec1 = Pos(point2.x - point1.x, point2.y - point1.y) 8 | vec2 = Pos(point3.x - point2.x, point3.y - point2.y) 9 | ret_cross = vec1.x*vec2.y - vec1.y*vec2.x 10 | return ret_cross*ret_cross 11 | end 12 | 13 | function jarvis_march(points::Vector{Pos}) 14 | hull = Vector{Pos}() 15 | 16 | # sorting array based on leftmost point 17 | sort!(points, by = item -> item.x) 18 | push!(hull, points[1]) 19 | 20 | i = 1 21 | curr_point = points[2] 22 | 23 | # Find cross product between points 24 | curr_product = jarvis_cross(Pos(0,0), hull[1], curr_point) 25 | #while (curr_point != hull[1]) 26 | while (length(hull) < 4) 27 | for point in points 28 | product = 0.0 29 | if (i == 1) 30 | if (hull[i] != point) 31 | product = jarvis_cross(Pos(0,0), hull[i], point) 32 | end 33 | else 34 | if (hull[i] != point && hull[i-1] != point) 35 | product = jarvis_cross(hull[i-1], hull[i], point) 36 | end 37 | end 38 | if (product > curr_product) 39 | curr_point = point 40 | curr_product = product 41 | end 42 | end 43 | push!(hull, curr_point) 44 | curr_product = 0 45 | i += 1 46 | end 47 | 48 | return hull 49 | end 50 | 51 | function main() 52 | 53 | points = [Pos(2,1.5), Pos(1, 1), Pos(2, 4), Pos(3, 1)] 54 | hull = jarvis_march(points) 55 | println(hull) 56 | end 57 | 58 | main() 59 | -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/java/verlet.java: -------------------------------------------------------------------------------- 1 | // Submitted by lolatomroflsinnlos 2 | static void verlet(double pos, double acc, double dt){ 3 | 4 | // Note that we are using a temp variable for the previous position 5 | double prev_pos, temp_pos, time; 6 | prev_pos = pos; 7 | time = 0; 8 | 9 | while (pos > 0){ 10 | time += dt; 11 | temp_pos = pos; 12 | pos = pos*2 - prev_pos + acc * dt * dt; 13 | prev_pos = temp_pos; 14 | } 15 | 16 | System.out.println(time); 17 | 18 | } 19 | 20 | // Simple function for stormer-verlet 21 | static void stormer_verlet(double pos, double acc, double dt){ 22 | 23 | // Note that we are using a temp variable for the previous position 24 | double prev_pos, temp_pos, time, vel; 25 | prev_pos = pos; 26 | vel = 0; 27 | time = 0; 28 | while (pos > 0){ 29 | time += dt; 30 | temp_pos = pos; 31 | pos = pos*2 - prev_pos + acc * dt * dt; 32 | prev_pos = temp_pos; 33 | 34 | // The acceleration is constant, so the velocity is straightforward 35 | vel += acc*dt; 36 | } 37 | 38 | System.out.println(time); 39 | 40 | } 41 | 42 | // Simple function for velocity-verlet 43 | static void velocity_verlet(double pos, double acc, double dt){ 44 | 45 | // Note that we are using a temp variable for the previous position 46 | double time, vel; 47 | vel = 0; 48 | time = 0; 49 | while (pos > 0){ 50 | time += dt; 51 | pos += vel*dt + 0.5*acc * dt * dt; 52 | vel += acc*dt; 53 | } 54 | 55 | System.out.println(time); 56 | 57 | } 58 | 59 | public static void main(String[] args) { 60 | 61 | verlet(5.0, -10, 0.01); 62 | stormer_verlet(5.0, -10, 0.01); 63 | velocity_verlet(5.0, -10, 0.01); 64 | 65 | } 66 | 67 | -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/python/verlet.py: -------------------------------------------------------------------------------- 1 | # KingFredrickVI 2 | class Ball: 3 | 4 | def __init__(self, pos=0, vel=0, acc=0): 5 | self.pos = pos 6 | self.vel = vel 7 | self.acc = acc 8 | 9 | 10 | class Simulation: 11 | 12 | def __init__(self, obj, dt = 0.01): 13 | self.obj = obj 14 | self.dt = dt 15 | self.prev_pos = self.obj.pos 16 | 17 | def run(self): 18 | self.time = 0 19 | 20 | while self.obj.pos > 0: 21 | self.time += self.dt 22 | self.step() 23 | 24 | def step(self): 25 | pass 26 | 27 | 28 | class Verlet(Simulation): 29 | 30 | def step(self): 31 | temp_pos = self.obj.pos 32 | self.obj.pos = self.obj.pos * 2 - self.prev_pos + self.obj.acc * self.dt * self.dt 33 | self.prev_pos = temp_pos 34 | 35 | class Stormer_Verlet(Simulation): 36 | 37 | def step(self): 38 | temp_pos = self.obj.pos 39 | self.obj.pos = self.obj.pos * 2 - self.prev_pos + self.obj.acc * self.dt * self.dt 40 | self.prev_pos = temp_pos 41 | 42 | self.obj.vel += self.obj.acc * self.dt 43 | 44 | class Velocity_Verlet(Simulation): 45 | 46 | def step(self): 47 | self.obj.pos += self.obj.vel * self.dt + 0.5 * self.obj.acc * self.dt * self.dt 48 | self.obj.vel += self.obj.acc * self.dt 49 | 50 | 51 | def main(): 52 | sim = Verlet(Ball(pos = 5.0, acc = -10)) 53 | sim.run() 54 | 55 | print("Verlet:", sim.time) 56 | 57 | sim = Stormer_Verlet(Ball(pos = 5.0, acc = -10)) 58 | sim.run() 59 | 60 | print("Stormer Verlet:", sim.time) 61 | 62 | sim = Velocity_Verlet(Ball(pos = 5.0, acc = -10)) 63 | sim.run() 64 | 65 | print("Velocity Verlet:", sim.time) 66 | 67 | 68 | if __name__ == "__main__": 69 | main() 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/code/c++/bubblesort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using std::begin; 8 | using std::end; 9 | 10 | template 11 | std::vector generate_input(std::size_t size, Rng& rng) { 12 | auto dist = std::uniform_real_distribution<>(0.0, 1.0); 13 | 14 | auto ret = std::vector(); 15 | std::generate_n(std::back_inserter(ret), size, 16 | [&rng, &dist] { return dist(rng); }); 17 | 18 | return ret; 19 | } 20 | 21 | template 22 | void print_range(std::ostream& os, Iter const first, Iter const last) { 23 | os << '{'; 24 | 25 | if (first != last) { 26 | os << *first; 27 | std::for_each(first + 1, last, [&os] (double d) { os << ", " << d; }); 28 | } 29 | 30 | os << "}\n"; 31 | } 32 | 33 | template 34 | void bubble_sort(Iter const first, Iter const last) { 35 | if (first == last) { 36 | // the empty range is vacuously sorted 37 | return; 38 | } 39 | 40 | for (;;) { 41 | bool is_sorted = true; 42 | 43 | for (auto it = first; it + 1 != last; ++it) { 44 | // these are unsorted! gotta swap 'em 45 | if (*(it + 1) < *it) { 46 | using std::swap; 47 | swap(*it, *(it + 1)); 48 | is_sorted = false; 49 | } 50 | } 51 | 52 | if (is_sorted) { 53 | break; 54 | } 55 | } 56 | } 57 | 58 | int main() { 59 | std::random_device random_device; 60 | auto rng = std::mt19937(random_device()); 61 | 62 | auto input = generate_input(10, rng); 63 | 64 | std::cout << "before sorting:\n"; 65 | print_range(std::cout, begin(input), end(input)); 66 | 67 | bubble_sort(begin(input), end(input)); 68 | 69 | std::cout << "\nafter sorting:\n"; 70 | print_range(std::cout, begin(input), end(input)); 71 | } 72 | -------------------------------------------------------------------------------- /chapters/physics_solvers/verlet/code/c++/verlet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Simple function for velocity-verlet 4 | void verlet(double pos, double acc, double dt) { 5 | 6 | // Note that we are using a temp variable for the previous position 7 | double prev_pos, temp_pos, time; 8 | prev_pos = pos; 9 | time = 0; 10 | 11 | while (pos > 0) { 12 | time += dt; 13 | temp_pos = pos; 14 | pos = pos * 2 - prev_pos + acc * dt * dt; 15 | prev_pos = temp_pos; 16 | } 17 | 18 | std::cout << time << '\n'; 19 | } 20 | 21 | // Simple function for stormer-verlet 22 | void stormer_verlet(double pos, double acc, double dt) { 23 | 24 | // Note that we are using a temp variable for the previous position 25 | double prev_pos, temp_pos, time, vel; 26 | prev_pos = pos; 27 | vel = 0; 28 | time = 0; 29 | while (pos > 0) { 30 | time += dt; 31 | temp_pos = pos; 32 | pos = pos * 2 - prev_pos + acc * dt * dt; 33 | prev_pos = temp_pos; 34 | 35 | // The acceleration is constant, so the velocity is straightforward 36 | vel += acc * dt; 37 | } 38 | 39 | std::cout << time << '\n'; 40 | } 41 | 42 | void velocity_verlet(double pos, double acc, double dt) { 43 | 44 | double time, vel; 45 | vel = 0; 46 | time = 0; 47 | while (pos > 0) { 48 | time += dt; 49 | pos += vel * dt + 0.5 * acc * dt * dt; 50 | vel += acc * dt; 51 | } 52 | 53 | std::cout << time << '\n'; 54 | } 55 | 56 | int main() { 57 | 58 | // Note that depending on the simulation, you might want to have the verlet 59 | // loop outside. 60 | 61 | // For example, if your acceleration chages as a function of time, you might 62 | // need to also change the acceleration to be read into each of these 63 | // functions 64 | verlet(5.0, -10, 0.01); 65 | stormer_verlet(5.0, -10, 0.01); 66 | velocity_verlet(5.0, -10, 0.01); 67 | } 68 | -------------------------------------------------------------------------------- /chapters/sorting_searching/sorting_searching.md: -------------------------------------------------------------------------------- 1 | # Sorting and Searching 2 | When it comes to algorithms that programmers know and love, the stereotypical examples are often algorithms that either sort or search through a given container of elements. 3 | For the most part, sorting and searching methods are two sides to the same coin and are almost always described together due to their similarities. 4 | To be honest, they are also good thought exercises for new programmers. 5 | It's often inspiring to hear how individuals who have no programming experience go about solving the problem, because there are so many ways to do it! 6 | 7 | All said, sorting and searching are fundamental to numerous algorithms and really show how computer science has evolved with time to lower the complexity of problems that seem straightforward at first-glance. 8 | 9 | As the Archive evolves, more and more sorting algorithms will be added, so feel free to let me know your favorite algorithm and I'll do my best to put it in! 10 | Right now, there are only a few (straightforward) examples, so expect some more complicated algorithms in the future! 11 | 12 | 13 | 16 | $$ 17 | \newcommand{\d}{\mathrm{d}} 18 | \newcommand{\bff}{\boldsymbol{f}} 19 | \newcommand{\bfg}{\boldsymbol{g}} 20 | \newcommand{\bfp}{\boldsymbol{p}} 21 | \newcommand{\bfq}{\boldsymbol{q}} 22 | \newcommand{\bfx}{\boldsymbol{x}} 23 | \newcommand{\bfu}{\boldsymbol{u}} 24 | \newcommand{\bfv}{\boldsymbol{v}} 25 | \newcommand{\bfA}{\boldsymbol{A}} 26 | \newcommand{\bfB}{\boldsymbol{B}} 27 | \newcommand{\bfC}{\boldsymbol{C}} 28 | \newcommand{\bfM}{\boldsymbol{M}} 29 | \newcommand{\bfJ}{\boldsymbol{J}} 30 | \newcommand{\bfR}{\boldsymbol{R}} 31 | \newcommand{\bfT}{\boldsymbol{T}} 32 | \newcommand{\bfomega}{\boldsymbol{\omega}} 33 | \newcommand{\bftau}{\boldsymbol{\tau}} 34 | $$ 35 | 36 | -------------------------------------------------------------------------------- /chapters/differential_equations/euler/code/c++/euler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::begin; 10 | using std::end; 11 | 12 | using std::size_t; 13 | 14 | std::vector solve_euler(double timestep, size_t size) { 15 | std::vector result; 16 | double current = 1.0; 17 | std::generate_n(std::back_inserter(result), size, [&] { 18 | return std::exchange(current, current - 3.0 * current * timestep); 19 | }); 20 | return result; 21 | } 22 | 23 | /* 24 | check_result takes an iterator over doubles, 25 | and returns whether any value is outside the passed threshold. 26 | */ 27 | template 28 | bool check_result(Iter first, Iter last, double threshold, double timestep) { 29 | auto it = first; 30 | for (size_t idx = 0; it != last; ++idx, ++it) { 31 | double solution = std::exp(-3.0 * idx * timestep); 32 | if (std::abs(*it - solution) > threshold) { 33 | std::cout << "We found a value outside the threshold; the " << idx 34 | << "-th value was " << *it << ", but the expected solution was " 35 | << solution << '\n'; 36 | std::cout << "(the threshold was " << threshold 37 | << " and the difference was " << std::abs(*it - solution) 38 | << ")\n"; 39 | return true; 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | int main() { 46 | double threshold = 0.01; 47 | double timestep = 0.01; 48 | 49 | auto result = solve_euler(timestep, 100); 50 | auto outside_threshold = 51 | check_result(begin(result), end(result), threshold, timestep); 52 | auto msg = outside_threshold ? "yes :(" : "no :D"; 53 | 54 | std::cout << "Were any of the values outside of the threshold (" << threshold 55 | << ")? " << msg << '\n'; 56 | } 57 | -------------------------------------------------------------------------------- /chapters/decision_problems/stable_marriage/code/javascript/stable-marriage.js: -------------------------------------------------------------------------------- 1 | class Person { 2 | constructor(name) { 3 | this.name = name; 4 | } 5 | 6 | get hasFiance() { 7 | return !!this.fiance; 8 | } 9 | 10 | prefers(other) { 11 | return this.preferences.indexOf(other) < this.preferences.indexOf(this.fiance); 12 | } 13 | 14 | engageTo(other) { 15 | if (other.hasFiance) { 16 | other.fiance.fiance = undefined; 17 | } 18 | 19 | this.fiance = other; 20 | other.fiance = this; 21 | } 22 | } 23 | 24 | function stableMarriage(guys, girls) { 25 | const bachelors = [...guys]; 26 | while (bachelors.length > 0) { 27 | const guy = bachelors.shift(); 28 | for (const girl of guy.preferences) { 29 | if (!girl.hasFiance) { 30 | guy.engageTo(girl); 31 | break; 32 | } else if (girl.prefers(guy)) { 33 | bachelors.push(girl.fiance); 34 | guy.engageTo(girl); 35 | break; 36 | } 37 | } 38 | } 39 | } 40 | 41 | function shuffle(iterable) { 42 | const array = [...iterable]; 43 | for (let i = array.length - 1; i > 0; i--) { 44 | const j = Math.floor(Math.random() * (i + 1)); 45 | [array[i], array[j]] = [array[j], array[i]]; 46 | } 47 | return array; 48 | } 49 | 50 | const guys = [..."ABCDE"].map(name => new Person(name)); 51 | const girls = [..."FGHIJ"].map(name => new Person(name)); 52 | 53 | console.log("Guys"); 54 | for (const guy of guys) { 55 | guy.preferences = shuffle(girls); 56 | console.log(`${guy.name}: ${guy.preferences.map(p => p.name).join()}`) 57 | } 58 | 59 | console.log("\nGirls"); 60 | for (const girl of girls) { 61 | girl.preferences = shuffle(guys); 62 | console.log(`${girl.name}: ${girl.preferences.map(p => p.name).join()}`) 63 | } 64 | 65 | stableMarriage(guys, girls); 66 | 67 | console.log("\nPairings"); 68 | for (const guy of guys) { 69 | console.log(`${guy.name}: ${guy.fiance.name}`); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /chapters/convolutions/code/c/convolutions.c: -------------------------------------------------------------------------------- 1 | #include "fft.h" 2 | 3 | #include 4 | 5 | void conv(double complex *signal1, double complex *signal2, double complex* out, 6 | size_t n1, size_t n2) { 7 | double complex sum = 0; 8 | 9 | for (size_t i = 0; i < (n1 < n2? n2 : n1); ++i) { 10 | for (size_t j = 0; j < i; ++j) { 11 | if (j < n1) { 12 | sum += signal1[j] * signal2[i-j]; 13 | } 14 | } 15 | out[i] = sum; 16 | sum = 0; 17 | } 18 | } 19 | 20 | void conv_fft(double complex *signal1, double complex *signal2, 21 | double complex* out, size_t n) { 22 | fft(signal1, n); 23 | fft(signal2, n); 24 | 25 | for (size_t i = 0; i < n; ++i) { 26 | out[i] = signal1[i] * signal2[i]; 27 | } 28 | 29 | ifft(out, n); 30 | } 31 | 32 | int main() { 33 | double complex signal1[64], signal2[64], signal3[128], signal4[128], 34 | out1[128], out2[128]; 35 | 36 | for (size_t i = 0; i < 128; ++i) { 37 | if (i >= 16 && i < 48) { 38 | signal1[i] = 1.0; 39 | signal2[i] = 1.0; 40 | signal3[i] = 1.0; 41 | signal4[i] = 1.0; 42 | out1[i] = 0.0; 43 | out2[i] = 0.0; 44 | } else if (i >= 64) { 45 | signal3[i] = 0.0; 46 | signal4[i] = 0.0; 47 | out1[i] = 0.0; 48 | out2[i] = 0.0; 49 | } else { 50 | signal1[i] = 0.0; 51 | signal2[i] = 0.0; 52 | signal3[i] = 0.0; 53 | signal4[i] = 0.0; 54 | out1[i] = 0.0; 55 | out2[i] = 0.0; 56 | } 57 | } 58 | 59 | conv(signal1, signal2, out1, 64, 64); 60 | conv_fft(signal3, signal4, out2, 128); 61 | 62 | for (size_t i = 0; i < 64; ++i) { 63 | printf("%zu %f %+fi\n", i, creal(out1[i]) - creal(out2[i]), 64 | cimag(out1[i]) - cimag(out2[i])); 65 | } 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /chapters/principles_of_code/choosing_a_language/compiled/compiled.md: -------------------------------------------------------------------------------- 1 | ## Compiled Languages 2 | 3 | Programming is hard because we need to write instructions for our computer. 4 | The computer then reads this set of instructions and executes them accordingly. 5 | That's the story, at least. 6 | In principle, there is more to it: *compilation*. 7 | Compilation is the act of translating what we write into something the computer can read. 8 | This is done with a *compiler*. 9 | In this section, we will talk about all the compiled languages and discuss how to deal with different compilers and compiling options. 10 | 11 | The first book I read in C++ had a chapter devoted to running C++ code for the first time on Windows, Mac, and Linux devices. 12 | If I'm being honest, this was by far the most confusing part of programming for me. 13 | I could grasp the computing concepts, but getting the computer to run my code seemed like an impossible chore. 14 | I blame this somewhat on the text I was reading at the time, as it strongly encouraged the usage of Integrated Development Environments (IDE) that I couldn't figure out. 15 | IDE's are coding environments that pull up a GUI text editor to write and run code in. 16 | This is obviously an optimal way to program; however, I tend to dislike GUI-based solutions when there is a command-line option available. 17 | It wasn't until I saw a compilation command in my terminal that it started to make sense: 18 | 19 | ``` 20 | g++ hello_world.cpp -o output_executable 21 | ./output_executable 22 | ``` 23 | 24 | To me, this was elegant and straightforward. 25 | We compile code with a compiler, `g++`. 26 | We supply the code, `hello_world.cpp`. 27 | We tell the compiler where to output the code, `-o output_executable`. 28 | We execute the code, `./output_executable`. 29 | Done. 30 | 31 | Again, there is nothing wrong with using an IDE, they are incredibly useful for large software projects and often have debugging in-built, which is a huge benefit! 32 | I just find it easier to avoid GUI's whenever possible. 33 | -------------------------------------------------------------------------------- /chapters/data_compression/huffman/code/haskell/huffman.hs: -------------------------------------------------------------------------------- 1 | import qualified Data.Map as M 2 | import Data.List (insert, sort) 3 | 4 | data Tree a = Leaf Int a 5 | | Node Int (Tree a) (Tree a) 6 | deriving (Show, Eq) 7 | 8 | freq :: Tree a -> Int 9 | freq (Leaf i _) = i 10 | freq (Node i _ _) = i 11 | 12 | instance (Eq a) => Ord (Tree a) where 13 | compare t1 t2 = compare (freq t1) (freq t2) 14 | 15 | getFrequencies :: Ord a => [a] -> [(Int, a)] 16 | getFrequencies = toSortedList . M.fromListWith (+) . flip zip (repeat 1) 17 | where toSortedList = sort . map swap . M.toList 18 | swap (a, i) = (i, a) 19 | 20 | buildTree :: (Ord a) => [a] -> Maybe (Tree a) 21 | buildTree = build . map (uncurry Leaf) . getFrequencies 22 | where build [] = Nothing 23 | build [t] = Just t 24 | build (t1:t2:ts) = build $ insert (Node (freq t1 + freq t2) t1 t2) ts 25 | 26 | data Bit = Zero | One 27 | 28 | instance Show Bit where 29 | show Zero = "0" 30 | show One = "1" 31 | 32 | encode :: (Ord a) => [a] -> (Maybe (Tree a), [Bit]) 33 | encode s = (tree, msg) 34 | where 35 | tree = buildTree s 36 | msg = concatMap (table M.!) s 37 | table = case tree of 38 | Nothing -> M.empty 39 | Just t -> M.fromList $ mkTable (t, []) 40 | mkTable (Leaf _ a, p) = [(a, reverse p)] 41 | mkTable (Node _ t1 t2, p) = concatMap mkTable [(t1, Zero:p), (t2, One:p)] 42 | 43 | decode :: (Ord a) => Maybe (Tree a) -> [Bit] -> [a] 44 | decode Nothing _ = [] 45 | decode (Just t) m = path t m 46 | where path (Leaf _ a) m = a : path t m 47 | path (Node _ t1 _) (Zero: m) = path t1 m 48 | path (Node _ _ t2) (One: m) = path t2 m 49 | path _ _ = [] 50 | 51 | main = do 52 | let msg = "bibbity bobbity" 53 | (tree, encoded) = encode msg 54 | decoded = decode tree encoded 55 | putStrLn $ "Endoding \"" ++ msg ++ "\": " ++ concatMap show encoded 56 | putStrLn $ "Length: " ++ (show $ length encoded) 57 | putStrLn $ "Decoding: " ++ decoded 58 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/pseudo/Tree.pseudo: -------------------------------------------------------------------------------- 1 | # This has not been implemented in your chosen language, so here's pseudocode 2 | type Node{ 3 | vector{Int} children 4 | int ID; 5 | } 6 | 7 | # This has not been implemented in your chosen language, so here's pseudocode 8 | function DFS_recursive(Node n){ 9 | // Here we are doing something... 10 | print(n.ID) 11 | 12 | for child in n.children{ 13 | DFS_recursive(child) 14 | } 15 | } 16 | 17 | # This has not been implemented in your chosen language, so here's pseudocode 18 | function DFS_recursive_postorder(Node n){ 19 | 20 | for child in n.children{ 21 | DFS_recursive_postorder(child) 22 | } 23 | 24 | // Here we are doing something... 25 | print(n.ID) 26 | } 27 | 28 | # This has not been implemented in your chosen language, so here's pseudocode 29 | # This assumes only 2 children 30 | function DFS_recursive_inorder_btree(Node n){ 31 | 32 | if (size(n.children) > 2)){ 33 | print("Not a binary tree!") 34 | exit(1) 35 | } 36 | 37 | if (size(n.children) > 0){ 38 | DFS_recursive_inorder_btree(n.children[0]) 39 | print(n.ID) 40 | DFS_recursive_inorder_btree(n.children[1]) 41 | } 42 | else{ 43 | print(n.ID) 44 | } 45 | } 46 | 47 | # This has not been implemented in your chosen language, so here's pseudocode 48 | function DFS_stack(Node n){ 49 | stack s 50 | s.push(n) 51 | Node temp 52 | 53 | while(size(s) > 0){ 54 | print(s.top().ID) 55 | temp = s.top() 56 | s.pop() 57 | for child in temp.children{ 58 | s.push(child) 59 | } 60 | } 61 | } 62 | 63 | # This has not been implemented in your chosen language, so here's pseudocode 64 | function BFS_queue(Node n){ 65 | queue q 66 | q.push(n) 67 | Node temp 68 | 69 | while(size(q) > 0){ 70 | print(q.front().ID) 71 | temp = q.front() 72 | q.pop() 73 | for child in temp.children{ 74 | q.push(child) 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/ocaml/tree.ml: -------------------------------------------------------------------------------- 1 | (* submitted by Nicole Mazzuca (ubsan) *) 2 | module Tree : sig 3 | type t 4 | 5 | val leaf : int -> t 6 | 7 | val with_child : t -> t -> t 8 | 9 | val dfs_recursive : t -> unit 10 | 11 | val dfs_stack : t -> unit 12 | 13 | val bfs_queue : t -> unit 14 | end = struct 15 | type t = {children: t list; value: int} 16 | 17 | let leaf value = {children= []; value} 18 | 19 | let with_child {children; value} child = {children= child :: children; value} 20 | 21 | (* recursive is by far the easiest to do in functional langs *) 22 | let rec dfs_recursive self = 23 | Printf.printf "%d\n" self.value ; 24 | List.iter dfs_recursive self.children 25 | 26 | 27 | let dfs_stack self = 28 | let rec helper = function 29 | | [] -> () 30 | | x :: xs -> 31 | Printf.printf "%d\n" x.value ; 32 | helper (x.children @ xs) 33 | in 34 | helper [self] 35 | 36 | 37 | let bfs_queue self = 38 | let rec push_all queue = function 39 | | x :: xs -> Queue.add x queue ; push_all queue xs 40 | | [] -> () 41 | in 42 | let queue = Queue.create () in 43 | Queue.add self queue ; 44 | while not (Queue.is_empty queue) do 45 | let x = Queue.take queue in 46 | Printf.printf "%d\n" x.value ; 47 | push_all queue x.children 48 | done 49 | end 50 | 51 | let rec build_tree num_row num_child = 52 | let tree = Tree.leaf num_row in 53 | match num_row with 54 | | 0 -> tree 55 | | n -> 56 | let child = build_tree (num_row - 1) num_child in 57 | let rec helper child tree = function 58 | | 0 -> tree 59 | | n -> Tree.with_child (helper child tree (n - 1)) child 60 | in 61 | helper child tree num_child 62 | 63 | 64 | let main () = 65 | let tree = build_tree 3 3 in 66 | print_endline "--- dfs_recursive ---" ; 67 | Tree.dfs_recursive tree ; 68 | print_endline "--- dfs_stack ---" ; 69 | Tree.dfs_stack tree ; 70 | print_endline "--- bfs_queue ---" ; 71 | Tree.bfs_queue tree 72 | 73 | 74 | let () = main () 75 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "gitbook": "3.x.x", 3 | "plugins": ["mathjax", "bibtex-cite", "creativecommons", "wordcount", "theme-api", "include-codeblock", "ga"], 4 | "lunr": { 5 | "maxIndexSize": 1000000000 6 | }, 7 | "pluginsConfig": { 8 | "include-codeblock": { 9 | "fixlang": true, 10 | "unindent": true 11 | }, 12 | "ga": { 13 | "token": "UA-118252470-1" 14 | }, 15 | "theme-api": { 16 | "languages": [ 17 | { 18 | "lang": "jl", 19 | "name": "Julia", 20 | "default": true 21 | }, 22 | { 23 | "lang": "pseudo", 24 | "name": "Pseudocode" 25 | }, 26 | { 27 | "lang": "cs", 28 | "name": "C#" 29 | }, 30 | { 31 | "lang": "cpp", 32 | "name": "C++" 33 | }, 34 | { 35 | "lang": "c", 36 | "name": "C" 37 | }, 38 | { 39 | "lang": "py", 40 | "name": "Python" 41 | }, 42 | { 43 | "lang": "js", 44 | "name": "JavaScript" 45 | }, 46 | { 47 | "lang": "scratch", 48 | "name": "Scratch" 49 | }, 50 | { 51 | "lang": "hs", 52 | "name": "Haskell" 53 | }, 54 | { 55 | "lang": "rs", 56 | "name": "Rust" 57 | }, 58 | { 59 | "lang": "ml", 60 | "name": "OCaml" 61 | }, 62 | { 63 | "lang": "java", 64 | "name": "Java" 65 | }, 66 | { 67 | "lang": "clj", 68 | "name": "Clojure" 69 | }, 70 | { 71 | "lang": "elm", 72 | "name": "Elm" 73 | }, 74 | { 75 | "lang": "LabVIEW", 76 | "name": "LabVIEW" 77 | }, 78 | { 79 | "lang": "d", 80 | "name": "D" 81 | }, 82 | { 83 | "lang": "go", 84 | "name": "Go" 85 | }, 86 | { 87 | "lang": "swift", 88 | "name": "Swift" 89 | }, 90 | { 91 | "lang": "racket", 92 | "name": "Racket" 93 | }, 94 | { 95 | "lang": "m", 96 | "name": "Matlab" 97 | } 98 | 99 | ], 100 | "split": false 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/c++/tree_example.cpp: -------------------------------------------------------------------------------- 1 | // initially contributed by James Schloss (Leios) 2 | // restyled by Nicole Mazzuca (ubsan) 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using std::size_t; 14 | 15 | struct node { 16 | std::vector children; 17 | int value; 18 | }; 19 | 20 | // Simple recursive scheme for DFS 21 | void dfs_recursive(node const& n) { 22 | // Here we are doing something... 23 | std::cout << n.value << '\n'; 24 | for (auto const& child : n.children) { 25 | dfs_recursive(child); 26 | } 27 | } 28 | 29 | // Simple non-recursive scheme for DFS 30 | void dfs_stack(node const& n) { 31 | // this stack holds pointers into n's `children` vector, 32 | // or its children's `children` vector. 33 | std::stack stack; 34 | stack.push(&n); 35 | 36 | while (stack.size() > 0) { 37 | auto const& temp = *stack.top(); 38 | stack.pop(); 39 | std::cout << temp.value << '\n'; 40 | 41 | for (auto const& child : temp.children) { 42 | stack.push(&child); 43 | } 44 | } 45 | } 46 | 47 | // simple non-recursive scheme for BFS 48 | void bfs_queue(node const& n) { 49 | std::queue queue; 50 | queue.push(&n); 51 | 52 | while (queue.size() > 0) { 53 | auto const& temp = *queue.front(); 54 | queue.pop(); 55 | 56 | std::cout << temp.value << '\n'; 57 | for (auto const& child : temp.children) { 58 | queue.push(&child); 59 | } 60 | } 61 | } 62 | 63 | node create_tree(size_t num_row, size_t num_child) { 64 | if (num_row == 0) { 65 | return node{std::vector(), 0}; 66 | } 67 | 68 | std::vector vec; 69 | std::generate_n(std::back_inserter(vec), num_child, [&] { 70 | return create_node(num_row - 1, num_child); 71 | }); 72 | 73 | return node{std::move(vec), num_row}; 74 | } 75 | 76 | int main() { 77 | // Creating Tree in main 78 | auto root = create_node(3, 3); 79 | dfs_recursive(root); 80 | dfs_stack(root); 81 | bfs_queue(root); 82 | } 83 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/jarvis_march/code/c/jarvis_march.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct point { 6 | double x,y; 7 | }; 8 | 9 | struct point left_most_point(struct point *points, size_t num_points) { 10 | struct point ret = points[0]; 11 | 12 | for (size_t i = 0; i < num_points; ++i) { 13 | if (points[i].x < ret.x) { 14 | ret = points[i]; 15 | } else if(points[i].x == ret.x) { 16 | if (points[i].y < ret.y) { 17 | ret = points[i]; 18 | } 19 | } 20 | } 21 | 22 | return ret; 23 | } 24 | 25 | bool equal(struct point a, struct point b) { 26 | return a.x == b.x && a.y == b.y; 27 | } 28 | 29 | double winding(struct point p, struct point q, struct point r) { 30 | return (q.x - p.x)*(r.y - p.y) - (q.y - p.y)*(r.x - p.x); 31 | } 32 | 33 | size_t jarvis_march(struct point *points, struct point *hull_points, 34 | size_t num_points) { 35 | struct point hull_point = left_most_point(points, num_points); 36 | struct point end_point; 37 | 38 | size_t i = 0; 39 | do { 40 | hull_points[i] = hull_point; 41 | end_point = points[0]; 42 | 43 | for (size_t j = 1; j < num_points; ++j) { 44 | if (equal(end_point, hull_point) || 45 | winding(hull_points[i], end_point, points[j]) > 0.0) { 46 | end_point = points[j]; 47 | } 48 | } 49 | 50 | i++; 51 | hull_point = end_point; 52 | } while (!equal(end_point, hull_points[0])); 53 | 54 | return i; 55 | } 56 | 57 | int main() { 58 | struct point points[] = {{0.0, 0.0}, {-1.0, -1.0}, {1.0, 1.0}, {0.0, 1.0}, 59 | {0.0, -1.0}, {2.0, 2.0}}; 60 | struct point hull_points[6]; 61 | 62 | size_t num_hull_points = jarvis_march(points, hull_points, 6); 63 | 64 | printf("The Hull points are:\n"); 65 | for (size_t i = 0; i < num_hull_points; ++i) { 66 | printf("x=%f y=%f\n", hull_points[i].x, hull_points[i].y); 67 | } 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /chapters/matrix_methods/gaussian_elimination/code/julia/gaussian_elimination.jl: -------------------------------------------------------------------------------- 1 | function gaussian_elimination(A::Array{Float64,2}) 2 | 3 | rows = size(A,1) 4 | cols = size(A,2) 5 | 6 | # Main loop going through all columns 7 | for k = 1:min(rows,cols) 8 | 9 | # Step 1: finding the maximum element for each column 10 | max_index = indmax(abs.(A[k:end,k])) + k-1 11 | 12 | # Check to make sure matrix is good! 13 | if (A[max_index, k] == 0) 14 | println("matrix is singular! End!") 15 | exit(0) 16 | end 17 | 18 | # Step 2: swap row with highest value for that column to the top 19 | temp_vector = A[max_index, :] 20 | A[max_index, :] = A[k, :] 21 | A[k, :] = temp_vector 22 | #println(A) 23 | 24 | # Loop for all remaining rows 25 | for i = (k+1):rows 26 | 27 | # Step 3: finding fraction 28 | fraction = A[i,k]/A[k,k] 29 | 30 | # loop through all columns for that row 31 | for j = (k+1):cols 32 | 33 | # Step 4: re-evaluate each element 34 | A[i,j] -= A[k,j]*fraction 35 | 36 | end 37 | 38 | # Step 5: Set lower elements to 0 39 | A[i,k] = 0 40 | end 41 | end 42 | end 43 | 44 | function back_substitution(A::Array{Float64,2}) 45 | 46 | rows = size(A,1) 47 | cols = size(A,2) 48 | 49 | # Creating the solution Vector 50 | soln = Vector{Float64}(rows) 51 | 52 | # initialize the final element 53 | soln[rows] = A[rows, cols] / A[rows, cols-1] 54 | 55 | for i = (rows - 1):-1:1 56 | sum = 0.0 57 | for j = rows:-1:i 58 | sum += soln[j]*A[i,j] 59 | end 60 | soln[i] = (A[i, cols] - sum) / A[i, i] 61 | end 62 | 63 | return soln 64 | end 65 | 66 | function main() 67 | A = [2. 3 4 6; 68 | 1 2 3 4; 69 | 3 -4 0 10] 70 | 71 | gaussian_elimination(A) 72 | println(A) 73 | soln = back_substitution(A) 74 | 75 | for element in soln 76 | println(element) 77 | end 78 | end 79 | 80 | main() 81 | -------------------------------------------------------------------------------- /chapters/decision_problems/stable_marriage/code/cs/Program.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) with great help by gustorn and Marius Becker 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace StableMarriageProblem 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | Console.WriteLine("GaleShapleyAlgorithm"); 12 | // Using men and women as an example. 13 | var men = new List() 14 | { 15 | new Man("A"), 16 | new Man("B"), 17 | new Man("C"), 18 | new Man("D"), 19 | new Man("E") 20 | }; 21 | var women = new List() 22 | { 23 | new Woman("F"), 24 | new Woman("G"), 25 | new Woman("H"), 26 | new Woman("I"), 27 | new Woman("J"), 28 | }; 29 | 30 | var random = new Random(); 31 | 32 | foreach (var man in men) 33 | { 34 | man.Choices = new List(women).Shuffle(random); 35 | Console.WriteLine(man.Name + ":"); 36 | foreach (var choice in man.Choices) 37 | Console.Write(choice.Name); 38 | Console.WriteLine(); 39 | } 40 | foreach (var woman in women) 41 | { 42 | woman.Choices = new List(men).Shuffle(random); 43 | Console.WriteLine(woman.Name + ":"); 44 | foreach (var choice in woman.Choices) 45 | Console.Write(choice.Name); 46 | Console.WriteLine(); 47 | } 48 | 49 | GaleShapleyAlgorithm.RunGaleShapleyAlgorithm(women, men); 50 | 51 | foreach (var woman in women) 52 | { 53 | Console.WriteLine(woman.Name + " : " + woman?.Partner.Name); 54 | } 55 | } 56 | } 57 | 58 | public class Man : Person 59 | { 60 | public Man(string name) : base(name) { } 61 | } 62 | 63 | public class Woman : Person 64 | { 65 | public Woman(string name) : base(name) { } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /chapters/multiplication/multiplication.md: -------------------------------------------------------------------------------- 1 | # Multiplication 2 | Multiplying two numbers is a relatively simple process. 3 | For the most part, elementary school students learn how to do so quickly before moving on to more complicated mathematical operations. 4 | Even so, there are plenty of incredibly complicated algorithms out there to perform the operation. 5 | 6 | In some sense, this is what I love about computer science research! 7 | It takes operations that everyone knows and loves, abstracts them, and transforms them into fast and efficient methods for the computer to implement. 8 | Sometimes these algorithms are completely baffling. 9 | I remember laughing for ten minutes after I heard that fft convolutions could be used to calculate a simple integer multiplicationing the Schönhage–Strassen algorithm. 10 | I thought, "Why would you ever want to use an fft to do something to trivial? This has to be a joke!" 11 | 12 | Oh boy was I wrong. 13 | The Schönhage–Strassen algorithm was actually the most efficient method to multiply two numbers until around 2007 when it was dethroned by the Fürer's algorithm. 14 | Even so, the Schönhage–Strassen is still used in practice by the math libraries of many languages due to its straightforward implementation and a few other factors. 15 | 16 | Here's the point: through time, computer science researchers have managed to take some of the simplest operations imaginable, overcomplicate them, and make them incredibly impressive. 17 | Sometimes it's even worth looking at trivial operations through a new lens. 18 | 19 | 20 | 23 | $$ 24 | \newcommand{\d}{\mathrm{d}} 25 | \newcommand{\bff}{\boldsymbol{f}} 26 | \newcommand{\bfg}{\boldsymbol{g}} 27 | \newcommand{\bfp}{\boldsymbol{p}} 28 | \newcommand{\bfq}{\boldsymbol{q}} 29 | \newcommand{\bfx}{\boldsymbol{x}} 30 | \newcommand{\bfu}{\boldsymbol{u}} 31 | \newcommand{\bfv}{\boldsymbol{v}} 32 | \newcommand{\bfA}{\boldsymbol{A}} 33 | \newcommand{\bfB}{\boldsymbol{B}} 34 | \newcommand{\bfC}{\boldsymbol{C}} 35 | \newcommand{\bfM}{\boldsymbol{M}} 36 | \newcommand{\bfJ}{\boldsymbol{J}} 37 | \newcommand{\bfR}{\boldsymbol{R}} 38 | \newcommand{\bfT}{\boldsymbol{T}} 39 | \newcommand{\bfomega}{\boldsymbol{\omega}} 40 | \newcommand{\bftau}{\boldsymbol{\tau}} 41 | $$ 42 | 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Arcane Algorithm Archive 2 | The Arcane Algorithm Archive is a collaborative effort to create a guide for all important algorithms in all languages. 3 | This goal is obviously too ambitious for a book of any size, but it is a great project to learn from and work on and will hopefully become an incredible resource for programmers in the future. 4 | The book can be found here: https://www.algorithm-archive.org/. 5 | The GitHub repository can be found here: https://github.com/algorithm-archivists/algorithm-archive. 6 | Most algorithms have been covered on the YouTube channel LeiosOS: https://www.youtube.com/user/LeiosOS 7 | and live coded on Twitch: https://www.twitch.tv/simuleios. 8 | If you would like to communicate more directly, please feel free to go to our discord: https://discord.gg/Pr2E9S6. 9 | 10 | 11 | Note that the this project is is essentially a book about algorithms collaboratively written by an online community. 12 | Fortunately, there are a lot of algorithms out there, which means that there is a lot of content material available. 13 | Unfortunately, this means that we will probably never cover every algorithm ever created and instead need to focus on what the community sees as useful and necessary. 14 | That said, we'll still cover a few algorithms for fun that have very little, if any practical purpose. 15 | 16 | If you would like to contribute, feel free to go to any chapter with code associated with it and implement that algorithm in your favorite language, 17 | and then submit the code via pull request, following the submission guidelines found in `chapters/how_to_contribute.md` (or [here](chapters/how_to_contribute.md) if you are reading this on gitbook). 18 | 19 | Hopefully, this project will grow and allow individuals to learn about and try their hand at implementing different algorithms for fun and (potentially) useful projects. 20 | If nothing else, it will be an enjoyable adventure for our community. 21 | 22 | Thanks for reading and let me know if there's anything wrong or if you want to see something implemented in the future! 23 | 24 | 25 | ---- 26 | 27 | ## License 28 | The content of this project itself is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License (link below). The code examples are licensed under the MIT license (found in LICENSE.md). 29 | 30 | {% creativecommons type="by-nc" %} 31 | {% endcreativecommons %} 32 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/jarvis_march/code/jarvis.jl: -------------------------------------------------------------------------------- 1 | # Struct to hold an x, y position. A tuple would also be fine. 2 | struct Pos 3 | x::Float64 4 | y::Float64 5 | end 6 | 7 | # This returns a measure of how far "left" the vector is with a cross product 8 | function cross(point1::Pos, point2::Pos, point3::Pos) 9 | vec1 = Pos(point2.x - point1.x, point2.y - point1.y) 10 | vec2 = Pos(point3.x - point2.x, point3.y - point2.y) 11 | ret_angle = vec1.x*vec2.y - vec1.y*vec2.x 12 | return ret_angle*ret_angle 13 | end 14 | 15 | function jarvis_march(points::Vector{Pos}) 16 | hull = Vector{Pos}() 17 | 18 | # sorting array based on leftmost point 19 | sort!(points, by = item -> item.x) 20 | push!(hull, points[1]) 21 | 22 | i = 1 23 | curr_point = points[2] 24 | 25 | # Find angle between points 26 | curr_product = cross(Pos(0,0), hull[1], curr_point) 27 | 28 | # We will hold a temp variable with the highest cross product as we iterate 29 | # through all the points and move our hull vector forward. 30 | while (curr_point != hull[1]) 31 | for point in points 32 | product = 0.0 33 | 34 | # Special case for the first element when there is no hull[i-1] 35 | if (i == 1) 36 | if (hull[i] != point) 37 | product = cross(Pos(0,0), hull[i], point) 38 | end 39 | else 40 | if (hull[i] != point && hull[i-1] != point) 41 | product = cross(hull[i-1], hull[i], point) 42 | end 43 | end 44 | if (product > curr_product) 45 | curr_point = point 46 | curr_product = product 47 | end 48 | end 49 | 50 | # Pushing to hull, moving simulation forward and resetting the product 51 | push!(hull, curr_point) 52 | curr_product = 0 53 | i += 1 54 | end 55 | 56 | return hull 57 | end 58 | 59 | function main() 60 | 61 | # These points are chosen such that there is a clearly defined hull with 62 | # several interior points. As a note, these will be generated either 63 | # randomly or via some mesh in practice. 64 | points = [Pos(2,1.5), Pos(1, 1), Pos(2, 4), Pos(3, 1), Pos(2,2), Pos(2,0.5)] 65 | hull = jarvis_march(points) 66 | println(hull) 67 | end 68 | 69 | main() 70 | -------------------------------------------------------------------------------- /chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl: -------------------------------------------------------------------------------- 1 | using Plots 2 | pyplot() 3 | 4 | # struct to hold all parameters for simulation 5 | struct Param 6 | xmax::Float64 7 | res::Int64 8 | dt::Float64 9 | timesteps::Int64 10 | dx::Float64 11 | x::Vector{Float64} 12 | dk::Float64 13 | k::Vector{Float64} 14 | 15 | Param() = new(10.0, 512, 0.05, 1000, 2 * 10.0/512, 16 | Vector{Float64}(-10.0 + 10.0/512 : 20.0/512 : 10.0), 17 | pi / 10.0, 18 | Vector{Float64}(vcat(0:512/2 - 1, -512/2 : -1) * pi/10.0)) 19 | Param(xmax::Float64, res::Int64, dt::Float64, timesteps::Int64) = new( 20 | xmax, res, dt, timesteps, 21 | 2*xmax/res, Vector{Float64}(-xmax+xmax/res:2*xmax/res:xmax), 22 | pi/xmax, Vector{Float64}(vcat(0:res/2-1, -res/2:-1)*pi/xmax) 23 | ) 24 | end 25 | 26 | # struct to hold all operators 27 | mutable struct Operators 28 | V::Vector{Complex{Float64}} 29 | PE::Vector{Complex{Float64}} 30 | KE::Vector{Complex{Float64}} 31 | wfc::Vector{Complex{Float64}} 32 | end 33 | 34 | # Function to initialize the wfc and potential 35 | function init(par::Param, voffset::Float64, wfcoffset::Float64) 36 | V = 0.5 * (par.x - voffset).^2 37 | wfc = 3 * exp.(-(par.x - wfcoffset).^2/2) 38 | PE = exp.(-0.5*im*V*par.dt) 39 | KE = exp.(-0.5*im*par.k.^2*par.dt) 40 | 41 | opr = Operators(V, PE, KE, wfc) 42 | end 43 | 44 | # Function for the split-operator loop 45 | function split_op(par::Param, opr::Operators) 46 | 47 | for i = 1:par.timesteps 48 | # Half-step in real space 49 | opr.wfc = opr.wfc .* opr.PE 50 | 51 | # fft to phase space 52 | opr.wfc = fft(opr.wfc) 53 | 54 | # Full step in phase space 55 | opr.wfc = opr.wfc .* opr.KE 56 | 57 | # ifft back 58 | opr.wfc = ifft(opr.wfc) 59 | 60 | # final half-step in real space 61 | opr.wfc = opr.wfc .* opr.PE 62 | 63 | # plotting density and potential 64 | density = abs2.(opr.wfc) 65 | 66 | plot([density, real(opr.V)]) 67 | savefig("density" * string(lpad(i, 5, 0)) * ".png") 68 | println(i) 69 | end 70 | end 71 | 72 | # main function 73 | function main() 74 | par = Param(10.0, 512, 0.05, 1000) 75 | opr = init(par, 0.0, 1.0) 76 | split_op(par, opr) 77 | end 78 | 79 | main() 80 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/c/utility.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_H 2 | #define UTILITY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct stack { 10 | void **data; 11 | size_t top, capacity, size; 12 | }; 13 | 14 | struct queue { 15 | void **data; 16 | size_t front, back, capacity; 17 | }; 18 | 19 | struct stack get_stack(size_t size) { 20 | struct stack stk; 21 | 22 | stk.data = malloc(4 * size); 23 | stk.capacity = 4; 24 | stk.top = 0; 25 | 26 | return stk; 27 | } 28 | 29 | bool stack_empty(struct stack *stk) { 30 | return stk->top == 0; 31 | } 32 | 33 | void stack_push(struct stack *stk, void *element) { 34 | if (stk->top == stk->capacity) { 35 | stk->capacity *= 2; 36 | stk->data = realloc(stk->data, stk->capacity * sizeof(stk->data[0])); 37 | } 38 | 39 | stk->data[stk->top++] = element; 40 | } 41 | 42 | void *stack_pop(struct stack *stk) { 43 | if (stack_empty(stk)) { 44 | return NULL; 45 | } 46 | 47 | return stk->data[--stk->top]; 48 | } 49 | 50 | void free_stack(struct stack stk) { 51 | free(stk.data); 52 | } 53 | 54 | struct queue get_queue(size_t size) { 55 | struct queue q; 56 | 57 | q.data = calloc(4, size); 58 | q.front = 0; 59 | q.back = 0; 60 | q.capacity = 4; 61 | 62 | return q; 63 | } 64 | 65 | bool queue_empty(struct queue *q) { 66 | return q->front == q->back; 67 | } 68 | 69 | void queue_resize(struct queue *q) { 70 | size_t size = sizeof(q->data[0]); 71 | void **tmp = calloc((q->capacity * 2), size); 72 | memcpy(tmp, q->data + q->front, (q->capacity - q->front) * size); 73 | memcpy(tmp + q->capacity - q->front, q->data, (q->front - 1) * size); 74 | 75 | q->data = tmp; 76 | q->back = q->capacity - 1; 77 | q->front = 0; 78 | q->capacity *= 2; 79 | } 80 | 81 | void enqueue(struct queue *q, void *element) { 82 | if (q->front == (q->back % q->capacity) + 1) { 83 | queue_resize(q); 84 | } 85 | 86 | q->data[q->back] = element; 87 | q->back = (q->back + 1) % q->capacity; 88 | } 89 | 90 | void *dequeue(struct queue *q) { 91 | if (queue_empty(q)) { 92 | return NULL; 93 | } 94 | 95 | void *ret = q->data[q->front]; 96 | q->front = (q->front + 1) % q->capacity; 97 | 98 | return ret; 99 | } 100 | 101 | void free_queue(struct queue q) { 102 | free(q.data); 103 | } 104 | 105 | #endif //UTILITY_H 106 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/jarvis_march/code/cs/JarvisMarch.cs: -------------------------------------------------------------------------------- 1 | // submitted by Julian Schacher (jspp) with great help by gustorn 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace JarvisMarch 7 | { 8 | public struct Vector 9 | { 10 | public readonly int x; 11 | public readonly int y; 12 | 13 | public Vector(int xValue, int yValue) 14 | { 15 | this.x = xValue; 16 | this.y = yValue; 17 | } 18 | 19 | public override bool Equals(object obj) => obj is Vector v && this.x == v.x && this.y == v.y; 20 | public override int GetHashCode() => (17 * 23 + this.x) * 23 + this.y; 21 | 22 | public static bool operator==(Vector a, Vector b) => a.Equals(b); 23 | public static bool operator!=(Vector a, Vector b) => !(a == b); 24 | } 25 | 26 | public class JarvisMarch 27 | { 28 | public List Run(List points) 29 | { 30 | var convexHull = new List(); 31 | 32 | // Set the intial pointOnHull to the point of the list, where the x-position is the lowest. 33 | var pointOnHull = points.Aggregate((leftmost, current) => leftmost.x < current.x ? leftmost : current); 34 | 35 | // Continue searching for the next pointOnHull until the next pointOnHull is equal to the first point of the convex hull. 36 | do 37 | { 38 | convexHull.Add(pointOnHull); 39 | 40 | // Search for the next pointOnHull by looking which of the points is the next most outer point. 41 | pointOnHull = points.Aggregate((potentialNextPointOnHull, current) => 42 | { 43 | // Returns true, if potentialNextPointOnHull is equal to the current pointOnHull or if the current point is left of the line defined by pointOnHull and potentialNextPointOnHull. 44 | if (potentialNextPointOnHull == pointOnHull || IsLeftOf(pointOnHull, potentialNextPointOnHull, current)) 45 | return current; 46 | return potentialNextPointOnHull; 47 | }); 48 | 49 | // Check if the gift wrap is completed. 50 | } while (pointOnHull != convexHull[0]); 51 | 52 | return convexHull; 53 | } 54 | 55 | // Returns true, if p is left of the line defined by a and b. 56 | private bool IsLeftOf(Vector a, Vector b, Vector p) => (b.x - a.x) * (p.y - a.y) > (p.x - a.x) * (b.y - a.y); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TO DO 2 | 3 | The Algorithm Archive is currently being written and is quite small at the moment. 4 | This is a list of all the things we need to get done ASAP. 5 | That said, because of my (real-world) work schedule and such, ASAP is not as fast as I'd like, but that's how it goes. 6 | I apologize for taking so long with each chapter, but I figure making this list public is a good step towards being as open as possible. 7 | 8 | ## For James (Leios) 9 | 10 | Write: 11 | 12 | * Algorithms already covered (Chan's, Monte Carlo) 13 | * Language choices (Makefiles, Fortran, Julia...). Note that I kinda wanted to turn this into a series of sorts where I review each language with a series of standard tests. 14 | 15 | Revise: 16 | 17 | * Mathematical Background -- Transform into "mathematical methods." 18 | 19 | I'll try to keep this list updated as I write more sections 20 | 21 | ## Points of Discussion 22 | 23 | Here are points of discussion that need to be had about the Algorithm Archive before it gets too big and becomes too difficult to revise everything 24 | 25 | * **Should community-submitted code be clean or efficient?** When it comes to writing code, I often feel readability is the most important factor to keep in mind; however, with the code submitted to this archive, there will be pseudocode available to guide new folks through the process of writing the algorithm for the first time. For this reason, it might be best for the community to submit the most efficient code they can write in their own languages, commenting in any tricks to improve performance. 26 | * **Is the current method of writing optimal?** When I originally envisioned this project, I thought that I would do all the writing and the community would do (most of) the coding. That said, I am becoming more open to the idea of letting community members write for the Archive. The advantage to this is obvious: The book gets written faster. The disadvantage is also obvious: We lose focus and consistency throughout the book. 27 | * **We need a Logo.** I have no idea how to go about this. Maybe a logo contest at 16384 subscribers on youtube? The project will be large enough at that point to warrant a good logo. I really want something simple, though, like a [Trefoil Knot](https://en.wikipedia.org/wiki/Trefoil_knot#/media/File:Trefoil_knot_left.svg) or something. It kinda looks like 3 A's if you look at it the right way, and we'll definitely cover knot algorithms at some point because they are fascinating! 28 | 29 | Anyway, let me know what you think. I love the community we have here and appreciate all the conversations we've had so far! 30 | -------------------------------------------------------------------------------- /chapters/data_compression/huffman/code/javascript/huffman.js: -------------------------------------------------------------------------------- 1 | function encode(str) { 2 | const tree = createTree(str); 3 | const codebook = createCodebook(tree); 4 | return { 5 | string: [...str].map(c => codebook[c]).join(""), 6 | tree, 7 | codebook 8 | }; 9 | 10 | function createTree(str) { 11 | const chars = [...str]; 12 | const charCounts = chars.reduce((counts, char) => { 13 | counts[char] = (counts[char] || 0) + 1; 14 | return counts; 15 | }, {}); 16 | 17 | const nodes = Object.entries(charCounts).map(([key, weight]) => ({ key, weight })); 18 | const priorityQueue = makeQueue(nodes); 19 | while (priorityQueue.data.length > 1) { 20 | const left = priorityQueue.dequeue(); 21 | const right = priorityQueue.dequeue(); 22 | priorityQueue.enqueue({ weight: left.weight + right.weight, left, right }); 23 | } 24 | return priorityQueue.dequeue(); 25 | } 26 | 27 | function createCodebook(tree) { 28 | return recurse(tree, "", {}); 29 | 30 | function recurse(node, bitstring, dict) { 31 | if (!node.left && !node.right) { 32 | dict[node.key] = bitstring; 33 | } else { 34 | if (node.left) { 35 | recurse(node.left, bitstring + "0", dict); 36 | } 37 | 38 | if (node.right) { 39 | recurse(node.right, bitstring + "1", dict); 40 | } 41 | } 42 | return dict; 43 | } 44 | } 45 | } 46 | 47 | function decode(bitstring, tree) { 48 | const result = []; 49 | let node = tree; 50 | 51 | for (const bit of [...bitstring]) { 52 | node = bit === "0" ? node.left : node.right; 53 | if (!node.left && !node.right) { 54 | result.push(node.key); 55 | node = tree; 56 | } 57 | } 58 | 59 | return result.join(""); 60 | } 61 | 62 | // This queue implementation is horribly inefficient, but a proper, heap-based implementation would 63 | // be longer that the algorithm itself 64 | function makeQueue(iterable) { 65 | return { 66 | data: [...iterable].sort((a, b) => a.weight - b.weight), 67 | enqueue(value) { 68 | const target = this.data.findIndex(x => x.weight > value.weight); 69 | if (target === -1) { 70 | this.data.push(value); 71 | } else { 72 | this.data = [...this.data.slice(0, target), value, ...this.data.slice(target)]; 73 | } 74 | }, 75 | dequeue() { 76 | return this.data.shift(); 77 | } 78 | }; 79 | } 80 | 81 | const encoded = encode("bibbity bobbity"); 82 | const decoded = decode(encoded.string, encoded.tree); 83 | console.log(encoded.string); 84 | console.log(decoded); 85 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bogo/bogo_sort.md: -------------------------------------------------------------------------------- 1 | # Bogo Sort 2 | Look, Bogo Sort doesn't really sort anything out. 3 | In fact, it should never be used in practice for any reason I can think of and really only serves as a joke in the programming community. 4 | As far as jokes go, though, this one's pretty good. 5 | 6 | So, here's how it goes: 7 | imagine you have an array of $$n$$ elements that you want sorted. 8 | One way to do it is to shuffle the array at random and hope that all the elements will be magically in order after shuffling. 9 | If they are not in order, just shuffle everything again. 10 | And then again. And again. 11 | In the best case, this algorithm runs with a complexity of $$\Omega(1)$$, and in the worst, $$\mathcal{O}(\infty)$$. 12 | 13 | In code, it looks something like this: 14 | 15 | {% method %} 16 | {% sample lang="jl" %} 17 | [import:1-14, lang:"julia"](code/julia/bogo.jl) 18 | {% sample lang="cs" %} 19 | [import:9-15, lang:"csharp"](code/cs/BogoSort.cs) 20 | {% sample lang="clj" %} 21 | [import:2-10, lang:"clojure"](code/clojure/bogo.clj) 22 | {% sample lang="c" %} 23 | [import:4-27, lang:"c_cpp"](code/c/bogo_sort.c) 24 | {% sample lang="java" %} 25 | [import:2-17, lang:"java"](code/java/bogo.java) 26 | {% sample lang="js" %} 27 | [import:1-16, lang:"javascript"](code/js/bogo.js) 28 | {% sample lang="py" %} 29 | [import:4-12, lang:"python"](code/python/bogo.py) 30 | {% sample lang="hs" %} 31 | [import, lang:"haskell"](code/haskell/bogoSort.hs) 32 | {% sample lang="m" %} 33 | [import, lang:"matlab"](code/matlab/bogosort.m) 34 | {% sample lang="cpp" %} 35 | [import, lang:"c_cpp"](code/c++/bogosort.cpp) 36 | {% sample lang="rs" %} 37 | [import, lang:"rust"](code/rust/bogosort.rs) 38 | {% sample lang="swift" %} 39 | [import, lang:"swift"](code/swift/bogosort.swift) 40 | {% endmethod %} 41 | 42 | That's it. 43 | Ship it! 44 | We are done here! 45 | 46 | 47 | 50 | $$ 51 | \newcommand{\d}{\mathrm{d}} 52 | \newcommand{\bff}{\boldsymbol{f}} 53 | \newcommand{\bfg}{\boldsymbol{g}} 54 | \newcommand{\bfp}{\boldsymbol{p}} 55 | \newcommand{\bfq}{\boldsymbol{q}} 56 | \newcommand{\bfx}{\boldsymbol{x}} 57 | \newcommand{\bfu}{\boldsymbol{u}} 58 | \newcommand{\bfv}{\boldsymbol{v}} 59 | \newcommand{\bfA}{\boldsymbol{A}} 60 | \newcommand{\bfB}{\boldsymbol{B}} 61 | \newcommand{\bfC}{\boldsymbol{C}} 62 | \newcommand{\bfM}{\boldsymbol{M}} 63 | \newcommand{\bfJ}{\boldsymbol{J}} 64 | \newcommand{\bfR}{\boldsymbol{R}} 65 | \newcommand{\bfT}{\boldsymbol{T}} 66 | \newcommand{\bfomega}{\boldsymbol{\omega}} 67 | \newcommand{\bftau}{\boldsymbol{\tau}} 68 | $$ 69 | -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/loops.md: -------------------------------------------------------------------------------- 1 | ### Loops 2 | 3 | Loops are weird. I'm not going to lie, it took me a super long time to figure out how and when to use them appropriately. 4 | Nowadays, I see them as essential elements to almost any program I write. 5 | There two basic loop types: `for` and `while`, which are syntactically similar and reasonably intuitive. 6 | Let's say you want to walk out of a room with a closed door. 7 | In code, this might look something like: 8 | 9 | ```julia 10 | while(me.position < door.position) 11 | me.take_step() 12 | end 13 | 14 | me.open_door() 15 | ``` 16 | 17 | Like before, we assume that you are part of a type of `human`s with the functions `take_step()` and `open_door()`. 18 | Here, the `while` loop simply keeps going until the condition is no longer met, and it's assumed that the `take_step()` function changes your `position` value. 19 | When the condition returns `false`, we assume that you are either at the door or have run into it, so it's safe to assume you can use the `open_door()` function. 20 | 21 | The other possible loop type is the `for` loop, which is arguable more common and iterates through a container (such as `vectors` mentioned before). 22 | Often times, the `for` loop will look something like this: 23 | 24 | ```julia 25 | for i = 1:10 26 | print(i) 27 | end 28 | ``` 29 | 30 | In this case, we are creating a range of values between $$1$$ and $$10$$ and setting the value of $$i$$ every iteration of the loop. 31 | In this case $$i$$ is an interable variable that steps through the range of `1:10`, and is the primary reason for using a `for` loop instead of a `while` loop for the same task. 32 | To be clear, $$i$$ does not need to iterate through integers and could instead iterate through any number of types held in some other container. 33 | 34 | Ultimately, loops allow programmers to repeat the same operation multiple times and are the heart most programs and simulations I have seen. 35 | 36 | 37 | 40 | $$ 41 | \newcommand{\d}{\mathrm{d}} 42 | \newcommand{\bff}{\boldsymbol{f}} 43 | \newcommand{\bfg}{\boldsymbol{g}} 44 | \newcommand{\bfp}{\boldsymbol{p}} 45 | \newcommand{\bfq}{\boldsymbol{q}} 46 | \newcommand{\bfx}{\boldsymbol{x}} 47 | \newcommand{\bfu}{\boldsymbol{u}} 48 | \newcommand{\bfv}{\boldsymbol{v}} 49 | \newcommand{\bfA}{\boldsymbol{A}} 50 | \newcommand{\bfB}{\boldsymbol{B}} 51 | \newcommand{\bfC}{\boldsymbol{C}} 52 | \newcommand{\bfM}{\boldsymbol{M}} 53 | \newcommand{\bfJ}{\boldsymbol{J}} 54 | \newcommand{\bfR}{\boldsymbol{R}} 55 | \newcommand{\bfT}{\boldsymbol{T}} 56 | \newcommand{\bfomega}{\boldsymbol{\omega}} 57 | \newcommand{\bftau}{\boldsymbol{\tau}} 58 | $$ 59 | 60 | -------------------------------------------------------------------------------- /chapters/decision_problems/stable_marriage/code/julia/stable_marriage.jl: -------------------------------------------------------------------------------- 1 | # Submitted by Gustorn 2 | 3 | const mnames = ["A", "B", "C", "D"] 4 | const wnames = ["E", "F", "G", "H"] 5 | 6 | const Preferences = Dict{String,Vector{String}} 7 | const Pairs = Dict{String,String} 8 | 9 | # Returns a name => preference list dictionary, in decreasing order of preference 10 | function genpreferences(mannames::Vector{String}, womannames::Vector{String}) 11 | men = Dict(map(m -> (m, shuffle(womannames)), mannames)) 12 | women = Dict(map(w -> (w, shuffle(mannames)), womannames)) 13 | return men, women 14 | end 15 | 16 | # Returns if `person` prefers the `first` candidate over the `second` one. 17 | # This translates to `first` appearing *sooner* in the preference list 18 | prefers(prefs, person, first, second) = 19 | findfirst(m -> m == first, prefs[person]) < 20 | findfirst(m -> m == second, prefs[person]) 21 | 22 | isfree(person, pairs) = !haskey(pairs, person) 23 | 24 | function galeshapely(men::Preferences, women::Preferences) 25 | mentowomen = Dict{String,String}() 26 | womentomen = Dict{String,String}() 27 | while true 28 | bachelors = [m for m in keys(men) if isfree(m, mentowomen)] 29 | if length(bachelors) == 0 30 | return mentowomen, womentomen 31 | end 32 | 33 | for bachelor in bachelors 34 | for candidate in men[bachelor] 35 | if isfree(candidate, womentomen) 36 | mentowomen[bachelor] = candidate 37 | womentomen[candidate] = bachelor 38 | break 39 | elseif prefers(women, candidate, bachelor, womentomen[candidate]) 40 | delete!(mentowomen, womentomen[candidate]) 41 | mentowomen[bachelor] = candidate 42 | womentomen[candidate] = bachelor 43 | break 44 | end 45 | end 46 | end 47 | end 48 | end 49 | 50 | function isstable(men::Preferences, women::Preferences, mentowomen::Pairs, womentoman::Pairs) 51 | for (husband, wife) in mentowomen 52 | for candidate in men[husband] 53 | if candidate != wife && 54 | prefers(men, husband, candidate, wife) && 55 | prefers(women, candidate, husband, womentoman[candidate]) 56 | return false 57 | end 58 | end 59 | end 60 | return true 61 | end 62 | 63 | function main() 64 | men, women = genpreferences(mnames, wnames) 65 | mentowomen, womentomen = galeshapely(men, women) 66 | println(mentowomen) 67 | println(isstable(men, women, mentowomen, womentomen) ? "Stable" : "Unstable") 68 | end 69 | 70 | main() 71 | -------------------------------------------------------------------------------- /chapters/QI/QI.md: -------------------------------------------------------------------------------- 1 | # Quantum Information 2 | 3 | Quantum information theory is... intense. 4 | It requires a strong and fundamental understanding of classical information theory and quantum mechanics. 5 | It is not obvious in any way and deserves many textbooks on it's own. 6 | In fact, there are numerous textbooks on the subject already. 7 | The purpose of this section isn't to outdo any of that fundamental knowledge. 8 | Instead, we will attempt to distill the knowledge into a short, intuitive summary, with the hopes of helping people to understand more about the topic and pursue it further on their own. 9 | 10 | At the time of writing, true quantum computers do not exist. 11 | We do have some systems that are able to simulate qubits, they are not truly universal quantum computers. 12 | The closest market-ready system we currently have is D-WAVE, which boasts an impressive 128 qubits! 13 | 14 | There are many places to start an introduction to quantum information theory, so we'll go through it one step at a time: 15 | 16 | 1. **Quantum bitlogic:** what is a qubit and how is it different than a classical bit? 17 | 2. **Quantum gates and quantum circuits:** How do you fundamentally build a quantum algorithm? 18 | 3. **Quantum computers in the wild:** Current experimental techniques to create a quantum computer and what makes them ill-suited as real quantum computers 19 | 4. **A survey of current quantum algorithms:** There are a number of algorithms that promise fantastic advantages when performed on quantum computers and should really shake up the industry when they are finally experimentally realized. 20 | 21 | As a note, item 3 might seem out of place for a book on algorithms, and I would tend to agree; however, at this point there is a phenomenal amount of research being done to realize the first truly quantum computer and there are a number of potential systems that could work for this purpose. 22 | These systems will change how we think about and interface with quantum computation in the future and it is important to discuss where the field might be heading and when we can expect quantum computers at home. 23 | 24 | Now, there are not too many languages that can compile quantum code. 25 | A while ago, we tried to make a quantum circuit compiler, which was modeled after the SPICE circuit simulator, but this was far from a computer language. 26 | At this point in time, it is impossible to tell what quantum computing languages will look like when we finally have a truly quantum machine, so for the time being, we will not ask for community code for the chapters related to quantum information. 27 | 28 | basically, it's hard to imagine how to would adequately implement Shor's algorithm in C. 29 | As always, this section will be updated as we add more algorithms to the list. 30 | 31 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/julia/Tree.jl: -------------------------------------------------------------------------------- 1 | using DataStructures 2 | 3 | struct Node 4 | children::Vector{Node} 5 | ID::Int64 6 | Node(ID::Int64) = new(Vector{Node}(), ID) 7 | end 8 | 9 | function DFS_recursive(n::Node) 10 | # Here we are doing something... 11 | println(n.ID) 12 | 13 | for child in n.children 14 | DFS_recursive(child) 15 | end 16 | end 17 | 18 | function DFS_recursive_postorder(n::Node) 19 | 20 | for child in n.children 21 | DFS_recursive_postorder(child) 22 | end 23 | 24 | # Here we are doing something... 25 | println(n.ID) 26 | end 27 | 28 | # This assumes only 2 children, but accounts for other possibilities 29 | function DFS_recursive_inorder_btree(n::Node) 30 | 31 | if (length(n.children) == 2) 32 | DFS_recursive_inorder_btree(n.children[1]) 33 | println(n.ID) 34 | DFS_recursive_inorder_btree(n.children[2]) 35 | elseif (length(n.children) == 1) 36 | DFS_recursive_inorder_btree(n.children[1]) 37 | println(n.ID) 38 | elseif (length(n.children) == 0) 39 | println(n.ID) 40 | else 41 | println("Not a binary tree!") 42 | end 43 | end 44 | 45 | function DFS_stack(n::Node) 46 | s = Stack(Node) 47 | push!(s, n) 48 | 49 | while(length(s) > 0) 50 | println(top(s).ID) 51 | temp = pop!(s) 52 | for child in temp.children 53 | push!(s, child) 54 | end 55 | end 56 | end 57 | 58 | function BFS_queue(n::Node) 59 | q = Queue(Node) 60 | enqueue!(q, n) 61 | 62 | while(length(q) > 0) 63 | println(front(q).ID) 64 | temp = dequeue!(q) 65 | for child in temp.children 66 | enqueue!(q, child) 67 | end 68 | end 69 | end 70 | 71 | # function to create a simple, balanced tree 72 | function create_tree(num_row::Int64, num_child::Int64) 73 | ret = Node(num_row) 74 | if (num_row == 0) 75 | return ret 76 | end 77 | 78 | for i = 1:num_child 79 | child = create_tree(num_row - 1, num_child) 80 | push!(ret.children, child) 81 | end 82 | 83 | return ret 84 | end 85 | 86 | function main() 87 | 88 | println("Creating Tree") 89 | root = create_tree(2,3) 90 | 91 | println("Using recursive DFS:") 92 | DFS_recursive(root); 93 | 94 | println("Using stack-based DFS:") 95 | DFS_stack(root); 96 | 97 | println("Using queue-based BFS:") 98 | BFS_queue(root); 99 | 100 | println("Creating binary tree to test in-order traversal.") 101 | root_binary = create_tree(3,2) 102 | println("Using In-order DFS:") 103 | DFS_recursive_inorder_btree(root_binary) 104 | end 105 | 106 | main() 107 | -------------------------------------------------------------------------------- /chapters/matrix_methods/thomas/thomas.md: -------------------------------------------------------------------------------- 1 | # Thomas Algorithm 2 | 3 | As alluded to in the [Gaussian Elimination chapter](../gaussian_elimination/gaussian_elimination.md), the Thomas Algorithm (or TDMA -- Tri-Diagonal Matrix Algorithm) allows for programmers to **massively** cut the computational cost of their code from $$\sim O(n^3) \rightarrow \sim O(n)$$! This is done by exploiting a particular case of Gaussian Elimination, particularly the case where our matrix looks like: 4 | 5 | $$ 6 | \left[ 7 | \begin{array}{ccccc|c} 8 | b_0 & c_0 & & & & d_0 \\ 9 | a_1 & b_1 & c_1 & & & d_1 \\ 10 | & a_2 & \ddots & & & \vdots \\ 11 | & & & & c_{n-1}& d_{n-1} \\ 12 | & & & a_n & b_n & d_n 13 | \end{array} 14 | \right] 15 | $$ 16 | 17 | By this, I mean that our matrix is *Tri-Diagonal* (excluding the right-hand side of our system of equations, of course!). Now, at first, it might not be obvious how this helps; however, we may divide this array into separate vectors corresponding to $$a$$, $$b$$, $$c$$, and $$d$$ and then solve for $$x$$ with back-substitution, like before. 18 | 19 | In particular, we need to find an optimal scale factor for each row and use that. What is the scale factor? Well, it is the diagonal $$-$$ the multiplicative sum of the off-diagonal elements. 20 | In the end, we will update $$c$$ and $$d$$ to be $$c'$$ and $$d'$$ like so: 21 | 22 | $$ 23 | \begin{align} 24 | c'_i &= \frac{c_i}{b_i - a_i \times c'_{i-1}} \\ 25 | d'_i &= \frac{d_i - a_i*d'_{i-1}}{b_i - a_i \times c'_{i-1}} 26 | \end{align} 27 | $$ 28 | 29 | Of course, the initial elements will need to be specifically defined as 30 | 31 | $$ 32 | \begin{align} 33 | c'_0 = \frac{c_0}{b_0} 34 | d'_0 = \frac{d_0}{b_0} 35 | \end{align} 36 | $$ 37 | 38 | In code, this will look like this: 39 | 40 | {% method %} 41 | {% sample lang="jl" %} 42 | [import, lang:"julia"](code/julia/thomas.jl) 43 | {% endmethod %} 44 | 45 | This is a much simpler implementation than Gaussian Elimination and only has one for loop before back-substitution, which is why it has a better complexity case. 46 | 47 | 50 | $$ 51 | \newcommand{\d}{\mathrm{d}} 52 | \newcommand{\bff}{\boldsymbol{f}} 53 | \newcommand{\bfg}{\boldsymbol{g}} 54 | \newcommand{\bfp}{\boldsymbol{p}} 55 | \newcommand{\bfq}{\boldsymbol{q}} 56 | \newcommand{\bfx}{\boldsymbol{x}} 57 | \newcommand{\bfu}{\boldsymbol{u}} 58 | \newcommand{\bfv}{\boldsymbol{v}} 59 | \newcommand{\bfA}{\boldsymbol{A}} 60 | \newcommand{\bfB}{\boldsymbol{B}} 61 | \newcommand{\bfC}{\boldsymbol{C}} 62 | \newcommand{\bfM}{\boldsymbol{M}} 63 | \newcommand{\bfJ}{\boldsymbol{J}} 64 | \newcommand{\bfR}{\boldsymbol{R}} 65 | \newcommand{\bfT}{\boldsymbol{T}} 66 | \newcommand{\bfomega}{\boldsymbol{\omega}} 67 | \newcommand{\bftau}{\boldsymbol{\tau}} 68 | $$ 69 | 70 | -------------------------------------------------------------------------------- /chapters/FFT/code/c/fft.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void dft(double complex *X, const size_t N) { 9 | double complex tmp[N]; 10 | for (size_t i = 0; i < N; ++i) { 11 | tmp[i] = 0; 12 | for (size_t j = 0; j < N; ++j) { 13 | tmp[i] += X[j] * cexp(-2.0 * M_PI * I * j * i / N); 14 | } 15 | } 16 | 17 | memcpy(X, tmp, N * sizeof(*X)); 18 | } 19 | 20 | void cooley_tukey(double complex *X, const size_t N) { 21 | if (N >= 2) { 22 | double complex tmp [N / 2]; 23 | for (size_t i = 0; i < N / 2; ++i) { 24 | tmp[i] = X[2*i + 1]; 25 | X[i] = X[2*i]; 26 | } 27 | for (size_t i = 0; i < N / 2; ++i) { 28 | X[i + N / 2] = tmp[i]; 29 | } 30 | 31 | cooley_tukey(X, N / 2); 32 | cooley_tukey(X + N / 2, N / 2); 33 | 34 | for (size_t i = 0; i < N / 2; ++i) { 35 | X[i + N / 2] = X[i] - cexp(-2.0 * I * M_PI * i / N) * X[i + N / 2]; 36 | X[i] -= (X[i + N / 2]-X[i]); 37 | } 38 | } 39 | } 40 | 41 | void bit_reverse(double complex *X, size_t N) { 42 | for (int i = 0; i < N; ++i) { 43 | int n = i; 44 | int a = i; 45 | int count = (int)log2((double)N) - 1; 46 | 47 | n >>= 1; 48 | while (n > 0) { 49 | a = (a << 1) | (n & 1); 50 | count--; 51 | n >>= 1; 52 | } 53 | n = (a << count) & ((1 << (int)log2((double)N)) - 1); 54 | 55 | if (n > i) { 56 | double complex tmp = X[i]; 57 | X[i] = X[n]; 58 | X[n] = tmp; 59 | } 60 | } 61 | } 62 | 63 | void iterative_cooley_tukey(double complex *X, size_t N) { 64 | bit_reverse(X, N); 65 | 66 | for (int i = 1; i <= log2((double)N); ++i) { 67 | int stride = pow(2, i); 68 | double complex w = cexp(-2.0 * I * M_PI / stride); 69 | for (size_t j = 0; j < N; j += stride) { 70 | double complex v = 1.0; 71 | for (size_t k = 0; k < stride / 2; ++k) { 72 | X[k + j + stride / 2] = X[k + j] - v * X[k + j + stride / 2]; 73 | X[k + j] -= (X[k + j + stride / 2] - X[k + j]); 74 | v *= w; 75 | } 76 | } 77 | } 78 | } 79 | 80 | void approx(double complex *X, double complex *Y, size_t N) { 81 | for (size_t i = 0; i < N; ++i) { 82 | printf("%f\n", cabs(X[i]) - cabs(Y[i])); 83 | } 84 | } 85 | 86 | int main() { 87 | srand(time(NULL)); 88 | double complex x[64], y[64], z[64]; 89 | for (size_t i = 0; i < 64; ++i) { 90 | x[i] = rand() / (double) RAND_MAX; 91 | y[i] = x[i]; 92 | z[i] = x[i]; 93 | } 94 | 95 | cooley_tukey(y, 64); 96 | iterative_cooley_tukey(z, 64); 97 | 98 | approx(y, z, 64); 99 | 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/jarvis_march/jarvis_march.md: -------------------------------------------------------------------------------- 1 | # Jarvis March 2 | 3 | The first two-dimensional convex hull algorithm was originally developed by R. A. Jarvis in 1973 {{ "jm1973" | cite }}. 4 | Though other convex hull algorithms exist, this algorithm is often called *the* gift-wrapping algorithm. 5 | 6 | The idea behind this algorithm is simple. 7 | If we start with a random distribution of points, we can find the convex hull by first starting with the left-most point and using the origin to calculate an angle between every other point in the simulation. 8 | As a note, the "angle" can be roughly approximated with a cross-product or a dot product, which is common for some implementations here. 9 | Whichever point has the largest interior angle is chosen as the next point in the convex hull and we draw a line between the two points. 10 | From there, we use the two known points to again calculate the angle between all other points in the simulation. 11 | We then choose the point with the largest interior angle and move the simulation forward. 12 | We keep repeating this process until we have returned to our original point. 13 | The set of points chosen in this simulation will be the convex hull. 14 | 15 | As we might expect, this algorithm is not incredibly efficient and has a runtime of $$\mathcal{O}(nh)$$, where $$n$$ is the number of points and $$h$$ is the size of the hull. 16 | As a note, the Jarvis March can be generalized to higher dimensions. 17 | Since this algorithm, there have been many other algorithms that have advanced the field of two-dimensional gift-wrapping forward, including the Graham Scan and Chan's Algorithm, which will be discussed in due time. 18 | 19 | ### Bibliography 20 | 21 | {% references %} {% endreferences %} 22 | 23 | ### Example Code 24 | 25 | {% method %} 26 | {% sample lang="cs" %} 27 | ### C# # 28 | JarvisMarch.cs 29 | [import, lang="csharp"](code/cs/JarvisMarch.cs) 30 | Program.cs 31 | [import, lang="csharp"](code/cs/Program.cs) 32 | {% sample lang="jl" %} 33 | ### Julia 34 | [import, lang:"julia"](code/julia/jarvis.jl) 35 | {% sample lang="hs" %} 36 | ### Haskell 37 | [import, lang:"haskell"](code/haskell/jarvisMarch.hs) 38 | {% sample lang="c" %} 39 | ### C 40 | [import, lang:"c_cpp"](code/c/jarvis_march.c) 41 | {% sample lang="js" %} 42 | ### JavaScript 43 | [import, lang:"javascript"](code/javascript/jarvis-march.js) 44 | {% endmethod %} 45 | 46 | 49 | $$ 50 | \newcommand{\d}{\mathrm{d}} 51 | \newcommand{\bff}{\boldsymbol{f}} 52 | \newcommand{\bfg}{\boldsymbol{g}} 53 | \newcommand{\bfp}{\boldsymbol{p}} 54 | \newcommand{\bfq}{\boldsymbol{q}} 55 | \newcommand{\bfx}{\boldsymbol{x}} 56 | \newcommand{\bfu}{\boldsymbol{u}} 57 | \newcommand{\bfv}{\boldsymbol{v}} 58 | \newcommand{\bfA}{\boldsymbol{A}} 59 | \newcommand{\bfB}{\boldsymbol{B}} 60 | \newcommand{\bfC}{\boldsymbol{C}} 61 | \newcommand{\bfM}{\boldsymbol{M}} 62 | \newcommand{\bfJ}{\boldsymbol{J}} 63 | \newcommand{\bfR}{\boldsymbol{R}} 64 | \newcommand{\bfT}{\boldsymbol{T}} 65 | \newcommand{\bfomega}{\boldsymbol{\omega}} 66 | \newcommand{\bftau}{\boldsymbol{\tau}} 67 | $$ 68 | -------------------------------------------------------------------------------- /chapters/taylor/taylor_series.md: -------------------------------------------------------------------------------- 1 | NOTE: Incomplete! 2 | 3 | # Taylor Series Expansion 4 | 5 | I have been formally trained as a physicist. In my mind, there are several mathematical topics that blur the boundary between mathematics and physics. Taylor Series Expansions are one of those topics. 6 | 7 | On the one hand, I can see how the expansion could be considered purely mathematical. I mean, here is the definition: 8 | $$ 9 | f(x) \simeq \sum_{n=0}^{\infty} \frac{f^{(n)}(a)}{n!}(x-a)^n 10 | $$ 11 | 12 | where $$f(x)$$ is some function along real or complex space, $$a$$ is the point that we are expanding from, and $$f^{(n)}(x)$$ denotes the $$n^{\text{th}}$$ derivative of $$f(x)$$. 13 | From this perspective, the expansion just looks like a bunch of derivatives strung together! Where's the physics? Well, let's expand this series for the first few derivatives: 14 | 15 | $$ 16 | f(x) \simeq f(a) + \frac{df(a)}{dx}(x-a) 17 | + \frac{1}{2}\frac{d^2f(a)}{dx^2}(x-a)^2 18 | $$ 19 | 20 | If we substitute the derivatives for their physical quantities with $$f(x) \rightarrow x(t)$$, expanding from 0, and set 21 | 22 | $$ 23 | \begin{align} 24 | \frac{dx(t)}{dt} &= \text{velocity} = v(t) \\ 25 | \frac{d^2x(t)}{dt^2} &= \text{acceleration} = a \\ 26 | \end{align} 27 | $$ 28 | 29 | The Taylor series expansion turns into one of the most common formulas in classical physics, the *kinematic equation*! 30 | 31 | $$ 32 | x(t) \simeq x_0 + v_0t 33 | + \frac{1}{2}at^2 34 | $$ 35 | 36 | Note that here, we assume the acceleration to be constant, but it could technically have higher order terms. 37 | 38 | Truth be told, the Taylor Series Expansion can be found in the most unusual places and is used as the foundation of many different algorithms throughout this book. At first, it might not seem obvious why, but we can approximate almost any smooth function with a Taylor Series Expansion, and the more terms we include, the better our approximation becomes! For example, take Figure 1. Any function can be approximated as a sum of all the derivatives for that function. If we evaluate these derivatives at any point, we closely approximate the actual function. 39 | 40 | ![Function sum][function_sum] 41 | 42 | This shows the true power of the Taylor Series Expansion. It allows us to more easily tackle complicated functions by approximating them as functions we can actually use and imagine! 43 | 44 | [function_sum]: function_sum.png 45 | 46 | 47 | 50 | $$ 51 | \newcommand{\d}{\mathrm{d}} 52 | \newcommand{\bff}{\boldsymbol{f}} 53 | \newcommand{\bfg}{\boldsymbol{g}} 54 | \newcommand{\bfp}{\boldsymbol{p}} 55 | \newcommand{\bfq}{\boldsymbol{q}} 56 | \newcommand{\bfx}{\boldsymbol{x}} 57 | \newcommand{\bfu}{\boldsymbol{u}} 58 | \newcommand{\bfv}{\boldsymbol{v}} 59 | \newcommand{\bfA}{\boldsymbol{A}} 60 | \newcommand{\bfB}{\boldsymbol{B}} 61 | \newcommand{\bfC}{\boldsymbol{C}} 62 | \newcommand{\bfM}{\boldsymbol{M}} 63 | \newcommand{\bfJ}{\boldsymbol{J}} 64 | \newcommand{\bfR}{\boldsymbol{R}} 65 | \newcommand{\bfT}{\boldsymbol{T}} 66 | \newcommand{\bfomega}{\boldsymbol{\omega}} 67 | \newcommand{\bftau}{\boldsymbol{\tau}} 68 | $$ 69 | 70 | -------------------------------------------------------------------------------- /chapters/principles_of_code/principles_of_code.md: -------------------------------------------------------------------------------- 1 | # The Principles of Code 2 | 3 | At least to me, programming is a form of creative expression. Sure, programming is difficult. It's difficult in the same way that art, music, or writing is difficult: you know exactly what you want to create, but it takes time to learn how to create it. As I mentioned previously, for a significant portion of my life, I wanted to be an author, so I spent hours and hours every day writing fantasy novels. The more I wrote, the better I got at writing, but when I went back to read the initial chapters of my books, I was frankly revolted at how poor my writing was. By the time I finished revising those chapters and writing more on the side, I felt that the second half of the story was in need of revision too. In the end, I wrote and re-wrote and re-wrote again until I was sick of the story altogether, so I wrote something else. Same characters, different story. It was a vicious cycle that ultimately lead to failure on my part to publish anything. 4 | 5 | Here's that cycle again in code: 6 | 7 | ```julia 8 | type Human 9 | ability::Int64 10 | standard::Int64 11 | end 12 | 13 | function create_something(me::Human) 14 | while (me.ability < me.standard) 15 | me.ability += 1 16 | me.standard += 1 17 | println("I am not good enough. Continuing...") 18 | end 19 | end 20 | 21 | create_something(Human(0,1)) 22 | ``` 23 | 24 | I am sure this has a name, but I like to call it the *perfectionist's loop*. It's obviously endless and the only way out is by forcing the code to terminate early with `ctrl+c`. Any artist knows this problem. At first, the act of creation is fun, but after a few iterations, it becomes frustrating. Soon, you are curled into a ball in the corner of a room with a paintbrush in your hand and a myriad of colors splattered all over you and the immediate area. In front of you lay the remains of your art, toppled to the ground. It happens. It will probably happen when you learn programming. When it happens, there is only one thing to do: *keep iterating through the loop!* 25 | 26 | The moment you press `ctrl+c` is the moment you stop improving. Don't stop improving. Don't lower your standards. If you ever need motivation to continue, look at who you were a few months ago. You should be "better" than that person. If not, figure out what's holding you back and keep iterating through the loop! 27 | 28 | The problem is that when it comes to programming, there are a bunch of technical problems that crop up and prevent us from improving. This chapter is specifically written to help you make decisions and improve your ability to program. We'll start with choosing a language -- a question that kept me from even starting programming to begin with. Then we'll move on to programming building blocks and important data structures to remember. The idea is that we'll link to the building block sections when necessary throughout the book. This section will probably be the section that changes the most frequently as the archive evolves. after all, the more algorithms we cover, the more building blocks will be necessary to write them. 29 | 30 | As always, let me know if there's anything that is unclear or you think needs to be fixed! Thanks for reading and good luck! 31 | -------------------------------------------------------------------------------- /chapters/sorting_searching/bubble/bubble_sort.md: -------------------------------------------------------------------------------- 1 | # Bubble Sort 2 | When it comes to sorting algorithms, Bubble Sort is usually the first that comes to mind. 3 | Though it might not be the fastest tool in the shed, it's definitely straightforward to implement and is often the first sorting method new programmers think of when trying to implement a sorting method on their own. 4 | 5 | Here's how it works: we go through each element in our vector and check to see if it is larger than the element to it's right. 6 | If it is, we swap the elements and then move to the next element. 7 | In this way, we sweep through the array $$n$$ times for each element and continually swap any two adjacent elements that are improperly ordered. 8 | This means that we need to go through the vector $$\mathcal{O}(n^2)$$ times with code similar to the following: 9 | 10 | {% method %} 11 | {% sample lang="jl" %} 12 | [import:1-10, lang:"julia"](code/julia/bubble.jl) 13 | {% sample lang="cs" %} 14 | [import:9-27, lang:"csharp"](code/cs/BubbleSort.cs) 15 | {% sample lang="c" %} 16 | [import:3-21, lang:"c_cpp"](code/c/bubble_sort.c) 17 | {% sample lang="java" %} 18 | [import:2-12, lang:"java"](code/java/bubble.java) 19 | {% sample lang="js" %} 20 | [import:1-11, lang:"javascript"](code/js/bubble.js) 21 | {% sample lang="py" %} 22 | [import:4-9, lang:"python"](code/python/bubblesort.py) 23 | {% sample lang="m" %} 24 | [import:11-23, lang:"matlab"](code/matlab/bubblesort.m) 25 | {% sample lang="hs" %} 26 | [import, lang:"haskell"](code/haskell/bubbleSort.hs) 27 | {% sample lang="cpp" %} 28 | [import, lang:"c_cpp"](code/c++/bubblesort.cpp) 29 | {% sample lang="rs" %} 30 | [import:6-19, lang:"rust"](code/rust/bubble_sort.rs) 31 | {% sample lang="d" %} 32 | [import:3-18, lang:"d"](code/d/bubble_sort.d) 33 | {% sample lang="go" %} 34 | [import:7-21, lang:"golang"](code/go/bubbleSort.go) 35 | {% sample lang="racket" %} 36 | [import:5-19, lang:"racket"](code/racket/bubbleSort.rkt) 37 | {% sample lang="swift" %} 38 | [import:1-15, lang:"swift"](code/swift/bubblesort.swift) 39 | {% endmethod %} 40 | 41 | ... And that's it for the simplest bubble sort method. 42 | Now, as you might imagine, computer scientists have optimized this to the fiery lakes of Michigan and back, so we'll come back to this in the future and talk about how to optimize it. 43 | For now, it's fine to just bask in the simplicity that is bubble sort. 44 | Trust me, there are plenty of more complicated algorithms that do precisely the same thing, only much, much better (for most cases). 45 | 46 | 47 | 50 | $$ 51 | \newcommand{\d}{\mathrm{d}} 52 | \newcommand{\bff}{\boldsymbol{f}} 53 | \newcommand{\bfg}{\boldsymbol{g}} 54 | \newcommand{\bfp}{\boldsymbol{p}} 55 | \newcommand{\bfq}{\boldsymbol{q}} 56 | \newcommand{\bfx}{\boldsymbol{x}} 57 | \newcommand{\bfu}{\boldsymbol{u}} 58 | \newcommand{\bfv}{\boldsymbol{v}} 59 | \newcommand{\bfA}{\boldsymbol{A}} 60 | \newcommand{\bfB}{\boldsymbol{B}} 61 | \newcommand{\bfC}{\boldsymbol{C}} 62 | \newcommand{\bfM}{\boldsymbol{M}} 63 | \newcommand{\bfJ}{\boldsymbol{J}} 64 | \newcommand{\bfR}{\boldsymbol{R}} 65 | \newcommand{\bfT}{\boldsymbol{T}} 66 | \newcommand{\bfomega}{\boldsymbol{\omega}} 67 | \newcommand{\bftau}{\boldsymbol{\tau}} 68 | $$ 69 | -------------------------------------------------------------------------------- /chapters/tree_traversal/code/c/tree_traversal.c: -------------------------------------------------------------------------------- 1 | #include "utility.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct node { 8 | struct node *children; 9 | size_t children_size; 10 | int id; 11 | }; 12 | 13 | struct node create_tree(int rows, size_t num_children) { 14 | struct node n = {NULL, 0, rows}; 15 | 16 | if (rows > 0) { 17 | n.children = (struct node*)malloc(num_children * sizeof(struct node)); 18 | n.children_size = num_children; 19 | for (size_t i = 0; i < num_children; ++i) { 20 | n.children[i] = create_tree(rows - 1, num_children); 21 | } 22 | } 23 | 24 | return n; 25 | } 26 | 27 | void destroy_tree(struct node n) { 28 | if (n.id > 0) { 29 | for (size_t i = 0; i < n.children_size; ++i) { 30 | destroy_tree(n.children[i]); 31 | } 32 | 33 | free(n.children); 34 | } 35 | } 36 | 37 | void dfs_recursive(struct node n) { 38 | printf("%d\n", n.id); 39 | 40 | if (n.children) { 41 | for (size_t i = 0; i < n.children_size; ++i) { 42 | dfs_recursive(n.children[i]); 43 | } 44 | } 45 | } 46 | 47 | void dfs_recursive_postorder(struct node n) { 48 | for (size_t i = 0; i < n.children_size; ++i) { 49 | dfs_recursive_postorder(n.children[i]); 50 | } 51 | 52 | printf("%d\n", n.id); 53 | } 54 | 55 | void dfs_recursive_inorder_btree(struct node n) { 56 | switch (n.children_size) { 57 | case 2: 58 | dfs_recursive_inorder_btree(n.children[0]); 59 | printf("%d\n", n.id); 60 | dfs_recursive_inorder_btree(n.children[1]); 61 | break; 62 | case 1: 63 | dfs_recursive_inorder_btree(n.children[0]); 64 | printf("%d\n", n.id); 65 | break; 66 | case 0: 67 | printf("%d\n", n.id); 68 | break; 69 | default: 70 | printf("This is not a binary tree.\n"); 71 | break; 72 | } 73 | } 74 | 75 | void dfs_stack(struct node n) { 76 | struct stack stk = get_stack(sizeof(struct node*)); 77 | stack_push(&stk, &n); 78 | struct node *tmp; 79 | 80 | while (!stack_empty(&stk)) { 81 | tmp = (struct node*)stack_pop(&stk); 82 | if (!tmp) { 83 | break; 84 | } 85 | 86 | printf("%d\n", tmp->id); 87 | for (size_t i = 0; i < tmp->children_size; ++i) { 88 | stack_push(&stk, &tmp->children[i]); 89 | } 90 | } 91 | 92 | free_stack(stk); 93 | } 94 | 95 | void bfs_queue(struct node n) { 96 | struct queue q = get_queue(sizeof(struct node*)); 97 | enqueue(&q, &n); 98 | struct node *tmp; 99 | 100 | while (!queue_empty(&q)) { 101 | tmp = (struct node*)dequeue(&q); 102 | if (!tmp) { 103 | break; 104 | } 105 | 106 | printf("%d\n", tmp->id); 107 | for (size_t i = 0; i < tmp->children_size; ++i) { 108 | enqueue(&q, &tmp->children[i]); 109 | } 110 | } 111 | 112 | free_queue(q); 113 | } 114 | 115 | int main() { 116 | struct node root = create_tree(3, 3); 117 | bfs_queue(root); 118 | destroy_tree(root); 119 | 120 | return 0; 121 | } 122 | -------------------------------------------------------------------------------- /chapters/computational_geometry/gift_wrapping/graham_scan/code/c/graham.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | struct point { 8 | double x, y; 9 | }; 10 | 11 | int cmp_points(const void *a, const void *b) { 12 | struct point* pa = (struct point*) a; 13 | struct point* pb = (struct point*) b; 14 | 15 | if (pa->y > pb->y) { 16 | return 1; 17 | } else if (pa->y < pb->y) { 18 | return -1; 19 | } else { 20 | return 0; 21 | } 22 | } 23 | 24 | double ccw(struct point a, struct point b, struct point c) { 25 | return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x); 26 | } 27 | 28 | double polar_angle(struct point origin, struct point p) { 29 | return atan2(p.y - origin.y, p.x - origin.x); 30 | } 31 | 32 | void polar_angles_sort(struct point *points, struct point origin, size_t size) { 33 | if (size < 2) { 34 | return; 35 | } 36 | 37 | double pivot_angle = polar_angle(origin, points[size / 2]); 38 | 39 | int i = 0; 40 | int j = size - 1; 41 | while (1) { 42 | while (polar_angle(origin, points[i]) < pivot_angle) { 43 | i++; 44 | } 45 | while (polar_angle(origin, points[j]) > pivot_angle) { 46 | j--; 47 | } 48 | 49 | if (i >= j) { 50 | break; 51 | } 52 | 53 | struct point tmp = points[i]; 54 | points[i] = points[j]; 55 | points[j] = tmp; 56 | 57 | i++; 58 | j--; 59 | } 60 | 61 | polar_angles_sort(points, origin, i); 62 | polar_angles_sort(points + i, origin, size - i); 63 | } 64 | 65 | size_t graham_scan(struct point *points, size_t size) { 66 | qsort(points, size, sizeof(struct point), cmp_points); 67 | polar_angles_sort(points, points[0], size); 68 | 69 | struct point tmp_points[size + 1]; 70 | memcpy(tmp_points + 1, points, size * sizeof(struct point)); 71 | tmp_points[0] = tmp_points[size]; 72 | 73 | size_t m = 1; 74 | for (size_t i = 2; i <= size; ++i) { 75 | while (ccw(tmp_points[m - 1], tmp_points[m], tmp_points[i]) <= 0) { 76 | if (m > 1) { 77 | m--; 78 | continue; 79 | } else if (i == size) { 80 | break; 81 | } else { 82 | i++; 83 | } 84 | } 85 | 86 | m++; 87 | struct point tmp = tmp_points[i]; 88 | tmp_points[i] = tmp_points[m]; 89 | tmp_points[m] = tmp; 90 | } 91 | 92 | memcpy(points, tmp_points + 1, size * sizeof(struct point)); 93 | 94 | return m; 95 | } 96 | 97 | int main() { 98 | struct point points[] = {{2.0, 1.9}, {1.0, 1.0}, {2.0, 4.0}, {3.0, 1.0}, 99 | {2.0, 0.0}}; 100 | 101 | printf("Points:\n"); 102 | for (size_t i = 0; i < 5; ++i) { 103 | printf("(%f,%f)\n", points[i].x, points[i].y); 104 | } 105 | 106 | size_t hull_size = graham_scan(points, 5); 107 | 108 | printf("\nHull:\n"); 109 | for (size_t i = 0; i < hull_size; ++i) { 110 | printf("(%f,%f)\n", points[i].x, points[i].y); 111 | } 112 | 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /chapters/FFT/code/julia/fft.jl: -------------------------------------------------------------------------------- 1 | #simple DFT function 2 | function DFT(x) 3 | N = length(x) 4 | 5 | # We want two vectors here for real space (n) and frequency space (k) 6 | n = 0:N-1 7 | k = n' 8 | transform_matrix = exp.(-2im*pi*n*k/N) 9 | return transform_matrix*x 10 | 11 | end 12 | 13 | # Implementing the Cooley-Tukey Algorithm 14 | function cooley_tukey(x) 15 | N = length(x) 16 | 17 | if (N > 2) 18 | x_odd = cooley_tukey(x[1:2:N]) 19 | x_even = cooley_tukey(x[2:2:N]) 20 | else 21 | x_odd = x[1] 22 | x_even = x[2] 23 | end 24 | n = 0:N-1 25 | half = div(N,2) 26 | factor = exp.(-2im*pi*n/N) 27 | return vcat(x_odd + x_even .* factor[1:half], 28 | x_odd - x_even .* factor[1:half]) 29 | 30 | end 31 | 32 | function bitreverse(a::Array) 33 | # First, we need to find the necessary number of bits 34 | digits = convert(Int,ceil(log2(length(a)))) 35 | 36 | indices = [i for i = 0:length(a)-1] 37 | 38 | bit_indices = [] 39 | for i = 1:length(indices) 40 | push!(bit_indices, bits(indices[i])) 41 | end 42 | 43 | # Now stripping the unnecessary numbers 44 | for i = 1:length(bit_indices) 45 | bit_indices[i] = bit_indices[i][end-digits:end] 46 | end 47 | 48 | # Flipping the bits 49 | for i =1:length(bit_indices) 50 | bit_indices[i] = reverse(bit_indices[i]) 51 | end 52 | 53 | #replacing indices 54 | for i = 1:length(indices) 55 | indices[i] = 0 56 | for j = 1:digits 57 | indices[i] += 2^(j-1) * parse(string(bit_indices[i][end-j])) 58 | end 59 | indices[i] += 1 60 | end 61 | 62 | b = [float(i) for i = 1:length(a)] 63 | for i = 1:length(indices) 64 | b[i] = a[indices[i]] 65 | end 66 | 67 | return b 68 | end 69 | 70 | function iterative_cooley_tukey(x) 71 | N = length(x) 72 | logN = convert(Int,ceil(log2(length(x)))) 73 | bnum = div(N,2) 74 | stride = 0; 75 | 76 | x = bitreverse(x) 77 | 78 | z = [Complex(x[i]) for i = 1:length(x)] 79 | for i = 1:logN 80 | stride = div(N, bnum) 81 | for j = 0:bnum-1 82 | start_index = j*stride + 1 83 | y = butterfly(z[start_index:start_index + stride - 1]) 84 | for k = 1:length(y) 85 | z[start_index+k-1] = y[k] 86 | end 87 | end 88 | bnum = div(bnum,2) 89 | end 90 | 91 | return z 92 | end 93 | 94 | function butterfly(x) 95 | N = length(x) 96 | half = div(N,2) 97 | n = [i for i = 0:N-1] 98 | half = div(N,2) 99 | factor = exp.(-2im*pi*n/N) 100 | 101 | y = [0 + 0.0im for i = 1:length(x)] 102 | 103 | for i = 1:half 104 | y[i] = x[i] + x[half+i]*factor[i] 105 | y[half+i] = x[i] - x[half+i]*factor[i] 106 | end 107 | 108 | return y 109 | end 110 | 111 | function approx(x, y) 112 | val = true 113 | for i = 1:length(x) 114 | if (abs(x[i]) - abs(y[i]) > 1e-5) 115 | val = false 116 | end 117 | end 118 | println(val) 119 | end 120 | 121 | function main() 122 | x = rand(128) 123 | y = cooley_tukey(x) 124 | z = iterative_cooley_tukey(x) 125 | w = fft(x) 126 | approx(y, w) 127 | approx(z, w) 128 | end 129 | 130 | main() 131 | -------------------------------------------------------------------------------- /chapters/principles_of_code/building_blocks/functions.md: -------------------------------------------------------------------------------- 1 | ### Functions 2 | 3 | Functions make sense from a mathematical point of view. 4 | $$f(x) = 2x+5$$ returns a value for $$f(x)$$ at any point $$x$$ that you want. 5 | For example $$f(5) = 15$$, or $$f(10) = 25$$. 6 | Often times, the function is graphed for *every point* indicating the precise nature of how the function and variable relate to one another, but that is another matter entirely. 7 | For the most part, functions in programming work exactly the same way. 8 | They are dependent on certain variables and return something at the end. 9 | In code, the above function might look like: 10 | 11 | ``` 12 | function f(x) 13 | return 2*x+5 14 | end 15 | ``` 16 | 17 | Syntactically, they are a little different, but the content is identical. 18 | That said, it's not obvious how functions help when writing code at this point; however, this will become incredibly obvious once you see them in action. 19 | Basically, functions allow programmers to create reusable operations that can be called at any point in the code. 20 | In a sense, functions make understanding code much, much easier. 21 | 22 | ### Recursion 23 | 24 | Simply put, recursion is the process of putting a function inside itself. 25 | Now, I know what you are thinking, "Why does this deserve a special name?" 26 | That is a very good question and one that tooke me a while to understand. 27 | Let's take a simple example: 28 | 29 | ```julia 30 | function f(x) 31 | x = x + 1 32 | f(x) 33 | end 34 | ``` 35 | 36 | Every time `f(x)` is called, it calls `f(x)`, which then calls `f(x)` again and again and again... 37 | Basically, we just replicated a `while` loop! 38 | The problem here is that *we forgot a stop condition!* 39 | This means that our function will run forever, constantly incrementing the value of x for all eternity! 40 | 41 | There are many possible solutions, one of which looks like this: 42 | 43 | ```julia 44 | function f(x, cutoff) 45 | if (x < cutoff) 46 | x = x + 1 47 | f(x) 48 | end 49 | end 50 | ``` 51 | 52 | In the end, no matter how you choose to use recursion, you need to think carefully about what you want the code to do. 53 | For example, in the case shown here, recursion is definitely not the most straightforward way to increment the value of $$x$$ by $$1$$. 54 | In some cases, though, recursion not only makes the code easier to use and understand, but it might also be the only way to solve a provided problem. 55 | In addition, the proper use of recursion can speed up certain code tremendously. 56 | 57 | I guess the main point is this: *recursion is powerful, but with great power comes great resposibility!* 58 | 59 | 60 | 63 | $$ 64 | \newcommand{\d}{\mathrm{d}} 65 | \newcommand{\bff}{\boldsymbol{f}} 66 | \newcommand{\bfg}{\boldsymbol{g}} 67 | \newcommand{\bfp}{\boldsymbol{p}} 68 | \newcommand{\bfq}{\boldsymbol{q}} 69 | \newcommand{\bfx}{\boldsymbol{x}} 70 | \newcommand{\bfu}{\boldsymbol{u}} 71 | \newcommand{\bfv}{\boldsymbol{v}} 72 | \newcommand{\bfA}{\boldsymbol{A}} 73 | \newcommand{\bfB}{\boldsymbol{B}} 74 | \newcommand{\bfC}{\boldsymbol{C}} 75 | \newcommand{\bfM}{\boldsymbol{M}} 76 | \newcommand{\bfJ}{\boldsymbol{J}} 77 | \newcommand{\bfR}{\boldsymbol{R}} 78 | \newcommand{\bfT}{\boldsymbol{T}} 79 | \newcommand{\bfomega}{\boldsymbol{\omega}} 80 | \newcommand{\bftau}{\boldsymbol{\tau}} 81 | $$ 82 | 83 | -------------------------------------------------------------------------------- /chapters/decision_problems/stable_marriage/stable_marriage.md: -------------------------------------------------------------------------------- 1 | # The Stable Marriage Problem 2 | Imagine you have two groups, each of size $$n$$. 3 | Each individual within a group has an internal ranking associated with all members of the opposing group. 4 | The *Stable Matching Problem* attempts to unite both groups into stable pairs. 5 | In this case, a set of pairs is considered stable if there are no pairs that like each other more than their current partners. 6 | This doesn't mean that everyone gets their top choices, but if an individual prefers someone else who also prefers them back, the set of pairs is not stable. 7 | 8 | Now, this is often told as a story. 9 | One group is male, the other is female, and everyone gets married, hence the name the *Stable Marriage Problem*. 10 | This problem is solved by the Gale-Shapley algorithm, which can be simply described as follows: 11 | 12 | 1. All the men propose to their top choice of women. 13 | 2. The women become tentatively engaged to their top choice of the men who have proposed to them. 14 | 3. All rejected men propose to their next choice, and the women again select whichever man they prefer, possibly rejecting the one they were already engaged to. 15 | 16 | This process continues until all individuals are paired, which means that this algorithm guarantees stable matching and also has a $$\mathcal{O}(n^2)$$ runtime. 17 | To be clear, even though this algorithm seems conceptually simple, it is rather tricky to implement correctly. 18 | I do not at all claim that the code provided here is efficient and we will definitely be coming back to this problem in the future when we have more tools under our belt. 19 | I am incredibly interested to see what you guys do and how you implement the algorithm. 20 | 21 | {% method %} 22 | {% sample lang="jl" %} 23 | ### Julia 24 | [import, lang:"julia"](code/julia/stable_marriage.jl) 25 | {% sample lang="py" %} 26 | ### Python 27 | [import, lang:"python"](code/python/stable_marriage.py) 28 | {% sample lang="hs" %} 29 | ### Haskell 30 | [import, lang:"haskell"](code/haskell/stableMarriage.hs) 31 | {% sample lang="c" %} 32 | ### C 33 | [import, lang:"c_cpp"](code/c/stable_marriage.c) 34 | {% sample lang="cpp" %} 35 | ### C++ 36 | [import, lang:"c_cpp"](code/c++/stable_marriage.cpp) 37 | {% sample lang="js" %} 38 | ### JavaScript 39 | [import, lang:"javascript"](code/javascript/stable-marriage.js) 40 | {% sample lang="cs" %} 41 | ### C# # 42 | GaleShapleyAlgorithm.cs 43 | [import, lang:"csharp"](code/cs/GaleShapleyAlgorithm.cs) 44 | Person.cs 45 | [import, lang:"csharp"](code/cs/Person.cs) 46 | Program.cs 47 | [import, lang:"csharp"](code/cs/Program.cs) 48 | ListExtensions.cs 49 | [import, lang:"csharp"](code/cs/ListExtensions.cs) 50 | {% endmethod %} 51 | 52 | 55 | $$ 56 | \newcommand{\d}{\mathrm{d}} 57 | \newcommand{\bff}{\boldsymbol{f}} 58 | \newcommand{\bfg}{\boldsymbol{g}} 59 | \newcommand{\bfp}{\boldsymbol{p}} 60 | \newcommand{\bfq}{\boldsymbol{q}} 61 | \newcommand{\bfx}{\boldsymbol{x}} 62 | \newcommand{\bfu}{\boldsymbol{u}} 63 | \newcommand{\bfv}{\boldsymbol{v}} 64 | \newcommand{\bfA}{\boldsymbol{A}} 65 | \newcommand{\bfB}{\boldsymbol{B}} 66 | \newcommand{\bfC}{\boldsymbol{C}} 67 | \newcommand{\bfM}{\boldsymbol{M}} 68 | \newcommand{\bfJ}{\boldsymbol{J}} 69 | \newcommand{\bfR}{\boldsymbol{R}} 70 | \newcommand{\bfT}{\boldsymbol{T}} 71 | \newcommand{\bfomega}{\boldsymbol{\omega}} 72 | \newcommand{\bftau}{\boldsymbol{\tau}} 73 | $$ 74 | 75 | --------------------------------------------------------------------------------