From 29303df541f44dde593af69524b47196656697de Mon Sep 17 00:00:00 2001 From: Marius Becker Date: Sat, 9 Jun 2018 12:02:45 +0200 Subject: [PATCH 1/8] Removed trailing whitespace everywhere --- README.md | 4 +- TODO.md | 4 +- book.json | 4 +- book_ace.json | 6 +- chapters/FFT/code/julia/fft.jl | 4 +- chapters/FFT/cooley_tukey.md | 70 +++++------ chapters/QI/QI.md | 2 +- .../computational_geometry.md | 4 +- .../gift_wrapping/chan/chans.md | 2 +- .../gift_wrapping/gift_wrapping.md | 2 +- .../graham_scan/code/julia/graham.jl | 2 +- .../gift_wrapping/jarvis_march/code/jarvis.jl | 2 +- .../jarvis_march/jarvis_march.md | 4 +- chapters/data_compression/data_compression.md | 18 +-- .../huffman/code/clojure/huffman.clj | 8 +- .../huffman/code/cs/HuffmanCoding.cs | 8 +- .../huffman/code/julia/huffman.jl | 6 +- .../huffman/code/python/huffman.py | 24 ++-- .../decision_problems/decision_problems.md | 4 +- .../code/cs/GaleShapleyAlgorithm.cs | 4 +- .../stable_marriage/code/cs/Person.cs | 6 +- .../code/julia/stable_marriage.jl | 2 +- .../stable_marriage/stable_marriage.md | 2 +- chapters/differential_equations.md | 2 +- .../euler/backward_euler.md | 2 +- .../differential_equations/euler/euler.md | 2 +- chapters/euclidean_algorithm/euclidean.md | 6 +- chapters/getting_started.md | 18 +-- chapters/how_to_contribute.md | 18 +-- chapters/introduction.md | 2 +- chapters/math.md | 2 +- .../code/julia/gaussian_elimination.jl | 2 +- .../gaussian_elimination.md | 58 ++++----- chapters/matrix_methods/matrix_methods.md | 4 +- .../thomas/code/julia/thomas.jl | 2 +- chapters/matrix_methods/thomas/thomas.md | 12 +- chapters/monte_carlo/monte_carlo.md | 2 +- chapters/multiplication/multiplication.md | 10 +- chapters/physics_solvers/barnes_hut.md | 6 +- chapters/physics_solvers/quantum/quantum.md | 16 +-- .../quantum/split-op/code/julia/split_op.jl | 2 +- .../quantum/split-op/split-op.md | 2 +- .../verlet/code/java/verlet.java | 18 +-- .../verlet/code/python2/verlet.py | 2 +- .../verlet/code/rust/verlet.rs | 2 +- chapters/physics_solvers/verlet/verlet.md | 6 +- .../building_blocks/bitlogic.md | 14 +-- .../building_blocks/building_blocks.md | 4 +- .../building_blocks/classes.md | 6 +- .../building_blocks/conditions.md | 14 +-- .../building_blocks/functions.md | 18 +-- .../building_blocks/loops.md | 10 +- .../building_blocks/variables.md | 44 +++---- .../choosing_a_language.md | 82 ++++++------ .../choosing_a_language/compiled/compiled.md | 14 +-- chapters/principles_of_code/code_quality.md | 14 +-- .../principles_of_code/notation/notation.md | 60 ++++----- .../principles_of_code/principles_of_code.md | 4 +- .../principles_of_code/version_control.md | 118 +++++++++--------- .../bogo/code/cs/BogoSort.cs | 2 +- .../bubble/code/cs/BubbleSort.cs | 2 +- .../bubble/code/python/bubblesort.py | 2 +- .../sorting_searching/sorting_searching.md | 2 +- chapters/taylor/taylor_series.md | 6 +- chapters/tree_traversal/code/cs/Tree/Tree.cs | 8 +- .../cs/TreeMdAdditional/TreeMdAdditional.cs | 4 +- .../code/javascript/Tree_example.js | 4 +- .../code/python3/Tree_example.py | 26 ++-- chapters/tree_traversal/code/rust/tree.rs | 2 +- 69 files changed, 424 insertions(+), 424 deletions(-) diff --git a/README.md b/README.md index 3d4032d99..ae8bd12fe 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # The Arcane Algorithm Archive -The Arcane Algorithm Archive is a collaborative effort to create a guide for all important algorithms in all languages. +The Arcane Algorithm Archive is a collaborative effort to create a guide for all important algorithms in all languages. 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. The book can be found here: https://www.algorithm-archive.org/. The github repository can be found here: https://github.com/algorithm-archivists/algorithm-archive. @@ -8,7 +8,7 @@ and livecoded on Twitch: https://www.twitch.tv/simuleios. If you would like to communicate more directly, please feel free to go to our discord: https://discord.gg/Pr2E9S6. -Note that the this project is is essentially a book about algorithms collaboratively written by an online community. +Note that the this project is is essentially a book about algorithms collaboratively written by an online community. Fortunately, there are a lot of algorithms out there, which means that there is a lot of content material available. 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. That said, we'll still cover a few algorithms for fun that have very little, if any practical purpose. diff --git a/TODO.md b/TODO.md index c66c5d2be..59cb25022 100644 --- a/TODO.md +++ b/TODO.md @@ -23,7 +23,7 @@ I'll try to keep this list updated as I write more sections 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 * **Should community-submitted code be clean or efficeint?** 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 psudocode 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. -* **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. -* **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! +* **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. +* **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! Anyway, let me know what you think. I love the community we have here and appreciate all the conversations we've had so far! diff --git a/book.json b/book.json index 0f621ffb6..3033ee1fe 100644 --- a/book.json +++ b/book.json @@ -25,7 +25,7 @@ }, { "lang": "cs", - "name": "C#" + "name": "C#" }, { "lang": "cpp", @@ -79,7 +79,7 @@ "lang": "LabVIEW", "name": "LabVIEW" } - + ], "split": false } diff --git a/book_ace.json b/book_ace.json index 8f47c96ef..270bf2e08 100644 --- a/book_ace.json +++ b/book_ace.json @@ -18,14 +18,14 @@ }, { "lang": "cs", - "name": "C#" + "name": "C#" }, { "lang": "c", - "name": "C" + "name": "C" } ], - "split": true + "split": true }, "include-codeblock": { "template": "ace", diff --git a/chapters/FFT/code/julia/fft.jl b/chapters/FFT/code/julia/fft.jl index 0481f16ab..03291fb8c 100644 --- a/chapters/FFT/code/julia/fft.jl +++ b/chapters/FFT/code/julia/fft.jl @@ -25,7 +25,7 @@ function cooley_tukey(x) half = div(N,2) factor = exp.(-2im*pi*n/N) return vcat(x_odd + x_even .* factor[1:half], - x_odd - x_even .* factor[1:half]) + x_odd - x_even .* factor[1:half]) end @@ -84,7 +84,7 @@ function iterative_cooley_tukey(x) for k = 1:length(y) z[start_index+k-1] = y[k] end - end + end bnum = div(bnum,2) end diff --git a/chapters/FFT/cooley_tukey.md b/chapters/FFT/cooley_tukey.md index 041f61610..f6ffafaa9 100644 --- a/chapters/FFT/cooley_tukey.md +++ b/chapters/FFT/cooley_tukey.md @@ -1,15 +1,15 @@ ## What Makes a Fourier Transform Fast? -If there were ever an algorithm to radically change the landscape of computer science and engineering by making seemingly impossible problems possible, it would be the Fast Fourier Transform (FFT). +If there were ever an algorithm to radically change the landscape of computer science and engineering by making seemingly impossible problems possible, it would be the Fast Fourier Transform (FFT). On the surface, the algorithm seems like a simple application of recursion, and in principle, that is exactly what it is; however, the Fourier Transform is no ordinary transform -- it allows researchers and engineers to easily bounce back and forth between real space and frequency space and is the heart of many physics and engineering applications. -From calculating superfluid vortex positions to super-resolution imaging, Fourier Transforms lay at the heart of many scientific disciplines and are essential to many algorithms we will cover later in this book. +From calculating superfluid vortex positions to super-resolution imaging, Fourier Transforms lay at the heart of many scientific disciplines and are essential to many algorithms we will cover later in this book. -Simply put, the Fourier Transform is a beautiful application of complex number systems; however, it would rarely be used today if not for the ability to quickly perform the operation with Fast Fourier Transform, first introduced by the great Frederick Gauss in 1805 and later independently discovered by James Cooley and John Tukey in 1965 {{ "ct1965" | cite }}. +Simply put, the Fourier Transform is a beautiful application of complex number systems; however, it would rarely be used today if not for the ability to quickly perform the operation with Fast Fourier Transform, first introduced by the great Frederick Gauss in 1805 and later independently discovered by James Cooley and John Tukey in 1965 {{ "ct1965" | cite }}. Gauss (of course) already had too many things named after him and Cooley and Tukey both had cooler names, so the most common algorithm for FFT's today is known as the Cooley-Tukey algorithm. ### What is a Fourier Transform? -To an outsider, the Fourier Transform looks like a mathematical mess -- certainly a far cry from the heroic portal between two domains I have depicted it to be; however, like most things, it's not as bad as it initially appears to be. +To an outsider, the Fourier Transform looks like a mathematical mess -- certainly a far cry from the heroic portal between two domains I have depicted it to be; however, like most things, it's not as bad as it initially appears to be. So, here it is in all it's glory! $$F(\xi) = \int_{-\infty} ^\infty f(x) e^{-2 \pi i x \xi} dx$$ @@ -18,24 +18,24 @@ and $$f(x) = \int_{-\infty} ^\infty F(\xi) e^{2 \pi i \xi x} d\xi$$ -Where $$F(\xi)$$ represents a function in frequency space, $$\xi$$ represents a value in frequency space, $$f(x)$$ represents a function in real space, and $$x$$ represents a value in the real space. -Note here that the only difference between the two exponential terms is a minus sign in the transformation to frequency space. +Where $$F(\xi)$$ represents a function in frequency space, $$\xi$$ represents a value in frequency space, $$f(x)$$ represents a function in real space, and $$x$$ represents a value in the real space. +Note here that the only difference between the two exponential terms is a minus sign in the transformation to frequency space. As I mentioned, this is not intuitive syntax, so please allow me to explain a bit. Firstly, **what does the Fourier Transform do?** If we take a sum sinusoidal functions (like $$\sin(\omega t)$$ or $$\cos(\omega t)$$), we might find a complicated mess of waves between $$\pm 1$$. Each constituent wave can be described by only one value: $$\omega$$. -So, instead of representing these curves as seen above, we could instead describe them as peaks in frequency space, as shown below. +So, instead of representing these curves as seen above, we could instead describe them as peaks in frequency space, as shown below.

-This is what the Fourier Transform does! +This is what the Fourier Transform does! After performing the transform, it is now much, much easier to understand precisely which frequencies are in our waveform, which is essential to most areas of signal processing. -Now, how does this relate to the transformations above? +Now, how does this relate to the transformations above? Well, the easiest way is to substitute in the Euler's formula: $$e^{2 \pi i \theta} = \cos(2 \pi \theta) + i \sin(2 \pi \theta)$$ @@ -48,10 +48,10 @@ and our function in real space into: $$f(x) = \int_{-\infty} ^\infty F(\xi) (\cos(2 \pi \xi x) + i \sin(2 \pi \xi x))e^{2 \pi i \xi x} d\xi$$ -Here, the $$\sin$$ and $$\cos$$ functions are clearly written in the formulas, so it looks much friendlier, right? -This means that a point in real space is defined by the integral over all space of it's corresponding frequency function multiplied by sinusoidal oscillations. +Here, the $$\sin$$ and $$\cos$$ functions are clearly written in the formulas, so it looks much friendlier, right? +This means that a point in real space is defined by the integral over all space of it's corresponding frequency function multiplied by sinusoidal oscillations. -Truth be told, even after seeing this math, I still didn't understand Fourier Transforms. +Truth be told, even after seeing this math, I still didn't understand Fourier Transforms. Truth be told, I didn't understand it fully until I discretized real and frequency space to create the Discrete Fourier Transform (DFT), which is the only way to implement Fourier Transforms in code. ### What is a Discrete Fourier Transform? @@ -60,12 +60,12 @@ In principle, the Discrete Fourier Transform (DFT) is simply the Fourier transfo $$X_k = \sum_{n=0}^{N-1} x_n \cdot e^{-2 \pi k n / N}$$ -and +and $$x_n = \frac{1}{N} \sum_{k=0}^{N-1} X_k \cdot e^{2 \pi k n / N}$$ -Where $$X_n$$ and $$x_n$$ are sequences of $$N$$ numbers in frequency and real space, respectively. -In principle, this is no easier to understand than the previous case! +Where $$X_n$$ and $$x_n$$ are sequences of $$N$$ numbers in frequency and real space, respectively. +In principle, this is no easier to understand than the previous case! For some reason, though, putting code to this transformation really helped me figure out what was actually going on. {% method %} @@ -83,21 +83,21 @@ For some reason, though, putting code to this transformation really helped me fi [import:2-11, lang:"julia"](code/julia/fft.jl) {% endmethod %} -In this function, we define `n` to be a set of integers from $$0 \rightarrow N-1$$ and arrange them to be a column. -We then set `k` to be the same thing, but in a row. -This means that when we multiply them together, we get a matrix, but not just any matrix! +In this function, we define `n` to be a set of integers from $$0 \rightarrow N-1$$ and arrange them to be a column. +We then set `k` to be the same thing, but in a row. +This means that when we multiply them together, we get a matrix, but not just any matrix! This matrix is the heart to the transformation itself! ``` -M = [1.0+0.0im 1.0+0.0im 1.0+0.0im 1.0+0.0im; - 1.0+0.0im 6.12323e-17-1.0im -1.0-1.22465e-16im -1.83697e-16+1.0im; - 1.0+0.0im -1.0-1.22465e-16im 1.0+2.44929e-16im -1.0-3.67394e-16im; +M = [1.0+0.0im 1.0+0.0im 1.0+0.0im 1.0+0.0im; + 1.0+0.0im 6.12323e-17-1.0im -1.0-1.22465e-16im -1.83697e-16+1.0im; + 1.0+0.0im -1.0-1.22465e-16im 1.0+2.44929e-16im -1.0-3.67394e-16im; 1.0+0.0im -1.83697e-16+1.0im -1.0-3.67394e-16im 5.51091e-16-1.0im] ``` -It was amazing to me when I saw the transform for what it truly was: an actual transformation matrix! -That said, the Discrete Fourier Transform is slow -- primarily because matrix multiplication is slow, and as mentioned before, slow code is not particularly useful. -So what was the trick that everyone used to go from a Discrete fourier Transform to a *Fast* Fourier Transform? +It was amazing to me when I saw the transform for what it truly was: an actual transformation matrix! +That said, the Discrete Fourier Transform is slow -- primarily because matrix multiplication is slow, and as mentioned before, slow code is not particularly useful. +So what was the trick that everyone used to go from a Discrete fourier Transform to a *Fast* Fourier Transform? Recursion! @@ -106,11 +106,11 @@ Recursion! The problem with using a standard DFT is that it requires a large matrix multiplications and sums over all elements, which are prohibitively complex operations. The Cooley-Tukey algorithm calculates the DFT directly with fewer summations and without matrix multiplications. If necessary, DFT's can still be calculated directly at the early stages of the FFT calculation. -The trick to the Cooley-Tukey algorithm is recursion. -In particular, we split the matrix we wish to perform the FFT on into two parts: one for all elements with even indices and another for all odd indices. -We then proceed to split the array again and again until we have a manageable array size to perform a DFT (or similar FFT) on. +The trick to the Cooley-Tukey algorithm is recursion. +In particular, we split the matrix we wish to perform the FFT on into two parts: one for all elements with even indices and another for all odd indices. +We then proceed to split the array again and again until we have a manageable array size to perform a DFT (or similar FFT) on. We can also perform a similar re-ordering by using a bit reversal scheme, where we output each array index's integer value in binary and flip it to find the new location of that element. -With recursion, we can reduce the complexity to $$\sim \mathcal{O}(n \log n)$$, which is a feasible operation. +With recursion, we can reduce the complexity to $$\sim \mathcal{O}(n \log n)$$, which is a feasible operation. In the end, the code looks like: {% method %} @@ -128,14 +128,14 @@ In the end, the code looks like: [import:14-31, lang:"julia"](code/julia/fft.jl) {% endmethod %} -As a side note, we are enforcing that the array must be a power of 2 for the operation to work. +As a side note, we are enforcing that the array must be a power of 2 for the operation to work. This is a limitation of the fact that we are using recursion and dividing the array in 2 every time; however, if your array is not a power of 2, you can simply pad the leftover space with 0's until your array is a power of 2. The above method is a perfectly valid FFT; however, it is missing the pictorial heart and soul of the Cooley-Tukey algorithm: Butterfly Diagrams. ### Butterfly Diagrams -Butterfly Diagrams show where each element in the array goes before, during, and after the FFT. -As mentioned, the FFT must perform a DFT. +Butterfly Diagrams show where each element in the array goes before, during, and after the FFT. +As mentioned, the FFT must perform a DFT. This means that even though we need to be careful about how we add elements together, we are still ultimately performing the following operation: $$X_k = \sum_{n=0}^{N-1} x_n \cdot e^{-2 \pi k n / N}$$ @@ -146,7 +146,7 @@ Basically, we split the array into a series of omega values: $$\omega_N^k = e^{-2 \pi k / N}$$ And at each step, we use the appropriate term. -For example, imagine we need to perform an FFT of an array of only 2 elements. +For example, imagine we need to perform an FFT of an array of only 2 elements. We can represent this addition with the following (radix-2) butterfly:

@@ -197,7 +197,7 @@ Here, the ordering of the array was simply divided into even and odd elements on Ultimately, that's all I want to say about Fourier Transforms for now, but this chapter still needs a good amount of work! I'll definitely come back to this at some point, so let me know what you liked and didn't like and we can go from there! - + ### Bibliography {% references %} {% endreferences %} @@ -238,11 +238,11 @@ Note: I implemented this in Julia because the code seems more straightforward in Some rather impressive scratch code was submitted by Jie and can be found here: https://scratch.mit.edu/projects/37759604/#editor {% endmethod %} - + -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/QI/QI.md b/chapters/QI/QI.md index b5ca00443..e30730cb6 100644 --- a/chapters/QI/QI.md +++ b/chapters/QI/QI.md @@ -1,6 +1,6 @@ # Quantum Information -Quantum information theory is... intense. +Quantum information theory is... intense. It requires a strong and fundamental understanding of classical information theory and quantum mechanics. It is not obvious in any way and deserves many textbooks on it's own. In fact, there are numerous textbooks on the subject already. diff --git a/chapters/computational_geometry/computational_geometry.md b/chapters/computational_geometry/computational_geometry.md index fd107c0ea..83c758ad8 100644 --- a/chapters/computational_geometry/computational_geometry.md +++ b/chapters/computational_geometry/computational_geometry.md @@ -1,13 +1,13 @@ # Computational Geometry When it comes to the different sectors of computational mathematics, there are none that bring me more joy than computational geometry. In some sense, it is the foundation for almost every area of automatically generated two and three dimensional graphics. -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). +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). 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! -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/computational_geometry/gift_wrapping/chan/chans.md b/chapters/computational_geometry/gift_wrapping/chan/chans.md index c6e4422ab..f79d9491d 100644 --- a/chapters/computational_geometry/gift_wrapping/chan/chans.md +++ b/chapters/computational_geometry/gift_wrapping/chan/chans.md @@ -1,7 +1,7 @@ -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/computational_geometry/gift_wrapping/gift_wrapping.md b/chapters/computational_geometry/gift_wrapping/gift_wrapping.md index c93ee50b5..66fa24ffd 100644 --- a/chapters/computational_geometry/gift_wrapping/gift_wrapping.md +++ b/chapters/computational_geometry/gift_wrapping/gift_wrapping.md @@ -9,7 +9,7 @@ Strictly speaking, though, the term is not entirely accurate for all convex hull -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/computational_geometry/gift_wrapping/graham_scan/code/julia/graham.jl b/chapters/computational_geometry/gift_wrapping/graham_scan/code/julia/graham.jl index 5797b2425..a581db9d3 100644 --- a/chapters/computational_geometry/gift_wrapping/graham_scan/code/julia/graham.jl +++ b/chapters/computational_geometry/gift_wrapping/graham_scan/code/julia/graham.jl @@ -12,7 +12,7 @@ function graham_scan(points::Vector{Point}) # Place the lowest point at the start of the array sort!(points, by = item -> item.y) - + # Sort all other points according to angle with that point other_points = sort(points[2:end], by = item -> atan2(item.y - points[1].y, item.x - points[1].x)) diff --git a/chapters/computational_geometry/gift_wrapping/jarvis_march/code/jarvis.jl b/chapters/computational_geometry/gift_wrapping/jarvis_march/code/jarvis.jl index 3710d835d..87a1de8cb 100644 --- a/chapters/computational_geometry/gift_wrapping/jarvis_march/code/jarvis.jl +++ b/chapters/computational_geometry/gift_wrapping/jarvis_march/code/jarvis.jl @@ -59,7 +59,7 @@ end function main() # These points are chosen such that there is a clearly defined hull with - # several interior points. As a note, these will be generated either + # several interior points. As a note, these will be generated either # randomly or via some mesh in practice. points = [Pos(2,1.5), Pos(1, 1), Pos(2, 4), Pos(3, 1), Pos(2,2), Pos(2,0.5)] hull = jarvis_march(points) diff --git a/chapters/computational_geometry/gift_wrapping/jarvis_march/jarvis_march.md b/chapters/computational_geometry/gift_wrapping/jarvis_march/jarvis_march.md index 82f902122..362628dcb 100644 --- a/chapters/computational_geometry/gift_wrapping/jarvis_march/jarvis_march.md +++ b/chapters/computational_geometry/gift_wrapping/jarvis_march/jarvis_march.md @@ -10,7 +10,7 @@ Whichever point has the largest interior angle is chosen as the next point in th From there, we use the two known points to again calculate the angle between all other points in the simulation. We then choose the point with the largest interior angle and move the simulation forward. We keep repeating this process until we have returned to our original point. -The set of points chosen in this simulation will be the convex hull. +The set of points chosen in this simulation will be the convex hull. 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. As a note, the Jarvis March can be generalized to higher dimensions. @@ -43,7 +43,7 @@ Program.cs -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/data_compression/data_compression.md b/chapters/data_compression/data_compression.md index 515613781..2bdc4b721 100644 --- a/chapters/data_compression/data_compression.md +++ b/chapters/data_compression/data_compression.md @@ -1,6 +1,6 @@ # Data Compression -I'll be honest, data compression used to be an incredibly hot topic, but kids these days usually have incredibly powerful devices that do not seem to be memory-limited at all. +I'll be honest, data compression used to be an incredibly hot topic, but kids these days usually have incredibly powerful devices that do not seem to be memory-limited at all. Because of this, it seems odd to talk about data compression as a field of intense debate and development. It would naively seem that better hardware means that there are less restrictions on programmers and less of a need to search for new and unique ways to compress their data; however, this is far from the case. @@ -23,19 +23,19 @@ As your mother slips food under your door one day, you reach out to her and ask, Overjoyed at the prospect of her child finally leaving their room, your mother might say, "It's bright, sunny and warm. A perfect day to go outside and relax!" This provides you a lot of information, and to some degree of certainty you can conclude it is summer. -Of course, after this interaction you do not acknowledge your mother's existence after her answer and go back to coding. +Of course, after this interaction you do not acknowledge your mother's existence after her answer and go back to coding. You have the information you need. No reason to overcomplicate things with further human contact. -See, information is defined in a number of different places for a number of different reasons, so for our purposes, we will define the unit of information to be the *bit*, a simple binary 1 or 0. +See, information is defined in a number of different places for a number of different reasons, so for our purposes, we will define the unit of information to be the *bit*, a simple binary 1 or 0. Taking the example mentioned before (assuming you can take your mother at face-value), you were provided 3 true statements: 1. It is bright 2. It is sunny 3. It is warm -With this information, you assumed that it was probably summer. -Unfortunately, your assumption about it being summer is not information. +With this information, you assumed that it was probably summer. +Unfortunately, your assumption about it being summer is not information. It might be a logical conclusion, but it was not provided as a "fact." This is an important distinction between what we might colloquially describe as information and what information theory requires. Information theory works with measurements -- binary absolutes. @@ -50,7 +50,7 @@ In this case, there are plenty of ways you can represent these characters in bit | _a_ | 0 | | _b_ | 1 | -So long as you don't add any new characters to the mix, this is a perfectly valid set of codewords. +So long as you don't add any new characters to the mix, this is a perfectly valid set of codewords. If you get the bitstring 0111101, you can easily decode it as _abbbbab_. But what if you wanted to add a third character, _c_? @@ -75,7 +75,7 @@ If we wanted a good, prefix-free set of codewords for 4 characters (_a_, _b_, _c | _c_ | 10 | | _d_ | 11 | -We can decode any even bitstring with this set. +We can decode any even bitstring with this set. 0100101010110100 is _bacccdba_. This is great, but now we have another question: given a string of characters, can we construct a set of codewords that *minimizes* the number of bits in its corresponding bitstring? @@ -118,14 +118,14 @@ L_2 &= 0.1\times 3 + 0.2 \times 3 + 0.3 \times 2 + 0.4 \times 1 = 1.9 \end{align} $$ -Here, it's clear that $$L_2 < L_1$$, and thus the second set of codewords compresses our data more than the first. +Here, it's clear that $$L_2 < L_1$$, and thus the second set of codewords compresses our data more than the first. This measure can be used as a direct test of certain simple data compression techniques, notably those created by Shannon, Fano, and [Huffman](huffman/huffman.md), which will be covered soon! -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/data_compression/huffman/code/clojure/huffman.clj b/chapters/data_compression/huffman/code/clojure/huffman.clj index a818bc955..3d60245b4 100644 --- a/chapters/data_compression/huffman/code/clojure/huffman.clj +++ b/chapters/data_compression/huffman/code/clojure/huffman.clj @@ -9,7 +9,7 @@ ;; vector of [character frequency] pair ;; for every char in string, added it to hash-map ;; with value one if it doesn't exist or increment its value - (def cf-vec (vec + (def cf-vec (vec (reduce (fn [m c] (assoc m c (inc (get m c 0)))) {} @@ -53,7 +53,7 @@ (cond (char? tree) {"" tree} :else - (let [left-map (hash-tree (first tree)) + (let [left-map (hash-tree (first tree)) right-map (hash-tree (second tree)) func #(apply hash-map ; apply hash-map because ; interleave return a seq @@ -80,12 +80,12 @@ (if-let [letter (get hash-decoder new-code)] ;; if there is a letter then add it to :message ;; and revert :code to empty - (assoc (update m :message #(str % letter)) + (assoc (update m :message #(str % letter)) :code "") ;; if there is not a letter then just add the ;; code letter to the :code (update m :code #(str % code))))) - {:message "",:code ""} + {:message "",:code ""} s) :message)) ;extract :message value ;; ----------------EXAMPLE---------------- diff --git a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs index 49ace6fde..ef711af26 100644 --- a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs +++ b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs @@ -5,7 +5,7 @@ namespace HuffmanCoding { - public class EncodingResult + public class EncodingResult { public string BitString { get; set; } public Dictionary Dictionary { get; set; } @@ -31,7 +31,7 @@ public class Node : IComparable public string Key { get; set; } public bool IsLeaf => LeftChild == null && RightChild == null; - + // Creates a leaf. So just a node is created with the given values. public static Node CreateLeaf(char key, int weight) => new Node(key.ToString(), weight, null, null); // Creates a branch. Here a node is created by adding the keys and weights of both childs together. @@ -100,7 +100,7 @@ public string Decode(EncodingResult result) currentNode = currentNode.RightChild; if (currentNode.IsLeaf) - { + { output += currentNode.Key; currentNode = result.Tree; } @@ -135,7 +135,7 @@ private Node CreateTree(string input) private Dictionary CreateDictionary(Node root) { - // We're using a string instead of a actual bits here, since it makes the code somewhat more readable and this is an educational example. + // We're using a string instead of a actual bits here, since it makes the code somewhat more readable and this is an educational example. var dictionary = new Dictionary(); CreateDictionary(root, "", dictionary); return dictionary; diff --git a/chapters/data_compression/huffman/code/julia/huffman.jl b/chapters/data_compression/huffman/code/julia/huffman.jl index 0fcc0dec5..db5993118 100644 --- a/chapters/data_compression/huffman/code/julia/huffman.jl +++ b/chapters/data_compression/huffman/code/julia/huffman.jl @@ -16,18 +16,18 @@ const Node = Union{Leaf, Branch} isbranch(branch::Branch) = true isbranch(other::T) where {T} = false -function codebook_recurse(leaf::Leaf, code::String, +function codebook_recurse(leaf::Leaf, code::String, dict::Dict{Char,String}) dict[leaf.key] = code end -function codebook_recurse(branch::Branch, code::String, +function codebook_recurse(branch::Branch, code::String, dict::Dict{Char,String}) codebook_recurse(branch.left, string(code, "1"), dict) codebook_recurse(branch.right, string(code, "0"), dict) end -# This will depth-first search through the tree +# This will depth-first search through the tree # to create bitstrings for each character. # Note: Any depth-first search method will work # This outputs encoding Dict to be used for encoding diff --git a/chapters/data_compression/huffman/code/python/huffman.py b/chapters/data_compression/huffman/code/python/huffman.py index 700dc68b9..1e1cc541e 100644 --- a/chapters/data_compression/huffman/code/python/huffman.py +++ b/chapters/data_compression/huffman/code/python/huffman.py @@ -1,23 +1,23 @@ # Huffman Encoding # Python 2.7+ -# Submitted by Matthew Giallourakis +# Submitted by Matthew Giallourakis from collections import Counter # constructs the tree def build_huffman_tree(message): - + # get sorted list of character and frequency pairs frequencies = Counter(message) trees = frequencies.most_common() # while there is more than one tree while len(trees) > 1: - + # pop off the two trees of least weight from the trees list tree_left,weight_left = trees.pop() tree_right,weight_right = trees.pop() - + # combine the nodes and add back to the nodes list new_tree = [tree_left, tree_right] new_weight = weight_left + weight_right @@ -25,7 +25,7 @@ def build_huffman_tree(message): # find the first tree that has a weight smaller than new_weight and returns its index in the list # If no such tree can be found, use len(trees) instead to append index = next((i for i, tree in enumerate(trees) if tree[1] < new_weight), len(trees)) - + # insert the new tree there trees.insert(index, (new_tree, new_weight)) @@ -41,14 +41,14 @@ def build_codebook(tree, code=''): left_tree, right_tree = tree # if the left node has children, find the mapping of those children - # else pair the character with the current code + 0 + # else pair the character with the current code + 0 if type(left_tree) is list: codebook += build_codebook(left_tree, code+'0') else: codebook.append((left_tree, code+'0')) # if the right node has children, find the mapping of those children - # else pair the character with the current code + 1 + # else pair the character with the current code + 1 if type(right_tree) is list: codebook += build_codebook(right_tree, code+'1') else: @@ -57,7 +57,7 @@ def build_codebook(tree, code=''): # encodes the message def huffman_encode(codebook, message): - + encoded_message = '' # build a char -> code dictionary @@ -66,12 +66,12 @@ def huffman_encode(codebook, message): # replace each character with its code for char in message: encoded_message += forward_dict[char] - + return encoded_message # decodes a message def huffman_decode(codebook, encoded_message): - + decoded_message = '' key = '' @@ -87,7 +87,7 @@ def huffman_decode(codebook, encoded_message): if key in inverse_dict: decoded_message += inverse_dict[key] key = '' - + return decoded_message def main(): @@ -113,6 +113,6 @@ def main(): # ('y', '101'), ('t', '110'), ('i', '111')] # encoded_message: 01110011111010110000100100111110101 # decoded_message: bibbity_bobbity - + if __name__ == '__main__': main() diff --git a/chapters/decision_problems/decision_problems.md b/chapters/decision_problems/decision_problems.md index 70282de95..ef367bbff 100644 --- a/chapters/decision_problems/decision_problems.md +++ b/chapters/decision_problems/decision_problems.md @@ -1,5 +1,5 @@ # Decision Problems -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. +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. 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. 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. @@ -9,7 +9,7 @@ Overall, these problems come up all over the place and are certainly worth study -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/decision_problems/stable_marriage/code/cs/GaleShapleyAlgorithm.cs b/chapters/decision_problems/stable_marriage/code/cs/GaleShapleyAlgorithm.cs index 082544daf..e21309576 100644 --- a/chapters/decision_problems/stable_marriage/code/cs/GaleShapleyAlgorithm.cs +++ b/chapters/decision_problems/stable_marriage/code/cs/GaleShapleyAlgorithm.cs @@ -11,7 +11,7 @@ public static void RunGaleShapleyAlgorithm(List follows, List le { // All follows are lonely. var lonelyFollows = new List(follows); - + // Carry on until there are no lonely follows anymore. while (lonelyFollows.Count > 0) { @@ -20,7 +20,7 @@ public static void RunGaleShapleyAlgorithm(List follows, List le { lonelyFollow.ProposeToNext(); } - + // Look which follows have a partner now and which don't. var newLonelyFollows = new List(); foreach (var follow in follows) diff --git a/chapters/decision_problems/stable_marriage/code/cs/Person.cs b/chapters/decision_problems/stable_marriage/code/cs/Person.cs index 8e506139b..c266a8159 100644 --- a/chapters/decision_problems/stable_marriage/code/cs/Person.cs +++ b/chapters/decision_problems/stable_marriage/code/cs/Person.cs @@ -15,14 +15,14 @@ public class Person public int CurrentTopChoiceIndex { get; set; } = 0; public Person(string name) => Name = name; - + public void ProposeToNext() { var interest = GetNextTopChoice(); - + // If the interest has no partner or prefers this person, // change interest's partner to this person. - if (interest.Partner == null || + if (interest.Partner == null || interest.Choices.IndexOf(this as TSelf) < interest.Choices.IndexOf(interest.Partner)) { // Should the interest already have a partner, set the partner diff --git a/chapters/decision_problems/stable_marriage/code/julia/stable_marriage.jl b/chapters/decision_problems/stable_marriage/code/julia/stable_marriage.jl index 05bf967be..b08ddaec6 100644 --- a/chapters/decision_problems/stable_marriage/code/julia/stable_marriage.jl +++ b/chapters/decision_problems/stable_marriage/code/julia/stable_marriage.jl @@ -13,7 +13,7 @@ function genpreferences(mannames::Vector{String}, womannames::Vector{String}) return men, women end -# Returns if `person` prefers the `first` candidate over the `second` one. +# Returns if `person` prefers the `first` candidate over the `second` one. # This translates to `first` appearing *sooner* in the preference list prefers(prefs, person, first, second) = findfirst(m -> m == first, prefs[person]) < diff --git a/chapters/decision_problems/stable_marriage/stable_marriage.md b/chapters/decision_problems/stable_marriage/stable_marriage.md index 51255b675..328c242bf 100644 --- a/chapters/decision_problems/stable_marriage/stable_marriage.md +++ b/chapters/decision_problems/stable_marriage/stable_marriage.md @@ -14,7 +14,7 @@ This problem is solved by the Gale-Shapley algorithm, which can be simply descri 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. 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. -To be clear, even though this algorithm seems conceptually simple, it is rather tricky to implement correctly. +To be clear, even though this algorithm seems conceptually simple, it is rather tricky to implement correctly. 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. I am incredibly interested to see what you guys do and how you implement the algorithm. diff --git a/chapters/differential_equations.md b/chapters/differential_equations.md index 9ddfda52f..6ba8e4635 100644 --- a/chapters/differential_equations.md +++ b/chapters/differential_equations.md @@ -1,7 +1,7 @@ -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/differential_equations/euler/backward_euler.md b/chapters/differential_equations/euler/backward_euler.md index 2f067f354..f415d969e 100644 --- a/chapters/differential_equations/euler/backward_euler.md +++ b/chapters/differential_equations/euler/backward_euler.md @@ -8,7 +8,7 @@ MORE TO COME!!! -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/differential_equations/euler/euler.md b/chapters/differential_equations/euler/euler.md index af49a0497..2ce9a63de 100644 --- a/chapters/differential_equations/euler/euler.md +++ b/chapters/differential_equations/euler/euler.md @@ -111,7 +111,7 @@ So, this time, let's remove ourselves from any physics and instead solve the fol Full code for the visualization follows: [import, lang:"elm"](code/elm/euler.elm) {% endmethod %} - + diff --git a/chapters/euclidean_algorithm/euclidean.md b/chapters/euclidean_algorithm/euclidean.md index 0c9d6c2af..3530cdcbf 100644 --- a/chapters/euclidean_algorithm/euclidean.md +++ b/chapters/euclidean_algorithm/euclidean.md @@ -1,6 +1,6 @@ # Euclidean Algorithm -Computer science is (almost by definition) a science about computers -- a device first conceptualized in the 1800's. Computers have become so revolutionary, that it is difficult to think of our lives today without them. That said, *algorithms* are much older and have existed in the world for millenia. Incredibly, a few of the algorithms created before the Common Era (AD) are still in use today. One such algorithm was first described in Euclid's *Elements* (~ 300 BC) and has come to be known as the *Euclidean Algorithm*. +Computer science is (almost by definition) a science about computers -- a device first conceptualized in the 1800's. Computers have become so revolutionary, that it is difficult to think of our lives today without them. That said, *algorithms* are much older and have existed in the world for millenia. Incredibly, a few of the algorithms created before the Common Era (AD) are still in use today. One such algorithm was first described in Euclid's *Elements* (~ 300 BC) and has come to be known as the *Euclidean Algorithm*. The algorithm is a simple way to find the *greatest common divisor* (GCD) of two numbers, which is useful for a number of different applications (like reducing fractions). The first method (envisioned by Euclid) uses simple subtraction: @@ -82,7 +82,7 @@ Program.cs ### Clojure [import 2-20, lang="clojure"](code/clojure/euclidean_example.clj) {% sample lang="cpp" %} -### Cpp +### Cpp [import, lang="c_cpp"](code/c++/euclidean.cpp) {% sample lang="js" %} ### JavaScript @@ -108,7 +108,7 @@ Program.cs -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/getting_started.md b/chapters/getting_started.md index c22f0d339..a9e5b9962 100644 --- a/chapters/getting_started.md +++ b/chapters/getting_started.md @@ -6,21 +6,21 @@ I don't know if you guys had a similar childhood to mine or not, but I found tha Like most of my friends, I spent my entire childhood in front of a television screen or monitor, trying desperately to compete with world-destroying supervillains or at the very least, anthropomorphic turtles with spikes on their backs. During school, we would come together and talk about the latest video game gossip. At the time, the internet was still young and I hardly used it for any real purpose. Sure, I would get online every now and again for a school project or two, but it was definitely not a central component to my life... Well, at least not until high school when I became addicted to one Massively Multiplayer Online game, in particular (which will remain nameless). -I bought my first laptop after working all summer as a lifeguard my freshman year in high school, but at the time, I was downright awful with computers. I couldn't even figure out antivirus software and my grandfather had to help me get everything set up. It was the era of Windows Vista and that seemed fine to me, but when I returned to school, my friends (who all seemed to know way more than I did on the subject), seemed to believe Vista to be a demon spawned from the pits of... Microsoft? +I bought my first laptop after working all summer as a lifeguard my freshman year in high school, but at the time, I was downright awful with computers. I couldn't even figure out antivirus software and my grandfather had to help me get everything set up. It was the era of Windows Vista and that seemed fine to me, but when I returned to school, my friends (who all seemed to know way more than I did on the subject), seemed to believe Vista to be a demon spawned from the pits of... Microsoft? Being the curious kid I was, I asked what I should do to avoid Vista and they said I should install another version of the Windows operating system, like Windows XP. I then asked a question that will forever change my life, "What is an operating system?" -My friends could have just said, "It's the thing that operates your hardware. It brings up the UI elements and stuff you work with." Sure, it's not quite the whole story, but as a computer novice, it would have been just fine for me. That said, they took it a step further and said, "Nowadays, there are many operating systems to choose from, including Windows, Mac, and Linux." I may have been a complete novice, but I at least knew about Windows and Mac. Linux, though? What the heck was that? +My friends could have just said, "It's the thing that operates your hardware. It brings up the UI elements and stuff you work with." Sure, it's not quite the whole story, but as a computer novice, it would have been just fine for me. That said, they took it a step further and said, "Nowadays, there are many operating systems to choose from, including Windows, Mac, and Linux." I may have been a complete novice, but I at least knew about Windows and Mac. Linux, though? What the heck was that? Of course I asked about it, but this was early high school. My friends may have been smarter than I was, but there was a limit to their knowledge. Apparently, the only thing they knew about linux was that it was supposedly faster and couldn't catch viruses. That caught me. Remember how I said I couldn't get the virus software to work on my computer? Yeah. At this point, I was thinking, *What? A computer that couldn't catch viruses? No way! That's gotta be **leagues** easier to use than Windows!* -*Oh ho* I was... well... I was downright naive. I had no idea what I was doing. That night, I ran home, super excited to learn about linux and operating systems, and spent the entire night browsing the internet, trying to find whatever information was out there. At the time, my google-fu was weak and my internet was slow. The first thing I learned was that there were apparently different types of linuxes called "distributions." At that point, I probably searched "What is the best linux?" or something to that effect. Somehow, I managed to find [distrowatch](https://distrowatch.com/), which had a list of all the most popular distros on the side. +*Oh ho* I was... well... I was downright naive. I had no idea what I was doing. That night, I ran home, super excited to learn about linux and operating systems, and spent the entire night browsing the internet, trying to find whatever information was out there. At the time, my google-fu was weak and my internet was slow. The first thing I learned was that there were apparently different types of linuxes called "distributions." At that point, I probably searched "What is the best linux?" or something to that effect. Somehow, I managed to find [distrowatch](https://distrowatch.com/), which had a list of all the most popular distros on the side. -I don't remember the exact order, but I knew the key players were there: Ubuntu, Mint, Fedora, Debian, and Arch. Now, here's where my years of gaming experience came in. I personified each distribution as a class in a game world. Ubuntu was the easy to use axe-wielding warrior that would get the job done. Fedora was the Archer in the back with a feather in his cap and a quick quip for everything. Debian was the grandmotherly spellcaster just trying to keep everyone alive. Then there was Arch, the one who rushed into combat without any armor and uses only the environment as a weapon. +I don't remember the exact order, but I knew the key players were there: Ubuntu, Mint, Fedora, Debian, and Arch. Now, here's where my years of gaming experience came in. I personified each distribution as a class in a game world. Ubuntu was the easy to use axe-wielding warrior that would get the job done. Fedora was the Archer in the back with a feather in his cap and a quick quip for everything. Debian was the grandmotherly spellcaster just trying to keep everyone alive. Then there was Arch, the one who rushed into combat without any armor and uses only the environment as a weapon. -Which one did I choose? Arch. I've always been a fan of playing the underdog characters. In fact, when I looked up what made Arch Arch, I found the [Archwiki](https://wiki.Archlinux.org/), which was absolutely beautiful and filled with any information I could ever want to know about the distribution, including a page on ["The Arch Way"](https://wiki.Archlinux.org/index.php/Arch_Linux#Principles) -- Which now redirects to a page about Archlinux principles instead. After reading through it, there was not a single shadow of a doubt in my mind. Arch was the distribution for me. +Which one did I choose? Arch. I've always been a fan of playing the underdog characters. In fact, when I looked up what made Arch Arch, I found the [Archwiki](https://wiki.Archlinux.org/), which was absolutely beautiful and filled with any information I could ever want to know about the distribution, including a page on ["The Arch Way"](https://wiki.Archlinux.org/index.php/Arch_Linux#Principles) -- Which now redirects to a page about Archlinux principles instead. After reading through it, there was not a single shadow of a doubt in my mind. Arch was the distribution for me. In hindsight, this could have been the most disastrous decision of my life. I hope that at this point, you understand how bad I was with computers, and a slow internet connection didn't help. The next day, I went to the store and bought a 25 pack of writable DVD's. So now for the hard part: Installation. @@ -30,7 +30,7 @@ Now, I know many of you reading think this is an easy thing to do. In fact, I al #### Step 2: Just type "root" -After the disk burning fiasco, I thought to myself, *Alright. It'll only get easier from here, right?* Nope. I booted up the Archiso and up popped a prompt talking about how to install Arch. I don't remember what it said exactly, but I know it mentioned that if you wanted to install Arch on a "kerosene-powered cheese grater" that you should consult the wiki. Now, here's the thing: for anyone else, this would just be an idle quip -- something to chuckle at before moving on, but I was not able to move past this prompt. Right under it was a rather surprising adversary, the phrase `Archiso login:` with a blinking cursor. +After the disk burning fiasco, I thought to myself, *Alright. It'll only get easier from here, right?* Nope. I booted up the Archiso and up popped a prompt talking about how to install Arch. I don't remember what it said exactly, but I know it mentioned that if you wanted to install Arch on a "kerosene-powered cheese grater" that you should consult the wiki. Now, here's the thing: for anyone else, this would just be an idle quip -- something to chuckle at before moving on, but I was not able to move past this prompt. Right under it was a rather surprising adversary, the phrase `Archiso login:` with a blinking cursor. In my head, I knew what this meant. I needed to create my username, right? So I tried putting in what I wanted my username to be. No luck. I tried any number of different combinations of letters and characters. I even tried our wifi password. Nothing. I tried re-burning the disk a few more times, but I was still completely lost. What did they want? What was I supposed to type to move forward with the installation? I couldn't figure it out, and after hours of sitting there, looking at a blinking prompt, I started wondering if my computer was actually a kerosene-powered cheese grater and consulted the wiki, but even that wasn't particularly clear. So I googled some more, and then some more and more. Somehow, I stumbled onto a page that gave me the answer -- the magical password that would allow me access to the Arch installer: @@ -42,7 +42,7 @@ Now, at the time, I didn't realize what I was doing. I didn't know that root was If you install Arch nowadays, things are different. There is a terminal prompt and the entire install is done manually. I love the new installer because it forces new users to really dig down and understand what makes Arch Arch. At the time of my first installation, though, this was not how things went. Instead of a terminal prompt, there was a semi-graphical installer, where the entire background was blue. -Now, I have blue eyes. I am fairly certain they were blue before the installation, but I cannot be certain. I do know that this blue hue was burned eternally into my retinas. I was staring at this screen for so long that the moment I would look up from the screen, everything seemed red. +Now, I have blue eyes. I am fairly certain they were blue before the installation, but I cannot be certain. I do know that this blue hue was burned eternally into my retinas. I was staring at this screen for so long that the moment I would look up from the screen, everything seemed red. Truth be told, I learned a lot at this stage of the installation, including mounting, partitioning, and how to use vi (not vim). That said, the most important thing I learned was how to use the Archwiki's Beginner's Guide. Holy cow! After this part of the installation, I felt like a real *man*. That is to say, I learned about the man command. Seriously, though, I was bombarded with a flurry of new ideas and methods that I could have never dreamed about before, and yet I took it all in stride. Quite frankly, it felt amazing! @@ -50,7 +50,7 @@ Truth be told, I learned a lot at this stage of the installation, including moun In the middle of the installation, when all the packages were popping up, I remember getting a very particular error under the acronym DRDY. I didn't know what this meant. In fact, I don't think very many people did. The error said it was fatal, so I restarted the install from scratch. I got the same error, but this time in a different place, so I did the install again. And then again. And then again. I repeated the installation so many times that I had memorized every last part from start to finish. I had read all the guides online, and yet I was still getting that darned error! DRDY. What could it mean? -Well, I didn't know, but at that point, it was late at night and I was a bit delirious. I phonetically sounded out the error and realized it sounded like the word "dirty." I figured this meant that the hard drive was dirty, so I unplugged it , blew on the socket, and plugged it back in. No more error. +Well, I didn't know, but at that point, it was late at night and I was a bit delirious. I phonetically sounded out the error and realized it sounded like the word "dirty." I figured this meant that the hard drive was dirty, so I unplugged it , blew on the socket, and plugged it back in. No more error. To this day, I don't know how or why this worked. @@ -59,7 +59,7 @@ To this day, I don't know how or why this worked. I'm skipping the bootloader and everything because that was surprisingly straightforward for my first install. The next thing I remember is the post-install. I had finally finished the grueling installation process after almost 48 hours without sleep. I rebooted my system and was welcomed with the most beautiful sight I had ever seen: a completely black screen, save one blinking prompt: ``` -Blitz login: +Blitz login: ``` The same as I saw in the installation before. Except this time, I didn't sit there waiting for hours, trying to figure out some password to enter my system. I simply entered my moniker and got to setting up my system. diff --git a/chapters/how_to_contribute.md b/chapters/how_to_contribute.md index 7f13debac..5b6d5276e 100644 --- a/chapters/how_to_contribute.md +++ b/chapters/how_to_contribute.md @@ -1,24 +1,24 @@ ## How to Contribute to the Algorithm Archive -The *Algorithm Archive* is an effort to learn about and teach algorithms as a community. -As such, it requires a certain level of trust between community members. -For the most part, the collaboration can be done via github and gitbook, so it is important to understand the basics of [version control](principles_of_code/version_control.md). +The *Algorithm Archive* is an effort to learn about and teach algorithms as a community. +As such, it requires a certain level of trust between community members. +For the most part, the collaboration can be done via github and gitbook, so it is important to understand the basics of [version control](principles_of_code/version_control.md). Ideally, all code provided by the community will be submitted via pull requests and discussed accordingly; however, I understand that many individuals are new to collaborative projects, so I will allow submissions by other means (comments, tweets, etc...). As this project grows in size, it will be harder and harder to facilitate these submissions. -In addition, by submitting in any way other than pull requests, I cannot gaurantee I will be able to list you as a collaborator (though I will certainly do my best to update the `CONTRIBUTERS.md` file accordingly). +In addition, by submitting in any way other than pull requests, I cannot gaurantee I will be able to list you as a collaborator (though I will certainly do my best to update the `CONTRIBUTERS.md` file accordingly). -At this point, I am trying to figure out the best way to balance community contributions and text. +At this point, I am trying to figure out the best way to balance community contributions and text. Right now, I feel comfortable writing the text associated with each algorithm and asking for the community to write individual implementations. In the future, I might allow other users to write algorithm chapters, but for now let's keep it simple: I'll do the writing, everyone else does the coding. Now for some specifics on submissions: -1. **Style**: Follow standard style guidelines associated with your language of choice. For C / C++, please use Stroustrup style, with `auto` used rarely or not at all. We have had plenty of discussions about this, which can be found [here](https://github.com/algorithm-archivists/algorithm-archive/issues/18). I will leave the issue open for now in the case that other individuals have more to contribute there. Basically, your code should be readable and understandable to anyone -- especially those who are new to the language. In addition, remember that your code will be displayed in this book, so try to keep to around 80 columns and try to remove any visual clutter. In addition, keep variable names clean and understandable. +1. **Style**: Follow standard style guidelines associated with your language of choice. For C / C++, please use Stroustrup style, with `auto` used rarely or not at all. We have had plenty of discussions about this, which can be found [here](https://github.com/algorithm-archivists/algorithm-archive/issues/18). I will leave the issue open for now in the case that other individuals have more to contribute there. Basically, your code should be readable and understandable to anyone -- especially those who are new to the language. In addition, remember that your code will be displayed in this book, so try to keep to around 80 columns and try to remove any visual clutter. In addition, keep variable names clean and understandable. 2. **Licensing**: All the code from this project will be under the MIT licence found in `LICENCE.md`; however, the text will be under a Creative Commons Attribution-NonCommercial 4.0 International License. 3. **CONTRIBUTORS.md**: After contributing code, please echo your name to the end of `CONTRIBUTORS.md` with `echo name >> CONTRIBUTORS.md`, and also leave a comment on the top of the code you submitted with your name (or username) saying `// submitted by name`. This way everyone is held accountable and we know who to contact if we want more information. 4. **Building the Algorithm Archive**: If you want to build the Algorithm Archive on your own machine, install gitbook and use `gitbook serve` in the main directory (where `README.md` is). This will provide a local url to go to to view the archive in your browser of choice. Use this server to make sure your version of the Algorithm Archive works cleanly for the chapter you are updating! -For this project, we allow submissions in every language. -To submit code, simply go to the code directory of whatever chapter you want and add a directory for your language of choice. +For this project, we allow submissions in every language. +To submit code, simply go to the code directory of whatever chapter you want and add a directory for your language of choice. We use two gitbook plugins to allow users to flip between languages on different algorithms. One is the theme-api, and the other is the include-codeblock api. We need the following statements in the markdown file for these to work together: @@ -30,7 +30,7 @@ Note that to standardize the language capitalization schemes, we ask that each l This keeps the title in the theme-api consistent across different languages. Also note that depending on the algorithm, there might be in-text code snippets that also need to be written. -I'll update this page as the project grows. Basically, when you submit code, it will be under an MIT license. Please keep the code clean and put your name (or username) in the `CONTRIBUTORS.md` file. +I'll update this page as the project grows. Basically, when you submit code, it will be under an MIT license. Please keep the code clean and put your name (or username) in the `CONTRIBUTORS.md` file. If you would like to be a part of the ongoing discussion, please feel free to join our discord server: https://discord.gg/pb976sY. Thanks for all the support and considering contributing to the Algorithm Archive! diff --git a/chapters/introduction.md b/chapters/introduction.md index 09c04910d..4904fdf01 100644 --- a/chapters/introduction.md +++ b/chapters/introduction.md @@ -1,6 +1,6 @@ # Introduction -People learn differently, there's no doubt about that. I for one, have never been able to follow a lecture. No matter how interesting the subject might be, the teacher or professor either moves too slowly or too quickly, and in both cases I lose the motivation to study and learn outside of class. Looking back at all my past lectures, this is a bit of a shame. I genuinely love learning! In fact, nowadays there's nothing I enjoy more than poring through the [ArXiv](https://arxiv.org/), looking for the latest and greatest algorithms in physics and computer science. Sure, I cannot *understand* them all, but sometimes it's nice to be completely overwhelmed and chip away at problems one piece at a time. In the end, modern research is a conglomeration of fun little (or big) puzzles to solve; however, I find that many papers are too harsh for most people to tackle without a significant background in computer science or physics. For this reason, they are ignored by the public. We live in an era where nearly the entire sum of human knowledge is available at our fingertips, and yet people are blissfully unaware of the unique ideas and challenges that are pushing our understanding forward. +People learn differently, there's no doubt about that. I for one, have never been able to follow a lecture. No matter how interesting the subject might be, the teacher or professor either moves too slowly or too quickly, and in both cases I lose the motivation to study and learn outside of class. Looking back at all my past lectures, this is a bit of a shame. I genuinely love learning! In fact, nowadays there's nothing I enjoy more than poring through the [ArXiv](https://arxiv.org/), looking for the latest and greatest algorithms in physics and computer science. Sure, I cannot *understand* them all, but sometimes it's nice to be completely overwhelmed and chip away at problems one piece at a time. In the end, modern research is a conglomeration of fun little (or big) puzzles to solve; however, I find that many papers are too harsh for most people to tackle without a significant background in computer science or physics. For this reason, they are ignored by the public. We live in an era where nearly the entire sum of human knowledge is available at our fingertips, and yet people are blissfully unaware of the unique ideas and challenges that are pushing our understanding forward. I guess that is the point of this work. Throughout the past few years, I have been collecting small morsels of knowledge that are hard to express in any meaningful way through blog posts, youtube, or twitch streaming. Youtube, for example, is a great place to introduce the general idea of an algorithm; however, I personally find it a poor choice to show a worked example. Twitch is great to show everything, but spending 5 hours programming up an algorithm for the first time is generally not everyone's idea of fun. Blog posts work well for this type of material; however, they lack a comprehensive nature that I tend to enjoy. So what's left? Well, I suppose that would be a book, which is an incredibly exciting prospect! diff --git a/chapters/math.md b/chapters/math.md index 57ffa4a04..12ff86b04 100644 --- a/chapters/math.md +++ b/chapters/math.md @@ -1,7 +1,7 @@ -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/matrix_methods/gaussian_elimination/code/julia/gaussian_elimination.jl b/chapters/matrix_methods/gaussian_elimination/code/julia/gaussian_elimination.jl index 2ca62f66d..b4aeb8ce5 100644 --- a/chapters/matrix_methods/gaussian_elimination/code/julia/gaussian_elimination.jl +++ b/chapters/matrix_methods/gaussian_elimination/code/julia/gaussian_elimination.jl @@ -46,7 +46,7 @@ function back_substitution(A::Array{Float64,2}) rows = size(A,1) cols = size(A,2) - # Creating the solution Vector + # Creating the solution Vector soln = Vector{Float64}(rows) # initialize the final element diff --git a/chapters/matrix_methods/gaussian_elimination/gaussian_elimination.md b/chapters/matrix_methods/gaussian_elimination/gaussian_elimination.md index 6b108ea44..877bd0538 100644 --- a/chapters/matrix_methods/gaussian_elimination/gaussian_elimination.md +++ b/chapters/matrix_methods/gaussian_elimination/gaussian_elimination.md @@ -7,7 +7,7 @@ $$ \begin{align} 2x + 3y + 4z &= 6 \\ x + 2y + 3z &= 4 \\ -3x - 4y &= 10 +3x - 4y &= 10 \end{align} $$ @@ -26,7 +26,7 @@ $$ \left[ \begin{array}{c} x \\ -y \\ +y \\ z \end{array} \right] @@ -34,7 +34,7 @@ z \left[ \begin{array}{c} 6 \\ -4 \\ +4 \\ 10 \end{array} \right] @@ -49,7 +49,7 @@ $$ \begin{array}{ccc|c} 2 & 3 & 4 & 6 \\ 1 & 2 & 3 & 4 \\ -3 & -4 & 0 & 10 +3 & -4 & 0 & 10 \end{array} \right] $$ @@ -62,7 +62,7 @@ $$ \begin{align} 2x + 3y + 4z &= 6 \\ y + 2z &= 2 \\ -11z &= 18 +11z &= 18 \end{align} $$ @@ -75,7 +75,7 @@ $$ \begin{array}{ccc|c} 2 & 3 & 4 & 6 \\ 0 & 1 & 2 & 2 \\ -0 & 0 & 11 & 18 +0 & 0 & 11 & 18 \end{array} \right] $$ @@ -93,7 +93,7 @@ $$ \begin{align} 11x &= 18 \\ 11y &= -14 \\ -11z &= 18 +11z &= 18 \end{align} $$ @@ -106,7 +106,7 @@ $$ \begin{array}{ccc|c} 11 & 0 & 0 & 18 \\ 0 & 11 & 0 & -14 \\ -0 & 0 & 11 & 18 +0 & 0 & 11 & 18 \end{array} \right] $$ @@ -135,15 +135,15 @@ $$ \begin{array}{ccc|c} 2 & 3 & 4 & 6 \\ 1 & 2 & 3 & 4 \\ -3 & -4 & 0 & 10 +3 & -4 & 0 & 10 \end{array} -\right] -\quad \rightarrow \quad +\right] +\quad \rightarrow \quad \left[ \begin{array}{ccc|c} 2 & 3 & 4 & 6 \\ 0 & 1 & 2 & 2 \\ -0 & 0 & 11 & 18 +0 & 0 & 11 & 18 \end{array} \right] $$ @@ -157,15 +157,15 @@ $$ \begin{array}{ccc|c} 2 & 3 & 4 & 6 \\ 0 & 1 & 2 & 2 \\ -0 & 0 & 11 & 18 +0 & 0 & 11 & 18 \end{array} -\right] -\quad \rightarrow \quad +\right] +\quad \rightarrow \quad \left[ \begin{array}{ccc|c} 11 & 0 & 0 & 18 \\ 0 & 11 & 0 & -14 \\ -0 & 0 & 11 & 18 +0 & 0 & 11 & 18 \end{array} \right] $$ @@ -184,7 +184,7 @@ $$ \begin{array}{ccc|c} 2 & 3 & 4 & 6 \\ 1 & 2 & 3 & 4 \\ -\mathbf{3} & -4 & 0 & 10 +\mathbf{3} & -4 & 0 & 10 \end{array} \right] $$ @@ -194,7 +194,7 @@ $$ \begin{array}{ccc|c} \mathbf{2} & \mathbf{3} & \mathbf{4} & \mathbf{6} \\ 1 & 2 & 3 & 4 \\ -\mathbf{3} & \mathbf{-4} & \mathbf{0} & \mathbf{10} +\mathbf{3} & \mathbf{-4} & \mathbf{0} & \mathbf{10} \end{array} \right] \rightarrow @@ -202,7 +202,7 @@ $$ \begin{array}{ccc|c} \mathbf{3} & \mathbf{-4} & \mathbf{0} & \mathbf{10} \\ 1 & 2 & 3 & 4 \\ -\mathbf{2} & \mathbf{3} & \mathbf{4} & \mathbf{6} +\mathbf{2} & \mathbf{3} & \mathbf{4} & \mathbf{6} \end{array} \right] $$ @@ -213,9 +213,9 @@ $$ \begin{array}{ccc|c} 3 & -4 & 0 & 10 \\ \mathbf{1} & 2 & 3 & 4 \\ -2 & 3 & 4 & 6 +2 & 3 & 4 & 6 \end{array} -\right] \\ +\right] \\ \begin{align} f &= A(\text{pivot}_{\text{row}}, \text{pivot}_{\text{col}}) / A(\text{curr_row}_{\text{row}}, \text{pivot}_{\text{col}}) \\ &= \frac{1}{3} @@ -223,12 +223,12 @@ $$ $$ 4. Set all values in the corresponding rows to be the value they were before $$-$$ the top row $$\times$$ the fraction. This is essentially performing move 3 from above, except with an optimal multiplicative factor. $$ -A(\text{curr_row}_{\text{row}}, \text{curr_col}_{\text{col}}) \mathrel{+}= A(\text{pivot_row}_{\text{row}}, \text{pivot_row}_{\text{curr_col}} \times f) \\ +A(\text{curr_row}_{\text{row}}, \text{curr_col}_{\text{col}}) \mathrel{+}= A(\text{pivot_row}_{\text{row}}, \text{pivot_row}_{\text{curr_col}} \times f) \\ \left[ \begin{array}{ccc|c} 3 & -4 & 0 & 10 \\ \mathbf{1} & \mathbf{2} & \mathbf{3} & \mathbf{4} \\ -2 & 3 & 4 & 6 +2 & 3 & 4 & 6 \end{array} \right] \rightarrow @@ -236,7 +236,7 @@ A(\text{curr_row}_{\text{row}}, \text{curr_col}_{\text{col}}) \mathrel{+}= A(\te \begin{array}{ccc|c} 3 & -4 & 0 & 10 \\ \mathbf{\frac{1}{3}} & \mathbf{\frac{2}{3}} & \mathbf{1} & \mathbf{\frac{4}{3}} \\ -2 & 3 & 4 & 6 +2 & 3 & 4 & 6 \end{array} \right] $$ @@ -246,7 +246,7 @@ $$ \begin{array}{ccc|c} 3 & -4 & 0 & 10 \\ 0 & 2 & 3 & 4 \\ -2 & 3 & 4 & 6 +2 & 3 & 4 & 6 \end{array} \right] @@ -263,8 +263,8 @@ As with all code, it takes time to fully absorb what is going on and why everyth Now, to be clear: this algorithm creates an upper-triangular matrix. In other words, it only creates a matrix in *Row Eschelon Form*, not * **Reduced** Row Eschelon Form*! So what do we do from here? Well, we could create another step to further reduce the matrix, but another method would be to use *Back-Substitution*. -The back-substitution method is precisely what we said above. -If we have a matrix in Row-Eschelon Form, we can directly solve for $$z$$, and then plug that value in to find $$y$$ and then plug both of those values in to find $$x$$! +The back-substitution method is precisely what we said above. +If we have a matrix in Row-Eschelon Form, we can directly solve for $$z$$, and then plug that value in to find $$y$$ and then plug both of those values in to find $$x$$! Even though this seems straightforward, the pseudocode might not be as simple as you thought! {% method %} @@ -283,11 +283,11 @@ The full code can be seen here: [import, lang:"julia"](code/julia/gaussian_elimination.jl) {% endmethod %} - + -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/matrix_methods/matrix_methods.md b/chapters/matrix_methods/matrix_methods.md index 1f8a3d933..5d309777d 100644 --- a/chapters/matrix_methods/matrix_methods.md +++ b/chapters/matrix_methods/matrix_methods.md @@ -8,11 +8,11 @@ Mathematics is the foundation for many areas of science and engineering, and it 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! - + -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/matrix_methods/thomas/code/julia/thomas.jl b/chapters/matrix_methods/thomas/code/julia/thomas.jl index 2fc151274..22c4f3e51 100644 --- a/chapters/matrix_methods/thomas/code/julia/thomas.jl +++ b/chapters/matrix_methods/thomas/code/julia/thomas.jl @@ -18,6 +18,6 @@ function(a::Vector{Float64}, b::Vector{Float64}, c::Vector{Float64}, for i = n-2:0 soln[i] = d[i] - c[i] * soln[i+1] end - + end diff --git a/chapters/matrix_methods/thomas/thomas.md b/chapters/matrix_methods/thomas/thomas.md index 90de2a4c5..27593c981 100644 --- a/chapters/matrix_methods/thomas/thomas.md +++ b/chapters/matrix_methods/thomas/thomas.md @@ -5,23 +5,23 @@ As alluded to in the [Gaussian Elimination chapter](../gaussian_elimination/gaus $$ \left[ \begin{array}{ccccc|c} - b_0 & c_0 & & & & d_0 \\ + b_0 & c_0 & & & & d_0 \\ a_1 & b_1 & c_1 & & & d_1 \\ - & a_2 & \ddots & & & \vdots \\ + & a_2 & \ddots & & & \vdots \\ & & & & c_{n-1}& d_{n-1} \\ & & & a_n & b_n & d_n \end{array} \right] $$ -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. +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. 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. In the end, we will update $$c$$ and $$d$$ to be $$c'$$ and $$d'$$ like so: $$ \begin{align} -c'_i &= \frac{c_i}{b_i - a_i \times c'_{i-1}} \\ +c'_i &= \frac{c_i}{b_i - a_i \times c'_{i-1}} \\ d'_i &= \frac{d_i - a_i*d'_{i-1}}{b_i - a_i \times c'_{i-1}} \end{align} $$ @@ -43,11 +43,11 @@ In code, this will look like this: {% endmethod %} 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. - + -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/monte_carlo/monte_carlo.md b/chapters/monte_carlo/monte_carlo.md index b9bd560f5..4c1ad0c5e 100644 --- a/chapters/monte_carlo/monte_carlo.md +++ b/chapters/monte_carlo/monte_carlo.md @@ -79,7 +79,7 @@ Feel free to submit your version via pull request, and thanks for reading! -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/multiplication/multiplication.md b/chapters/multiplication/multiplication.md index 370181bc3..e285d2300 100644 --- a/chapters/multiplication/multiplication.md +++ b/chapters/multiplication/multiplication.md @@ -1,11 +1,11 @@ # Multiplication -Multiplying two numbers is a relatively simple process. +Multiplying two numbers is a relatively simple process. For the most part, elementary school students learn how to do so quickly before moving on to more complicated mathematical operations. Even so, there are plenty of incredibly complicated algorithms out there to perform the operation. In some sense, this is what I love about computer science research! It takes operations that everyone knows and loves, abstracts them, and transforms them into fast and efficient methods for the computer to implement. -Sometimes these algorithms are completely baffling. +Sometimes these algorithms are completely baffling. 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. I thought, "Why would you ever want to use an fft to do something to trivial? This has to be a joke!" @@ -14,13 +14,13 @@ The Schönhage–Strassen algorithm was actually the most efficient method to mu 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. Here's the point: through time, computer science researchers have managed to take some of the simplist operations imaginable, overcomplicate them, and make them incredibly impressive. -Sometimes it's even worth looking at trivial operations through a new lens. +Sometimes it's even worth looking at trivial operations through a new lens. + - -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/physics_solvers/barnes_hut.md b/chapters/physics_solvers/barnes_hut.md index 17957465a..491b5bb13 100644 --- a/chapters/physics_solvers/barnes_hut.md +++ b/chapters/physics_solvers/barnes_hut.md @@ -3,15 +3,15 @@ # Barnes Hut Algorithm -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! +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! TODO - + -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/physics_solvers/quantum/quantum.md b/chapters/physics_solvers/quantum/quantum.md index 804713229..da78d5e18 100644 --- a/chapters/physics_solvers/quantum/quantum.md +++ b/chapters/physics_solvers/quantum/quantum.md @@ -1,10 +1,10 @@ # Quantum Systems -As I am sure you have heard, the quantum world is weird. +As I am sure you have heard, the quantum world is weird. As you deal with progressively smaller and smaller systems, at some point, it becomes less accurate to describe objects as particles. Instead, it is better to describe objects as probability waves. Again, this is pretty common knowledge; however, there is a distinct lack of readable literature on how to simulate quantum systems, even though there are numerous methods for exactly that! -This section will deal with the computation of quantum states with classical machines. +This section will deal with the computation of quantum states with classical machines. Now, I know what you are thinking, "Wait. Why are we simulating quantum systems on classical computers? Why not simulate it with some sort of experiment or with quantum computers?" Well, here's where the notation get's really sticky. @@ -18,7 +18,7 @@ derstand quantum mechanics Because supercomputers are not great at performing quantum computations, quantum simulators exist as a building block for quantum computation; however, their purpose is not explicity for quantum information theory. Often times a _universal quantum simulator_ is often called a quantum computer. -The truth is that until we have real quantum simulators, simulating quantum systems on classical hardware is as good as we can do. +The truth is that until we have real quantum simulators, simulating quantum systems on classical hardware is as good as we can do. This section is devoted to all the different methods currently used to solve complex quantum systems, so let's start with the Schrodinger Equation, which has many different fomulations. Here is the easiest one to explain: @@ -38,7 +38,7 @@ where $$D$$ is some positive definite matrix and $$\phi(\mathbf{r},t)$$ is the d In fact, this is why one of the most common types of quantum simulation is via _diffusion monte carlo_. There really isn't that much of a difference between the two systems in terms of classical simulation. -As a note: quantum mechanics works fundamentally differently than classical mechanics in physics. +As a note: quantum mechanics works fundamentally differently than classical mechanics in physics. The wavefunction is essentially a set of all possible states for an object to be in, where there is some probability for the particle to be found in each state. This means that it is not possible to say that a particle is at a particular location, and instead we often say that it could be at any location with probability, as shown in the _probability density_: @@ -67,7 +67,7 @@ $$ where $$h$$ is Planck's constant and $$\lambda$$ is the wavelength. This means that we can ultimately move between real and momentum space by using [Fourier Transforms](../../FFT/cooley_tukey.md), which is incredibly useful in a number of cases! -Unfortunately, the interpretation of quantum simulation is rather tricky and is ultimately easier to understand with slightly different notation. +Unfortunately, the interpretation of quantum simulation is rather tricky and is ultimately easier to understand with slightly different notation. This notation is called _braket_ notation, where a _ket_ looks like this: $$ @@ -89,14 +89,14 @@ As we proceed to add new algorithms to simulate quantum systems, I will add more We don't want to re-invent the wheel here. Instead, we want to focus on an area that is often not considered with too much detail -- the algorithms and methods researchers use to ascertain new knowedge about quantum mechanics, like the split-operator method, DMRG, quantum monte carlo, exact diagonalization, and many more. -Quantum mechanics is one of those areas of physics that really does push the boundary of human knowledge in a number of different areas and computing is no different. +Quantum mechanics is one of those areas of physics that really does push the boundary of human knowledge in a number of different areas and computing is no different. In fact, [quantum information theory](../../QI/QI.md) is currently set to be the next innovation to radically change the landscape of modern computation as we know it! Of course, because of the large-scale effects that this will likely have on the industry, it deserved it's own section. - + -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl b/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl index 636f58af0..b77bae5f6 100644 --- a/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl +++ b/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl @@ -17,7 +17,7 @@ struct Param pi / 10.0, Vector{Float64}(vcat(0:512/2 - 1, -512/2 : -1) * pi/10.0)) Param(xmax::Float64, res::Int64, dt::Float64, timesteps::Int64) = new( - xmax, res, dt, timesteps, + xmax, res, dt, timesteps, 2*xmax/res, Vector{Float64}(-xmax+xmax/res:2*xmax/res:xmax), pi/xmax, Vector{Float64}(vcat(0:res/2-1, -res/2:-1)*pi/xmax) ) diff --git a/chapters/physics_solvers/quantum/split-op/split-op.md b/chapters/physics_solvers/quantum/split-op/split-op.md index 6a170e498..85b589561 100644 --- a/chapters/physics_solvers/quantum/split-op/split-op.md +++ b/chapters/physics_solvers/quantum/split-op/split-op.md @@ -91,7 +91,7 @@ The Split-Operator method is one of the most commonly used quantum simulation al -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/physics_solvers/verlet/code/java/verlet.java b/chapters/physics_solvers/verlet/code/java/verlet.java index 412a481be..de6459508 100644 --- a/chapters/physics_solvers/verlet/code/java/verlet.java +++ b/chapters/physics_solvers/verlet/code/java/verlet.java @@ -30,18 +30,18 @@ static void stormer_verlet(double pos, double acc, double dt){ temp_pos = pos; pos = pos*2 - prev_pos + acc * dt * dt; prev_pos = temp_pos; - + // The acceleration is constant, so the velocity is straightforward vel += acc*dt; } - + System.out.println(time); - + } // Simple function for velocity-verlet static void velocity_verlet(double pos, double acc, double dt){ - + // Note that we are using a temp variable for the previous position double time, vel; vel = 0; @@ -51,16 +51,16 @@ static void velocity_verlet(double pos, double acc, double dt){ pos += vel*dt + 0.5*acc * dt * dt; vel += acc*dt; } - + System.out.println(time); - + } - + public static void main(String[] args) { - + verlet(5.0, -10, 0.01); stormer_verlet(5.0, -10, 0.01); velocity_verlet(5.0, -10, 0.01); - + } diff --git a/chapters/physics_solvers/verlet/code/python2/verlet.py b/chapters/physics_solvers/verlet/code/python2/verlet.py index 7800584b8..882fa3084 100644 --- a/chapters/physics_solvers/verlet/code/python2/verlet.py +++ b/chapters/physics_solvers/verlet/code/python2/verlet.py @@ -26,7 +26,7 @@ def step(self): class Verlet(Simulation): - + def step(self): temp_pos = self.obj.pos self.obj.pos = self.obj.pos * 2 - self.prev_pos + self.obj.acc * self.dt * self.dt diff --git a/chapters/physics_solvers/verlet/code/rust/verlet.rs b/chapters/physics_solvers/verlet/code/rust/verlet.rs index 37193e19c..4793afda7 100644 --- a/chapters/physics_solvers/verlet/code/rust/verlet.rs +++ b/chapters/physics_solvers/verlet/code/rust/verlet.rs @@ -28,7 +28,7 @@ fn stormer_verlet(mut pos: f64, acc: f64, dt: f64) { fn velocity_verlet(mut pos: f64, acc: f64, dt: f64) { let mut time = 0.0; - let mut vel = 0.0; + let mut vel = 0.0; while pos > 0.0 { time += dt; diff --git a/chapters/physics_solvers/verlet/verlet.md b/chapters/physics_solvers/verlet/verlet.md index 607723d75..b936601a5 100644 --- a/chapters/physics_solvers/verlet/verlet.md +++ b/chapters/physics_solvers/verlet/verlet.md @@ -1,6 +1,6 @@ # Verlet Integration -Verlet Integration is essentially a solution to the kinematic equation for the motion of any object, +Verlet Integration is essentially a solution to the kinematic equation for the motion of any object, $$ x = x_0 + v_0t + \frac{1}{2}at^2 + \frac{1}{6}bt^3 + \cdots @@ -206,12 +206,12 @@ Submitted by P. Mekhail ### Rust [import, lang:"rust"](code/rust/verlet.rs) {% endmethod %} - + -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/principles_of_code/building_blocks/bitlogic.md b/chapters/principles_of_code/building_blocks/bitlogic.md index b9ed15fe6..dcfc0b411 100644 --- a/chapters/principles_of_code/building_blocks/bitlogic.md +++ b/chapters/principles_of_code/building_blocks/bitlogic.md @@ -40,7 +40,7 @@ Another method is to "roll over" to negative numbers when the bit count gets too | -------------- | ------------- | | 126 | `01111110` | | 127 | `01111111` | -| -128 | `10000000` | +| -128 | `10000000` | | -127 | `10000001` | Ultimately, integer numbers are not that difficult to deal with in binary, so let's move onto something more complicated: *floating-point numbers!* @@ -60,7 +60,7 @@ The idea is similar to before: Each digit represents a power of 2; however, this So for 9.125, we have 1 $$2^3 = 8$$, 1 $$2^0 = 1$$, and 1 $$2^{-3} = \frac{1}{8}$$. Now, how is this actually implemented on your computer? -Well, one way is with the IEE 754 Floating-point Arithmetic Standard. +Well, one way is with the IEE 754 Floating-point Arithmetic Standard. For 32 bits, the first bit is the *sign bit*, the next 8 bits tell us about the number's exponent, and the next 23 are called the *mantissa* and hold the binary string, itself. Now, there are a few points to keep in mind: 1. Because the exponent is being represented in 8 bits, we only have 256 values to play with. This means that the largest exponent we can represent (in single precision) is 128 and the smallest is -127. For this reason, we will add 127 to the power of every floating-point number. So, $$1 = 1 \times 2^{0}$$. The exponent stored is $$0+127 = 127$$. @@ -73,12 +73,12 @@ So here are a few floating-point numbers and their corresponding bitstrings: | ----- | ---- | -------- | -------- | | 9.125 | `0` | `10000010` | `00100100000000000000000`| | - 5.25 | `1` | `10000001` | `01010000000000000000000`| -| - 4096.625 | `1` | `10001011` | `00000000000010100000000` | +| - 4096.625 | `1` | `10001011` | `00000000000010100000000` | Now that we know how to represent integers and floating-point numbers, let's move on to operations, starting with *bitshift operators* #### Bitshift Operators: <<,>> -Bitshift operators do what their name implies: they shift a string of bits one digit to the left (<<) or right (>>). +Bitshift operators do what their name implies: they shift a string of bits one digit to the left (<<) or right (>>). This has the somewhat profound effect of multiplying or dividing the value by 2, which makes sense when you consider that each digit represents a power of 2. Because of the somewhat complicated nature of floating-point numbers, bitshift operators usually only work on integer numbers, like so: @@ -92,7 +92,7 @@ There are more complicated things that can be done with the bitshift operators; #### Logic gates In addition to the bitshift operations, there are a number of logical operations that can be performed on one or two bits together. -These operations are called *gates*, and follow soemwhat straightforward logic. +These operations are called *gates*, and follow soemwhat straightforward logic. The *AND* gate, for example, reads in 2 bits and will only output a 1 value if both inputs are 1. This can be seen in the corresponding truth table: ![AND Truth Table](and.jpg) @@ -119,11 +119,11 @@ And NOT and OR create *NOR*: There are a few other gates, but this is enough for most things. We'll add more as the need arises! That's about it for bitlogic. I realize it was a bit long, but this is absolutely essential to understanding how computers think and how to use programming as an effective tool! - + -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/principles_of_code/building_blocks/building_blocks.md b/chapters/principles_of_code/building_blocks/building_blocks.md index bdbd353d2..12cf2b5ca 100644 --- a/chapters/principles_of_code/building_blocks/building_blocks.md +++ b/chapters/principles_of_code/building_blocks/building_blocks.md @@ -4,6 +4,6 @@ When it comes to programming, there are certain features that will be used again 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. 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. -It's worth pointing out that algorithms and data stuctures almost always go hand-in-hand. -There are many different ways to climb a mountain, but depending on the mountain you need to climb, you might need different tools. +It's worth pointing out that algorithms and data stuctures almost always go hand-in-hand. +There are many different ways to climb a mountain, but depending on the mountain you need to climb, you might need different tools. Similarly, many different algorithms do similar tasks; however, with the right data structures, some algorithms become much more efficient than others. diff --git a/chapters/principles_of_code/building_blocks/classes.md b/chapters/principles_of_code/building_blocks/classes.md index 84bdd67e2..371894b1a 100644 --- a/chapters/principles_of_code/building_blocks/classes.md +++ b/chapters/principles_of_code/building_blocks/classes.md @@ -1,6 +1,6 @@ ### Classes and Structs -A while ago, one of my friends asked me the purpose of classes in programming. +A while ago, one of my friends asked me the purpose of classes in programming. 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. To put it simply, classes are data types that allow programmers to store multiple data types within them. That said, depending on the language, classes might look slightly different. @@ -21,6 +21,6 @@ The truth is that there is a philosophical difference between how languages impl *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. There is merit to both of these arguments, so it's best to go with whatever you feel comfortable with. -In the case of object-oriented languages, classes have an additional layer of complexity associated with them that should definitely be discussed. -That said, I would like to forgo that discussion at this time and come back to it in the near future. +In the case of object-oriented languages, classes have an additional layer of complexity associated with them that should definitely be discussed. +That said, I would like to forgo that discussion at this time and come back to it in the near future. Please bug me if you think I might have forgotten! diff --git a/chapters/principles_of_code/building_blocks/conditions.md b/chapters/principles_of_code/building_blocks/conditions.md index 250115b2f..41a8ec979 100644 --- a/chapters/principles_of_code/building_blocks/conditions.md +++ b/chapters/principles_of_code/building_blocks/conditions.md @@ -21,8 +21,8 @@ Conditions allow you to modify the flow of your program depending on other value It's worth noting here that all the mathematical conditions work in these statements: -| Symbol | Meaning | -| --------------------------- | --------------------------------------- | +| Symbol | Meaning | +| --------------------------- | --------------------------------------- | | a == b | a is equal to b | | a > b | a is greater than b | | a < b | a is less than b | @@ -32,10 +32,10 @@ It's worth noting here that all the mathematical conditions work in these statem Here, the `&&` operator means both conditions must be `true` for the statement as a whole to be considered `true`, while the `||` operator means that only one of the two statements must be `true` for the statement to be considered `true`. Also note that the `!` operator can be used in front of boolean values to signify the value should be to opposite. -For example, if you are trying to indicate that you are not tired (even though you clearly are), you might say `!me.tired()`. +For example, if you are trying to indicate that you are not tired (even though you clearly are), you might say `!me.tired()`. `me.tired()` will return `true`, but the `!` operator will flip the `true` to `false`. -In addition to the `if` and `else` keywords, there is also the `else if`, which varies notationally depending on the language you are using. +In addition to the `if` and `else` keywords, there is also the `else if`, which varies notationally depending on the language you are using. Imagine that we wanted to add two additional functions to the `human` type: `care()`, which evaluates the amount you care about a particular topic and `procrastinate()`, which is the action of wasting time. Imagine (again) that you are studying for an exam that is a month away, but this time, you are studying for a class you do not care about. You might update your thought to be something like, *if I am tired, I will go to sleep. If I don't care about the class, I can continue procrastinating. Otherwise, I should get back to work!* @@ -51,11 +51,11 @@ else end ``` -To be clear: if `me.care()` returns `true`, then the `!` will flip the statement in the `else if` to `false`, and thus you will not procrastinate. +To be clear: if `me.care()` returns `true`, then the `!` will flip the statement in the `else if` to `false`, and thus you will not procrastinate. If `me.care()` returns `false`, the `!` will flip the statement to `true` and you will begin procrastinating if you are not tired. This might take a little thought, and I encourage you to meditate on it, if you so desire. -Now on to something slightly more complicated: *switches*. +Now on to something slightly more complicated: *switches*. Imagine you have a lot of conditions to keep in mind, all of which depend on the same variable. You couldgo through these conditions one-by-one with a chain of `if` and `else if` conditions, like so: @@ -96,7 +96,7 @@ end ``` -To clarify: not all languages have a `switch` statement, and as mentioned, it's not precisely necessary. +To clarify: not all languages have a `switch` statement, and as mentioned, it's not precisely necessary. That said, in languages that do have a `switch`, it's often preferred to a chain of `else if` statements; Though simple, conditions are essential to almost all modern code, so get used to seeing them everywhere! diff --git a/chapters/principles_of_code/building_blocks/functions.md b/chapters/principles_of_code/building_blocks/functions.md index 8fd30afa4..128441247 100644 --- a/chapters/principles_of_code/building_blocks/functions.md +++ b/chapters/principles_of_code/building_blocks/functions.md @@ -1,11 +1,11 @@ ### Functions -Functions make sense from a mathematical point of view. -$$f(x) = 2x+5$$ returns a value for $$f(x)$$ at any point $$x$$ that you want. +Functions make sense from a mathematical point of view. +$$f(x) = 2x+5$$ returns a value for $$f(x)$$ at any point $$x$$ that you want. For example $$f(5) = 15$$, or $$f(10) = 25$$. -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. -For the most part, functions in programming work exactly the same way. -They are dependent on certain variables and return something at the end. +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. +For the most part, functions in programming work exactly the same way. +They are dependent on certain variables and return something at the end. In code, the above function might look like: ``` @@ -21,9 +21,9 @@ In a sense, functions make understanding code much, much easier. ### Recursion -Simply put, recursion is the process of putting a function inside itself. -Now, I know what you are thinking, "Why does this deserve a special name?" -That is a very good question and one that tooke me a while to understand. +Simply put, recursion is the process of putting a function inside itself. +Now, I know what you are thinking, "Why does this deserve a special name?" +That is a very good question and one that tooke me a while to understand. Let's take a simple example: ```julia @@ -60,7 +60,7 @@ I guess the main point is this: *recursion is powerful, but with great power com -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/principles_of_code/building_blocks/loops.md b/chapters/principles_of_code/building_blocks/loops.md index 51973d216..12062ff34 100644 --- a/chapters/principles_of_code/building_blocks/loops.md +++ b/chapters/principles_of_code/building_blocks/loops.md @@ -1,9 +1,9 @@ ### Loops -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. -Nowadays, I see them as essential elements to almost any program I write. +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. +Nowadays, I see them as essential elements to almost any program I write. There two basic loop types: `for` and `while`, which are syntactically similar and reasonably intuitive. -Let's say you want to walk out of a room with a closed door. +Let's say you want to walk out of a room with a closed door. In code, this might look something like: ```julia @@ -32,12 +32,12 @@ In this case $$i$$ is an interable variable that steps through the range of `1:1 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. Ultimately, loops allow programmers to repeat the same operation multiple times and are the heart most programs and simulations I have seen. - + -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/principles_of_code/building_blocks/variables.md b/chapters/principles_of_code/building_blocks/variables.md index bf3c3ce29..a27ea350c 100644 --- a/chapters/principles_of_code/building_blocks/variables.md +++ b/chapters/principles_of_code/building_blocks/variables.md @@ -1,30 +1,30 @@ ### Variable and Types -For many people, declaring variables and types is a straightforward process. -The idea is simple: variables hold values. +For many people, declaring variables and types is a straightforward process. +The idea is simple: variables hold values. We set these values with the `=` sign. -For example, if we say +For example, if we say ``` x = 5 ``` -Then we have set the value of the variable $$x$$ to be $$5$$. +Then we have set the value of the variable $$x$$ to be $$5$$. But here's a question that your computer has to answer: what is $$5$$? -To us, the answer's trivial, it's a number! -This is true, but there are different kinds of numbers. -There are integers that include all counting numbers from negative to positive infinity: $$-\infty, \cdots, -1, 0, 1, \cdots, \infty$$. -Then there are floating-point numbers which include everything in-between every counting number; however, that is not the end of the story. -Floating-point numbers also have certain levels of precision, the numbers of $$0$$'s after the decimal point. +To us, the answer's trivial, it's a number! +This is true, but there are different kinds of numbers. +There are integers that include all counting numbers from negative to positive infinity: $$-\infty, \cdots, -1, 0, 1, \cdots, \infty$$. +Then there are floating-point numbers which include everything in-between every counting number; however, that is not the end of the story. +Floating-point numbers also have certain levels of precision, the numbers of $$0$$'s after the decimal point. For example, $$1.01$$ is more precise than $$1.0$$. Each of these levels of precision will require a different level of storage space on the computer, so it make sense to differentiate them based on the amount of storage they require. -In the end, all of these variables will be stored as some number, $$n$$, binary bits, which are constrained to be either $$0$$ or $$1$$ and as we increase the number of bits, we can hold $$2^n$$ possible values. +In the end, all of these variables will be stored as some number, $$n$$, binary bits, which are constrained to be either $$0$$ or $$1$$ and as we increase the number of bits, we can hold $$2^n$$ possible values. -This means that we have multiple different floating-point and integer types: `float16`, `int16`, `float32`, `int32`, `float64`, `int64`, and so on. +This means that we have multiple different floating-point and integer types: `float16`, `int16`, `float32`, `int32`, `float64`, `int64`, and so on. Here, the number ($$16, 32, 64,\cdots$$) at the end of the declared variable corresponds to the number of bits used to represent that number. -For the most part, *double precision* or `float64` is good enough for almost all computation; however, sometimes higher precision is necessary and other times lower precision will speed up computation tremendously. +For the most part, *double precision* or `float64` is good enough for almost all computation; however, sometimes higher precision is necessary and other times lower precision will speed up computation tremendously. -Most languages allow you to explicitly state the type of every variable, but some languages may treat these variables differently than expected, depending on the type provided. +Most languages allow you to explicitly state the type of every variable, but some languages may treat these variables differently than expected, depending on the type provided. For example: ``` @@ -43,9 +43,9 @@ print(1/y) ``` Here, the same mathematical expression provided two radically different results! -Now, you might be thinking that the first output is *more correct*, but this is not exactly true. -The second expression was simply a case of *integer division* and is useful in many cases. -Unfortunately, it is also a notorious source of errors, which is why it's always a good idea to check the types of all variables in a program just to be sure you are doing the appropriate computation. +Now, you might be thinking that the first output is *more correct*, but this is not exactly true. +The second expression was simply a case of *integer division* and is useful in many cases. +Unfortunately, it is also a notorious source of errors, which is why it's always a good idea to check the types of all variables in a program just to be sure you are doing the appropriate computation. To be explicit: ``` @@ -54,13 +54,13 @@ To be explicit: It's important to keep in mind what you are trying to say and what your computer hears you saying. -Now, variables do not need to be explicitly numbers. -They can be strings (`"hello world!"`), or any data structure you could want. +Now, variables do not need to be explicitly numbers. +They can be strings (`"hello world!"`), or any data structure you could want. These data structures will interact with each other differently and these interactions are sometimes language-dependent, so be careful when working with them! In addition, some of these data structures have functions unique to them that me may call upon as programmers. -For example, `vectors` are data containers that hold other data structures. -In almost every language, there is a function that can be used to get the size of a `vector` in order to tell how many elements it holds. +For example, `vectors` are data containers that hold other data structures. +In almost every language, there is a function that can be used to get the size of a `vector` in order to tell how many elements it holds. In addition, the vector also has methods to `push` elements into it. In C++, for example, vectors often look like this: @@ -87,11 +87,11 @@ Here, the `size()` function should return 3, because we have put in 3 elements. We will talk more about vectors in a bit, but for now, know that certain functions are available to be used on certain types, and in most object-oriented languages, these functions are called with a simple `.`. Almost all laguages also allow users to define their own types in the form of `classes`, which will also be touched on later in this section. - + -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/principles_of_code/choosing_a_language/choosing_a_language.md b/chapters/principles_of_code/choosing_a_language/choosing_a_language.md index eb17a4d45..1a90b0768 100644 --- a/chapters/principles_of_code/choosing_a_language/choosing_a_language.md +++ b/chapters/principles_of_code/choosing_a_language/choosing_a_language.md @@ -1,56 +1,56 @@ ## Choosing a Language -I'm not going to beat around the bush here. -Every single time I try something new, I fail at it. -Programming was no exception. -By the time I started to learn programming, I knew how to use a terminal decently well, but that was it. -I remember googling, "What is the best programming language." The response was (of course) mixed. -Many experts said Python was the way to go when learning programming because it was easy to use and used professionally in many areas of computer science and scientific research. -Others said to go for Java, which was the most common language to learn for computer science students and thus had a large and rich archive of text to learn from. -Still others said to go for C++ or FORTRAN. -I was inundated with new information, and I felt like I was drowning in it. +I'm not going to beat around the bush here. +Every single time I try something new, I fail at it. +Programming was no exception. +By the time I started to learn programming, I knew how to use a terminal decently well, but that was it. +I remember googling, "What is the best programming language." The response was (of course) mixed. +Many experts said Python was the way to go when learning programming because it was easy to use and used professionally in many areas of computer science and scientific research. +Others said to go for Java, which was the most common language to learn for computer science students and thus had a large and rich archive of text to learn from. +Still others said to go for C++ or FORTRAN. +I was inundated with new information, and I felt like I was drowning in it. -As a fledgling programmer, the problem for me was deciding which language was right for the projects I wanted to do. -In my head, I still wanted to be an author, so I wanted to make something creative, and because my entire group of friends was into gaming at the time, I wanted a language that I could make games with. -This radically changed my google search to "What language is best for making games?" -It was still a bad search. -Apparently, almost any language can be used to make games. -Who would have guessed? +As a fledgling programmer, the problem for me was deciding which language was right for the projects I wanted to do. +In my head, I still wanted to be an author, so I wanted to make something creative, and because my entire group of friends was into gaming at the time, I wanted a language that I could make games with. +This radically changed my google search to "What language is best for making games?" +It was still a bad search. +Apparently, almost any language can be used to make games. +Who would have guessed? -So there I was, struggling to figure out what to do and where to go. -I decided to do what any teenage boy would do in that situation: go to the bookstore and see what books were actually available for purchase at the time. -Now, I think the first book I picked up really describes the desperate pit I had dug for myself. -It was a book on how to make websites in HTML. -That was about as far away as I could have gotten from my goal of making video games. -I will refrain from commenting further on that book for now because a much more important decision was ahead of me. -There before me was an aisle with all the key players I had heard about online: C, C++, C#, Java, Python, Ruby, and so on. -They were there just waiting to be chosen. +So there I was, struggling to figure out what to do and where to go. +I decided to do what any teenage boy would do in that situation: go to the bookstore and see what books were actually available for purchase at the time. +Now, I think the first book I picked up really describes the desperate pit I had dug for myself. +It was a book on how to make websites in HTML. +That was about as far away as I could have gotten from my goal of making video games. +I will refrain from commenting further on that book for now because a much more important decision was ahead of me. +There before me was an aisle with all the key players I had heard about online: C, C++, C#, Java, Python, Ruby, and so on. +They were there just waiting to be chosen. I knew my time had come. I needed to make a decision then and there! -At the time, I knew the choice didn't really matter. -I knew that no matter which language I learned first, most ideas would transfer from language to language. -At the same time, the thought of making an uninformed decision terrified me, so I sat there in the bookstore for hours, just staring and thinking to myself. -At some point, a store employee walked by and I asked if he knew anything about programming. -He said he did, so I asked the only question that popped into my head at the time, "What's the difference between C, C++, and C#?" +At the time, I knew the choice didn't really matter. +I knew that no matter which language I learned first, most ideas would transfer from language to language. +At the same time, the thought of making an uninformed decision terrified me, so I sat there in the bookstore for hours, just staring and thinking to myself. +At some point, a store employee walked by and I asked if he knew anything about programming. +He said he did, so I asked the only question that popped into my head at the time, "What's the difference between C, C++, and C#?" -The employee said that C# was the newest of the three languages, but that all three were used regularly and if I wanted to learn programming, any would do. -Like the experts online, he then suggested Python because it was easy for beginners and I was clearly a novice. -I thanked him for his time and began thumbing through the book on C#. +The employee said that C# was the newest of the three languages, but that all three were used regularly and if I wanted to learn programming, any would do. +Like the experts online, he then suggested Python because it was easy for beginners and I was clearly a novice. +I thanked him for his time and began thumbing through the book on C#. I remember thinking, *C must be the original language. C+ must be the next generation, followed by C++, then C+++, and then they stylistically changed C++++ to C# by placing the 4 plusses in a pound sign. I guess this means that C will be a little too outdated, but C# might be a little too new. I'll go with C++.* -I was proud of my deductive reasoning, but before continuing, I would like to point out that this logic was completely flawed. -There was never a C+ or a C+++ (so far as I'm aware). -The truth was that I didn't know any better. +I was proud of my deductive reasoning, but before continuing, I would like to point out that this logic was completely flawed. +There was never a C+ or a C+++ (so far as I'm aware). +The truth was that I didn't know any better. My hope is that many people had similar experiences when they started programming, otherwise I am going to be really embarrassed when people start reading this book. -Suffice it to say that I learned a good deal of C++, which was a good choice in the end. -It is one of the languages I use most frequently nowadays (alongside Python, CUDA, Julia, and FORTRAN), and is an essential tool in my belt. -That said, I primarily do computational physics. -Everyone will need a different set of tools to attack different problems. +Suffice it to say that I learned a good deal of C++, which was a good choice in the end. +It is one of the languages I use most frequently nowadays (alongside Python, CUDA, Julia, and FORTRAN), and is an essential tool in my belt. +That said, I primarily do computational physics. +Everyone will need a different set of tools to attack different problems. So. Let's address the issue of choosing a language. -As mentioned, this text does everything it can to be *language agnostic,* so the language will not matter too much when trying to learn the algorithms herein; however, it will matter when you try to implement anything on your own. +As mentioned, this text does everything it can to be *language agnostic,* so the language will not matter too much when trying to learn the algorithms herein; however, it will matter when you try to implement anything on your own. It would also be nice to formally distinguish what makes certain languages worth using. For now, let's briefly list all the languages we will eventually cover in the archive: @@ -65,6 +65,6 @@ For now, let's briefly list all the languages we will eventually cover in the ar 1. Python 2. Julia (half interpreted, to be discussed) -We will obviously add more languages with time. -This is simply a quick list. +We will obviously add more languages with time. +This is simply a quick list. Please let me know which languages you want to cover and I'll add them here! diff --git a/chapters/principles_of_code/choosing_a_language/compiled/compiled.md b/chapters/principles_of_code/choosing_a_language/compiled/compiled.md index d79ebb404..83a759e64 100644 --- a/chapters/principles_of_code/choosing_a_language/compiled/compiled.md +++ b/chapters/principles_of_code/choosing_a_language/compiled/compiled.md @@ -1,18 +1,18 @@ ## Compiled Languages -Programming is hard because we need to write instructions for our computer. -The computer then reads this set of instructions and executes them accordingly. -That's the story, at least. -In principle, there is more to it: *compilation*. -Compilation is the act of translating what we write into something the computer can read. +Programming is hard because we need to write instructions for our computer. +The computer then reads this set of instructions and executes them accordingly. +That's the story, at least. +In principle, there is more to it: *compilation*. +Compilation is the act of translating what we write into something the computer can read. This is done with a *compiler*. In this section, we will talk about all the compiled languages and discuss how to deal with different compilers and compiling options. 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. -If I'm being honest, this was by far the most confusing part of programming for me. +If I'm being honest, this was by far the most confusing part of programming for me. I could grasp the computing concepts, but getting the computer to run my code seemed like an impossible chore. 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. -IDE's are coding environments that pull up a GUI text editor to write and run code in. +IDE's are coding environments that pull up a GUI text editor to write and run code in. This is obviously an optimal way to program; however, I tend to dislike GUI-based solutions when there is a command-line option available. It wasn't until I saw a compilation command in my terminal that it started to make sense: diff --git a/chapters/principles_of_code/code_quality.md b/chapters/principles_of_code/code_quality.md index 988dceed4..c4ed35ac2 100644 --- a/chapters/principles_of_code/code_quality.md +++ b/chapters/principles_of_code/code_quality.md @@ -1,19 +1,19 @@ ## Code Quality -I am a computational physicist. Industry programmers give researchers a hard time for their programming capabilities, not because they cannot code, but because (for the most part) research code looks bad. -Programming, like any other form of creative expression, is limited by the artist's ability to creatively express themselves. -For many computational researchers, the code is not their art. Science is. -Programming is simply the brush they use to stroke the canvas of reality. +I am a computational physicist. Industry programmers give researchers a hard time for their programming capabilities, not because they cannot code, but because (for the most part) research code looks bad. +Programming, like any other form of creative expression, is limited by the artist's ability to creatively express themselves. +For many computational researchers, the code is not their art. Science is. +Programming is simply the brush they use to stroke the canvas of reality. Many times, they become so consumed with their painting that they ignore their tools. Now, truth be told, I have seen some pretty repulsive industry code, too, so this complaint is not exclusively biased towards researchers. -No matter what the intended goal might be, it is important to be able to read and understand the code you are writing. I know putting a comment block at the start of programs might seem like a chore, but it's not so bad, and letting everyone know up-front what the code is intended to do is incredibly useful to readers. Remember that in a few months, you will be a reader too. Take the time to properly care for your code, to clean your brush after using it. It'll pay off in the long run, I promise. +No matter what the intended goal might be, it is important to be able to read and understand the code you are writing. I know putting a comment block at the start of programs might seem like a chore, but it's not so bad, and letting everyone know up-front what the code is intended to do is incredibly useful to readers. Remember that in a few months, you will be a reader too. Take the time to properly care for your code, to clean your brush after using it. It'll pay off in the long run, I promise. ### Comments / style Comments. Every language has a different way to introduce them. Some use the noble #, others the //, still others the ! or $ or C. Regardless of your language of choice, every single language offers you the ability to tell readers what you are intending to do with your code. This is a necessary component to programming. In fact, I would argue that it is one of the most useful part of any code. Sure, the code has to work. It's gotta compile and do something useful, but I cannot tell you how many times I have had to fix broken code that no one had looked at for years. Sometimes this is a long and laborious process, taking every ounce of my mental abilities, and other times it only takes a few minutes. What's the difference? Comments and documentation. -I remember the first time I learned to program, I found commenting tedious. I remember thinking, "Hah. This is completely useless. Any programmer worth their salt will be able to figure out what I am trying to do in no time!" Turns out, I wasn't worth my salt because after trying to figure out my code a month later, I couldn't figure out what on Earth I was trying to do. Here's the truth: when it comes to programming, you are often your own audience. Trust me, I know it seems like a good idea to keep the code short -- to go for witty one-liners that make you feel brilliant, but these make your code impossible to read. +I remember the first time I learned to program, I found commenting tedious. I remember thinking, "Hah. This is completely useless. Any programmer worth their salt will be able to figure out what I am trying to do in no time!" Turns out, I wasn't worth my salt because after trying to figure out my code a month later, I couldn't figure out what on Earth I was trying to do. Here's the truth: when it comes to programming, you are often your own audience. Trust me, I know it seems like a good idea to keep the code short -- to go for witty one-liners that make you feel brilliant, but these make your code impossible to read. -When researching, we keep lab notebooks. It's common practice for obvious reasons. If I forget what I was doing the other day or need to look up parameters, I check the lab notebook. If other researchers question the results of my simulations, I check my lab notebook. If I don't know what to do because I have tried everything I can possibly think of, I check my lab notebook. It's a place for inspiration, for validation, and for guidance. When programming, your code should tell the story of your program. It should reveal the hidden secrets that make your code tick. If anyone finds a bug in the code downstream, they should be able to figure out exactly what went wrong and fix it themselves. +When researching, we keep lab notebooks. It's common practice for obvious reasons. If I forget what I was doing the other day or need to look up parameters, I check the lab notebook. If other researchers question the results of my simulations, I check my lab notebook. If I don't know what to do because I have tried everything I can possibly think of, I check my lab notebook. It's a place for inspiration, for validation, and for guidance. When programming, your code should tell the story of your program. It should reveal the hidden secrets that make your code tick. If anyone finds a bug in the code downstream, they should be able to figure out exactly what went wrong and fix it themselves. I guess my point is that commenting your code and keeping proper documentation is about more than just cleaning up after yourself. It is a fundamental part to the art of programming. It's like polishing your guitar on a sunny day. It's revising your poems after a long evening of writing. It's levelling your monk before the next raid. It's essential. Do not neglect it! diff --git a/chapters/principles_of_code/notation/notation.md b/chapters/principles_of_code/notation/notation.md index 2410e1e71..d3247bc29 100644 --- a/chapters/principles_of_code/notation/notation.md +++ b/chapters/principles_of_code/notation/notation.md @@ -1,12 +1,12 @@ ### Complexity Notation -Algorithms are designed to solve problems. -Over time, new algorithms are created to solve problems that old algorithms have already solved. -In some cases, the new algorithms are not intrinsically *better* than the older ones. -In other cases, these new algorithms breathe life into areas of research and engineering that could not exist without them. +Algorithms are designed to solve problems. +Over time, new algorithms are created to solve problems that old algorithms have already solved. +In some cases, the new algorithms are not intrinsically *better* than the older ones. +In other cases, these new algorithms breathe life into areas of research and engineering that could not exist without them. The question is: what makes an algorithm "better" than another one? -Obviously, there is no good answer to this question. +Obviously, there is no good answer to this question. If you write an algorithm to solve a problem, whatever you come up with will probably work just fine for small problems. That said, if you need to use the algorithm for a larger system, you might find yourself waiting for longer and longer on your code to run. In these cases, it's obvious that *if you are working on a large system, you need an algorithm that scales well with a large size*. @@ -22,7 +22,7 @@ Big $$O$$ assumes the worst, which is the often the most useful description of a On the other hand, $$\Omega$$ assumes the best and $$\Theta$$ is used when the best and worst cases are the same. Of the three Big $$O$$ is used the most, and is used in conversation to mean that the algorithm will take "on the order of" $$n$$ operations. -Unfortunately, at this point, these notations might be a little vague. +Unfortunately, at this point, these notations might be a little vague. In fact, it was incredibly vague for me for a long time, and it wasn't until I saw the notations in action that it all started to make sense, so that's what this section is about: providing concrete examples to better understand computational complexity notation. ### Constant Time @@ -35,9 +35,9 @@ function constant(a::Array{Float64}) end ``` -Obviously, no matter how large `a` is, this function will not take any longer to run. +Obviously, no matter how large `a` is, this function will not take any longer to run. Because of this, we say it has a constant runtime and notate it with $$O(1) = \Omega(1) = \Theta(1)$$. -Basically, we are saying that this function will run with 1 operation total (a single print). +Basically, we are saying that this function will run with 1 operation total (a single print). The best-case runtime will be 1 operation, the worst-case runtime will be 1 operation, and because they are both the same, we can use $$\Theta$$ to notate that. Now imagine the following function: @@ -51,24 +51,24 @@ function constant(a::Array{Float64}) end ``` -This function has 3 print statements, so it has 3 operations total. +This function has 3 print statements, so it has 3 operations total. Because of this, it's tempting to say that the runtime would be $$O(3) = \Omega(3) = \Theta(3)$$, and you would not be wrong; however, complexity notations often make a big assumption: **we don't care about constants!** What does this mean? Well, it means that we get rid of all constants that are not 1! In this case, that means we set $$O(3) = O(1)$$. Now, I know what you are thinking, *That's stupid! It's clear that the second function will take 3 times as long to run, shouldn't we notate that?* -You're not wrong; however, complexity notation is mostly interested in how algorithms scale with larger and larger inputs. +You're not wrong; however, complexity notation is mostly interested in how algorithms scale with larger and larger inputs. Because we are talking about constant run-time, there is no scaling with larger inputs. No matter what array you read in to the above functions, they will always take a constant number of operations to finish. -Whether that constant time is 1 operation or 3 operations doesn't really matter because different machines will have different runtimes anyway. +Whether that constant time is 1 operation or 3 operations doesn't really matter because different machines will have different runtimes anyway. Now, here's the thing: as we move on to more complicated examples, we will continue to ignore constants and extra terms to make the notation easier to understand. -Just because this is common practice does not mean it's the *best* practice. +Just because this is common practice does not mean it's the *best* practice. I have run into several situation where knowing the constants has saved me hours of run-time, so keep in mind that all of these notations are somewhat vague and dependent on a number of auxiliary factors. Still, that doesn't mean the notation is completely useless. For now, let's keep moving forward with some more complicated (and useful) examples! ### Linear Time -Now we are moving into interesting territory! +Now we are moving into interesting territory! Let's consider the following function: ```julia @@ -102,7 +102,7 @@ Technically has a complexity of $$\Theta(\frac{3n}{2} + 2)$$, but we'll just cal Regardless of the notation, if you see something that is $$O(n)$$, you know that *at worst* it will run at the speed of a `for` loop, which is pretty good! ### Polynomial Time -A promise of $$O(n)$$ is not bad in terms of run-time; however, it is unlikely that you will run into too many straightforward algorithms that are $$O(n)$$. +A promise of $$O(n)$$ is not bad in terms of run-time; however, it is unlikely that you will run into too many straightforward algorithms that are $$O(n)$$. For example, let's say you have a square, 2D image and want to iterate through all of its points. Well, to do this, we might write code that looks something like: @@ -119,12 +119,12 @@ end ``` This is a simple case where a nested `for` loop is perfectly acceptable, and it's obvious geometrically that we need to access $$\mathrm{size}\times\mathrm{size}$$ number of elements (because we are working with a square). -This means that this example has $$\Theta(n^2)$$ complexity. This is not great. +This means that this example has $$\Theta(n^2)$$ complexity. This is not great. If you have to access 3D space, this might require $$\Theta(n^3)$$, which is even worse! Don't even get me started on 4D! Intuitively, if you see anything that has a polynomial runtime, it's easy to think of it as a bunch of nested `for` loops. That said, there have been several cases throughout the history of algorithms where polynomial runtimes have inhibited certain algorithms from being used entirely, simply because it takes too long to run! -For this reason, if you can avoid writing nested `for` loops, you certainly should! +For this reason, if you can avoid writing nested `for` loops, you certainly should! However, there are several cases where this cannot be avoided, so don't spend too much time worrying about it unless runtime becomes an issue! ### Exponential and Logarithmic Time @@ -143,7 +143,7 @@ function exponential(value::Int64, n::Int64) end ``` -Here, we read in the maximum number `n` we are iterating through and recursively call the `exponential` function, decrementing the number of iterations left each time. +Here, we read in the maximum number `n` we are iterating through and recursively call the `exponential` function, decrementing the number of iterations left each time. Because we are calling the `exponential` function twice, this has a complexity of $$\Theta(2^n)$$, which is not great, but if it's the only way to get a job done, it's the only way to get a job done. Logarithmic algorithms can be thought of as the opposite of exponential ones. @@ -159,9 +159,9 @@ function logarithmic(a::Array{Float64}, cutoff::Int64) end ``` To be honest, it is not obvious that the provided `logarithmic` function should operate in $$\Theta(\log(n))$$ time, where $$n$$ is the size of `a`. -That said, I encourage you to think about an array of size 8. -First, we split it in half, creating 2 arrays of 4 elements each. -If we split these new arrays, we have 4 arrays of 2, and if we split these by two we have 8 arrays of 1 element each. +That said, I encourage you to think about an array of size 8. +First, we split it in half, creating 2 arrays of 4 elements each. +If we split these new arrays, we have 4 arrays of 2, and if we split these by two we have 8 arrays of 1 element each. This is as far as we can go, and we ended up dividing the array 3 times to get to this point. $$3 = \log_2(8)$$, so this function runs with a logarithmic number of operations. @@ -169,39 +169,39 @@ $$3 = \log_2(8)$$, so this function runs with a logarithmic number of operations We've outlined the most common complexity cases of different algorithms here, but at this point things might still be unclear. Which is better: $$O(n^2)$$ or $$O(log(n))$$? -Well, let's plot all the different cases out, and the answer should become obvious. +Well, let's plot all the different cases out, and the answer should become obvious. ![Complexity plot](cplot.png) -Here, we see each of the complexity cases as $$n$$ increases. +Here, we see each of the complexity cases as $$n$$ increases. Clearly, linear time is not bad when compared to polynomial or exponential time; however, if you can manage something in logarithmic or constant time, do it! Now, there is a lot more to say about computational complexity and we'll definitely cover it at some point, but I can only move so fast! In particular, I would love to have a discussion on the $$P=NP$$ issue that has been rustling the jimmies of a few computer scientists for a while, but we'll get to that in due time. ### Final Warning -This is a book about algorithms. +This is a book about algorithms. It would be nearly impossible to talk about most algorithms without touching on complexity theory and explaining why certain algorithms are faster than others. -That said, just because an algorithm runs in $$O(\log n)$$ does not mean it will always be faster than one that runs in $$O(n^2)$$. +That said, just because an algorithm runs in $$O(\log n)$$ does not mean it will always be faster than one that runs in $$O(n^2)$$. Because complexity notation often ignores constants, there could be a crazy constant that we are missing that actually makes a huge difference in runtime. In addition, in order to use an algorithm that seems faster based on complexity notation, you may need to use a library that massively increases runtime due to a plethora of other reasons. -Basically, take complexity notation with a grain of salt. -It is a useful descriptor of how fast algorithms should run in an ideal world; however, ideal worlds do not exist. -When it comes to programming, there may be hundreds of other factors that need to be considered before implementing anything. -That said, complexity notation should not be ignored. +Basically, take complexity notation with a grain of salt. +It is a useful descriptor of how fast algorithms should run in an ideal world; however, ideal worlds do not exist. +When it comes to programming, there may be hundreds of other factors that need to be considered before implementing anything. +That said, complexity notation should not be ignored. If you can easily implement an algorithm that is notationally faster with no repercussions, go for it! Just be sure you do not waste time trying to optimize code you haven't written yet. In general, my advice would be the following: -write code first and optimize what you can on the first run-through without going too far out of your way. +write code first and optimize what you can on the first run-through without going too far out of your way. If the runtime is awful, go back and see about implementing algorithms that are faster based on complexity notation. -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/principles_of_code/principles_of_code.md b/chapters/principles_of_code/principles_of_code.md index 2afb9798b..7e7a58ec3 100644 --- a/chapters/principles_of_code/principles_of_code.md +++ b/chapters/principles_of_code/principles_of_code.md @@ -1,6 +1,6 @@ # The Principles of Code -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. +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. Here's that cycle again in code: @@ -21,7 +21,7 @@ end create_something(Human(0,1)) ``` -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!* +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!* 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! diff --git a/chapters/principles_of_code/version_control.md b/chapters/principles_of_code/version_control.md index d89f4e848..85fe6fee9 100644 --- a/chapters/principles_of_code/version_control.md +++ b/chapters/principles_of_code/version_control.md @@ -1,44 +1,44 @@ ## Git and Version Control -I am a fan of open-source software. It allows users to see inside the code running on their system and mess around with it if they like. -Unlike proprietary software, open source software allows any user to learn the entire codebase from the ground up, and that's an incredibly exciting prospect! -More than that, open-source development breeds strong communities of like-minded individuals who work together to solve problems they care about. -At least in my case, different open-source communites inspired me to code in my free time. -It taught me that programming is more than a simple series of instructions for a computer. -More than anything, though, open-source software development taught me about how to work with others and overcome petty squabbles, because if there's one thing any open-source community is known for, it's petty squabbling. - -It might be because of my appreciation of large-scale software development that I never questioned the utility of version control. -If there are a couple hundred people all contributing source code to the same place, there has to be some way to control all the different codebases each individual has on their own machine. -Even if I have no collaborators, version control is a way to make sure my laptop and work machine both have the same code without having to transer a USB stick back and forth. -That said, at some point in my life, I became a physics researcher. -This meant that I wrote code to solve physics problems with a small team. The problem was that even though I was using version control, the rest of my team was not. +I am a fan of open-source software. It allows users to see inside the code running on their system and mess around with it if they like. +Unlike proprietary software, open source software allows any user to learn the entire codebase from the ground up, and that's an incredibly exciting prospect! +More than that, open-source development breeds strong communities of like-minded individuals who work together to solve problems they care about. +At least in my case, different open-source communites inspired me to code in my free time. +It taught me that programming is more than a simple series of instructions for a computer. +More than anything, though, open-source software development taught me about how to work with others and overcome petty squabbles, because if there's one thing any open-source community is known for, it's petty squabbling. + +It might be because of my appreciation of large-scale software development that I never questioned the utility of version control. +If there are a couple hundred people all contributing source code to the same place, there has to be some way to control all the different codebases each individual has on their own machine. +Even if I have no collaborators, version control is a way to make sure my laptop and work machine both have the same code without having to transer a USB stick back and forth. +That said, at some point in my life, I became a physics researcher. +This meant that I wrote code to solve physics problems with a small team. The problem was that even though I was using version control, the rest of my team was not. This was frustrating. -I would hear my labmates say things like, "I rewrote my code last night and now nothing works, but I already saved over my previous version, so I'll just work with what I have." +I would hear my labmates say things like, "I rewrote my code last night and now nothing works, but I already saved over my previous version, so I'll just work with what I have." Or, "I'm writing a paper with my boss. We are using Dropbox and upload files with slightly different names after we modify them. Right now, we are on paper_78c." -The point is: version control exists to control different versions of software (and other documents). -If you are writing code, it exists as a way to quickly save what you have before making largescale modifications. +The point is: version control exists to control different versions of software (and other documents). +If you are writing code, it exists as a way to quickly save what you have before making largescale modifications. It also allows individuals to collaborate on a larger scale by providing necessary tools to merge work created by different individuals into a single, cohesive story. No matter how you look at it, version control is a useful and necessary tool to collaborate with other programmers and is definitely worth discussing in depth. Though many version control systems exist, for now we will focus on git, simply because it is incredibly popular and this book is hosted both on github and gitbook. -We hope to discuss other version control methods and strengthen this tutorial on git in the future; however, this book is meant as an archive of algorithms, not as an introduction to version control or best software practices. +We hope to discuss other version control methods and strengthen this tutorial on git in the future; however, this book is meant as an archive of algorithms, not as an introduction to version control or best software practices. Though discussions like these are useful, we must be careful not to get too far out-of-scope. -For now, this tutorial is simply meant as a quick way to kickstart our community into using git and collaborating more effectively with each other (specifically on this book). +For now, this tutorial is simply meant as a quick way to kickstart our community into using git and collaborating more effectively with each other (specifically on this book). I feel like this introduction may have been a little too long. Let me know what you think! Regardless, now it's time to talk about git! ### *Git*ting started! -I suppose let's start simply: git manages different versions of code available on different machines and from different locations. -When using git, there will be a local copy of a repository of code that may or may not be up-to-date with a copy of the code repository in some remote location. +I suppose let's start simply: git manages different versions of code available on different machines and from different locations. +When using git, there will be a local copy of a repository of code that may or may not be up-to-date with a copy of the code repository in some remote location. -Now, there is an easy way, a hard way, and an impossibly complicated way to use git. +Now, there is an easy way, a hard way, and an impossibly complicated way to use git. We'll be walking through the easy and hard ways. We are not trying to impress anyone with git wizardry. We are simply trying to provide the basics with a little undersanding sprinkled in. -As a side note: we will be assuming that you are using git from the terminal. There is a GUI available from github and it works super well for most cases; however, it's also self-explanatory in most cases. +As a side note: we will be assuming that you are using git from the terminal. There is a GUI available from github and it works super well for most cases; however, it's also self-explanatory in most cases. Put another way: if you can understand the ways of the terminal, the git GUI will be much more straightforward. On the other hand, learning the GUI will not necessarily help you when using the terminal. So, first things first. Make sure git is installed on your system and set it up with the following commands @@ -50,19 +50,19 @@ git config --global user.email name@email.com Obviously, use your own name and e-mail... unless your name is actually *name* and your e-mail is actually *name@email.com*, in which case the above commands are correct. In the rare case that a user named "name" with the e-mail "name@email.com" is reading this, I apologize for spoiling your anonymity. -For everyone else, remember that git is meant to facilitate collaborative code development, so we need to know who is submitting code so we can communicate more effectively later. -That said, it is alright to use a username and e-mail address that does not spoil your identity in the real world, so long as you are reachable by the information provided. +For everyone else, remember that git is meant to facilitate collaborative code development, so we need to know who is submitting code so we can communicate more effectively later. +That said, it is alright to use a username and e-mail address that does not spoil your identity in the real world, so long as you are reachable by the information provided. ### Finding some code Now we need to find a repository of code to work on. If you are starting your own repository or want to work on an internal network, this will not be too big of an issue. -If you just want to get the feel for how git works, I suggest going to [github.com](https://github.com/) and checking out the code developed there. +If you just want to get the feel for how git works, I suggest going to [github.com](https://github.com/) and checking out the code developed there. Note that you will not be able to contribute to any old directory on github, simply because if anyone could contribute any code they wanted to any repository they wanted, the world would become incredibly chaotic. Because of this, you may want to create a repository under your own github username or make your own copy of someone elses code on github by clicking the *fork* button: ![How to fork](fork.png) -Note that if you have a fork of a particular code repository, you can ask the owner of the original code repository to pull your changes into their version of the code with a *pull request*, but we are getting ahead of ourselves here. +Note that if you have a fork of a particular code repository, you can ask the owner of the original code repository to pull your changes into their version of the code with a *pull request*, but we are getting ahead of ourselves here. If you cannot think of what repository to work on and want to collaborate on this project in the future, feel free to fork the [Algorithm Archive](https://github.com/algorithm-archivists/algorithm-archive) and modify that! Regardless, as long as there is a repository under your username on github, we can continue by linking that remote github location to your local git directory. First, we need to find the url of the github repository, as shown here: @@ -70,7 +70,7 @@ Regardless, as long as there is a repository under your username on github, we c ![How to clone](clone.png) Note that there are 2 provided urls here, one for *ssh* and another for *https*. From the user's perspective, the difference between the two is minimal: ssh requires the user to type only a password when interacting with the remote github repository, while https requires both a username and password. -Now, you will probably be interacting with github a lot, so ssh will definitely save time and is preferred for many people who use git a lot; however, [there is some initial set-up](https://help.github.com/articles/connecting-to-github-with-ssh/). +Now, you will probably be interacting with github a lot, so ssh will definitely save time and is preferred for many people who use git a lot; however, [there is some initial set-up](https://help.github.com/articles/connecting-to-github-with-ssh/). If you want, we can discuss the set-up in more detail later (just let me know!), but for now, we'll stick with https because it's more familiar to new users. Once you have the url, there are 2 ways to proceed: @@ -95,7 +95,7 @@ For now, we will breifly describe each of the commands; however, we will definit So, here it is, step-by-step: 1. `mkdir algorithm_archive`: make a directory. We can call this directory anything, but we'll call it algorithm_archive for now. 2. `git init`: initialize git -3. `git remote add origin https://github.com/algorithm-archivists/algorithm-archive`: add a remote location (the github url we found just a second ago). Again, we can call this remote location anything, but `git clone` always calls it `origin`, so well stick with that. +3. `git remote add origin https://github.com/algorithm-archivists/algorithm-archive`: add a remote location (the github url we found just a second ago). Again, we can call this remote location anything, but `git clone` always calls it `origin`, so well stick with that. 4. `git fetch`: update the local directory with the information from the remote online repository 5. `git merge origin/master`: merge those updates. Right now, the `origin/master` part of this command might seem like a bit of black octocat magic, but we will cover it in just a bit! @@ -107,7 +107,7 @@ origin https://github.com/user/algorithm-archive.git (fetch) origin https://github.com/user/algorithm-archive.git (push) ``` -This provides information on different `remotes`. We'll talk about `fetch` and `push` a bit later. +This provides information on different `remotes`. We'll talk about `fetch` and `push` a bit later. Now, you might be asking yourself: If I am only connected to the url I forked earlier, what happens when the owner of the main code repository pushes changes? How will I update my code when this happens? Actually, you probably were not asking that question. It's not an obvious question to ask at all, but it's a useful question to move this tutorial forward. The solution is simple: Add another `remote` like so: @@ -144,23 +144,23 @@ git add CONTRIBUTORS.md Then if we type `git status` again, it will show that the file `CONTRIBUTORS.md` is in a *staging area* awaiting commit. This simply means that git is waiting to make sure there are no other changes we want to package up. -Now we create the `commit` by typing +Now we create the `commit` by typing ``` git commit -m "Adding name to contributors file" ``` -Note that if you do not use the `-m` message flag (just `git commit`), git will open your default editor (probably vi) to ask for a message. +Note that if you do not use the `-m` message flag (just `git commit`), git will open your default editor (probably vi) to ask for a message. *Every git commit needs a git message!* Make the messages count. -Be as descriptive as possible! +Be as descriptive as possible! If you want to see all commits that have ever been made on this repository, simply type ``` git log ``` -This will show you the history so far. As a side note, it also shows why good, clean commit messages are essential to managing large, open-source projects. -If there are hundreds (or thousands) of commits, and one of the features implemented somewhere down the line has a bug, clean commit messages allow us to find when that feature was implemented and possibly when the bug arose. +This will show you the history so far. As a side note, it also shows why good, clean commit messages are essential to managing large, open-source projects. +If there are hundreds (or thousands) of commits, and one of the features implemented somewhere down the line has a bug, clean commit messages allow us to find when that feature was implemented and possibly when the bug arose. Now let's say you want to checkout what the code looked like at a particular commit. To do this, we need to look at the generated unique string (SHA-1 checksum) associated with the commit we want and paste the first few (roughly 5) characters into the following command: @@ -169,11 +169,11 @@ git checkout CHARS ``` It's incredibly unlikely that any two commits will share the first *n* characters, so this is unique enough for git to identify which commit we were referring to and send us back there, but here's where the notation get's a little crazy! -See, when we are sent back in time to the chosen commit (with the above command), we will be in a *detached head* state. +See, when we are sent back in time to the chosen commit (with the above command), we will be in a *detached head* state. This refers to the term we use to describe the very latest commit, **HEAD**. If we wanted to checkout the previous commit (for example), we would use `git checkout HEAD~1`, the second-to-last commit would be `HEAD~2`, and so on and so-forth. -When we checkout another commit, we are rolling the head of our commitment snake back to what it was in the past. +When we checkout another commit, we are rolling the head of our commitment snake back to what it was in the past. In the detached head state, we shouldn't really do any development. It's more of a read-only type of thing; however, if we want to develop the code starting at that commit, we could use ``` @@ -185,16 +185,16 @@ But this requires a little explanation! ### Checkout these branches! -Now let's take a step to the side and talk about another fantastic git feature, *branches*. -At this point, we might have code forked under our own username on github. This means that there could be at least 2 functioning versions of the code we are working on: our own fork and the original owner's fork. +Now let's take a step to the side and talk about another fantastic git feature, *branches*. +At this point, we might have code forked under our own username on github. This means that there could be at least 2 functioning versions of the code we are working on: our own fork and the original owner's fork. That said, within each fork, there is the ability to have multiple lines of development, each one on a different *branch*. If you are new to software development, this might not seem too useful; however, imagine you are working on a large, open-source project that thousands of people use. -At some point, you might want to re-organize a bunch of features in the code. +At some point, you might want to re-organize a bunch of features in the code. As a developer, you might not be sure whether all the features you are re-organizing will still work properly after re-organizing them, but you know the code needs to be modified! -The problem is that you have users who may need the features you might accidentally break. +The problem is that you have users who may need the features you might accidentally break. For this reason, you might want to have a "master" branch -- one that is always working for the users, and a "development" branch -- one that is in the middle of creating new features for users. -In truth, there are dozens of reasons why developers might want to work on slightly different versions of the code. +In truth, there are dozens of reasons why developers might want to work on slightly different versions of the code. Rather than spending time outlining all the potential reasons, let's just dive into how branches are made and maintained. To check which branch you are on, simply type: @@ -210,7 +210,7 @@ To switch branches, use git checkout branch ``` -And this will change all of the files on your local directory to match the branch you have swapped to. +And this will change all of the files on your local directory to match the branch you have swapped to. Note that if you have local changes that will be overwritten when changing branches, git will note these changes and tell you to do something about them before switching to a new branch. If you want to get rid of the changes, you could delete any files that are causing conflicts; however, this is barbaric and should be avoided in civilized society. Another solution is to use a feature of git called the `stash`. @@ -227,25 +227,25 @@ git stash apply ``` Now, here's the problem: because `git stash` is so convenient, I tend to have the habit of stashing local changes quite often. This means that I have multiple modifications stored, all connected to different commits. -Quite frankly, it's a mess. That said, I can list out everything in my stash with +Quite frankly, it's a mess. That said, I can list out everything in my stash with ``` git stash list ``` -and apply whichever stash I want with +and apply whichever stash I want with ``` git apply stash@{i} ``` -Where `i` is the value of the stash item I want to apply. +Where `i` is the value of the stash item I want to apply. Now, to be clear: I am not encouraging anyone to use `git stash` to hide away local changes and make branch traversal easier; however, if you are about to delete files, maybe try `git stash` instead? -Finally, we need to talk about a super sticky part of git: *merging branches*. -Following from the story above, you might have code in a development branch. -When you are happy with the changes in the development branch, you might want to merge those changes back to the master branch. +Finally, we need to talk about a super sticky part of git: *merging branches*. +Following from the story above, you might have code in a development branch. +When you are happy with the changes in the development branch, you might want to merge those changes back to the master branch. Assuming that no one was developing on the master branch and that the development branch is ahead of the master branch, this can be done with the following: ``` @@ -253,11 +253,11 @@ git checkout master git merge branch ``` -This is the simplest case, but it's rarely this simple. Often times, there will be development on different branches and when we merge these brances together, there will be conflicts. +This is the simplest case, but it's rarely this simple. Often times, there will be development on different branches and when we merge these brances together, there will be conflicts. These conflicts are noted in each of the files that need to be modified like so ``` -I am writing about +I am writing about <<<<<<< HEAD things ======= @@ -277,7 +277,7 @@ Also: let me know if there's any tools you like, and I'll add them to this guide ### Interacting with github To this point, we have introduced the concept of `remote`s and how to set them up, but we have not discussed how to interact with them. -For the most part, there are only a few commands to keep in mind. the easiest one to explain is +For the most part, there are only a few commands to keep in mind. the easiest one to explain is ``` git push @@ -323,12 +323,12 @@ Now let's talk about something that will certainly happen in your programming ca ### Dealing with mistakes I cannot help with programming mistakes (typos and such), but when it comes to version control there are two times during which mistakes can be made: **before a commit** and **after a commit**. -Each of these have a different solution and have different repercussions depending on how you want to proceed with code development. -Note that these solutions can be quite complicated and may easily move beyond the scope of this text. +Each of these have a different solution and have different repercussions depending on how you want to proceed with code development. +Note that these solutions can be quite complicated and may easily move beyond the scope of this text. Because of this, I will link to appropriate documentation as necessary. -Firstly, let's talk about what happens when you make a mistake while your code is in the staging area, awaiting a commit. -Here, the solution is simple: +Firstly, let's talk about what happens when you make a mistake while your code is in the staging area, awaiting a commit. +Here, the solution is simple: ``` git reset @@ -337,7 +337,7 @@ git reset That's it. Don't overcomplicate it. You haven't committed to the code yet, so just unstage everything back to the `HEAD`. The problem is that this command is quite nuanced and has plenty of other uses. This goes beyong the scope of this text, but you can find more information here: [https://git-scm.com/blog](https://git-scm.com/blog). -Now, what if your mistake was found after committing? Well, that's a little more complicated. Your mistake is already in your `git log`. +Now, what if your mistake was found after committing? Well, that's a little more complicated. Your mistake is already in your `git log`. The easiest way to deal with this is to live with the mistake and make a new commit that fixes it later. One way to reverse the commit completely is with @@ -352,8 +352,8 @@ Assuming you are working with a small team and don't mind having a somewhat dirt git rebase ``` -the problem is that `git rebase` is complicated and could potentially destroy your codebase if it's used inappropriately. -Because of this, I often just live with my mistakes; however, in rare cases, having a clean `git log` is incredibly important. +the problem is that `git rebase` is complicated and could potentially destroy your codebase if it's used inappropriately. +Because of this, I often just live with my mistakes; however, in rare cases, having a clean `git log` is incredibly important. I am not a git magician (yet), so I will not delve into what is essentially black magic to me. Instead, I'll link a guide: [https://git-scm.com/book/en/v2/Git-Branching-Rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing). I know that this section is a little sparse and there's a lot I missed. @@ -361,9 +361,9 @@ If you want to provide more information, feel free to do so and submit it via pu ### Concepts we missed -Unfortunately, this discussion has a scope. It is not meant to give you a deep, meaningful understanding of git. +Unfortunately, this discussion has a scope. It is not meant to give you a deep, meaningful understanding of git. Instead, we focused on the basics, with the hope of encouraging our community to start collaborating together. The more you use git, the easier it will be to use in the future and the more it will start to make sense. -That said, due to the nature of this guide, there were a few things we missed, the two most important of which are **rebasing** and **merge conflicts**. +That said, due to the nature of this guide, there were a few things we missed, the two most important of which are **rebasing** and **merge conflicts**. In addition, I need to be honest in saying that I am not the most qualified person to teach anyone how to use git or version control and that there are plenty of good guides out there already, so if you have any guides that you like, please let me know and I can add them to the end of this guide for more information. diff --git a/chapters/sorting_searching/bogo/code/cs/BogoSort.cs b/chapters/sorting_searching/bogo/code/cs/BogoSort.cs index e533a6dc0..94a6fa8e4 100644 --- a/chapters/sorting_searching/bogo/code/cs/BogoSort.cs +++ b/chapters/sorting_searching/bogo/code/cs/BogoSort.cs @@ -10,7 +10,7 @@ public static List RunBogoSort(List list) where T : IComparable { while (!IsSorted(list)) list = Shuffle(list, new Random()); - + return list; } diff --git a/chapters/sorting_searching/bubble/code/cs/BubbleSort.cs b/chapters/sorting_searching/bubble/code/cs/BubbleSort.cs index c589711dd..be7531c61 100644 --- a/chapters/sorting_searching/bubble/code/cs/BubbleSort.cs +++ b/chapters/sorting_searching/bubble/code/cs/BubbleSort.cs @@ -9,7 +9,7 @@ public static class BubbleSort public static List RunBubbleSort(List list) where T : IComparable { var length = list.Count; - + for (int i = 0; i < length; i++) { for (int j = 1; j < length; j++) diff --git a/chapters/sorting_searching/bubble/code/python/bubblesort.py b/chapters/sorting_searching/bubble/code/python/bubblesort.py index e1bc22831..6125ecffb 100644 --- a/chapters/sorting_searching/bubble/code/python/bubblesort.py +++ b/chapters/sorting_searching/bubble/code/python/bubblesort.py @@ -1,6 +1,6 @@ #!usr/bin/python3 -#import section +#import section import random diff --git a/chapters/sorting_searching/sorting_searching.md b/chapters/sorting_searching/sorting_searching.md index 98ffe3af8..34f9542a2 100644 --- a/chapters/sorting_searching/sorting_searching.md +++ b/chapters/sorting_searching/sorting_searching.md @@ -13,7 +13,7 @@ Right now, there are only a few (straightforward) examples, so expect some more -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/taylor/taylor_series.md b/chapters/taylor/taylor_series.md index 796959db6..3ce4c81b0 100644 --- a/chapters/taylor/taylor_series.md +++ b/chapters/taylor/taylor_series.md @@ -13,7 +13,7 @@ where $$f(x)$$ is some function along real or complex space, $$a$$ is the point 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: $$ -f(x) \simeq f(a) + \frac{df(a)}{dx}(x-a) +f(x) \simeq f(a) + \frac{df(a)}{dx}(x-a) + \frac{1}{2}\frac{d^2f(a)}{dx^2}(x-a)^2 $$ @@ -29,7 +29,7 @@ $$ The Taylor series expansion turns into one of the most common formulas in classical physics, the *kinematic equation*! $$ -x(t) \simeq x_0 + v_0t +x(t) \simeq x_0 + v_0t + \frac{1}{2}at^2 $$ @@ -47,7 +47,7 @@ This shows the true power of the Taylor Series Expansion. It allows us to more e -$$ +$$ \newcommand{\d}{\mathrm{d}} \newcommand{\bff}{\boldsymbol{f}} \newcommand{\bfg}{\boldsymbol{g}} diff --git a/chapters/tree_traversal/code/cs/Tree/Tree.cs b/chapters/tree_traversal/code/cs/Tree/Tree.cs index f08905608..062db0e43 100644 --- a/chapters/tree_traversal/code/cs/Tree/Tree.cs +++ b/chapters/tree_traversal/code/cs/Tree/Tree.cs @@ -11,9 +11,9 @@ private class Node public List Children { get; set; } = new List(); public int Id { get; set; } } - + private Node root; - + public Tree(int depthCount, int childrenCount) { CreateTree(depthCount, childrenCount); @@ -27,7 +27,7 @@ public void CreateTree(int depthCount, int childrenCount) }; CreateAllChildren(root, depthCount, childrenCount); } - + public void StartDFSRecursive() { DFSRecursive(root); @@ -83,7 +83,7 @@ private void CreateAllChildren(Node node, int rowCount, int childrenCount) CreateAllChildren(node.Children[i], rowCount - 1, childrenCount); } } - + private void DFSRecursive(Node node) { Console.WriteLine(node.Id); diff --git a/chapters/tree_traversal/code/cs/TreeMdAdditional/TreeMdAdditional.cs b/chapters/tree_traversal/code/cs/TreeMdAdditional/TreeMdAdditional.cs index 1167b060d..745cbd79f 100644 --- a/chapters/tree_traversal/code/cs/TreeMdAdditional/TreeMdAdditional.cs +++ b/chapters/tree_traversal/code/cs/TreeMdAdditional/TreeMdAdditional.cs @@ -78,11 +78,11 @@ public void DFSRecursivePostorder(Node node) { DFSRecursivePostorder(c); } - + // Here we are doing something... Console.WriteLine(node.Id); } - + // This assumes only 2 children public void DFSRecursiveInorderBinary(Node node) { diff --git a/chapters/tree_traversal/code/javascript/Tree_example.js b/chapters/tree_traversal/code/javascript/Tree_example.js index 5e08cdd73..20301a16a 100644 --- a/chapters/tree_traversal/code/javascript/Tree_example.js +++ b/chapters/tree_traversal/code/javascript/Tree_example.js @@ -26,7 +26,7 @@ function DFS_stack(n){ var s = []; s.push(n); var temp; - + while(s.length > 0){ temp = s.pop(); console.log(temp.ID); @@ -43,7 +43,7 @@ function BFS_queue(n){ var q = []; q.push(n); var temp; - + while(q.length > 0){ temp = q.shift(); console.log(temp.ID); diff --git a/chapters/tree_traversal/code/python3/Tree_example.py b/chapters/tree_traversal/code/python3/Tree_example.py index d1b695039..1aec718d4 100644 --- a/chapters/tree_traversal/code/python3/Tree_example.py +++ b/chapters/tree_traversal/code/python3/Tree_example.py @@ -1,14 +1,14 @@ # Depth-First and Breadth-First Traversal -# Submitted by Matthew Giallourakis +# Submitted by Matthew Giallourakis from collections import deque - + class node(): "Create the node structure" def __init__(self, value, left, right): self.value = value self.left = left self.right = right - + def make_tree(root,nums): "Makes a binary search tree from a list of numbers" for num in nums: @@ -27,7 +27,7 @@ def make_tree(root,nums): break else: temp_node = temp_node.right - + def depth_first_search(root): "Traverses through a tree depth-first by putting nodes on a stack" stack = deque() @@ -43,8 +43,8 @@ def depth_first_search(root): if temp_node.left is not None: stack.append(temp_node.left) return result_list - - + + def breadth_first_search(root): "Traverses through a tree breadth-first by putting nodes into a queue" queue = deque() @@ -60,8 +60,8 @@ def breadth_first_search(root): if temp_node.right is not None: queue.appendleft(temp_node.right) return result_list - - + + def main(): nums = [5,8,6,9,2,1,3] root = node(value=nums.pop(0),left=None,right=None) @@ -70,15 +70,15 @@ def main(): # 5 # 2 8 # 1 3 6 9 - # - + # + print("Depth First:",depth_first_search(root)) # prints [5, 2, 1, 3, 8, 6, 9] - + print("Breadth First:",breadth_first_search(root)) # prints [5, 2, 8, 1, 3, 6, 9] - - + + if __name__ == '__main__': main() diff --git a/chapters/tree_traversal/code/rust/tree.rs b/chapters/tree_traversal/code/rust/tree.rs index 507bd6915..44d6dbcf6 100644 --- a/chapters/tree_traversal/code/rust/tree.rs +++ b/chapters/tree_traversal/code/rust/tree.rs @@ -37,7 +37,7 @@ fn create_tree(num_row: u64, num_child: u64) -> Node { if num_row == 0 { return Node { children: vec![], value: 0 }; } - + let children = (0..num_child) .map(|_| create_tree(num_row - 1, num_child)) .collect(); From 9483eb07b39ce2c9a52f84cf66cc4dae7473904f Mon Sep 17 00:00:00 2001 From: Marius Becker Date: Sat, 9 Jun 2018 12:07:41 +0200 Subject: [PATCH 2/8] Cleaned up C# source files Removed trailing whitespace, changed line endings from CRLF to LF and removed the UTF-8 BOM --- .../jarvis_march/code/cs/Program.cs | 66 ++++----- .../huffman/code/cs/Program.cs | 48 +++---- .../code/cs/GaleShapleyAlgorithm.cs | 2 +- .../stable_marriage/code/cs/ListExtensions.cs | 2 +- .../stable_marriage/code/cs/Person.cs | 2 +- .../stable_marriage/code/cs/Program.cs | 134 +++++++++--------- .../EuclideanAlgorithm/EuclideanAlgorithm.cs | 2 +- .../code/cs/EuclideanAlgorithm/Program.cs | 36 ++--- .../EuclideanAlgorithmMdAdditional.cs | 2 +- .../EuclideanAlgorithmMdAdditional/Program.cs | 36 ++--- .../bogo/code/cs/BogoSort.cs | 2 +- .../sorting_searching/bogo/code/cs/Program.cs | 48 +++---- .../bubble/code/cs/BubbleSort.cs | 2 +- .../bubble/code/cs/Program.cs | 48 +++---- .../tree_traversal/code/cs/Tree/Program.cs | 40 +++--- chapters/tree_traversal/code/cs/Tree/Tree.cs | 2 +- .../code/cs/TreeMdAdditional/Program.cs | 46 +++--- .../cs/TreeMdAdditional/TreeMdAdditional.cs | 2 +- 18 files changed, 260 insertions(+), 260 deletions(-) diff --git a/chapters/computational_geometry/gift_wrapping/jarvis_march/code/cs/Program.cs b/chapters/computational_geometry/gift_wrapping/jarvis_march/code/cs/Program.cs index d927b62bf..82ed6a04d 100644 --- a/chapters/computational_geometry/gift_wrapping/jarvis_march/code/cs/Program.cs +++ b/chapters/computational_geometry/gift_wrapping/jarvis_march/code/cs/Program.cs @@ -1,33 +1,33 @@ -// submitted by Julian Schacher (jspp) with great help by gustorn -using System; -using System.Collections.Generic; - -namespace JarvisMarch -{ - class Program - { - static void Main(string[] args) - { - System.Console.WriteLine("JarvisMarch"); - // Example list of points. - // The points are represented by vectors here, but that doesn't really matter. - var points = new List() - { - new Vector(1, 3), - new Vector(2, 4), - new Vector(4, 0), - new Vector(1, 0), - new Vector(0, 2), - new Vector(2, 2), - new Vector(3, 4), - new Vector(3, 1), - }; - var jarvisMarch = new JarvisMarch(); - var giftWrap = jarvisMarch.Run(points); - - // Print the points of the gift wrap. - foreach (var point in giftWrap) - System.Console.WriteLine($"{point.x}, {point.y}"); - } - } -} +// submitted by Julian Schacher (jspp) with great help by gustorn +using System; +using System.Collections.Generic; + +namespace JarvisMarch +{ + class Program + { + static void Main(string[] args) + { + System.Console.WriteLine("JarvisMarch"); + // Example list of points. + // The points are represented by vectors here, but that doesn't really matter. + var points = new List() + { + new Vector(1, 3), + new Vector(2, 4), + new Vector(4, 0), + new Vector(1, 0), + new Vector(0, 2), + new Vector(2, 2), + new Vector(3, 4), + new Vector(3, 1), + }; + var jarvisMarch = new JarvisMarch(); + var giftWrap = jarvisMarch.Run(points); + + // Print the points of the gift wrap. + foreach (var point in giftWrap) + System.Console.WriteLine($"{point.x}, {point.y}"); + } + } +} diff --git a/chapters/data_compression/huffman/code/cs/Program.cs b/chapters/data_compression/huffman/code/cs/Program.cs index a336507ad..dd7568d86 100644 --- a/chapters/data_compression/huffman/code/cs/Program.cs +++ b/chapters/data_compression/huffman/code/cs/Program.cs @@ -1,25 +1,25 @@ -// submitted by Julian Schacher (jspp), thanks to gustorn for the help -using System.Collections; -using System.Collections.Generic; - -namespace HuffmanCoding -{ - class Program - { - static void Main(string[] args) - { - var huffmanCoding = new HuffmanCoding(); - - var result = huffmanCoding.Encode("bibbity bobbity"); - // The bitStrings are just strings and provide no compression. Look in HuffmanCoding.cs for explanation. - // Print dictionary. - foreach (var entry in result.Dictionary) - System.Console.WriteLine($"{entry.Key} {entry.Value}"); - // Print BitString. - System.Console.WriteLine($"{result.BitString} count: {result.BitString.Length}"); - - var originalString = huffmanCoding.Decode(result); - System.Console.WriteLine(originalString); - } - } +// submitted by Julian Schacher (jspp), thanks to gustorn for the help +using System.Collections; +using System.Collections.Generic; + +namespace HuffmanCoding +{ + class Program + { + static void Main(string[] args) + { + var huffmanCoding = new HuffmanCoding(); + + var result = huffmanCoding.Encode("bibbity bobbity"); + // The bitStrings are just strings and provide no compression. Look in HuffmanCoding.cs for explanation. + // Print dictionary. + foreach (var entry in result.Dictionary) + System.Console.WriteLine($"{entry.Key} {entry.Value}"); + // Print BitString. + System.Console.WriteLine($"{result.BitString} count: {result.BitString.Length}"); + + var originalString = huffmanCoding.Decode(result); + System.Console.WriteLine(originalString); + } + } } \ No newline at end of file diff --git a/chapters/decision_problems/stable_marriage/code/cs/GaleShapleyAlgorithm.cs b/chapters/decision_problems/stable_marriage/code/cs/GaleShapleyAlgorithm.cs index e21309576..2e80369d3 100644 --- a/chapters/decision_problems/stable_marriage/code/cs/GaleShapleyAlgorithm.cs +++ b/chapters/decision_problems/stable_marriage/code/cs/GaleShapleyAlgorithm.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) with great help by gustorn and Marius Becker +// submitted by Julian Schacher (jspp) with great help by gustorn and Marius Becker using System.Collections.Generic; namespace StableMarriageProblem diff --git a/chapters/decision_problems/stable_marriage/code/cs/ListExtensions.cs b/chapters/decision_problems/stable_marriage/code/cs/ListExtensions.cs index 812a0a836..9eee222eb 100644 --- a/chapters/decision_problems/stable_marriage/code/cs/ListExtensions.cs +++ b/chapters/decision_problems/stable_marriage/code/cs/ListExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace StableMarriageProblem diff --git a/chapters/decision_problems/stable_marriage/code/cs/Person.cs b/chapters/decision_problems/stable_marriage/code/cs/Person.cs index c266a8159..de63f2399 100644 --- a/chapters/decision_problems/stable_marriage/code/cs/Person.cs +++ b/chapters/decision_problems/stable_marriage/code/cs/Person.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) with great help by gustorn and Marius Becker +// submitted by Julian Schacher (jspp) with great help by gustorn and Marius Becker using System.Collections.Generic; namespace StableMarriageProblem diff --git a/chapters/decision_problems/stable_marriage/code/cs/Program.cs b/chapters/decision_problems/stable_marriage/code/cs/Program.cs index 606dd6c0c..e5c238be8 100644 --- a/chapters/decision_problems/stable_marriage/code/cs/Program.cs +++ b/chapters/decision_problems/stable_marriage/code/cs/Program.cs @@ -1,67 +1,67 @@ -// submitted by Julian Schacher (jspp) with great help by gustorn and Marius Becker -using System; -using System.Collections.Generic; - -namespace StableMarriageProblem -{ - class Program - { - static void Main(string[] args) - { - Console.WriteLine("GaleShapleyAlgorithm"); - // Using men and women as an example. - var men = new List() - { - new Man("A"), - new Man("B"), - new Man("C"), - new Man("D"), - new Man("E") - }; - var women = new List() - { - new Woman("F"), - new Woman("G"), - new Woman("H"), - new Woman("I"), - new Woman("J"), - }; - - var random = new Random(); - - foreach (var man in men) - { - man.Choices = new List(women).Shuffle(random); - Console.WriteLine(man.Name + ":"); - foreach (var choice in man.Choices) - Console.Write(choice.Name); - Console.WriteLine(); - } - foreach (var woman in women) - { - woman.Choices = new List(men).Shuffle(random); - Console.WriteLine(woman.Name + ":"); - foreach (var choice in woman.Choices) - Console.Write(choice.Name); - Console.WriteLine(); - } - - GaleShapleyAlgorithm.RunGaleShapleyAlgorithm(women, men); - - foreach (var woman in women) - { - Console.WriteLine(woman.Name + " : " + woman?.Partner.Name); - } - } - } - - public class Man : Person - { - public Man(string name) : base(name) { } - } - - public class Woman : Person - { - public Woman(string name) : base(name) { } - } -} +// submitted by Julian Schacher (jspp) with great help by gustorn and Marius Becker +using System; +using System.Collections.Generic; + +namespace StableMarriageProblem +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("GaleShapleyAlgorithm"); + // Using men and women as an example. + var men = new List() + { + new Man("A"), + new Man("B"), + new Man("C"), + new Man("D"), + new Man("E") + }; + var women = new List() + { + new Woman("F"), + new Woman("G"), + new Woman("H"), + new Woman("I"), + new Woman("J"), + }; + + var random = new Random(); + + foreach (var man in men) + { + man.Choices = new List(women).Shuffle(random); + Console.WriteLine(man.Name + ":"); + foreach (var choice in man.Choices) + Console.Write(choice.Name); + Console.WriteLine(); + } + foreach (var woman in women) + { + woman.Choices = new List(men).Shuffle(random); + Console.WriteLine(woman.Name + ":"); + foreach (var choice in woman.Choices) + Console.Write(choice.Name); + Console.WriteLine(); + } + + GaleShapleyAlgorithm.RunGaleShapleyAlgorithm(women, men); + + foreach (var woman in women) + { + Console.WriteLine(woman.Name + " : " + woman?.Partner.Name); + } + } + } + + public class Man : Person + { + public Man(string name) : base(name) { } + } + + public class Woman : Person + { + public Woman(string name) : base(name) { } + } +} diff --git a/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithm/EuclideanAlgorithm.cs b/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithm/EuclideanAlgorithm.cs index f91d98f04..605ee91c8 100644 --- a/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithm/EuclideanAlgorithm.cs +++ b/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithm/EuclideanAlgorithm.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) +// submitted by Julian Schacher (jspp) using System; namespace EuclideanAlgorithm diff --git a/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithm/Program.cs b/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithm/Program.cs index dd612181c..f88f4eaf6 100644 --- a/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithm/Program.cs +++ b/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithm/Program.cs @@ -1,18 +1,18 @@ -// submitted by Julian Schacher (jspp) -using System; - -namespace EuclideanAlgorithm -{ - class Program - { - static void Main(string[] args) - { - Console.WriteLine("EuclideanAlgorithm"); - int check = EuclideanAlgorithm.EuclidMod(64 * 67, 64 * 81); - int check2 = EuclideanAlgorithm.EuclidSub(128 * 12, 128 * 77); - - Console.WriteLine(check); - Console.WriteLine(check2); - } - } -} +// submitted by Julian Schacher (jspp) +using System; + +namespace EuclideanAlgorithm +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("EuclideanAlgorithm"); + int check = EuclideanAlgorithm.EuclidMod(64 * 67, 64 * 81); + int check2 = EuclideanAlgorithm.EuclidSub(128 * 12, 128 * 77); + + Console.WriteLine(check); + Console.WriteLine(check2); + } + } +} diff --git a/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithmMdAdditional/EuclideanAlgorithmMdAdditional.cs b/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithmMdAdditional/EuclideanAlgorithmMdAdditional.cs index eb033e566..a33ffbd12 100644 --- a/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithmMdAdditional/EuclideanAlgorithmMdAdditional.cs +++ b/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithmMdAdditional/EuclideanAlgorithmMdAdditional.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) +// submitted by Julian Schacher (jspp) namespace EuclideanAlgorithmMdAdditional { public class EuclideanAlgorithmMdAdditional diff --git a/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithmMdAdditional/Program.cs b/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithmMdAdditional/Program.cs index 2257445b1..6254361a9 100644 --- a/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithmMdAdditional/Program.cs +++ b/chapters/euclidean_algorithm/code/cs/EuclideanAlgorithmMdAdditional/Program.cs @@ -1,18 +1,18 @@ -// submitted by Julian Schacher (jspp) -using System; - -namespace EuclideanAlgorithmMdAdditional -{ - class Program - { - static void Main(string[] args) - { - Console.WriteLine("EuclideanAlgorithmMdAdditional"); - int checkMdAdditional = EuclideanAlgorithmMdAdditional.EuclidMod(64 * 67, 64 * 81); - int checkMdAdditional2 = EuclideanAlgorithmMdAdditional.EuclidSub(128 * 12, 128 * 77); - - Console.WriteLine(checkMdAdditional); - Console.WriteLine(checkMdAdditional2); - } - } -} +// submitted by Julian Schacher (jspp) +using System; + +namespace EuclideanAlgorithmMdAdditional +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("EuclideanAlgorithmMdAdditional"); + int checkMdAdditional = EuclideanAlgorithmMdAdditional.EuclidMod(64 * 67, 64 * 81); + int checkMdAdditional2 = EuclideanAlgorithmMdAdditional.EuclidSub(128 * 12, 128 * 77); + + Console.WriteLine(checkMdAdditional); + Console.WriteLine(checkMdAdditional2); + } + } +} diff --git a/chapters/sorting_searching/bogo/code/cs/BogoSort.cs b/chapters/sorting_searching/bogo/code/cs/BogoSort.cs index 94a6fa8e4..3d5e981c3 100644 --- a/chapters/sorting_searching/bogo/code/cs/BogoSort.cs +++ b/chapters/sorting_searching/bogo/code/cs/BogoSort.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) +// submitted by Julian Schacher (jspp) using System; using System.Collections.Generic; diff --git a/chapters/sorting_searching/bogo/code/cs/Program.cs b/chapters/sorting_searching/bogo/code/cs/Program.cs index 45b1020e9..66cc135e6 100644 --- a/chapters/sorting_searching/bogo/code/cs/Program.cs +++ b/chapters/sorting_searching/bogo/code/cs/Program.cs @@ -1,24 +1,24 @@ -// submitted by Julian Schacher (jspp) -using System; -using System.Collections.Generic; - -namespace BogoSort -{ - class Program - { - static void Main(string[] args) - { - Console.WriteLine("BogoSort"); - var listBogo = new List() { 1, 2, 6, 4, 9, 54, 3, 2, 7, 15 }; - Console.Write("unsorted: "); - foreach (var number in listBogo) - Console.Write(number + " "); - Console.WriteLine(); - listBogo = BogoSort.RunBogoSort(listBogo); - Console.Write("sorted: "); - foreach (var number in listBogo) - Console.Write(number + " "); - Console.WriteLine(); - } - } -} +// submitted by Julian Schacher (jspp) +using System; +using System.Collections.Generic; + +namespace BogoSort +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("BogoSort"); + var listBogo = new List() { 1, 2, 6, 4, 9, 54, 3, 2, 7, 15 }; + Console.Write("unsorted: "); + foreach (var number in listBogo) + Console.Write(number + " "); + Console.WriteLine(); + listBogo = BogoSort.RunBogoSort(listBogo); + Console.Write("sorted: "); + foreach (var number in listBogo) + Console.Write(number + " "); + Console.WriteLine(); + } + } +} diff --git a/chapters/sorting_searching/bubble/code/cs/BubbleSort.cs b/chapters/sorting_searching/bubble/code/cs/BubbleSort.cs index be7531c61..244397b40 100644 --- a/chapters/sorting_searching/bubble/code/cs/BubbleSort.cs +++ b/chapters/sorting_searching/bubble/code/cs/BubbleSort.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) +// submitted by Julian Schacher (jspp) using System; using System.Collections.Generic; diff --git a/chapters/sorting_searching/bubble/code/cs/Program.cs b/chapters/sorting_searching/bubble/code/cs/Program.cs index 71aa7b9a2..19fbc94a6 100644 --- a/chapters/sorting_searching/bubble/code/cs/Program.cs +++ b/chapters/sorting_searching/bubble/code/cs/Program.cs @@ -1,24 +1,24 @@ -// submitted by Julian Schacher (jspp) -using System; -using System.Collections.Generic; - -namespace BubbleSort -{ - class Program - { - static void Main(string[] args) - { - Console.WriteLine("BubbleSort"); - var listBubble = new List() { 1, 2, 6, 4, 9, 54, 3, 2, 7, 15 }; - Console.Write("unsorted: "); - foreach (var number in listBubble) - Console.Write(number + " "); - Console.WriteLine(); - listBubble = BubbleSort.RunBubbleSort(listBubble); - Console.Write("sorted: "); - foreach (var number in listBubble) - Console.Write(number + " "); - Console.WriteLine(); - } - } -} +// submitted by Julian Schacher (jspp) +using System; +using System.Collections.Generic; + +namespace BubbleSort +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("BubbleSort"); + var listBubble = new List() { 1, 2, 6, 4, 9, 54, 3, 2, 7, 15 }; + Console.Write("unsorted: "); + foreach (var number in listBubble) + Console.Write(number + " "); + Console.WriteLine(); + listBubble = BubbleSort.RunBubbleSort(listBubble); + Console.Write("sorted: "); + foreach (var number in listBubble) + Console.Write(number + " "); + Console.WriteLine(); + } + } +} diff --git a/chapters/tree_traversal/code/cs/Tree/Program.cs b/chapters/tree_traversal/code/cs/Tree/Program.cs index 98e978c90..3f9569381 100644 --- a/chapters/tree_traversal/code/cs/Tree/Program.cs +++ b/chapters/tree_traversal/code/cs/Tree/Program.cs @@ -1,20 +1,20 @@ -// submitted by Julian Schacher (jspp) -using System; - -namespace TreeTraversal -{ - class Program - { - static void Main(string[] args) - { - Console.WriteLine("TreeTraversal"); - var tree = new Tree(3, 3); - Console.WriteLine("StartDFSRecursive:"); - tree.StartDFSRecursive(); - Console.WriteLine("DFSStack:"); - tree.DFSStack(); - Console.WriteLine("DFSQueue:"); - tree.BFSQueue(); - } - } -} +// submitted by Julian Schacher (jspp) +using System; + +namespace TreeTraversal +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("TreeTraversal"); + var tree = new Tree(3, 3); + Console.WriteLine("StartDFSRecursive:"); + tree.StartDFSRecursive(); + Console.WriteLine("DFSStack:"); + tree.DFSStack(); + Console.WriteLine("DFSQueue:"); + tree.BFSQueue(); + } + } +} diff --git a/chapters/tree_traversal/code/cs/Tree/Tree.cs b/chapters/tree_traversal/code/cs/Tree/Tree.cs index 062db0e43..0c8bd2851 100644 --- a/chapters/tree_traversal/code/cs/Tree/Tree.cs +++ b/chapters/tree_traversal/code/cs/Tree/Tree.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) +// submitted by Julian Schacher (jspp) using System; using System.Collections.Generic; diff --git a/chapters/tree_traversal/code/cs/TreeMdAdditional/Program.cs b/chapters/tree_traversal/code/cs/TreeMdAdditional/Program.cs index f23c2b84e..7e621aa4b 100644 --- a/chapters/tree_traversal/code/cs/TreeMdAdditional/Program.cs +++ b/chapters/tree_traversal/code/cs/TreeMdAdditional/Program.cs @@ -1,23 +1,23 @@ -// submitted by Julian Schacher (jspp) -using System; - -namespace TreeTraversalMdAdditional -{ - class Program - { - static void Main(string[] args) - { - Console.WriteLine("TreeTraversalMdAdditional"); - var treeMdAdditional = new TreeMdAdditional(3, 3); - Console.WriteLine("StartDFSRecursive"); - treeMdAdditional.StartDFSRecursive(); - Console.WriteLine("StartDFSRecursivePostorder"); - treeMdAdditional.StartDFSRecursivePostorder(); - // Console.WriteLine("StartDFSRecursiveInorder (fail)"); - // treeMdAdditional.StartDFSRecursiveInorderBinary(); - treeMdAdditional = new TreeMdAdditional(3, 2); - Console.WriteLine("StartDFSRecursiveInorder (succeed)"); - treeMdAdditional.StartDFSRecursiveInorderBinary(); - } - } -} +// submitted by Julian Schacher (jspp) +using System; + +namespace TreeTraversalMdAdditional +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("TreeTraversalMdAdditional"); + var treeMdAdditional = new TreeMdAdditional(3, 3); + Console.WriteLine("StartDFSRecursive"); + treeMdAdditional.StartDFSRecursive(); + Console.WriteLine("StartDFSRecursivePostorder"); + treeMdAdditional.StartDFSRecursivePostorder(); + // Console.WriteLine("StartDFSRecursiveInorder (fail)"); + // treeMdAdditional.StartDFSRecursiveInorderBinary(); + treeMdAdditional = new TreeMdAdditional(3, 2); + Console.WriteLine("StartDFSRecursiveInorder (succeed)"); + treeMdAdditional.StartDFSRecursiveInorderBinary(); + } + } +} diff --git a/chapters/tree_traversal/code/cs/TreeMdAdditional/TreeMdAdditional.cs b/chapters/tree_traversal/code/cs/TreeMdAdditional/TreeMdAdditional.cs index 745cbd79f..022905cda 100644 --- a/chapters/tree_traversal/code/cs/TreeMdAdditional/TreeMdAdditional.cs +++ b/chapters/tree_traversal/code/cs/TreeMdAdditional/TreeMdAdditional.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) +// submitted by Julian Schacher (jspp) using System; using System.Collections.Generic; From 2a3b70fab3f301abb6fc5da209c36160941002fa Mon Sep 17 00:00:00 2001 From: Marius Becker Date: Sat, 9 Jun 2018 12:12:11 +0200 Subject: [PATCH 3/8] Added a .gitattributes file C# source files are now forced to have LF line endings --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..eeb87cc0a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Force C# source files to have LF line endings +*.cs text eol=lf From acbf3f3a0a8857bb70becb8ec2c70e1f436471db Mon Sep 17 00:00:00 2001 From: Marius Becker Date: Sat, 9 Jun 2018 12:13:23 +0200 Subject: [PATCH 4/8] EditorConfig rule to cover all text files --- .editorconfig | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.editorconfig b/.editorconfig index ac5bb0dd5..d7e312b12 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,12 +1,7 @@ root = true -# This file -[.editorconfig] -trim_trailing_whitespace = true -insert_final_newline = true - -# Pretty much everything should trim whitespace and have a final EOL -[*.{c,clj,cpp,cs,css,elm,go,hs,html,jl,js,md,py,rs}] +# Base for all text files +[*] trim_trailing_whitespace = true insert_final_newline = true From d2b389b847912d69eaa5646e83547e7f3148a253 Mon Sep 17 00:00:00 2001 From: Marius Becker Date: Sat, 9 Jun 2018 20:20:36 +0200 Subject: [PATCH 5/8] Added more file types to .gitattributes --- .gitattributes | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index eeb87cc0a..4a3475274 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,18 @@ -# Force C# source files to have LF line endings +# Force all text files to have LF line endings +*.c text eol=lf +*.clj text eol=lf +*.cpp text eol=lf *.cs text eol=lf +*.css text eol=lf +*.elm text eol=lf +*.go text eol=lf +*.hs text eol=lf +*.html text eol=lf +*.jl text eol=lf +*.js text eol=lf +*.md text eol=lf +*.py text eol=lf +*.rs text eol=lf + +# Assume that dotfiles are always text files +.* text eol=lf From f8faaa6903b4b6139f6b7869229686bc282f830f Mon Sep 17 00:00:00 2001 From: Marius Becker Date: Sat, 9 Jun 2018 20:22:00 +0200 Subject: [PATCH 6/8] Cleaned up OCAML source files And also added them to .gitattributes and .editorconfig --- .editorconfig | 5 + .gitattributes | 1 + chapters/tree_traversal/code/ocaml/tree.ml | 148 ++++++++++----------- 3 files changed, 80 insertions(+), 74 deletions(-) diff --git a/.editorconfig b/.editorconfig index d7e312b12..02c8ee206 100644 --- a/.editorconfig +++ b/.editorconfig @@ -64,6 +64,11 @@ indent_size = 2 indent_style = space indent_size = 2 +# OCAML +[*.ml] +indent_style = space +indent_size = 2 + # Python [*.py] indent_style = space diff --git a/.gitattributes b/.gitattributes index 4a3475274..78c6b9a37 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11,6 +11,7 @@ *.jl text eol=lf *.js text eol=lf *.md text eol=lf +*.ml text eol=lf *.py text eol=lf *.rs text eol=lf diff --git a/chapters/tree_traversal/code/ocaml/tree.ml b/chapters/tree_traversal/code/ocaml/tree.ml index ae764cc1a..8ad7f617f 100644 --- a/chapters/tree_traversal/code/ocaml/tree.ml +++ b/chapters/tree_traversal/code/ocaml/tree.ml @@ -1,74 +1,74 @@ -(* submitted by Nicole Mazzuca (ubsan) *) -module Tree : sig - type t - - val leaf : int -> t - - val with_child : t -> t -> t - - val dfs_recursive : t -> unit - - val dfs_stack : t -> unit - - val bfs_queue : t -> unit -end = struct - type t = {children: t list; value: int} - - let leaf value = {children= []; value} - - let with_child {children; value} child = {children= child :: children; value} - - (* recursive is by far the easiest to do in functional langs *) - let rec dfs_recursive self = - Printf.printf "%d\n" self.value ; - List.iter dfs_recursive self.children - - - let dfs_stack self = - let rec helper = function - | [] -> () - | x :: xs -> - Printf.printf "%d\n" x.value ; - helper (x.children @ xs) - in - helper [self] - - - let bfs_queue self = - let rec push_all queue = function - | x :: xs -> Queue.add x queue ; push_all queue xs - | [] -> () - in - let queue = Queue.create () in - Queue.add self queue ; - while not (Queue.is_empty queue) do - let x = Queue.take queue in - Printf.printf "%d\n" x.value ; - push_all queue x.children - done -end - -let rec build_tree num_row num_child = - let tree = Tree.leaf num_row in - match num_row with - | 0 -> tree - | n -> - let child = build_tree (num_row - 1) num_child in - let rec helper child tree = function - | 0 -> tree - | n -> Tree.with_child (helper child tree (n - 1)) child - in - helper child tree num_child - - -let main () = - let tree = build_tree 3 3 in - print_endline "--- dfs_recursive ---" ; - Tree.dfs_recursive tree ; - print_endline "--- dfs_stack ---" ; - Tree.dfs_stack tree ; - print_endline "--- bfs_queue ---" ; - Tree.bfs_queue tree - - -let () = main () +(* submitted by Nicole Mazzuca (ubsan) *) +module Tree : sig + type t + + val leaf : int -> t + + val with_child : t -> t -> t + + val dfs_recursive : t -> unit + + val dfs_stack : t -> unit + + val bfs_queue : t -> unit +end = struct + type t = {children: t list; value: int} + + let leaf value = {children= []; value} + + let with_child {children; value} child = {children= child :: children; value} + + (* recursive is by far the easiest to do in functional langs *) + let rec dfs_recursive self = + Printf.printf "%d\n" self.value ; + List.iter dfs_recursive self.children + + + let dfs_stack self = + let rec helper = function + | [] -> () + | x :: xs -> + Printf.printf "%d\n" x.value ; + helper (x.children @ xs) + in + helper [self] + + + let bfs_queue self = + let rec push_all queue = function + | x :: xs -> Queue.add x queue ; push_all queue xs + | [] -> () + in + let queue = Queue.create () in + Queue.add self queue ; + while not (Queue.is_empty queue) do + let x = Queue.take queue in + Printf.printf "%d\n" x.value ; + push_all queue x.children + done +end + +let rec build_tree num_row num_child = + let tree = Tree.leaf num_row in + match num_row with + | 0 -> tree + | n -> + let child = build_tree (num_row - 1) num_child in + let rec helper child tree = function + | 0 -> tree + | n -> Tree.with_child (helper child tree (n - 1)) child + in + helper child tree num_child + + +let main () = + let tree = build_tree 3 3 in + print_endline "--- dfs_recursive ---" ; + Tree.dfs_recursive tree ; + print_endline "--- dfs_stack ---" ; + Tree.dfs_stack tree ; + print_endline "--- bfs_queue ---" ; + Tree.bfs_queue tree + + +let () = main () From 0c2809fc98a122ae198331a0a9ce43d98e870271 Mon Sep 17 00:00:00 2001 From: Marius Becker Date: Sat, 9 Jun 2018 20:29:36 +0200 Subject: [PATCH 7/8] Added end_of_line = lf to .editorconfig --- .editorconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/.editorconfig b/.editorconfig index 02c8ee206..07f00c615 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,6 +4,7 @@ root = true [*] trim_trailing_whitespace = true insert_final_newline = true +end_of_line = lf # C [*.c] From 523a94e57c6d2133c47efe2d561cee4d9a7a1d9b Mon Sep 17 00:00:00 2001 From: Marius Becker Date: Sat, 9 Jun 2018 20:42:24 +0200 Subject: [PATCH 8/8] Made .gitattributes way simpler --- .gitattributes | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/.gitattributes b/.gitattributes index 78c6b9a37..3230ab7ec 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,19 +1,2 @@ # Force all text files to have LF line endings -*.c text eol=lf -*.clj text eol=lf -*.cpp text eol=lf -*.cs text eol=lf -*.css text eol=lf -*.elm text eol=lf -*.go text eol=lf -*.hs text eol=lf -*.html text eol=lf -*.jl text eol=lf -*.js text eol=lf -*.md text eol=lf -*.ml text eol=lf -*.py text eol=lf -*.rs text eol=lf - -# Assume that dotfiles are always text files -.* text eol=lf +* text=auto eol=lf