diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 000000000..352dcca68
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,24 @@
+// For format details, see https://aka.ms/devcontainer.json.
+{
+ "name": "Arcane Algorithm Archive All Languages",
+
+ // Comment out 'image' and uncomment 'build' to test changes to the dockerfile locally
+ "image": "ghcr.io/algorithm-archivists/aaa-langs:latest",
+ // "build": {\
+ // // For config options, see the README at:https://github.com/microsoft/vscode-dev-containers/tree/v0.187.0/containers/ubuntu
+ // "dockerfile": "../Dockerfile",
+ // // Update 'VARIANT' to pick an Ubuntu version: focal, bionic
+ // "args": { "VARIANT": "focal" }
+ // },
+
+ // Set *default* container specific settings.json values on container create.
+ "settings": {},
+
+ // Add the IDs of extensions you want installed when the container is created.
+ "extensions": [],
+
+ // Use 'forwardPorts' to make a list of ports inside the container available locally (outside the container).
+ // Port : Usage
+ // 4000 : Honkit serves by default on this port
+ "forwardPorts": [4000]
+}
diff --git a/.editorconfig b/.editorconfig
index 4ea5e2ea9..a3fbd6e02 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -172,3 +172,6 @@ indent_size = 4
indent_style = space
indent_size = 2
+[*.coco]
+indent_style = space
+indent_size = 4
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9c6e68b99..cd2038090 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,11 +2,17 @@ name: build
on: pull_request
jobs:
- build-and-deploy:
+ build:
runs-on: ubuntu-latest
+ container:
+ options: --entrypoint /bin/bash --user 0
+ image: ghcr.io/algorithm-archivists/aaa-langs:latest
+ defaults:
+ run:
+ shell: bash --rcfile /root/.bashrc -eo pipefail {0}
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
persist-credentials: false
@@ -14,3 +20,10 @@ jobs:
run: |
npm install
npx honkit build
+
+ - name: Initalize cargo and run SCons
+ env:
+ HOME: /root
+ run: |
+ . "$HOME/.cargo/env"
+ scons -Q --random -j2
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 361978a7a..e07b1fade 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -2,7 +2,7 @@ name: Build and Deploy
on:
push:
branches:
- - master
+ - main
jobs:
build-and-deploy:
diff --git a/.github/workflows/issue_comment.yml b/.github/workflows/issue_comment.yml
new file mode 100644
index 000000000..e7d87c53d
--- /dev/null
+++ b/.github/workflows/issue_comment.yml
@@ -0,0 +1,19 @@
+name: Add Label with Comment
+
+on: [issue_comment]
+
+jobs:
+ create_comment:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions-ecosystem/action-regex-match@v2
+ id: regex-match
+ with:
+ text: ${{ github.event.comment.body }}
+ regex: '\[lang:\s*(.*?)\s*\]'
+
+ - uses: actions-ecosystem/action-add-labels@v1
+ if: ${{ steps.regex-match.outputs.match != '' }}
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ labels: "lang: ${{ steps.regex-match.outputs.group1 }}"
diff --git a/.github/workflows/publish_container.yml b/.github/workflows/publish_container.yml
new file mode 100644
index 000000000..e49663542
--- /dev/null
+++ b/.github/workflows/publish_container.yml
@@ -0,0 +1,18 @@
+name: Publish Docker
+on:
+ push:
+ branches:
+ - main
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ if: github.repository == 'algorithm-archivists/algorithm-archive'
+ steps:
+ - uses: actions/checkout@master
+ - name: Publish to Registry
+ uses: elgohr/Publish-Docker-Github-Action@v5
+ with:
+ name: algorithm-archivists/aaa-langs
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ registry: ghcr.io
diff --git a/.gitignore b/.gitignore
index db26e0ad0..08c567100 100644
--- a/.gitignore
+++ b/.gitignore
@@ -478,7 +478,7 @@ paket-files/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
-
+*.ipynb_checkpoints*
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
@@ -517,3 +517,21 @@ vscode/
# aspell
*.bak
+
+# SCons intermidiate files
+.sconsign.dblite
+*.o
+
+# SCons build directory
+build/
+
+# Cargo artifacts
+Cargo.lock
+target/
+
+*.out
+*.class
+
+# OCaml compilation files
+*.cmi
+*.cmx
diff --git a/.nojekyll b/.nojekyll
new file mode 100644
index 000000000..e69de29bb
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index b497e39e2..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-dist: trusty
-sudo: false
-
-language: node_js
-node_js:
- - "12"
-
-before_script:
- - export BOOK_BUILD_DIR="${TRAVIS_BUILD_DIR}"/_book
- - env | sort
-
-script:
- - npm run build
- # Make sure the book built.
- - |
- book_check_file="${BOOK_BUILD_DIR}/index.html"
- if [[ ! -f "${book_check_file}" ]]; then
- echo "${book_check_file} not found"
- exit 1
- fi
-
-after_success:
- - |
- if [[ "${TRAVIS_BRANCH}" == master && "${TRAVIS_PULL_REQUEST}" == false ]]; then
- # Commits to master that are not pull requests, that is, only
- # actual addition of code to master, should deploy the book to
- # the site.
- bash "${TRAVIS_BUILD_DIR}"/tools/deploy/update_site_travis.bash
- fi
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 29d9e8e09..15c319751 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -51,8 +51,17 @@ This file lists everyone, who contributed to this repo and wanted to show up her
- Vincent Zalzal
- Jonathan D B Van Schenck
- James Goytia
-- Amaras
+- Sammy Plat
- Jonathan Dönszelmann
- Ishaan Verma
- Delphi1024
- ntindle
+- Mahdi Sarikhani
+- Ridham177
+- Hugo Salou
+- Dimitri Belopopsky
+- Henrik Abel Christensen
+- K. Shudipto Amin
+- Peanutbutter_Warrior
+- Thijs Raymakers
+- Michael Ciccotosto-Camp
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 000000000..7e8a3826a
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,112 @@
+# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.187.0/containers/ubuntu/.devcontainer/base.Dockerfile
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+# [Choice] Ubuntu version: bionic, focal
+ARG VARIANT="focal"
+FROM mcr.microsoft.com/vscode/devcontainers/base:0-${VARIANT}
+
+RUN apt-get update \
+ && apt-get -y install --no-install-recommends build-essential software-properties-common xz-utils g++ sbcl julia python3 python3-pip python3-dev ghc openjdk-11-jdk libssl-dev gfortran libxml2-dev libyaml-dev libgmp-dev libz-dev libncurses5 gnuplot nodejs npm lua5.3 ocaml php ruby-full gnu-smalltalk scratch libfftw3-dev cmake mono-devel
+
+# Setup Crystal
+RUN echo 'deb http://download.opensuse.org/repositories/devel:/languages:/crystal/xUbuntu_20.04/ /' | sudo tee /etc/apt/sources.list.d/devel:languages:crystal.list
+RUN curl -fsSL https://download.opensuse.org/repositories/devel:languages:crystal/xUbuntu_20.04/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/devel_languages_crystal.gpg > /dev/null
+
+# Setup Dart
+RUN sudo sh -c 'wget -qO- https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
+RUN sudo sh -c 'wget -qO- https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list'
+
+# Setup Powershell
+RUN sudo sh -c 'wget -q https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb'
+RUN sudo sh -c 'dpkg -i packages-microsoft-prod.deb'
+
+# Setup Clojure
+RUN sudo sh -c 'curl -O https://download.clojure.org/install/linux-install-1.10.3.967.sh'
+RUN sudo sh -c 'chmod +x linux-install-1.10.3.967.sh'
+RUN sudo sh -c 'sudo ./linux-install-1.10.3.967.sh'
+
+# Setup dotnet
+RUN sudo sh -c 'wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb'
+RUN sudo sh -c 'sudo dpkg -i packages-microsoft-prod.deb'
+RUN sudo sh -c 'rm packages-microsoft-prod.deb'
+
+# Setup D Lang
+ENV DLANG_VERSION=2.097.2
+RUN mkdir -p ~/dlang && wget https://dlang.org/install.sh -O ~/dlang/install.sh
+RUN bash ~/dlang/install.sh dmd-$DLANG_VERSION
+ENV PATH=$PATH:~/dlang/dmd-$DLANG_VERSION/linux/bin64/
+
+# Setup Go
+RUN sudo sh -c 'wget -c https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz -O - | sudo tar -xz -C /usr/local'
+ENV PATH=$PATH:/usr/local/go/bin
+
+# Setup Kotlin
+RUN mkdir -p ~/kotlin && wget -c https://github.com/JetBrains/kotlin/releases/download/v1.5.30/kotlin-compiler-1.5.30.zip -O ~/kotlin/kotlinc.zip && cd ~/kotlin && unzip kotlinc.zip
+ENV PATH=$PATH:~/kotlin/kotlinc/bin
+
+# Setup lolcode
+RUN git clone https://github.com/justinmeza/lci.git ~/lolcode && cd ~/lolcode && mkdir build && cd build && cmake .. && make -B
+ENV PATH=$PATH:~/lolcode/build
+
+# Setup Piet
+RUN python3 -m pip install --no-cache-dir repiet
+
+# Setup Matlab
+# ?????? This is a licensed language???
+
+# Setup Emojicode
+RUN mkdir -p ~/emojicode && wget -c https://github.com/emojicode/emojicode/releases/download/v1.0-beta.2/Emojicode-1.0-beta.2-Linux-x86_64.tar.gz -O ~/emojicode/emojicode.tar.gz && \
+ tar -xzf ~/emojicode/emojicode.tar.gz -C ~/emojicode --strip-components=1
+ENV PATH=$PATH:~/emojicode
+
+# Setup Factor
+RUN mkdir -p ~/factor && wget https://downloads.factorcode.org/releases/0.98/factor-linux-x86-64-0.98.tar.gz -O ~/factor/factor.tar.gz && tar -xzf ~/factor/factor.tar.gz -C ~/factor --strip-components=1
+ENV PATH=$PATH:~/factor/factor
+
+# Setup R
+RUN sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9
+RUN sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu focal-cran40/'
+
+# Setup Racket and Scheme
+# To run scheme files, use `racket -f `
+RUN sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D9D33FCD84D82C17288BA03B3C9A6980F827E01E
+RUN sudo add-apt-repository 'deb http://ppa.launchpad.net/plt/racket/ubuntu focal main'
+
+# Setup Rust
+RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
+
+# Setup Scratch
+## using 1.x right now.... in future checkout snap or adobe air?
+
+# Setup Swift
+RUN mkdir -p ~/swift && wget https://swift.org/builds/swift-5.5-release/ubuntu2004/swift-5.5-RELEASE/swift-5.5-RELEASE-ubuntu20.04.tar.gz -O ~/swift/swift.tar.gz && \
+ tar -xzf ~/swift/swift.tar.gz -C ~/swift --strip-components=1
+ENV PATH=$PATH:~/swift/usr/bin
+
+# Setup viml
+# To run vim script commands use `/usr/bin/vim -c ":source %" `
+RUN apt-get -y install --no-install-recommends vim
+
+# Setup whitespace
+RUN mkdir -p ~/whitespace && git clone https://github.com/wspace/whitespace-haskell ~/whitespace && cd ~/whitespace && make -B
+ENV PATH=$PATH:~/whitespace
+
+# Setup Elm
+RUN mkdir -p ~/elm && curl -L -o ~/elm/elm.gz https://github.com/elm/compiler/releases/download/0.19.1/binary-for-linux-64-bit.gz && \
+ gunzip ~/elm/elm.gz && chmod +x ~/elm/elm
+ENV PATH=$PATH:~/elm
+
+# Setup V
+RUN mkdir -p ~/vlang && wget https://github.com/vlang/v/releases/download/weekly.2021.44/v_linux.zip -O ~/vlang/vlang.zip && \
+ unzip ~/vlang/vlang.zip -d ~/vlang
+ENV PATH=$PATH:~/vlang/v
+
+# Install the packages that needed extra help
+RUN apt-get update \
+ && apt-get -y install --no-install-recommends crystal dart nim powershell scala dotnet-sdk-5.0 r-base racket
+
+
+RUN python3 -m pip install --no-cache-dir wheel matplotlib numpy coconut scons
+
+RUN sudo sh -c 'npm install -g typescript'
diff --git a/README.md b/README.md
index e8d947857..ff37394dd 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ Here are some essential links:
- Book / website:
- GitHub repository:
- YouTube channel (LeiosOS):
-- Twitch livestream (simuleios):
+- Twitch livestream:
- Discord server:
Note that this project is essentially a book about algorithms collaboratively written by an online community.
diff --git a/SConstruct b/SConstruct
new file mode 100644
index 000000000..74e05ea85
--- /dev/null
+++ b/SConstruct
@@ -0,0 +1,141 @@
+"""
+SCons top-level build description (SConstruct) for the Arcane Algorithm Achive
+
+This provides Builder objects for each of the language implementations in the AAA; however, this work cannot be considered exhaustive until every language has been covered.
+
+Currently, the aim is to provide a way to compile or copy the implementation files to the build directory, as well as to provide ways to run them and capture their output.
+
+To run the compilation for all implementations in one language, e.g. C, run the command `scons build/c`, and the resulting executables will be available in the `build/c` directory, each in their respective algorithm directory, containing the executable."""
+
+from pathlib import Path
+from collections import namedtuple
+import os
+
+import SCons
+SCons.Warnings.warningAsException()
+
+# For interpreted languages to copy to build directory
+copy_builder = Builder(action=Copy('$TARGET', '$SOURCE'))
+
+env = Environment(ENV=os.environ,
+ BUILDERS={'Copier': copy_builder},
+ tools=[
+ 'g++', 'gas', 'gcc', 'gfortran', 'gnulink', 'javac'],
+ toolpath=['builders'])
+
+available_languages = {
+ 'asm-x64',
+ 'bash',
+ 'c',
+ 'cpp',
+ 'csharp',
+ 'fortran',
+ 'java',
+ 'julia',
+ 'lolcode'
+ 'lua',
+ 'php',
+ 'powershell',
+ 'python',
+ 'ruby',
+ 'viml',
+ 'racket',
+}
+
+languages_to_import = {
+ 'coconut': ['coconut'],
+ 'csharp': ['mcs'],
+ 'go': ['go'],
+ 'rust': ['rustc', 'cargo'],
+ 'kotlin': ['kotlin'],
+ 'racket': ['racket'],
+}
+
+for language, tools in languages_to_import.items():
+ for tool in tools:
+ try:
+ env.Tool(tool)
+ except SCons.Warnings.SConsWarning as w:
+ print(f'{w.args[0][0]}, ignoring')
+ break
+ else:
+ available_languages.add(language)
+
+
+Export('env')
+
+env['CCFLAGS'] = '-Wall -Wextra -Werror -pedantic -Wconversion'
+env['CFLAGS'] = '-std=gnu99'
+env['CXXFLAGS'] = '-std=c++17 -Wold-style-cast'
+env['ASFLAGS'] = '--64'
+env['COCONUTFLAGS'] = '--target 3.8'
+
+# Add other languages here when you want to add language targets
+# Put 'name_of_language_directory' : 'file_extension'
+
+languages = {
+ 'asm-x64': 's',
+ 'bash': 'bash',
+ 'c': 'c',
+ 'coconut': 'coco',
+ 'cpp': 'cpp',
+ 'csharp': 'cs',
+ 'fortran': 'f90',
+ 'go': 'go',
+ 'java': 'java',
+ 'javascript': 'js',
+ 'julia': 'jl',
+ 'kotlin': 'kt',
+ 'lolcode': 'lol',
+ 'lua': 'lua',
+ 'php': 'php',
+ 'powershell': 'ps1',
+ 'python': 'py',
+ 'ruby': 'rb',
+ 'rust': 'rs',
+ 'viml': 'vim',
+ 'racket': 'rkt'
+}
+
+# Do not add new Builders here, add them to the BUILDERS argument in the call to Environment above
+env.C = env.Program
+env.CPlusPlus = env.Program
+env.X64 = env.Program
+env.Fortran = env.Program
+
+for language in available_languages:
+ Alias(language, f'#/build/{language}')
+
+sconscripts = []
+files_to_compile = {language: [] for language in languages if language in available_languages}
+
+FileInformation = namedtuple('FileInformation', ['path', 'chapter', 'language'])
+
+
+contents_path = Path.cwd().joinpath('contents')
+for chapter_dir in contents_path.iterdir():
+ for code_dir in chapter_dir.glob('**/code'):
+ # For nested chapters e.g. contents/convolutions/1d/
+ extended_chapter_path = code_dir.relative_to(contents_path).parent
+
+ for language_dir in code_dir.iterdir():
+ if (language := language_dir.stem) in available_languages:
+ new_files = [FileInformation(path=file_path,
+ chapter=extended_chapter_path,
+ language=language)
+ for file_path in language_dir.glob(f'**/*.{languages[language]}')
+ ]
+ # Check for overriding SConscript
+ if (sconscript_path := language_dir / 'SConscript').exists():
+ SConscript(sconscript_path, exports={'files_to_compile': new_files})
+ else:
+ files_to_compile[language].extend(new_files)
+
+sconscript_dir_path = Path.cwd().joinpath('sconscripts')
+for language, files in files_to_compile.items():
+ if files:
+ if (sconscript_path := sconscript_dir_path / f"{language}_SConscript").exists():
+ SConscript(sconscript_path, exports = {'files_to_compile': files})
+ else:
+ print(f'{language} file found at {files[0]}, but no sconscript file is present ')
+
diff --git a/SUMMARY.md b/SUMMARY.md
index d76af219d..412b7fd12 100644
--- a/SUMMARY.md
+++ b/SUMMARY.md
@@ -3,6 +3,7 @@
* [Algorithm Archive](README.md)
* [Introduction](contents/introduction/introduction.md)
* [How To Contribute](contents/how_to_contribute/how_to_contribute.md)
+ * [Code Reviewers](contents/code_reviews/code_reviewers.md)
* [Plotting](contents/plotting/plotting.md)
* [Domain Coloring](contents/domain_coloring/domain_coloring.md)
* [Iterated Function Systems](contents/IFS/IFS.md)
@@ -19,9 +20,13 @@
* [Multiplication as a Convolution](contents/convolutions/multiplication/multiplication.md)
* [Convolutions of Images (2D)](contents/convolutions/2d/2d.md)
* [Convolutional Theorem](contents/convolutions/convolutional_theorem/convolutional_theorem.md)
+ * [Box Muller Transform](contents/box_muller/box_muller.md)
+ * [How costly is rejection sampling?](contents/box_muller/box_muller_rejection.md)
+ * [Probability Distributions](contents/probability_distributions/distributions.md)
* [Tree Traversal](contents/tree_traversal/tree_traversal.md)
* [Euclidean Algorithm](contents/euclidean_algorithm/euclidean_algorithm.md)
* [Monte Carlo](contents/monte_carlo_integration/monte_carlo_integration.md)
+ * [Metropolis](contents/metropolis/metropolis.md)
* [Matrix Methods](contents/matrix_methods/matrix_methods.md)
* [Gaussian Elimination](contents/gaussian_elimination/gaussian_elimination.md)
* [Thomas Algorithm](contents/thomas_algorithm/thomas_algorithm.md)
@@ -32,8 +37,6 @@
* [FFT](contents/cooley_tukey/cooley_tukey.md)
* [Decision Problems](contents/decision_problems/decision_problems.md)
* [Stable Marriage Problem](contents/stable_marriage_problem/stable_marriage_problem.md)
-* [Differential Equation Solvers](contents/differential_equations/differential_equations.md)
- * [Forward Euler Method](contents/forward_euler_method/forward_euler_method.md)
* [Physics Solvers](contents/physics_solvers/physics_solvers.md)
* [Verlet Integration](contents/verlet_integration/verlet_integration.md)
* [Quantum Systems](contents/quantum_systems/quantum_systems.md)
@@ -43,5 +46,6 @@
* [Computer Graphics](contents/computer_graphics/computer_graphics.md)
* [Flood Fill](contents/flood_fill/flood_fill.md)
* [Quantum Information](contents/quantum_information/quantum_information.md)
+* [Cryptography](contents/cryptography/cryptography.md)
* [Computus](contents/computus/computus.md)
* [Approximate Counting Algorithm](contents/approximate_counting/approximate_counting.md)
diff --git a/book.json b/book.json
index 4614a850c..690acec87 100644
--- a/book.json
+++ b/book.json
@@ -193,8 +193,8 @@
{
"lang": "ps1",
"name": "PowerShell"
- },
- {
+ },
+ {
"lang": "v",
"name": "Vlang"
},
@@ -206,6 +206,10 @@
"lang": "kotlin",
"name": "Kotlin"
},
+ {
+ "lang": "ts",
+ "name": "TypeScript"
+ },
{
"lang": "vim",
"name": "VimL"
@@ -213,6 +217,10 @@
{
"lang": "coco",
"name": "Coconut"
+ },
+ {
+ "lang": "dart",
+ "name": "Dart"
}
]
}
diff --git a/builders/cargo.py b/builders/cargo.py
new file mode 100644
index 000000000..0ac22e086
--- /dev/null
+++ b/builders/cargo.py
@@ -0,0 +1,41 @@
+from SCons.Builder import Builder
+from SCons.Script import Move
+import SCons.Util
+
+class ToolCargoWarning(SCons.Warnings.SConsWarning):
+ pass
+
+class CargoNotFound(ToolCargoWarning):
+ pass
+
+SCons.Warnings.enableWarningClass(ToolCargoWarning)
+
+def _detect(env):
+ try:
+ return env['cargo']
+ except KeyError:
+ pass
+
+ cargo = env.WhereIs('cargo')
+ if cargo:
+ return cargo
+
+ SCons.Warnings.warn(CargoNotFound, 'Could not detect cargo')
+
+def exists(env):
+ return env.Detect('cargo')
+
+
+def generate(env):
+ env['CARGO'] = _detect(env)
+ env['CARGOFLAGS'] = []
+ env['MANIFEST'] = []
+
+ rust_cargo_builder = Builder(
+ action=['"$CARGO" build $CARGOFLAGS --bins --manifest-path $MANIFEST',
+ Move('$TARGET$PROGSUFFIX',
+ '$SOURCE_DIR/target/debug/main$PROGSUFFIX')
+ ],
+ suffix='$PROGSUFFIX',
+ )
+ env.Append(BUILDERS={'cargo': rust_cargo_builder})
diff --git a/builders/coconut.py b/builders/coconut.py
new file mode 100644
index 000000000..36498412b
--- /dev/null
+++ b/builders/coconut.py
@@ -0,0 +1,40 @@
+from SCons.Builder import Builder
+import SCons.Util
+
+class ToolCocoWarning(SCons.Warnings.SConsWarning):
+ pass
+
+class CoconutNotFound(ToolCocoWarning):
+ pass
+
+SCons.Warnings.enableWarningClass(ToolCocoWarning)
+
+def _detect(env):
+ try:
+ return env['coconut']
+ except KeyError:
+ pass
+
+ coconut = env.WhereIs('coconut')
+ if coconut:
+ return coconut
+
+ SCons.Warnings.warn(CoconutNotFound, 'Could not find Coconut executable')
+
+
+def generate(env):
+ env['COCONUT'] = _detect(env)
+ env['COCONUTFLAGS'] = []
+
+ coconut_compiler = Builder(
+ action='"$COCONUT" $COCONUTFLAGS $SOURCE $TARGET',
+ src_suffix='.coco',
+ suffix='.py',
+ )
+
+ env.Append(BUILDERS={'Coconut': coconut_compiler})
+
+def exists(env):
+ return env.Detect('coconut')
+
+
diff --git a/builders/go.py b/builders/go.py
new file mode 100644
index 000000000..261789092
--- /dev/null
+++ b/builders/go.py
@@ -0,0 +1,37 @@
+from SCons.Builder import Builder
+import SCons.Util
+
+class ToolGoWarning(SCons.Warnings.SConsWarning):
+ pass
+
+class GoNotFound(ToolGoWarning):
+ pass
+
+SCons.Warnings.enableWarningClass(ToolGoWarning)
+
+def _detect(env):
+ try:
+ return env['go']
+ except KeyError:
+ pass
+
+ go = env.WhereIs('go')
+ if go:
+ return go
+
+ SCons.Warnings.warn(GoNotFound, 'Could not find go executable')
+
+def exists(env):
+ env.Detect('go')
+
+def generate(env):
+ env['GO'] = _detect(env)
+ env['GOFLAGS'] = []
+
+ go_builder = Builder(
+ action='"$GO" build -o $TARGET $GOFLAGS $SOURCE',
+ src_suffix='.go',
+ suffix='$PROGSUFFIX',
+ )
+
+ env.Append(BUILDERS={'Go': go_builder})
diff --git a/builders/kotlin.py b/builders/kotlin.py
new file mode 100644
index 000000000..fc1d9ecb1
--- /dev/null
+++ b/builders/kotlin.py
@@ -0,0 +1,184 @@
+# MIT License
+#
+# Copyright The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+"""SCons.Tool.kotlin
+Tool-specific initialization for Kotlin.
+"""
+
+import SCons.Action
+import SCons.Builder
+import SCons.Util
+
+
+class ToolKotlinWarning(SCons.Warnings.SConsWarning):
+ pass
+
+
+class KotlinNotFound(ToolKotlinWarning):
+ pass
+
+
+SCons.Warnings.enableWarningClass(ToolKotlinWarning)
+
+
+def _detect(env):
+ """ Try to detect the kotlinc binary """
+ try:
+ return env["kotlinc"]
+ except KeyError:
+ pass
+
+ kotlin = env.Detect("kotlinc")
+ if kotlin:
+ return kotlin
+
+ SCons.Warnings.warn(KotlinNotFound, "Could not find kotlinc executable")
+
+
+#
+# Builders
+#
+kotlinc_builder = SCons.Builder.Builder(
+ action=SCons.Action.Action("$KOTLINCCOM", "$KOTLINCCOMSTR"),
+ suffix="$KOTLINCLASSSUFFIX",
+ src_suffix="$KOTLINSUFFIX",
+ single_source=True,
+) # file by file
+
+kotlin_jar_builder = SCons.Builder.Builder(
+ action=SCons.Action.Action("$KOTLINJARCOM", "$KOTLINJARCOMSTR"),
+ suffix="$KOTLINJARSUFFIX",
+ src_suffix="$KOTLINSUFFIX",
+ single_source=True,
+) # file by file
+
+kotlin_rtjar_builder = SCons.Builder.Builder(
+ action=SCons.Action.Action("$KOTLINRTJARCOM", "$KOTLINRTJARCOMSTR"),
+ suffix="$KOTLINJARSUFFIX",
+ src_suffix="$KOTLINSUFFIX",
+ single_source=True,
+) # file by file
+
+
+def Kotlin(env, target, source=None, *args, **kw):
+ """
+ A pseudo-Builder wrapper for the kotlinc executable.
+ kotlinc [options] file
+ """
+ if not SCons.Util.is_List(target):
+ target = [target]
+ if not source:
+ source = target[:]
+ if not SCons.Util.is_List(source):
+ source = [source]
+
+ result = []
+ kotlinc_suffix = env.subst("$KOTLINCLASSSUFFIX")
+ kotlinc_extension = env.subst("$KOTLINEXTENSION")
+ for t, s in zip(target, source):
+ t_ext = t
+ if not t.endswith(kotlinc_suffix):
+ if not t.endswith(kotlinc_extension):
+ t_ext += kotlinc_extension
+
+ t_ext += kotlinc_suffix
+ # Ensure that the case of first letter is upper-case
+ t_ext = t_ext[:1].upper() + t_ext[1:]
+ # Call builder
+ kotlin_class = kotlinc_builder.__call__(env, t_ext, s, **kw)
+ result.extend(kotlin_class)
+
+ return result
+
+
+def KotlinJar(env, target, source=None, *args, **kw):
+ """
+ A pseudo-Builder wrapper for creating JAR files with the kotlinc executable.
+ kotlinc [options] file -d target
+ """
+ if not SCons.Util.is_List(target):
+ target = [target]
+ if not source:
+ source = target[:]
+ if not SCons.Util.is_List(source):
+ source = [source]
+
+ result = []
+ for t, s in zip(target, source):
+ # Call builder
+ kotlin_jar = kotlin_jar_builder.__call__(env, t, s, **kw)
+ result.extend(kotlin_jar)
+
+ return result
+
+
+def KotlinRuntimeJar(env, target, source=None, *args, **kw):
+ """
+ A pseudo-Builder wrapper for creating standalone JAR files with the kotlinc executable.
+ kotlinc [options] file -d target -include-runtime
+ """
+ if not SCons.Util.is_List(target):
+ target = [target]
+ if not source:
+ source = target[:]
+ if not SCons.Util.is_List(source):
+ source = [source]
+
+ result = []
+ for t, s in zip(target, source):
+ # Call builder
+ kotlin_jar = kotlin_rtjar_builder.__call__(env, t, s, **kw)
+ result.extend(kotlin_jar)
+
+ return result
+
+
+def generate(env):
+ """Add Builders and construction variables for kotlinc to an Environment."""
+
+ env["KOTLINC"] = _detect(env)
+
+ env.SetDefault(
+ KOTLINC="kotlinc",
+ KOTLINSUFFIX=".kt",
+ KOTLINEXTENSION="Kt",
+ KOTLINCLASSSUFFIX=".class",
+ KOTLINJARSUFFIX=".jar",
+ KOTLINCFLAGS=SCons.Util.CLVar(),
+ KOTLINJARFLAGS=SCons.Util.CLVar(),
+ KOTLINRTJARFLAGS=SCons.Util.CLVar(["-include-runtime"]),
+ KOTLINCCOM="$KOTLINC $KOTLINCFLAGS $SOURCE",
+ KOTLINCCOMSTR="",
+ KOTLINJARCOM="$KOTLINC $KOTLINJARFLAGS -d $TARGET $SOURCE",
+ KOTLINJARCOMSTR="",
+ KOTLINRTJARCOM="$KOTLINC $KOTLINRTJARFLAGS -d $TARGET $SOURCE",
+ KOTLINRTJARCOMSTR="",
+ )
+
+ env.AddMethod(Kotlin, "Kotlin")
+ env.AddMethod(KotlinJar, "KotlinJar")
+ env.AddMethod(KotlinRuntimeJar, "KotlinRuntimeJar")
+
+
+def exists(env):
+ return _detect(env)
diff --git a/builders/mcs.py b/builders/mcs.py
new file mode 100644
index 000000000..07f1bd76c
--- /dev/null
+++ b/builders/mcs.py
@@ -0,0 +1,37 @@
+from SCons.Builder import Builder
+import SCons.Util
+
+class ToolMCSWarning(SCons.Warnings.SConsWarning):
+ pass
+
+class MCSNotFound(ToolMCSWarning):
+ pass
+
+SCons.Warnings.enableWarningClass(ToolMCSWarning)
+
+def _detect(env):
+ try:
+ return env['mcs']
+ except KeyError:
+ pass
+
+ mcs = env.WhereIs('mcs')
+ if mcs:
+ return mcs
+
+ SCons.Warnings.warn(MCSNotFound, 'Could not find mcs executable')
+
+def exists(env):
+ env.Detect('mcs')
+
+def generate(env):
+ env['MCS'] = _detect(env)
+ env['MCSFLAGS'] = []
+
+ mcs_builder = Builder(
+ action='"$MCS" -out:$TARGET $MCSFLAGS $SOURCES',
+ src_suffix='.cs',
+ suffix='$PROGSUFFIX',
+ )
+
+ env.Append(BUILDERS={'MCS': mcs_builder})
diff --git a/builders/racket.py b/builders/racket.py
new file mode 100644
index 000000000..2729658fe
--- /dev/null
+++ b/builders/racket.py
@@ -0,0 +1,37 @@
+from SCons.Builder import Builder
+import SCons.Util
+
+class ToolRacketWarning(SCons.Warnings.SConsWarning):
+ pass
+
+class RacketNotFound(ToolRacketWarning):
+ pass
+
+SCons.Warnings.enableWarningClass(ToolRacketWarning)
+
+def _detect(env):
+ try:
+ return env['raco']
+ except KeyError:
+ pass
+
+ go = env.WhereIs('raco')
+ if go:
+ return go
+
+ SCons.Warnings.warn(RacketNotFound, 'Could not find raco executable')
+
+def exists(env):
+ env.Detect('raco')
+
+def generate(env):
+ env['RACO'] = _detect(env)
+ env['RACOFLAGS'] = []
+
+ racket_builder = Builder(
+ action='"$RACO" exe -o $TARGET $RACOFLAGS $SOURCE',
+ src_suffix='.rkt',
+ suffix='$PROGSUFFIX',
+ )
+
+ env.Append(BUILDERS={'Racket': racket_builder})
diff --git a/builders/rustc.py b/builders/rustc.py
new file mode 100644
index 000000000..f07cf4fad
--- /dev/null
+++ b/builders/rustc.py
@@ -0,0 +1,45 @@
+from SCons.Builder import Builder
+import SCons.Util
+
+class ToolRustcWarning(SCons.Warnings.SConsWarning):
+ pass
+
+class RustcNotFound(ToolRustcWarning):
+ pass
+
+SCons.Warnings.enableWarningClass(ToolRustcWarning)
+
+def _detect(env):
+ try:
+ return env['rustc']
+ except KeyError:
+ pass
+
+ cargo = env.WhereIs('rustc')
+ if cargo:
+ return cargo
+
+ SCons.Warnings.warn(RustcNotFound, 'Could not detect rustc')
+
+
+def exists(env):
+ return env.Detect('rustc')
+
+def rustc_emitter(target, source, env):
+ src_name = str(source[0])
+ pdb_name = src_name.replace(source[0].suffix, '.pdb')
+ env.SideEffect(pdb_name, target)
+ env.Clean(target, pdb_name)
+ return (target, source)
+
+def generate(env):
+ env['RUSTC'] = _detect(env)
+ env['RUSTCFLAGS'] = []
+
+ rust_cargo_builder = Builder(
+ action='"$RUSTC" $RUSTCFLAGS -o $TARGET $SOURCE',
+ suffix='$PROGSUFFIX',
+ src_suffix='.rs',
+ emitter=rustc_emitter,
+ )
+ env.Append(BUILDERS={'rustc': rust_cargo_builder})
diff --git a/contents/IFS/IFS.md b/contents/IFS/IFS.md
index 67422d9fd..1e1e45d37 100644
--- a/contents/IFS/IFS.md
+++ b/contents/IFS/IFS.md
@@ -20,8 +20,8 @@ To begin the discussion of Iterated Function Systems (IFSs), we will first discu
This image is clearly a set of triangles embedded in a larger triangle in such a way that it can be continually cut into three identical pieces and still retain its internal structure.
-This idea is known as self-similarity {{"self-similar" | cite }}, and it is usually the first aspect of fractals to catch an audience's attention.
-In fact, there are plenty of uses of fractals and their mathematical underpinnings, such as estimating the coastline of Britain {{ "mandelbrot1967long" | cite}}, identifying fingerprints {{ "jampour2010new" | cite }}, and image compression {{ "fractal-compression" | cite }}{{ "saupe1994review" | cite }}.
+This idea is known as self-similarity {{ "self-similar" | cite }}, and it is usually the first aspect of fractals to catch an audience's attention.
+In fact, there are plenty of uses of fractals and their mathematical underpinnings, such as estimating the coastline of Britain {{ "mandelbrot1967long" | cite }}, identifying fingerprints {{ "jampour2010new" | cite }}, and image compression {{ "fractal-compression" | cite }}{{ "saupe1994review" | cite }}.
In many more rigorous definitions, a fractal can be described as any system that has a non-integer Hausdorff dimension {{ "3b1bfractal" | cite }}{{ "hausdorff" | cite }}{{ "gneiting2012estimators" | cite }}.
Though this is an incredibly interesting concept, the discussion of this chapter will instead focus on methods to generate fractal patterns through iterated function systems.
@@ -41,7 +41,7 @@ f_3(P) &= \frac{P + C}{2}\\
$$
Each function will read in a particular location in space (here, $$P \in \mathbb{R}^2$$) and output a new location that is the midpoint between the input location and $$A$$, $$B$$, or $$C$$ for $$f_1$$, $$f_2$$, and $$f_3$$ respectively.
-The union of all of these functions (the set of all possible functions available for use) is often notated as the _Hutchinson operator_ {{ "hutchinson-operator" | cite }}{{ "hutchinson1981fractals" | cite}}, and for this case it would look like this:
+The union of all of these functions (the set of all possible functions available for use) is often notated as the _Hutchinson operator_ {{ "hutchinson-operator" | cite }}{{ "hutchinson1981fractals" | cite }}, and for this case it would look like this:
$$
H(P) = \bigcup_{i=1}^3f_i(P)
@@ -132,16 +132,24 @@ Here, instead of tracking children of children, we track a single individual tha
{% method %}
{% sample lang="jl" %}
[import:4-17, lang:"julia"](code/julia/IFS.jl)
+{% sample lang="hs" %}
+[import:7-13, lang:"haskell"](code/haskell/IFS.hs)
{% sample lang="cpp" %}
-[import:39-52, lang:"cpp"](code/c++/IFS.cpp)
+[import:39-52, lang:"cpp"](code/cpp/IFS.cpp)
{% sample lang="py" %}
[import:5-12, lang:"python"](code/python/IFS.py)
{% sample lang="c" %}
[import:18-29, lang:"c"](code/c/IFS.c)
+{% sample lang="lisp" %}
+[import:5-14, lang:"lisp"](code/clisp/ifs.lisp)
{% sample lang="coco" %}
[import:4-16, lang:"coconut"](code/coconut/IFS.coco)
+{% sample lang="rust" %}
+[import:9-20, lang:"rust"](code/rust/IFS.rs)
{% sample lang="java" %}
[import:16-39, lang:"java"](code/java/IFS.java)
+{% sample lang="ps1" %}
+[import:2-19, lang:"powershell"](code/powershell/IFS.ps1)
{% endmethod %}
If we set the initial point to the on the equilateral triangle we saw before, we can see the Sierpinski triangle again after a few thousand iterations, as shown below:
@@ -200,7 +208,7 @@ If you are interested, please let me know and I will be more than willing to add
Here is a video describing iterated function systems:
-
@@ -214,16 +222,24 @@ In addition, we have written the chaos game code to take in a set of points so t
{% method %}
{% sample lang="jl" %}
[import, lang:"julia"](code/julia/IFS.jl)
+{% sample lang="hs" %}
+[import, lang:"haskell"](code/haskell/IFS.hs)
{% sample lang="cpp" %}
-[import, lang:"cpp"](code/c++/IFS.cpp)
+[import, lang:"cpp"](code/cpp/IFS.cpp)
{% sample lang="py" %}
[import, lang:"python"](code/python/IFS.py)
{% sample lang="c" %}
[import, lang:"c"](code/c/IFS.c)
+{% sample lang="lisp" %}
+[import, lang:"lisp"](code/clisp/ifs.lisp)
{%sample lang="coco" %}
[import, lang:"coconut"](code/coconut/IFS.coco)
+{%sample lang="rust" %}
+[import, lang:"rust"](code/rust/IFS.rs)
{%sample lang="java" %}
[import, lang:"java"](code/java/IFS.java)
+{% sample lang="ps1" %}
+[import, lang:"powershell"](code/powershell/IFS.ps1)
{% endmethod %}
### Bibliography
@@ -238,7 +254,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/IFS/code/c/IFS.c b/contents/IFS/code/c/IFS.c
index 2ba8cbdd2..ffd56f6fe 100644
--- a/contents/IFS/code/c/IFS.c
+++ b/contents/IFS/code/c/IFS.c
@@ -20,7 +20,7 @@ void chaos_game(struct point *in, size_t in_n, struct point *out,
struct point cur_point = {drand(), drand()};
- for (int i = 0; i < out_n; ++i) {
+ for (size_t i = 0; i < out_n; ++i) {
out[i] = cur_point;
struct point tmp = random_element(in, in_n);
cur_point.x = 0.5 * (cur_point.x + tmp.x);
@@ -29,16 +29,18 @@ void chaos_game(struct point *in, size_t in_n, struct point *out,
}
int main() {
+ const size_t point_count = 10000;
+
struct point shape_points [3] = {{0.0,0.0}, {0.5,sqrt(0.75)}, {1.0,0.0}};
- struct point out_points[1000];
+ struct point out_points[point_count];
- srand(time(NULL));
+ srand((unsigned int)time(NULL));
- chaos_game(shape_points, 3, out_points, 1000);
+ chaos_game(shape_points, 3, out_points, point_count);
FILE *fp = fopen("sierpinksi.dat", "w+");
- for (int i = 0; i < 1000; ++i) {
+ for (size_t i = 0; i < point_count; ++i) {
fprintf(fp, "%f\t%f\n", out_points[i].x, out_points[i].y);
}
@@ -46,4 +48,3 @@ int main() {
return 0;
}
-
diff --git a/contents/IFS/code/clisp/ifs.lisp b/contents/IFS/code/clisp/ifs.lisp
new file mode 100644
index 000000000..c9fc0e432
--- /dev/null
+++ b/contents/IFS/code/clisp/ifs.lisp
@@ -0,0 +1,28 @@
+;;;; Iterated Function System implementation
+
+(defstruct (point (:constructor make-point (x y))) x y)
+
+(defun chaos-game (iterations shape-points)
+ "Plays a chaos game with a certain shape for a determined amount of iterations"
+ (loop
+ repeat iterations
+ for rand-point = (svref shape-points (random (length shape-points)))
+ for point = (make-point (random 1.0) (random 1.0)) ; starting point
+ then (make-point
+ (* 0.5 (+ (point-x rand-point) (point-x point)))
+ (* 0.5 (+ (point-y rand-point) (point-y point)))) ; every subsequent point
+ collect point))
+
+(defparameter *shape-points*
+ (map
+ 'vector
+ (lambda (e) (apply #'make-point e))
+ ;; the backquote allows us to selectively evaluate (sqrt 0.75) with the comma
+ `((0 0) (0.5 ,(sqrt 0.75)) (1 0))))
+
+;; output the data to the "out.dat" file
+(with-open-file (out "sierpinski.dat" :direction :output :if-exists :supersede)
+ (flet ((format-point (p)
+ ;; this is not very clean, but it's the simplest way to insert a tab into a string.
+ (format nil "~f~c~f" (point-x p) #\tab (point-y p))))
+ (format out "~{~a~%~}" (map 'list #'format-point (chaos-game 10000 *shape-points*)))))
diff --git a/contents/IFS/code/c++/IFS.cpp b/contents/IFS/code/cpp/IFS.cpp
similarity index 100%
rename from contents/IFS/code/c++/IFS.cpp
rename to contents/IFS/code/cpp/IFS.cpp
diff --git a/contents/IFS/code/haskell/IFS.hs b/contents/IFS/code/haskell/IFS.hs
new file mode 100644
index 000000000..41d8b4c9a
--- /dev/null
+++ b/contents/IFS/code/haskell/IFS.hs
@@ -0,0 +1,30 @@
+import Data.Array ((!), Array, bounds, listArray)
+import Data.List (intercalate)
+import System.Random
+
+data Point = Point Double Double
+
+chaosGame :: RandomGen g => g -> Int -> Array Int (Point -> Point) -> [Point]
+chaosGame g n hutchinson = take n points
+ where
+ (x, g') = random g
+ (y, g'') = random g'
+ choices = randomRs (bounds hutchinson) g''
+ points = Point x y : zipWith (hutchinson !) choices points
+
+main :: IO ()
+main = do
+ g <- newStdGen
+
+ let midPoint (Point a b) (Point x y) = Point ((a + x) / 2) ((b + y) / 2)
+ sierpinski =
+ listArray
+ (1, 3)
+ [ midPoint (Point 0 0),
+ midPoint (Point 0.5 (sqrt 0.75)),
+ midPoint (Point 1 0)
+ ]
+ points = chaosGame g 10000 sierpinski
+ showPoint (Point x y) = show x ++ "\t" ++ show y
+
+ writeFile "sierpinski.dat" $ intercalate "\n" $ map showPoint points
diff --git a/contents/IFS/code/powershell/IFS.ps1 b/contents/IFS/code/powershell/IFS.ps1
new file mode 100644
index 000000000..086c80072
--- /dev/null
+++ b/contents/IFS/code/powershell/IFS.ps1
@@ -0,0 +1,34 @@
+# This function simulates a "chaos game"
+function Simulate-ChaosGame($n, $shapePoints) {
+ $outputPoints = New-Object System.Collections.ArrayList
+
+ # Initialize the starting point
+ $point = @($(Get-Random -Minimum 0.0 -Maximum 1.0), $(Get-Random -Minimum 0.0 -Maximum 1.0))
+
+ for ($i = 0; $i -lt $n; $i++) {
+ $outputPoints.add($point) | Out-Null
+ $temp = $shapePoints[$(Get-Random -Maximum $shapePoints.Count)]
+
+ $point = @(
+ 0.5 * ($point[0] + $temp[0])
+ 0.5 * ($point[1] + $temp[1])
+ )
+ }
+
+ return $outputPoints
+}
+
+
+# This will generate a Sierpinski triangle with a chaos game of n points for an
+# initial triangle with three points on the vertices of an equilateral triangle:
+# A = (0.0, 0.0)
+# B = (0.5, sqrt(0.75))
+# C = (1.0, 0.0)
+# It will output the file sierpinski.dat, which can be plotted after
+$shapePoints = @(
+ @(0.0, 0.0),
+ @(0.5, [math]::sqrt(0.75)),
+ @(1.0, 0.0)
+)
+
+Simulate-ChaosGame -n 10000 -shapePoints $shapePoints | % { "$($_[0])`t$($_[1])" } | Out-File -Path "sierpinski.dat"
diff --git a/contents/IFS/code/rust/Cargo.toml b/contents/IFS/code/rust/Cargo.toml
new file mode 100644
index 000000000..90fbca22d
--- /dev/null
+++ b/contents/IFS/code/rust/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "rust"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+rand = "0.8.4"
+
+[[bin]]
+path = "./IFS.rs"
+name = "main"
\ No newline at end of file
diff --git a/contents/IFS/code/rust/IFS.rs b/contents/IFS/code/rust/IFS.rs
new file mode 100644
index 000000000..476565f0f
--- /dev/null
+++ b/contents/IFS/code/rust/IFS.rs
@@ -0,0 +1,36 @@
+use rand::*;
+
+#[derive(Clone, Copy)]
+struct Point {
+ x: f64,
+ y: f64,
+}
+
+fn chaos_game(iters: usize, shapes: Vec) -> Vec {
+ let mut rng = rand::thread_rng();
+ let mut p = Point{x: rng.gen(), y: rng.gen()};
+
+ (0..iters).into_iter().map(|_| {
+ let old_point = p;
+ let tmp = shapes[rng.gen_range(0..shapes.len())];
+ p.x = 0.5 * (p.x + tmp.x);
+ p.y = 0.5 * (p.y + tmp.y);
+ old_point
+ }).collect()
+}
+
+fn main() {
+ let shapes = vec![
+ Point{x: 0., y: 0.},
+ Point{x: 0.5, y: 0.75_f64.sqrt()},
+ Point{x: 1., y: 0.},
+ ];
+
+ let mut out = String::new();
+
+ for point in chaos_game(10_000, shapes) {
+ out += format!("{}\t{}\n", point.x, point.y).as_str();
+ }
+
+ std::fs::write("./sierpinski.dat", out).unwrap();
+}
\ No newline at end of file
diff --git a/contents/affine_transformations/affine_transformations.md b/contents/affine_transformations/affine_transformations.md
index 88f140443..d832f9fc0 100644
--- a/contents/affine_transformations/affine_transformations.md
+++ b/contents/affine_transformations/affine_transformations.md
@@ -297,7 +297,7 @@ I think that is a nice note to end on: affine transformations are linear transfo
Here is a video describing affine transformations:
-
+
+
+## License
+
+##### Code Examples
+
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
+
+##### Text
+
+The text of this chapter was written by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+[
](https://creativecommons.org/licenses/by-sa/4.0/)
+
+#### Images/Graphics
+
+- The image "[IFS triangle 1](../IFS/res/IFS_triangle_1.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The image "[IFS square 3](../IFS/res/IFS_square_3.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The image "[Simple Barnsley fern](res/full_fern.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Affine random transform 0](res/affine_rnd_0.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Affine random transform 1](res/affine_rnd_1.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Affine random transform 2](res/affine_rnd_2.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Affine random transform 3](res/affine_rnd_3.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Affine fern transform 0](res/affine_fern_0.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Affine fern transform 1](res/affine_fern_1.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Affine fern transform 2](res/affine_fern_2.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Affine fern transform 3](res/affine_fern_3.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Fern twiddle 0](res/fern_twiddle_0.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Fern twiddle 1](res/fern_twiddle_1.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Fern twiddle 2](res/fern_twiddle_2.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+- The video "[Fern twiddle 3](res/fern_twiddle_3.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
diff --git a/contents/box_muller/box_muller_rejection.md b/contents/box_muller/box_muller_rejection.md
new file mode 100644
index 000000000..37e1c0e3d
--- /dev/null
+++ b/contents/box_muller/box_muller_rejection.md
@@ -0,0 +1,126 @@
+# Just how costly is rejection sampling anyway?
+
+Let's imagine we want to have a final Gaussian distribution with $$n$$ particles in it.
+With the Cartesian Box—Muller method, this is easy: start the initial distribution(s) with $$n$$ particles and then do the transform.
+Things *can* be just as easy with the Polar Box—Muller method as well, so long as we start with a uniformly distributed *circle* instead of a uniformly distributed *square*.
+That is to say, so long as we do the rejection sampling before-hand, the Polar Box—Muller method will always be more efficient.
+To be fair, there are methods to generate a uniform distribution of points within a circle without rejection sampling, but let's assume that we require rejection sampling for this example
+
+This means that someone somehow needs to do the rejection sampling for the Polar method, which is sometimes a painful process.
+This also means that the Box—Muller method can be used to teach some of the fundamentals of General-Purpose GPU computing.
+Note that because of the specificity of this problem, all the code in this subsection will be in Julia and using the package KernelAbstractions.jl, which allows us to execute the same kernels on either CPU or GPU hardware depending on how we configure things.
+
+Let's first consider the case where we do the rejection sampling as a part of the polar Box—Muller kernel instead of as a pre-processing step.
+In this case, we can imagine 2 separate ways of writing our kernel:
+1. With replacement: In this case, we *absolutely require* the final number of points in our Gaussian distribution to be $$n$$, so if we find a point outside of the unit circle while running the kernel, we will "re-roll" again for a new point that *is* within the circle.
+2. Without replacement: This means that we will start with a uniform distribution of $$n$$ points, but end with a Gaussian of $$m < n$$ points. In this case, if we find a point outside of the unit circle while running the kernel, we just ignore it by setting the output values to NaNs (or something similar).
+
+OK, so first with replacement:
+
+[import:70-84, lang:"julia"](code/julia/performance.jl)
+
+This is an awful idea for a number of reasons.
+Here are a few:
+1. If we find a point outside of the unit circle, we have to continually look for new points until we *do* find one inside of the circle. Because we are running this program in parallel, where each thread transforms one point at a time, some threads might take literally forever to find a new point (if we are really unlucky).
+2. To generate new points, we need to re-generate a uniform distribution, but what if our uniform distribution is not random? What if it's a grid (or something similar) instead? In this case, we really shouldn't look for a new point on the inside of the circle as all those points have already been accounted for.
+3. The `rand()` function is kinda tricky on some parallel platforms (like GPUs) and might not work out of the box. In fact, the implementation shown above can only be run on the CPU.
+
+OK, fine.
+I don't think anyone expected a kernel with a `while` loop inside of it to be fast.
+So what about a method without replacement?
+Surely there is no problem if we just ignore the `while` loop altogether!
+Well, the problem with this approach is a bit less straightforward, but first, code:
+
+[import:53-68, lang:"julia"](code/julia/performance.jl)
+
+To start discussing why a polar kernel without replacement is *also* a bad idea, let's go back to the [Monte Carlo chapter](../monte_carlo/monte_carlo.md), where we calculated the value of $$\pi$$ by embedding it into a circle.
+There, we found that the probability of a randomly chosen point falling within the unit circle to be $$\frac{\pi r^2}{(2r)^2} = \frac{pi}{4} \sim 78.54\%$$, shown in the visual below:
+
+
+
+
+
+This means that a uniform distribution of points within a circle will reject $$\sim 21.46\%$$ of points on the square.
+This also means that if we have a specific $$n$$ value we want for the final distribution, we will need $$\frac{1}{0.7853} \sim 1.273 \times$$ more input values on average!
+
+No problem!
+In this hypothetical case, we don't need *exactly* $$n$$ points, so we can just start the initial distributions with $$1.273 \times n$$ points, right?
+
+Right.
+That will work well on parallel CPU hardware, but on the GPU this will still have an issue.
+
+On the GPU, computation is all done in parallel, but there is a minimum unit of parallelism called a *warp*.
+The warp is the smallest number of threads that can execute something in parallel and is usually about 32.
+This means that if an operation is queued, all 32 threads will do it at the same time.
+If 16 threads need to execute something and the other 16 threads need to execute something else, this will lead to *warp divergence* where 2 actions need to be performed instead of 1:
+
+
+
+
+
+In this image, every odd thread needs to perform the pink action, while the even threads need to perform the blue action.
+This means that 2 separate parallel tasks will be performed, one for the even threads, another for the odd threads.
+This means that if $$\ell$$ separate operations are queued, it could take $$\ell\times$$ as long for all the threads to do their work!
+This is why `if` statements in a kernel can be dangerous!
+If used improperly, they can cause certain threads in a warp to do different things!
+
+So let's imagine that the above image is part of a larger array of values, such that there are a bunch of warps with the same divergence issue.
+In this case, we could sort the array before-hand so that all even elements come before all odd elements.
+This would mean that the warps will almost certainly not diverge because the elements queued will all be of the same type and require the same operations.
+Unfortunately, this comes at the cost of a sorting operation which is prohibitively expensive.
+
+If we look at the above kernel, we are essentially asking $$21.47\%$$ of our threads to do something different than everyone else, and because we are usually inputting a uniform random distribution, this means that *most* warps will have to queue up 2 parallel actions instead of 1.
+
+Essentially, we need to pick our poison:
+* Slow $$\sin$$ and $$\cos$$ operations with the Cartesian method
+* Warp divergence with the Polar method
+
+The only way to know which is better is to perform benchmarks, which we will show in a bit, but there is one final scenario we should consider: what about doing the rejection sampling as a pre-processing step?
+This would mean that we pre-initialize the polar kernel with a uniform distribution of points in the unit circle.
+This means no warp divergence, so we can get the best of both worlds, right?
+
+Well, not exactly.
+The polar Box—Muller method will definitely be faster, but again: someone somewhere needed to do rejection sampling and if we include that step into the process, things become complicated again.
+The truth is that this pre-processing step is difficult to get right, so it might require a chapter in it's own right.
+
+In many cases, it's worth spending a little time before-hand to make sure subsequent operations are fast, but in this case, we only have a single operation, not a set of operations.
+The Box—Muller method will usually only be used once at the start of the simulation, which means that the pre-processing step of rejection sampling might end up being overkill.
+
+No matter the case, benchmarks will show the true nature of what we are dealing with here:
+
+| Method | CPU | GPU |
+| ------------------------- | ---------------------- | ---------------------- |
+| Cartesian | $$385.819 \pm 1.9$$ms | $$19.347 \pm 0.618$$ms |
+| Polar without replacement | $$273.308 \pm 2.81$$ms | $$26.712 \pm 0.592$$ms |
+| Polar with replacement | $$433.644 \pm 2.64$$ms | NA |
+
+These were run with an Nvidia GTX 970 GPU and a Ryzen 3700X 16 core CPU.
+For those interested, the code can be found below.
+For these benchmarks, we used Julia's inbuilt benchmarking suite from `BenchmarkTools`, making sure to sync the GPU kernels with `CUDA.@sync`.
+We also ran with $$4096^2$$ input points.
+
+Here, we see an interesting divergence in the results.
+On the CPU, the polar method is *always* faster, but on the GPU, both methods are comparable.
+I believe this is the most important lesson to be learned from the Box—Muller method: sometimes, no matter how hard you try to optimize your code, different hardware can provide radically different results!
+It's incredibly important to benchmark code to make sure it is actually is as performant as you think it is!
+
+## Full Script
+
+[import, lang:"julia"](code/julia/performance.jl)
+
+
+
+## License
+
+##### Code Examples
+
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
+
+##### Text
+
+The text of this chapter was written by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+[
](https://creativecommons.org/licenses/by-sa/4.0/)
+
diff --git a/contents/box_muller/code/julia/box_muller.jl b/contents/box_muller/code/julia/box_muller.jl
new file mode 100644
index 000000000..82f614bd6
--- /dev/null
+++ b/contents/box_muller/code/julia/box_muller.jl
@@ -0,0 +1,156 @@
+using DelimitedFiles, LinearAlgebra
+using Test
+
+function create_grid(n, endpoints)
+
+ grid_extents = endpoints[2] - endpoints[1]
+
+ # number of points along any given axis
+ # For 2D, we take the sqrt(n) and then round up
+ axis_num = ceil(Int, sqrt(n))
+
+ # we are now rounding n up to the nearest square if it was not already one
+ if sqrt(n) != axis_num
+ n = axis_num^2
+ end
+
+ # Distance between each point
+ dx = grid_extents / (axis_num)
+
+ # Initializing the array, particles along the column, dimensions along rows
+ a = zeros(n, 2)
+
+ # This loops over the relevant dimensions
+ for i = 1:axis_num
+ for j = 1:axis_num
+ a[(i - 1) * axis_num + j, :] .=
+ [(i - 0.5) * dx + endpoints[1],
+ (j - 0.5) * dx + endpoints[1]]
+ end
+ end
+
+ return a
+end
+
+function create_rand_dist(n, endpoints)
+ grid_extents = endpoints[2] - endpoints[1]
+ return(rand(n,2) * grid_extents .+ endpoints[1])
+end
+
+# This function reads in a pair of input points and performs the Cartesian
+# Box--Muller transform
+function cartesian_box_muller(input_pts, sigma, mu)
+ r = sqrt(-2 * log(input_pts[1]))
+ theta = 2 * pi * input_pts[2]
+
+ return [sigma * r * cos(theta) + mu[1],
+ sigma * r * sin(theta) + mu[2]]
+
+end
+
+# This function reads in a pair of input points and performs the Cartesian
+# Box--Muller transform
+function polar_box_muller(input_pts, sigma, mu)
+ r_0 = input_pts[1]^2 + input_pts[2]^2
+
+ # this method is only valid for points within the unit circle
+ if r_0 == 0 || r_0 > 1
+ return [NaN, NaN]
+ end
+
+ return [sigma * input_pts[1] * sqrt(-2 * log(r_0) / r_0) + mu[1],
+ sigma * input_pts[2] * sqrt(-2 * log(r_0) / r_0) + mu[2]]
+
+end
+
+function is_gaussian(input_pts; bounds = [-1 1; -1 1], dx = 0.1,
+ sigma = 1, mu = [0,0], threshold = 0.1)
+ histogram = zeros(ceil(Int,(bounds[1,2]-bounds[1,1])/dx),
+ ceil(Int,(bounds[2,2]-bounds[2,1])/dx))
+
+ for i = 1:size(input_pts)[1]
+ input_x = input_pts[i, 1]
+ input_y = input_pts[i, 2]
+ if !(isnan(input_x) || isnan(input_y))
+
+ bin = CartesianIndex(ceil(Int, (input_x - bounds[1,1]) / dx),
+ ceil(Int, (input_y - bounds[2,1]) / dx))
+
+ if bin[1] <= size(histogram)[1] && bin[1] > 0 &&
+ bin[2] <= size(histogram)[2] && bin[2] > 0
+ histogram[bin] += 1
+ end
+ end
+ end
+
+ n = sum(histogram)
+ normalize!(histogram)
+
+ rms = 0
+ for i = 1:size(histogram)[1]
+ x = bounds[1,1] + i*dx
+ for j = 1:size(histogram)[2]
+ y = bounds[2,1] + j*dx
+ gaussian_value = exp(-(((x+mu[1])^2)/(2*sigma^2) +
+ ((y+mu[2])^2)/(2*sigma^2)))
+ rms += (gaussian_value - histogram[i,j])^2
+ end
+ end
+
+ return sqrt(rms/n) < threshold
+end
+
+function main(n)
+
+ # This casts the input onto the nearest square for the cartesian grids
+ n = Int(ceil(sqrt(n))^2)
+
+ cartesian_grid = create_grid(n, [0,1])
+ polar_grid = create_grid(n, [-1,1])
+ cartesian_rand = create_rand_dist(n, [0,1])
+ polar_rand = create_rand_dist(n, [-1,1])
+
+ cartesian_grid_output = similar(cartesian_grid)
+ polar_grid_output = similar(polar_grid)
+ cartesian_rand_output = similar(cartesian_rand)
+ polar_rand_output = similar(polar_rand)
+
+ # going through each pair of points and using the x,y coordinates in
+ # their respective functions
+ for i = 1:size(cartesian_grid)[1]
+ cartesian_grid_output[i,:] .=
+ cartesian_box_muller(cartesian_grid[i,:], 1, [0,0])
+
+ polar_grid_output[i,:] .= polar_box_muller(polar_grid[i,:], 1, [0,0])
+
+ cartesian_rand_output[i,:] .=
+ cartesian_box_muller(cartesian_rand[i,:], 1, [0,0])
+
+ polar_rand_output[i,:] .= polar_box_muller(polar_rand[i,:], 1, [0,0])
+ end
+
+ @testset "histogram tests of Box--Muller Gaussianness" begin
+ @test is_gaussian(cartesian_grid_output;
+ bounds = [-3 3; -3 3], dx = 0.3,
+ sigma = 1, mu = [0,0])
+ @test is_gaussian(cartesian_rand_output;
+ bounds = [-3 3; -3 3], dx = 0.3,
+ sigma = 1, mu = [0,0])
+ @test is_gaussian(polar_grid_output;
+ bounds = [-3 3; -3 3], dx = 0.3,
+ sigma = 1, mu = [0,0])
+ @test is_gaussian(polar_rand_output;
+ bounds = [-3 3; -3 3], dx = 0.3,
+ sigma = 1, mu = [0,0])
+ end
+
+ writedlm("cartesian_grid_output.dat", cartesian_grid_output)
+ writedlm("polar_grid_output.dat", polar_grid_output)
+ writedlm("cartesian_rand_output.dat", cartesian_rand_output)
+ writedlm("polar_rand_output.dat", polar_rand_output)
+
+ writedlm("cartesian_grid.dat", cartesian_grid)
+ writedlm("polar_grid.dat", polar_grid)
+ writedlm("cartesian_rand.dat", cartesian_rand)
+ writedlm("polar_rand.dat", polar_rand)
+end
diff --git a/contents/box_muller/code/julia/performance.jl b/contents/box_muller/code/julia/performance.jl
new file mode 100644
index 000000000..d8732df33
--- /dev/null
+++ b/contents/box_muller/code/julia/performance.jl
@@ -0,0 +1,142 @@
+using KernelAbstractions
+using CUDA
+
+if has_cuda_gpu()
+ using CUDAKernels
+end
+
+function create_grid(n, endpoints; AT = Array)
+
+ grid_extents = endpoints[2] - endpoints[1]
+
+ # number of points along any given axis
+ # For 2D, we take the sqrt(n) and then round up
+ axis_num = ceil(Int, sqrt(n))
+
+ # we are now rounding n up to the nearest square if it was not already one
+ if sqrt(n) != axis_num
+ n = axis_num^2
+ end
+
+ # Distance between each point
+ dx = grid_extents / (axis_num)
+
+ # This is warning in the case that we do not have a square number
+ if sqrt(n) != axis_num
+ println("Cannot evenly divide ", n, " into 2 dimensions!")
+ end
+
+ # Initializing the array, particles along the column, dimensions along rows
+ a = AT(zeros(n, 2))
+
+ # This works by firxt generating an N dimensional tuple with the number
+ # of particles to be places along each dimension ((10,10) for 2D and n=100)
+ # Then we generate the list of all CartesianIndices and cast that onto a
+ # grid by multiplying by dx and subtracting grid_extents/2
+ for i = 1:axis_num
+ for j = 1:axis_num
+ a[(i - 1) * axis_num + j, 1] = i * dx + endpoints[1]
+ a[(i - 1) * axis_num + j, 2] = j * dx + endpoints[1]
+ end
+ end
+
+ return a
+end
+
+function create_rand_dist(n, endpoints; AT = Array)
+ grid_extents = endpoints[2] - endpoints[1]
+ return(AT(rand(n,2)) * grid_extents .+ endpoints[1])
+end
+
+# This function reads in a pair of input points and performs the Cartesian
+# Box--Muller transform
+@kernel function polar_muller_noreplacement!(input_pts, output_pts, sigma, mu)
+ tid = @index(Global, Linear)
+ @inbounds r_0 = input_pts[tid, 1]^2 + input_pts[tid, 2]^2
+
+ # this method is only valid for points within the unit circle
+ if r_0 == 0 || r_0 > 1
+ @inbounds output_pts[tid,1] = NaN
+ @inbounds output_pts[tid,2] = NaN
+ else
+ @inbounds output_pts[tid,1] = sigma * input_pts[tid,1] *
+ sqrt(-2 * log(r_0) / r_0) + mu
+ @inbounds output_pts[tid,2] = sigma * input_pts[tid, 2] *
+ sqrt(-2 * log(r_0) / r_0) + mu
+ end
+
+end
+
+@kernel function polar_muller_replacement!(input_pts, output_pts, sigma, mu)
+ tid = @index(Global, Linear)
+ @inbounds r_0 = input_pts[tid, 1]^2 + input_pts[tid, 2]^2
+
+ while r_0 > 1 || r_0 == 0
+ p1 = rand()*2-1
+ p2 = rand()*2-1
+ r_0 = p1^2 + p2^2
+ end
+
+ @inbounds output_pts[tid,1] = sigma * input_pts[tid,1] *
+ sqrt(-2 * log(r_0) / r_0) + mu
+ @inbounds output_pts[tid,2] = sigma * input_pts[tid, 2] *
+ sqrt(-2 * log(r_0) / r_0) + mu
+end
+
+
+function polar_box_muller!(input_pts, output_pts, sigma, mu;
+ numthreads = 256, numcores = 4,
+ f = polar_muller_noreplacement!)
+ if isa(input_pts, Array)
+ kernel! = f(CPU(), numcores)
+ else
+ kernel! = f(CUDADevice(), numthreads)
+ end
+ kernel!(input_pts, output_pts, sigma, mu, ndrange=size(input_pts)[1])
+end
+
+
+@kernel function cartesian_kernel!(input_pts, output_pts, sigma, mu)
+ tid = @index(Global, Linear)
+
+ @inbounds r = sqrt(-2 * log(input_pts[tid,1]))
+ @inbounds theta = 2 * pi * input_pts[tid, 2]
+
+ @inbounds output_pts[tid,1] = sigma * r * cos(theta) + mu
+ @inbounds output_pts[tid,2] = sigma * r * sin(theta) + mu
+end
+
+function cartesian_box_muller!(input_pts, output_pts, sigma, mu;
+ numthreads = 256, numcores = 4)
+ if isa(input_pts, Array)
+ kernel! = cartesian_kernel!(CPU(), numcores)
+ else
+ kernel! = cartesian_kernel!(CUDADevice(), numthreads)
+ end
+
+ kernel!(input_pts, output_pts, sigma, mu, ndrange=size(input_pts)[1])
+end
+
+function main()
+
+ input_pts = create_rand_dist(4096^2,[0,1])
+ output_pts = create_rand_dist(4096^2,[0,1])
+
+ wait(cartesian_box_muller!(input_pts, output_pts, 1, 0))
+ @time wait(cartesian_box_muller!(input_pts, output_pts, 1, 0))
+ wait(polar_box_muller!(input_pts, output_pts, 1, 0))
+ @time wait(polar_box_muller!(input_pts, output_pts, 1, 0))
+
+ if has_cuda_gpu()
+ input_pts = create_rand_dist(4096^2,[0,1], AT = CuArray)
+ output_pts = create_rand_dist(4096^2,[0,1], AT = CuArray)
+
+ wait(cartesian_box_muller!(input_pts, output_pts, 1, 0))
+ CUDA.@time wait(cartesian_box_muller!(input_pts, output_pts, 1, 0))
+ wait(polar_box_muller!(input_pts, output_pts, 1, 0))
+ CUDA.@time wait(polar_box_muller!(input_pts, output_pts, 1, 0))
+ end
+
+end
+
+main()
diff --git a/contents/box_muller/code/julia/plot.gp b/contents/box_muller/code/julia/plot.gp
new file mode 100644
index 000000000..7dbbf4808
--- /dev/null
+++ b/contents/box_muller/code/julia/plot.gp
@@ -0,0 +1,31 @@
+set terminal pngcairo
+set size square
+
+set output "cartesian_grid.png"
+p "cartesian_grid.dat" pt 7 title ""
+
+set output "cartesian_rand.png"
+p "cartesian_rand.dat" pt 7 title ""
+
+set output "polar_rand.png"
+p "polar_rand.dat" pt 7 title ""
+
+set output "polar_grid.png"
+p "polar_grid.dat" pt 7 title ""
+
+
+set xrange[-3:3]
+set yrange[-3:3]
+
+set output "polar_grid_output.png"
+p "polar_grid_output.dat" pt 7 title ""
+
+set output "polar_rand_output.png"
+p "polar_rand_output.dat" pt 7 title ""
+
+set output "cartesian_rand_output.png"
+p "cartesian_rand_output.dat" pt 7 title ""
+
+set output "cartesian_grid_output.png"
+p "cartesian_grid_output.dat" pt 7 title ""
+
diff --git a/contents/box_muller/res/cartesian_grid.png b/contents/box_muller/res/cartesian_grid.png
new file mode 100644
index 000000000..c96144a65
Binary files /dev/null and b/contents/box_muller/res/cartesian_grid.png differ
diff --git a/contents/box_muller/res/cartesian_grid_output.png b/contents/box_muller/res/cartesian_grid_output.png
new file mode 100644
index 000000000..daf0151af
Binary files /dev/null and b/contents/box_muller/res/cartesian_grid_output.png differ
diff --git a/contents/box_muller/res/cartesian_grid_transform.png b/contents/box_muller/res/cartesian_grid_transform.png
new file mode 100644
index 000000000..c5e88c484
Binary files /dev/null and b/contents/box_muller/res/cartesian_grid_transform.png differ
diff --git a/contents/box_muller/res/cartesian_grid_transform.xcf b/contents/box_muller/res/cartesian_grid_transform.xcf
new file mode 100644
index 000000000..b81accf3d
Binary files /dev/null and b/contents/box_muller/res/cartesian_grid_transform.xcf differ
diff --git a/contents/box_muller/res/cartesian_rand.png b/contents/box_muller/res/cartesian_rand.png
new file mode 100644
index 000000000..8c21b32d7
Binary files /dev/null and b/contents/box_muller/res/cartesian_rand.png differ
diff --git a/contents/box_muller/res/cartesian_rand_output.png b/contents/box_muller/res/cartesian_rand_output.png
new file mode 100644
index 000000000..3be2945ce
Binary files /dev/null and b/contents/box_muller/res/cartesian_rand_output.png differ
diff --git a/contents/box_muller/res/cartesian_rand_transform.png b/contents/box_muller/res/cartesian_rand_transform.png
new file mode 100644
index 000000000..08018bf34
Binary files /dev/null and b/contents/box_muller/res/cartesian_rand_transform.png differ
diff --git a/contents/box_muller/res/grid.png b/contents/box_muller/res/grid.png
new file mode 100644
index 000000000..bc4e80890
Binary files /dev/null and b/contents/box_muller/res/grid.png differ
diff --git a/contents/box_muller/res/polar_grid.png b/contents/box_muller/res/polar_grid.png
new file mode 100644
index 000000000..36088f773
Binary files /dev/null and b/contents/box_muller/res/polar_grid.png differ
diff --git a/contents/box_muller/res/polar_grid_output.png b/contents/box_muller/res/polar_grid_output.png
new file mode 100644
index 000000000..5fb774e3f
Binary files /dev/null and b/contents/box_muller/res/polar_grid_output.png differ
diff --git a/contents/box_muller/res/polar_grid_transform.png b/contents/box_muller/res/polar_grid_transform.png
new file mode 100644
index 000000000..1335cf06a
Binary files /dev/null and b/contents/box_muller/res/polar_grid_transform.png differ
diff --git a/contents/box_muller/res/polar_rand.png b/contents/box_muller/res/polar_rand.png
new file mode 100644
index 000000000..e4ff7ac58
Binary files /dev/null and b/contents/box_muller/res/polar_rand.png differ
diff --git a/contents/box_muller/res/polar_rand_output.png b/contents/box_muller/res/polar_rand_output.png
new file mode 100644
index 000000000..52944893f
Binary files /dev/null and b/contents/box_muller/res/polar_rand_output.png differ
diff --git a/contents/box_muller/res/polar_rand_transform.png b/contents/box_muller/res/polar_rand_transform.png
new file mode 100644
index 000000000..aeefa3e4d
Binary files /dev/null and b/contents/box_muller/res/polar_rand_transform.png differ
diff --git a/contents/box_muller/res/rand100.png b/contents/box_muller/res/rand100.png
new file mode 100644
index 000000000..5a09a248a
Binary files /dev/null and b/contents/box_muller/res/rand100.png differ
diff --git a/contents/box_muller/res/rand1000.png b/contents/box_muller/res/rand1000.png
new file mode 100644
index 000000000..94609737d
Binary files /dev/null and b/contents/box_muller/res/rand1000.png differ
diff --git a/contents/box_muller/res/rand10000.png b/contents/box_muller/res/rand10000.png
new file mode 100644
index 000000000..62adeaa1f
Binary files /dev/null and b/contents/box_muller/res/rand10000.png differ
diff --git a/contents/box_muller/res/rand_dist.png b/contents/box_muller/res/rand_dist.png
new file mode 100644
index 000000000..d56d8f588
Binary files /dev/null and b/contents/box_muller/res/rand_dist.png differ
diff --git a/contents/box_muller/res/right_arrow.pdf b/contents/box_muller/res/right_arrow.pdf
new file mode 100644
index 000000000..9105474fa
Binary files /dev/null and b/contents/box_muller/res/right_arrow.pdf differ
diff --git a/contents/box_muller/res/warp_divergence.png b/contents/box_muller/res/warp_divergence.png
new file mode 100644
index 000000000..7b385b82c
Binary files /dev/null and b/contents/box_muller/res/warp_divergence.png differ
diff --git a/contents/cc/license.txt b/contents/cc/license.txt
index e9c662f91..1e11bba93 100644
--- a/contents/cc/license.txt
+++ b/contents/cc/license.txt
@@ -3,7 +3,7 @@
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/chans_algorithm/chans_algorithm.md b/contents/chans_algorithm/chans_algorithm.md
index 62e125114..18daaa889 100644
--- a/contents/chans_algorithm/chans_algorithm.md
+++ b/contents/chans_algorithm/chans_algorithm.md
@@ -10,7 +10,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/choosing_a_language/choosing_a_language.md b/contents/choosing_a_language/choosing_a_language.md
index 88ad8c986..5385c309a 100644
--- a/contents/choosing_a_language/choosing_a_language.md
+++ b/contents/choosing_a_language/choosing_a_language.md
@@ -73,7 +73,7 @@ Please let me know which languages you want to cover and I'll add them here!
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/code_reviews/code_reviewers.md b/contents/code_reviews/code_reviewers.md
new file mode 100644
index 000000000..e2fd22b0a
--- /dev/null
+++ b/contents/code_reviews/code_reviewers.md
@@ -0,0 +1,70 @@
+# Code Reviewers
+
+If you are comfortable reviewing a language, please add yourself to the table below:
+
+[//]: # (To add yourself to the table, please add a link at the bottom of the article and reference yourself in the following format next to each language [@username]. If there are multiple usernames for a language, make sure to seperate them with commas)
+
+Language | Reviewers
+-|-
+asm-x64 |
+bash |
+c | [@amaras]
+c# |
+clojure |
+coconut | [@amaras]
+c++ | [@ShadowMitia]
+crystal |
+D |
+dart |
+elm |
+emojicode |
+factor |
+fortran | [@leios]
+gnuplot | [@leios]
+go |
+haskell |
+java |
+javascript | [@ntindle],[@ShadowMitia]
+julia | [@leios]
+kotlin |
+labview |
+lolcode |
+lisp |
+lua |
+matlab |
+nim |
+ocaml | [@ShadowMitia]
+php |
+piet |
+powershell |
+python | [@ntindle],[@ShadowMitia],[@amaras],[@PeanutbutterWarrior]
+r |
+racket |
+ruby |
+rust | [@ShadowMitia],[@PeanutbutterWarrior]
+scala |
+scheme |
+scratch | [@leios]
+smalltask |
+swift |
+typescript | [@ntindle]
+v |
+viml |
+whitespace |
+
+If you are comfortable reviewing a toolchain change, please add yourself to the list below:
+
+Feature | Reviewers
+-|-
+Dev Container | [@ntindle], [@ShadowMitia]
+Docker | [@ntindle], [@ShadowMitia]
+Github Actions | [@ntindle]
+Honkit |
+Scons | [@amaras],[@PeanutbutterWarrior]
+Chapters | [@leios]
+
+[@leios]: https://github.com/leios
+[@ntindle]: https://github.com/ntindle
+[@amaras]: https://github.com/amaras
+[@ShadowMitia]: https://github.com/ShadowMitia
+[@PeanutbutterWarrior]: https://github.com/PeanutbutterWarrior
diff --git a/contents/compiled_languages/compiled_languages.md b/contents/compiled_languages/compiled_languages.md
index 3f6424359..b8bac2e75 100644
--- a/contents/compiled_languages/compiled_languages.md
+++ b/contents/compiled_languages/compiled_languages.md
@@ -35,7 +35,7 @@ I just find it easier to avoid GUI's whenever possible.
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/computational_geometry/computational_geometry.md b/contents/computational_geometry/computational_geometry.md
index a99c0a4e9..bcd702fd7 100644
--- a/contents/computational_geometry/computational_geometry.md
+++ b/contents/computational_geometry/computational_geometry.md
@@ -12,7 +12,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/computus/code/c++/gauss_easter.cpp b/contents/computus/code/cpp/gauss_easter.cpp
similarity index 100%
rename from contents/computus/code/c++/gauss_easter.cpp
rename to contents/computus/code/cpp/gauss_easter.cpp
diff --git a/contents/computus/code/dart/gauss_easter.dart b/contents/computus/code/dart/gauss_easter.dart
new file mode 100644
index 000000000..ab48aab20
--- /dev/null
+++ b/contents/computus/code/dart/gauss_easter.dart
@@ -0,0 +1,63 @@
+String computus(int year, {bool servois = false}) {
+ // Year's position in metonic cycle
+ final a = year % 19;
+
+ // Century index
+ final k = (year / 100).floor();
+
+ // Shift of metonic cycle, add a day offset every 300 years
+ final p = ((13 + 8 * k) / 25).floor();
+
+ // Correction for non-observed leap days
+ final q = (k / 4).floor();
+
+ // Correction to starting point of calculation each century
+ final M = (15 - p + k - q) % 30;
+
+ // Number of days from March 21st until the full moon
+ final d = (19 * a + M) % 30;
+
+ // Returning if user wants value for Servois' table
+ if (servois) {
+ return ((21 + d) % 31).toString();
+ }
+
+ // Finding the next Sunday
+ // Century-based offset in weekly calculation
+ final N = (4 + k - q) % 7;
+
+ // Correction for leap days
+ final b = year % 4;
+ final c = year % 7;
+
+ // Days from d to next Sunday
+ var e = (2 * b + 4 * c + 6 * d + N) % 7;
+
+ // Historical corrections for April 26 and 25
+ if (e == 6) {
+ if (d == 29 || (d == 28 && a > 10)) {
+ e = -1;
+ }
+ }
+
+ // Determination of the correct month for Easter
+ if (22 + d + e > 31) {
+ return 'April ${d + e - 9}';
+ } else {
+ return 'March ${22 + d + e}';
+ }
+}
+
+void main() {
+ print("The following are the dates of the Paschal full moon (using Servois " +
+ "notation) and the date of Easter for 2020-2030 AD:");
+
+ print("Year\tServois number\tEaster");
+
+ for (var year = 2020; year <= 2030; year++) {
+ final servoisNumber = computus(year, servois: true);
+ final easterDate = computus(year);
+
+ print('$year\t$servoisNumber\t\t$easterDate');
+ }
+}
diff --git a/contents/computus/code/javascript/gauss_easter.js b/contents/computus/code/javascript/gauss_easter.js
new file mode 100644
index 000000000..f413644f5
--- /dev/null
+++ b/contents/computus/code/javascript/gauss_easter.js
@@ -0,0 +1,91 @@
+/**
+ * In this code, the modulus operator is used.
+ * However, this operator in javascript/typescript doesn't support negative numbers.
+ * So, where there may be negative numbers, the function mod is used.
+ * This function gives the modulo of any relative number a
+ */
+
+/**
+ * @param {number} a
+ * @param {number} b
+ * @returns {number}
+ */
+function mod(a, b) {
+ if (a < 0) return mod(a + b, b);
+ else return a % b;
+}
+
+/**
+ * @param {number} year
+ * @param {boolean} [servois=false]
+ * @returns {string}
+ */
+function computus(year, servois = false) {
+ // Year's position in metonic cycle
+ const a = year % 19;
+
+ // Century index
+ const k = Math.floor(year / 100);
+
+ // Shift of metonic cycle, add a day offset every 300 years
+ const p = Math.floor((13 + 8 * k) / 25);
+
+ // Correction for non-observed leap days
+ const q = Math.floor(k / 4);
+
+ // Correction to starting point of calculation each century
+ const M = mod(15 - p + k - q, 30);
+
+ // Number of days from March 21st until the full moon
+ const d = (19 * a + M) % 30;
+
+ // Returning if user wants value for Servois' table
+ if (servois) {
+ return ((21 + d) % 31).toString();
+ }
+
+ // Finding the next Sunday
+ // Century-based offset in weekly calculation
+ const N = mod(4 + k - q, 7);
+
+ // Correction for leap days
+ const b = year % 4;
+ const c = year % 7;
+
+ // Days from d to next Sunday
+ let e = (2 * b + 4 * c + 6 * d + N) % 7;
+
+ // Historical corrections for April 26 and 25
+ if (e === 6) {
+ if (d === 29 || (d === 28 && a > 10)) {
+ e = -1;
+ }
+ }
+
+ // Determination of the correct month for Easter
+ if (22 + d + e > 31) {
+ return `April ${d + e - 9}`;
+ } else {
+ return `March ${22 + d + e}`;
+ }
+}
+
+console.log(
+ "The following are the dates of the Paschal full moon (using Servois " +
+ "notation) and the date of Easter for 2020-2030 AD:"
+);
+
+const values = [];
+
+for (let year = 2020; year <= 2030; year++) {
+ const servoisNumber = computus(year, true);
+ const easterDate = computus(year);
+
+ // Creation of an object to be displayed as a line in the output table
+ values[year] = {
+ "servois number": +servoisNumber,
+ easter: easterDate,
+ };
+}
+
+console.table(values);
diff --git a/contents/computus/code/scala/gauss_easter.scala b/contents/computus/code/scala/gauss_easter.scala
new file mode 100644
index 000000000..01f5a4c30
--- /dev/null
+++ b/contents/computus/code/scala/gauss_easter.scala
@@ -0,0 +1,58 @@
+object GaussEaster {
+ def computus(year : Int, servois: Boolean = false): String = {
+
+ // Year's position on the 19 year metonic cycle
+ val a = year % 19
+
+ // Century index
+ val k = (year / 100).toInt
+
+ // Shift of metonic cycle, add a day offset every 300 years
+ val p = ((13 + 8 * k) / 25).toInt
+
+ // Correction for non-observed leap days
+ val q = (k / 4).toInt
+
+ // Correction to starting point of calculation each century
+ val M = (15 - p + k - q) % 30
+
+ // Number of days from March 21st until the full moon
+ val d = (19 * a + M) % 30
+
+ // Returning if user wants value for Servois' table
+ if (servois)
+ return s"${(21 + d) % 31}"
+
+ // Finding the next Sunday
+ // Century-based offset in weekly calculation
+ val N = (4 + k - q) % 7
+
+ // Correction for leap days
+ val b = year % 4
+ val c = year % 7
+
+ // Days from d to next Sunday
+ var e = (2 * b + 4 * c + 6 * d + N) % 7
+
+ // Historical corrections for April 26 and 25
+ if ((d == 29 && e == 6) || (d == 28 && e == 6 && a > 10)) {
+ e = -1
+ }
+
+ // Determination of the correct month for Easter
+ if (22 + d + e > 31)
+ s"April ${d + e - 9}"
+ else
+ s"March ${22 + d + e}"
+ }
+
+ def main(args: Array[String]): Unit = {
+ println("The following are the dates of the Paschal full moon (using " +
+ "Servois notation) and the date of Easter for 2020-2030 AD:\n" +
+ "Year\tServois number\tEaster\n")
+
+ for( year <- 2020 to 2030){
+ println(s"$year \t\t ${computus(year, true)} \t${computus(year)}")
+ }
+ }
+}
\ No newline at end of file
diff --git a/contents/computus/code/typescript/gauss_easter.ts b/contents/computus/code/typescript/gauss_easter.ts
new file mode 100644
index 000000000..789b9bd7e
--- /dev/null
+++ b/contents/computus/code/typescript/gauss_easter.ts
@@ -0,0 +1,91 @@
+/**
+ * In this code, the modulus operator is used.
+ * However, this operator in javascript/typescript doesn't support negative numbers.
+ * So, where there may be negative numbers, the function mod is used.
+ * This function gives the modulo of any relative number a
+ */
+
+function mod(a: number, b: number): number {
+ if (a < 0) {
+ return mod(a + b, b);
+ } else {
+ return a % b;
+ }
+}
+function computus(year: number, servois: boolean = false): string {
+ // Year's position in metonic cycle
+ const a: number = year % 19;
+
+ // Century index
+ const k: number = Math.floor(year / 100);
+
+ // Shift of metonic cycle, add a day offset every 300 years
+ const p: number = Math.floor((13 + 8 * k) / 25);
+
+ // Correction for non-observed leap days
+ const q: number = Math.floor(k / 4);
+
+ // Correction to starting point of calculation each century
+ const M: number = mod(15 - p + k - q, 30);
+
+ // Number of days from March 21st until the full moon
+ const d: number = (19 * a + M) % 30;
+
+ // Returning if user wants value for Servois' table
+ if (servois) {
+ return ((21 + d) % 31).toString();
+ }
+
+ // Finding the next Sunday
+ // Century-based offset in weekly calculation
+ const N: number = mod(4 + k - q, 7);
+
+ // Correction for leap days
+ const b: number = year % 4;
+ const c: number = year % 7;
+
+ // Days from d to next Sunday
+ let e: number = (2 * b + 4 * c + 6 * d + N) % 7;
+
+ // Historical corrections for April 26 and 25
+ if (e === 6) {
+ if (d === 29 || (d === 28 && a > 10)) {
+ e = -1;
+ }
+ }
+
+ // Determination of the correct month for Easter
+ if (22 + d + e > 31) {
+ return `April ${d + e - 9}`;
+ } else {
+ return `March ${22 + d + e}`;
+ }
+}
+
+console.log(
+ "The following are the dates of the Paschal full moon (using Servois " +
+ "notation) and the date of Easter for 2020-2030 AD:"
+);
+
+// Type of a line in the output table
+interface IOutputLine {
+ "servois number": number;
+ easter: string;
+}
+
+const values: IOutputLine[] = [];
+
+for (let year = 2020; year <= 2030; year++) {
+ const servoisNumber: string = computus(year, true);
+ const easterDate: string = computus(year);
+
+ // Creation of an object to be displayed as a line in the output table
+ const line: IOutputLine = {
+ "servois number": +servoisNumber,
+ easter: easterDate,
+ };
+
+ values[year] = line;
+}
+
+console.table(values);
diff --git a/contents/computus/computus.md b/contents/computus/computus.md
index 6be87f2f6..1eeec678d 100644
--- a/contents/computus/computus.md
+++ b/contents/computus/computus.md
@@ -291,7 +291,7 @@ Sure, this can be done straightforwardly with a calculator, but it is no doubt a
Here is a video describing key elements of Gauss's Easter Algorithm:
-
+
## Example Code
@@ -315,11 +315,19 @@ For now, we have the code outputting a tuple of $$d$$ and $$e$$, so users can us
{% sample lang="c" %}
[import, lang:"c"](code/c/gauss_easter.c)
{% sample lang="cpp" %}
-[import, lang:"cpp"](code/c++/gauss_easter.cpp)
+[import, lang:"cpp"](code/cpp/gauss_easter.cpp)
{% sample lang="lisp" %}
[import, lang:"lisp"](code/clisp/gauss-easter.lisp)
{% sample lang="nim" %}
[import, lang:"nim"](code/nim/gauss_easter.nim)
+{% sample lang="scala" %}
+[import, lang:"scala"](code/scala/gauss_easter.scala)
+{% sample lang="dart" %}
+[import, lang:"dart"](code/dart/gauss_easter.dart)
+{% sample lang="javascript" %}
+[import, lang:"javascript"](code/javascript/gauss_easter.js)
+{% sample lang="typescript" %}
+[import, lang:"typescript"](code/typescript/gauss_easter.ts)
{% endmethod %}
@@ -335,7 +343,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/convolutions/1d/1d.md b/contents/convolutions/1d/1d.md
index 3a3ca0cf6..ecf56a1df 100644
--- a/contents/convolutions/1d/1d.md
+++ b/contents/convolutions/1d/1d.md
@@ -53,7 +53,11 @@ With this in mind, we can almost directly transcribe the discrete equation into
{% method %}
{% sample lang="jl" %}
-[import:29-48, lang:"julia"](../code/julia/1d_convolution.jl)
+[import:27-46, lang:"julia"](code/julia/1d_convolution.jl)
+{% sample lang="cs" %}
+[import:63-84, lang:"csharp"](code/csharp/1DConvolution.cs)
+{% sample lang="py" %}
+[import:20-31, lang:"python"](code/python/1d_convolution.py)
{% endmethod %}
The easiest way to reason about this code is to read it as you might read a textbook.
@@ -184,7 +188,11 @@ Here it is again for clarity:
{% method %}
{% sample lang="jl" %}
-[import:29-48, lang:"julia"](../code/julia/1d_convolution.jl)
+[import:27-46, lang:"julia"](code/julia/1d_convolution.jl)
+{% sample lang="cs" %}
+[import:63-84, lang:"csharp"](code/csharp/1DConvolution.cs)
+{% sample lang="py" %}
+[import:20-31, lang:"python"](code/python/1d_convolution.py)
{% endmethod %}
Here, the main difference between the bounded and unbounded versions is that the output array size is smaller in the bounded case.
@@ -192,14 +200,22 @@ For an unbounded convolution, the function would be called with a the output arr
{% method %}
{% sample lang="jl" %}
-[import:60-61, lang:"julia"](../code/julia/1d_convolution.jl)
+[import:58-59, lang:"julia"](code/julia/1d_convolution.jl)
+{% sample lang="cs" %}
+[import:96-97, lang:"csharp"](code/csharp/1DConvolution.cs)
+{% sample lang="py" %}
+[import:41-42, lang:"python"](code/python/1d_convolution.py)
{% endmethod %}
On the other hand, the bounded call would set the output array size to simply be the length of the signal
{% method %}
{% sample lang="jl" %}
-[import:63-64, lang:"julia"](../code/julia/1d_convolution.jl)
+[import:61-62, lang:"julia"](code/julia/1d_convolution.jl)
+{% sample lang="cs" %}
+[import:98-99, lang:"csharp"](code/csharp/1DConvolution.cs)
+{% sample lang="py" %}
+[import:44-45, lang:"python"](code/python/1d_convolution.py)
{% endmethod %}
Finally, as we mentioned before, it is possible to center bounded convolutions by changing the location where we calculate the each point along the filter.
@@ -207,7 +223,11 @@ This can be done by modifying the following line:
{% method %}
{% sample lang="jl" %}
-[import:37-37, lang:"julia"](../code/julia/1d_convolution.jl)
+[import:35-35, lang:"julia"](code/julia/1d_convolution.jl)
+{% sample lang="cs" %}
+[import:71-71, lang:"csharp"](code/csharp/1DConvolution.cs)
+{% sample lang="py" %}
+[import:25-25, lang:"python"](code/python/1d_convolution.py)
{% endmethod %}
Here, `j` counts from `i-length(filter)` to `i`.
@@ -239,7 +259,11 @@ In code, this typically amounts to using some form of modulus operation, as show
{% method %}
{% sample lang="jl" %}
-[import:4-27, lang:"julia"](../code/julia/1d_convolution.jl)
+[import:4-25, lang:"julia"](code/julia/1d_convolution.jl)
+{% sample lang="cs" %}
+[import:38-61, lang:"csharp"](code/csharp/1DConvolution.cs)
+{% sample lang="py" %}
+[import:5-17, lang:"python"](code/python/1d_convolution.py)
{% endmethod %}
This is essentially the same as before, except for the modulus operations, which allow us to work on a periodic domain.
@@ -254,7 +278,11 @@ For the code associated with this chapter, we have used the convolution to gener
{% method %}
{% sample lang="jl" %}
-[import, lang:"julia"](../code/julia/1d_convolution.jl)
+[import, lang:"julia"](code/julia/1d_convolution.jl)
+{% sample lang="cs" %}
+[import, lang:"csharp"](code/csharp/1DConvolution.cs)
+{% sample lang="py" %}
+[import, lang:"python"](code/python/1d_convolution.py)
{% endmethod %}
At a test case, we have chosen to use two sawtooth functions, which should produce the following images:
@@ -276,7 +304,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Images/Graphics
- The image "[Square Wave](../res/square_wave.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
diff --git a/contents/convolutions/1d/code/csharp/1DConvolution.cs b/contents/convolutions/1d/code/csharp/1DConvolution.cs
new file mode 100755
index 000000000..c4c1016c6
--- /dev/null
+++ b/contents/convolutions/1d/code/csharp/1DConvolution.cs
@@ -0,0 +1,110 @@
+using System;
+using System.IO;
+
+namespace Convolution1D
+{
+ public class Convolution1D
+ {
+ // Creates a sawtooth function with the given length.
+ static double[] CreateSawtooth(int length)
+ {
+ var array = new double[length];
+ for (var i = 0; i < length; i++)
+ array[i] = (i + 1) / 200f;
+ return array;
+ }
+
+ // Normalizes the given array.
+ static void Normalize(double[] array)
+ {
+ var norm = Norm(array);
+ for (var i = 0; i < array.Length; i++)
+ array[i] /= norm;
+ }
+
+ // Calculates the norm of the array.
+ static double Norm(double[] array)
+ {
+ var sum = 0.0;
+ for (var i = 0; i < array.Length; i++)
+ sum += Math.Pow(array[i], 2);
+ return Math.Sqrt(sum);
+ }
+
+ // Modulus function which handles negative values properly.
+ // Assumes that y >= 0.
+ static int Mod(int x, int y) => ((x % y) + y) % y;
+
+ static double[] ConvolveCyclic(double[] signal, double[] filter)
+ {
+ var outputSize = Math.Max(signal.Length, filter.Length);
+
+ // Convolutional output.
+ var output = new double[outputSize];
+ var sum = 0.0;
+
+ for (var i = 0; i < outputSize; i++)
+ {
+ for (var j = 0; j < outputSize; j++)
+ {
+ if (Mod(i - j, outputSize) < filter.Length)
+ {
+ sum += signal[Mod(j - 1, outputSize)] * filter[Mod(i - j, outputSize)];
+ }
+ }
+
+ output[i] = sum;
+ sum = 0.0;
+ }
+
+ return output;
+ }
+
+ static double[] ConvolveLinear(double[] signal, double[] filter, int outputSize)
+ {
+ // Convolutional output.
+ var output = new double[outputSize];
+ var sum = 0.0;
+
+ for (var i = 0; i < outputSize; i++)
+ {
+ for (var j = Math.Max(0, i - filter.Length); j <= i; j++)
+ {
+ if (j < signal.Length && (i - j) < filter.Length)
+ {
+ sum += signal[j] * filter[i - j];
+ }
+ }
+
+ output[i] = sum;
+ sum = 0.0;
+ }
+
+ return output;
+ }
+
+ static void Main()
+ {
+ // Create sawtooth functions for x and y.
+ var x = CreateSawtooth(200);
+ var y = CreateSawtooth(200);
+
+ // Normalization is not strictly necessary, but good practice.
+ Normalize(x);
+ Normalize(y);
+
+ // Full convolution, output will be the size of x + y - 1.
+ var fullLinearOutput = ConvolveLinear(x, y, x.Length + y.Length - 1);
+ // Simple boundaries.
+ var simpleLinearOutput = ConvolveLinear(x, y, x.Length);
+ // Cyclic convolution.
+ var cyclicOutput = ConvolveCyclic(x, y);
+
+ // Output convolutions to different files for plotting.
+ File.WriteAllText("full_linear.dat", String.Join(Environment.NewLine, fullLinearOutput));
+ File.WriteAllText("simple_linear.dat", String.Join(Environment.NewLine, simpleLinearOutput));
+ File.WriteAllText("cyclic.dat", String.Join(Environment.NewLine, cyclicOutput));
+ }
+ }
+}
+
diff --git a/contents/convolutions/code/julia/1d_convolution.jl b/contents/convolutions/1d/code/julia/1d_convolution.jl
similarity index 88%
rename from contents/convolutions/code/julia/1d_convolution.jl
rename to contents/convolutions/1d/code/julia/1d_convolution.jl
index 78dafc0ed..0019c2496 100644
--- a/contents/convolutions/code/julia/1d_convolution.jl
+++ b/contents/convolutions/1d/code/julia/1d_convolution.jl
@@ -13,9 +13,7 @@ function convolve_cyclic(signal::Array{T, 1},
for i = 1:output_size
for j = 1:output_size
- if (mod1(i-j, output_size) <= length(filter))
- sum += signal[mod1(j, output_size)] * filter[mod1(i-j, output_size)]
- end
+ sum += get(signal, mod1(j, output_size), 0) * get(filter, mod1(i-j, output_size), 0)
end
out[i] = sum
@@ -57,8 +55,8 @@ function main()
normalize!(x)
normalize!(y)
- # full convolution, output will be the size of x + y
- full_linear_output = convolve_linear(x, y, length(x) + length(y))
+ # full convolution, output will be the size of x + y - 1
+ full_linear_output = convolve_linear(x, y, length(x) + length(y) - 1)
# simple boundaries
simple_linear_output = convolve_linear(x, y, length(x))
diff --git a/contents/convolutions/1d/code/python/1d_convolution.py b/contents/convolutions/1d/code/python/1d_convolution.py
new file mode 100644
index 000000000..e77e68d09
--- /dev/null
+++ b/contents/convolutions/1d/code/python/1d_convolution.py
@@ -0,0 +1,53 @@
+import numpy as np
+
+def mod1(x, y): return ((x % y) + y) % y
+
+def convolve_cyclic(signal, filter_array):
+ output_size = max(len(signal), len(filter_array))
+ out = np.zeros(output_size)
+ s = 0
+
+ for i in range(output_size):
+ for j in range(output_size):
+ if(mod1(i - j, output_size) < len(filter_array)):
+ s += signal[mod1(j - 1, output_size)] * filter_array[mod1(i - j, output_size)]
+ out[i] = s
+ s = 0
+
+ return out
+
+
+def convolve_linear(signal, filter_array, output_size):
+ out = np.zeros(output_size)
+ s = 0
+
+ for i in range(output_size):
+ for j in range(max(0, i - len(filter_array)), i + 1):
+ if j < len(signal) and (i - j) < len(filter_array):
+ s += signal[j] * filter_array[i - j]
+ out[i] = s
+ s = 0
+
+ return out
+
+# sawtooth functions for x and y
+x = [float(i + 1)/200 for i in range(200)]
+y = [float(i + 1)/200 for i in range(200)]
+
+# Normalization is not strictly necessary, but good practice
+x /= np.linalg.norm(x)
+y /= np.linalg.norm(y)
+
+# full convolution, output will be the size of x + y - 1
+full_linear_output = convolve_linear(x, y, len(x) + len(y) - 1)
+
+# simple boundaries
+simple_linear_output = convolve_linear(x, y, len(x))
+
+# cyclic convolution
+cyclic_output = convolve_cyclic(x, y)
+
+# outputting convolutions to different files for plotting in external code
+np.savetxt('full_linear.dat', full_linear_output)
+np.savetxt('simple_linear.dat', simple_linear_output)
+np.savetxt('cyclic.dat', cyclic_output)
diff --git a/contents/convolutions/2d/2d.md b/contents/convolutions/2d/2d.md
index d026c8a52..e2cace847 100644
--- a/contents/convolutions/2d/2d.md
+++ b/contents/convolutions/2d/2d.md
@@ -20,7 +20,9 @@ In code, a two-dimensional convolution might look like this:
{% method %}
{% sample lang="jl" %}
-[import:4-28, lang:"julia"](../code/julia/2d_convolution.jl)
+[import:4-28, lang:"julia"](code/julia/2d_convolution.jl)
+{% sample lang="py" %}
+[import:5-19, lang:"python"](code/python/2d_convolution.py)
{% endmethod %}
This is very similar to what we have shown in previous sections; however, it essentially requires four iterable dimensions because we need to iterate through each axis of the output domain *and* the filter.
@@ -47,7 +49,9 @@ At this stage, it is important to write some code, so we will generate a simple
{% method %}
{% sample lang="jl" %}
-[import:30-47, lang:"julia"](../code/julia/2d_convolution.jl)
+[import:30-47, lang:"julia"](code/julia/2d_convolution.jl)
+{% sample lang="py" %}
+[import:21-33, lang:"python"](code/python/2d_convolution.py)
{% endmethod %}
Though it is entirely possible to create a Gaussian kernel whose standard deviation is independent on the kernel size, we have decided to enforce a relation between the two in this chapter.
@@ -134,7 +138,9 @@ In code, the Sobel operator involves first finding the operators in $$x$$ and $$
{% method %}
{% sample lang="jl" %}
-[import:49-63, lang:"julia"](../code/julia/2d_convolution.jl)
+[import:49-63, lang:"julia"](code/julia/2d_convolution.jl)
+{% sample lang="py" %}
+[import:36-52, lang:"python"](code/python/2d_convolution.py)
{% endmethod %}
With that, I believe we are at a good place to stop discussions on two-dimensional convolutions.
@@ -147,7 +153,9 @@ We have also added code to create the Gaussian kernel and Sobel operator and app
{% method %}
{% sample lang="jl" %}
-[import, lang:"julia"](../code/julia/2d_convolution.jl)
+[import, lang:"julia"](code/julia/2d_convolution.jl)
+{% sample lang="py" %}
+[import, lang:"python"](code/python/2d_convolution.py)
{% endmethod %}
@@ -52,7 +62,12 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
+
+##### Images/Graphics
+
+- The image "[Cyclic](../res/cyclic.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
##### Text
diff --git a/contents/convolutions/res/Sobel_filters.png b/contents/convolutions/res/Sobel_filters.png
deleted file mode 100644
index 7dbd105b9..000000000
Binary files a/contents/convolutions/res/Sobel_filters.png and /dev/null differ
diff --git a/contents/cooley_tukey/code/asm-x64/SConscript b/contents/cooley_tukey/code/asm-x64/SConscript
new file mode 100644
index 000000000..2a10fbc14
--- /dev/null
+++ b/contents/cooley_tukey/code/asm-x64/SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.X64(build_target, str(file_info.path), LIBS='m', LINKFLAGS='-no-pie')
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/contents/cooley_tukey/code/c/SConscript b/contents/cooley_tukey/code/c/SConscript
new file mode 100644
index 000000000..bb40f4a85
--- /dev/null
+++ b/contents/cooley_tukey/code/c/SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.C(build_target, str(file_info.path), LIBS=['m', 'fftw3'])
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/contents/cooley_tukey/code/c/fft.c b/contents/cooley_tukey/code/c/fft.c
index 90691f373..212b272b1 100644
--- a/contents/cooley_tukey/code/c/fft.c
+++ b/contents/cooley_tukey/code/c/fft.c
@@ -6,12 +6,12 @@
#include
#include
-void fft(double complex *x, int n) {
+void fft(double complex *x, size_t n) {
double complex y[n];
memset(y, 0, sizeof(y));
fftw_plan p;
- p = fftw_plan_dft_1d(n, (fftw_complex*)x, (fftw_complex*)y,
+ p = fftw_plan_dft_1d((int)n, (fftw_complex*)x, (fftw_complex*)y,
FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(p);
@@ -27,7 +27,7 @@ void dft(double complex *X, const size_t N) {
for (size_t i = 0; i < N; ++i) {
tmp[i] = 0;
for (size_t j = 0; j < N; ++j) {
- tmp[i] += X[j] * cexp(-2.0 * M_PI * I * j * i / N);
+ tmp[i] += X[j] * cexp(-2.0 * M_PI * I * (double)j * (double)i / (double)N);
}
}
@@ -49,16 +49,16 @@ void cooley_tukey(double complex *X, const size_t N) {
cooley_tukey(X + N / 2, N / 2);
for (size_t i = 0; i < N / 2; ++i) {
- X[i + N / 2] = X[i] - cexp(-2.0 * I * M_PI * i / N) * X[i + N / 2];
+ X[i + N / 2] = X[i] - cexp(-2.0 * I * M_PI * (double)i / (double)N) * X[i + N / 2];
X[i] -= (X[i + N / 2]-X[i]);
}
}
}
void bit_reverse(double complex *X, size_t N) {
- for (int i = 0; i < N; ++i) {
- int n = i;
- int a = i;
+ for (size_t i = 0; i < N; ++i) {
+ size_t n = i;
+ size_t a = i;
int count = (int)log2((double)N) - 1;
n >>= 1;
@@ -67,7 +67,7 @@ void bit_reverse(double complex *X, size_t N) {
count--;
n >>= 1;
}
- n = (a << count) & ((1 << (int)log2((double)N)) - 1);
+ n = (a << count) & (size_t)((1 << (size_t)log2((double)N)) - 1);
if (n > i) {
double complex tmp = X[i];
@@ -81,8 +81,8 @@ void iterative_cooley_tukey(double complex *X, size_t N) {
bit_reverse(X, N);
for (int i = 1; i <= log2((double)N); ++i) {
- int stride = pow(2, i);
- double complex w = cexp(-2.0 * I * M_PI / stride);
+ size_t stride = (size_t)pow(2, i);
+ double complex w = cexp(-2.0 * I * M_PI / (double)stride);
for (size_t j = 0; j < N; j += stride) {
double complex v = 1.0;
for (size_t k = 0; k < stride / 2; ++k) {
@@ -105,7 +105,7 @@ void approx(double complex *X, double complex *Y, size_t N) {
}
int main() {
- srand(time(NULL));
+ srand((unsigned int)time(NULL));
double complex x[64], y[64], z[64];
for (size_t i = 0; i < 64; ++i) {
x[i] = rand() / (double) RAND_MAX;
diff --git a/contents/cooley_tukey/code/c++/fft.cpp b/contents/cooley_tukey/code/cpp/fft.cpp
similarity index 95%
rename from contents/cooley_tukey/code/c++/fft.cpp
rename to contents/cooley_tukey/code/cpp/fft.cpp
index 5d4772f10..d4697d1df 100644
--- a/contents/cooley_tukey/code/c++/fft.cpp
+++ b/contents/cooley_tukey/code/cpp/fft.cpp
@@ -55,7 +55,7 @@ void cooley_tukey(Iter first, Iter last) {
// now combine each of those halves with the butterflies
for (int k = 0; k < size / 2; ++k) {
- auto w = std::exp(complex(0, -2.0 * pi * k / size));
+ auto w = std::exp(complex(0, -2.0 * pi * k / static_cast(size)));
auto& bottom = first[k];
auto& top = first[k + size / 2];
@@ -78,7 +78,7 @@ void sort_by_bit_reverse(Iter first, Iter last) {
b = (((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2));
b = (((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4));
b = (((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8));
- b = ((b >> 16) | (b << 16)) >> (32 - std::uint32_t(log2(size)));
+ b = ((b >> 16) | (b << 16)) >> (32 - std::uint32_t(log2(static_cast(size))));
if (b > i) {
swap(first[b], first[i]);
}
diff --git a/contents/cooley_tukey/code/rust/Cargo.toml b/contents/cooley_tukey/code/rust/Cargo.toml
new file mode 100644
index 000000000..0cba5179d
--- /dev/null
+++ b/contents/cooley_tukey/code/rust/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "rust"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+rand = "0.7.3"
+rustfft = "4.1.0"
+
+[[bin]]
+path = "./fft.rs"
+name = "main"
\ No newline at end of file
diff --git a/contents/cooley_tukey/cooley_tukey.md b/contents/cooley_tukey/cooley_tukey.md
index d67d4dbd2..d528832d1 100644
--- a/contents/cooley_tukey/cooley_tukey.md
+++ b/contents/cooley_tukey/cooley_tukey.md
@@ -76,13 +76,11 @@ For some reason, though, putting code to this transformation really helped me fi
{% sample lang="clj" %}
[import:15-30, lang:"clojure"](code/clojure/fft.clj)
{% sample lang="cpp" %}
-[import:23-33, lang:"cpp"](code/c++/fft.cpp)
+[import:23-33, lang:"cpp"](code/cpp/fft.cpp)
{% sample lang="hs" %}
[import:7-13, lang:"haskell"](code/haskell/fft.hs)
{% sample lang="py" %}
[import:6-12, lang:"python"](code/python/fft.py)
-{% sample lang="scratch" %}
-[import:4-13, lang:"julia"](code/julia/fft.jl)
{% sample lang="asm-x64" %}
[import:15-74, lang:"asm-x64"](code/asm-x64/fft.s)
{% sample lang="js" %}
@@ -131,13 +129,11 @@ In the end, the code looks like:
{% sample lang="clj" %}
[import:31-58, lang:"clojure"](code/clojure/fft.clj)
{% sample lang="cpp" %}
-[import:36-66, lang:"cpp"](code/c++/fft.cpp)
+[import:36-66, lang:"cpp"](code/cpp/fft.cpp)
{% sample lang="hs" %}
[import:15-28, lang:"haskell"](code/haskell/fft.hs)
{% sample lang="py" %}
[import:15-26, lang:"python"](code/python/fft.py)
-{% sample lang="scratch" %}
-[import:16-32, lang:"julia"](code/julia/fft.jl)
{% sample lang="asm-x64" %}
[import:76-165, lang:"asm-x64"](code/asm-x64/fft.s)
{% sample lang="js" %}
@@ -246,13 +242,11 @@ Note: I implemented this in Julia because the code seems more straightforward in
{% sample lang="clj" %}
[import, lang:"clojure"](code/clojure/fft.clj)
{% sample lang="cpp" %}
-[import, lang:"cpp"](code/c++/fft.cpp)
+[import, lang:"cpp"](code/cpp/fft.cpp)
{% sample lang="hs" %}
[import, lang:"haskell"](code/haskell/fft.hs)
{% sample lang="py" %}
[import, lang:"python"](code/python/fft.py)
-{% sample lang="scratch" %}
-Some rather impressive scratch code was submitted by Jie and can be found here: https://scratch.mit.edu/projects/37759604/#editor
{% sample lang="asm-x64" %}
[import, lang:"asm-x64"](code/asm-x64/fft.s)
{% sample lang="js" %}
@@ -271,7 +265,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/cryptography/cryptography.md b/contents/cryptography/cryptography.md
new file mode 100644
index 000000000..dd136dae8
--- /dev/null
+++ b/contents/cryptography/cryptography.md
@@ -0,0 +1,135 @@
+# Cryptography
+
+Humans have almost always been interested in sending secret messages that only the sender and receiver understand.
+The reason for this is obvious: secret messages should remain secret.
+The easiest way for this to happen is to talk behind closed doors, but that simply doesn't work if the sender and receiver are separated by a significant distance.
+In this case, they need to rely on a messenger or mailman to send the message.
+
+For simplicity, let's assume they are sending a written letter for the purpose of negotiating war tactics in ancient Greece or Rome.
+Obviously, the message can remain secret if both the sender and receiver also trust the messenger; however, what if the messenger is actually an evil spy?
+What if the messenger is killed and the letter is stolen?
+What if (in an elaborate ruse), some third party slips into the messenger's tent in the dead-of-night and replaces the letter with another one entirely different?
+
+These are all important questions cryptography addresses.
+
+The idea is simple: we procedurally scramble the message we are sending and only provide the unscrambling procedure to trusted parties.
+In this way, the message would seem like utter gobbledygook to anyone other than the sender and receiver.
+It doesn't matter if the messenger is evil.
+They cannot read the message anyway.
+It's also fine if the message is replaced, because then the receiver won't be able to properly decode the message and can just ask for another message to be sent (probably on another path with a different messenger).
+Unsurprisingly, a very early method of encryption was supposedly developed by Julius Caeser and called the "Caesar Cipher" {{ "ceasar_cipher_wiki" | cite }}.
+Here, every character in the message is replaced by another character based on some pre-defined table or chart that only the sender and receiver have.
+The table is created by simply rotating the alphabet by $$n$$ spaces, where $$n$$ is chosen in a discussion between the sender and receiver before-hand.
+
+ | $$n$$ | 0 | 2 | 14 | 18 | 21 | 24 |
+ | ----- | - | - | -- | -- | -- | -- |
+ | a | a | c | o | s | v | y |
+ | b | b | d | p | t | w | z |
+ | c | c | e | q | u | x | a |
+ | d | d | f | r | v | y | b |
+ | e | e | g | s | w | z | c |
+ | f | f | h | t | x | a | d |
+ | g | g | i | u | y | b | e |
+ | h | h | j | v | z | c | f |
+ | i | i | k | w | a | d | g |
+ | j | j | l | x | b | e | h |
+ | k | k | m | y | c | f | i |
+ | l | l | n | z | d | g | j |
+ | m | m | o | a | e | h | k |
+ | n | n | p | b | f | i | l |
+ | o | o | q | c | g | j | m |
+ | p | p | r | d | h | k | n |
+ | q | q | s | e | i | l | o |
+ | r | r | t | f | j | m | p |
+ | s | s | u | g | k | n | q |
+ | t | t | v | h | l | o | r |
+ | u | u | w | i | m | p | s |
+ | v | v | x | j | n | q | t |
+ | w | w | y | k | o | r | u |
+ | x | x | z | l | p | s | v |
+ | y | y | a | m | q | t | w |
+ | z | z | b | n | r | u | x |
+
+It is certainly not the most complicated scheme out there, but it is generally the first encryption scheme people come up with when trying to encode secret messages to one another.
+Honestly, I remember sending messages back and forth to friends in elementary school, but we would never provide the necessary table to decode the message.
+Instead, we would provide enough text that they could find the table themselves from context.
+If a bunch of elementary school kids can figure out how to break this encryption scheme, it cannot be too robust.
+In fact, it's interesting to see how the field of cryptography has grown since the Caesar cipher was developed.
+In the cryptographic literature, there is always a sender, receiver, and eavesdropper.
+For some reason beyond my own comprehension, the first two people are almost always given the names Alice (sender) and Bob (receiver).
+Meanwhile, the attacker or eavesdropper is usually called either Eve or Charlie
+These names are consistent even with quantum cryptography, so they are here to stay.
+
+In general, there are two different types of encryption: symmetric and asymmetric.
+Both of which are described in the following sections.
+
+Cryptographic systems are a cornerstone to modern information technology and lie at the heart of everything from WiFi to online banking.
+If an attacker manages to crack modern cryptographic algorithms, they could cause serious damage.
+For this reason, it is important to keep a few things in mind:
+* Because cryptography has become such an advanced field cryptographic systems should be analyzed by trained professionals and have undergo extensive testing and vetting.
+ This means that whenever possible, one should use a widely accepted cryptography library instead of writing their own cypher.
+* Kerckhoffs's principle says that when determining the robustness of a cryptographic system it should be assumed that the attacker knows the encryption and decryption algorithm {{ "Kerckhoffs_principle_wiki" | cite }}.
+ This does not include any pre-shared or secret keys.
+* With the advances in technology, cryptography often hits its limits.
+ Many formerly state-of-the-art hashing algorithms have become obsolete because the computers used to crack them have gotten faster and better.
+ Another field that cryptography will have to face is [quantum computing](../quantum_information/quantum_information.md).
+ Quantum computers will have a big impact on cryptography and especially asymmetric cryptography.
+ This whole set of problems is summarized in the field of post-quantum cryptography {{ "post-quantum_crypto_wiki" | cite }}.
+
+## Symmetric Cryptography
+
+Symmetric cryptography is called symmetric because the key that is used is the same for encrypting and decrypting.
+For this to work Alice and Bob both need the same key, which they have to share before communicating.
+Some examples for symmetric cryptography are:
+* **Ceasar Cipher**: Alice and Bob rotate the alphabet by $$n$$ characters and use that as a table to encode and decode their message {{ "ceasar_cipher_wiki" | cite }}.
+* **Rot13**: This is a special case of the Caeser Cipher where the alphabet is rotated by 13, hence the name "Rot13" {{ "rot13_wiki" | cite }}
+* **Permutation Cipher**: Here we choose a permutation $$\pi$$ (i.e. $$\pi=(3,1,2,4)$$) and reorder the the letters according to that $$\pi$$ which is the key {{ "CC_permutation" | cite }}.
+* **XOR encryption**: This method works on bit strings and combines the message and a key of equal bit length with the XOR operator {{ "xor_cipher_wiki" | cite }}.
+ To decrypt, simply XOR again with the same key.
+* **DES or Data Encryption Standard**: This is a newer encryption algorithm which was standardized in 1977 {{ "DES_wiki" | cite }}.
+ It has since been deemed insecure and is superseded by AES.
+* **AES or Advanced Encryption Standard**: The actual algorithm is called "Rijndael" {{ "AES_wiki" | cite }}.
+ Like with XOR or DES we generate a bit string (depending on which AES you use 128/192 or 256 bit long) which is your key.
+* **Blowfish**: This algorithm was also a good contender for the AES but lost to Rijndael {{ "blowfish_cipher_wiki" | cite }}.
+
+This section is currently a work-in-progress, and all of these methods will have corresponding chapters in the near future.
+
+## Asymmetric Cryptography
+
+Asymmetric cryptography is sometimes called "public key cryptography" (or PK cryptography in short) because Bob and Alice both need a shared public key and a private key they keep to themselves.
+These algorithms are called asymmetric because what is encrypted with the public key can only be decrypted with the private key and vice versa.
+This can be used for a number of different applications, like digital signing, encrypted communication, or secretly sharing keys.
+For example, if Alice wants to send a message to Bob and this message has to be kept private, Alice will encrypt the message with Bob's public key.
+Now only Bob can decrypt the message again and read it.
+If Charlie were to alter Alice's message, Bob couldn't decrypt it anymore.
+If Bob wants to make sure the message is actually from Alice, Alice can encrypt the already encrypted message with her private key again.
+This is to keep Charlie from sending forged or altered messages since Bob couldn't decrypt that layer with Alice's public key.
+Some examples for public key cryptography:
+* **RSA**: This algorithm calculates a public and a private key from two very large primes {{ "RSA_wiki" | cite }}.
+ It is (hopefully) near impossible to factor the product of two such primes in a feasible amount of time.
+* **ECC or Elliptic-curve cryptography**: Here you calculate the private and public key from two points on an elliptic curve {{ "ECC_crypto_wiki" | cite }}.
+ This has the positive side effect that you need smaller numbers than non-ECC algorithms like RSA to achieve the same level of security.
+
+This section is currently a work-in-progress. These methods will also have corresponding chapters in the near future.
+
+### Bibliography
+
+{% references %} {% endreferences %}
+
+
+
+## License
+The text of this chapter was written by [Liikt](https://github.com/Liikt) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+The code examples are licensed under the MIT license (found in LICENSE.md).
+
+##### Code Examples
+
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+
+##### Text
+
+The text of this chapter was written by [Liikt](https://github.com/Liikt) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+[
](https://creativecommons.org/licenses/by-sa/4.0/)
diff --git a/contents/cryptography/res/table.jl b/contents/cryptography/res/table.jl
new file mode 100644
index 000000000..314c238c4
--- /dev/null
+++ b/contents/cryptography/res/table.jl
@@ -0,0 +1,33 @@
+function print_table(a::Array{T, 2},
+ header::Vector{String}) where T <: Union{Char, String}
+ print(" | ")
+ for i = 1:length(header)
+ print(string(header[i]), " | ")
+ end
+ println()
+
+ print(" | ")
+ for i = 1:length(header)
+ print("---", " | ")
+ end
+ println()
+
+ for i = 1:size(a)[1]
+ print(" | ")
+ for j = 1:size(a)[2]
+ print(string(a[i,j]), " | ")
+ end
+ println()
+ end
+end
+
+alphabet = [char for char = 'a':'z']
+offsets = Int.([0, 0, 2, 14, 18, 21, 24])
+alphabet_array = Array{Char}(undef, 26, length(offsets))
+
+for i = 1:length(offsets)
+ alphabet_array[:,i] = vcat(alphabet[offsets[i]+1:26],alphabet[1:offsets[i]])
+end
+
+header = vcat(string.(offsets))
+print_table(alphabet_array, header)
diff --git a/contents/data_compression/data_compression.md b/contents/data_compression/data_compression.md
index 1f48c0c99..5a04c3706 100644
--- a/contents/data_compression/data_compression.md
+++ b/contents/data_compression/data_compression.md
@@ -130,7 +130,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/data_structures/data_structures.md b/contents/data_structures/data_structures.md
index 11ae7aa4b..60680b95e 100644
--- a/contents/data_structures/data_structures.md
+++ b/contents/data_structures/data_structures.md
@@ -7,7 +7,7 @@ The fundamental building blocks of algorithms are data structures, and thus as m
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/decision_problems/decision_problems.md b/contents/decision_problems/decision_problems.md
index 064c1d067..2ab9ed612 100644
--- a/contents/decision_problems/decision_problems.md
+++ b/contents/decision_problems/decision_problems.md
@@ -14,7 +14,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/differential_equations/differential_equations.md b/contents/differential_equations/differential_equations.md
index 3cfbba1fa..0bb08349c 100644
--- a/contents/differential_equations/differential_equations.md
+++ b/contents/differential_equations/differential_equations.md
@@ -7,7 +7,7 @@ Here, we discuss many different methods to solve particular sets of differential
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/domain_coloring/domain_coloring.md b/contents/domain_coloring/domain_coloring.md
index 39159e650..746c52241 100644
--- a/contents/domain_coloring/domain_coloring.md
+++ b/contents/domain_coloring/domain_coloring.md
@@ -164,7 +164,7 @@ We will be using domain coloring in other contexts throughout this text when des
Here is a video describing domain coloring:
-
+
## Example Code
@@ -190,7 +190,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/domain_coloring/domain_coloring.md.bak b/contents/domain_coloring/domain_coloring.md.bak
deleted file mode 100644
index 8ec9129ad..000000000
--- a/contents/domain_coloring/domain_coloring.md.bak
+++ /dev/null
@@ -1,185 +0,0 @@
-# Domain coloring
-
-Domain coloring is a much more complicated plotting technique than those outlined in the [plotting chapter](../plotting/plotting.md) and is used to plot complex functions where both the input and output have imaginary and real components.
-For the code in this chapter, we will focus on languages that are easily able to plot two-dimensional images or heatmaps, instead of languages meant for number-crunching.
-That is to say that this chapter will certainly have a code implementation in gnuplot, but it will not likely have an implementation in C, Fortran, or Java because these languages do not have plotting capabilities in-built.
-
-Imagine the following function: $$f(z) = z^2$$.
-In this case, we could create a plot that looks like this:
-
-
-
-
-
-This indicates that for various input values along $$z$$, we have different function outputs from $$f(z)$$.
-Now let's imagine another function with complex input $$(z \in \mathbb{C})$$, but a purely real output $$(f(z) \in \mathbb{R})$$:
-
-$$
-f(z) = |z|
-$$
-
-In this case, each complex input has a real output.
-This can be plotted as a two-dimensional dataset like so:
-
-
-
-
-
-Here, the $$x$$-axis and $$y$$-axis represent the real and imaginary components of the input variable, respectively.
-The colorbar represents the output of $$f(z)$$.
-
-At this point, we can start to see the problem.
-If the output of $$f(z)$$ also requires plotting of the real and imaginary components, then we would need four dimensions to appropriately represent the function space, one axis for the real component and another for the imaginary component of both the input ($$z$$) and the output of $$f(z)$$!
-Unfortunately, feeble human minds are incapable of understanding four spatial dimensions without projecting onto lower dimensionality, so we need to improvise.
-
-We do this by assuming the complex output can be represented in the following form:
-
-$$
-z = re^{i \theta} = r(\cos(\theta) + i\sin(\theta))
-$$
-
-where, $$r$$ is a complex magnitude and $$\theta$$ is a complex phase.
-This is the formula for a circle in the complex plane and we can easily find $$r$$ and $$\theta$$ like so:
-
-$$
-\begin{align}
- r &= \sqrt{\text{Re}(z)^2 + \text{Im}(z)^2} \\
- \theta &= \text{atan}\left(\frac{\text{Im}(z)}{\text{Re}(z)}\right)
-\end{align}
-$$
-
-Once we have our complex function output in this form, we then color the output domain according to a color space with at least 2 independent dimensions, like RGB (Red, Green, Blue), or HSV (Hue, Saturation, Value) [CITE].
-The choice of color space is completely dependent on what the users feel is most visually intuitive.
-In any case, one dimension of the color system will be used to represent the complex magnitude of the output and another dimension of the color system will be used to represent the complex phase.
-The $$xy$$ grid will be representing the real and imaginary inputs to these functions.
-That is to say, we plug every value in the 2D complex plane into the function and then color each pixel based on the function output.
-
-As an example, let's look at the simplest function we can $$f(z) = z$$, but in this case $$z \in \mathbb{C}$$.
-If we use an RGB color scheme, where red represents $$\theta$$ and blue represents $$r$$, we can generate the following image:
-
-
-
-
-
-As a note here, there is a clear phase discontinuity along the vertical axis.
-That is to say that the complex phase wraps around the origin, ranging from 0 (clear) to $$2\pi$$ (red).
-In addition, the edges of the plot are blue because the function value increases linearly as we move from the origin.
-
-If we instead look at the function $$f(z) = z^2$$, we can generate a similar plot:
-
-
-
-
-
-Here, it is clear that the complex phase wraps around the origin twice, creating two separate phase discontinuities on top of each other.
-This indicates a $$4\pi$$ phase winding, and for some purposes, such as vortex tracking for inviscid fluids, this visualizaton is ideal, because a vortex is located precisely at the phase discontinuity [CITE].
-For other purposes, the discontinuity is visually distracting, and for this reason, many people use an HSV scheme for plotting complex functions.
-So here is the same function $$\left(f(z)=z^2\right)$$, but using hue to represent the complex phase and saturation to represent the magnitude.
-
-
-
-
-
-Here, the value for HSV was always set to 1.
-When looking at the edges of the plot, the hue changes rapidly, but each color is mirrored on the oposite edge.
-This indicates the $$4\pi$$ phase winding we saw in the RGB plots.
-Also, because the complex magnitude increases as we move further from the center of the plot, the saturation also increases.
-Thus the very center of the plot is completely washed out!
-We need to fix this in subsequent plots to make them representative of the actual data.
-
-One easy way to show that the complex magnitude is increasing as we move further from the origin is with contours.
-Essentially, at ever integer value of the magnitude, we want to draw some kind of line.
-There are a number of ways to generate these lines, and one simple way is by using an alternative shading function like so:
-
-$$
-g(r) = r-\lfloor r \rfloor.
-$$
-
-This will create the following image:
-
-
-
-
-
-This function will essentially create a smooth gradient, but because of the floor operation $$\left(\lfloor \cdot \rfloor \right)$$, the saturation will go from 0 to 1 between each integer value of the magnitude.
-Here, it is clear that the magnitude is increasing as $$z^2$$ from the origin; however, because the saturation is fluctuating so much, it is difficult to see the phase pattern next to each contour.
-This can be fixed simply by adding an offset to the shading function such that,
-
-$$
-g(r) = \frac{1}{2} + \frac{1}{2}\left(r-\lfloor r \rfloor \right).
-$$
-
-Which will produce the following image:
-
-
-
-
-
-This means that the saturation will fluctuate from $$\frac12$$ to 1 instead of from 0 to 1, which makes it way easier to see phase information next to contours.
-Again, there is a lot of ways to play with these equations, so feel free to use whatever function you want!
-As long as some sort of rounding operation is used to establish some form of integer value for the magnitude, it should be possible to create contours of various types.
-
-Unfortunately, there the changing saturation only shows changes in the complex magnitude, and changing hue only shows changes in the complex phase.
-Neither the magnitude or the phase directly show what is happening in real or imaginary space with the output.
-To show this, we might want to draw gridlines that color out grid black whenever the imaginary or real components of the output function are integer values.
-
-For example, let's go back to a simpler function $$f(z) = z$$.
-If we draw lines on this plot, corresponding to integer values in the output, we get a simple grid
-
-
-
-
-
-Like before, the choice of which function to use in order to create the gridlines is somewhat arbitrary.
-It is important to choose a function that sharply drops to 0 or peaks at 1 for all integer values, and then you multiply this by the output of $$f(z)$$.
-For these purposes, we chose the following function
-
-$$
-h(z) = |\sin(\pi\times\text{Re}(f(z)))^t|\times|\sin(\pi\times\text{Im}(f(z)))^t|,
-$$
-
-where $$t$$ is some threshold value, and was set to be 0.1 in our plot.
-A plot of h(z) for $$f(z) = z$$ where $$z\in\mathbb{R}$$ is shown below:
-
-
-
-
-
-So, putting it altogether and returning to the function of $$f(z) = z^2$$, we find the following image.
-
-
-
-
-
-Here, the diagonal lines through the center represent integer values along the imaginary axis for $$f(z)$$ and the vertical and horizontal represent integer values of the real axis for $$f(z)$$.
-
-## Example Code
-
-Here is the full script to generate a domain colored output of $$f(z)=z^2$$.
-
-### Bibliography
-
-{% references %} {% endreferences %}
-
-
-
-## License
-
-##### Code Examples
-
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
-
-##### Text
-
-The text of this chapter was written by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-
-[
](https://creativecommons.org/licenses/by-sa/4.0/)
-
-##### Images/Graphics
-
-##### Pull Requests
-
-The following pull requests have modified the text or graphics of this chapter:
-- none
diff --git a/contents/euclidean_algorithm/code/asm-x64/euclidean_example.s b/contents/euclidean_algorithm/code/asm-x64/euclidean_example.s
index c08bb0878..53a008908 100644
--- a/contents/euclidean_algorithm/code/asm-x64/euclidean_example.s
+++ b/contents/euclidean_algorithm/code/asm-x64/euclidean_example.s
@@ -1,7 +1,8 @@
.intel_syntax noprefix
.section .rodata
- fmt: .string "%d\n"
+ euclid_mod_fmt: .string "[#]\nModulus-based euclidean algorithm result:\n%d\n"
+ euclid_sub_fmt: .string "[#]\nSubtraction-based euclidean algorithm result:\n%d\n"
.section .text
.global main
@@ -59,14 +60,14 @@ main:
mov rdi, 4288 # Call euclid_mod
mov rsi, 5184
call euclid_mod
- mov rdi, OFFSET fmt # Print output
+ mov rdi, OFFSET euclid_mod_fmt # Print output
mov rsi, rax
xor rax, rax
call printf
mov rdi, 1536 # Call euclid_sub
mov rsi, 9856
call euclid_sub
- mov rdi, OFFSET fmt # Print output
+ mov rdi, OFFSET euclid_sub_fmt # Print output
mov rsi, rax
xor rax, rax
call printf
diff --git a/contents/euclidean_algorithm/code/bash/euclid.bash b/contents/euclidean_algorithm/code/bash/euclid.bash
index bef4b5da0..0ddd49537 100755
--- a/contents/euclidean_algorithm/code/bash/euclid.bash
+++ b/contents/euclidean_algorithm/code/bash/euclid.bash
@@ -38,6 +38,6 @@ euclid_sub() {
}
result=$(euclid_mod $((64 * 67)) $((64 * 81)))
-echo "$result"
+echo -e "[#]\nModulus-based euclidean algorithm result:\n$result"
result=$(euclid_sub $((128 * 12)) $((128 * 77)))
-echo "$result"
+echo -e "[#]\nSubtraction-based euclidean algorithm result:\n$result"
diff --git a/contents/euclidean_algorithm/code/c/euclidean_example.c b/contents/euclidean_algorithm/code/c/euclidean_example.c
index 16b0ce9ea..d1c0b69d1 100644
--- a/contents/euclidean_algorithm/code/c/euclidean_example.c
+++ b/contents/euclidean_algorithm/code/c/euclidean_example.c
@@ -1,40 +1,40 @@
#include
-#include
+#include
int euclid_mod(int a, int b) {
- a = abs(a);
- b = abs(b);
+ a = abs(a);
+ b = abs(b);
- while (b != 0) {
- int temp = b;
- b = a % b;
- a = temp;
- }
+ while (b != 0) {
+ int temp = b;
+ b = a % b;
+ a = temp;
+ }
- return a;
+ return a;
}
int euclid_sub(int a, int b) {
- a = abs(a);
- b = abs(b);
-
- while (a != b) {
- if (a > b) {
- a -= b;
- } else {
- b -= a;
- }
+ a = abs(a);
+ b = abs(b);
+
+ while (a != b) {
+ if (a > b) {
+ a -= b;
+ } else {
+ b -= a;
}
+ }
- return a;
+ return a;
}
int main() {
- int check1 = euclid_mod(64 * 67, 64 * 81);
- int check2 = euclid_sub(128 * 12, 128 * 77);
+ int check1 = euclid_mod(64 * 67, 64 * 81);
+ int check2 = euclid_sub(128 * 12, 128 * 77);
- printf("%d\n", check1);
- printf("%d\n", check2);
+ printf("[#]\nModulus-based euclidean algorithm result:\n%d\n", check1);
+ printf("[#]\nSubtraction-based euclidean algorithm result:\n%d\n", check2);
- return 0;
+ return 0;
}
diff --git a/contents/euclidean_algorithm/code/clisp/euclidean.lisp b/contents/euclidean_algorithm/code/clisp/euclidean.lisp
index 62f525ac3..19cba7358 100644
--- a/contents/euclidean_algorithm/code/clisp/euclidean.lisp
+++ b/contents/euclidean_algorithm/code/clisp/euclidean.lisp
@@ -17,8 +17,10 @@
(abs a)
(euclid-mod b (mod a b))))
-(print (euclid-sub (* 64 67) (* 64 81)))
-(print (euclid-mod (* 128 12) (* 128 77)))
+(format T "[#]~%Modulus-based euclidean algorithm result:~%")
+(format T "~d~%" (euclid-sub (* 64 67) (* 64 81)))
+(format T "[#]~%Subtraction-based euclidean algorithm result:~%")
+(format T "~d~%" (euclid-mod (* 128 12) (* 128 77)))
;; Quick test
(assert
diff --git a/contents/euclidean_algorithm/code/coconut/euclidean.coco b/contents/euclidean_algorithm/code/coconut/euclidean.coco
index 8f5b5c9d7..17c592cf0 100644
--- a/contents/euclidean_algorithm/code/coconut/euclidean.coco
+++ b/contents/euclidean_algorithm/code/coconut/euclidean.coco
@@ -1,7 +1,7 @@
-def euclid_sub(a is int, 0) = a
-addpattern def euclid_sub(0, b is int) = b
+def euclid_sub(int(a), 0) = a
+addpattern def euclid_sub(0, int(b)) = b
-addpattern def euclid_sub(a is int, b is int):
+addpattern def euclid_sub(int(a), int(b)):
if a < b:
return euclid_sub(a, b - a)
elif b < a:
@@ -9,11 +9,13 @@ addpattern def euclid_sub(a is int, b is int):
return a
-def euclid_mod(a is int, 0) = a
-addpattern def euclid_mod(0, b is int) = b
+def euclid_mod(int(a), 0) = a
+addpattern def euclid_mod(0, int(b)) = b
-addpattern def euclid_mod(a is int, b is int) = euclid_mod(b, a % b)
+addpattern def euclid_mod(int(a), int(b)) = euclid_mod(b, a % b)
if __name__ == '__main__':
- print('Euclidean mod:', euclid_mod(64 * 67, 64 * 81))
- print('Euclidean sub:', euclid_sub(128 * 12, 128 * 77))
+ print('[#]\nModulus-based euclidean algorithm result:')
+ print(euclid_mod(64 * 67, 64 * 81))
+ print('[#]\nSubtraction-based euclidean algorithm result:')
+ print(euclid_sub(128 * 12, 128 * 77))
diff --git a/contents/euclidean_algorithm/code/c++/euclidean.cpp b/contents/euclidean_algorithm/code/cpp/euclidean.cpp
similarity index 76%
rename from contents/euclidean_algorithm/code/c++/euclidean.cpp
rename to contents/euclidean_algorithm/code/cpp/euclidean.cpp
index f7b818802..1f6c04e27 100644
--- a/contents/euclidean_algorithm/code/c++/euclidean.cpp
+++ b/contents/euclidean_algorithm/code/cpp/euclidean.cpp
@@ -34,6 +34,6 @@ int main() {
auto check1 = euclid_mod(64 * 67, 64 * 81);
auto check2 = euclid_sub(128 * 12, 128 * 77);
- std::cout << check1 << '\n';
- std::cout << check2 << '\n';
+ std::cout << "[#]\nModulus-based euclidean algorithm result:\n" << check1 << '\n';
+ std::cout << "[#]\nSubtraction-based euclidean algorithm result:\n" << check2 << '\n';
}
diff --git a/contents/euclidean_algorithm/code/csharp/Program.cs b/contents/euclidean_algorithm/code/csharp/Program.cs
index edf1edfd4..80857df27 100644
--- a/contents/euclidean_algorithm/code/csharp/Program.cs
+++ b/contents/euclidean_algorithm/code/csharp/Program.cs
@@ -7,12 +7,13 @@ class Program
{
static void Main(string[] args)
{
- Console.WriteLine("EuclideanAlgorithm");
var euclideanAlgorithm = new EuclideanAlgorithm();
int check = euclideanAlgorithm.EuclidMod(64 * 67, 64 * 81);
int check2 = euclideanAlgorithm.EuclidSub(128 * 12, 128 * 77);
+ Console.WriteLine("[#]\nModulus-based euclidean algorithm result:");
Console.WriteLine(check);
+ Console.WriteLine("[#]\nSubtraction-based euclidean algorithm result:");
Console.WriteLine(check2);
}
}
diff --git a/contents/euclidean_algorithm/code/d/euclidean_algorithm.d b/contents/euclidean_algorithm/code/d/euclidean_algorithm.d
index 042a9bae1..585d0aa1b 100644
--- a/contents/euclidean_algorithm/code/d/euclidean_algorithm.d
+++ b/contents/euclidean_algorithm/code/d/euclidean_algorithm.d
@@ -37,6 +37,6 @@ void main()
auto check1 = euclid_mod(64 * 67, 64 * 81);
auto check2 = euclid_sub(128 * 12, 128 * 77);
- writeln("Modulus-based euclidean algorithm result: ", check1);
- writeln("Subtraction-based euclidean algorithm result: ", check2);
+ writeln("[#]\nModulus-based euclidean algorithm result:\n", check1);
+ writeln("[#]\nSubtraction-based euclidean algorithm result:\n", check2);
}
diff --git a/contents/euclidean_algorithm/code/expected.json b/contents/euclidean_algorithm/code/expected.json
new file mode 100644
index 000000000..f6b6ffb70
--- /dev/null
+++ b/contents/euclidean_algorithm/code/expected.json
@@ -0,0 +1,8 @@
+{
+ "Description": "euclidean algorithm",
+ "Delta" : 0.0,
+ "OutputValues" : [
+ "64",
+ "128"
+ ]
+}
diff --git a/contents/euclidean_algorithm/code/fortran/euclidean.f90 b/contents/euclidean_algorithm/code/fortran/euclidean.f90
index 3107e4de2..e0dc9610e 100644
--- a/contents/euclidean_algorithm/code/fortran/euclidean.f90
+++ b/contents/euclidean_algorithm/code/fortran/euclidean.f90
@@ -38,12 +38,18 @@ PROGRAM euclidean
IMPLICIT NONE
INTEGER :: a, b, euclid_sub, euclid_mod
- a = 24
- b = 27
- WRITE(*,*) 'Subtraction method: GCD is: ', euclid_sub(a, b)
+ a = 64 * 67
+ b = 64 * 81
- a = 24
- b = 27
- WRITE(*,*) 'Modulus method: GCD is: ', euclid_mod(a, b)
+ WRITE(*,'(a)') '[#]'
+ WRITE(*,'(a)') 'Modulus-based euclidean algorithm result:'
+ WRITE(*, '(g0)') euclid_mod(a, b)
+
+ a = 128 * 12
+ b = 128 * 77
+
+ WRITE(*,'(a)') '[#]'
+ WRITE(*,'(a)') 'Subtraction-based euclidean algorithm result:'
+ WRITE(*, '(g0)') euclid_sub(a, b)
END PROGRAM euclidean
diff --git a/contents/euclidean_algorithm/code/go/euclidean.go b/contents/euclidean_algorithm/code/go/euclidean.go
index f457b1849..ea543fe75 100644
--- a/contents/euclidean_algorithm/code/go/euclidean.go
+++ b/contents/euclidean_algorithm/code/go/euclidean.go
@@ -41,6 +41,8 @@ func main() {
check1 := euclidMod(64*67, 64*81)
check2 := euclidSub(128*12, 128*77)
+ fmt.Println("[#]\nModulus-based euclidean algorithm result:")
fmt.Println(check1)
+ fmt.Println("[#]\nSubtraction-based euclidean algorithm result:")
fmt.Println(check2)
}
diff --git a/contents/euclidean_algorithm/code/haskell/euclidean_algorithm.hs b/contents/euclidean_algorithm/code/haskell/euclidean_algorithm.hs
index 9227de4e9..917aef7df 100644
--- a/contents/euclidean_algorithm/code/haskell/euclidean_algorithm.hs
+++ b/contents/euclidean_algorithm/code/haskell/euclidean_algorithm.hs
@@ -31,5 +31,7 @@ main :: IO ()
main = do
let chk1 = euclidMod (64 * 67) (64 * 81)
chk2 = euclidSub (128 * 12) (128 * 77)
+ putStrLn "[#]\nModulus-based euclidean algorithm result:"
print chk1
+ putStrLn "[#]\nSubtraction-based euclidean algorithm result:"
print chk2
diff --git a/contents/euclidean_algorithm/code/java/EuclideanAlgo.java b/contents/euclidean_algorithm/code/java/EuclideanAlgo.java
index 95d233f58..ac53379da 100644
--- a/contents/euclidean_algorithm/code/java/EuclideanAlgo.java
+++ b/contents/euclidean_algorithm/code/java/EuclideanAlgo.java
@@ -26,7 +26,9 @@ public static int euclidMod(int a, int b) {
}
public static void main(String[] args) {
+ System.out.println("[#]\nModulus-based euclidean algorithm result:");
System.out.println(euclidMod(64 * 67, 64 * 81));
+ System.out.println("[#]\nSubtraction-based euclidean algorithm result:");
System.out.println(euclidSub(128 * 12, 128 * 77));
}
}
diff --git a/contents/euclidean_algorithm/code/javascript/euclidean_example.js b/contents/euclidean_algorithm/code/javascript/euclidean_example.js
index fbaf4bfcc..2199c37dc 100644
--- a/contents/euclidean_algorithm/code/javascript/euclidean_example.js
+++ b/contents/euclidean_algorithm/code/javascript/euclidean_example.js
@@ -18,14 +18,16 @@ function euclidSub(a, b) {
while (a !== b) {
if (a > b) {
- a -= a - b;
+ a -= b;
} else {
- b = b - a;
+ b -= a;
}
}
return a;
}
+console.log('[#]\nModulus-based euclidean algorithm result:')
console.log(euclidMod(64 * 67, 64 * 81));
+console.log('[#]\nSubtraction-based euclidean algorithm result:')
console.log(euclidSub(128 * 12, 128 * 77));
diff --git a/contents/euclidean_algorithm/code/julia/euclidean.jl b/contents/euclidean_algorithm/code/julia/euclidean.jl
index 744ae2187..a85f931ae 100644
--- a/contents/euclidean_algorithm/code/julia/euclidean.jl
+++ b/contents/euclidean_algorithm/code/julia/euclidean.jl
@@ -28,8 +28,8 @@ function main()
check1 = euclid_mod(64 * 67, 64 * 81);
check2 = euclid_sub(128 * 12, 128 * 77);
- println("Modulus-based euclidean algorithm result: $(check1)")
- println("subtraction-based euclidean algorithm result: $(check2)")
+ println("[#]\nModulus-based euclidean algorithm result:\n$(check1)")
+ println("[#]\nSubtraction-based euclidean algorithm result:\n$(check2)")
end
diff --git a/contents/euclidean_algorithm/code/kotlin/Euclidean.kt b/contents/euclidean_algorithm/code/kotlin/Euclidean.kt
index 9e14c7463..855afcd59 100644
--- a/contents/euclidean_algorithm/code/kotlin/Euclidean.kt
+++ b/contents/euclidean_algorithm/code/kotlin/Euclidean.kt
@@ -26,6 +26,8 @@ fun euclidMod(a: Int, b: Int): Int {
}
fun main(args: Array) {
- println(euclidSub(128 * 12, 128 * 77))
+ println("[#]\nModulus-based euclidean algorithm result:")
println(euclidMod(64 * 67, 64 * 81))
-}
+ println("[#]\nSubtraction-based euclidean algorithm result:")
+ println(euclidSub(128 * 12, 128 * 77))
+}
\ No newline at end of file
diff --git a/contents/euclidean_algorithm/code/lolcode/euclid.lol b/contents/euclidean_algorithm/code/lolcode/euclid.lol
index 418851107..28e3230e3 100644
--- a/contents/euclidean_algorithm/code/lolcode/euclid.lol
+++ b/contents/euclidean_algorithm/code/lolcode/euclid.lol
@@ -24,7 +24,7 @@ HAI 1.2
HOW IZ I UKLIDSUP YR NUM1 AN YR NUM2
NUM1 R I IZ ABZ YR NUM1 MKAY
- NUM2 R EI IZ ABZ YR NUM2 MKAY
+ NUM2 R I IZ ABZ YR NUM2 MKAY
IM IN YR LOOP
BOTH SAEM NUM1 AN NUM2, O RLY?
@@ -44,4 +44,4 @@ HAI 1.2
VISIBLE CHECK1
VISIBLE CHECK2
-KTHXBYE
\ No newline at end of file
+KTHXBYE
diff --git a/contents/euclidean_algorithm/code/lua/euclidean.lua b/contents/euclidean_algorithm/code/lua/euclidean.lua
index 6b2aa8faa..0149ffd34 100644
--- a/contents/euclidean_algorithm/code/lua/euclidean.lua
+++ b/contents/euclidean_algorithm/code/lua/euclidean.lua
@@ -25,8 +25,10 @@ local function euclid_mod(a, b)
end
local function main()
- print(euclid_sub(128 * 12, 128 * 77))
+ print("[#]\nModulus-based euclidean algorithm result:")
print(euclid_mod(64 * 67, 64 * 81))
+ print("[#]\nSubtraction-based euclidean algorithm result:")
+ print(euclid_sub(128 * 12, 128 * 77))
end
main()
diff --git a/contents/euclidean_algorithm/code/matlab/euclidean.m b/contents/euclidean_algorithm/code/matlab/euclidean.m
index de2a63dec..7a9b317f3 100644
--- a/contents/euclidean_algorithm/code/matlab/euclidean.m
+++ b/contents/euclidean_algorithm/code/matlab/euclidean.m
@@ -31,6 +31,7 @@
end
function euclid()
- ['gcd(520,420) via euclidSub: ',num2str(euclidSub(520,420))]
- ['gcd(183,244) via euclidMod: ',num2str(euclidMod(183,244))]
+ ['[#] Modulus-based euclidean algorithm result: ',num2str(euclidMod(64 * 67, 64 * 81))]
+
+ ['[#] Subtraction-based euclidean algorithm result: ',num2str(euclidSub(128 * 12, 128 * 77))]
end
\ No newline at end of file
diff --git a/contents/euclidean_algorithm/code/nim/euclid_algorithm.nim b/contents/euclidean_algorithm/code/nim/euclid_algorithm.nim
index e74855592..d52b8062a 100644
--- a/contents/euclidean_algorithm/code/nim/euclid_algorithm.nim
+++ b/contents/euclidean_algorithm/code/nim/euclid_algorithm.nim
@@ -24,5 +24,7 @@ func euclid_sub(in1, in2: int): int =
result = a
when isMainModule:
+ echo "[#]\nModulus-based euclidean algorithm result:"
echo euclid_sub(64 * 67, 64 * 81)
+ echo "[#]\nSubtraction-based euclidean algorithm result:"
echo euclid_mod(128 * 12, 128 * 77)
diff --git a/contents/euclidean_algorithm/code/ocaml/euclidean_example.ml b/contents/euclidean_algorithm/code/ocaml/euclidean_example.ml
index 27e3ab166..c363e5e4f 100644
--- a/contents/euclidean_algorithm/code/ocaml/euclidean_example.ml
+++ b/contents/euclidean_algorithm/code/ocaml/euclidean_example.ml
@@ -19,6 +19,7 @@ let euclid_sub a b =
let chk1 = euclid_mod (64 * 67) (64 * 81)
let chk2 = euclid_sub (128 * 12) (128 * 77)
let () =
+ Printf.printf "[#]\nModulus-based euclidean algorithm result:\n";
chk1 |> print_int |> print_newline;
- chk2 |> print_int |> print_newline
-
+ Printf.printf "[#]\nSubtraction-based euclidean algorithm result:\n";
+ chk2 |> print_int |> print_newline
\ No newline at end of file
diff --git a/contents/euclidean_algorithm/code/php/euclidean.php b/contents/euclidean_algorithm/code/php/euclidean.php
index 52aac08c9..cd13e9d74 100644
--- a/contents/euclidean_algorithm/code/php/euclidean.php
+++ b/contents/euclidean_algorithm/code/php/euclidean.php
@@ -29,7 +29,7 @@ function euclid_mod(int $a, int $b): int
return $a;
}
-printf('Euclidean mod: %s', euclid_mod(64 * 67, 64 * 81));
+printf('[#]'.PHP_EOL.'Modulus-based euclidean algorithm result:'.PHP_EOL.'%s', euclid_mod(64 * 67, 64 * 81));
echo PHP_EOL;
-printf('Euclidean sub: %s', euclid_sub(128 * 12, 128 * 77));
+printf('[#]'.PHP_EOL.'Subtraction-based euclidean algorithm result:'.PHP_EOL.'%s', euclid_sub(128 * 12, 128 * 77));
echo PHP_EOL;
diff --git a/contents/euclidean_algorithm/code/powershell/euclidean_algorithm.ps1 b/contents/euclidean_algorithm/code/powershell/euclidean_algorithm.ps1
index d717320c8..3e3925ed7 100644
--- a/contents/euclidean_algorithm/code/powershell/euclidean_algorithm.ps1
+++ b/contents/euclidean_algorithm/code/powershell/euclidean_algorithm.ps1
@@ -26,5 +26,5 @@ function Mod-Euclid($a, $b) {
return $a
}
-Write-Host "Subtraction-based euclidean algorithm result: $(Mod-Euclid $(64 * 67) $(64 * 81))"
-Write-Host "Modulus-based euclidean algorithm result: $(Sub-Euclid $(128 * 12) $(128 * 77))"
+Write-Host "[#]`nSubtraction-based euclidean algorithm result:`n$(Mod-Euclid $(64 * 67) $(64 * 81))"
+Write-Host "[#]`nModulus-based euclidean algorithm result:`n$(Sub-Euclid $(128 * 12) $(128 * 77))"
diff --git a/contents/euclidean_algorithm/code/python/euclidean_example.py b/contents/euclidean_algorithm/code/python/euclidean_example.py
index 0badc2ca8..03d51aa4b 100644
--- a/contents/euclidean_algorithm/code/python/euclidean_example.py
+++ b/contents/euclidean_algorithm/code/python/euclidean_example.py
@@ -27,5 +27,7 @@ def euclid_sub(a, b):
return a
if __name__=="__main__":
- print('Euclidean mod: ', euclid_mod(64 * 67, 64 * 81))
- print('Euclidean sub: ', euclid_sub(128 * 12, 128 * 77))
+ print('[#]\nModulus-based euclidean algorithm result:'),
+ print(euclid_mod(64 * 67, 64 * 81))
+ print('[#]\nSubtraction-based euclidean algorithm result:')
+ print(euclid_sub(128 * 12, 128 * 77))
diff --git a/contents/euclidean_algorithm/code/racket/euclidean_algorithm.rkt b/contents/euclidean_algorithm/code/racket/euclidean_algorithm.rkt
index f170d8e17..8d19eab86 100755
--- a/contents/euclidean_algorithm/code/racket/euclidean_algorithm.rkt
+++ b/contents/euclidean_algorithm/code/racket/euclidean_algorithm.rkt
@@ -23,5 +23,7 @@
)
)
+(displayln "[#]\nModulus-based euclidean algorithm result:")
(displayln (euclid_sub (* 64 67) (* 64 81)))
+(displayln "[#]\nSubtraction-based euclidean algorithm result:")
(displayln (euclid_mod (* 128 12) (* 128 77)))
diff --git a/contents/euclidean_algorithm/code/ruby/euclidean.rb b/contents/euclidean_algorithm/code/ruby/euclidean.rb
index b8667ad71..b55bbd728 100644
--- a/contents/euclidean_algorithm/code/ruby/euclidean.rb
+++ b/contents/euclidean_algorithm/code/ruby/euclidean.rb
@@ -17,9 +17,8 @@ def gcd_minus(a, b)
end
a
end
-
-p gcd_mod(12 * 6, 12 * 4) #=> 12
-p gcd_mod(9 * 667, 9 * 104) #=> 9
-p gcd_minus(12 * 6, 12 * 4) #=> 12
-p gcd_minus(9 * 667, 9 * 104) #=> 9
+print "[#]\nModulus-based euclidean algorithm result:\n"
+p gcd_mod(64 * 67, 64 * 81)
+print "[#]\nSubtraction-based euclidean algorithm result:\n"
+p gcd_minus(128 * 12, 128 * 77)
diff --git a/contents/euclidean_algorithm/code/rust/euclidean_example.rs b/contents/euclidean_algorithm/code/rust/euclidean_example.rs
index 89b55ba22..1c9fb55f7 100644
--- a/contents/euclidean_algorithm/code/rust/euclidean_example.rs
+++ b/contents/euclidean_algorithm/code/rust/euclidean_example.rs
@@ -29,6 +29,6 @@ fn euclid_rem(mut a: i64, mut b: i64) -> i64 {
fn main() {
let chk1 = euclid_rem(64 * 67, 64 * 81);
let chk2 = euclid_sub(128 * 12, 128 * 77);
- println!("{}", chk1);
- println!("{}", chk2);
+ println!("[#]\nModulus-based euclidean algorithm result:\n{}", chk1);
+ println!("[#]\nSubtraction-based euclidean algorithm result:\n{}", chk2);
}
diff --git a/contents/euclidean_algorithm/code/scala/euclidean.scala b/contents/euclidean_algorithm/code/scala/euclidean.scala
index bc3fe103a..25079e603 100644
--- a/contents/euclidean_algorithm/code/scala/euclidean.scala
+++ b/contents/euclidean_algorithm/code/scala/euclidean.scala
@@ -3,8 +3,8 @@ object Euclid {
def euclid_sub(a: Int, b: Int): Int =
(Math.abs(a), Math.abs(b)) match {
case (0, _) | (_, 0) => 0
- case (x, y) if x < y => euclid(x, y - x)
- case (x, y) if x > y => euclid(x - y, y)
+ case (x, y) if x < y => euclid_sub(x, y - x)
+ case (x, y) if x > y => euclid_sub(x - y, y)
case _ => a
}
@@ -15,8 +15,10 @@ object Euclid {
}
def main(args: Array[String]): Unit = {
- println(euclid_sub(151 * 899, 151 * 182))
- println(euclid_mod(151 * 899, 151 * 182))
+ println("[#]\nModulus-based euclidean algorithm result:")
+ println(euclid_mod(64 * 67, 64 * 81))
+ println("[#]\nSubtraction-based euclidean algorithm result:")
+ println(euclid_sub(128 * 12, 128 * 77))
}
}
diff --git a/contents/euclidean_algorithm/code/scheme/euclidalg.ss b/contents/euclidean_algorithm/code/scheme/euclidalg.ss
index 3d891ba73..2cda992d8 100644
--- a/contents/euclidean_algorithm/code/scheme/euclidalg.ss
+++ b/contents/euclidean_algorithm/code/scheme/euclidalg.ss
@@ -11,5 +11,8 @@
a
(euclid-mod b (modulo a b))))
+(display "[#]\nModulus-based euclidean algorithm result:") (newline)
(display (euclid-mod (* 64 67) (* 64 81))) (newline)
-(display (euclid-sub (* 64 12) (* 64 27))) (newline)
+
+(display "[#]\nSubtraction-based euclidean algorithm result:") (newline)
+(display (euclid-sub (* 128 12) (* 128 77))) (newline)
diff --git a/contents/euclidean_algorithm/code/swift/euclidean_algorithm.swift b/contents/euclidean_algorithm/code/swift/euclidean_algorithm.swift
index 7b43959ad..9c2c71448 100644
--- a/contents/euclidean_algorithm/code/swift/euclidean_algorithm.swift
+++ b/contents/euclidean_algorithm/code/swift/euclidean_algorithm.swift
@@ -27,7 +27,9 @@ func euclidMod(a: Int, b: Int) -> Int {
}
func main() {
+ print("[#]\nModulus-based euclidean algorithm result:")
print(euclidMod(a: 64 * 67, b: 64 * 81))
+ print("[#]\nSubtraction-based euclidean algorithm result:")
print(euclidSub(a: 128 * 12, b: 128 * 77))
}
diff --git a/contents/euclidean_algorithm/euclidean_algorithm.md b/contents/euclidean_algorithm/euclidean_algorithm.md
index 035e7ae81..f75f6651f 100644
--- a/contents/euclidean_algorithm/euclidean_algorithm.md
+++ b/contents/euclidean_algorithm/euclidean_algorithm.md
@@ -14,7 +14,7 @@ The algorithm is a simple way to find the *greatest common divisor* (GCD) of two
{% sample lang="clj" %}
[import:2-8, lang="clojure"](code/clojure/euclidean_example.clj)
{% sample lang="cpp" %}
-[import:18-31, lang="c_cpp"](code/c++/euclidean.cpp)
+[import:18-31, lang="c_cpp"](code/cpp/euclidean.cpp)
{% sample lang="java" %}
[import:3-16, lang="java"](code/java/EuclideanAlgo.java)
{% sample lang="kotlin" %}
@@ -56,7 +56,7 @@ The algorithm is a simple way to find the *greatest common divisor* (GCD) of two
{% sample lang="scala" %}
[import:3-8, lang="scala"](code/scala/euclidean.scala)
{% sample lang="racket" %}
-[import:3-14, lang="lisp"](code/racket/euclidean_algorithm.rkt)
+[import:3-14, lang="racket"](code/racket/euclidean_algorithm.rkt)
{% sample lang="ruby" %}
[import:8-19, lang="ruby"](code/ruby/euclidean.rb)
{% sample lang="st" %}
@@ -104,7 +104,7 @@ Modern implementations, though, often use the modulus operator (%) like so
{% sample lang="clj" %}
[import:9-13, lang="clojure"](code/clojure/euclidean_example.clj)
{% sample lang="cpp" %}
-[import:5-15, lang="c_cpp"](code/c++/euclidean.cpp)
+[import:5-15, lang="c_cpp"](code/cpp/euclidean.cpp)
{% sample lang="java" %}
[import:18-26, lang="java"](code/java/EuclideanAlgo.java)
{% sample lang="kotlin" %}
@@ -146,7 +146,7 @@ Modern implementations, though, often use the modulus operator (%) like so
{% sample lang="scala" %}
[import:10-14, lang="scala"](code/scala/euclidean.scala)
{% sample lang="racket" %}
-[import:16-24, lang="lisp"](code/racket/euclidean_algorithm.rkt)
+[import:16-24, lang="racket"](code/racket/euclidean_algorithm.rkt)
{% sample lang="ruby" %}
[import:1-6, lang="ruby"](code/ruby/euclidean.rb)
{% sample lang="st" %}
@@ -189,7 +189,7 @@ The Euclidean Algorithm is truly fundamental to many other algorithms throughout
Here's a video on the Euclidean algorithm:
-
+
## Example Code
@@ -207,9 +207,11 @@ Here's a video on the Euclidean algorithm:
{% sample lang="clj" %}
[import, lang="clojure"](code/clojure/euclidean_example.clj)
{% sample lang="cpp" %}
-[import, lang="c_cpp"](code/c++/euclidean.cpp)
+[import, lang="c_cpp"](code/cpp/euclidean.cpp)
{% sample lang="java" %}
[import, lang="java"](code/java/EuclideanAlgo.java)
+{% sample lang="kotlin" %}
+[import, lang="kotlin"](code/kotlin/Euclidean.kt)
{% sample lang="js" %}
[import, lang="javascript"](code/javascript/euclidean_example.js)
{% sample lang="lisp" %}
@@ -250,7 +252,7 @@ and modulo method:
{% sample lang="scala" %}
[import, lang="scala"](code/scala/euclidean.scala)
{% sample lang="racket" %}
-[import, lang="lisp"](code/racket/euclidean_algorithm.rkt)
+[import, lang="racket"](code/racket/euclidean_algorithm.rkt)
{% sample lang="ruby" %}
[import, lang="ruby"](code/ruby/euclidean.rb)
{% sample lang="st" %}
@@ -300,7 +302,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/flood_fill/code/c/flood_fill.c b/contents/flood_fill/code/c/flood_fill.c
index d922412a1..03df6f1fb 100644
--- a/contents/flood_fill/code/c/flood_fill.c
+++ b/contents/flood_fill/code/c/flood_fill.c
@@ -25,7 +25,7 @@ int inbounds(struct point p, struct canvas c) {
return (p.x < 0 || p.y < 0 || p.y >= c.max_y || p.x >= c.max_x) ? 0 : 1;
}
-int find_neighbors(struct canvas c, struct point p, int old_val, int new_val,
+int find_neighbors(struct canvas c, struct point p, int old_val,
struct point *neighbors) {
int cnt = 0;
struct point points[4] = {
@@ -90,7 +90,7 @@ void stack_fill(struct canvas c, struct point p, int old_val, int new_val) {
c.data[cur_loc.x + c.max_x * cur_loc.y] = new_val;
struct point neighbors[4];
- int cnt = find_neighbors(c, cur_loc, old_val, new_val, neighbors);
+ int cnt = find_neighbors(c, cur_loc, old_val, neighbors);
for (int i = 0; i < cnt; ++i) {
stack_push(&stk, neighbors[i]);
@@ -160,7 +160,7 @@ void queue_fill(struct canvas c, struct point p, int old_val, int new_val) {
c.data[cur_loc.x + c.max_x * cur_loc.y] = new_val;
struct point neighbors[4];
- int cnt = find_neighbors(c, cur_loc, old_val, new_val, neighbors);
+ int cnt = find_neighbors(c, cur_loc, old_val, neighbors);
for (int i = 0; i < cnt; ++i) {
enqueue(&q, neighbors[i]);
@@ -181,7 +181,7 @@ void recursive_fill(struct canvas c, struct point p, int old_val,
c.data[p.x + c.max_x * p.y] = new_val;
struct point neighbors[4];
- int cnt = find_neighbors(c, p, old_val, new_val, neighbors);
+ int cnt = find_neighbors(c, p, old_val, neighbors);
for (int i = 0; i < cnt; ++i) {
recursive_fill(c, neighbors[i], old_val, new_val);
diff --git a/contents/flood_fill/code/coconut/flood_fill.coco b/contents/flood_fill/code/coconut/flood_fill.coco
new file mode 100644
index 000000000..861d4d04b
--- /dev/null
+++ b/contents/flood_fill/code/coconut/flood_fill.coco
@@ -0,0 +1,113 @@
+from collections import deque
+import numpy as np
+
+
+data Point(x, y):
+ def __add__(self, Point(other)) = Point(self.x + other.x, self.y + other.y)
+
+
+# This function is necessary, because negative indices wrap around the
+# array in Coconut.
+def inbounds(canvas_shape, Point(location)) =
+ min(location) >= 0 and location.x < canvas_shape[0] and location.y < canvas_shape[1]
+
+
+def find_neighbours(canvas, Point(location), old_value):
+ possible_neighbours = ((Point(0, 1), Point(1, 0), Point(0, -1), Point(-1, 0))
+ |> map$(location.__add__))
+
+ yield from possible_neighbours |> filter$(x -> (inbounds(canvas.shape, x)
+ and canvas[x] == old_value))
+
+
+def stack_fill(canvas, Point(location), old_value, new_value):
+ if new_value == old_value or not inbounds(canvas.shape, location):
+ return
+
+ stack = [location]
+
+ while stack:
+ current_location = stack.pop()
+ if canvas[current_location] == old_value:
+ canvas[current_location] = new_value
+ stack.extend(find_neighbours(canvas, current_location, old_value))
+
+
+def queue_fill(canvas, Point(location), old_value, new_value):
+ if new_value == old_value or not inbounds(canvas.shape, location):
+ return
+
+ queue = deque()
+ queue.append(location)
+
+ canvas[location] = new_value
+
+ while queue:
+ current_location = queue.popleft()
+ for neighbour in find_neighbours(canvas, current_location, old_value):
+ canvas[neighbour] = new_value
+ queue.append(neighbour)
+
+
+def recursive_fill(canvas, Point(location), old_value, new_value):
+ if new_value == old_value or not inbounds(canvas.shape, location):
+ return
+
+ canvas[location] = new_value
+ # consume is important here, because otherwise, the recursive function is not called again
+ consume(
+ find_neighbours(canvas, location, old_value)
+ |> map$(recursive_fill$(canvas, ?, old_value, new_value))
+ )
+
+
+def test_grid(initial_canvas, final_canvas, function):
+ canvas = initial_canvas.copy() # ensure the initial_canvas is unchanged
+ function(canvas)
+ return (canvas == final_canvas).all()
+
+def test():
+ from collections import namedtuple
+
+ TestResults = namedtuple('TestResults', 'passes failures')
+ pass_count = failure_count = 0
+
+ grid = np.zeros((5, 5))
+ grid[2,:] = 1
+ solution_grid = np.zeros((5, 5))
+ solution_grid[:3,] = 1
+
+ starting_location = Point(0, 0)
+
+ recursive_test_func = recursive_fill$(?, starting_location, 0, 1)
+ # The following is manual unit testing of the function
+ if test_grid(grid, solution_grid, recursive_test_func):
+ pass_count += 1
+ print('.', end='')
+ else:
+ failure_count += 1
+ print('F', end='')
+
+ stack_test_func = stack_fill$(?, starting_location, 0, 1)
+ if test_grid(grid, solution_grid, stack_test_func):
+ print('.', end='')
+ pass_count += 1
+ else:
+ print('F', end='')
+ failure_count += 1
+
+ queue_test_func = queue_fill$(?, starting_location, 0, 1)
+ if test_grid(grid, solution_grid, queue_test_func):
+ print('.', end='')
+ pass_count += 1
+ else:
+ print('F', end='')
+ failure_count += 1
+
+ print()
+ print(TestResults(pass_count, failure_count))
+
+if __name__ == '__main__':
+ # Testing setup
+ test()
+
diff --git a/contents/flood_fill/code/cpp/flood_fill.cpp b/contents/flood_fill/code/cpp/flood_fill.cpp
new file mode 100644
index 000000000..918566809
--- /dev/null
+++ b/contents/flood_fill/code/cpp/flood_fill.cpp
@@ -0,0 +1,156 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+using CartesianIndex = std::array;
+
+auto inbounds(CartesianIndex size, CartesianIndex loc) {
+ if (loc[0] < 0 || loc[1] < 0) {
+ return false;
+ } else if (loc[0] >= size[0] || loc[1] >= size[1]) {
+ return false;
+ }
+ return true;
+}
+
+auto find_neighbors(
+ std::vector> const& grid,
+ CartesianIndex loc,
+ float old_value,
+ float /* new_value */) {
+
+ const std::vector possible_neighbors{
+ {loc[0], loc[1] + 1},
+ {loc[0] + 1, loc[1]},
+ {loc[0], loc[1] - 1},
+ {loc[0] - 1, loc[1]}};
+
+ std::vector neighbors;
+
+ for (auto const& possible_neighbor : possible_neighbors) {
+ const auto size = CartesianIndex{
+ static_cast(grid[0].size()), static_cast(grid.size())};
+ const auto x = static_cast(possible_neighbor[0]);
+ const auto y = static_cast(possible_neighbor[1]);
+ if (inbounds(size, possible_neighbor) && grid[x][y] == old_value) {
+ neighbors.push_back(possible_neighbor);
+ }
+ }
+
+ return neighbors;
+}
+
+void recursive_fill(
+ std::vector>& grid,
+ CartesianIndex loc,
+ float old_value,
+ float new_value) {
+ if (old_value == new_value) {
+ return;
+ }
+
+ const auto x = static_cast(loc[0]);
+ const auto y = static_cast(loc[1]);
+
+ grid[x][y] = new_value;
+
+ const auto possible_neighbors = find_neighbors(grid, loc, old_value, new_value);
+ for (auto const& possible_neighbor : possible_neighbors) {
+ recursive_fill(grid, possible_neighbor, old_value, new_value);
+ }
+}
+
+void queue_fill(
+ std::vector>& grid,
+ CartesianIndex loc,
+ float old_value,
+ float new_value) {
+ if (old_value == new_value) {
+ return;
+ }
+
+ auto q = std::queue{};
+ q.push(loc);
+ const auto x = static_cast(loc[0]);
+ const auto y = static_cast(loc[1]);
+ grid[x][y] = new_value;
+
+ while (q.size() > 0) {
+ const auto current_loc = q.front();
+ q.pop();
+ const auto possible_neighbors =
+ find_neighbors(grid, current_loc, old_value, new_value);
+ for (auto const& neighbor : possible_neighbors) {
+ const auto neighbor_x = static_cast(neighbor[0]);
+ const auto neighbor_y = static_cast(neighbor[1]);
+ grid[neighbor_x][neighbor_y] = new_value;
+ q.push(neighbor);
+ }
+ }
+}
+
+void stack_fill(
+ std::vector>& grid,
+ CartesianIndex loc,
+ float old_value,
+ float new_value) {
+ if (old_value == new_value) {
+ return;
+ }
+
+ auto s = std::stack{};
+ s.push(loc);
+
+ while (s.size() > 0) {
+ const auto current_loc = s.top();
+ s.pop();
+
+ const auto x = static_cast(current_loc[0]);
+ const auto y = static_cast(current_loc[1]);
+
+ if (grid[x][y] == old_value) {
+ grid[x][y] = new_value;
+ const auto possible_neighbors =
+ find_neighbors(grid, current_loc, old_value, new_value);
+ for (auto const& neighbor : possible_neighbors) {
+ s.push(neighbor);
+ }
+ }
+ }
+}
+
+int main() {
+
+ const std::vector> grid{
+ {0, 0, 1, 0, 0},
+ {0, 0, 1, 0, 0},
+ {0, 0, 1, 0, 0},
+ {0, 0, 1, 0, 0},
+ {0, 0, 1, 0, 0}};
+
+ const std::vector> solution_grid{
+ {1, 1, 1, 0, 0},
+ {1, 1, 1, 0, 0},
+ {1, 1, 1, 0, 0},
+ {1, 1, 1, 0, 0},
+ {1, 1, 1, 0, 0}};
+
+ const CartesianIndex start_loc{1, 1};
+
+ auto test_grid = grid;
+ recursive_fill(test_grid, start_loc, 0.0, 1.0);
+ assert(test_grid == solution_grid);
+
+ test_grid = grid;
+ queue_fill(test_grid, start_loc, 0.0, 1.0);
+ assert(test_grid == solution_grid);
+
+ test_grid = grid;
+ stack_fill(test_grid, start_loc, 0.0, 1.0);
+ assert(test_grid == solution_grid);
+
+ return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/contents/flood_fill/flood_fill.md b/contents/flood_fill/flood_fill.md
index 87ec2b7a7..ed84683a6 100644
--- a/contents/flood_fill/flood_fill.md
+++ b/contents/flood_fill/flood_fill.md
@@ -90,8 +90,12 @@ In code, this might look like this:
[import:23-41, lang:"julia"](code/julia/flood_fill.jl)
{% sample lang="c" %}
[import:28-46, lang:"c"](code/c/flood_fill.c)
+{% sample lang="cpp" %}
+[import:19-44, lang:"cpp"](code/cpp/flood_fill.cpp)
{% sample lang="py" %}
[import:10-25, lang="python"](code/python/flood_fill.py)
+{% sample lang="coco" %}
+[import:15-20, lang="coconut"](code/coconut/flood_fill.coco)
{% endmethod %}
@@ -108,8 +112,12 @@ In code, it might look like this:
[import:92-104, lang:"julia"](code/julia/flood_fill.jl)
{% sample lang="c" %}
[import:174-189, lang:"c"](code/c/flood_fill.c)
+{% sample lang="cpp" %}
+[import:46-64, lang:"cpp"](code/cpp/flood_fill.cpp)
{% sample lang="py" %}
[import:55-63, lang="python"](code/python/flood_fill.py)
+{% sample lang="coco" %}
+[import:52-61, lang:"coconut"](code/coconut/flood_fill.coco)
{% endmethod %}
The above code continues recursing through available neighbors as long as neighbors exist, and this should work so long as we are adding the correct set of neighbors.
@@ -121,8 +129,12 @@ Additionally, it is possible to do the same type of traversal by managing a stac
[import:43-63, lang:"julia"](code/julia/flood_fill.jl)
{% sample lang="c" %}
[import:79-102, lang:"c"](code/c/flood_fill.c)
+{% sample lang="cpp" %}
+[import:95-123, lang:"cpp"](code/cpp/flood_fill.cpp)
{% sample lang="py" %}
[import:27-36, lang="python"](code/python/flood_fill.py)
+{% sample lang="coco" %}
+[import:23-34, lang:"coconut"](code/coconut/flood_fill.coco)
{% endmethod %}
This is ultimately the same method of traversal as before; however, because we are managing our own data structure, there are a few distinct differences:
@@ -162,8 +174,12 @@ The code would look something like this:
[import:66-90, lang:"julia"](code/julia/flood_fill.jl)
{% sample lang="c" %}
[import:149-172, lang:"c"](code/c/flood_fill.c)
+{% sample lang="cpp" %}
+[import:66-93, lang:"cpp"](code/cpp/flood_fill.cpp)
{% sample lang="py" %}
[import:38-53, lang="python"](code/python/flood_fill.py)
+{% sample lang="coco" %}
+[import:36-49, lang:"coconut"](code/coconut/flood_fill.coco)
{% endmethod %}
Now, there is a small trick in this code that must be considered to make sure it runs optimally.
@@ -228,7 +244,7 @@ These will all be covered in subsequent chapters which will come out somewhat re
Here is a video describing tree traversal:
-
+
## Example Code
@@ -242,8 +258,12 @@ After, we will fill in the left-hand side of the array to be all ones by choosin
[import, lang:"julia"](code/julia/flood_fill.jl)
{% sample lang="c" %}
[import, lang:"c"](code/c/flood_fill.c)
+{% sample lang="cpp" %}
+[import, lang:"cpp"](code/cpp/flood_fill.cpp)
{% sample lang="py" %}
[import:, lang="python"](code/python/flood_fill.py)
+{% sample lang="coco" %}
+[import, lang="coconut"](code/coconut/flood_fill.coco)
{% endmethod %}
@@ -259,7 +279,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/flood_fill/flood_fill.md.bak b/contents/flood_fill/flood_fill.md.bak
deleted file mode 100644
index d15b1ef97..000000000
--- a/contents/flood_fill/flood_fill.md.bak
+++ /dev/null
@@ -1,258 +0,0 @@
-# Flood Fill
-
-Flood fill is a method that is surprisingly useful in a large number of different situations and keeps finding me wherever I go.
-When I was completing my PhD, I had an idea to track superfluid vortices by using flood fill as a way to help mask out unnecessary features of the simulation.
-When I was making a terminal game, I thought of creating an animation that was just flood fill in disguise.
-When I decided to play minesweeper or Go with my girlfriend, flood fill was used in both!
-
-Flood fill is probably most commonly known as the "Bucket Fill" application in most art programs {{ "gimp_bucket" | cite }}.
-It's usually indicated by an icon that looks like a bucket and is known to fill in any enclosed area, as shown below:
-
-
-
-
-
-Because flood fill is incredibly common, there are a large number of variations to the method, some of which are more optimal than others.
-For this chapter, we will cover the basics: how to fill a domain in a quick and dirty way.
-In subsequent chapters, we will continue our journey by creating more and more efficient flood fill methods, including scanline-based and fixed memory methods {{ "torbert2016" | cite }}.
-
-I have decided to split the chapter up for a few important reasons:
-1. I did not want to flood the Algorithm Archive with flood fill methods all at the same time.
-I feel it's worth letting each chapter sit for a bit while we savour it's unique flavour.
-2. Many users are implementing versions of each algorithm in their own languages and it is difficult to review and submit code for chapters with a lot of code chunks.
-Several sub-chapters with less code is easier for everyone.
-3. I am kinda under a time-constraint right now and wanted to make sure we regularly get content into the Algorithm Archive.
-
-So, without further a-do, let's hop right into it!
-
-
-## What does flood fill do?
-
-Flood fill is essentially composed of 2 parts:
-1. Determining the extents of the domain to fill
-2. Walking through all elements within a domain and changing some property
-
-For the purposes of this chapter, we will be using a set of floating-point values that range from 0 to 1 instead of a color-space like RGB.
-Though bucket fill is always used in art programs in some sort of color space, flood fill is more general and can be used in a space with any type of element.
-As such, it makes sense to use a simpler element type so we can better understand the method.
-
-So how do we go about finding the extents of the domain to fill?
-
-Here, a domain will be defined as any connected set of elements in an $$n$$-dimensional space whose values do not vary beyond a pre-defined threshold.
-As an example, if we take a circle embedded into a 2-dimensional grid, we have 3 separate domains:
-1. Inside the circle where all elements are 0.
-2. The circle, itself, where the elements are set to 0.75.
-3. Outside the circle where all elements are similarly 0.
-
-
-
-
-
-Though there are some more complicated ways to determine the extents of the domain, we will not focus on this aspect of the flood fill method for the remainder of this chapter and instead leave it for subsequent chapters.
-So now we will focus on the process of walking through each element in the domain and changing some property.
-
-## Domain traversal
-
-As before, the simplest example to work with is that of an image, where each element in our domain is a single pixel.
-Here, we can connect each pixel to all other pixels in its vicinity, like so:
-
-
-
-
-
-In this image, a border is shown between each individual pixel and a grid is superimposed to show how each pixel is connected to its neighbors.
-This means that each element has 4 neighbors: north, south, east, and west.
-We could also include northeast, southeast, southwest, and northwest if we wanted to do an 8-way fill, but we will restrict the discussion to the 4-way fill for now, as the method is essentially the same and slightly easier to understand with fewer elements to worry about.
-
-By connecting each pixel to its neighbors in this way, the flood fill operation becomes a process of graph traversal, not too dissimilar from the [tree traversal](../tree_traversal/tree_traversal.md) methods described before.
-This means that after selecting our initial location, we can then traverse through all elements in either a depth-first or breadth-first fashion.
-We will be covering the following this chapter:
-
-1. Finding all neighbours
-2. Depth-first node traversal
-3. Breadth-first node traversal and small-scale optimizations
-
-So let's start by discussing how we might go about finding the neighbors to fill.
-
-### Finding all neighbors
-
-The first step of this method is to query the location of all possible neighbors.
-At first glance, this seems rather straightforward.
-One simply needs to look up, down, left, and right of the current location and add those elements to the list of neighbors if they are:
-
-1. On the canvas
-2. Have a value *close enough* to the old value we would like to replace
-
-In code, this might look like this:
-
-{% method %}
-{% sample lang="jl" %}
-[import:37-55, lang:"julia"](code/julia/flood_fill.jl)
-{% endmethod %}
-
-
-This code is set up to return a vector of elements to then use for subsequent sections.
-
-### Depth-first node traversal
-
-Now that we have the ability to find all neighboring elements, we can proceed to traverse through those nodes in the most straightforward way: recursion.
-
-In code, it might look like this:
-
-{% method %}
-{% sample lang="jl" %}
-[import:106-118, lang:"julia"](code/julia/flood_fill.jl)
-
-All Julia code snippets for this chapter rely on an exterior `color!(...)` function, defined as
-
-[import:23-35, lang:"julia"](code/julia/flood_fill.jl)
-{% endmethod %}
-
-The above code continues recursing through available neighbors as long as neighbors exist, and this should work so long as we are adding the correct set of neighbors.
-
-Additionally, it is possible to do the same type of traversal by managing a stack, like so:
-
-{% method %}
-{% sample lang="jl" %}
-[import:57-77, lang:"julia"](code/julia/flood_fill.jl)
-{% endmethod %}
-
-This is ultimately the same method of traversal as before; however, because we are managing our own data structure, there are a few distinct differences:
-1. The manually managed stack could be slightly slower and potentially more memory-intensive
-2. It is easy to reach the maximum recursion depth on certain hardware with the recursive method, so it is best to use the stack-based implementation in those cases.
-
-If we were to use either of these methods to fill a circle embedded in a two dimensional domain, we would see the following
-
-
-
-
-
-Here, we see that these methods will traverse through one direction first before filling from there.
-This is potentially the easiest method to write, but it is not the most intuitive fill pattern.
-I suspect that if someone was asked to fill the contents of the circle on their own, they would fill it more evenly from the center, like so:
-
-
-
-
-
-This is simply another traversal strategy known as breadth-first traversal and comes with its own set of caveats.
-We will discuss this further in the next subsection
-
-### Breadth-first node traversal and small-scale optimizations
-
-Breadth-first node traversal is as simple as switching the stack in the depth-first strategy with a queue.
-The code would look something like this:
-
-{% method %}
-{% sample lang="jl" %}
-[import:80-104, lang:"julia"](code/julia/flood_fill.jl)
-{% endmethod %}
-
-Now, there is a small trick in this code that must be considered to make sure it runs optimally.
-Namely, the nodes must be colored *when they are being enqueued*, not when visiting the node.
-At least for me, it was not immediately obvious why this would be the case, but let me try to explain.
-
-Let's imagine that we decided to write code that colored all neighboring nodes only when visiting them.
-When querying all possible neighbors, we will add 4 elements to the queue for the north, south, east, and west neighbors of the initial node, as shown below:
-
-
-
-
-
-Now let's imagine we travel east first.
-It then enqueues three more nodes: north, south, and east again.
-This is shown below:
-
-
-
-
-
-It does not enqueue its west neighbour because this has already been colored.
-At this stage, we will have six nodes ready to be colored and 2 that are already colored.
-Now let's say we travel north next.
-This node will enqueue three more nodes: west, north, and east, as shown below:
-
-
-
-
-
-The problem is that the east element has *already been enqueued for coloring by the previous node*!.
-This shared element is colored in red.
-As we progress through all four initial neighbours, we will find 4 nodes that are doubly enqueued: all directions diagonal to the initial location!
-This is again shown below:
-
-
-
-
-
-As the number of nodes increases, so does the number of duplicate nodes.
-A quick fix is to color the nodes *when they are being enqueud* like in the example code above.
-When doing this, duplicates will not be enqueued with a breadth-first scheme because they will already be colored when other nodes are trying to find their neighbors.
-This created a node connection pattern like so:
-
-
-
-
-
-As some final food for thought: why wasn't this a problem with the depth-first strategy?
-The simple answer is that it actually was an issue, but it was way less prevalent.
-With the depth-first strategy, a number of unnecessary nodes are still pushed to the stack, but because we consistently push one direction before spreading out to other directions, it is more likely that the nodes have filled neighbours when they are looking for what to fill around them.
-
-Simply put: depth-first traversal is slightly more efficient in this case unless you can color as querying for neighbors, in which case breadth-first is more efficient.
-
-## Conclusions
-
-As stated before, the method discussed in this chapter is just the tip of the iceberg and many other flood fill methods exist that are likely to be more efficient for most purposes.
-These will all be covered in subsequent chapters which will come out somewhat regularly throughout the next few months, lest we flood that archive with flood fill methods.
-
-## Example Code
-
-The example code for this chapter will be the simplest application of flood fill that still adequately tests the code to ensure it is stopping at boundaries appropriately.
-For this, we will create a two dimensional array of floats, all starting at 0.0, and then set a single vertical line of elements at the center to be 1.0.
-After, we will fill in the left-hand side of the array to be all ones by choosing any point within the left domain to fill.
-
-{% method %}
-{% sample lang="jl" %}
-[import, lang:"julia"](code/julia/flood_fill.jl)
-{% endmethod %}
-
-
-### Bibliography
-
-{% references %} {% endreferences %}
-
-
-
-## License
-
-##### Code Examples
-
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
-
-##### Text
-
-The text of this chapter was written by [James Schloss](https://github.com/leio) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-
-[
](https://creativecommons.org/licenses/by-sa/4.0/)
-
-##### Images/Graphics
-- The image "[Example Bucket Fill](res/example.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-- The image "[Circle Domains](res/simple_circle.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-- The image "[Grid 1](res/grid_1.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-- The image "[Grid 2](res/grid_2.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-- The image "[Grid 3](res/grid_3.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-- The image "[Grid 4](res/grid_4.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-- The image "[Grid 5](res/grid_5.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-- The image "[Grid 6](res/grid_6.png)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-- The video "[Stack Fill](res/recurse_animation.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-- The video "[Queue Fill](res/queue_animation.mp4)" was created by [James Schloss](https://github.com/leios) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
-
-
diff --git a/contents/fortran/fortran.md b/contents/fortran/fortran.md
index f705d3c17..491a33b6e 100644
--- a/contents/fortran/fortran.md
+++ b/contents/fortran/fortran.md
@@ -6,7 +6,7 @@ Alright, so here's the thing about Fortran. It's old.
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/forward_euler_method/code/asm-x64/SConscript b/contents/forward_euler_method/code/asm-x64/SConscript
new file mode 100644
index 000000000..2a10fbc14
--- /dev/null
+++ b/contents/forward_euler_method/code/asm-x64/SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.X64(build_target, str(file_info.path), LIBS='m', LINKFLAGS='-no-pie')
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/contents/forward_euler_method/code/c/SConscript b/contents/forward_euler_method/code/c/SConscript
new file mode 100644
index 000000000..b81220a0e
--- /dev/null
+++ b/contents/forward_euler_method/code/c/SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.C(build_target, str(file_info.path), LIBS='m')
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/contents/forward_euler_method/code/c/euler.c b/contents/forward_euler_method/code/c/euler.c
index 9ce095930..211e2f614 100644
--- a/contents/forward_euler_method/code/c/euler.c
+++ b/contents/forward_euler_method/code/c/euler.c
@@ -13,7 +13,7 @@ void solve_euler(double timestep, double *result, size_t n) {
int check_result(double *result, size_t n, double threshold, double timestep) {
int is_approx = 1;
for (size_t i = 0; i < n; ++i) {
- double solution = exp(-3.0 * i * timestep);
+ double solution = exp(-3.0 * (double)i * timestep);
if (fabs(result[i] - solution) > threshold) {
printf("%f %f\n", result[i], solution);
is_approx = 0;
diff --git a/contents/forward_euler_method/code/coconut/euler.coco b/contents/forward_euler_method/code/coconut/euler.coco
new file mode 100644
index 000000000..7297e9c51
--- /dev/null
+++ b/contents/forward_euler_method/code/coconut/euler.coco
@@ -0,0 +1,28 @@
+import math
+
+def forward_euler(time_step, n):
+ factors = [1] + [1 - 3 * time_step] * (n-1)
+ # We want all the cumulative values, thus the use of scan
+ return scan((*), factors)
+
+
+
+def check(result, threshold, time_step):
+ approx = True
+ # A scan object has a len if the underlying iterable has a len
+ solution = range(len(result)) |> map$(i -> math.exp(-3*i*time_step))
+ for y, sol in zip(result, solution):
+ if not math.isclose(y, sol, abs_tol=threshold):
+ print(y, sol)
+ approx = False
+ return approx
+
+
+if __name__ == '__main__':
+ time_step = 0.01
+ n = 100
+ threshold = 0.01
+
+ result = forward_euler(time_step, n)
+ approx = check(result, threshold, time_step)
+ print("All values within threshold") if approx else print("Value(s) not in threshold")
diff --git a/contents/forward_euler_method/code/c++/euler.cpp b/contents/forward_euler_method/code/cpp/euler.cpp
similarity index 95%
rename from contents/forward_euler_method/code/c++/euler.cpp
rename to contents/forward_euler_method/code/cpp/euler.cpp
index a341655f4..0fbeb8426 100644
--- a/contents/forward_euler_method/code/c++/euler.cpp
+++ b/contents/forward_euler_method/code/cpp/euler.cpp
@@ -27,7 +27,7 @@ template
bool check_result(Iter first, Iter last, double threshold, double timestep) {
auto it = first;
for (size_t idx = 0; it != last; ++idx, ++it) {
- double solution = std::exp(-3.0 * idx * timestep);
+ double solution = std::exp(-3.0 * static_cast(idx) * timestep);
if (std::abs(*it - solution) > threshold) {
std::cout << "We found a value outside the threshold; the " << idx
<< "-th value was " << *it << ", but the expected solution was "
diff --git a/contents/forward_euler_method/code/elm/elm-package.json b/contents/forward_euler_method/code/elm/elm-package.json
deleted file mode 100644
index fccb4595b..000000000
--- a/contents/forward_euler_method/code/elm/elm-package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "version": "1.0.0",
- "summary": "helpful summary of your project, less than 80 characters",
- "repository": "https://github.com/user/project.git",
- "license": "BSD3",
- "source-directories": [
- "."
- ],
- "exposed-modules": [],
- "dependencies": {
- "CallumJHays/elm-sliders": "1.0.1 <= v < 2.0.0",
- "elm-lang/core": "5.1.1 <= v < 6.0.0",
- "elm-lang/html": "2.0.0 <= v < 3.0.0",
- "elm-lang/mouse": "1.0.1 <= v < 2.0.0",
- "elm-lang/svg": "2.0.0 <= v < 3.0.0",
- "elm-lang/window": "1.0.1 <= v < 2.0.0",
- "rtfeldman/hex": "1.0.0 <= v < 2.0.0"
- },
- "elm-version": "0.18.0 <= v < 0.19.0"
-}
diff --git a/contents/forward_euler_method/code/elm/elm.json b/contents/forward_euler_method/code/elm/elm.json
new file mode 100644
index 000000000..5eac761dd
--- /dev/null
+++ b/contents/forward_euler_method/code/elm/elm.json
@@ -0,0 +1,28 @@
+{
+ "type": "application",
+ "source-directories": [
+ "src"
+ ],
+ "elm-version": "0.19.1",
+ "dependencies": {
+ "direct": {
+ "bemyak/elm-slider": "1.0.0",
+ "elm/browser": "1.0.2",
+ "elm/core": "1.0.5",
+ "elm/html": "1.0.0",
+ "elm/json": "1.1.3",
+ "elm/svg": "1.0.1",
+ "elm/time": "1.0.0",
+ "rtfeldman/elm-hex": "1.0.0"
+ },
+ "indirect": {
+ "debois/elm-dom": "1.3.0",
+ "elm/url": "1.0.0",
+ "elm/virtual-dom": "1.0.2"
+ }
+ },
+ "test-dependencies": {
+ "direct": {},
+ "indirect": {}
+ }
+}
diff --git a/contents/forward_euler_method/code/elm/euler.elm b/contents/forward_euler_method/code/elm/euler.elm
deleted file mode 100644
index a8d8d3c89..000000000
--- a/contents/forward_euler_method/code/elm/euler.elm
+++ /dev/null
@@ -1,332 +0,0 @@
-module Euler exposing (..)
-
-import Html exposing (Html, div, button, text, h3)
-import Html.Attributes exposing (style)
-import Html.Events exposing (onClick, on)
-import Time exposing (Time, second)
-import Maybe exposing (withDefault)
-import Window exposing (Size, size)
-import Svg exposing (svg, circle, line, polyline)
-import Svg.Attributes exposing (width, height, stroke, x1, x2, y1, y2, cx, cy, r, points, fill)
-import Task exposing (perform)
-import Slider exposing (..)
-import Mouse
-import Json.Decode as Decode
-import Hex
-
-
-main =
- Html.program
- { init = init
- , view = view
- , update = update
- , subscriptions = subscriptions
- }
-
-
-
--- MODEL
-
-
-type alias Model =
- { part : Particle
- , dt : Time
- , dt0 : Time
- , t : Time
- , status : Status
- , wWidth : Int
- , wHeight : Int
- , history : List ( Time, Time, Particle )
- , drag : Maybe Drag
- }
-
-
-type alias Position =
- Float
-
-
-type alias Velocity =
- Float
-
-
-type alias Particle =
- { pos : List Position, vel : List Velocity }
-
-
-type Status
- = Idle
- | Running
-
-
-type alias Drag =
- { start : Position
- , current : Position
- }
-
-
-getX : Particle -> Position
-getX p =
- withDefault 0 <| List.head <| .pos p
-
-
-getV : Particle -> Velocity
-getV p =
- withDefault 0 <| List.head <| .vel p
-
-
-getX0 : Model -> Position
-getX0 m =
- let
- scale x =
- 3 - 6 * x / (toFloat m.wHeight)
- in
- case m.drag of
- Nothing ->
- getX m.part
-
- Just { start, current } ->
- getX m.part + scale current - scale start
-
-
-
--- INIT
-
-
-init : ( Model, Cmd Msg )
-init =
- ( Model (Particle [ x0 ] [ 0 ]) 0.5 0.5 0 Idle 0 0 [] Nothing, perform GetSize size )
-
-
-x0 : Position
-x0 =
- 2.5
-
-
-
--- UPDATE
-
-
-type Msg
- = Start
- | Stop
- | Tick Time
- | GetSize Size
- | SliderUpdate Float
- | DragStart Mouse.Position
- | DragAt Mouse.Position
- | DragEnd Mouse.Position
-
-
-update : Msg -> Model -> ( Model, Cmd Msg )
-update msg model =
- case msg of
- Start ->
- ( { model
- | status = Running
- , t = 0
- , dt = model.dt0
- , drag = Nothing
- }
- , Cmd.none
- )
-
- Stop ->
- ( { model
- | status = Idle
- , part = Particle [ x0 ] [ 0 ]
- , t = 0
- }
- , Cmd.none
- )
-
- Tick _ ->
- case model.status of
- Idle ->
- ( model, Cmd.none )
-
- Running ->
- if model.t > 5 + model.dt then
- ( { model
- | status = Idle
- , part = Particle [ x0 ] [ 0 ]
- , history = ( model.dt, model.t, model.part ) :: model.history
- , t = 0
- }
- , Cmd.none
- )
- else
- ( { model
- | part = evolve model.part model.t model.dt
- , t = model.t + model.dt
- }
- , perform GetSize size
- )
-
- GetSize s ->
- ( { model | wWidth = s.width, wHeight = s.height * 8 // 10 }, Cmd.none )
-
- SliderUpdate dt ->
- ( { model | dt0 = dt }, Cmd.none )
-
- DragStart { x, y } ->
- case model.status of
- Idle ->
- ( { model | drag = Just (Drag (toFloat y) (toFloat y)) }, Cmd.none )
-
- Running ->
- ( model, Cmd.none )
-
- DragAt { x, y } ->
- ( { model | drag = Maybe.map (\{ start } -> Drag start (toFloat y)) model.drag }
- , Cmd.none
- )
-
- DragEnd _ ->
- ( { model
- | drag = Nothing
- , part = Particle [ getX0 model ] [ k * getX0 model ]
- }
- , Cmd.none
- )
-
-
-k : Float
-k =
- -2
-
-
-diffEq : Position -> Velocity -> Time -> Time -> ( Position, Velocity )
-diffEq x v t dt =
- ( x + (k * x) * dt, k * (x + (k * x) * dt) )
-
-
-evolve : Particle -> Time -> Time -> Particle
-evolve p t dt =
- let
- ( x, v ) =
- diffEq (getX p) (getV p) t dt
- in
- { p | pos = x :: p.pos, vel = v :: p.vel }
-
-
-
--- SUBSCRIPTIONS
-
-
-subscriptions : Model -> Sub Msg
-subscriptions model =
- case model.drag of
- Nothing ->
- Time.every (model.dt * second) Tick
-
- Just _ ->
- Sub.batch [ Mouse.moves DragAt, Mouse.ups DragEnd ]
-
-
-
--- VIEW
-
-
-view : Model -> Html Msg
-view model =
- div []
- [ h3 [] [ text "Drag the ball up or down, pick a dt and click Start" ]
- , h3 [ style [ ( "color", gradient model.dt0 ) ] ]
- [ viewSlider
- , text ("dt = " ++ toString model.dt0)
- , button [ onClick Start ] [ text "Start" ]
- , button [ onClick Stop ] [ text "Stop" ]
- ]
- , svg
- [ width (toString model.wWidth)
- , height (toString model.wHeight)
- , stroke "black"
- ]
- ([ line
- [ x1 "0"
- , x2 (toString model.wWidth)
- , y1 (toString (model.wHeight // 2))
- , y2 (toString (model.wHeight // 2))
- ]
- []
- , line
- [ x1 (toString (model.wWidth // 20))
- , x2 (toString (model.wWidth // 20))
- , y1 "0"
- , y2 (toString model.wHeight)
- ]
- []
- , viewCircle model
- ]
- ++ (plotHistory model)
- )
- ]
-
-
-viewSlider : Html Msg
-viewSlider =
- props2view [ MinVal 0, MaxVal 1, Step 0.01, onChange SliderUpdate ]
-
-
-scaleX : Int -> Position -> String
-scaleX h x =
- toString (toFloat h / 2 * (1 - x / 3))
-
-
-scaleT : Int -> Time -> String
-scaleT w t =
- toString (toFloat w * (0.05 + t / 5))
-
-
-viewCircle : Model -> Html Msg
-viewCircle m =
- circle
- [ cy (scaleX m.wHeight (getX0 m))
- , cx (scaleT m.wWidth m.t)
- , r "10"
- , on "mousedown" (Decode.map DragStart Mouse.position)
- ]
- []
-
-
-plotPath : Int -> Int -> ( Time, Time, Particle ) -> String
-plotPath w h ( dt, tf, particle ) =
- let
- comb x ( t, s ) =
- ( t - dt, s ++ (scaleT w t) ++ "," ++ (scaleX h x) ++ " " )
- in
- Tuple.second <| List.foldl comb ( tf, "" ) particle.pos
-
-
-plotHistory : Model -> List (Html Msg)
-plotHistory m =
- let
- ( w, h ) =
- ( m.wWidth, m.wHeight )
- in
- List.map
- (\( dt, t, p ) ->
- polyline
- [ stroke "black"
- , fill "none"
- , stroke (gradient dt)
- , points (plotPath w h ( dt, t, p ))
- ]
- []
- )
- (( m.dt, m.t, m.part ) :: m.history)
-
-
-gradient : Time -> String
-gradient dt =
- let
- ( r, g, b ) =
- ( round (255 * dt), 0, round (255 * (1 - dt)) )
-
- col =
- Hex.toString (256 * (256 * r + g) + b)
- in
- if String.length col < 6 then
- "#" ++ String.repeat (6 - String.length col) "0" ++ col
- else
- "#" ++ col
diff --git a/contents/forward_euler_method/code/elm/src/Euler.elm b/contents/forward_euler_method/code/elm/src/Euler.elm
new file mode 100644
index 000000000..c9207d2de
--- /dev/null
+++ b/contents/forward_euler_method/code/elm/src/Euler.elm
@@ -0,0 +1,397 @@
+module Euler exposing (..)
+
+import Browser
+import Browser.Dom exposing (Viewport)
+import Browser.Events as Events
+import Hex
+import Html exposing (Html, button, div, h3, text)
+import Html.Attributes exposing (style)
+import Html.Events exposing (on, onClick)
+import Json.Decode as Decode exposing (Decoder)
+import Maybe
+import SingleSlider as Slider
+import Svg exposing (circle, line, polyline, svg)
+import Svg.Attributes exposing (cx, cy, fill, height, points, r, stroke, width, x1, x2, y1, y2)
+import Task
+import Time exposing (Posix)
+
+
+main : Platform.Program () Model Msg
+main =
+ Browser.element
+ { init = \() -> init
+ , view = view
+ , update = update
+ , subscriptions = subscriptions
+ }
+
+
+
+-- MODEL
+
+
+type alias Model =
+ { part : Particle
+ , dt : Time
+ , dt0 : Time
+ , t : Time
+ , status : Status
+ , wWidth : Float
+ , wHeight : Float
+ , history : List ( Time, Time, Particle )
+ , drag : Maybe Drag
+ , slider : Slider.Model
+ }
+
+
+x0 : Position
+x0 =
+ 2.5
+
+
+init : ( Model, Cmd Msg )
+init =
+ ( { part = Particle [ x0 ] [ 0 ]
+ , dt = 0.25
+ , dt0 = 0.25
+ , t = 0
+ , status = Idle
+ , wWidth = 0
+ , wHeight = 0
+ , history = []
+ , drag = Nothing
+ , slider =
+ { min = 0
+ , max = 1
+ , step = 0.01
+ , value = 0.25
+ , minFormatter = \_ -> ""
+ , maxFormatter = \_ -> ""
+ , currentValueFormatter = \_ _ -> ""
+ , disabled = False
+ }
+ }
+ , Task.perform GetViewPort Browser.Dom.getViewport
+ )
+
+
+type alias Time =
+ Float
+
+
+type alias Position =
+ Float
+
+
+type alias Velocity =
+ Float
+
+
+type alias Particle =
+ { pos : List Position, vel : List Velocity }
+
+
+type Status
+ = Idle
+ | Running
+
+
+type alias Drag =
+ { start : Float
+ , current : Float
+ }
+
+
+getX : Particle -> Position
+getX p =
+ Maybe.withDefault 0 <| List.head <| .pos p
+
+
+getV : Particle -> Velocity
+getV p =
+ Maybe.withDefault 0 <| List.head <| .vel p
+
+
+getX0 : Model -> Position
+getX0 m =
+ let
+ scale x =
+ 3 - 6 * x / m.wHeight
+ in
+ case m.drag of
+ Nothing ->
+ getX m.part
+
+ Just { start, current } ->
+ getX m.part + scale current - scale start
+
+
+resetParticle : Particle -> Particle
+resetParticle { pos, vel } =
+ case ( List.reverse pos, List.reverse vel ) of
+ ( x :: _, v :: _ ) ->
+ Particle [ x ] [ v ]
+
+ _ ->
+ Particle [ x0 ] [ 0 ]
+
+
+
+-- UPDATE
+
+
+type Msg
+ = Start
+ | Stop
+ | Tick Posix
+ | GetViewPort Viewport
+ | SliderUpdate Float
+ | SliderMsg Slider.Msg
+ | DragStart Float
+ | DragAt Float
+ | DragEnd Float
+
+
+update : Msg -> Model -> ( Model, Cmd Msg )
+update msg model =
+ case msg of
+ Start ->
+ ( { model
+ | status = Running
+ , t = 0
+ , dt = model.dt0
+ , drag = Nothing
+ , part = resetParticle model.part
+ }
+ , Cmd.none
+ )
+
+ Stop ->
+ ( { model
+ | status = Idle
+ , part = resetParticle model.part
+ , t = 0
+ }
+ , Cmd.none
+ )
+
+ Tick _ ->
+ case model.status of
+ Idle ->
+ ( model, Cmd.none )
+
+ Running ->
+ if model.t > 5 + model.dt then
+ ( { model
+ | status = Idle
+ , part = Particle [ x0 ] [ 0 ]
+ , history = ( model.dt, model.t, model.part ) :: model.history
+ , t = 0
+ }
+ , Cmd.none
+ )
+
+ else
+ ( { model
+ | part = evolve model.part model.t model.dt
+ , t = model.t + model.dt
+ }
+ , Task.perform GetViewPort Browser.Dom.getViewport
+ )
+
+ GetViewPort { viewport } ->
+ ( { model | wWidth = viewport.width, wHeight = viewport.height * 8 / 10 }, Cmd.none )
+
+ SliderUpdate dt ->
+ ( { model | dt0 = dt }, Cmd.none )
+
+ SliderMsg sliderMsg ->
+ let
+ ( newSlider, cmd, updateResults ) =
+ Slider.update sliderMsg model.slider
+
+ newModel =
+ { model | slider = newSlider, dt0 = newSlider.value }
+
+ newCmd =
+ if updateResults then
+ Cmd.batch [ Cmd.map SliderMsg cmd, Cmd.none ]
+
+ else
+ Cmd.none
+ in
+ ( newModel, newCmd )
+
+ DragStart y ->
+ case model.status of
+ Idle ->
+ ( { model | drag = Just (Drag y y) }, Cmd.none )
+
+ Running ->
+ ( model, Cmd.none )
+
+ DragAt y ->
+ ( { model | drag = Maybe.map (\{ start } -> Drag start y) model.drag }
+ , Cmd.none
+ )
+
+ DragEnd _ ->
+ ( { model
+ | drag = Nothing
+ , part = Particle [ getX0 model ] [ k * getX0 model ]
+ }
+ , Cmd.none
+ )
+
+
+k : Float
+k =
+ -2
+
+
+diffEq : Position -> Velocity -> Time -> Time -> ( Position, Velocity )
+diffEq x _ _ dt =
+ ( x + (k * x) * dt, k * (x + (k * x) * dt) )
+
+
+evolve : Particle -> Time -> Time -> Particle
+evolve p t dt =
+ let
+ ( x, v ) =
+ diffEq (getX p) (getV p) t dt
+ in
+ { p | pos = x :: p.pos, vel = v :: p.vel }
+
+
+
+-- SUBSCRIPTIONS
+
+
+subscriptions : Model -> Sub Msg
+subscriptions model =
+ (Slider.subscriptions model.slider |> Sub.map SliderMsg)
+ :: (case model.drag of
+ Nothing ->
+ [ Time.every (model.dt * 1000) Tick ]
+
+ Just _ ->
+ [ Events.onMouseMove (Decode.map DragAt decodeMouseHeight)
+ , Events.onMouseUp (Decode.map DragEnd decodeMouseHeight)
+ ]
+ )
+ |> Sub.batch
+
+
+decodeMouseHeight : Decoder Float
+decodeMouseHeight =
+ Decode.field "pageY" Decode.float
+
+
+
+-- VIEW
+
+
+view : Model -> Html Msg
+view model =
+ div []
+ [ h3 [] [ text "Drag the ball up or down, pick a dt and click Start" ]
+ , h3 [ style "color" (gradient model.dt0) ]
+ [ viewSlider model.slider
+ , button [ onClick Start ] [ text "Start" ]
+ , button [ onClick Stop ] [ text "Stop" ]
+ , text ("dt = " ++ String.fromFloat model.dt0)
+ ]
+ , svg
+ [ width (String.fromFloat model.wWidth)
+ , height (String.fromFloat model.wHeight)
+ , stroke "black"
+ ]
+ ([ line
+ [ x1 "0"
+ , x2 (String.fromFloat model.wWidth)
+ , y1 (String.fromFloat (model.wHeight / 2))
+ , y2 (String.fromFloat (model.wHeight / 2))
+ ]
+ []
+ , line
+ [ x1 (String.fromFloat (model.wWidth / 20))
+ , x2 (String.fromFloat (model.wWidth / 20))
+ , y1 "0"
+ , y2 (String.fromFloat model.wHeight)
+ ]
+ []
+ , viewCircle model
+ ]
+ ++ plotHistory model
+ )
+ ]
+
+
+viewSlider : Slider.Model -> Html Msg
+viewSlider slider =
+ Slider.view slider |> Html.map SliderMsg
+
+
+scaleX : Float -> Position -> String
+scaleX h x =
+ String.fromFloat (h / 2 * (1 - x / 3))
+
+
+scaleT : Float -> Time -> String
+scaleT w t =
+ String.fromFloat (w * (0.05 + t / 5))
+
+
+viewCircle : Model -> Html Msg
+viewCircle m =
+ circle
+ [ cy (scaleX m.wHeight (getX0 m))
+ , cx (scaleT m.wWidth m.t)
+ , r "10"
+ , on "mousedown" (Decode.map DragStart decodeMouseHeight)
+ ]
+ []
+
+
+plotPath : Float -> Float -> ( Time, Time, Particle ) -> String
+plotPath w h ( dt, tf, particle ) =
+ let
+ comb x ( t, s ) =
+ ( t - dt, s ++ scaleT w t ++ "," ++ scaleX h x ++ " " )
+ in
+ Tuple.second <| List.foldl comb ( tf, "" ) particle.pos
+
+
+plotHistory : Model -> List (Html Msg)
+plotHistory m =
+ let
+ ( w, h ) =
+ ( m.wWidth, m.wHeight )
+ in
+ List.map
+ (\( dt, t, p ) ->
+ polyline
+ [ stroke "black"
+ , fill "none"
+ , stroke (gradient dt)
+ , points (plotPath w h ( dt, t, p ))
+ ]
+ []
+ )
+ (( m.dt, m.t, m.part ) :: m.history)
+
+
+gradient : Time -> String
+gradient dt =
+ let
+ ( r, g, b ) =
+ ( round (255 * dt), 0, round (255 * (1 - dt)) )
+
+ col =
+ Hex.toString (256 * (256 * r + g) + b)
+ in
+ if String.length col < 6 then
+ "#" ++ String.repeat (6 - String.length col) "0" ++ col
+
+ else
+ "#" ++ col
diff --git a/contents/forward_euler_method/code/golang/euler.go b/contents/forward_euler_method/code/go/euler.go
similarity index 100%
rename from contents/forward_euler_method/code/golang/euler.go
rename to contents/forward_euler_method/code/go/euler.go
diff --git a/contents/forward_euler_method/forward_euler_method.md b/contents/forward_euler_method/forward_euler_method.md
index 175ef1337..f2f21c8b9 100644
--- a/contents/forward_euler_method/forward_euler_method.md
+++ b/contents/forward_euler_method/forward_euler_method.md
@@ -96,7 +96,7 @@ That said, variations of this method *are* certainly used (for example Crank-Nic
Here is a video describing the forward Euler method:
-
+
## Example Code
@@ -112,15 +112,15 @@ Note that in this case, the velocity is directly given by the ODE and the accele
{% sample lang="c" %}
[import, lang:"c"](code/c/euler.c)
{% sample lang="cpp" %}
-[import, lang:"cpp"](code/c++/euler.cpp)
+[import, lang:"cpp"](code/cpp/euler.cpp)
{% sample lang="rs" %}
[import, lang:"rust"](code/rust/euler.rs)
{% sample lang="elm" %}
-[import:44-54, lang:"elm"](code/elm/euler.elm)
-[import:193-210, lang:"elm"](code/elm/euler.elm)
+[import:78-91, lang:"elm"](code/elm/src/Euler.elm)
+[import:236-252, lang:"elm"](code/elm/src/Euler.elm)
Full code for the visualization follows:
-[import, lang:"elm"](code/elm/euler.elm)
+[import, lang:"elm"](code/elm/src/Euler.elm)
{% sample lang="py" %}
[import, lang:"python"](code/python/euler.py)
@@ -135,7 +135,7 @@ Full code for the visualization follows:
{% sample lang="f90" %}
[import, lang:"fortran"](code/fortran/euler.f90)
{% sample lang="go" %}
-[import, lang:"go"](code/golang/euler.go)
+[import, lang:"go"](code/go/euler.go)
{% sample lang="v" %}
[import, lang:"v"](code/v/euler.v)
{% sample lang="asm-x64" %}
@@ -146,6 +146,8 @@ Full code for the visualization follows:
[import, lang:"nim"](code/nim/forwardeuler.nim)
{% sample lang="lisp" %}
[import, lang="lisp"](code/clisp/euler.lisp)
+{%sample lang="coco" %}
+[import, lang:"coconut"](code/coconut/euler.coco)
{% endmethod %}
+
+### Bibliography
+
+{% references %} {% endreferences %}
+
+## License
+
+##### Code Examples
+
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+
+
+##### Images/Graphics
+- The animation "[Animated Random Walk](res/animated_random_walk.gif)" was created by [K. Shudipto Amin](https://github.com/shudipto-amin) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+- The animation "[Animated Metropolis](res/animated_metropolis.gif)" was created by [K. Shudipto Amin](https://github.com/shudipto-amin) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+- The image "[Plot of P(x)](res/plot_of_P.png)" was created by [K. Shudipto Amin](https://github.com/shudipto-amin) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+- The image "[Multiple Histograms](res/multiple_histograms.png)" was created by [K. Shudipto Amin](https://github.com/shudipto-amin) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+##### Text
+
+The text of this chapter was written by [K. Shudipto Amin](https://github.com/shudipto-amin) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+[
](https://creativecommons.org/licenses/by-sa/4.0/)
+
+##### Pull Requests
+
+After initial licensing ([#560](https://github.com/algorithm-archivists/algorithm-archive/pull/560)), the following pull requests have modified the text or graphics of this chapter:
+- none
diff --git a/contents/metropolis/res/1D_particles.png b/contents/metropolis/res/1D_particles.png
new file mode 100644
index 000000000..3d8ab7d99
Binary files /dev/null and b/contents/metropolis/res/1D_particles.png differ
diff --git a/contents/metropolis/res/animated_metropolis.gif b/contents/metropolis/res/animated_metropolis.gif
new file mode 100644
index 000000000..93356bb7e
Binary files /dev/null and b/contents/metropolis/res/animated_metropolis.gif differ
diff --git a/contents/metropolis/res/animated_metropolis.mp4 b/contents/metropolis/res/animated_metropolis.mp4
new file mode 100644
index 000000000..68bfc36ec
Binary files /dev/null and b/contents/metropolis/res/animated_metropolis.mp4 differ
diff --git a/contents/metropolis/res/animated_random_walk.gif b/contents/metropolis/res/animated_random_walk.gif
new file mode 100644
index 000000000..f80bc11b0
Binary files /dev/null and b/contents/metropolis/res/animated_random_walk.gif differ
diff --git a/contents/metropolis/res/animated_random_walk.mp4 b/contents/metropolis/res/animated_random_walk.mp4
new file mode 100644
index 000000000..d7825ec3c
Binary files /dev/null and b/contents/metropolis/res/animated_random_walk.mp4 differ
diff --git a/contents/metropolis/res/multiple_histograms.png b/contents/metropolis/res/multiple_histograms.png
new file mode 100644
index 000000000..9180253bc
Binary files /dev/null and b/contents/metropolis/res/multiple_histograms.png differ
diff --git a/contents/metropolis/res/plot_of_P.png b/contents/metropolis/res/plot_of_P.png
new file mode 100644
index 000000000..3e4f3d10b
Binary files /dev/null and b/contents/metropolis/res/plot_of_P.png differ
diff --git a/contents/monte_carlo_integration/code/asm-x64/monte_carlo.s b/contents/monte_carlo_integration/code/asm-x64/monte_carlo.s
index 61355cc95..4fb6d93aa 100644
--- a/contents/monte_carlo_integration/code/asm-x64/monte_carlo.s
+++ b/contents/monte_carlo_integration/code/asm-x64/monte_carlo.s
@@ -84,5 +84,6 @@ main:
call printf
add rsp, 16
pop rbp
+ xor rax, rax # Set exit code to 0
ret
diff --git a/contents/monte_carlo_integration/code/c/monte_carlo.c b/contents/monte_carlo_integration/code/c/monte_carlo.c
index 9920ff55c..14f823fe4 100644
--- a/contents/monte_carlo_integration/code/c/monte_carlo.c
+++ b/contents/monte_carlo_integration/code/c/monte_carlo.c
@@ -24,7 +24,7 @@ double monte_carlo(unsigned int samples) {
}
int main() {
- srand(time(NULL));
+ srand((unsigned int)time(NULL));
double estimate = monte_carlo(1000000);
diff --git a/contents/monte_carlo_integration/code/clojure/monte_carlo.clj b/contents/monte_carlo_integration/code/clojure/monte_carlo.clj
index f66baef67..de517e56c 100644
--- a/contents/monte_carlo_integration/code/clojure/monte_carlo.clj
+++ b/contents/monte_carlo_integration/code/clojure/monte_carlo.clj
@@ -8,9 +8,11 @@
(map #(* % %))
(reduce +))
(* r r)))
+
(defn rand-point [r]
"return a random point from (0,0) inclusive to (r,r) exclusive"
(repeatedly 2 #(rand r)))
+
(defn monte-carlo [n r]
"take the number of random points and radius return an estimate to
pi"
@@ -22,11 +24,12 @@ pi"
(if (in-circle? (rand-point r) r)
(inc count)
count))))))
+
(defn -main []
(let [constant-pi Math/PI
computed-pi (monte-carlo 10000000 2) ;; this may take some time on lower end machines
difference (Math/abs (- constant-pi computed-pi))
error (* 100 (/ difference constant-pi))]
(println "world's PI: " constant-pi
- ",our PI: " (double computed-pi)
+ ",our PI: " (double computed-pi)
",error: " error)))
diff --git a/contents/monte_carlo_integration/code/coconut/monte_carlo.coco b/contents/monte_carlo_integration/code/coconut/monte_carlo.coco
index a1a1d9975..7d58c077c 100644
--- a/contents/monte_carlo_integration/code/coconut/monte_carlo.coco
+++ b/contents/monte_carlo_integration/code/coconut/monte_carlo.coco
@@ -4,7 +4,7 @@ import random
data point(x, y):
def __abs__(self) = (self.x, self.y) |> map$(pow$(?, 2)) |> sum |> math.sqrt
-def in_circle(p is point, radius = 1):
+def in_circle(point(p), radius = 1):
"""Return True if the point is in the circle and False otherwise."""
return abs(p) < radius
diff --git a/contents/monte_carlo_integration/code/c++/monte_carlo.cpp b/contents/monte_carlo_integration/code/cpp/monte_carlo.cpp
similarity index 88%
rename from contents/monte_carlo_integration/code/c++/monte_carlo.cpp
rename to contents/monte_carlo_integration/code/cpp/monte_carlo.cpp
index beff97170..4a600d72e 100644
--- a/contents/monte_carlo_integration/code/c++/monte_carlo.cpp
+++ b/contents/monte_carlo_integration/code/cpp/monte_carlo.cpp
@@ -37,12 +37,7 @@ double monte_carlo_pi(unsigned samples) {
}
int main() {
- unsigned samples;
-
- std::cout << "Enter samples to use: ";
- std::cin >> samples;
-
- double pi_estimate = monte_carlo_pi(samples);
+ double pi_estimate = monte_carlo_pi(10000000);
std::cout << "Pi = " << pi_estimate << '\n';
std::cout << "Percent error is: " << 100 * std::abs(pi_estimate - PI) / PI << " %\n";
}
diff --git a/contents/monte_carlo_integration/code/powershell/MonteCarlo.ps1 b/contents/monte_carlo_integration/code/powershell/MonteCarlo.ps1
new file mode 100644
index 000000000..fe80d6db0
--- /dev/null
+++ b/contents/monte_carlo_integration/code/powershell/MonteCarlo.ps1
@@ -0,0 +1,21 @@
+function Is-InCircle($x, $y, $radius=1) {
+ return ([Math]::Pow($x, 2) + [Math]::Pow($y, 2)) -lt [Math]::Pow($radius, 2)
+}
+
+function Monte-Carlo([int]$n) {
+ $PiCount = 0;
+ for ($i = 0; $i -lt $n; $i++) {
+ $x = Get-Random -Minimum 0.0 -Maximum 1.0
+ $y = Get-Random -Minimum 0.0 -Maximum 1.0
+
+ if (Is-InCircle $x $y) {
+ $PiCount++
+ }
+ }
+ return 4.0 * $PiCount / $n
+}
+
+# This could take some time
+$PiEstimate = Monte-Carlo 10000000
+Write-Host "The pi estimate is: $PiEstimate"
+Write-Host "Percent error is: $(100 * [Math]::Abs($PiEstimate - ([Math]::PI)) / ([Math]::PI))"
\ No newline at end of file
diff --git a/contents/monte_carlo_integration/code/racket/monte_carlo.rkt b/contents/monte_carlo_integration/code/racket/monte_carlo.rkt
index 0f652db93..0278e7ed6 100755
--- a/contents/monte_carlo_integration/code/racket/monte_carlo.rkt
+++ b/contents/monte_carlo_integration/code/racket/monte_carlo.rkt
@@ -1,22 +1,25 @@
-#lang racket
-(define (in_circle x y)
- (< (+ (sqr x) (sqr y)) 1)
- )
+#lang racket/base
-(define (monte_carlo_pi n)
- (* (/ (local ((define (monte_carlo* n count)
+(require racket/local)
+(require racket/math)
+
+(define (in-circle x y)
+ "Checks if a point is in a unit circle"
+ (< (+ (sqr x) (sqr y)) 1))
+
+(define (monte-carlo-pi n)
+ "Returns an approximation of pi"
+ (* (/ (local ((define (monte-carlo-pi* n count)
(if (= n 0)
count
- (monte_carlo_pi* (sub1 n)
- (if (in_circle (random) (random))
- (add1 count)
- count
- )
- )
- )
- )) (monte_carlo_pi* n 0)
- ) n) 4)
- )
-
+ (monte-carlo-pi* (sub1 n)
+ (if (in-circle (random) (random))
+ (add1 count)
+ count)))))
+ (monte-carlo-pi* n 0)) n) 4))
-(display (monte_carlo_pi 1000))
+(define nsamples 5000000)
+(define pi-estimate (monte-carlo-pi nsamples))
+(displayln (string-append "Estimate (rational): " (number->string pi-estimate)))
+(displayln (string-append "Estimate (float): " (number->string (real->single-flonum pi-estimate))))
+(displayln (string-append "Error:" (number->string (* (/ (abs (- pi-estimate pi)) pi) 100))))
diff --git a/contents/monte_carlo_integration/code/rust/Cargo.toml b/contents/monte_carlo_integration/code/rust/Cargo.toml
new file mode 100644
index 000000000..17ff7f385
--- /dev/null
+++ b/contents/monte_carlo_integration/code/rust/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "montecarlo"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+rand = "0.8.4"
+
+[[bin]]
+path = "./monte_carlo.rs"
+name = "main"
\ No newline at end of file
diff --git a/contents/monte_carlo_integration/monte_carlo_integration.md b/contents/monte_carlo_integration/monte_carlo_integration.md
index 4256009b8..5a96fc1ef 100644
--- a/contents/monte_carlo_integration/monte_carlo_integration.md
+++ b/contents/monte_carlo_integration/monte_carlo_integration.md
@@ -44,7 +44,7 @@ each point is tested to see whether it's in the circle or not:
{% sample lang="c" %}
[import:7-9, lang:"c"](code/c/monte_carlo.c)
{% sample lang="cpp" %}
-[import:7-16, lang:"cpp"](code/c++/monte_carlo.cpp)
+[import:7-16, lang:"cpp"](code/cpp/monte_carlo.cpp)
{% sample lang="js" %}
[import:2-6, lang:"javascript"](code/javascript/monte_carlo.js)
{% sample lang="hs" %}
@@ -80,7 +80,7 @@ each point is tested to see whether it's in the circle or not:
{% sample lang="lua" %}
[import:2-4, lang="lua"](code/lua/monte_carlo.lua)
{% sample lang="racket" %}
-[import:2-4, lang:"lisp"](code/racket/monte_carlo.rkt)
+[import:6-8, lang:"racket"](code/racket/monte_carlo.rkt)
{% sample lang="scala" %}
[import:3-3, lang:"scala"](code/scala/monte_carlo.scala)
{% sample lang="lisp" %}
@@ -99,6 +99,8 @@ each point is tested to see whether it's in the circle or not:
{% sample lang="coco" %}
[import:4-9, lang:"coconut"](code/coconut/monte_carlo.coco)
+{% sample lang="ps1" %}
+[import:1-3, lang:"powershell"](code/powershell/MonteCarlo.ps1)
{% endmethod %}
If it's in the circle, we increase an internal count by one, and in the end,
@@ -123,7 +125,7 @@ I can guarantee that we will see similar methods crop up all over the place in t
Here is a video describing Monte Carlo integration:
-
+
## Example Code
@@ -145,7 +147,7 @@ Feel free to submit your version via pull request, and thanks for reading!
{% sample lang="c" %}
[import, lang:"c"](code/c/monte_carlo.c)
{% sample lang="cpp" %}
-[import, lang:"cpp"](code/c++/monte_carlo.cpp)
+[import, lang:"cpp"](code/cpp/monte_carlo.cpp)
{% sample lang="js" %}
[import, lang:"javascript"](code/javascript/monte_carlo.js)
{% sample lang="hs" %}
@@ -186,7 +188,7 @@ Feel free to submit your version via pull request, and thanks for reading!
{% sample lang="lua" %}
[import, lang="lua"](code/lua/monte_carlo.lua)
{% sample lang="racket" %}
-[import, lang:"lisp"](code/racket/monte_carlo.rkt)
+[import, lang:"racket"](code/racket/monte_carlo.rkt)
{% sample lang="scala" %}
[import, lang:"scala"](code/scala/monte_carlo.scala)
{% sample lang="lisp" %}
@@ -206,6 +208,8 @@ The code snippets were taken from this [scratch project](https://scratch.mit.edu
{% sample lang="coco" %}
[import, lang:"coconut"](code/coconut/monte_carlo.coco)
+{% sample lang="ps1" %}
+[import, lang:"powershell"](code/powershell/MonteCarlo.ps1)
{% endmethod %}
+
+## License
+
+##### Images/Graphics
+
+- The image "[Frequency distribution of a double die roll](res/double_die_frequencies.png)" was created by [K. Shudipto Amin](https://github.com/shudipto-amin) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+- The image "[Probability Density](res/normal_distribution.png)" was created by [K. Shudipto Amin](https://github.com/shudipto-amin) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+##### Text
+
+The text of this chapter was written by [K. Shudipto Amin](https://github.com/shudipto-amin) and is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+
+[
](https://creativecommons.org/licenses/by-sa/4.0/)
+
+##### Pull Requests
+
+After initial licensing ([#560](https://github.com/algorithm-archivists/algorithm-archive/pull/560)), the following pull requests have modified the text or graphics of this chapter:
+- none
+
diff --git a/contents/probability_distributions/res/double_die_frequencies.png b/contents/probability_distributions/res/double_die_frequencies.png
new file mode 100644
index 000000000..874633331
Binary files /dev/null and b/contents/probability_distributions/res/double_die_frequencies.png differ
diff --git a/contents/probability_distributions/res/normal_distribution.png b/contents/probability_distributions/res/normal_distribution.png
new file mode 100644
index 000000000..36ea67790
Binary files /dev/null and b/contents/probability_distributions/res/normal_distribution.png differ
diff --git a/contents/quantum_information/quantum_information.md b/contents/quantum_information/quantum_information.md
index 56636b724..7916d36b7 100644
--- a/contents/quantum_information/quantum_information.md
+++ b/contents/quantum_information/quantum_information.md
@@ -33,7 +33,7 @@ As always, this section will be updated as we add more algorithms to the list.
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/quantum_systems/code/c++/energy.cpp b/contents/quantum_systems/code/c++/energy.cpp
deleted file mode 100644
index 15a58bd01..000000000
--- a/contents/quantum_systems/code/c++/energy.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#include
-#include
-
-#include
-
-void fft(std::vector> &x, bool inverse) {
- std::vector> y(x.size(), std::complex(0.0, 0.0));
-
- fftw_plan p;
-
- fftw_complex *in = reinterpret_cast(x.data());
- fftw_complex *out = reinterpret_cast(y.data());
-
- p = fftw_plan_dft_1d(x.size(), in, out,
- (inverse ? FFTW_BACKWARD : FFTW_FORWARD), FFTW_ESTIMATE);
-
-
- fftw_execute(p);
- fftw_destroy_plan(p);
-
- for (size_t i = 0; i < x.size(); ++i) {
- x[i] = y[i] / sqrt(static_cast(x.size()));
- }
-}
-
-double calculate_energy(std::vector> wfc,
- std::vector> h_r,
- std::vector> h_k,
- double dx, size_t size) {
- std::vector> wfc_k(wfc);
- std::vector> wfc_c(size);
- fft(wfc_k, false);
-
- for (size_t i = 0; i < size; ++i) {
- wfc_c[i] = conj(wfc[i]);
- }
-
- std::vector> energy_k(size);
- std::vector> energy_r(size);
-
- for (size_t i = 0; i < size; ++i) {
- energy_k[i] = wfc_k[i] * pow(h_k[i], 2);
- }
-
- fft(energy_k, true);
-
- for (size_t i = 0; i < size; ++i) {
- energy_k[i] *= 0.5 * wfc_c[i];
- energy_r[i] = wfc_c[i] * h_r[i] * wfc[i];
- }
-
- double energy_final = 0;
-
- for (size_t i = 0; i < size; ++i) {
- energy_final += real(energy_k[i] + energy_r[i]);
- }
-
- return energy_final * dx;
-}
diff --git a/contents/quantum_systems/code/c/energy.c b/contents/quantum_systems/code/c/energy.c
deleted file mode 100644
index 9086ffcd5..000000000
--- a/contents/quantum_systems/code/c/energy.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include
-#include
-#include
-#include
-
-#include
-
-void fft(double complex *x, int n, bool inverse) {
- double complex y[n];
- memset(y, 0, sizeof(y));
- fftw_plan p;
-
- if (inverse) {
- p = fftw_plan_dft_1d(n, (fftw_complex*)x, (fftw_complex*)y,
- FFTW_BACKWARD, FFTW_ESTIMATE);
- } else {
- p = fftw_plan_dft_1d(n, (fftw_complex*)x, (fftw_complex*)y,
- FFTW_FORWARD, FFTW_ESTIMATE);
- }
-
- fftw_execute(p);
- fftw_destroy_plan(p);
-
- for (size_t i = 0; i < n; ++i) {
- x[i] = y[i] / sqrt((double)n);
- }
-}
-
-double calculate_energy(double complex *wfc, double complex *h_r,
- double complex *h_k, double dx, size_t size) {
- double complex wfc_k[size];
- double complex wfc_c[size];
- memcpy(wfc_k, wfc, sizeof(wfc_k));
- fft(wfc_k, size, false);
-
- for (size_t i = 0; i < size; ++i) {
- wfc_c[i] = conj(wfc[i]);
- }
-
- double complex energy_k[size];
- double complex energy_r[size];
-
- for (size_t i = 0; i < size; ++i) {
- energy_k[i] = wfc_k[i] * h_k[i];
- }
-
- fft(energy_k, size, true);
-
- for (size_t i = 0; i < size; ++i) {
- energy_k[i] *= wfc_c[i];
- energy_r[i] = wfc_c[i] * h_r[i] * wfc[i];
- }
-
- double energy_final = 0;
-
- for (size_t i = 0; i < size; ++i) {
- energy_final += creal(energy_k[i] + energy_r[i]);
- }
-
- return energy_final * dx;
-}
diff --git a/contents/quantum_systems/code/haskell/Energy.hs b/contents/quantum_systems/code/haskell/Energy.hs
deleted file mode 100644
index a024fd139..000000000
--- a/contents/quantum_systems/code/haskell/Energy.hs
+++ /dev/null
@@ -1,14 +0,0 @@
-import Data.Array.CArray
-import Data.Complex
-import Math.FFT (dft, idft) -- Binding to fftw
-
-type Vector = CArray Int (Complex Double)
-
-calculateEnergy :: Double -> Vector -> Vector -> Vector -> Double
-calculateEnergy dx kin pot wfc = (* dx) . sum . map realPart $ elems total
- where
- total = liftArray2 (+) kineticE potentialE
- potentialE = wfcConj .* pot .* wfc
- kineticE = wfcConj .* idft (kin .* dft wfc)
- wfcConj = liftArray conjugate wfc
- a .* b = liftArray2 (*) a b
diff --git a/contents/quantum_systems/code/julia/energy.jl b/contents/quantum_systems/code/julia/energy.jl
deleted file mode 100644
index 3efce0cb7..000000000
--- a/contents/quantum_systems/code/julia/energy.jl
+++ /dev/null
@@ -1,18 +0,0 @@
-# We are calculating the energy to check
-function calculate_energy(wfc, H_k, H_r, dx)
- # Creating momentum and conjugate wavefunctions
- wfc_k = fft(wfc)
- wfc_c = conj(wfc)
-
- # Finding the momentum and real-space energy terms
- energy_k = wfc_c.*ifft((H_k) .* wfc_k)
- energy_r = wfc_c.* H_r .* wfc
-
- # Integrating over all space
- energy_final = 0
- for i = 1:length(energy_k)
- energy_final += real(energy_k[i] + energy_r[i])
- end
-
- return energy_final*dx
-end
diff --git a/contents/quantum_systems/code/python/energy.py b/contents/quantum_systems/code/python/energy.py
deleted file mode 100644
index 328fa9950..000000000
--- a/contents/quantum_systems/code/python/energy.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import numpy as np
-
-
-def calculate_energy(wfc, H_k, H_r, dx):
- """Calculate the energy ."""
- # Creating momentum conjugate wavefunctions
- wfc_k = np.fft.fft(wfc)
- wfc_c = np.conj(wfc)
-
- # Finding the momentum and real-space energy terms
- energy_k = 0.5 * wfc_c * np.fft.ifft((H_k ** 2) * wfc_k)
- energy_r = wfc_c * H_r * wfc
-
- # Integrating over all space
- energy_final = sum(energy_k + energy_r).real
-
- return energy_final * dx
diff --git a/contents/quantum_systems/quantum_systems.md b/contents/quantum_systems/quantum_systems.md
index a74c22068..71eb9305a 100644
--- a/contents/quantum_systems/quantum_systems.md
+++ b/contents/quantum_systems/quantum_systems.md
@@ -226,15 +226,15 @@ This ultimately looks like this:
{% method %}
{% sample lang="jl" %}
-[import, lang:"julia"](code/julia/energy.jl)
+[import:114-132, lang:"julia"](../split-operator_method/code/julia/split_op.jl)
{% sample lang="hs" %}
-[import, lang:"haskell"](code/haskell/Energy.hs)
+[import:75-82, lang:"haskell"](../split-operator_method/code/haskell/splitOp.hs)
{% sample lang="c" %}
-[import:29-, lang:"c"](code/c/energy.c)
+[import:150-184, lang:"c"](../split-operator_method/code/c/split_op.c)
{% sample lang="cpp" %}
-[import:26-, lang:"cpp"](code/c++/energy.cpp)
+[import:158-189, lang:"cpp"](../split-operator_method/code/cpp/split_op.cpp)
{% sample lang="py" %}
-[import:4-17, lang:"python"](code/python/energy.py)
+[import:98-112, lang:"python"](../split-operator_method/code/python/split_op.py)
{% endmethod %}
This calculation will be used in many different simulations of quantum systems to check our results.
@@ -260,7 +260,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/split-operator_method/code/c/SConscript b/contents/split-operator_method/code/c/SConscript
new file mode 100644
index 000000000..bb40f4a85
--- /dev/null
+++ b/contents/split-operator_method/code/c/SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.C(build_target, str(file_info.path), LIBS=['m', 'fftw3'])
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/contents/split-operator_method/code/c/split_op.c b/contents/split-operator_method/code/c/split_op.c
index 0550e4ef2..fd5a84001 100644
--- a/contents/split-operator_method/code/c/split_op.c
+++ b/contents/split-operator_method/code/c/split_op.c
@@ -28,16 +28,16 @@ struct operators {
double complex *wfc;
};
-void fft(double complex *x, int n, bool inverse) {
+void fft(double complex *x, size_t n, bool inverse) {
double complex y[n];
memset(y, 0, sizeof(y));
fftw_plan p;
if (inverse) {
- p = fftw_plan_dft_1d(n, (fftw_complex*)x, (fftw_complex*)y,
+ p = fftw_plan_dft_1d((int)n, (fftw_complex*)x, (fftw_complex*)y,
FFTW_BACKWARD, FFTW_ESTIMATE);
} else {
- p = fftw_plan_dft_1d(n, (fftw_complex*)x, (fftw_complex*)y,
+ p = fftw_plan_dft_1d((int)n, (fftw_complex*)x, (fftw_complex*)y,
FFTW_FORWARD, FFTW_ESTIMATE);
}
@@ -63,9 +63,9 @@ void init_params(struct params *par, double xmax, unsigned int res, double dt,
par->im_time = im;
for (size_t i = 0; i < res; ++i) {
- par->x[i] = xmax / res - xmax + i * (2.0 * xmax / res);
+ par->x[i] = xmax / res - xmax + (double)i * (2.0 * xmax / res);
if (i < res / 2) {
- par->k[i] = i * M_PI / xmax;
+ par->k[i] = (double)i * M_PI / xmax;
} else {
par->k[i] = ((double)i - res) * M_PI / xmax;
}
@@ -139,8 +139,8 @@ void split_op(struct params par, struct operators opr) {
sprintf(filename, "output%lu.dat", i);
FILE *fp = fopen(filename, "w");
- for (int i = 0; i < opr.size; ++i) {
- fprintf(fp, "%d\t%f\t%f\n", i, density[i], creal(opr.v[i]));
+ for (size_t i = 0; i < opr.size; ++i) {
+ fprintf(fp, "%ld\t%f\t%f\n", i, density[i], creal(opr.v[i]));
}
fclose(fp);
diff --git a/contents/split-operator_method/code/cpp/SConscript b/contents/split-operator_method/code/cpp/SConscript
new file mode 100644
index 000000000..f9ec1b545
--- /dev/null
+++ b/contents/split-operator_method/code/cpp/SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.CPlusPlus(build_target, str(file_info.path), LIBS=['m', 'fftw3'])
+ env.Alias(str(file_info.chapter), build_result)
diff --git a/contents/split-operator_method/code/c++/split_op.cpp b/contents/split-operator_method/code/cpp/split_op.cpp
similarity index 93%
rename from contents/split-operator_method/code/c++/split_op.cpp
rename to contents/split-operator_method/code/cpp/split_op.cpp
index 74f8df2b7..bb160c901 100644
--- a/contents/split-operator_method/code/c++/split_op.cpp
+++ b/contents/split-operator_method/code/cpp/split_op.cpp
@@ -28,9 +28,9 @@ struct Params {
im_time = im;
for (size_t i = 0; i < res; ++i) {
- x.emplace_back(xmax / res - xmax + i * (2.0 * xmax / res));
+ x.emplace_back(xmax / res - xmax + static_cast(i) * (2.0 * xmax / res));
if (i < res / 2) {
- k.push_back(i * M_PI / xmax);
+ k.push_back(static_cast(i) * M_PI / xmax);
} else {
k.push_back((static_cast(i) - res) * M_PI / xmax);
}
@@ -85,7 +85,7 @@ void fft(vector_complex &x, bool inverse) {
fftw_complex *in = reinterpret_cast(x.data());
fftw_complex *out = reinterpret_cast(y.data());
- p = fftw_plan_dft_1d(x.size(), in, out,
+ p = fftw_plan_dft_1d(static_cast(x.size()), in, out,
(inverse ? FFTW_BACKWARD : FFTW_FORWARD), FFTW_ESTIMATE);
fftw_execute(p);
@@ -97,7 +97,7 @@ void fft(vector_complex &x, bool inverse) {
}
void split_op(Params &par, Operators &opr) {
- double density[opr.size];
+ auto density = std::vector(opr.size, 0);
for (size_t i = 0; i < par.timesteps; ++i) {
for (size_t j = 0; j < opr.size; ++j) {
@@ -142,7 +142,7 @@ void split_op(Params &par, Operators &opr) {
std::ofstream fstream = std::ofstream(filename_stream.str());
if (fstream) {
- for (int i = 0; i < opr.size; ++i) {
+ for (std::size_t i = 0; i < opr.size; ++i) {
std::stringstream data_stream;
data_stream << i << "\t" << density[i] << "\t" << real(opr.v[i]) << "\n";
diff --git a/contents/split-operator_method/code/rust/Cargo.toml b/contents/split-operator_method/code/rust/Cargo.toml
new file mode 100644
index 000000000..def85c23e
--- /dev/null
+++ b/contents/split-operator_method/code/rust/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "splitop"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+rustfft = "4.1.0"
+
+[[bin]]
+path = "./split_op.rs"
+name = "main"
\ No newline at end of file
diff --git a/contents/split-operator_method/code/rust/split_op.rs b/contents/split-operator_method/code/rust/split_op.rs
index 7269f5148..d29e16a2e 100644
--- a/contents/split-operator_method/code/rust/split_op.rs
+++ b/contents/split-operator_method/code/rust/split_op.rs
@@ -1,7 +1,6 @@
-extern crate num;
extern crate rustfft;
-use num::complex::Complex;
+use rustfft::num_complex::Complex;
use rustfft::FFTplanner;
use std::f64::consts::PI;
use std::fs::File;
@@ -95,7 +94,7 @@ fn fft(x: &mut Vec>, inverse: bool) {
let mut y = vec![Complex::new(0.0_f64, 0.0_f64); x.len()];
let mut p = FFTplanner::new(inverse);
let fft = p.plan_fft(x.len());
- fft.process(x, &mut y);
+ fft.process(x.as_mut_slice(), y.as_mut_slice());
for i in 0..x.len() {
x[i] = y[i] / (x.len() as f64).sqrt();
diff --git a/contents/split-operator_method/split-operator_method.md b/contents/split-operator_method/split-operator_method.md
index 33af1f225..08fc3d33d 100644
--- a/contents/split-operator_method/split-operator_method.md
+++ b/contents/split-operator_method/split-operator_method.md
@@ -103,7 +103,7 @@ Regardless, we first need to set all the initial parameters, including the initi
[import:11-21, lang:"c"](code/c/split_op.c)
[import:52-73, lang:"c"](code/c/split_op.c)
{% sample lang="cpp" %}
-[import:14-49, lang:"cpp"](code/c++/split_op.cpp)
+[import:14-49, lang:"cpp"](code/cpp/split_op.cpp)
{% sample lang="py" %}
[import:11-30, lang:"python"](code/python/split_op.py)
{% sample lang="hs" %}
@@ -126,7 +126,7 @@ Afterwards, we turn them into operators:
[import:23-29, lang:"c"](code/c/split_op.c)
[import:75-96, lang:"c"](code/c/split_op.c)
{% sample lang="cpp" %}
-[import:51-80, lang:"cpp"](code/c++/split_op.cpp)
+[import:51-80, lang:"cpp"](code/cpp/split_op.cpp)
{% sample lang="py" %}
[import:33-54, lang:"python"](code/python/split_op.py)
{% sample lang="hs" %}
@@ -149,7 +149,7 @@ The final step is to do the iteration, itself.
{% sample lang="c" %}
[import:98-148, lang:"c"](code/c/split_op.c)
{% sample lang="cpp" %}
-[import:99-156, lang:"cpp"](code/c++/split_op.cpp)
+[import:99-156, lang:"cpp"](code/cpp/split_op.cpp)
{% sample lang="py" %}
[import:57-95, lang:"python"](code/python/split_op.py)
{% sample lang="hs" %}
@@ -172,7 +172,7 @@ The Split-Operator method is one of the most commonly used quantum simulation al
Here is a video describing the split-operator method:
-
+
## Example Code
@@ -186,7 +186,7 @@ Checking to make sure your code can output the correct energy for a harmonic tra
{% sample lang="c" %}
[import, lang:"c"](code/c/split_op.c)
{% sample lang="cpp" %}
-[import, lang:"cpp"](code/c++/split_op.cpp)
+[import, lang:"cpp"](code/cpp/split_op.cpp)
{% sample lang="py" %}
[import:5-127, lang:"python"](code/python/split_op.py)
{% sample lang="hs" %}
@@ -203,7 +203,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/stable_marriage_problem/code/c/stable_marriage.c b/contents/stable_marriage_problem/code/c/stable_marriage.c
index 546a0d5d1..8537e82f2 100644
--- a/contents/stable_marriage_problem/code/c/stable_marriage.c
+++ b/contents/stable_marriage_problem/code/c/stable_marriage.c
@@ -5,7 +5,7 @@
#include
struct person {
- int id;
+ size_t id;
struct person *partner;
size_t *prefers;
size_t index;
@@ -13,18 +13,18 @@ struct person {
void shuffle(size_t *array, size_t size) {
for (size_t i = size - 1; i > 0; --i) {
- size_t j = rand() % (i + 1);
+ size_t j = (size_t)rand() % (i + 1);
size_t tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
-void create_group(struct person *group, size_t size, bool are_men) {
+void create_group(struct person *group, size_t size) {
for (size_t i = 0; i < size; ++i) {
group[i].id = i;
group[i].partner = NULL;
- group[i].prefers = (size_t*)malloc(sizeof(size_t) * size);
+ group[i].prefers = malloc(sizeof(size_t) * size);
group[i].index = 0;
for (size_t j = 0; j < size; ++j) {
@@ -43,6 +43,7 @@ bool prefers_partner(size_t *prefers, size_t partner, size_t id, size_t size) {
return false;
}
}
+ return true;
}
void stable_marriage(struct person *men, struct person *women, size_t size) {
@@ -81,12 +82,12 @@ void free_group(struct person *group, size_t size) {
}
int main() {
- srand(time(NULL));
+ srand((unsigned int)time(NULL));
struct person men[5], women[5];
- create_group(men, 5, true);
- create_group(women, 5, false);
+ create_group(men, 5);
+ create_group(women, 5);
for (size_t i = 0; i < 5; ++i) {
printf("preferences of man %zu: ", i);
@@ -113,7 +114,7 @@ int main() {
printf("\n");
for (size_t i = 0; i < 5; ++i) {
- printf("the partner of man %zu is woman %d\n", i, men[i].partner->id);
+ printf("the partner of man %zu is woman %ld\n", i, men[i].partner->id);
}
free_group(men, 5);
diff --git a/contents/stable_marriage_problem/code/c++/stable_marriage.cpp b/contents/stable_marriage_problem/code/cpp/stable_marriage.cpp
similarity index 100%
rename from contents/stable_marriage_problem/code/c++/stable_marriage.cpp
rename to contents/stable_marriage_problem/code/cpp/stable_marriage.cpp
diff --git a/contents/stable_marriage_problem/stable_marriage_problem.md b/contents/stable_marriage_problem/stable_marriage_problem.md
index 3121c6478..f6a3e5b2a 100644
--- a/contents/stable_marriage_problem/stable_marriage_problem.md
+++ b/contents/stable_marriage_problem/stable_marriage_problem.md
@@ -23,7 +23,7 @@ I am incredibly interested to see what you guys do and how you implement the alg
Here is a video describing the stable marriage problem:
-
+
## Example Code
@@ -40,7 +40,7 @@ Here is a video describing the stable marriage problem:
{% sample lang="c" %}
[import, lang:"c"](code/c/stable_marriage.c)
{% sample lang="cpp" %}
-[import, lang:"cpp"](code/c++/stable_marriage.cpp)
+[import, lang:"cpp"](code/cpp/stable_marriage.cpp)
{% sample lang="js" %}
[import, lang:"javascript"](code/javascript/stable-marriage.js)
{% sample lang="cs" %}
@@ -68,7 +68,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/stacks_and_queues/code/cpp/queue.cpp b/contents/stacks_and_queues/code/cpp/queue.cpp
new file mode 100644
index 000000000..009abbd06
--- /dev/null
+++ b/contents/stacks_and_queues/code/cpp/queue.cpp
@@ -0,0 +1,91 @@
+#include
+#include
+#include
+
+namespace my {
+ /**
+ * implementation using linked list
+ * [value][next] -> [value][next] -> ... -> [value][next]
+ * (front Node) (intermediat Nodes) (rear Node)
+ */
+ template
+ struct Node {
+ /**
+ * next: will store right Node address
+ */
+ T value;
+ std::shared_ptr> next;
+ Node(const T& V) : value(V) { }
+ };
+
+ template
+ class queue {
+ private:
+ /**
+ * front_pointer: points to left most node
+ * count: keeps track of current number of elements present in queue
+ * rear_pointer: points to most recent Node added into the queue, which is right most Node
+ */
+ std::shared_ptr> front_pointer;
+ std::shared_ptr> rear_pointer;
+ size_t count;
+ public:
+ queue() : count(0ULL) { }
+
+ void enqueue(const T& element) {
+ auto new_node = std::make_shared>(element);
+ if (count > 0) {
+ rear_pointer->next = new_node;
+ rear_pointer = new_node;
+ } else {
+ rear_pointer = front_pointer = new_node;
+ }
+ count = count + 1;
+ }
+
+ void dequeue() {
+ if (count > 1) {
+ front_pointer = front_pointer->next;
+ count = count - 1;
+ } else if (count == 1) {
+ front_pointer.reset();
+ rear_pointer.reset();
+ count = count - 1;
+ }
+ }
+
+ T& front() {
+ assert(count > 0 && "calling front on an empty queue");
+ return front_pointer->value;
+ }
+
+ T const& front() const {
+ assert(count > 0 && "calling front on an empty queue");
+ return front_pointer->value;
+ }
+
+ size_t size() const { return count; }
+
+ bool empty() const { return count == 0; }
+
+ ~queue() {
+ while (front_pointer.get() != nullptr) {
+ front_pointer = front_pointer->next;
+ }
+ }
+ };
+}
+
+int main() {
+ my::queue intQueue;
+ intQueue.enqueue(4);
+ intQueue.enqueue(5);
+ intQueue.enqueue(9);
+
+ int frontElement = intQueue.front();
+ intQueue.dequeue();
+ std::cout << frontElement << '\n';
+ std::cout << intQueue.size() << '\n';
+ std::cout << intQueue.front() << '\n';
+ return 0;
+}
diff --git a/contents/stacks_and_queues/code/cpp/stack.cpp b/contents/stacks_and_queues/code/cpp/stack.cpp
new file mode 100644
index 000000000..0d13beda3
--- /dev/null
+++ b/contents/stacks_and_queues/code/cpp/stack.cpp
@@ -0,0 +1,84 @@
+#include
+#include
+#include
+
+namespace my {
+ /**
+ * implementation using linked list
+ * [value][next] -> [value][next] -> ... -> [value][next]
+ * (top Node) (intermediat Nodes)
+ * left most Node represents top element of stack
+ */
+ template
+ struct Node {
+ /**
+ * next: will store right Node address
+ */
+ T value;
+ std::unique_ptr> next;
+ Node(const T& V) : value(V) { }
+ };
+
+ template
+ class stack {
+ private:
+ /**
+ * top_pointer: points to left most node
+ * count: keeps track of current number of elements present in stack
+ */
+ std::unique_ptr> top_pointer;
+ size_t count;
+ public:
+ stack() : count(0ULL) { }
+
+ void push(const T& element) {
+ auto new_node = std::make_unique>(element);
+ new_node->next = std::move(top_pointer);
+ top_pointer = std::move(new_node);
+ count = count + 1;
+ }
+
+ void pop() {
+ if (count > 0) {
+ top_pointer = std::move(top_pointer->next);
+ count = count - 1;
+ }
+ }
+
+ T& top() {
+ assert(count > 0 and "calling top() on an empty stack");
+ return top_pointer->value;
+ }
+ // returning mutable reference can very be usefull if someone wants to modify top element
+
+ T const& top() const {
+ assert(count > 0 and "calling top() on an empty stack");
+ return top_pointer->value;
+ }
+
+ size_t size() const { return count; }
+
+ bool empty() const { return count == 0; }
+
+ ~stack() {
+ while (top_pointer.get() != nullptr) {
+ top_pointer = std::move(top_pointer->next);
+ }
+ }
+ };
+}
+
+int main() {
+ my::stack intStack;
+
+ intStack.push(4);
+ intStack.push(5);
+ intStack.push(9);
+
+ int topElement = intStack.top();
+ intStack.pop();
+ std::cout << topElement << '\n';
+ std::cout << intStack.size() << '\n';
+ std::cout << intStack.top() << '\n';
+ return 0;
+}
diff --git a/contents/stacks_and_queues/code/java/QueueTest.java b/contents/stacks_and_queues/code/java/QueueTest.java
new file mode 100644
index 000000000..2bf8bbe33
--- /dev/null
+++ b/contents/stacks_and_queues/code/java/QueueTest.java
@@ -0,0 +1,71 @@
+import java.util.List;
+import java.util.ArrayList;
+
+public class QueueTest {
+
+ public static void main(String[] args) {
+ IQueue intQueue = new Queue<>();
+
+ intQueue.enqueue(4);
+ intQueue.enqueue(5);
+ intQueue.enqueue(9);
+
+ System.out.println(intQueue.dequeue());
+ System.out.println(intQueue.size());
+ System.out.println(intQueue.front());
+ }
+
+}
+
+
+interface IQueue {
+
+ /*
+ * 'dequeue' removes the first element from the queue and returns it
+ */
+ T dequeue();
+
+ /*
+ * 'enqueue' adds an element at the end of the queue and returns the new size
+ */
+ int enqueue(T element);
+
+
+ /*
+ * 'size' returns the size of the queue
+ */
+ int size();
+
+ /*
+ * 'front' returns the first element of the queue without removing it
+ */
+ T front();
+}
+
+
+class Queue implements IQueue {
+
+ private List list;
+
+ public Queue() {
+ this.list = new ArrayList<>();
+ }
+
+ public T dequeue() {
+ return this.list.remove(0);
+ }
+
+ public int enqueue(T element) {
+ this.list.add(element);
+ return this.size();
+ }
+
+ public int size() {
+ return this.list.size();
+ }
+
+ public T front() {
+ return this.list.get(0);
+ }
+
+}
diff --git a/contents/stacks_and_queues/code/java/StackTest.java b/contents/stacks_and_queues/code/java/StackTest.java
new file mode 100644
index 000000000..07c96d066
--- /dev/null
+++ b/contents/stacks_and_queues/code/java/StackTest.java
@@ -0,0 +1,72 @@
+import java.util.List;
+import java.util.ArrayList;
+
+
+public class StackTest {
+
+ public static void main(String[] args) {
+ IStack intStack = new Stack<>();
+
+ intStack.push(4);
+ intStack.push(5);
+ intStack.push(9);
+
+ System.out.println(intStack.pop());
+ System.out.println(intStack.size());
+ System.out.println(intStack.top());
+ }
+
+}
+
+
+interface IStack {
+ /*
+ * 'pop' removed the last element from the stack and returns it
+ */
+ T pop();
+
+ /*
+ * 'push' adds an element to at the end of the stack and returns the new size
+ */
+ int push(T element);
+
+ /*
+ * 'size' returns the length of the stack
+ */
+ int size();
+
+ /*
+ * 'top' returns the first element of the stack
+ */
+ T top();
+}
+
+
+class Stack implements IStack {
+
+ private List list;
+
+ public Stack() {
+ this.list = new ArrayList<>();
+ }
+
+ public T pop() {
+ return this.list.remove(this.size() - 1);
+ }
+
+ public int push(T element) {
+ this.list.add(element);
+ return this.size();
+ }
+
+ public int size() {
+ return this.list.size();
+ }
+
+ public T top() {
+ return this.list.get(this.size() - 1);
+ }
+
+}
+
+
diff --git a/contents/stacks_and_queues/code/python/queue.py b/contents/stacks_and_queues/code/python/queue.py
new file mode 100644
index 000000000..ec68a0839
--- /dev/null
+++ b/contents/stacks_and_queues/code/python/queue.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+
+__author__ = "Michael Ciccotosto-Camp"
+
+from typing import TypeVar, Generic
+
+
+T = TypeVar("T")
+
+
+class Queue(Generic[T]):
+ def __init__(self) -> None:
+ self.__list: list[T] = list()
+
+ def dequeue(self) -> T:
+ return self.__list.pop(0)
+
+ def enqueue(self, element: T) -> int:
+ self.__list.append(element)
+ return len(self)
+
+ def front(self) -> T:
+ return self.__list[0]
+
+ def __len__(self) -> int:
+ return len(self.__list)
+
+ def __str__(self) -> str:
+ return str(self.__list)
+
+
+def main() -> None:
+ int_queue: Queue[int] = Queue()
+
+ int_queue.enqueue(4)
+ int_queue.enqueue(5)
+ int_queue.enqueue(9)
+
+ print(int_queue.dequeue())
+ print(len(int_queue))
+ print(int_queue.front())
+
+
+if __name__ == "__main__":
+ main()
diff --git a/contents/stacks_and_queues/code/python/stack.py b/contents/stacks_and_queues/code/python/stack.py
new file mode 100644
index 000000000..5f890baa3
--- /dev/null
+++ b/contents/stacks_and_queues/code/python/stack.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+
+__author__ = "Michael Ciccotosto-Camp"
+
+from typing import TypeVar, Generic
+
+
+T = TypeVar("T")
+
+
+class Stack(Generic[T]):
+ def __init__(self) -> None:
+ self.__list: list[T] = []
+
+ def pop(self) -> T:
+ return self.__list.pop()
+
+ def push(self, element: T) -> int:
+ self.__list.append(element)
+ return len(self)
+
+ def top(self) -> T:
+ return self.__list[-1]
+
+ def __len__(self) -> int:
+ return len(self.__list)
+
+ def __str__(self) -> str:
+ return str(self.__list)
+
+
+def main() -> None:
+ int_stack: Stack[int] = Stack()
+
+ int_stack.push(4)
+ int_stack.push(5)
+ int_stack.push(9)
+
+ print(int_stack.pop())
+ print(len(int_stack))
+ print(int_stack.top())
+
+
+if __name__ == "__main__":
+ main()
diff --git a/contents/stacks_and_queues/code/rust/Queue.rs b/contents/stacks_and_queues/code/rust/Queue.rs
new file mode 100644
index 000000000..0f432e621
--- /dev/null
+++ b/contents/stacks_and_queues/code/rust/Queue.rs
@@ -0,0 +1,43 @@
+use std::collections::VecDeque;
+
+struct Queue {
+ list: VecDeque
+}
+
+impl Queue {
+ fn new() -> Self {
+ Queue{
+ list: VecDeque::new(),
+ }
+ }
+
+ // Note that this returns a reference to the value
+ // This is in contrast to dequeue which gives ownership of the value
+ fn front(&self) -> Option<&T> {
+ self.list.front()
+ }
+
+ fn dequeue(&mut self) -> Option {
+ self.list.pop_front()
+ }
+
+ fn enqueue(&mut self, item: T) {
+ self.list.push_back(item);
+ }
+
+ fn size(&self) -> usize {
+ self.list.len()
+ }
+}
+
+fn main() {
+ let mut i32queue = Queue::new();
+
+ i32queue.enqueue(4);
+ i32queue.enqueue(5);
+ i32queue.enqueue(6);
+
+ println!("{:?}", i32queue.dequeue().unwrap()); // 4
+ println!("{:?}", i32queue.size()); // 2
+ println!("{:?}", i32queue.front().unwrap()); // 5
+}
diff --git a/contents/stacks_and_queues/code/rust/SConscript b/contents/stacks_and_queues/code/rust/SConscript
new file mode 100644
index 000000000..343755fa8
--- /dev/null
+++ b/contents/stacks_and_queues/code/rust/SConscript
@@ -0,0 +1,8 @@
+Import('*')
+from pathlib import Path
+
+dirname = Path.cwd().parents[1].stem
+
+env.rustc(f'#/build/rust/{dirname}/stack', '#/contents/stacks_and_queues/code/rust/Stack.rs')
+
+env.rustc(f'#/build/rust/{dirname}/queue', '#/contents/stacks_and_queues/code/rust/Queue.rs')
diff --git a/contents/stacks_and_queues/code/rust/Stack.rs b/contents/stacks_and_queues/code/rust/Stack.rs
new file mode 100644
index 000000000..13010c3f0
--- /dev/null
+++ b/contents/stacks_and_queues/code/rust/Stack.rs
@@ -0,0 +1,41 @@
+struct Stack {
+ list: Vec
+}
+
+impl Stack {
+ fn new() -> Self {
+ Stack {
+ list: Vec::new(),
+ }
+ }
+
+ // Note that this returns a reference to the value
+ // This is in contrast to pop which gives ownership of the value
+ fn top(&self) -> Option<&T> {
+ self.list.last()
+ }
+
+ fn pop(&mut self) -> Option {
+ self.list.pop()
+ }
+
+ fn push(&mut self, item: T) {
+ self.list.push(item);
+ }
+
+ fn size(&self) -> usize {
+ self.list.len()
+ }
+}
+
+fn main() {
+ let mut i32stack: Stack = Stack::new();
+
+ i32stack.push(4);
+ i32stack.push(5);
+ i32stack.push(6);
+
+ println!("{:?}", i32stack.pop().unwrap()); // 6
+ println!("{:?}", i32stack.size()); // 2
+ println!("{:?}", i32stack.top().unwrap()); // 5
+}
diff --git a/contents/stacks_and_queues/code/typescript/queue.ts b/contents/stacks_and_queues/code/typescript/queue.ts
new file mode 100644
index 000000000..59d9c8321
--- /dev/null
+++ b/contents/stacks_and_queues/code/typescript/queue.ts
@@ -0,0 +1,52 @@
+interface IQueue {
+ /**
+ * `dequeue` removes first element from the queue and returns the same
+ */
+ dequeue(): T;
+ /**
+ * `enqueue` adds element to last of the queue and returns the size
+ */
+ enqueue(data: T): number;
+ /**
+ * `size` return size or length of the queue
+ */
+ size(): number;
+ /**
+ * `front` returns first element of the queue
+ */
+ front(): T;
+}
+
+class Queue implements IQueue {
+ private readonly list: Array = [];
+
+ public enqueue(data: T) {
+ return this.list.push(data);
+ }
+
+ public dequeue() {
+ return this.list.shift();
+ }
+
+ public size() {
+ return this.list.length;
+ }
+
+ public front() {
+ return this.list[0];
+ }
+}
+
+function exampleQueue() {
+ const numberQueue = new Queue();
+
+ numberQueue.enqueue(4);
+ numberQueue.enqueue(5);
+ numberQueue.enqueue(9);
+
+ console.log(numberQueue.dequeue());
+ console.log(numberQueue.size());
+ console.log(numberQueue.front());
+}
+
+exampleQueue();
diff --git a/contents/stacks_and_queues/code/typescript/stack.ts b/contents/stacks_and_queues/code/typescript/stack.ts
new file mode 100644
index 000000000..58b38ac40
--- /dev/null
+++ b/contents/stacks_and_queues/code/typescript/stack.ts
@@ -0,0 +1,52 @@
+interface IStack {
+ /**
+ * `pop` removes last element from the stack and returns the same
+ */
+ pop(): T;
+ /**
+ * `push` adds element to last of the stack and returns the size
+ */
+ push(data: T): number;
+ /**
+ * `size` return size or length of the stack
+ */
+ size(): number;
+ /**
+ * `top` returns last element of the stack
+ */
+ top(): T;
+}
+
+class Stack implements IStack {
+ private readonly list: Array = [];
+
+ public push(data: T) {
+ return this.list.push(data);
+ }
+
+ public pop() {
+ return this.list.pop();
+ }
+
+ public size() {
+ return this.list.length;
+ }
+
+ public top() {
+ return this.list[this.list.length - 1];
+ }
+}
+
+function exampleStack() {
+ const numberStack = new Stack();
+
+ numberStack.push(4);
+ numberStack.push(5);
+ numberStack.push(9);
+
+ console.log(numberStack.pop());
+ console.log(numberStack.size());
+ console.log(numberStack.top());
+}
+
+exampleStack();
diff --git a/contents/stacks_and_queues/stacks_and_queues.md b/contents/stacks_and_queues/stacks_and_queues.md
index 17b8b75b2..e63f72a41 100644
--- a/contents/stacks_and_queues/stacks_and_queues.md
+++ b/contents/stacks_and_queues/stacks_and_queues.md
@@ -7,17 +7,48 @@ In *stacks*, data follows *Last In, First Out* (LIFO), which basically means tha
In *Queues*, data follows *First In, First Out* (FIFO), which means that whichever element you put in first will be the first element you take out. Imagine a queue of people. It would be unfair if the first person in line for groceries were not the first person to receive attention once the attendant finally shows up.
For the most part, though, queues and stacks are treated the same way. There must be a way to:
+
1. look at the first element (`top()`)
2. to remove the first element (`pop()`)
3. to push elements onto the data structure (`push()`)
The notation for this depends on the language you are using. Queues, for example, will often use `dequeue()` instead of `pop()` and `front()` instead of `top()`. You will see the language-specific details in the source code under the algorithms in this book, so for now it's simply important to know what stacks and queues are and how to access elements held within them.
+## Example Code
+
+Here is a simple implementation of a stack:
+{% method %}
+{% sample lang="ts" %}
+[import, lang:"typescript"](code/typescript/stack.ts)
+{% sample lang="java" %}
+[import, lang:"java"](code/java/StackTest.java)
+{% sample lang = "cpp"%}
+[import, lang:"cpp"](code/cpp/stack.cpp)
+{% sample lang="rust" %}
+[import, lang:"rust"](code/rust/Stack.rs)
+{% sample lang="python" %}
+[import, lang:"python"](code/python/stack.py)
+{% endmethod %}
+
+Here is a simple implementation of a queue:
+{% method %}
+{% sample lang="ts" %}
+[import, lang:"typescript"](code/typescript/queue.ts)
+{% sample lang="java" %}
+[import, lang:"java" ](code/java/QueueTest.java)
+{% sample lang = "cpp"%}
+[import, lang:"cpp"](code/cpp/queue.cpp)
+{% sample lang="rust" %}
+[import, lang:"rust" ](code/rust/Queue.rs)
+{% sample lang="python" %}
+[import, lang:"python"](code/python/queue.py)
+{% endmethod %}
+
## License
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
@@ -28,4 +59,5 @@ The text of this chapter was written by [James Schloss](https://github.com/leios
##### Pull Requests
After initial licensing ([#560](https://github.com/algorithm-archivists/algorithm-archive/pull/560)), the following pull requests have modified the text or graphics of this chapter:
+
- none
diff --git a/contents/taylor_series_expansion/taylor_series_expansion.md b/contents/taylor_series_expansion/taylor_series_expansion.md
index 29ba87be4..76effd506 100644
--- a/contents/taylor_series_expansion/taylor_series_expansion.md
+++ b/contents/taylor_series_expansion/taylor_series_expansion.md
@@ -51,7 +51,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/thomas_algorithm/code/c++/thomas.cpp b/contents/thomas_algorithm/code/c++/thomas.cpp
deleted file mode 100644
index 72ddd70db..000000000
--- a/contents/thomas_algorithm/code/c++/thomas.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#include
-#include
-#include
-
-void thomas(std::vector const a, std::vector const b, std::vector const c, std::vector& x) {
- int size = a.size();
- double y[size];
- memset(y, 0, size * sizeof(double));
-
- y[0] = c[0] / b[0];
- x[0] = x[0] / b[0];
-
- for (size_t i = 1; i < size; ++i) {
- double scale = 1.0 / (b[i] - a[i] * y[i - 1]);
- y[i] = c[i] * scale;
- x[i] = (x[i] - a[i] * x[i - 1]) * scale;
- }
-
- for (int i = size - 2; i >= 0; --i) {
- x[i] -= y[i] * x[i + 1];
- }
-}
-
-int main() {
- std::vector a = {0.0, 2.0, 3.0};
- std::vector b = {1.0, 3.0, 6.0};
- std::vector c = {4.0, 5.0, 0.0};
- std::vector x = {7.0, 5.0, 3.0};
-
- std::cout << "The system" << std::endl;
- std::cout << "[1.0 4.0 0.0][x] = [7.0]" << std::endl;
- std::cout << "[2.0 3.0 5.0][y] = [5.0]" << std::endl;
- std::cout << "[0.0 3.0 6.0][z] = [3.0]" << std::endl;
- std::cout << "has the solution" << std::endl;
-
- thomas(a, b, c, x);
-
- for (size_t i = 0; i < 3; ++i) {
- std::cout << "[" << x[i] << "]" << std::endl;
- }
-
- return 0;
-}
diff --git a/contents/thomas_algorithm/code/c/thomas.c b/contents/thomas_algorithm/code/c/thomas.c
index 3aed94e8e..415d31d97 100644
--- a/contents/thomas_algorithm/code/c/thomas.c
+++ b/contents/thomas_algorithm/code/c/thomas.c
@@ -16,7 +16,7 @@ void thomas(double * const a, double * const b, double * const c,
x[i] = (x[i] - a[i] * x[i - 1]) * scale;
}
- for (int i = size - 2; i >= 0; --i) {
+ for (size_t i = size - 2; i < size - 1; --i) {
x[i] -= y[i] * x[i + 1];
}
}
diff --git a/contents/thomas_algorithm/code/cpp/thomas.cpp b/contents/thomas_algorithm/code/cpp/thomas.cpp
new file mode 100644
index 000000000..a96bf2f8b
--- /dev/null
+++ b/contents/thomas_algorithm/code/cpp/thomas.cpp
@@ -0,0 +1,45 @@
+#include
+#include
+#include
+
+void thomas(
+ std::vector const& a,
+ std::vector const& b,
+ std::vector const& c,
+ std::vector& x) {
+ auto y = std::vector(a.size(), 0.0);
+
+ y[0] = c[0] / b[0];
+ x[0] = x[0] / b[0];
+
+ for (std::size_t i = 1; i < a.size(); ++i) {
+ const auto scale = 1.0 / (b[i] - a[i] * y[i - 1]);
+ y[i] = c[i] * scale;
+ x[i] = (x[i] - a[i] * x[i - 1]) * scale;
+ }
+
+ for (std::size_t i = a.size() - 2; i < a.size(); --i) {
+ x[i] -= y[i] * x[i + 1];
+ }
+}
+
+int main() {
+ const std::vector a = {0.0, 2.0, 3.0};
+ const std::vector b = {1.0, 3.0, 6.0};
+ const std::vector c = {4.0, 5.0, 0.0};
+ std::vector x = {7.0, 5.0, 3.0};
+
+ std::cout << "The system\n";
+ std::cout << "[1.0 4.0 0.0][x] = [7.0]\n";
+ std::cout << "[2.0 3.0 5.0][y] = [5.0]\n";
+ std::cout << "[0.0 3.0 6.0][z] = [3.0]\n";
+ std::cout << "has the solution:\n";
+
+ thomas(a, b, c, x);
+
+ for (auto const& val : x) {
+ std::cout << "[" << val << "]\n";
+ }
+
+ return 0;
+}
diff --git a/contents/thomas_algorithm/code/golang/thomas.go b/contents/thomas_algorithm/code/go/thomas.go
similarity index 100%
rename from contents/thomas_algorithm/code/golang/thomas.go
rename to contents/thomas_algorithm/code/go/thomas.go
diff --git a/contents/thomas_algorithm/thomas_algorithm.md b/contents/thomas_algorithm/thomas_algorithm.md
index 5af6c3334..607e9741a 100644
--- a/contents/thomas_algorithm/thomas_algorithm.md
+++ b/contents/thomas_algorithm/thomas_algorithm.md
@@ -112,7 +112,7 @@ You will find this algorithm implemented [in this project](https://scratch.mit.e
{% sample lang="hs" %}
[import, lang:"haskell"](code/haskell/thomas.hs)
{% sample lang="go" %}
-[import, lang:"go"](code/golang/thomas.go)
+[import, lang:"go"](code/go/thomas.go)
{% sample lang="v" %}
[import, lang:"v"](code/v/thomas.v)
{% sample lang="swift" %}
@@ -122,7 +122,7 @@ You will find this algorithm implemented [in this project](https://scratch.mit.e
{% sample lang="nim" %}
[import, lang:"nim"](code/nim/thomas_algorithm.nim)
{% sample lang="cpp" %}
-[import, lang:"cpp"](code/c++/thomas.cpp)
+[import, lang:"cpp"](code/cpp/thomas.cpp)
{% sample lang="lua" %}
[import, lang:"lua"](code/lua/thomas.lua)
{% sample lang="crystal" %}
@@ -147,7 +147,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/tree_traversal/code/c/tree_traversal.c b/contents/tree_traversal/code/c/tree_traversal.c
index 7fed9a16c..16be536c8 100644
--- a/contents/tree_traversal/code/c/tree_traversal.c
+++ b/contents/tree_traversal/code/c/tree_traversal.c
@@ -35,7 +35,7 @@ void destroy_tree(struct node n) {
}
void dfs_recursive(struct node n) {
- printf("%d\n", n.id);
+ printf("%d ", n.id);
if (n.children) {
for (size_t i = 0; i < n.children_size; ++i) {
@@ -49,22 +49,22 @@ void dfs_recursive_postorder(struct node n) {
dfs_recursive_postorder(n.children[i]);
}
- printf("%d\n", n.id);
+ printf("%d ", n.id);
}
void dfs_recursive_inorder_btree(struct node n) {
switch (n.children_size) {
case 2:
dfs_recursive_inorder_btree(n.children[0]);
- printf("%d\n", n.id);
+ printf("%d ", n.id);
dfs_recursive_inorder_btree(n.children[1]);
break;
case 1:
dfs_recursive_inorder_btree(n.children[0]);
- printf("%d\n", n.id);
+ printf("%d ", n.id);
break;
case 0:
- printf("%d\n", n.id);
+ printf("%d ", n.id);
break;
default:
printf("This is not a binary tree.\n");
@@ -83,7 +83,7 @@ void dfs_stack(struct node n) {
break;
}
- printf("%d\n", tmp->id);
+ printf("%d ", tmp->id);
for (size_t i = 0; i < tmp->children_size; ++i) {
stack_push(&stk, &tmp->children[i]);
}
@@ -103,7 +103,7 @@ void bfs_queue(struct node n) {
break;
}
- printf("%d\n", tmp->id);
+ printf("%d ", tmp->id);
for (size_t i = 0; i < tmp->children_size; ++i) {
enqueue(&q, &tmp->children[i]);
}
@@ -113,9 +113,31 @@ void bfs_queue(struct node n) {
}
int main() {
- struct node root = create_tree(3, 3);
+ struct node root = create_tree(2, 3);
+
+ printf("[#]\nRecursive DFS:\n");
+ dfs_recursive(root);
+ printf("\n");
+
+ printf("[#]\nRecursive Postorder DFS:\n");
+ dfs_recursive_postorder(root);
+ printf("\n");
+
+ printf("[#]\nStack-based DFS:\n");
+ dfs_stack(root);
+ printf("\n");
+
+ printf("[#]\nQueue-based BFS:\n");
bfs_queue(root);
+ printf("\n");
+
destroy_tree(root);
+ struct node root_binary = create_tree(3, 2);
+ printf("[#]\nRecursive Inorder DFS for Binary Tree:\n");
+ dfs_recursive_inorder_btree(root_binary);
+ printf("\n");
+
+ destroy_tree(root_binary);
return 0;
}
diff --git a/contents/tree_traversal/code/clisp/tree-traversal.lisp b/contents/tree_traversal/code/clisp/tree-traversal.lisp
index 417a6f242..8c74db43b 100644
--- a/contents/tree_traversal/code/clisp/tree-traversal.lisp
+++ b/contents/tree_traversal/code/clisp/tree-traversal.lisp
@@ -58,36 +58,41 @@
(defun make-tree (num-rows num-child)
"Creates a simple tree, where every node has 'num-child' children and is 'num-rows' deep."
;; A tree with 0 rows can't be created.
- (if (eql num-rows 1)
+ (if (eql num-rows 0)
(make-node
- :data 1
+ :data 0
:children nil)
(make-node
:data num-rows
:children (loop repeat num-child collect (make-tree (1- num-rows) num-child)))))
;; A tree for testing
-(defvar tree (make-tree 3 3))
+(defvar tree (make-tree 2 3))
;; A binary tree for testing
(defvar binary-tree (make-tree 3 2))
;; Should print: 3 2 1 1 1 2 1 1 1 2 1 1 1
+(format t "[#]~%Recursive DFS:~%")
(dfs-recursive tree)
(format t "~%")
;; Should print: 1 1 1 2 1 1 1 2 1 1 1 2 3
+(format t "[#]~%Recursive Postorder DFS:~%")
(dfs-recursive-postorder tree)
(format t "~%")
-;; Should print: 1 2 1 3 1 2 1
-(dfs-recursive-inorder-btree binary-tree)
-(format t "~%")
-
;; Should print: 3 2 1 1 1 2 1 1 1 2 1 1 1
+(format t "[#]~%Stack-based DFS:~%")
(dfs-stack tree)
(format t "~%")
;; Should print: 3 2 2 2 1 1 1 1 1 1 1 1 1
+(format t "[#]~%Queue-based BFS:~%")
(bfs-queue tree)
(format t "~%")
+
+;; Should print: 1 2 1 3 1 2 1
+(format t "[#]~%Recursive Inorder DFS for Binary Tree:~%")
+(dfs-recursive-inorder-btree binary-tree)
+(format t "~%")
diff --git a/contents/tree_traversal/code/coconut/tree_traversal.coco b/contents/tree_traversal/code/coconut/tree_traversal.coco
index c7433fea2..a5ba371b6 100644
--- a/contents/tree_traversal/code/coconut/tree_traversal.coco
+++ b/contents/tree_traversal/code/coconut/tree_traversal.coco
@@ -16,20 +16,20 @@ def dfs_recursive_postorder(Node(value, children)):
def dfs_recursive_inorder_btree(Node(value, children)):
"""A depth first search approach for printing all values in a binary tree."""
- case len(children):
- match 2:
+ match len(children):
+ case 2:
dfs_recursive_inorder_btree(children[0])
print(value, end=' ')
dfs_recursive_inorder_btree(children[1])
- match 1:
+ case 1:
dfs_recursive_inorder_btree(children[0])
print(value, end=' ')
- match 0:
+ case 0:
print(value, end=' ')
else:
print('Invalid binary tree')
-def dfs_stack(node is Node):
+def dfs_stack(Node(node)):
"""A depth first approach for printing out all values in a tree using a stack."""
stack = [node]
while stack:
@@ -38,7 +38,7 @@ def dfs_stack(node is Node):
for child in current_node.children:
stack.append(child)
-def bfs_queue(node is Node):
+def bfs_queue(Node(node)):
"""A breadth first search approach for printing out all values in a tree."""
queue = deque([node])
while queue:
@@ -50,8 +50,8 @@ def bfs_queue(node is Node):
def create_tree(num_rows, num_child):
"""Creates a simple tree, where every node has
'num_child' children and is 'num_rows' deep."""
- if num_rows == 1:
- return Node(1, ())
+ if num_rows == 0:
+ return Node(0, ())
else:
return Node(num_rows, tuple(create_tree(num_rows-1, num_child)
for _ in range(num_child)))
@@ -59,33 +59,28 @@ def create_tree(num_rows, num_child):
if __name__ =='__main__':
# A ternary tree for testing
- tree = create_tree(3, 3)
+ tree = create_tree(2, 3)
- # Should print: 3 2 1 1 1 2 1 1 1 2 1 1 1
- print("Recursive DFS:")
+ print("[#]\nRecursive DFS:")
dfs_recursive(tree)
print()
- # Should print: 1 1 1 2 1 1 1 2 1 1 1 2 3
- print("Recursive Postorder DFS:")
+ print("[#]\nRecursive Postorder DFS:")
dfs_recursive_postorder(tree)
print()
- # Should print: 3 2 1 1 1 2 1 1 1 2 1 1 1
- print("Stack (DFS):")
+ print("[#]\nStack-based DFS:")
dfs_stack(tree)
print()
- # Should print: 3 2 2 2 1 1 1 1 1 1 1 1 1
- print("Queue (BFS):")
+ print("[#]\nQueue-based BFS:")
bfs_queue(tree)
print()
# And a binary tree for testing
binary_tree = create_tree(3, 2)
- # Should print: 1 2 1 3 1 2 1
- print("Recursive Inorder Binary Tree:")
+ print("[#]\nRecursive Inorder DFS for Binary Tree:")
dfs_recursive_inorder_btree(binary_tree)
print()
diff --git a/contents/tree_traversal/code/c++/tree_example.cpp b/contents/tree_traversal/code/cpp/tree_example.cpp
similarity index 77%
rename from contents/tree_traversal/code/c++/tree_example.cpp
rename to contents/tree_traversal/code/cpp/tree_example.cpp
index 9f2dd80e1..90271b58d 100644
--- a/contents/tree_traversal/code/c++/tree_example.cpp
+++ b/contents/tree_traversal/code/cpp/tree_example.cpp
@@ -11,13 +11,13 @@ using std::size_t;
struct node {
std::vector children;
- int value;
+ size_t value;
};
// Simple recursive scheme for DFS
void dfs_recursive(node const& n) {
// Here we are doing something...
- std::cout << n.value << '\n';
+ std::cout << n.value << ' ';
for (auto const& child : n.children) {
dfs_recursive(child);
}
@@ -27,7 +27,7 @@ void dfs_recursive_postorder(node const& n) {
for (auto const& child : n.children) {
dfs_recursive_postorder(child);
}
- std::cout << n.value << '\n';
+ std::cout << n.value << ' ';
}
@@ -35,15 +35,15 @@ void dfs_recursive_inorder_btree(node const& n) {
switch (n.children.size()) {
case 2:
dfs_recursive_inorder_btree(n.children[0]);
- std::cout << n.value << '\n';
+ std::cout << n.value << ' ';
dfs_recursive_inorder_btree(n.children[1]);
break;
case 1:
dfs_recursive_inorder_btree(n.children[0]);
- std::cout << n.value << '\n';
+ std::cout << n.value << ' ';
break;
case 0:
- std::cout << n.value << '\n';
+ std::cout << n.value << ' ';
break;
default:
std::cout << "This is not a binary tree.\n";
@@ -61,7 +61,7 @@ void dfs_stack(node const& n) {
while (stack.size() > 0) {
auto const& temp = *stack.top();
stack.pop();
- std::cout << temp.value << '\n';
+ std::cout << temp.value << ' ';
for (auto const& child : temp.children) {
stack.push(&child);
@@ -78,7 +78,7 @@ void bfs_queue(node const& n) {
auto const& temp = *queue.front();
queue.pop();
- std::cout << temp.value << '\n';
+ std::cout << temp.value << ' ';
for (auto const& child : temp.children) {
queue.push(&child);
}
@@ -100,18 +100,23 @@ node create_tree(size_t num_row, size_t num_child) {
int main() {
// Creating Tree in main
- auto root = create_tree(3, 3);
+ auto root = create_tree(2, 3);
auto binary_root = create_tree(3, 2);
- std::cout << "DFS recursive:\n";
+ std::cout << "[#]\nRecursive DFS:\n";
dfs_recursive(root);
- std::cout << "DFS post order recursive:\n";
+ std::cout << '\n';
+ std::cout << "[#]\nRecursive Postorder DFS:\n";
dfs_recursive_postorder(root);
- std::cout << "DFS inorder binary tree:\n";
- dfs_recursive_inorder_btree(binary_root);
- std::cout << "DFS stack:\n";
+ std::cout << '\n';
+ std::cout << "[#]\nStack-based DFS:\n";
dfs_stack(root);
- std::cout << "BFS queue:\n";
+ std::cout << '\n';
+ std::cout << "[#]\nQueue-based BFS:\n";
bfs_queue(root);
+ std::cout << '\n';
+ std::cout << "[#]\nRecursive Inorder DFS for Binary Tree:\n";
+ dfs_recursive_inorder_btree(binary_root);
+ std::cout << '\n';
return 0;
}
diff --git a/contents/tree_traversal/code/crystal/tree-traversal.cr b/contents/tree_traversal/code/crystal/tree-traversal.cr
index e3556d8eb..e63dbbb7e 100644
--- a/contents/tree_traversal/code/crystal/tree-traversal.cr
+++ b/contents/tree_traversal/code/crystal/tree-traversal.cr
@@ -5,26 +5,26 @@ class Node
end
def dfs_recursive(node)
- print node.id
+ print "#{node.id} "
node.children.each{ |child| dfs_recursive child }
end
def dfs_recursive_postorder(node)
node.children.each{ |child| dfs_recursive_postorder child }
- print node.id
+ print "#{node.id} "
end
def dfs_recursive_inorder_btree(node)
case node.children.size
when 2
dfs_recursive_inorder_btree node.children[0]
- print node.id
+ print "#{node.id} "
dfs_recursive_inorder_btree node.children[1]
when 1
dfs_recursive_inorder_btree node.children[0]
- print node.id
+ print "#{node.id} "
when 0
- print node.id
+ print "#{node.id} "
else
print "Not a binary tree!"
end
@@ -35,7 +35,7 @@ def dfs_stack(node)
until stack.empty?
temp = stack.pop
- print temp.id
+ print "#{temp.id} "
temp.children.each{ |child| stack.push child }
end
end
@@ -45,7 +45,7 @@ def bfs_queue(node)
until queue.empty?
temp = queue.shift
- print temp.id
+ print "#{temp.id} "
temp.children.each{ |child| queue.push child }
end
end
@@ -60,54 +60,28 @@ def create_tree(levels, num_childs)
Node.new(levels, children)
end
-def print_tree(node, depth = [] of String)
- puts "(#{node.id})"
- depth.push " "
- len = node.children.size - 1
-
- (0 .. len).each do |i|
- depth.each{|c| print c}
- unless i == len
- print "├"
- depth.push "│"
- print_tree node.children[i], depth
- depth.pop
- else
- print "â””"
- depth.push " "
- print_tree node.children[i], depth
- depth.pop
- end
- end
- depth.pop
-end
-
def main
- puts "Creating Tree"
root = create_tree levels: 2, num_childs: 3
- print_tree root
- puts "Using recursive DFS:"
+ puts "[#]\nRecursive DFS:"
dfs_recursive root
puts
- puts "Using recursive DFS with post-order traversal:"
+ puts "[#]\nRecursive Postorder DFS:"
dfs_recursive_postorder root
puts
- puts "Using stack-based DFS:"
+ puts "[#]\nStack-based DFS:"
dfs_stack root
puts
- puts "Using queue-based BFS:"
+ puts "[#]\nQueue-based BFS:"
bfs_queue root
puts
- puts "Creating binary tree to test in-order traversal"
root_bin = create_tree levels: 3, num_childs: 2
- print_tree root_bin
- puts "Using In-order DFS:"
+ puts "[#]\nRecursive Inorder DFS for Binary Tree:"
dfs_recursive_inorder_btree root_bin
puts
end
diff --git a/contents/tree_traversal/code/csharp/Program.cs b/contents/tree_traversal/code/csharp/Program.cs
index aa2df0485..0fc35c547 100644
--- a/contents/tree_traversal/code/csharp/Program.cs
+++ b/contents/tree_traversal/code/csharp/Program.cs
@@ -1,4 +1,3 @@
-// submitted by Julian Schacher (jspp)
using System;
namespace TreeTraversal
@@ -7,23 +6,27 @@ class Program
{
static void Main(string[] args)
{
- Console.WriteLine("TreeTraversal");
- var tree = new Tree(3, 3);
- Console.WriteLine("DFSRecursive:");
+ var tree = new Tree(2, 3);
+ Console.WriteLine("[#]\nRecursive DFS:");
tree.DFSRecursive();
- Console.WriteLine("DFSStack:");
+ Console.WriteLine();
+
+ Console.WriteLine("[#]\nRecursive Postorder DFS:");
+ tree.DFSRecursivePostorder();
+ Console.WriteLine();
+
+ Console.WriteLine("[#]\nStack-based DFS:");
tree.DFSStack();
- Console.WriteLine("BFSQueue:");
+ Console.WriteLine();
+
+ Console.WriteLine("[#]\nQueue-based BFS:");
tree.BFSQueue();
- Console.WriteLine("DFSRecursivePostorder");
- tree.DFSRecursivePostorder();
+ Console.WriteLine();
- // Uncommenting the following 2 lines will result in an exception thrown because at least one Node of the Tree has more than 2 children and therefor a DFSRecursiveInorderBinary doesn't work.
- // Console.WriteLine("DFSRecursiveInorder (fail)");
- // tree.DFSRecursiveInorderBinary();
tree = new Tree(3, 2);
- Console.WriteLine("DFSRecursiveInorder (succeed)");
+ Console.WriteLine("[#]\nRecursive Inorder DFS for Binary Tree:");
tree.DFSRecursiveInorderBinary();
+ Console.WriteLine();
}
}
}
diff --git a/contents/tree_traversal/code/csharp/Tree.cs b/contents/tree_traversal/code/csharp/Tree.cs
index e38be26fc..5e8bc263c 100644
--- a/contents/tree_traversal/code/csharp/Tree.cs
+++ b/contents/tree_traversal/code/csharp/Tree.cs
@@ -1,4 +1,3 @@
-// submitted by Julian Schacher (jspp)
using System;
using System.Collections.Generic;
@@ -11,49 +10,71 @@ public class Tree
public Tree(int depthCount, int childrenCount)
{
- this.Id = 1;
+ Id = 1;
- if (!(depthCount <= 1))
+ if (depthCount > 0)
{
for (int i = 0; i < childrenCount; i++)
- this._children.Add(new Tree(this.Id * 10 + i + 1, depthCount - 1, childrenCount));
+ _children.Add(new Tree(Id * 10 + i + 1, depthCount - 1, childrenCount));
}
}
private Tree(int id, int depthCount, int childrenCount)
{
- this.Id = id;
+ Id = id;
if (!(depthCount <= 1))
{
for (int i = 0; i < childrenCount; i++)
- this._children.Add(new Tree(this.Id * 10 + i + 1, depthCount - 1, childrenCount));
+ _children.Add(new Tree(Id * 10 + i + 1, depthCount - 1, childrenCount));
}
}
+ private void DFSRecursive(Tree tree) {
+ Console.Write(tree.Id + " ");
+
+ foreach (var c in tree._children)
+ DFSRecursive(c);
+ }
+
public void DFSRecursive()
{
DFSRecursive(this);
- void DFSRecursive(Tree tree)
- {
- Console.WriteLine(tree.Id);
+ }
- foreach (var c in tree._children)
- DFSRecursive(c);
- }
+ private void DFSRecursivePostorder(Tree tree)
+ {
+ foreach (var c in tree._children)
+ DFSRecursivePostorder(c);
+
+ Console.Write(tree.Id + " ");
}
public void DFSRecursivePostorder()
{
DFSRecursivePostorder(this);
- void DFSRecursivePostorder(Tree tree)
- {
- foreach (var c in tree._children)
- DFSRecursivePostorder(c);
+ }
- Console.WriteLine(tree.Id);
+ private void DFSRecursiveInorderBinary(Tree tree)
+ {
+ switch (tree._children.Count)
+ {
+ case 2:
+ DFSRecursiveInorderBinary(tree._children[0]);
+ Console.Write(tree.Id + " ");
+ DFSRecursiveInorderBinary(tree._children[1]);
+ break;
+ case 1:
+ DFSRecursiveInorderBinary(tree._children[0]);
+ Console.Write(tree.Id + " ");
+ break;
+ case 0:
+ Console.Write(tree.Id + " ");
+ break;
+ default:
+ throw new Exception("Not binary tree!");
}
}
@@ -61,21 +82,6 @@ public void DFSRecursiveInorderBinary()
{
DFSRecursiveInorderBinary(this);
- // This assumes only 2 children
- void DFSRecursiveInorderBinary(Tree tree)
- {
- if (tree._children.Count > 2)
- throw new Exception("Not binary tree!");
-
- if (tree._children.Count > 0)
- {
- DFSRecursiveInorderBinary(tree._children[0]);
- Console.WriteLine(tree.Id);
- DFSRecursiveInorderBinary(tree._children[1]);
- }
- else
- Console.WriteLine(tree.Id);
- }
}
public void DFSStack()
@@ -85,7 +91,7 @@ public void DFSStack()
while (stack.Count != 0)
{
- Console.WriteLine(stack.Peek().Id);
+ Console.Write(stack.Peek().Id + " ");
var temp = stack.Pop();
foreach (var c in temp._children)
@@ -100,7 +106,7 @@ public void BFSQueue()
while (queue.Count != 0)
{
- Console.WriteLine(queue.Peek().Id);
+ Console.Write(queue.Peek().Id + " ");
var temp = queue.Dequeue();
foreach (var c in temp._children)
diff --git a/contents/tree_traversal/code/csharp/code.csproj b/contents/tree_traversal/code/csharp/code.csproj
new file mode 100644
index 000000000..98c5e6713
--- /dev/null
+++ b/contents/tree_traversal/code/csharp/code.csproj
@@ -0,0 +1,9 @@
+
+
+
+ Exe
+ net5.0
+ false
+
+
+
diff --git a/contents/tree_traversal/code/golang/treetraversal.go b/contents/tree_traversal/code/go/treetraversal.go
similarity index 68%
rename from contents/tree_traversal/code/golang/treetraversal.go
rename to contents/tree_traversal/code/go/treetraversal.go
index 548f552f7..fb5142712 100644
--- a/contents/tree_traversal/code/golang/treetraversal.go
+++ b/contents/tree_traversal/code/go/treetraversal.go
@@ -8,7 +8,7 @@ type node struct {
}
func dfsRecursive(n *node) {
- fmt.Println(n.id)
+ fmt.Printf("%d ", n.id)
for _, child := range n.children {
dfsRecursive(child)
}
@@ -16,22 +16,22 @@ func dfsRecursive(n *node) {
func dfsRecursivePostorder(n *node) {
for _, child := range n.children {
- dfsRecursive(child)
+ dfsRecursivePostorder(child)
}
- fmt.Println(n.id)
+ fmt.Printf("%d ", n.id)
}
func dfsRecursiveInorderBtree(n *node) {
switch len(n.children) {
case 2:
dfsRecursiveInorderBtree(n.children[0])
- fmt.Println(n.id)
+ fmt.Printf("%d ", n.id)
dfsRecursiveInorderBtree(n.children[1])
case 1:
dfsRecursiveInorderBtree(n.children[0])
- fmt.Println(n.id)
+ fmt.Printf("%d ", n.id)
case 0:
- fmt.Println(n.id)
+ fmt.Printf("%d ", n.id)
default:
fmt.Println("This is not a binary tree")
}
@@ -43,7 +43,7 @@ func dfsStack(n *node) {
for len(stack) > 0 {
cur := stack[0]
stack = stack[1:]
- fmt.Println(cur.id)
+ fmt.Printf("%d ", cur.id)
stack = append(cur.children, stack...)
}
}
@@ -54,7 +54,7 @@ func bfsQueue(n *node) {
for len(queue) > 0 {
cur := queue[0]
queue = queue[1:]
- fmt.Println(cur.id)
+ fmt.Printf("%d ", cur.id)
queue = append(queue, cur.children...)
}
}
@@ -74,17 +74,27 @@ func createTree(numRow, numChild int) *node {
}
func main() {
- root := createTree(3, 3)
+ root := createTree(2, 3)
binTree := createTree(3, 2)
- fmt.Println("DFS recursive:")
+ fmt.Println("[#]\nRecursive DFS:")
dfsRecursive(root)
- fmt.Println("DFS post order recursive:")
+ fmt.Println()
+
+ fmt.Println("[#]\nRecursive Postorder DFS:")
dfsRecursivePostorder(root)
- fmt.Println("DFS inorder binary tree:")
- dfsRecursiveInorderBtree(binTree)
- fmt.Println("DFS stack:")
+ fmt.Println()
+
+ fmt.Println("[#]\nStack-based DFS:")
dfsStack(root)
- fmt.Println("BFS queue:")
+ fmt.Println()
+
+ fmt.Println("[#]\nQueue-based BFS:")
bfsQueue(root)
+ fmt.Println()
+
+ fmt.Println("[#]\nRecursive Inorder DFS for Binary Tree:")
+ dfsRecursiveInorderBtree(binTree)
+ fmt.Println()
+
}
diff --git a/contents/tree_traversal/code/haskell/TreeTraversal.hs b/contents/tree_traversal/code/haskell/TreeTraversal.hs
index 389dc0900..1f9d27db8 100644
--- a/contents/tree_traversal/code/haskell/TreeTraversal.hs
+++ b/contents/tree_traversal/code/haskell/TreeTraversal.hs
@@ -1,7 +1,8 @@
data Tree a = Node
- { node :: a
- , forest :: [Tree a]
- } deriving (Show)
+ { node :: a,
+ forest :: [Tree a]
+ }
+ deriving (Show)
dfs :: Tree a -> [a]
dfs (Node x ts) = x : concatMap dfs ts
@@ -19,7 +20,7 @@ dfsStack :: Tree a -> [a]
dfsStack t = go [t]
where
go [] = []
- go ((Node x ts):stack) = x : go (ts ++ stack)
+ go ((Node x ts) : stack) = x : go (ts ++ stack)
bfs :: Tree a -> [a]
bfs (Node x ts) = x : go ts
@@ -27,26 +28,22 @@ bfs (Node x ts) = x : go ts
go [] = []
go ts = map node ts ++ go (concatMap forest ts)
-toBin :: Tree a -> Tree a
-toBin (Node x ts) = Node x (map toBin $ take 2 ts)
+createTree :: Int -> Int -> Tree Int
+createTree 0 _ = Node 0 []
+createTree numRow numChild = Node numRow children
+ where
+ children = map (createTree (numRow - 1)) $ replicate numChild numChild
main = do
- print $ dfs testTree
- print $ dfsPostOrder testTree
- print $ dfsInOrder $ toBin testTree
- print $ dfsStack testTree
- print $ bfs testTree
-
-testTree :: Tree Int
-testTree =
- Node
- 1
- [ Node 2 [Node 3 [], Node 4 [Node 5 []]]
- , Node
- 6
- [ Node 7 []
- , Node 8 [Node 9 [Node 10 [Node 11 []], Node 12 []]]
- , Node 13 [Node 14 []]
- ]
- , Node 15 []
- ]
+ let testTree = createTree 2 3
+ showNodes = unwords . map show
+ putStrLn "[#]\nRecursive DFS:"
+ putStrLn $ showNodes $ dfs testTree
+ putStrLn "[#]\nRecursive Postorder DFS:"
+ putStrLn $ showNodes $ dfsPostOrder testTree
+ putStrLn "[#]\nStack-based DFS:"
+ putStrLn $ showNodes $ dfsStack testTree
+ putStrLn "[#]\nQueue-based BFS:"
+ putStrLn $ showNodes $ bfs testTree
+ putStrLn "[#]\nRecursive Inorder DFS for Binary Tree:"
+ putStrLn $ showNodes $ dfsInOrder $ createTree 3 2
diff --git a/contents/tree_traversal/code/java/MainClass.java b/contents/tree_traversal/code/java/MainClass.java
index 59dd20c09..d7c062c03 100644
--- a/contents/tree_traversal/code/java/MainClass.java
+++ b/contents/tree_traversal/code/java/MainClass.java
@@ -1,31 +1,34 @@
//submitted by xam4lor
public class MainClass {
public static void main(String[] args) {
- System.out.println("Creating Tree");
- Tree tree = new Tree(3, 3);
+ Tree tree = new Tree(2, 3);
- System.out.println("Using recursive DFS :");
+ System.out.println("[#]\nRecursive DFS:");
tree.dfsRecursive();
+ System.out.println();
- System.out.println("Using stack-based DFS :");
+ System.out.println("[#]\nRecursive Postorder DFS:");
+ tree.dfsRecursivePostOrder();
+ System.out.println();
+
+
+ System.out.println("[#]\nStack-based DFS:");
tree.dfsStack();
+ System.out.println();
- System.out.println("Using queue-based BFS :");
- tree.bfsQueue();
- System.out.println("Using post-order recursive DFS :");
- tree.dfsRecursivePostOrder();
+ System.out.println("[#]\nQueue-based BFS:");
+ tree.bfsQueue();
+ System.out.println();
// Uncommenting the following 2 lines will result in an exception thrown because at least one Node of the Tree has more than 2 children and therefor a DFSRecursiveInorderBinary doesn't work.
- System.out.println("Using in-order binary recursive DFS : (fail)");
- tree.dfsRecursiveInOrderBinary();
+ //System.out.println("Using in-order binary recursive DFS : (fail)");
+ //tree.dfsRecursiveInOrderBinary();
tree = new Tree(3, 2);
- System.out.println("Using in-order binary recursive DFS : (succeed)");
+ System.out.println("[#]\nRecursive Inorder DFS for Binary Tree:");
tree.dfsRecursiveInOrderBinary();
-
-
- System.out.println("");
+ System.out.println();
}
}
diff --git a/contents/tree_traversal/code/java/Tree.java b/contents/tree_traversal/code/java/Tree.java
index 595df47b0..93e508f6c 100644
--- a/contents/tree_traversal/code/java/Tree.java
+++ b/contents/tree_traversal/code/java/Tree.java
@@ -1,6 +1,5 @@
-// submitted by xam4lor
import java.util.ArrayList;
-import java.util.PriorityQueue;
+import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
@@ -9,8 +8,8 @@ public class Tree {
public Tree(int rowCount, int childrenCount) {
// this.root is the root node of the Tree
- this.root = new Node(1);
- this.createAllChildren(this.root, rowCount, childrenCount);
+ this.root = new Node(rowCount);
+ this.createAllChildren(this.root, rowCount-1, childrenCount);
}
@@ -19,7 +18,7 @@ public void dfsRecursive() {
}
private void dfsRecursive(Node node) {
- System.out.println(node.id);
+ System.out.print(node.id + " ");
for (Node n : node.children) {
dfsRecursive(n);
@@ -37,7 +36,7 @@ private void dfsRecursivePostOrder(Node node) {
}
// Here we are doing something ...
- System.out.println(node.id);
+ System.out.print(node.id + " ");
}
@@ -45,19 +44,22 @@ public void dfsRecursiveInOrderBinary() {
dfsRecursiveInOrderBinary(this.root);
}
- // This assumes only 2 children
private void dfsRecursiveInOrderBinary(Node node) {
- if (node.children.size() > 2) {
- System.err.println("Not a binary tree at dfsRecursiveInOrderBinary()!");
- return;
- }
-
- if (node.children.size() > 1) {
- dfsRecursiveInOrderBinary(node.children.get(0));
- System.out.println(node.id);
- dfsRecursiveInOrderBinary(node.children.get(1));
- } else {
- System.out.println(node.id);
+ switch (node.children.size()) {
+ case 2:
+ dfsRecursiveInOrderBinary(node.children.get(0));
+ System.out.print(node.id + " ");
+ dfsRecursiveInOrderBinary(node.children.get(1));
+ break;
+ case 1:
+ dfsRecursiveInOrderBinary(node.children.get(0));
+ System.out.print(node.id + " ");
+ break;
+ case 0:
+ System.out.print(node.id + " ");
+ break;
+ default:
+ System.err.println("Not a binary tree at dfsRecursiveInOrderBinary()!");
}
}
@@ -69,7 +71,7 @@ public void dfsStack() {
Node tmp;
while (stack.size() != 0) {
- System.out.println(stack.peek().id);
+ System.out.print(stack.peek().id + " ");
tmp = stack.pop();
for (Node c : tmp.children) {
@@ -79,11 +81,11 @@ public void dfsStack() {
}
public void bfsQueue() {
- Queue queue = new PriorityQueue();
+ Queue queue = new LinkedList();
queue.add(this.root);
while (queue.size() != 0) {
- System.out.println(queue.peek().id);
+ System.out.print(queue.peek().id + " ");
Node temp = queue.poll(); // return null if the queue is empty
if (temp != null) {
@@ -96,12 +98,12 @@ public void bfsQueue() {
private void createAllChildren(Node node, int rowCount, int childrenCount) {
- if (rowCount <= 1) {
+ if (rowCount < 0) {
return;
}
for (int i = 0; i < childrenCount; i++) {
- node.children.add(new Node(node.id * 10 + i + 1));
+ node.children.add(new Node(rowCount));
createAllChildren(node.children.get(i), rowCount - 1, childrenCount);
}
}
@@ -124,4 +126,36 @@ public int compareTo(Node other) {
return Integer.compare(this.id, other.id);
}
}
+
+ public static void main(String[] args) {
+ Tree tree = new Tree(2, 3);
+
+ System.out.println("[#]\nRecursive DFS:");
+ tree.dfsRecursive();
+ System.out.println();
+
+ System.out.println("[#]\nRecursive Postorder DFS:");
+ tree.dfsRecursivePostOrder();
+ System.out.println();
+
+
+ System.out.println("[#]\nStack-based DFS:");
+ tree.dfsStack();
+ System.out.println();
+
+
+ System.out.println("[#]\nQueue-based BFS:");
+ tree.bfsQueue();
+ System.out.println();
+
+
+ // Uncommenting the following 2 lines will result in an exception thrown because at least one Node of the Tree has more than 2 children and therefor a DFSRecursiveInorderBinary doesn't work.
+ //System.out.println("Using in-order binary recursive DFS : (fail)");
+ //tree.dfsRecursiveInOrderBinary();
+
+ tree = new Tree(3, 2);
+ System.out.println("[#]\nRecursive Inorder DFS for Binary Tree:");
+ tree.dfsRecursiveInOrderBinary();
+ System.out.println();
+ }
}
diff --git a/contents/tree_traversal/code/javascript/tree.js b/contents/tree_traversal/code/javascript/tree.js
index b6705bfdd..1fbffa02a 100644
--- a/contents/tree_traversal/code/javascript/tree.js
+++ b/contents/tree_traversal/code/javascript/tree.js
@@ -10,13 +10,21 @@ function createTree(rows, children) {
}
function dfsPreorder(tree) {
- console.log(tree.id);
+ if (!tree) {
+ return;
+ }
+
+ process.stdout.write(tree.id + " ");
tree.children.forEach(dfsPreorder);
}
function dfsPostorder(tree) {
+ if (!tree) {
+ return;
+ }
+
tree.children.forEach(dfsPostorder);
- console.log(tree.id);
+ process.stdout.write(tree.id + " ");
}
function dfsInorder(tree) {
@@ -24,20 +32,29 @@ function dfsInorder(tree) {
return;
}
- if (tree.children.length > 2) {
- throw new Error("Postorder traversal is only valid for binary trees");
+ switch (tree.children.length) {
+ case 2:
+ dfsInorder(tree.children[0]);
+ console.log(tree.id);
+ dfsInorder(tree.children[1]);
+ break;
+ case 1:
+ dfsInorder(tree.children[0]);
+ console.log(tree.id);
+ break;
+ case 0:
+ console.log(tree.id);
+ break;
+ default:
+ throw new Error("Postorder traversal is only valid for binary trees");
}
-
- dfsInorder(tree.children[0]);
- console.log(tree.id);
- dfsInorder(tree.children[1]);
}
function dfsIterative(tree) {
const stack = [tree];
while (stack.length > 0) {
const current = stack.pop();
- console.log(current.id);
+ process.stdout.write(current.id + " ");
stack.push(...current.children);
}
}
@@ -46,13 +63,26 @@ function bfs(tree) {
const queue = [tree];
while (queue.length > 0) {
const current = queue.shift();
- console.log(current.id);
+ process.stdout.write(current.id + " ");
queue.push(...current.children);
}
}
-const root = createTree(3, 3);
+const root = createTree(2, 3);
+console.log("[#]\nRecursive DFS:");
dfsPreorder(root);
+console.log();
+console.log("[#]\nRecursive Postorder DFS:");
dfsPostorder(root);
+console.log();
+console.log("[#]\nStack-based DFS:");
dfsIterative(root);
+console.log();
+console.log("[#]\nQueue-based BFS:");
bfs(root);
+console.log();
+const root_binary = createTree(3, 2);
+console.log("[#]\nRecursive Inorder DFS for Binary Tree:");
+dfsInorder(root_binary);
+console.log();
+
diff --git a/contents/tree_traversal/code/julia/Tree.jl b/contents/tree_traversal/code/julia/Tree.jl
index 8e7893cd1..7382fdad0 100644
--- a/contents/tree_traversal/code/julia/Tree.jl
+++ b/contents/tree_traversal/code/julia/Tree.jl
@@ -1,4 +1,4 @@
-using DataStructures
+using DataStructures, Printf
struct Node
children::Vector{Node}
@@ -8,7 +8,7 @@ end
function DFS_recursive(n::Node)
# Here we are doing something...
- println(n.ID)
+ print(n.ID, " ")
for child in n.children
DFS_recursive(child)
@@ -22,7 +22,7 @@ function DFS_recursive_postorder(n::Node)
end
# Here we are doing something...
- println(n.ID)
+ print(n.ID, " ")
end
# This assumes only 2 children, but accounts for other possibilities
@@ -30,13 +30,13 @@ function DFS_recursive_inorder_btree(n::Node)
if (length(n.children) == 2)
DFS_recursive_inorder_btree(n.children[1])
- println(n.ID)
+ print(n.ID, " ")
DFS_recursive_inorder_btree(n.children[2])
elseif (length(n.children) == 1)
DFS_recursive_inorder_btree(n.children[1])
- println(n.ID)
+ print(n.ID, " ")
elseif (length(n.children) == 0)
- println(n.ID)
+ print(n.ID, " ")
else
println("Not a binary tree!")
end
@@ -47,7 +47,7 @@ function DFS_stack(n::Node)
push!(s, n)
while(length(s) > 0)
- println(top(s).ID)
+ print(top(s).ID, " ")
temp = pop!(s)
for child in temp.children
push!(s, child)
@@ -60,7 +60,7 @@ function BFS_queue(n::Node)
enqueue!(q, n)
while(length(q) > 0)
- println(front(q).ID)
+ print(first(q).ID, " ")
temp = dequeue!(q)
for child in temp.children
enqueue!(q, child)
@@ -84,26 +84,28 @@ function create_tree(num_row::Int64, num_child::Int64)
end
function main()
-
- println("Creating Tree")
root = create_tree(2, 3)
- println("Using recursive DFS:")
+ println("[#]\nRecursive DFS:")
DFS_recursive(root);
+ println()
- println("Using recursive DFS with post-order traversal:")
+ println("[#]\nRecursive Postorder DFS:")
DFS_recursive_postorder(root);
+ println()
- println("Using stack-based DFS:")
+ println("[#]\nStack-based DFS:")
DFS_stack(root);
+ println()
- println("Using queue-based BFS:")
+ println("[#]\nQueue-based BFS:")
BFS_queue(root);
+ println()
- println("Creating binary tree to test in-order traversal.")
root_binary = create_tree(3,2)
- println("Using In-order DFS:")
+ println("[#]\nRecursive Inorder DFS for Binary Tree:")
DFS_recursive_inorder_btree(root_binary)
+ println()
end
main()
diff --git a/contents/tree_traversal/code/php/tree_traversal.php b/contents/tree_traversal/code/php/tree_traversal.php
index fde55046a..3c829977b 100644
--- a/contents/tree_traversal/code/php/tree_traversal.php
+++ b/contents/tree_traversal/code/php/tree_traversal.php
@@ -40,9 +40,7 @@ class TreeTraversal
{
public static function DFSRecursive(Tree $tree): void
{
- if ($tree->getId()) {
- echo $tree->getId() . PHP_EOL;
- }
+ echo $tree->getId() . ' ';
foreach ($tree->getChildren() as $child) {
static::DFSRecursive($child);
}
@@ -53,7 +51,7 @@ public static function DFSRecursivePostorder(Tree $tree): void
foreach ($tree->getChildren() as $child) {
static::DFSRecursivePostorder($child);
}
- echo $tree->getId() . PHP_EOL;
+ echo $tree->getId() . ' ';
}
public static function DFSRecursiveInorderBinary(Tree $tree): void
@@ -61,15 +59,15 @@ public static function DFSRecursiveInorderBinary(Tree $tree): void
switch (count($tree->getChildren())) {
case 2:
static::DFSRecursiveInorderBinary($tree->getChildren()[0]);
- echo $tree->getId() . PHP_EOL;
+ echo $tree->getId() . ' ';
static::DFSRecursiveInorderBinary($tree->getChildren()[1]);
break;
case 1:
static::DFSRecursiveInorderBinary($tree->getChildren()[0]);
- echo $tree->getId() . PHP_EOL;
+ echo $tree->getId() . ' ';
break;
case 0:
- echo $tree->getId() . PHP_EOL;
+ echo $tree->getId() . ' ';
break;
default:
throw new InvalidArgumentException('Not a binary tree!');
@@ -83,7 +81,7 @@ public static function DFSStack(Tree $tree): void
$temp = null;
while (null !== ($temp = array_pop($stack))) {
- echo $temp->getId() . PHP_EOL;
+ echo $temp->getId() . ' ';
foreach ($temp->getChildren() as $child) {
$stack[] = $child;
}
@@ -96,7 +94,7 @@ public static function DFSQueue(Tree $tree): void
$temp = null;
while (null !== ($temp = array_shift($stack))) {
- echo $temp->getId() . PHP_EOL;
+ echo $temp->getId() . ' ';
foreach ($temp->getChildren() as $child) {
$stack[] = $child;
}
@@ -104,16 +102,13 @@ public static function DFSQueue(Tree $tree): void
}
}
-function generate_tree(int $numOfRows, int $numOfChildren, int $id = -1): Tree
+function generate_tree(int $numOfRows, int $numOfChildren): Tree
{
- if ($id === -1) {
- $id = 1;
- }
- $node = new Tree($id);
+ $node = new Tree($numOfRows);
- if ($numOfRows > 1) {
+ if ($numOfRows > 0) {
for ($i = 0; $i < $numOfChildren; $i++) {
- $child = generate_tree($numOfRows - 1, $numOfChildren, $id * 10 + $i + 1);
+ $child = generate_tree($numOfRows - 1, $numOfChildren);
$node->addChild($child);
}
}
@@ -121,23 +116,28 @@ function generate_tree(int $numOfRows, int $numOfChildren, int $id = -1): Tree
return $node;
}
-$node = generate_tree(3, 3);
+$node = generate_tree(2, 3);
-echo 'DFS Recursive:' . PHP_EOL;
+echo '[#]' . PHP_EOL . 'Recursive DFS:' . PHP_EOL;
TreeTraversal::DFSRecursive($node);
+echo PHP_EOL;
-echo 'DFS Recursive Postorder:' . PHP_EOL;
+echo '[#]' . PHP_EOL . 'Recursive Postorder DFS:' . PHP_EOL;
TreeTraversal::DFSRecursivePostorder($node);
+echo PHP_EOL;
-echo 'DFS Stack:' . PHP_EOL;
+echo '[#]' . PHP_EOL . 'Stack-based DFS:' . PHP_EOL;
TreeTraversal::DFSStack($node);
+echo PHP_EOL;
-echo 'DFS Queue:' . PHP_EOL;
+echo '[#]' . PHP_EOL . 'Queue-based BFS:' . PHP_EOL;
TreeTraversal::DFSQueue($node);
+echo PHP_EOL;
// If you want to try to run binary order on a non-binary tree,
// comment out the generation of the new tree below.
// If you do that, an exception will be thrown
$node = generate_tree(3, 2);
-echo 'DFS Recursive Inorder Binary:' . PHP_EOL;
+echo '[#]' . PHP_EOL . 'Recursive Inorder DFS for Binary Tree:' . PHP_EOL;
TreeTraversal::DFSRecursiveInorderBinary($node);
+echo PHP_EOL;
diff --git a/contents/tree_traversal/code/python/Tree_example.py b/contents/tree_traversal/code/python/Tree_example.py
deleted file mode 100644
index 67dd516a3..000000000
--- a/contents/tree_traversal/code/python/Tree_example.py
+++ /dev/null
@@ -1,99 +0,0 @@
-class Node:
- def __init__(self):
- self.data = None
- self.children = []
-
-
-def create_tree(node, num_row, num_child):
- node.data = num_row
-
- if num_row > 0:
- for i in range(num_child):
- child = create_tree(Node(), num_row-1, num_child)
- node.children.append(child)
-
- return node
-
-
-def DFS_recursive(node):
- if node.data != None:
- print(node.data)
-
- for child in node.children:
- DFS_recursive(child)
-
-
-def DFS_recursive_postorder(node):
- for child in node.children:
- DFS_recursive_postorder(child)
-
- if node.data != None:
- print(node.data)
-
-
-# This assumes only 2 children, but accounts for other possibilities
-def DFS_recursive_inorder_btree(node):
- if (len(node.children) == 2):
- DFS_recursive_inorder_btree(node.children[0])
- print(node.data)
- DFS_recursive_inorder_btree(node.children[1])
- elif (len(node.children) == 1):
- DFS_recursive_inorder_btree(node.children[0])
- print(node.data)
- elif (len(node.children) == 0):
- print(node.data)
- else:
- print("Not a binary tree!")
-
-
-def DFS_stack(node):
- stack = []
- stack.append(node)
-
- temp = None
-
- while len(stack) > 0:
- print(stack[-1].data)
- temp = stack.pop()
-
- for child in temp.children:
- stack.append(child)
-
-
-def BFS_queue(node):
- queue = []
- queue.append(node)
-
- temp = None
-
- while len(queue) > 0:
- print(queue[0].data)
- temp = queue.pop(0)
-
- for child in temp.children:
- queue.append(child)
-
-
-def main():
- tree = create_tree(Node(), 3, 3)
-
- print("Recursive:")
- DFS_recursive(tree)
-
- print("Recursive Postorder:")
- DFS_recursive_postorder(tree)
-
- print("Stack:")
- DFS_stack(tree)
-
- print("Queue:")
- BFS_queue(tree)
-
- binaryTree = create_tree(Node(), 3, 2)
-
- print("Recursive Inorder Binary Tree:")
- DFS_recursive_inorder_btree(binaryTree)
-
-if __name__ == '__main__':
- main()
-
diff --git a/contents/tree_traversal/code/python/tree_traversal.py b/contents/tree_traversal/code/python/tree_traversal.py
new file mode 100644
index 000000000..1c15eae23
--- /dev/null
+++ b/contents/tree_traversal/code/python/tree_traversal.py
@@ -0,0 +1,90 @@
+class Node:
+ def __init__(self):
+ self.data = None
+ self.children = []
+
+def create_tree(node, num_row, num_child):
+ node.data = num_row
+
+ if num_row > 0:
+ for i in range(num_child):
+ child = create_tree(Node(), num_row-1, num_child)
+ node.children.append(child)
+
+ return node
+
+
+def dfs_recursive(node):
+ if node.data != None:
+ print(node.data, end=' ')
+
+ for child in node.children:
+ dfs_recursive(child)
+
+
+def dfs_recursive_postorder(node):
+ for child in node.children:
+ dfs_recursive_postorder(child)
+
+ if node.data != None:
+ print(node.data, end=' ')
+
+
+# This assumes only 2 children, but accounts for other possibilities
+def dfs_recursive_inorder_btree(node):
+ if len(node.children) == 2:
+ dfs_recursive_inorder_btree(node.children[0])
+ print(node.data, end=' ')
+ dfs_recursive_inorder_btree(node.children[1])
+ elif len(node.children) == 1:
+ dfs_recursive_inorder_btree(node.children[0])
+ print(node.data, end=' ')
+ elif len(node.children) == 0:
+ print(node.data, end=' ')
+ else:
+ print("Not a binary tree!")
+
+
+def dfs_stack(node):
+ stack = [node]
+ while stack:
+ node = stack.pop()
+ stack.extend(node.children)
+ print(node.data, end=' ')
+
+def bfs_queue(node):
+ queue = [node]
+ while queue:
+ node = queue.pop(0)
+ queue.extend(node.children)
+ print(node.data)
+
+
+def main():
+ tree = create_tree(Node(), 2, 3)
+
+ print("[#]\nRecursive DFS:")
+ dfs_recursive(tree)
+ print()
+
+ print("[#]\nRecursive Postorder DFS:")
+ dfs_recursive_postorder(tree)
+ print()
+
+ print("[#]\nStack-based DFS:")
+ dfs_stack(tree)
+ print()
+
+ print("[#]\nQueue-based BFS:")
+ bfs_queue(tree)
+ print()
+
+ binary_tree = create_tree(Node(), 3, 2)
+
+ print("[#]\nRecursive Inorder DFS for Binary Tree:")
+ dfs_recursive_inorder_btree(binary_tree)
+ print()
+
+if __name__ == '__main__':
+ main()
+
diff --git a/contents/tree_traversal/code/rust/tree.rs b/contents/tree_traversal/code/rust/tree.rs
index f281e1a8c..60e833858 100644
--- a/contents/tree_traversal/code/rust/tree.rs
+++ b/contents/tree_traversal/code/rust/tree.rs
@@ -7,7 +7,7 @@ struct Node {
}
fn dfs_recursive(n: &Node) {
- println!("{}", n.value);
+ print!("{} ", n.value);
for child in &n.children {
dfs_recursive(child);
@@ -19,22 +19,22 @@ fn dfs_recursive_postorder(n: &Node) {
dfs_recursive_postorder(child);
}
- println!("{}", n.value);
+ print!("{} ", n.value);
}
fn dfs_recursive_inorder_btree(n: &Node) {
match &n.children[..] {
[left, right] => {
dfs_recursive_inorder_btree(left);
- println!("{}", n.value);
+ print!("{} ", n.value);
dfs_recursive_inorder_btree(right);
}
[left] => {
dfs_recursive_inorder_btree(left);
- println!("{}", n.value);
+ print!("{} ", n.value);
}
- [] => println!("{}", n.value),
- _ => println!("This is not a binary tree."),
+ [] => print!("{} ", n.value),
+ _ => print!("This is not a binary tree. "),
}
}
@@ -42,7 +42,7 @@ fn dfs_stack(n: &Node) {
let mut stack = vec![n];
while let Some(current) = stack.pop() {
- println!("{}", current.value);
+ print!("{} ", current.value);
stack.extend(¤t.children);
}
}
@@ -52,7 +52,7 @@ fn bfs_queue(n: &Node) {
queue.push_back(n);
while let Some(current) = queue.pop_front() {
- println!("{}", current.value);
+ print!("{} ", current.value);
queue.extend(¤t.children);
}
}
@@ -78,19 +78,24 @@ fn create_tree(num_row: u64, num_child: u64) -> Node {
fn main() {
let root = create_tree(2, 3);
- println!("Recursive DFS:");
+ println!("[#]\nRecursive DFS:");
dfs_recursive(&root);
+ println!();
- println!("Stack DFS:");
+ println!("[#]\nRecursive Postorder DFS:");
+ dfs_recursive_postorder(&root);
+ println!();
+
+ println!("[#]\nStack-based DFS:");
dfs_stack(&root);
+ println!();
- println!("Queue BFS:");
+ println!("[#]\nQueue-based BFS:");
bfs_queue(&root);
+ println!();
- println!("Recursive post-order DFS:");
- dfs_recursive_postorder(&root);
-
- println!("Recursive in-order DFS BTree:");
+ println!("[#]\nRecursive Inorder DFS for Binary Tree:");
let root_binary = create_tree(3, 2);
dfs_recursive_inorder_btree(&root_binary);
+ println!();
}
diff --git a/contents/tree_traversal/code/smalltalk/tree_traversal.st b/contents/tree_traversal/code/smalltalk/tree_traversal.st
new file mode 100644
index 000000000..411e5ff45
--- /dev/null
+++ b/contents/tree_traversal/code/smalltalk/tree_traversal.st
@@ -0,0 +1,81 @@
+Object subclass: #Node
+ instanceVariableNames: 'children data'
+ classVariableNames: ''
+ package: ''
+
+Node>>children
+ "Children getter."
+ ^ children
+
+Node>>children: newChildren
+ "Children setter."
+ children := newChildren.
+
+Node>>data
+ "Data getter"
+ ^ data
+
+Node>>data: newData
+ "Data setter"
+ data := newData.
+
+Node>>dfsRecursive
+ "Recursive depth first search."
+ Transcript show: data; cr.
+ children collect: [ :child | child dfsRecursive ]
+
+Node>>dfsRecursivePostOrder
+ "Recursive depth first search (post-order)."
+ children collect: [ :child | (child dfsRecursivePostOrder)].
+ Transcript show: data; cr.
+
+Node>>dfsInOrderBinaryTree
+ "Recursive depth first search on a binary tree in order."
+ children size > 2 ifTrue: [
+ Transcript show: 'This is not a binary tree!'; cr.
+ ^self.
+ ].
+ children size = 2 ifTrue: [
+ (children at: 1) dfsInOrderBinaryTree: value.
+ ].
+ Transcript show: data; cr.
+ children size >= 1 ifTrue: [
+ (children at: 0) dfsInOrderBinaryTree: value.
+ ].
+ ^self.
+
+Node>>dfsStack
+ "Depth-first search with a stack."
+ | stack top |
+ stack := Stack new.
+ stack push: self.
+ [stack size > 0] whileTrue: [
+ top := stack pop.
+ Transcript show: (top data); cr.
+ top children reverseDo: [ :child |
+ stack push: child.
+ ].
+ ].
+
+Node>>bfs
+ "A breadth-first tree search using queues."
+ | queue current |
+ queue := LinkedList with: self.
+ [ queue size > 0 ] whileTrue: [
+ current := queue first.
+ queue removeFirst.
+ Transcript show: (current data); cr.
+ current children collect: [ :child |
+ queue addLast: child
+ ].
+ ].
+
+| test |
+test := Node new: 1 children: { Node new: 2.
+ Node new: 3 children: { Node new: 4.
+ Node new: 5. } }.
+test dfsRecursive.
+test dfsRecursivePostorder.
+test dfsInOrderBinaryTree.
+test dfsStack.
+test bfs.
diff --git a/contents/tree_traversal/code/swift/tree.swift b/contents/tree_traversal/code/swift/tree.swift
index e286c8fb0..ae64315ec 100644
--- a/contents/tree_traversal/code/swift/tree.swift
+++ b/contents/tree_traversal/code/swift/tree.swift
@@ -22,7 +22,7 @@ func createTree(numRows: Int, numChildren: Int) -> Node {
}
func dfsRecursive(node: Node) {
- print(node.value)
+ print(node.value, terminator:" ")
for child in node.children! {
dfsRecursive(node: child)
@@ -34,19 +34,19 @@ func dfsRecursivePostOrder(node: Node) {
dfsRecursivePostOrder(node: child)
}
- print(node.value)
+ print(node.value, terminator:" ")
}
func dfsRecursiveInOrderBinary(node: Node) {
if node.children?.count == 2 {
dfsRecursiveInOrderBinary(node: node.children![0])
- print(node.value)
+ print(node.value, terminator:" ")
dfsRecursiveInOrderBinary(node: node.children![1])
} else if node.children?.count == 1 {
dfsRecursiveInOrderBinary(node: node.children![0])
- print(node.value)
+ print(node.value, terminator:" ")
} else if node.children?.count == 0 {
- print(node.value)
+ print(node.value, terminator:" ")
} else {
print("Not a binary tree!")
}
@@ -58,7 +58,7 @@ func dfsStack(node: Node) {
while stack.count > 0 {
temp = stack.popLast()!
- print(temp.value)
+ print(temp.value, terminator:" ")
for child in temp.children! {
stack.append(child)
@@ -72,7 +72,7 @@ func bfsQueue(node: Node) {
while queue.count > 0 {
temp = queue.remove(at: 0)
- print(temp.value)
+ print(temp.value, terminator:" ")
for child in temp.children! {
queue.append(child)
@@ -81,24 +81,29 @@ func bfsQueue(node: Node) {
}
func main() {
- let root = createTree(numRows: 3, numChildren: 3)
+ let root = createTree(numRows: 2, numChildren: 3)
- print("Using recursive DFS:")
+ print("[#]\nRecursive DFS:")
dfsRecursive(node: root)
+ print()
- print("Using recursive postorder DFS:")
+ print("[#]\nRecursive Postorder DFS:")
dfsRecursivePostOrder(node: root)
+ print()
- print("Using stack-based DFS:")
+ print("[#]\nStack-based DFS:")
dfsStack(node: root)
+ print()
- print("Using queue-based BFS:")
+ print("[#]\nQueue-based BFS:")
bfsQueue(node: root)
+ print()
let rootBinary = createTree(numRows: 3, numChildren: 2)
- print("Using In-order DFS:")
+ print("[#]\nRecursive Inorder DFS for Binary Tree:")
dfsRecursiveInOrderBinary(node: rootBinary)
+ print()
}
main()
diff --git a/contents/tree_traversal/tree_traversal.md b/contents/tree_traversal/tree_traversal.md
index 3cc5a2fbb..b0e829b1b 100644
--- a/contents/tree_traversal/tree_traversal.md
+++ b/contents/tree_traversal/tree_traversal.md
@@ -6,18 +6,18 @@ Trees are naturally recursive data structures, and because of this, we cannot ac
{% sample lang="jl" %}
[import:3-7, lang:"julia"](code/julia/Tree.jl)
{% sample lang="cpp" %}
-[import:12-15, lang:"cpp"](code/c++/tree_example.cpp)
+[import:12-15, lang:"cpp"](code/cpp/tree_example.cpp)
{% sample lang="cs" %}
-[import:7-11, lang:"csharp"](code/csharp/Tree.cs)
+[import:6-10, lang:"csharp"](code/csharp/Tree.cs)
{% sample lang="c" %}
[import:7-11, lang:"c"](code/c/tree_traversal.c)
{% sample lang="java" %}
-[import:110-126, lang:"java"](code/java/Tree.java)
+[import:112-128, lang:"java"](code/java/Tree.java)
{% sample lang="js" %}
[import:1-10, lang:"javascript"](code/javascript/tree.js)
As a note, a `node` struct is not necessary in javascript, so this is an example of how a tree might be constructed.
{% sample lang="py" %}
-[import:1-4, lang:"python"](code/python/Tree_example.py)
+[import:1-4, lang:"python"](code/python/tree_traversal.py)
{% sample lang="scratch" %}
@@ -32,8 +32,10 @@ As a note, a `node` struct is not necessary in javascript, so this is an example
[import:4-37, lang:"php"](code/php/tree_traversal.php)
{% sample lang="crystal" %}
[import:1-5, lang:"crystal"](code/crystal/tree-traversal.cr)
+{% sample lang="st" %}
+[import:1-20, lang:"smalltalk"](code/smalltalk/tree_traversal.st)
{% sample lang="go" %}
-[import:5-8, lang:"go"](code/golang/treetraversal.go)
+[import:5-8, lang:"go"](code/go/treetraversal.go)
{% sample lang="asm-x64" %}
[import:24-27, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
{% sample lang="emojic" %}
@@ -52,17 +54,17 @@ Because of this, the most straightforward way to traverse the tree might be recu
{% sample lang="jl" %}
[import:9-16, lang:"julia"](code/julia/Tree.jl)
{% sample lang="cpp" %}
-[import:17-24, lang:"cpp"](code/c++/tree_example.cpp)
+[import:17-24, lang:"cpp"](code/cpp/tree_example.cpp)
{% sample lang="cs" %}
-[import:34-45, lang:"csharp"](code/csharp/Tree.cs)
+[import:33-44, lang:"csharp"](code/csharp/Tree.cs)
{% sample lang="c" %}
[import:37-45, lang:"c"](code/c/tree_traversal.c)
{% sample lang="java" %}
-[import:21-27, lang:"java"](code/java/Tree.java)
+[import:20-26, lang:"java"](code/java/Tree.java)
{% sample lang="js" %}
-[import:12-15, lang:"javascript"](code/javascript/tree.js)
+[import:12-19, lang:"javascript"](code/javascript/tree.js)
{% sample lang="py" %}
-[import:18-23, lang:"python"](code/python/Tree_example.py)
+[import:17-22, lang:"python"](code/python/tree_traversal.py)
{% sample lang="scratch" %}
@@ -70,15 +72,17 @@ Because of this, the most straightforward way to traverse the tree might be recu
{% sample lang="rs" %}
[import:9-15 lang:"rust"](code/rust/tree.rs)
{% sample lang="hs" %}
-[import:6-7, lang:"haskell"](code/haskell/TreeTraversal.hs)
+[import:7-8, lang:"haskell"](code/haskell/TreeTraversal.hs)
{% sample lang="swift" %}
[import:24-30, lang:"swift"](code/swift/tree.swift)
{% sample lang="php" %}
-[import:41-49, lang:"php"](code/php/tree_traversal.php)
+[import:41-47, lang:"php"](code/php/tree_traversal.php)
{% sample lang="crystal" %}
[import:7-10, lang:"crystal"](code/crystal/tree-traversal.cr)
+{% sample lang="st" %}
+[import:22-27, lang:"smalltalk"](code/smalltalk/tree_traversal.st)
{% sample lang="go" %}
-[import:10-15, lang:"go"](code/golang/treetraversal.go)
+[import:10-15, lang:"go"](code/go/treetraversal.go)
{% sample lang="asm-x64" %}
[import:290-314, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
{% sample lang="emojic" %}
@@ -106,17 +110,17 @@ Now, in this case the first element searched through is still the root of the tr
{% sample lang="jl" %}
[import:18-26, lang:"julia"](code/julia/Tree.jl)
{% sample lang="cpp" %}
-[import:26-31, lang:"cpp"](code/c++/tree_example.cpp)
+[import:26-31, lang:"cpp"](code/cpp/tree_example.cpp)
{% sample lang="cs" %}
-[import:47-58, lang:"csharp"](code/csharp/Tree.cs)
+[import:46-57, lang:"csharp"](code/csharp/Tree.cs)
{% sample lang="c" %}
[import:47-53, lang:"c"](code/c/tree_traversal.c)
{% sample lang="java" %}
-[import:34-41, lang:"java"](code/java/Tree.java)
+[import:33-40, lang:"java"](code/java/Tree.java)
{% sample lang="js" %}
-[import:17-20, lang:"javascript"](code/javascript/tree.js)
+[import:21-28, lang:"javascript"](code/javascript/tree.js)
{% sample lang="py" %}
-[import:26-31, lang:"python"](code/python/Tree_example.py)
+[import:25-30, lang:"python"](code/python/tree_traversal.py)
{% sample lang="scratch" %}
@@ -124,15 +128,17 @@ Now, in this case the first element searched through is still the root of the tr
{% sample lang="rs" %}
[import:17-24, lang:"rust"](code/rust/tree.rs)
{% sample lang="hs" %}
-[import:9-10, lang:"haskell"](code/haskell/TreeTraversal.hs)
+[import:10-11, lang:"haskell"](code/haskell/TreeTraversal.hs)
{% sample lang="swift" %}
[import:32-38, lang:"swift"](code/swift/tree.swift)
{% sample lang="php" %}
-[import:51-57, lang:"php"](code/php/tree_traversal.php)
+[import:49-55, lang:"php"](code/php/tree_traversal.php)
{% sample lang="crystal" %}
[import:12-15, lang:"crystal"](code/crystal/tree-traversal.cr)
+{% sample lang="st" %}
+[import:29-34, lang:"smalltalk"](code/smalltalk/tree_traversal.st)
{% sample lang="go" %}
-[import:17-22, lang:"go"](code/golang/treetraversal.go)
+[import:17-22, lang:"go"](code/go/treetraversal.go)
{% sample lang="asm-x64" %}
[import:316-344, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
{% sample lang="emojic" %}
@@ -142,7 +148,7 @@ Now, in this case the first element searched through is still the root of the tr
{% sample lang="m" %}
[import:47-62, lang:"matlab"](code/matlab/tree.m)
{% sample lang="coco" %}
-[import:11-15, lang:="coconut"](codo/coconut/tree_traversal.coco)
+[import:11-15, lang:="coconut"](code/coconut/tree_traversal.coco)
{% endmethod %}
@@ -155,17 +161,17 @@ In this case, the first node visited is at the bottom of the tree and moves up t
{% sample lang="jl" %}
[import:28-43, lang:"julia"](code/julia/Tree.jl)
{% sample lang="cpp" %}
-[import:34-52 lang:"cpp"](code/c++/tree_example.cpp)
+[import:34-52 lang:"cpp"](code/cpp/tree_example.cpp)
{% sample lang="cs" %}
-[import:60-79, lang:"csharp"](code/csharp/Tree.cs)
+[import:59-83, lang:"csharp"](code/csharp/Tree.cs)
{% sample lang="c" %}
[import:55-73, lang:"c"](code/c/tree_traversal.c)
{% sample lang="java" %}
-[import:48-62, lang:"java"](code/java/Tree.java)
+[import:47-64, lang:"java"](code/java/Tree.java)
{% sample lang="js" %}
-[import:22-34, lang:"javascript"](code/javascript/tree.js)
+[import:30-51, lang:"javascript"](code/javascript/tree.js)
{% sample lang="py" %}
-[import:34-46, lang:"python"](code/python/Tree_example.py)
+[import:34-45, lang:"python"](code/python/tree_traversal.py)
{% sample lang="scratch" %}
@@ -173,15 +179,17 @@ In this case, the first node visited is at the bottom of the tree and moves up t
{% sample lang="rs" %}
[import:25-40, lang:"rust"](code/rust/tree.rs)
{% sample lang="hs" %}
-[import:12-16, lang:"haskell"](code/haskell/TreeTraversal.hs)
+[import:13-17, lang:"haskell"](code/haskell/TreeTraversal.hs)
{% sample lang="swift" %}
[import:40-53, lang:"swift"](code/swift/tree.swift)
{% sample lang="php" %}
-[import:59-78, lang:"php"](code/php/tree_traversal.php)
+[import:57-76, lang:"php"](code/php/tree_traversal.php)
{% sample lang="crystal" %}
[import:17-31, lang:"crystal"](code/crystal/tree-traversal.cr)
+{% sample lang="st" %}
+[import:36-49, lang:"smalltalk"](code/smalltalk/tree_traversal.st)
{% sample lang="go" %}
-[import:24-38, lang:"go"](code/golang/treetraversal.go)
+[import:24-38, lang:"go"](code/go/treetraversal.go)
{% sample lang="asm-x64" %}
[import:346-396, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
{% sample lang="emojic" %}
@@ -213,17 +221,17 @@ In code, it looks like this:
{% sample lang="jl" %}
[import:45-56, lang:"julia"](code/julia/Tree.jl)
{% sample lang="cpp" %}
-[import:55-70, lang:"cpp"](code/c++/tree_example.cpp)
+[import:55-70, lang:"cpp"](code/cpp/tree_example.cpp)
{% sample lang="cs" %}
-[import:81-94, lang:"csharp"](code/csharp/Tree.cs)
+[import:85-98, lang:"csharp"](code/csharp/Tree.cs)
{% sample lang="c" %}
[import:75-93, lang:"c"](code/c/tree_traversal.c)
{% sample lang="java" %}
-[import:65-79, lang:"java"](code/java/Tree.java)
+[import:67-81, lang:"java"](code/java/Tree.java)
{% sample lang="js" %}
-[import:36-43, lang:"javascript"](code/javascript/tree.js)
+[import:53-60, lang:"javascript"](code/javascript/tree.js)
{% sample lang="py" %}
-[import:49-60, lang:"python"](code/python/Tree_example.py)
+[import:48-53, lang:"python"](code/python/tree_traversal.py)
{% sample lang="scratch" %}
@@ -282,15 +292,17 @@ And this is exactly what Breadth-First Search (BFS) does! On top of that, it can
{% sample lang="rs" %}
[import:50-58, lang:"rust"](code/rust/tree.rs)
{% sample lang="hs" %}
-[import:24-28, lang:"haskell"](code/haskell/TreeTraversal.hs)
+[import:25-29, lang:"haskell"](code/haskell/TreeTraversal.hs)
{% sample lang="swift" %}
[import:69-81, lang:"swift"](code/swift/tree.swift)
{% sample lang="php" %}
-[import:93-104, lang:"php"](code/php/tree_traversal.php)
+[import:91-102, lang:"php"](code/php/tree_traversal.php)
{% sample lang="crystal" %}
[import:43-51, lang:"crystal"](code/crystal/tree-traversal.cr)
+{% sample lang="st" %}
+[import:60-71, lang:"smalltalk"](code/smalltalk/tree_traversal.st)
{% sample lang="go" %}
-[import:51-60, lang:"go"](code/golang/treetraversal.go)
+[import:51-60, lang:"go"](code/go/treetraversal.go)
{% sample lang="asm-x64" %}
[import:447-498, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
{% sample lang="emojic" %}
@@ -308,7 +320,7 @@ And this is exactly what Breadth-First Search (BFS) does! On top of that, it can
Here is a video describing tree traversal:
-
+
## Example Code
@@ -316,7 +328,7 @@ Here is a video describing tree traversal:
{% sample lang="jl" %}
[import, lang:"julia"](code/julia/Tree.jl)
{% sample lang="cpp" %}
-[import, lang:"cpp"](code/c++/tree_example.cpp)
+[import, lang:"cpp"](code/cpp/tree_example.cpp)
{% sample lang="cs" %}
##### Tree.cs
[import, lang:"csharp"](code/csharp/Tree.cs)
@@ -330,12 +342,10 @@ Here is a video describing tree traversal:
{% sample lang="java" %}
##### Tree.java
[import, lang:"java"](code/java/Tree.java)
-##### MainClass.java
-[import, lang:"java"](code/java/MainClass.java)
{% sample lang="js" %}
[import, lang:"javascript"](code/javascript/tree.js)
{% sample lang="py" %}
-[import, lang:"python"](code/python/Tree_example.py)
+[import, lang:"python"](code/python/tree_traversal.py)
{% sample lang="scratch" %}
The code snippets were taken from this [Scratch project](https://scratch.mit.edu/projects/174017753/)
@@ -353,8 +363,10 @@ The code snippets were taken from this [Scratch project](https://scratch.mit.edu
[import, lang:"php"](code/php/tree_traversal.php)
{% sample lang="crystal" %}
[import, lang:"crystal"](code/crystal/tree-traversal.cr)
+{% sample lang="st" %}
+[import, lang:"smalltalk"](code/smalltalk/tree_traversal.st)
{% sample lang="go" %}
-[import, lang:"go"](code/golang/treetraversal.go)
+[import, lang:"go"](code/go/treetraversal.go)
{% sample lang="asm-x64" %}
[import, lang:"asm-x64"](code/asm-x64/tree_traversal.s)
{% sample lang="emojic" %}
@@ -376,7 +388,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/contents/verlet_integration/code/asm-x64/verlet.s b/contents/verlet_integration/code/asm-x64/verlet.s
index ed2521f78..87de6cb7a 100644
--- a/contents/verlet_integration/code/asm-x64/verlet.s
+++ b/contents/verlet_integration/code/asm-x64/verlet.s
@@ -4,9 +4,9 @@
zero: .double 0.0
two: .double 2.0
half: .double 0.5
- verlet_fmt: .string "Time for Verlet integration is: %lf\n"
- stormer_fmt: .string "Time and Velocity for Stormer Verlet Integration is: %lf, %lf\n"
- velocity_fmt: .string "Time and Velocity for Velocity Verlet Integration is: %lf, %lf\n"
+ verlet_fmt: .string "[#]\nTime for Verlet integration is:\n%lf\n"
+ stormer_fmt: .string "[#]\nTime for Stormer Verlet Integration is:\n%lf\n[#]\nVelocity for Stormer Verlet Integration is:\n%lf\n"
+ velocity_fmt: .string "[#]\nTime for Velocity Verlet Integration is:\n%lf\n[#]\nVelocity for Velocity Verlet Integration is:\n%lf\n"
pos: .double 5.0
acc: .double -10.0
dt: .double 0.01
@@ -124,5 +124,6 @@ main:
mov rax, 1
call printf
pop rbp
+ xor rax, rax # Set exit code to 0
ret
diff --git a/contents/verlet_integration/code/c/verlet.c b/contents/verlet_integration/code/c/verlet.c
index c56a3cc5b..a5febb92c 100644
--- a/contents/verlet_integration/code/c/verlet.c
+++ b/contents/verlet_integration/code/c/verlet.c
@@ -46,16 +46,20 @@ int main() {
double time, vel;
verlet(&time, 5.0, -10, 0.01);
- printf("Time for Verlet integration is: %lf\n",
- time);
+ printf("[#]\nTime for Verlet integration is:\n");
+ printf("%lf\n", time);
stormer_verlet(&time, &vel, 5.0, -10, 0.01);
- printf("Time and velocity for Stormer Verlet integration is: %lf, %lf\n",
- time, vel);
+ printf("[#]\nTime for Stormer Verlet integration is:\n");
+ printf("%lf\n", time);
+ printf("[#]\nVelocity for Stormer Verlet integration is:\n");
+ printf("%lf\n", vel);
velocity_verlet(&time, &vel, 5.0, -10, 0.01);
- printf("Time and velocity for velocity Verlet integration is: %lf, %lf\n",
- time, vel);
+ printf("[#]\nTime for velocity Verlet integration is:\n");
+ printf("%lf\n", time);
+ printf("[#]\nVelocity for Stormer Verlet integration is:\n");
+ printf("%lf\n", vel);
return 0;
}
diff --git a/contents/verlet_integration/code/clisp/verlet.lisp b/contents/verlet_integration/code/clisp/verlet.lisp
index 726b1f1c6..f8d4c6c14 100644
--- a/contents/verlet_integration/code/clisp/verlet.lisp
+++ b/contents/verlet_integration/code/clisp/verlet.lisp
@@ -34,12 +34,17 @@
while (> p 0)
finally (return (list time vel))))
-(format T "Time for Verlet integration: ~d~%" (verlet 5 -10 0.01))
+(format T "[#]~%Time for Verlet integration:~%")
+(format T "~d~%" (verlet 5 -10 0.01))
(defvar stormer-verlet-result (stormer-verlet 5 -10 0.01))
-(format T "Time for Stormer Verlet integration is: ~d~%" (first stormer-verlet-result))
-(format T "Velocity for Stormer Verlet integration is: ~d~%" (second stormer-verlet-result))
+(format T "[#]~%Time for Stormer Verlet integration is:~%")
+(format T "~d~%" (first stormer-verlet-result))
+(format T "[#]~%Velocity for Stormer Verlet integration is:~%")
+(format T "~d~%" (second stormer-verlet-result))
(defvar velocity-verlet-result (velocity-verlet 5 -10 0.01))
-(format T "Time for velocity Verlet integration is: ~d~%" (first velocity-verlet-result))
-(format T "Velocity for velocity Verlet integration is: ~d~%" (second velocity-verlet-result))
+(format T "[#]~%Time for velocity Verlet integration is:~%")
+(format T "~d~%" (first velocity-verlet-result))
+(format T "[#]~%Velocity for velocity Verlet integration is:~%")
+(format T "~d~%" (second velocity-verlet-result))
\ No newline at end of file
diff --git a/contents/verlet_integration/code/c++/verlet.cpp b/contents/verlet_integration/code/cpp/verlet.cpp
similarity index 83%
rename from contents/verlet_integration/code/c++/verlet.cpp
rename to contents/verlet_integration/code/cpp/verlet.cpp
index 473f92ee9..ccceb0ff3 100644
--- a/contents/verlet_integration/code/c++/verlet.cpp
+++ b/contents/verlet_integration/code/cpp/verlet.cpp
@@ -64,19 +64,19 @@ int main() {
// each of these functions.
double time = verlet(5.0, -10, 0.01);
- std::cout << "Time for Verlet integration is: " \
+ std::cout << "[#]\nTime for Verlet integration is:\n" \
<< time << std::endl;
timestep timestep_sv = stormer_verlet(5.0, -10, 0.01);
- std::cout << "Time for Stormer Verlet integration is: " \
+ std::cout << "[#]\nTime for Stormer Verlet integration is:\n" \
<< timestep_sv.time << std::endl;
- std::cout << "Velocity for Stormer Verlet integration is: " \
+ std::cout << "[#]\nVelocity for Stormer Verlet integration is:\n" \
<< timestep_sv.vel << std::endl;
timestep timestep_vv = velocity_verlet(5.0, -10, 0.01);
- std::cout << "Time for velocity Verlet integration is: " \
+ std::cout << "[#]\nTime for velocity Verlet integration is:\n" \
<< timestep_vv.time << std::endl;
- std::cout << "Velocity for velocity Verlet integration is: " \
+ std::cout << "[#]\nVelocity for velocity Verlet integration is:\n" \
<< timestep_vv.vel << std::endl;
return 0;
diff --git a/contents/verlet_integration/code/fortran/verlet.f90 b/contents/verlet_integration/code/fortran/verlet.f90
index 417fc77b7..3fda9f950 100644
--- a/contents/verlet_integration/code/fortran/verlet.f90
+++ b/contents/verlet_integration/code/fortran/verlet.f90
@@ -91,18 +91,32 @@ SUBROUTINE velocity_verlet(pos, acc, dt, time, vel)
! Verlet
CALL verlet(pos, acc, dt, time)
- WRITE(*,*) 'Time for Verlet integration: ', time
+ WRITE(*,*) '[#]'
+ WRITE(*,*) 'Time for Verlet integration:'
+ WRITE(*,*) time
! stormer Verlet
pos = 5d0
CALL stormer_verlet(pos, acc, dt, time, vel)
- WRITE(*,*) 'Time for Stormer-Verlet integration: ', time
+ WRITE(*,*) '[#]'
+ WRITE(*,*) 'Time for Stormer Verlet integration:'
+ WRITE(*,*) time
+ WRITE(*,*) '[#]'
+ WRITE(*,*) 'Velocity for Stormer Verlet integration:'
+ WRITE(*,*) vel
+
+
! Velocity Verlet
pos = 5d0
CALL velocity_verlet(pos, acc, dt, time, vel)
- WRITE(*,*) 'Time for Velocity-Verlet integration: ', time
-
+ WRITE(*,*) '[#]'
+ WRITE(*,*) 'Time for velocity Verlet integration:'
+ WRITE(*,*) time
+ WRITE(*,*) '[#]'
+ WRITE(*,*) 'Velocity for velocity Verlet integration:'
+ WRITE(*,*) vel
+
END PROGRAM verlet_integration
diff --git a/contents/verlet_integration/code/golang/verlet.go b/contents/verlet_integration/code/go/verlet.go
similarity index 65%
rename from contents/verlet_integration/code/golang/verlet.go
rename to contents/verlet_integration/code/go/verlet.go
index 778521da4..d4fc956a9 100644
--- a/contents/verlet_integration/code/golang/verlet.go
+++ b/contents/verlet_integration/code/go/verlet.go
@@ -43,18 +43,18 @@ func velocityVerlet(pos, acc, dt float64) (time, vel float64) {
func main() {
time := verlet(5., -10., .01)
- fmt.Println("Verlet")
- fmt.Println("Time:", time)
- fmt.Println()
+ fmt.Println("[#]\nTime for Verlet integration is:")
+ fmt.Println(time)
time, vel := stormerVerlet(5., -10., .01)
- fmt.Println("Stormer-Verlet")
- fmt.Println("Time:", time)
- fmt.Println("Velocity:", vel)
- fmt.Println()
-
+ fmt.Println("[#]\nTime for Stormer Verlet integration is:")
+ fmt.Println(time)
+ fmt.Println("[#]\nVelocity for Stormer Verlet integration is:")
+ fmt.Println(vel)
+
time, vel = velocityVerlet(5., -10., .01)
- fmt.Println("Velocity Verlet")
- fmt.Println("Time:", time)
- fmt.Println("Velocity:", vel)
+ fmt.Println("[#]\nTime for velocity Verlet integration is:")
+ fmt.Println(time)
+ fmt.Println("[#]\nVelocity for velocity Verlet integration is:")
+ fmt.Println(vel)
}
diff --git a/contents/verlet_integration/code/haskell/verlet.hs b/contents/verlet_integration/code/haskell/verlet.hs
index df82004e6..af964d4d7 100644
--- a/contents/verlet_integration/code/haskell/verlet.hs
+++ b/contents/verlet_integration/code/haskell/verlet.hs
@@ -48,7 +48,17 @@ main = do
dt = 0.001
freefall _ = -10
aboveGround (x, _, _, _) = x > 0
- integrate m = last $ takeWhile aboveGround $ trajectory m freefall dt p0
- print $ integrate verlet
- print $ integrate stormerVerlet
- print $ integrate velocityVerlet
+ timeVelocity m =
+ let (_, v, _, t) = last $ takeWhile aboveGround $ trajectory m freefall dt p0
+ in (show t, show v)
+
+ putStrLn "[#]\nTime for Verlet integration is:"
+ putStrLn $ fst $ timeVelocity verlet
+ putStrLn "[#]\nTime for Stormer Verlet integration is:"
+ putStrLn $ fst $ timeVelocity stormerVerlet
+ putStrLn "[#]\nVelocity for Stormer Verlet integration is:"
+ putStrLn $ snd $ timeVelocity stormerVerlet
+ putStrLn "[#]\nTime for velocity Verlet integration is:"
+ putStrLn $ fst $ timeVelocity velocityVerlet
+ putStrLn "[#]\nVelocity for velocity Verlet integration is:"
+ putStrLn $ snd $ timeVelocity velocityVerlet
diff --git a/contents/verlet_integration/code/java/Verlet.java b/contents/verlet_integration/code/java/Verlet.java
index b7494d65f..38283abed 100644
--- a/contents/verlet_integration/code/java/Verlet.java
+++ b/contents/verlet_integration/code/java/Verlet.java
@@ -1,4 +1,16 @@
public class Verlet {
+
+ private static class VerletValues {
+ public double time;
+ public double vel;
+
+ public VerletValues(double time, double vel) {
+ this.time = time;
+ this.vel = vel;
+ }
+ }
+
+
static double verlet(double pos, double acc, double dt) {
// Note that we are using a temp variable for the previous position
@@ -53,14 +65,20 @@ static VerletValues velocity_verlet(double pos, double acc, double dt) {
public static void main(String[] args) {
double verletTime = verlet(5.0, -10, 0.01);
- System.out.println("Time for Verlet integration is: " + verletTime);
+ System.out.println("[#]\nTime for Verlet integration is:");
+ System.out.println(verletTime);
VerletValues stormerVerlet = stormer_verlet(5.0, -10, 0.01);
- System.out.println("Time for Stormer Verlet integration is: " + stormerVerlet.time);
- System.out.println("Velocity for Stormer Verlet integration is: " + stormerVerlet.vel);
+ System.out.println("[#]\nTime for Stormer Verlet integration is:");
+ System.out.println(stormerVerlet.time);
+ System.out.println("[#]\nVelocity for Stormer Verlet integration is:");
+ System.out.println(stormerVerlet.vel);
VerletValues velocityVerlet = velocity_verlet(5.0, -10, 0.01);
- System.out.println("Time for velocity Verlet integration is: " + velocityVerlet.time);
- System.out.println("Velocity for velocity Verlet integration is: " + velocityVerlet.vel);
+ System.out.println("[#]\nTime for velocity Verlet integration is:");
+ System.out.println(velocityVerlet.time);
+ System.out.println("[#]\nVelocity for velocity Verlet integration is:");
+ System.out.println(velocityVerlet.vel);
+
}
}
diff --git a/contents/verlet_integration/code/java/VerletValues.java b/contents/verlet_integration/code/java/VerletValues.java
deleted file mode 100644
index 8dc5ceb84..000000000
--- a/contents/verlet_integration/code/java/VerletValues.java
+++ /dev/null
@@ -1,9 +0,0 @@
-public class VerletValues {
- public double time;
- public double vel;
-
- public VerletValues(double time, double vel) {
- this.time = time;
- this.vel = vel;
- }
-}
diff --git a/contents/verlet_integration/code/javascript/verlet.js b/contents/verlet_integration/code/javascript/verlet.js
index 013a7fa3f..d406482d4 100644
--- a/contents/verlet_integration/code/javascript/verlet.js
+++ b/contents/verlet_integration/code/javascript/verlet.js
@@ -45,12 +45,17 @@ function velocityVerlet(pos, acc, dt) {
}
const time = verlet(5, -10, 0.01);
-console.log(`Time for Verlet integration is: ${time}\n`);
+console.log(`[#]\nTime for Verlet integration is:`);
+console.log(`${time}`);
const stormer = stormerVerlet(5, -10, 0.01);
-console.log(`Time for Stormer Verlet integration is: ${stormer.time}`);
-console.log(`Velocity for Stormer Verlet integration is: ${stormer.vel}\n`);
+console.log(`[#]\nTime for Stormer Verlet integration is:`);
+console.log(`${stormer.time}`);
+console.log(`[#]\nVelocity for Stormer Verlet integration is:`);
+console.log(`${stormer.vel}`);
const velocity = velocityVerlet(5, -10, 0.01);
-console.log(`Time for Velocity Verlet integration is: ${velocity.time}`);
-console.log(`Velocity for Velocity Verlet integration is: ${velocity.vel}\n`);
+console.log(`[#]\nTime for velocity Verlet integration is:`);
+console.log(`${velocity.time}`);
+console.log(`[#]\nVelocity for velocity Verlet integration is:`);
+console.log(`${velocity.vel}`);
diff --git a/contents/verlet_integration/code/julia/verlet.jl b/contents/verlet_integration/code/julia/verlet.jl
index b55b85a9e..2d50e5512 100644
--- a/contents/verlet_integration/code/julia/verlet.jl
+++ b/contents/verlet_integration/code/julia/verlet.jl
@@ -46,15 +46,21 @@ end
function main()
time = verlet(5.0, -10.0, 0.01);
- println("Time for Verlet integration is: $(time)\n")
+ println("[#]\nTime for Verlet integration is:")
+ println("$(time)")
time, vel = stormer_verlet(5.0, -10.0, 0.01);
- println("Time for Stormer Verlet integration is: $(time)")
- println("Velocity for Stormer Verlet integration is: $(vel)\n")
-
+ println("[#]\nTime for Stormer Verlet integration is:")
+ println("$(time)")
+ println("[#]\nVelocity for Stormer Verlet integration is:")
+ println("$(vel)")
+
time, vel = velocity_verlet(5.0, -10.0, 0.01);
- println("Time for velocity Verlet integration is: $(time)")
- println("Velocity for velocity Verlet integration is: $(vel)\n")
+ println("[#]\nTime for velocity Verlet integration is:")
+ println("$(time)")
+ println("[#]\nVelocity for velocity Verlet integration is:")
+ println("$(vel)")
+
end
main()
diff --git a/contents/verlet_integration/code/kotlin/verlet.kt b/contents/verlet_integration/code/kotlin/verlet.kt
index c2d41b3ff..3b365451c 100644
--- a/contents/verlet_integration/code/kotlin/verlet.kt
+++ b/contents/verlet_integration/code/kotlin/verlet.kt
@@ -43,13 +43,18 @@ fun velocityVerlet(_pos: Double, acc: Double, dt: Double): VerletValues {
fun main(args: Array) {
val verletTime = verlet(5.0, -10.0, 0.01)
- println("Time for Verlet integration is: $verletTime")
+ println("[#]\nTime for Verlet integration is:")
+ println("$verletTime")
val stormerVerlet = stormerVerlet(5.0, -10.0, 0.01)
- println("Time for Stormer Verlet integration is: $stormerVerlet.time")
- println("Velocity for Stormer Verlet integration is: $stormerVerlet.vel")
+ println("[#]\nTime for Stormer Verlet integration is:")
+ println("${stormerVerlet.time}")
+ println("[#]\nVelocity for Stormer Verlet integration is:")
+ println("${stormerVerlet.vel}")
val velocityVerlet = velocityVerlet(5.0, -10.0, 0.01)
- println("Time for Velocity Verlet integration is: $velocityVerlet.time")
- println("Velocity for Velocity Verlet integration is: $velocityVerlet.vel")
+ println("[#]\nTime for Velocity Verlet integration is:")
+ println("${velocityVerlet.time}")
+ println("[#]\nVelocity for Velocity Verlet integration is:")
+ println("${velocityVerlet.vel}")
}
diff --git a/contents/verlet_integration/code/nim/verlet.nim b/contents/verlet_integration/code/nim/verlet.nim
index d88a2e586..ff454b7ee 100644
--- a/contents/verlet_integration/code/nim/verlet.nim
+++ b/contents/verlet_integration/code/nim/verlet.nim
@@ -46,12 +46,17 @@ func velocityVerlet(pos_in, acc, dt: float): (float, float) =
when isMainModule:
let timeV = verlet(5.0, -10.0, 0.01)
- echo "Time for Verlet integration is: ", timeV
+ echo "[#]\nTime for Verlet integration is:"
+ echo timeV
let (timeSV, velSV) = stormerVerlet(5.0, -10.0, 0.01)
- echo "Time for Stormer Verlet integration is: ", timeSV
- echo "Velocity for Stormer Verlet integration is: ", velSV
+ echo "[#]\nTime for Stormer Verlet integration is:"
+ echo timeSV
+ echo "[#]\nVelocity for Stormer Verlet integration is:"
+ echo velSV
let (timeVV, velVV) = velocityVerlet(5.0, -10.0, 0.01)
- echo "Time for velocity Verlet integration is: ", timeVV
- echo "Velocity for velocity Verlet integration is: ", velVV
+ echo "[#]\nTime for velocity Verlet integration is:"
+ echo timeVV
+ echo "[#]\nVelocity for velocity Verlet integration is:"
+ echo velVV
diff --git a/contents/verlet_integration/code/python/verlet.py b/contents/verlet_integration/code/python/verlet.py
index c921d1954..063e19666 100644
--- a/contents/verlet_integration/code/python/verlet.py
+++ b/contents/verlet_integration/code/python/verlet.py
@@ -35,21 +35,21 @@ def velocity_verlet(pos, acc, dt):
def main():
time = verlet(5, -10, 0.01)
- print("Verlet")
- print("Time: {:.10f}".format(time))
- print()
+ print("[#]\nTime for Verlet integration is:")
+ print("{:.10f}".format(time))
time, vel = stormer_verlet(5, -10, 0.01)
- print("Stormer-Verlet")
- print("Time: {:.10f}".format(time))
- print("Velocity: {:.10f}".format(vel))
- print()
+ print("[#]\nTime for Stormer Verlet integration is:")
+ print("{:.10f}".format(time))
+ print("[#]\nVelocity for Stormer Verlet integration is:")
+ print("{:.10f}".format(vel))
time, vel = velocity_verlet(5, -10, 0.01)
- print("Velocity Verlet")
- print("Time: {:.10f}".format(time))
- print("Velocity: {:.10f}".format(vel))
- print()
+ print("[#]\nTime for velocity Verlet integration is:")
+ print("{:.10f}".format(time))
+ print("[#]\nVelocity for velocity Verlet integration is:")
+ print("{:.10f}".format(vel))
+
if __name__ == '__main__':
main()
diff --git a/contents/verlet_integration/code/ruby/verlet.rb b/contents/verlet_integration/code/ruby/verlet.rb
index 10246c6b7..d11243568 100644
--- a/contents/verlet_integration/code/ruby/verlet.rb
+++ b/contents/verlet_integration/code/ruby/verlet.rb
@@ -27,7 +27,7 @@ def stormer_verlet(pos, acc, dt)
vel += acc*dt
end
- return time
+ return time, vel
end
@@ -41,10 +41,21 @@ def velocity_verlet(pos, acc, dt)
vel += acc*dt
end
- return time
+ return time, vel
end
+puts "[#]\nTime for Verlet integration is:"
p verlet(5.0, -10, 0.01)
-p stormer_verlet(5.0, -10, 0.01)
-p velocity_verlet(5.0, -10, 0.01)
+
+time, vel = stormer_verlet(5.0, -10, 0.01)
+puts "[#]\nTime for Stormer Verlet integration is:"
+p time
+puts "[#]\nVelocity for Stormer Verlet integration is:"
+p vel
+
+time, vel = velocity_verlet(5.0, -10, 0.01)
+puts "[#]\nTime for velocity Verlet integration is:"
+p time
+puts "[#]\nVelocity for velocity Verlet integration is:"
+p vel
diff --git a/contents/verlet_integration/code/rust/verlet.rs b/contents/verlet_integration/code/rust/verlet.rs
index 490994da2..8901a3790 100644
--- a/contents/verlet_integration/code/rust/verlet.rs
+++ b/contents/verlet_integration/code/rust/verlet.rs
@@ -49,13 +49,16 @@ fn main() {
let (time_sv, vel_sv) = stormer_verlet(5.0, -10.0, 0.01);
let (time_vv, vel_vv) = velocity_verlet(5.0, -10.0, 0.01);
- println!("Time for original Verlet integration: {}", time_v);
- println!(
- "Time and velocity for Stormer Verlet integration: {}, {}",
- time_sv, vel_sv
- );
- println!(
- "Time and velocity for velocity Verlet integration: {}, {}",
- time_vv, vel_vv
- );
+ println!("[#]\nTime for Verlet integration is:");
+ println!("{}", time_v);
+
+ println!("[#]\nTime for Stormer Verlet integration is:");
+ println!("{}", time_sv);
+ println!("[#]\nVelocity for Stormer Verlet integration is:");
+ println!("{}", vel_sv);
+
+ println!("[#]\nTime for velocity Verlet integration is:");
+ println!("{}", time_vv);
+ println!("[#]\nVelocity for velocity Verlet integration is:");
+ println!("{}", vel_vv);
}
diff --git a/contents/verlet_integration/code/swift/verlet.swift b/contents/verlet_integration/code/swift/verlet.swift
index a241660a9..f7d1973bc 100644
--- a/contents/verlet_integration/code/swift/verlet.swift
+++ b/contents/verlet_integration/code/swift/verlet.swift
@@ -50,15 +50,20 @@ func velocityVerlet(pos: Double, acc: Double, dt: Double) -> (time: Double, vel:
func main() {
let verletTime = verlet(pos: 5.0, acc: -10.0, dt: 0.01)
- print("Time for Verlet integration is: \(verletTime)")
+ print("[#]\nTime for Verlet integration is:")
+ print("\(verletTime)")
let stormer = stormerVerlet(pos: 5.0, acc: -10.0, dt: 0.01);
- print("Time for Stormer Verlet integration is: \(stormer.time)")
- print("Velocity for Stormer Verlet integration is: \(stormer.vel)")
+ print("[#]\nTime for Stormer Verlet integration is:")
+ print("\(stormer.time)")
+ print("[#]\nVelocity for Stormer Verlet integration is:")
+ print("\(stormer.vel)")
let velVerlet = velocityVerlet(pos: 5.0, acc: -10, dt: 0.01)
- print("Time for velocity Verlet integration is: \(velVerlet.time)")
- print("Velocity for velocity Verlet integration is: \(velVerlet.vel)")
+ print("[#]\nTime for velocity Verlet integration is:")
+ print("\(velVerlet.time)")
+ print("[#]\nVelocity for velocity Verlet integration is:")
+ print("\(velVerlet.vel)")
}
main()
diff --git a/contents/verlet_integration/verlet_integration.md b/contents/verlet_integration/verlet_integration.md
index 06fe319c6..ad75814d4 100644
--- a/contents/verlet_integration/verlet_integration.md
+++ b/contents/verlet_integration/verlet_integration.md
@@ -33,24 +33,15 @@ Here is what it looks like in code:
{% sample lang="jl" %}
[import:1-13, lang:"julia"](code/julia/verlet.jl)
{% sample lang="cpp" %}
-[import:9-22, lang:"cpp"](code/c++/verlet.cpp)
+[import:9-22, lang:"cpp"](code/cpp/verlet.cpp)
{% sample lang="c" %}
[import:3-14, lang:"c"](code/c/verlet.c)
{% sample lang="java" %}
-[import:2-17, lang:"java"](code/java/Verlet.java)
+[import:14-29, lang:"java"](code/java/Verlet.java)
{% sample lang="py" %}
[import:1-10, lang:"python"](code/python/verlet.py)
{% sample lang="hs" %}
[import:14-21, lang:"haskell"](code/haskell/verlet.hs)
-{% sample lang="scratch" %}
-Unfortunately, this has not yet been implemented in scratch, so here's Julia code:
-[import:1-13, lang:"julia"](code/julia/verlet.jl)
-{% sample lang="m" %}
-Unfortunately, this has not yet been implemented in matlab, so here's Julia code:
-[import:1-13, lang:"julia"](code/julia/verlet.jl)
-{% sample lang="LabVIEW" %}
-Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia code:
-[import:1-13, lang:"julia"](code/julia/verlet.jl)
{% sample lang="js" %}
[import:1-14, lang:"javascript"](code/javascript/verlet.js)
{% sample lang="rs" %}
@@ -62,7 +53,7 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod
{% sample lang="ruby" %}
[import:1-14, lang="ruby"](code/ruby/verlet.rb)
{% sample lang="go" %}
-[import:5-16, lang:"go"](code/golang/verlet.go)
+[import:5-16, lang:"go"](code/go/verlet.go)
{% sample lang="asm-x64" %}
[import:18-42, lang:"asm-x64"](code/asm-x64/verlet.s)
{% sample lang="kotlin" %}
@@ -73,13 +64,24 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod
[import:3-13, lang:"lisp"](code/clisp/verlet.lisp)
{% endmethod %}
-Now, obviously this poses a problem; what if we want to calculate a term that requires velocity, like the kinetic energy, $$\frac{1}{2}mv^2$$? In this case, we certainly cannot get rid of the velocity! Well, we can find the velocity to $$\mathcal{O}(\Delta t^2)$$ accuracy by using the Stormer-Verlet method, which is the same as before, but we calculate velocity like so
+Now, obviously this poses a problem; what if we want to calculate a term that requires velocity, like the kinetic energy, $$\frac{1}{2}mv^2$$? In this case, we certainly cannot get rid of the velocity! Well, we can find the velocity to $$\mathcal{O}(\Delta t^2)$$ accuracy by using the Stormer-Verlet method.
+We have the equations for $$x(t+\Delta t)$$ and $$x(t-\Delta t)$$ above, so let's start there.
+If we subtract the latter from the former, we get the following:
$$
-v(t) = \frac{x(t+\Delta t) - x(t-\Delta t)}{2\Delta t} + \mathcal{O}(\Delta t^2)
+x(t+\Delta t) - x(t - \Delta t) = 2v(t)\Delta t + \frac{1}{3}b(t)\Delta t^3.
$$
-Note that the 2 in the denominator appears because we are going over 2 timesteps. It's essentially solving $$v=\frac{\Delta x}{\Delta t}$$. In addition, we can calculate the velocity of the next timestep like so
+When we solve for $$v(t)$$, we get
+
+$$
+\begin{align}
+v(t) &= \frac{x(t+\Delta t) - x(t-\Delta t)}{2\Delta t} + \frac{b(t) \Delta t^3}{3 \Delta t} \\
+v(t) &= \frac{x(t+\Delta t) - x(t-\Delta t)}{2\Delta t} + \mathcal{O}(\Delta t^2).
+\end{align}
+$$
+
+Note that the 2 in the denominator makes sense because we are going over 2 timesteps. It's essentially solving $$v=\frac{\Delta x}{\Delta t}$$. In addition, we can calculate the velocity of the next timestep like so
$$
v(t+\Delta t) = \frac{x(t+\Delta t) - x(t)}{\Delta t} + \mathcal{O}(\Delta t)
@@ -91,24 +93,15 @@ However, the error for this is $$\mathcal{O}(\Delta t)$$, which is quite poor, b
{% sample lang="jl" %}
[import:15-31, lang:"julia"](code/julia/verlet.jl)
{% sample lang="cpp" %}
-[import:24-41, lang:"cpp"](code/c++/verlet.cpp)
+[import:24-41, lang:"cpp"](code/cpp/verlet.cpp)
{% sample lang="c" %}
[import:16-31, lang:"c"](code/c/verlet.c)
{% sample lang="java" %}
-[import:19-37, lang:"java"](code/java/Verlet.java)
+[import:31-49, lang:"java"](code/java/Verlet.java)
{% sample lang="py" %}
[import:12-23, lang:"python"](code/python/verlet.py)
{% sample lang="hs" %}
[import:23-28, lang:"haskell"](code/haskell/verlet.hs)
-{% sample lang="scratch" %}
-Unfortunately, this has not yet been implemented in scratch, so here's Julia code:
-[import:15-31, lang:"julia"](code/julia/verlet.jl)
-{% sample lang="m" %}
-Unfortunately, this has not yet been implemented in matlab, so here's Julia code:
-[import:15-31, lang:"julia"](code/julia/verlet.jl)
-{% sample lang="LabVIEW" %}
-Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia code:
-[import:15-31, lang:"julia"](code/julia/verlet.jl)
{% sample lang="js" %}
[import:16-32, lang:"javascript"](code/javascript/verlet.js)
{% sample lang="rs" %}
@@ -120,7 +113,7 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod
{% sample lang="ruby" %}
[import:16-32, lang="ruby"](code/ruby/verlet.rb)
{% sample lang="go" %}
-[import:18-30, lang:"go"](code/golang/verlet.go)
+[import:18-30, lang:"go"](code/go/verlet.go)
{% sample lang="asm-x64" %}
[import:44-71, lang:"asm-x64"](code/asm-x64/verlet.s)
{% sample lang="kotlin" %}
@@ -163,24 +156,15 @@ Here is the velocity Verlet method in code:
{% sample lang="jl" %}
[import:33-45, lang:"julia"](code/julia/verlet.jl)
{% sample lang="cpp" %}
-[import:43-54, lang:"cpp"](code/c++/verlet.cpp)
+[import:43-54, lang:"cpp"](code/cpp/verlet.cpp)
{% sample lang="c" %}
[import:33-43, lang:"c"](code/c/verlet.c)
{% sample lang="java" %}
-[import:39-51, lang:"java"](code/java/Verlet.java)
+[import:51-63, lang:"java"](code/java/Verlet.java)
{% sample lang="py" %}
[import:25-34, lang:"python"](code/python/verlet.py)
{% sample lang="hs" %}
[import:30-35, lang:"haskell"](code/haskell/verlet.hs)
-{% sample lang="scratch" %}
-Unfortunately, this has not yet been implemented in scratch, so here's Julia code:
-[import:33-45, lang:"julia"](code/julia/verlet.jl)
-{% sample lang="m" %}
-Unfortunately, this has not yet been implemented in matlab, so here's Julia code:
-[import:33-45, lang:"julia"](code/julia/verlet.jl)
-{% sample lang="LabVIEW" %}
-Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia code:
-[import:33-45, lang:"julia"](code/julia/verlet.jl)
{% sample lang="js" %}
[import:34-45, lang:"javascript"](code/javascript/verlet.js)
{% sample lang="rs" %}
@@ -192,7 +176,7 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod
{% sample lang="ruby" %}
[import:34-46, lang="ruby"](code/ruby/verlet.rb)
{% sample lang="go" %}
-[import:32-42, lang:"go"](code/golang/verlet.go)
+[import:32-42, lang:"go"](code/go/verlet.go)
{% sample lang="asm-x64" %}
[import:73-101, lang:"asm-x64"](code/asm-x64/verlet.s)
{% sample lang="kotlin" %}
@@ -203,14 +187,14 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod
[import:28-35, lang:"lisp"](code/clisp/verlet.lisp)
{% endmethod %}
-Even though this method is more widely used than the simple Verlet method mentioned above, it unforunately has an error term of $$\mathcal{O}(\Delta t^2)$$, which is two orders of magnitude worse. That said, if you want to have a simulaton with many objects that depend on one another --- like a gravity simulation --- the Velocity Verlet algorithm is a handy choice; however, you may have to play further tricks to allow everything to scale appropriately. These types of simulatons are sometimes called *n-body* simulations and one such trick is the Barnes-Hut algorithm, which cuts the complexity of n-body simulations from $$\sim \mathcal{O}(n^2)$$ to $$\sim \mathcal{O}(n\log(n))$$.
+Even though this method is more widely used than the simple Verlet method mentioned above, it unfortunately has an error term of $$\mathcal{O}(\Delta t^2)$$, which is two orders of magnitude worse. That said, if you want to have a simulation with many objects that depend on one another --- like a gravity simulation --- the Velocity Verlet algorithm is a handy choice; however, you may have to play further tricks to allow everything to scale appropriately. These types of simulations are sometimes called *n-body* simulations and one such trick is the Barnes-Hut algorithm, which cuts the complexity of n-body simulations from $$\sim \mathcal{O}(n^2)$$ to $$\sim \mathcal{O}(n\log(n))$$.
## Video Explanation
Here is a video describing Verlet integration:
-
+
## Example Code
@@ -221,29 +205,15 @@ Both of these methods work simply by iterating timestep-by-timestep and can be w
{% sample lang="jl" %}
[import, lang:"julia"](code/julia/verlet.jl)
{% sample lang="cpp" %}
-[import, lang:"cpp"](code/c++/verlet.cpp)
+[import, lang:"cpp"](code/cpp/verlet.cpp)
{% sample lang="c" %}
[import, lang:"c"](code/c/verlet.c)
{% sample lang="java" %}
-[import, lang:"java"](code/java/VerletValues.java)
[import, lang:"java"](code/java/Verlet.java)
{% sample lang="py" %}
[import, lang:"python"](code/python/verlet.py)
{% sample lang="hs" %}
[import, lang:"haskell"](code/haskell/verlet.hs)
-{% sample lang="scratch" %}
-Submitted by Jie
-
-
-
-Link: [https://scratch.mit.edu/projects/173039394/](https://scratch.mit.edu/projects/173039394/)
-{% sample lang="m" %}
-[import, lang:"matlab"](code/matlab/verlet.m)
-{% sample lang="LabVIEW" %}
-Submitted by P. Mekhail
-
-
-
{% sample lang="js" %}
[import, lang:"javascript"](code/javascript/verlet.js)
{% sample lang="rs" %}
@@ -255,7 +225,7 @@ Submitted by P. Mekhail
{% sample lang="ruby" %}
[import, lang="ruby"](code/ruby/verlet.rb)
{% sample lang="go" %}
-[import, lang:"go"](code/golang/verlet.go)
+[import, lang:"go"](code/go/verlet.go)
{% sample lang="asm-x64" %}
[import, lang:"asm-x64"](code/asm-x64/verlet.s)
{% sample lang="kotlin" %}
@@ -275,7 +245,7 @@ MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
##### Code Examples
-The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/master/LICENSE.md)).
+The code examples are licensed under the MIT license (found in [LICENSE.md](https://github.com/algorithm-archivists/algorithm-archive/blob/main/LICENSE.md)).
##### Text
diff --git a/literature.bib b/literature.bib
index 2f22c0dc8..80e55f787 100644
--- a/literature.bib
+++ b/literature.bib
@@ -346,3 +346,198 @@ @misc{3b1b_finger_count
url={https://youtu.be/1SMmc9gQmHQ},
year={2015}
}
+
+#------------------------------------------------------------------------------#
+# Metropolis #
+#------------------------------------------------------------------------------#
+
+@article{metropolis1953equation,
+author = {Metropolis,Nicholas and Rosenbluth,Arianna W. and Rosenbluth,Marshall N. and Teller,Augusta H. and Teller,Edward },
+title = {Equation of State Calculations by Fast Computing Machines},
+journal = {The Journal of Chemical Physics},
+volume = {21},
+number = {6},
+pages = {1087-1092},
+year = {1953},
+doi = {10.1063/1.1699114},
+
+URL = {
+ https://doi.org/10.1063/1.1699114
+
+},
+eprint = {
+ https://doi.org/10.1063/1.1699114
+
+}
+
+}
+
+@article{rosenthal2011optimal,
+ title={Optimal proposal distributions and adaptive MCMC},
+ author={Rosenthal, Jeffrey S and others},
+ journal={Handbook of Markov Chain Monte Carlo},
+ volume={4},
+ number={10.1201},
+ year={2011},
+ publisher={Chapman & Hall/CRC Boca Raton, FL}
+}
+
+@article{gareth2001optimal,
+author = {Gareth O. Roberts and Jeffrey S. Rosenthal},
+title = {Optimal scaling for various Metropolis-Hastings algorithms},
+volume = {16},
+journal = {Statistical Science},
+number = {4},
+publisher = {Institute of Mathematical Statistics},
+pages = {351 -- 367},
+year = {2001},
+doi = {10.1214/ss/1015346320},
+URL = {https://doi.org/10.1214/ss/1015346320}
+}
+
+@misc{potential_energy_wiki,
+ title={Wikipedia: Potential Energy},
+ url={https://en.wikipedia.org/wiki/Potential_energy},
+ year={2021}
+}
+
+@misc{ludwig_boltzmann_wiki,
+ title={Wikipedia: Ludwig Boltzmann},
+ url={https://en.wikipedia.org/wiki/Ludwig_Boltzmann},
+ year={2021}
+}
+
+@misc{boltzmann_distribution_wiki,
+ title={Wikipedia: Boltzmann distribution},
+ url={https://en.wikipedia.org/wiki/Boltzmann_distribution},
+ year={2021}
+}
+
+@article{hastings1970monte,
+ author = {Hastings, W. K.},
+ title = "Monte Carlo sampling methods using Markov chains and their applications",
+ journal = {Biometrika},
+ volume = {57},
+ number = {1},
+ pages = {97-109},
+ year = {1970},
+ month = {04},
+ abstract = "{A generalization of the sampling method introduced by Metropolis et al. (1953) is presented along with an exposition of the relevant theory, techniques of application and methods and difficulties of assessing the error in Monte Carlo estimates. Examples of the methods, including the generation of random orthogonal matrices and potential applications of the methods to numerical problems arising in statistics, are discussed.}",
+ issn = {0006-3444},
+ doi = {10.1093/biomet/57.1.97},
+ url = {https://doi.org/10.1093/biomet/57.1.97},
+ eprint = {https://academic.oup.com/biomet/article-pdf/57/1/97/23940249/57-1-97.pdf},
+}
+
+@misc{mala_wiki,
+ title={Wikipedia: Metropolis-adjusted Langevin Algorithm},
+ url={https://en.wikipedia.org/wiki/Metropolis-adjusted_Langevin_algorithm},
+ year={2021}
+}
+
+@misc{hmc_wiki,
+ title={Wikipedia: Hamiltonian Monte Carlo},
+ url={https://en.wikipedia.org/wiki/Hamiltonian_Monte_Carlo},
+ year={2021}
+}
+
+@misc{rmsd_wiki,
+ title={Wikipedia: Root Mean Square Deviation},
+ url={https://en.wikipedia.org/wiki/Root-mean-square_deviation},
+ year={2021}
+}
+
+#------------------------------------------------------------------------------#
+# Cryptography
+#------------------------------------------------------------------------------#
+
+@misc{ceasar_cipher_wiki,
+ title={Wikipedia: Ceasar Cipher},
+ url={https://en.wikipedia.org/wiki/Caesar_cipher},
+ year={2022}
+}
+
+@misc{post-quantum_crypto_wiki,
+ title={Wikipedia: Post-quantum Cryptography},
+ url={https://en.wikipedia.org/wiki/Post-quantum_cryptography},
+ year={2022}
+}
+
+@misc{Kerckhoffs_principle_wiki,
+ title={Wikipedia: Kerckhoffs's principle},
+ url={https://en.wikipedia.org/wiki/Kerckhoffs%27s_principle},
+ year={2022}
+}
+
+@misc{rot13_wiki,
+ title={Wikipedia: ROT13},
+ url={https://en.wikipedia.org/wiki/ROT13},
+ year={2022}
+}
+
+@misc{CC_permutation,
+ title={Crypto Corner: Permutation Cipher},
+ url={https://crypto.interactive-maths.com/permutation-cipher.html},
+ year={2022}
+}
+
+@misc{xor_cipher_wiki,
+ title={Wikipedia: XOR cipher},
+ url={https://en.wikipedia.org/wiki/XOR_cipher},
+ year={2022}
+}
+
+@misc{DES_wiki,
+ title={Wikipedia: Data Encryption Standard},
+ url={https://en.wikipedia.org/wiki/Data_Encryption_Standard},
+ year={2022}
+}
+
+@misc{AES_wiki,
+ title={Wikipedia: Advanced Encryption Standard},
+ url={https://en.wikipedia.org/wiki/Advanced_Encryption_Standard},
+ year={2022}
+}
+
+@misc{blowfish_cipher_wiki,
+ title={Wikipedia: Blowfish (cipher)},
+ url={https://en.wikipedia.org/wiki/Blowfish_(cipher)},
+ year={2022}
+}
+
+@misc{RSA_wiki,
+ title={Wikipedia: RSA (cryptosystem)},
+ url={https://en.wikipedia.org/wiki/RSA_(cryptosystem)},
+ year={2022}
+}
+
+@misc{ECC_crypto_wiki,
+ title={Wikipedia: Elliptic-curve cryptography},
+ url={https://en.wikipedia.org/wiki/Elliptic-curve_cryptography},
+ year={2022}
+}
+
+#------------------------------------------------------------------------------#
+# BOX--MULLER
+#------------------------------------------------------------------------------#
+
+@article{box1958,
+ title={A note on the generation of random normal deviates},
+ author={Box, George EP},
+ journal={Ann. Math. Statist.},
+ volume={29},
+ pages={610--611},
+ year={1958}
+}
+
+@misc{marsaglia_wiki,
+ title={Wikipedia: Marsaglia Transform},
+ url={https://en.wikipedia.org/wiki/Marsaglia_polar_method},
+ year={2022}
+}
+
+@misc{box_muller_wiki,
+ title={Wikipedia: Box-Muller Transform},
+ url={https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform},
+ year={2022}
+}
diff --git a/redirects.json b/redirects.json
index 2e2858568..0415c8b20 100644
--- a/redirects.json
+++ b/redirects.json
@@ -139,6 +139,10 @@
{
"from": "chapters/QI/QI.html",
"to": "contents/quantum_information/quantum_information.html"
+ },
+ {
+ "from": "chapters/cryptography/cryptography.html",
+ "to": "contents/cryptography/cryptography.html"
}
]
}
diff --git a/sconscripts/asm-x64_SConscript b/sconscripts/asm-x64_SConscript
new file mode 100644
index 000000000..ba90ee330
--- /dev/null
+++ b/sconscripts/asm-x64_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.X64(build_target, str(file_info.path), LINKFLAGS='-no-pie')
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/bash_SConscript b/sconscripts/bash_SConscript
new file mode 100644
index 000000000..0b3c17dc0
--- /dev/null
+++ b/sconscripts/bash_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.bash'
+ build_result = env.Copier(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
diff --git a/sconscripts/c_SConscript b/sconscripts/c_SConscript
new file mode 100644
index 000000000..ebc6aeead
--- /dev/null
+++ b/sconscripts/c_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.C(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/coconut_SConscript b/sconscripts/coconut_SConscript
new file mode 100644
index 000000000..9325cfe24
--- /dev/null
+++ b/sconscripts/coconut_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.py'
+ build_result = env.Coconut(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
diff --git a/sconscripts/cpp_SConscript b/sconscripts/cpp_SConscript
new file mode 100644
index 000000000..f1ae9f974
--- /dev/null
+++ b/sconscripts/cpp_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.CPlusPlus(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
diff --git a/sconscripts/csharp_SConscript b/sconscripts/csharp_SConscript
new file mode 100644
index 000000000..366471f19
--- /dev/null
+++ b/sconscripts/csharp_SConscript
@@ -0,0 +1,15 @@
+Import('files_to_compile env')
+
+language = files_to_compile[0].language
+chapter = files_to_compile[0].chapter
+
+from collections import defaultdict
+chapter_files = defaultdict(list)
+
+for file_info in files_to_compile:
+ chapter_files[file_info.chapter].append(file_info.path)
+
+for chapter, files in chapter_files.items():
+ build_target = f'#/build/{language}/{chapter}/{chapter}'
+ build_result = env.MCS(build_target, [str(file) for file in files])
+ env.Alias(str(chapter), build_result)
diff --git a/sconscripts/fortran_SConscript b/sconscripts/fortran_SConscript
new file mode 100644
index 000000000..ab85e9f06
--- /dev/null
+++ b/sconscripts/fortran_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.Fortran(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/go_SConscript b/sconscripts/go_SConscript
new file mode 100644
index 000000000..d521574a9
--- /dev/null
+++ b/sconscripts/go_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.Go(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
diff --git a/sconscripts/java_SConscript b/sconscripts/java_SConscript
new file mode 100644
index 000000000..78f87d8a4
--- /dev/null
+++ b/sconscripts/java_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}'
+ build_result = env.Java(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
diff --git a/sconscripts/javascript_SConscript b/sconscripts/javascript_SConscript
new file mode 100644
index 000000000..767f5cd4a
--- /dev/null
+++ b/sconscripts/javascript_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.js'
+ build_result = env.Copier(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/julia_SConscript b/sconscripts/julia_SConscript
new file mode 100644
index 000000000..84de28959
--- /dev/null
+++ b/sconscripts/julia_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.jl'
+ build_result = env.Copier(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/kotlin_SConscript b/sconscripts/kotlin_SConscript
new file mode 100644
index 000000000..81748b367
--- /dev/null
+++ b/sconscripts/kotlin_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.KotlinJar(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
diff --git a/sconscripts/lolcode_SConscript b/sconscripts/lolcode_SConscript
new file mode 100644
index 000000000..241565f53
--- /dev/null
+++ b/sconscripts/lolcode_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.lol'
+ build_result = env.Copier(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/lua_SConscript b/sconscripts/lua_SConscript
new file mode 100644
index 000000000..a64415d74
--- /dev/null
+++ b/sconscripts/lua_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.lua'
+ build_result = env.Copier(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/php_SConscript b/sconscripts/php_SConscript
new file mode 100644
index 000000000..9748a1a5a
--- /dev/null
+++ b/sconscripts/php_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.php'
+ build_result = env.Copier(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/powershell_SConscript b/sconscripts/powershell_SConscript
new file mode 100644
index 000000000..bbb4a9b1a
--- /dev/null
+++ b/sconscripts/powershell_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.ps1'
+ build_result = env.Copier(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/python_SConscript b/sconscripts/python_SConscript
new file mode 100644
index 000000000..0d26a9620
--- /dev/null
+++ b/sconscripts/python_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.py'
+ build_result = env.Copier(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/racket_SConscript b/sconscripts/racket_SConscript
new file mode 100644
index 000000000..e8d23fd83
--- /dev/null
+++ b/sconscripts/racket_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ build_result = env.Racket(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
diff --git a/sconscripts/ruby_SConscript b/sconscripts/ruby_SConscript
new file mode 100644
index 000000000..ad58ed64a
--- /dev/null
+++ b/sconscripts/ruby_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.rb'
+ build_result = env.Copier(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/sconscripts/rust_SConscript b/sconscripts/rust_SConscript
new file mode 100644
index 000000000..893877a67
--- /dev/null
+++ b/sconscripts/rust_SConscript
@@ -0,0 +1,15 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
+ if (file_info.path.parent / 'Cargo.toml').exists():
+ build_result = env.cargo(target=build_target,
+ source=str(file_info.path),
+ MANIFEST=str(file_info.path.parent / 'Cargo.toml'),
+ SOURCE_DIR=str(file_info.path.parent))
+ env.Clean('rust', str(file_info.path.parent / 'target'))
+ else:
+ build_result = env.rustc(build_target, str(file_info.path))
+ env.Clean('rust', f'{build_target}.pdb')
+
+ env.Alias(str(file_info.chapter), build_result)
diff --git a/sconscripts/viml_SConscript b/sconscripts/viml_SConscript
new file mode 100644
index 000000000..bef5029f4
--- /dev/null
+++ b/sconscripts/viml_SConscript
@@ -0,0 +1,6 @@
+Import('files_to_compile env')
+
+for file_info in files_to_compile:
+ build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}.vim'
+ build_result = env.Copier(build_target, str(file_info.path))
+ env.Alias(str(file_info.chapter), build_result)
\ No newline at end of file
diff --git a/update_site.sh b/update_site.sh
deleted file mode 100755
index 0ccf8f7bb..000000000
--- a/update_site.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env bash
-
-if [ $# -ge 1 ]; then
- if [ $# -eq 2 ]; then
- out_dir="$2"
- else
- if [ -z ${AAA_DIR+x} ]; then
- echo "No output directory specified"
- exit 1
- fi
- out_dir="$AAA_DIR"
- fi
-
- if [[ ! -d "$out_dir" ]]; then
- echo "$out_dir is not a directory"
- exit 1
- fi
-
- npm run build . /tmp/algorithm-archivists.github.io
-
- if [ $? -ne 0 ]; then
- echo "Failed to build the book"
- exit 1
- fi
-
- cd "$out_dir"
- git reset --hard && \
- git clean -dfx && \
- git pull origin master
-
- if [ $? -ne 0 ]; then
- echo "Failed to prepare repository"
- exit 1
- fi
-
- cp -r /tmp/algorithm-archivists.github.io/* .
- rm -r /tmp/algorithm-archivists.github.io
- git add .
- git commit -m "$1"
- git push origin master
-
-else
- echo "No commit message specified"
-fi