├── .JuliaFormatter.toml ├── .github └── workflows │ ├── CI.yml │ ├── CompatHelper.yml │ ├── TagBot.yml │ ├── approved-label.yml │ ├── check_format.yml │ └── directory_writer.yml ├── .gitignore ├── .gitpod.dockerfile ├── .gitpod.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── DIRECTORY.md ├── LICENSE.md ├── Project.toml ├── README.md ├── docs ├── CODEOWNERS ├── Project.toml ├── make.jl └── src │ └── index.md ├── pluto_notebooks ├── seir.jl └── sir.jl ├── src ├── README.md ├── TheAlgorithms.jl ├── basic │ ├── Basic.jl │ ├── difference_arr.jl │ ├── hanoi.jl │ └── prefix_sum.jl ├── cipher │ ├── Cipher.jl │ ├── affine.jl │ ├── atbash.jl │ ├── caesar.jl │ └── vigenere.jl ├── conversions │ ├── Conversions.jl │ ├── length_conversion.jl │ ├── temparature_conversion.jl │ └── weight_conversion.jl ├── data_structures │ ├── DataStructure.jl │ ├── binary_heap.jl │ ├── binary_tree │ │ ├── basic_binary_search_tree.jl │ │ ├── basic_binary_tree.jl │ │ └── splay.jl │ ├── disjoint_set │ │ └── disjoint_set.jl │ ├── fenwick_tree.jl │ └── linked_list.jl ├── dynamic_programming │ ├── DynamicProgramming.jl │ └── coin_change.jl ├── graph │ ├── Graph.jl │ ├── bellman_ford.jl │ ├── bfs.jl │ ├── dfs.jl │ └── dijkstra.jl ├── knapsack │ ├── KnapSack.jl │ ├── dynamic_programming.jl │ └── greedy_algorithm.jl ├── longest_increasing_subsequence │ ├── LongSubSeq.jl │ ├── binary_search.jl │ └── dynamic_programming.jl ├── machine_learning │ ├── ML.jl │ ├── k_means.jl │ └── linear_regression.jl ├── math │ ├── Math.jl │ ├── abs.jl │ ├── amicable_numbers.jl │ ├── area.jl │ ├── armstrong_number.jl │ ├── average_absolute_deviation.jl │ ├── average_mean.jl │ ├── average_median.jl │ ├── average_mode.jl │ ├── babylonian_sqrt.jl │ ├── binary_length.jl │ ├── catalan_number.jl │ ├── ceil.jl │ ├── collatz_sequence.jl │ ├── combination.jl │ ├── divisors.jl │ ├── euler_method.jl │ ├── eulers_totient.jl │ ├── factorial.jl │ ├── fibonacci.jl │ ├── floor.jl │ ├── krishnamurthy_number.jl │ ├── least_common_multiple.jl │ ├── line_length.jl │ ├── mersenne_prime.jl │ ├── monte_carlo_integration.jl │ ├── partitions.jl │ ├── perfect_cube.jl │ ├── perfect_number.jl │ ├── perfect_square.jl │ ├── permutation.jl │ ├── prime_check.jl │ ├── prime_factors.jl │ ├── riemann_integration.jl │ ├── runge_kutta_integration.jl │ ├── sieve_of_eratosthenes.jl │ ├── simpsons_integration.jl │ ├── sum_of_arithmetic_series.jl │ ├── sum_of_geometric_progression.jl │ ├── trapezoid_integration.jl │ ├── verlet.jl │ └── volume.jl ├── matrix │ ├── MatrixAlgo.jl │ ├── determinant.jl │ ├── gauss_jordan_elim.jl │ ├── lu_decompose.jl │ └── rotation_matrix.jl ├── project_euler │ ├── ProjectEuler.jl │ ├── problem_001.jl │ ├── problem_002.jl │ ├── problem_003.jl │ ├── problem_004.jl │ ├── problem_005.jl │ ├── problem_006.jl │ ├── problem_007.jl │ ├── problem_008.jl │ ├── problem_009.jl │ ├── problem_010.jl │ ├── problem_011.jl │ ├── problem_012.jl │ ├── problem_013.jl │ ├── problem_014.jl │ ├── problem_015.jl │ ├── problem_016.jl │ ├── problem_017.jl │ ├── problem_018.jl │ ├── problem_019.jl │ └── problem_020.jl ├── project_rosalind │ ├── ProjectRosalind.jl │ ├── count_nucleotide.jl │ ├── dna2_rna.jl │ ├── rabbits.jl │ └── reverse_complement.jl ├── scheduling │ ├── Scheduling.jl │ └── fcfs.jl ├── searches │ ├── Searches.jl │ ├── binary_search.jl │ ├── exponential_search.jl │ ├── interpolation_search.jl │ ├── jump_search.jl │ └── linear_search.jl ├── sorts │ ├── Sorts.jl │ ├── bogo_sort.jl │ ├── bubble_sort.jl │ ├── bucket_sort.jl │ ├── counting_sort.jl │ ├── exchange_sort.jl │ ├── heap_sort.jl │ ├── insertion_sort.jl │ ├── merge_sort.jl │ ├── quick_sort.jl │ └── selection_sort.jl ├── statistics │ ├── StatAlgo.jl │ ├── pearson_correlation.jl │ └── variance.jl └── strings │ ├── StringAlgo.jl │ ├── detect_anagrams.jl │ ├── hamming_distance.jl │ ├── is_palindrome.jl │ ├── kmp_substring_search.jl │ ├── lcs.jl │ ├── naive_pattern_search.jl │ ├── pangram.jl │ ├── rabin_karp.jl │ └── word_count.jl └── test ├── Project.toml ├── basic.jl ├── cipher.jl ├── conversions.jl ├── data_structures.jl ├── dynamic_programming.jl ├── graph.jl ├── knapsack.jl ├── longest_increasing_subsequence.jl ├── machine_learning.jl ├── math.jl ├── matrix.jl ├── project_euler.jl ├── project_rosalind.jl ├── runtests.jl ├── scheduling.jl ├── searches.jl ├── sorts.jl ├── statistics.jl └── strings.jl /.JuliaFormatter.toml: -------------------------------------------------------------------------------- 1 | always_for_in = true 2 | always_use_return = true 3 | margin = 80 4 | remove_extra_newlines = true 5 | short_to_long_function_def = true 6 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | - push 4 | - pull_request 5 | jobs: 6 | test: 7 | name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | version: 13 | - '1.9' 14 | - 'nightly' 15 | os: 16 | - ubuntu-latest 17 | - macOS-latest 18 | - windows-latest 19 | arch: 20 | - x64 21 | - x86 22 | threads: 23 | - "4" 24 | exclude: 25 | - os: macOS-latest 26 | arch: x86 27 | - os: macOS-latest 28 | version: 'nightly' 29 | steps: 30 | - uses: actions/checkout@v4 31 | - uses: julia-actions/setup-julia@v1 32 | with: 33 | version: ${{ matrix.version }} 34 | arch: ${{ matrix.arch }} 35 | - uses: actions/cache@v1 36 | env: 37 | cache-name: cache-artifacts 38 | with: 39 | path: ~/.julia/artifacts 40 | key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} 41 | restore-keys: | 42 | ${{ runner.os }}-test-${{ env.cache-name }}- 43 | ${{ runner.os }}-test- 44 | ${{ runner.os }}- 45 | - uses: julia-actions/julia-buildpkg@v1 46 | - uses: julia-actions/julia-runtest@v1 47 | env: 48 | JULIA_NUM_THREADS: ${{ matrix.threads }} 49 | - uses: julia-actions/julia-processcoverage@v1 50 | - uses: codecov/codecov-action@v3 51 | with: 52 | file: lcov.info 53 | docs: 54 | name: Documentation 55 | runs-on: ubuntu-latest 56 | steps: 57 | - uses: actions/checkout@v4 58 | - uses: julia-actions/setup-julia@v1 59 | with: 60 | version: '1.8' 61 | - run: | 62 | julia --project=docs -e ' 63 | using Pkg 64 | Pkg.develop(PackageSpec(path=pwd())) 65 | Pkg.instantiate()' 66 | - run: | 67 | julia --project=docs -e ' 68 | using Documenter: DocMeta 69 | using TheAlgorithms 70 | DocMeta.setdocmeta!(TheAlgorithms, :DocTestSetup, :(using TheAlgorithms); recursive=true)' 71 | - run: julia --project=docs docs/make.jl 72 | env: 73 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 74 | DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} 75 | -------------------------------------------------------------------------------- /.github/workflows/CompatHelper.yml: -------------------------------------------------------------------------------- 1 | name: CompatHelper 2 | on: 3 | schedule: 4 | - cron: 0 0 * * * 5 | workflow_dispatch: 6 | jobs: 7 | CompatHelper: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Pkg.add("CompatHelper") 11 | run: julia -e 'using Pkg; Pkg.add("CompatHelper")' 12 | - name: CompatHelper.main() 13 | env: 14 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 15 | COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }} 16 | run: julia -e 'using CompatHelper; CompatHelper.main()' 17 | -------------------------------------------------------------------------------- /.github/workflows/TagBot.yml: -------------------------------------------------------------------------------- 1 | name: TagBot 2 | on: 3 | issue_comment: 4 | types: 5 | - created 6 | workflow_dispatch: 7 | jobs: 8 | TagBot: 9 | if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: JuliaRegistries/TagBot@v1 13 | with: 14 | token: ${{ secrets.GITHUB_TOKEN }} 15 | ssh: ${{ secrets.DOCUMENTER_KEY }} 16 | -------------------------------------------------------------------------------- /.github/workflows/approved-label.yml: -------------------------------------------------------------------------------- 1 | on: pull_request_review 2 | name: Add "approved" label when approved 3 | jobs: 4 | add_label: 5 | name: Add "approved" label when approved 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Add "approved" label when approved 9 | uses: pullreminders/label-when-approved-action@master 10 | env: 11 | APPROVALS: "1" 12 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 13 | ADD_LABEL: "approved" 14 | REMOVE_LABEL: "" 15 | -------------------------------------------------------------------------------- /.github/workflows/check_format.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: check_format 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | workflow_dispatch: 7 | push: 8 | branches: 9 | - main 10 | pull_request: 11 | 12 | jobs: 13 | check_format: 14 | name: Check format 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: julia-actions/setup-julia@v1 18 | with: 19 | version: 1.9 20 | - uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Install JuliaFormatter 25 | run: | 26 | julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter"))' 27 | 28 | - name: Format code 29 | run: | 30 | git clean -f -x -d 31 | julia -e 'using JuliaFormatter; format(".", verbose=true)' 32 | 33 | - name: Fail if needs reformatting 34 | run: | 35 | if [[ $(git status --porcelain) ]]; then 36 | echo "please reformat these files:" 37 | git status --porcelain=v1 38 | exit 1 39 | fi 40 | ... 41 | -------------------------------------------------------------------------------- /.github/workflows/directory_writer.yml: -------------------------------------------------------------------------------- 1 | name: Directory writer 2 | on: 3 | schedule: 4 | # ┌───────────── minute (0 - 59) 5 | # │ ┌───────────── hour (0 - 23) 6 | # │ │ ┌───────────── day of the month (1 - 31) 7 | # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) 8 | # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) 9 | # │ │ │ │ │ 10 | # │ │ │ │ │ 11 | # │ │ │ │ │ 12 | # * * * * * 13 | - cron: '0 0 * * *' 14 | workflow_dispatch: 15 | jobs: 16 | build: 17 | if: github.repository == 'TheAlgorithms/Julia' # We only need this to run in our repository. 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | - name: Build directory 24 | uses: TheAlgorithms/scripts/directory_md@main 25 | with: 26 | language: Julia 27 | working-directory: src 28 | filetypes: jl 29 | ignored-directories: docs/,pluto_notebooks/,test/ 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files generated by invoking Julia with --code-coverage 2 | *.jl.cov 3 | *.jl.*.cov 4 | 5 | # Files generated by invoking Julia with --track-allocation 6 | *.jl.mem 7 | 8 | # System-specific files and directories generated by the BinaryProvider and BinDeps packages 9 | # They contain absolute paths specific to the host computer, and so should not be committed 10 | deps/deps.jl 11 | deps/build.log 12 | deps/downloads/ 13 | deps/usr/ 14 | deps/src/ 15 | 16 | # Build artifacts for creating documentation generated by the Documenter package 17 | docs/build/ 18 | docs/site/ 19 | docs/Manifest.toml 20 | 21 | Manifest.toml 22 | 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /.gitpod.dockerfile: -------------------------------------------------------------------------------- 1 | FROM gitpod/workspace-base:2023-10-19-14-24-02 2 | 3 | ENV JULIA_TMP="julia_tmp.tar.gz" 4 | 5 | RUN test ! -e "${JULIA_TMP}" \ 6 | && curl https://julialang-s3.julialang.org/bin/linux/x64/1.9/julia-1.9.3-linux-x86_64.tar.gz -sSf -o "${JULIA_TMP}" \ 7 | && tar zxvf ${JULIA_TMP} \ 8 | && rm ${JULIA_TMP} \ 9 | && echo "export PATH=${HOME}/julia-1.9.3/bin/:\$PATH" >> ~/.bashrc 10 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: 2 | file: .gitpod.dockerfile 3 | 4 | github: 5 | prebuilds: 6 | addBadge: true 7 | addComment: false 8 | addCheck: false 9 | master: true 10 | branches: true 11 | pullRequestsFromForks: true 12 | 13 | vscode: 14 | extensions: 15 | - julialang.language-julia 16 | - singularitti.vscode-julia-formatter 17 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ### Bug Fixes 6 | 7 | - Endline 8 | - Worng output order ([#114](https://github.com/orhun/git-cliff/issues/114)) 9 | - Formatting issues 10 | - `.gitpod.dockerfile` issues ([#162](https://github.com/orhun/git-cliff/issues/162)) 11 | - Break `ceil_floor` into separate entries for ceil and floor ([#168](https://github.com/orhun/git-cliff/issues/168)) 12 | - Using DataStructures in Graph 13 | 14 | ### CompatHelper 15 | 16 | - Add new compat entry for "DifferentialEquations" at version "6" ([#26](https://github.com/orhun/git-cliff/issues/26)) 17 | - Add new compat entry for "DataFrames" at version "1" ([#25](https://github.com/orhun/git-cliff/issues/25)) 18 | - Add new compat entry for "GLM" at version "1" ([#24](https://github.com/orhun/git-cliff/issues/24)) 19 | - Add new compat entry for "Plots" at version "1" ([#23](https://github.com/orhun/git-cliff/issues/23)) 20 | - Add new compat entry for DataStructures at version 0.18, (keep existing compat) ([#144](https://github.com/orhun/git-cliff/issues/144)) 21 | 22 | ### Documentation 23 | 24 | - Improve the contributing guidelines ([#165](https://github.com/orhun/git-cliff/issues/165)) 25 | - Update DIRECTORY.md 26 | - Update README 27 | - Disable doctest 28 | - Reenable doctests 29 | 30 | ### Features 31 | 32 | - Add the `Approved label` workflow 33 | - Add Simpson's Integration algorithm ([#89](https://github.com/orhun/git-cliff/issues/89)) 34 | - Add trapezoid sum integration algorithm ([#88](https://github.com/orhun/git-cliff/issues/88)) 35 | - Format code with JuliaFormatter ([#140](https://github.com/orhun/git-cliff/issues/140)) 36 | - Add a Gitpod Dockerfile ([#147](https://github.com/orhun/git-cliff/issues/147)) 37 | - Run formatter workflow on PRs ([#157](https://github.com/orhun/git-cliff/issues/157)) 38 | - Improve the Julia formatter workflow ([#163](https://github.com/orhun/git-cliff/issues/163)) 39 | - Add directory and filename formatter workflow ([#167](https://github.com/orhun/git-cliff/issues/167)) 40 | 41 | ### Miscellaneous Tasks 42 | 43 | - Run Julia Formatter ([#148](https://github.com/orhun/git-cliff/issues/148)) 44 | - Update copyright notice 45 | - Add codeowners file ([#154](https://github.com/orhun/git-cliff/issues/154)) 46 | 47 | ### Refactor 48 | 49 | - Create Basic submodule 50 | - Create Cipher submodule 51 | - Create DataStructure submodule 52 | - Create Graph submodule 53 | - Import MinHeap in dijkstra algo 54 | - Create DynamicProgramming submodule 55 | - Add Cipher submodule 56 | - Add Scheduling submodule 57 | - Add Conversions submodule 58 | - Add Sorts submodule 59 | - Add KnapSack submodule 60 | - Add Math submodule 61 | - Add MatrixAlgo submodule 62 | - Add Searches submodule 63 | - Add LongSubSeq submodule 64 | - Add StatAlgo submodule 65 | - Add StringAlgo submodule 66 | - Add ML submodule 67 | - Update DataStructure 68 | - Add ProjectRosalind submodule 69 | - Add ProjectEuler submodule 70 | - Bundle exports of new submodules 71 | 72 | ### Testing 73 | 74 | - Add Basic to namespace 75 | - Add Cipher to namespace 76 | - Add DataStructure to namespace 77 | - Add Graph to namespace 78 | - Add DynamicProgramming to namespace 79 | 80 | ### Ci 81 | 82 | - Update Julia to latest release ([#141](https://github.com/orhun/git-cliff/issues/141)) 83 | 84 | ### Format 85 | 86 | - JuliaFormatter 87 | 88 | ### Remove 89 | 90 | - Directory/file_formatter 91 | - Formatter 92 | 93 | 94 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2022 The Algorithms & contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Project.toml: -------------------------------------------------------------------------------- 1 | name = "TheAlgorithms" 2 | uuid = "e4253e37-a807-4a6a-91a4-87b21ad1f734" 3 | authors = ["Panquesito7"] 4 | version = "0.1.0" 5 | 6 | [deps] 7 | DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" 8 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 9 | Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 10 | 11 | [compat] 12 | DataStructures = "0.18" 13 | julia = "1.8" 14 | 15 | [extras] 16 | Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 17 | 18 | [targets] 19 | test = ["Test"] 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Algorithms - Julia 2 | 3 | [![Discord chat](https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=7289DA&style=flat-square)](https://the-algorithms.com/discord/)  4 | [![Gitter chat](https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square)](https://gitter.im/TheAlgorithms)  5 | [![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://TheAlgorithms.github.io/Julia/stable) 6 | [![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://TheAlgorithms.github.io/Julia/dev) 7 | [![Build Status](https://github.com/TheAlgorithms/Julia/workflows/CI/badge.svg)](https://github.com/TheAlgorithms/Julia/actions) 8 | [![codecov](https://codecov.io/gh/TheAlgorithms/Julia/branch/main/graph/badge.svg)](https://codecov.io/gh/TheAlgorithms/Julia) 9 | [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/TheAlgorithms/Julia) 10 | [![Donate](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/TheAlgorithms/donate) 11 | 12 | ### Algorithms implemented in Julia (for educational purposes) 13 | 14 | These implementations are for learning purposes. The implementations may be less efficient than the Julia standard library.\ 15 | We're collaborating with the amazing Humans of Julia community. Check their website here: https://humansofjulia.org/ 16 | 17 | ## Contribution Guidelines 18 | 19 | Read our [Contribution Guidelines](https://github.com/TheAlgorithms/Julia/blob/main/CONTRIBUTING.md) before you contribute. 20 | 21 | ## Community Channel 22 | 23 | We're on [Gitter](https://gitter.im/TheAlgorithms) and [Discord](https://the-algorithms.com/discord/)! Please join us. 24 | -------------------------------------------------------------------------------- /docs/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @uncomfyhalomacro @Azzaare ## Has access over all files 2 | *.md @Panquesito7 3 | *.yml @Panquesito7 4 | /docs/ @Panquesito7 5 | /.github/ @Panquesito7 6 | -------------------------------------------------------------------------------- /docs/Project.toml: -------------------------------------------------------------------------------- 1 | [deps] 2 | Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" 3 | -------------------------------------------------------------------------------- /docs/make.jl: -------------------------------------------------------------------------------- 1 | cd(@__DIR__) 2 | using Pkg; 3 | Pkg.activate(@__DIR__); 4 | push!(LOAD_PATH, "../") 5 | using TheAlgorithms 6 | using Documenter 7 | 8 | DocMeta.setdocmeta!( 9 | TheAlgorithms, 10 | :DocTestSetup, 11 | :(using TheAlgorithms, 12 | TheAlgorithms.Basic, 13 | TheAlgorithms.Basic.Hanoi, 14 | TheAlgorithms.Cipher, 15 | TheAlgorithms.Conversions, 16 | TheAlgorithms.DataStructure, 17 | TheAlgorithms.DataStructure.LinkedList, 18 | TheAlgorithms.DataStructure.FenwickTree, 19 | TheAlgorithms.DynamicProgramming, 20 | TheAlgorithms.Graph, 21 | TheAlgorithms.KnapSack, 22 | TheAlgorithms.LongSubSeq, 23 | TheAlgorithms.Math, 24 | TheAlgorithms.MatrixAlgo, 25 | TheAlgorithms.ML, 26 | TheAlgorithms.ProjectEuler, 27 | TheAlgorithms.ProjectRosalind, 28 | TheAlgorithms.Scheduling, 29 | TheAlgorithms.Searches, 30 | TheAlgorithms.Sorts, 31 | TheAlgorithms.StatAlgo, 32 | TheAlgorithms.StringAlgo); 33 | recursive = true, 34 | ) 35 | 36 | makedocs(; 37 | modules = [ 38 | TheAlgorithms, 39 | TheAlgorithms.Basic, 40 | TheAlgorithms.Basic.Hanoi, 41 | TheAlgorithms.Cipher, 42 | TheAlgorithms.Conversions, 43 | TheAlgorithms.DataStructure, 44 | TheAlgorithms.DataStructure.LinkedList, 45 | TheAlgorithms.DataStructure.FenwickTree, 46 | TheAlgorithms.DynamicProgramming, 47 | TheAlgorithms.Graph, 48 | TheAlgorithms.KnapSack, 49 | TheAlgorithms.LongSubSeq, 50 | TheAlgorithms.Math, 51 | TheAlgorithms.MatrixAlgo, 52 | TheAlgorithms.ML, 53 | TheAlgorithms.ProjectEuler, 54 | TheAlgorithms.ProjectRosalind, 55 | TheAlgorithms.Scheduling, 56 | TheAlgorithms.Searches, 57 | TheAlgorithms.Sorts, 58 | TheAlgorithms.StatAlgo, 59 | TheAlgorithms.StringAlgo, 60 | ], 61 | authors = "Panquesito7", 62 | repo = "https://github.com/TheAlgorithms/Julia/blob/{commit}{path}#{line}", 63 | sitename = "TheAlgorithms.jl", 64 | format = Documenter.HTML(; 65 | prettyurls = get(ENV, "CI", "false") == "true", 66 | canonical = "https://TheAlgorithms.github.io/Julia", 67 | assets = String[], 68 | size_threshold = 409600, 69 | ), 70 | pages = ["Home" => "index.md"], 71 | doctest = true, 72 | ) 73 | 74 | deploydocs(; repo = "github.com/TheAlgorithms/Julia", devbranch = "main") 75 | -------------------------------------------------------------------------------- /docs/src/index.md: -------------------------------------------------------------------------------- 1 | ```@meta 2 | CurrentModule = TheAlgorithms 3 | ``` 4 | 5 | # TheAlgorithms 6 | 7 | Documentation for [TheAlgorithms](https://github.com/TheAlgorithms/Julia). 8 | 9 | ```@index 10 | ``` 11 | 12 | ```@autodocs 13 | Modules = [ 14 | TheAlgorithms, 15 | TheAlgorithms.Basic, 16 | TheAlgorithms.Basic.Hanoi, 17 | TheAlgorithms.Basic.DifferenceArray, 18 | TheAlgorithms.Cipher, 19 | TheAlgorithms.Conversions, 20 | TheAlgorithms.DataStructure, 21 | TheAlgorithms.DataStructure.LinkedList, 22 | TheAlgorithms.DataStructure.FenwickTree, 23 | TheAlgorithms.DynamicProgramming, 24 | TheAlgorithms.Graph, 25 | TheAlgorithms.KnapSack, 26 | TheAlgorithms.LongSubSeq, 27 | TheAlgorithms.Math, 28 | TheAlgorithms.MatrixAlgo, 29 | TheAlgorithms.ML, 30 | TheAlgorithms.ProjectEuler, 31 | TheAlgorithms.ProjectRosalind, 32 | TheAlgorithms.Scheduling, 33 | TheAlgorithms.Searches, 34 | TheAlgorithms.Sorts, 35 | TheAlgorithms.StatAlgo, 36 | TheAlgorithms.StringAlgo 37 | ] 38 | ``` 39 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | ../DIRECTORY.md -------------------------------------------------------------------------------- /src/TheAlgorithms.jl: -------------------------------------------------------------------------------- 1 | module TheAlgorithms 2 | 3 | # Usings/Imports (keep sorted) 4 | using LinearAlgebra 5 | using Random 6 | using DataStructures 7 | 8 | ## Exports 9 | # Please keep the folders/functions sorted 10 | 11 | include("basic/Basic.jl") 12 | include("cipher/Cipher.jl") 13 | include("conversions/Conversions.jl") 14 | include("data_structures/DataStructure.jl") 15 | include("dynamic_programming/DynamicProgramming.jl") 16 | include("graph/Graph.jl") 17 | include("knapsack/KnapSack.jl") 18 | include("longest_increasing_subsequence/LongSubSeq.jl") 19 | include("machine_learning/ML.jl") 20 | include("math/Math.jl") 21 | include("matrix/MatrixAlgo.jl") 22 | include("project_euler/ProjectEuler.jl") 23 | include("project_rosalind/ProjectRosalind.jl") 24 | include("scheduling/Scheduling.jl") 25 | include("searches/Searches.jl") 26 | include("sorts/Sorts.jl") 27 | include("statistics/StatAlgo.jl") 28 | include("strings/StringAlgo.jl") 29 | 30 | end 31 | -------------------------------------------------------------------------------- /src/basic/Basic.jl: -------------------------------------------------------------------------------- 1 | export Basic 2 | """ 3 | Basic 4 | 5 | Basic algorthims for TheAlgorithms/Julia 6 | """ 7 | module Basic 8 | 9 | using TheAlgorithms 10 | 11 | export prefix_sum 12 | export DifferenceArray 13 | export Hanoi 14 | 15 | include("hanoi.jl") 16 | include("difference_arr.jl") 17 | include("prefix_sum.jl") 18 | 19 | end 20 | -------------------------------------------------------------------------------- /src/basic/difference_arr.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Difference array 3 | 4 | # Brief: 5 | For any array A with N numbers, we can create difference array D with N numbers also. 6 | Every k-th element of D is equal to difference between A[k] and A[k-1] 7 | D[k] = A[k-1] - A[k] 8 | 9 | # Complexity of some operations 10 | - add some value x to the m consecutive elements of array - O(1) 11 | - print array after any numbers of changes - O(N) 12 | 13 | # Functions 14 | - create_diff_arr(original::Array{<:Number}) 15 | * Create difference array for array 'original' 16 | - calculate_arr(diff_arr::Array{<:Number}) 17 | * Recreate the original array from the given difference array 18 | - add_to_arr(diff_arr::Array{<:Number}, l::Int, r::Int, x::Number) 19 | * Add x to all elements with index from [l, r] 20 | 21 | 22 | # Contributed by: [Nikola Mircic](https://github.com/Nikola-Mircic) 23 | """ 24 | module DifferenceArray 25 | # Create difference array for array 'original' 26 | # Parameters: 27 | # - original - an array which is used for calculating the difference array 28 | function create_diff_arr(original::Array{T}) where {T<:Number} 29 | n = length(original) 30 | 31 | diff_arr = copy(original) 32 | 33 | for i in 2:n 34 | diff_arr[i] = original[i] - original[i-1] 35 | end 36 | 37 | return diff_arr 38 | end 39 | 40 | # Create a original array from the given difference array 41 | # Parameters: 42 | # - diff_arr - an difference array which is used for calculating the original array 43 | function calculate_arr(diff_arr::Array{T}) where {T<:Number} 44 | n = length(diff_arr) 45 | 46 | arr = copy(diff_arr) 47 | 48 | for i in 2:n 49 | arr[i] = diff_arr[i] + arr[i-1] 50 | end 51 | 52 | return arr 53 | end 54 | 55 | # Add x to all elements with index from [l, r] 56 | # Parameters: 57 | # - diff_arr - a difference array of the array you want to change 58 | # - l - leftmost index of the affected range 59 | # - r - rightmost index of the affected range 60 | # - x - a value to be added to all elements from a given range 61 | function add_to_arr( 62 | diff_arr::Array{T}, 63 | l::Int, 64 | r::Int, 65 | x::Number, 66 | ) where {T<:Number} 67 | diff_arr[l] += x 68 | if r < length(diff_arr) 69 | diff_arr[r+1] -= x 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /src/basic/hanoi.jl: -------------------------------------------------------------------------------- 1 | """ 2 | The Tower of Hanoi 3 | 4 | # Brief: 5 | The Tower of Hanoi is a mathematical game or puzzle consisting of three rods and a number 6 | of disks of various diameters, which can slide onto any rod. 7 | The puzzle begins with the disks stacked on one rod in order of decreasing size, 8 | the smallest at the top, thus approximating a conical shape. 9 | The objective of the puzzle is to move the entire stack to the last rod, 10 | obeying the following rules: 11 | 1. Only one disk may be moved at a time. 12 | 2. Each move consists of taking the upper disk from one of the stacks and placing it on 13 | top of another stack or on an empty rod. 14 | 3. No disk may be placed on top of a disk that is smaller than it. 15 | 16 | # Complexity: O(2^n) 17 | 18 | # Functions 19 | - solveUtil(tower1, tower2, tower3, n::Int, solution::Array{Pair}) - The recursive function which finds the solution and saves it to 20 | the array of pairs where each pair represents one move 21 | - solve(tower1, tower2, tower3,n::Int) - The main function for finding the set of steps to move n rings from tower 1 to tower 3, using tower 2 22 | - printSolution(solution::Array{Pair}) - Prints the solution given as an array of pairs by printing each pair ( step ) in a different line 23 | 24 | # Reference:- [Wikipedia](https://en.wikipedia.org/wiki/Tower_of_Hanoi) 25 | 26 | # Contributed by:- [Nikola Mircic](https://github.com/Nikola-Mircic) 27 | """ 28 | 29 | module Hanoi 30 | function solveUtil(tower1, tower2, tower3, n::Int, solution::Array{Pair}) 31 | if n == 1 32 | push!(solution, tower1 => tower3) # There is only one ring, so just move it from tower1 to tower3 33 | else 34 | solveUtil(tower1, tower3, tower2, n - 1, solution) # Move n-1 rings from tower1 to tower2 to free the bottom ring 35 | push!(solution, tower1 => tower3) # Move the bottom ring from tower1 to tower3 36 | solveUtil(tower2, tower1, tower3, n - 1, solution) # Now move those n-1 rings from tower2 to tower3 37 | end 38 | end 39 | 40 | function solve(tower1, tower2, tower3, n::Int) 41 | solution = Array{Pair}(undef, 0) 42 | solveUtil(tower1, tower2, tower3, n, solution) 43 | return solution 44 | end 45 | 46 | function printSolution(solution::Array{Pair}) 47 | for step in solution 48 | println(step) 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /src/basic/prefix_sum.jl: -------------------------------------------------------------------------------- 1 | """ 2 | prefix_sum(arr::Vector{<:Number}) 3 | 4 | # Brief 5 | Given an input array of numbers, return an array of the sum of each "prefix" of the input array i.e. 6 | the 1st element, 1st + 2nd element, 1st + 2nd + 3rd, etc. 7 | 8 | This functionality is available in base Julia as `cumsum`. 9 | 10 | # Arguments 11 | - `arr`: an array of numbers 12 | 13 | # Examples 14 | ```julia 15 | julia> prefix_sum([1, 2, 3]) 16 | 3-element Vector{Int64}: 17 | 1 18 | 3 19 | 6 20 | 21 | julia> prefix_sum([0.0, 10.0, π]) 22 | 3-element Vector{Float64}: 23 | 0.0 24 | 10.0 25 | 13.141592653589793 26 | ``` 27 | """ 28 | function prefix_sum(arr::Vector{T}) where {T<:Number} 29 | pre = T[] 30 | preans = zero(T) 31 | for i in arr 32 | preans += i 33 | push!(pre, preans) 34 | end 35 | return pre 36 | end 37 | -------------------------------------------------------------------------------- /src/cipher/Cipher.jl: -------------------------------------------------------------------------------- 1 | export Cipher 2 | """ 3 | Cipher 4 | 5 | `Cipher` algorithms. 6 | """ 7 | module Cipher 8 | 9 | using TheAlgorithms 10 | 11 | export caesar 12 | # export rotate 13 | export atbash_encode 14 | export affine 15 | export encrypt_vigenere 16 | export decrypt_vigenere 17 | 18 | include("affine.jl") 19 | include("caesar.jl") 20 | include("atbash.jl") 21 | include("vigenere.jl") 22 | 23 | end 24 | -------------------------------------------------------------------------------- /src/cipher/affine.jl: -------------------------------------------------------------------------------- 1 | """ 2 | affine(text, alphabet, nMultiply, nAdd) 3 | 4 | Program to implement affine cipher for the given input. A full description of it can be found on [wikipedia](https://en.wikipedia.org/wiki/Affine_cipher). 5 | 6 | # Arguments: 7 | - `text` : text to be encoded/decoded 8 | - `alphabet` : the alphaebt the text uses 9 | - `nMultiply` : the number to the multiply by (a) 10 | - `nAdd` : the number to add (b) 11 | 12 | # Examples/Tests 13 | ```julia 14 | 15 | julia> affine("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", 3, 1) 16 | "behknqtwzcfiloruxadgjmpsvy" 17 | 18 | julia> affine("whyhellothere", "abcdefghijklmnopqrstuvwxyz", 17, 82) 19 | "otwtujjiptuhu" 20 | 21 | julia> affine("1234", "0123456789", 5, 2) 22 | "9630" 23 | 24 | ``` 25 | 26 | # Algorithm: 27 | As usual, julia's 1 based indexing doesn't play nicely with the affine cipher, but all that is required is `-1` from the initial index of the letter and `+1` after the mod. 28 | 29 | An affine cipher uses a simple function: `f(x) = ax + b`. 30 | 31 | Notes: 32 | 33 | - `nMultiply` and `length(alphabet)` *must* be coprime so that the two plaintext letters are not substituted for the same cipehrtext letter. 34 | - This doesn't check that the all of the characters in `text` actually are in `alphabet`, but that does need to be the case! 35 | 36 | ```julia 37 | 38 | join([ 39 | alphabet[((findfirst(isequal(letter), alphabet) - 1) * nMultiply + nAdd) % length(alphabet) + 1] 40 | for letter in text 41 | ]) 42 | 43 | ``` 44 | 45 | # References: 46 | https://www.dcode.fr/affine-cipher 47 | https://github.com/Squalm/Cipher-Tools 48 | 49 | 50 | ### Contributed by: [Chirp (Squalm)](https://github.com/Squalm) 51 | """ 52 | function affine(text::String, alphabet::String, nMultiply::Int, nAdd::Int) 53 | return join([ 54 | alphabet[((findfirst( 55 | isequal(letter), 56 | alphabet, 57 | )-1)*nMultiply+nAdd)%length(alphabet)+1] for letter in text 58 | ]) 59 | end # function 60 | -------------------------------------------------------------------------------- /src/cipher/atbash.jl: -------------------------------------------------------------------------------- 1 | """ 2 | encode(input) 3 | 4 | Program to implement atbash cipher for the given sentence.A full description of the algorithm can be found on [wikipedia](https://en.wikipedia.org/wiki/Atbash) 5 | 6 | # Arguments: 7 | - `input` : The sentence needed to rotate 8 | 9 | # Examples/Tests 10 | ```julia 11 | julia> atbash_encode("test") 12 | gvhg 13 | 14 | julia> atbash_encode("abcdefghijklmnopqrstuvwxyz") 15 | zyxwvutsrqponmlkjihgfedcba 16 | 17 | julia> atbash_encode("hello") 18 | svool 19 | 20 | ``` 21 | 22 | # Algorithm: 23 | 24 | ```julia 25 | 26 | for r in input 27 | part *= xform(r) 28 | if length(part) >= 5 29 | push!(parts, part) 30 | part = "" 31 | end 32 | end 33 | if part != "" 34 | push!(parts, part) 35 | end 36 | return join(parts, " ") 37 | 38 | ``` 39 | 40 | # References: 41 | https://en.wikipedia.org/wiki/Atbash 42 | 43 | ``` 44 | 45 | # Contributed by:- [Ihjass Thasbekha](https://github.com/Ihjass) 46 | """ 47 | function atbash_encode(input) 48 | input = replace(lowercase(input), reject_re => "") 49 | parts = [] 50 | part = "" 51 | for r in input 52 | part *= xform(r) 53 | if length(part) >= 5 54 | push!(parts, part) 55 | part = "" 56 | end 57 | end 58 | if !isempty(part) 59 | push!(parts, part) 60 | end 61 | return join(parts, " ") 62 | end 63 | reject_re = r"[^a-z\d]+" 64 | xform(r) = (r >= 'a' && r <= 'z') ? r = 25 - (r - 'a') + 'a' : r 65 | -------------------------------------------------------------------------------- /src/cipher/caesar.jl: -------------------------------------------------------------------------------- 1 | """ 2 | caesar(rot, s) 3 | 4 | Program to implement rotational cipher for the given sentence. A full description of the algorithm can be found on [wikipedia](https://en.wikipedia.org/wiki/Caesar_cipher) 5 | 6 | # Arguments: 7 | - `rot`: The number of rotations needed. 8 | - `s` : The sentence needed to rotate 9 | 10 | # Examples/Tests 11 | ```julia 12 | julia> caesar(13,"abcdefghijklmnopqrstuvwxyz") 13 | nopqrstuvwxyzabcdefghijklm 14 | 15 | julia> caesar(5,"omg") 16 | trl 17 | 18 | julia> caesar(0,"hello") 19 | hello 20 | 21 | ``` 22 | 23 | # Algorithm: 24 | 25 | ```julia 26 | 27 | if r >= 'a' && r <= 'z' 28 | v = ((r - 'a') + rot) % 26 29 | return v + 'a' 30 | end 31 | if r >= 'A' && r <= 'Z' 32 | v = ((r - 'A') + rot) % 26 33 | return v + 'A' 34 | end 35 | return r 36 | 37 | ``` 38 | 39 | # References: 40 | https://en.wikipedia.org/wiki/Caesar_cipher 41 | 42 | ``` 43 | 44 | # Contributed by:- [Ihjass Thasbekha](https://github.com/Ihjass) 45 | """ 46 | function caesar(rot, s) 47 | rotate = function (r) 48 | if 'a' <= r <= 'z' 49 | v = ((r - 'a') + rot) % 26 50 | return v + 'a' 51 | end 52 | if 'A' <= r <= 'Z' 53 | v = ((r - 'A') + rot) % 26 54 | return v + 'A' 55 | end 56 | return r 57 | end 58 | if s isa Char 59 | return rotate(s) 60 | end 61 | result = "" 62 | for r in s 63 | result *= rotate(r) 64 | end 65 | return result 66 | end 67 | -------------------------------------------------------------------------------- /src/cipher/vigenere.jl: -------------------------------------------------------------------------------- 1 | LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 2 | 3 | """ 4 | encrypt_vigenere(text, key) 5 | 6 | Encrypts a plaintext message using the Vigenere cipher. 7 | 8 | # Arguments 9 | - `text`: the plaintext message to encrypt 10 | - `key`: the keyword used for encryption 11 | 12 | # Examples 13 | ```julia-repl 14 | julia> encrypt_vigenere("Hello, World!", "key") 15 | Rijvs, Uyvjn! 16 | ``` 17 | """ 18 | function encrypt_vigenere(text::String, key::String)::String 19 | global LETTERS 20 | encrypted = "" 21 | key_index = 1 22 | key = uppercase(key) 23 | for symbol in text 24 | num = findfirst(isequal(uppercase(symbol)), LETTERS) 25 | if !isnothing(num) 26 | num += findfirst(isequal(key[key_index]), LETTERS) - 1 27 | num %= length(LETTERS) 28 | num = num == 0 ? 26 : num 29 | encrypted *= 30 | isuppercase(symbol) ? LETTERS[num] : lowercase(LETTERS[num]) 31 | key_index = key_index == length(key) ? 1 : key_index + 1 32 | else 33 | encrypted *= symbol 34 | end 35 | end 36 | return encrypted 37 | end 38 | 39 | """ 40 | decrypt_vigenere(text, key) 41 | 42 | Decrypts a plaintext message using the Vigenere cipher. 43 | 44 | # Arguments 45 | - `text`: the ciphertext message to decrypt 46 | - `key`: the keyword used for decryption 47 | 48 | # Examples 49 | ```julia-repl 50 | julia> decrypt_vigenere("Rijvs, Uyvjn!", "key") 51 | Hello, World! 52 | ``` 53 | """ 54 | function decrypt_vigenere(text::String, key::String)::String 55 | global LETTERS 56 | key = uppercase(key) 57 | key_index = 1 58 | decrypted = "" 59 | for symbol in text 60 | num = findfirst(isequal(uppercase(symbol)), LETTERS) 61 | if !isnothing(num) 62 | num -= findfirst(isequal(key[key_index]), LETTERS) - 1 63 | num %= length(LETTERS) 64 | num = num <= 0 ? num + length(LETTERS) : num 65 | decrypted *= 66 | isuppercase(symbol) ? LETTERS[num] : lowercase(LETTERS[num]) 67 | key_index = key_index == length(key) ? 1 : key_index + 1 68 | else 69 | decrypted *= symbol 70 | end 71 | end 72 | return decrypted 73 | end 74 | 75 | println(encrypt_vigenere("QUICKBROWNFOX", "LAZYDOG")) 76 | -------------------------------------------------------------------------------- /src/conversions/Conversions.jl: -------------------------------------------------------------------------------- 1 | export Conversions 2 | """ 3 | Conversions 4 | 5 | `Conversions` are conversions of measurements in Julia 6 | """ 7 | module Conversions 8 | 9 | using TheAlgorithms 10 | 11 | export celsius_to_fahrenheit 12 | export celsius_to_kelvin 13 | export fahrenheit_to_celsius 14 | export fahrenheit_to_kelvin 15 | export kelvin_to_celsius 16 | export kelvin_to_fahrenheit 17 | export weight_conversion 18 | export length_conversion 19 | 20 | include("weight_conversion.jl") 21 | include("temparature_conversion.jl") 22 | include("length_conversion.jl") 23 | 24 | end 25 | -------------------------------------------------------------------------------- /src/conversions/length_conversion.jl: -------------------------------------------------------------------------------- 1 | """ 2 | function length_conversion(value, from_type, to_type) 3 | 4 | A function that converts a value from a measurement unit to another one 5 | 6 | Accepted units are: millimeter(s), centimeter(s), meter(s), kilometer(s), 7 | inch(es), feet, foot, yard(s), mile(s). Abbreviations are also supported. 8 | 9 | # Examples/Tests (optional but recommended) 10 | ```julia 11 | length_conversion(10, "METERS", "cm") 12 | length_conversion(12345, "yards", "FEET") 13 | ``` 14 | 15 | Because the algorithm converts values to meters, and from meters to the final type, 16 | some imperial system units may have errors: 17 | length_conversion(1, "yards", "FEET") returns 3.000000096, intead of 3. 18 | 19 | # Contributed by:- [Fernanda Kawasaki](https://github.com/fernandakawasaki) 20 | """ 21 | 22 | # Lookup table that returns conversion of 1 unit of type to meters 23 | METER_CONVERSION = Dict{String,Float64}( 24 | "mm" => 0.001, 25 | "cm" => 0.01, 26 | "m" => 1, 27 | "km" => 1000, 28 | "in" => 0.0254, 29 | "ft" => 0.3048, 30 | "yd" => 0.9144, 31 | "mi" => 1609.34, 32 | ) 33 | 34 | # Lookup table that returns the conversion of 1 meter to type 35 | TYPE_CONVERSION = Dict{String,Float64}( 36 | "mm" => 1000, 37 | "cm" => 100, 38 | "m" => 1, 39 | "km" => 0.001, 40 | "in" => 39.3701, 41 | "ft" => 3.28084, 42 | "yd" => 1.09361, 43 | "mi" => 0.000621371, 44 | ) 45 | 46 | NAME_CONVERSION = Dict{String,String}( 47 | "millimeter" => "mm", 48 | "millimeters" => "mm", 49 | "centimeter" => "cm", 50 | "centimeters" => "cm", 51 | "meter" => "m", 52 | "meters" => "m", 53 | "kilometer" => "km", 54 | "kilometers" => "km", 55 | "inch" => "in", 56 | "inches" => "in", 57 | "feet" => "ft", 58 | "foot" => "ft", 59 | "yard" => "yd", 60 | "yards" => "yd", 61 | "mile" => "mi", 62 | "miles" => "mi", 63 | ) 64 | 65 | function normalize_type(type) 66 | l_type = lowercase(type) 67 | if !haskey(METER_CONVERSION, l_type) 68 | if !haskey(NAME_CONVERSION, l_type) 69 | throw( 70 | error( 71 | "Invalid 'type' value: $(type)\n", 72 | "Supported values are: $(keys(NAME_CONVERSION))\n", 73 | "Supported abbreviations are: $(keys(METER_CONVERSION))\n", 74 | ), 75 | ) 76 | end 77 | return NAME_CONVERSION[l_type] 78 | end 79 | return l_type 80 | end 81 | 82 | function length_conversion(value, from_type, to_type) 83 | from_type_norm = normalize_type(from_type) 84 | to_type_norm = normalize_type(to_type) 85 | value_in_meters = value * METER_CONVERSION[from_type_norm] 86 | return value_in_meters * TYPE_CONVERSION[to_type_norm] 87 | end 88 | -------------------------------------------------------------------------------- /src/conversions/weight_conversion.jl: -------------------------------------------------------------------------------- 1 | KILOGRAM_CHART = Dict{String,Float64}( 2 | "kilogram" => 1.0, 3 | "gram" => 10^3, 4 | "milligram" => 10^6, 5 | "metric-ton" => 10^-3, 6 | "long-ton" => 0.0009842073, 7 | "short-ton" => 0.0011023122, 8 | "pound" => 2.2046244202, 9 | "ounce" => 35.273990723, 10 | "carrat" => 5000.0, 11 | "atomic-mass-unit" => 6.022136652e26, 12 | ) 13 | 14 | WEIGHT_TYPE_CHART = Dict{String,Float64}( 15 | "kilogram" => 1.0, 16 | "gram" => 10^-3, 17 | "milligram" => 10^-6, 18 | "metric-ton" => 10^3, 19 | "long-ton" => 1016.04608, 20 | "short-ton" => 907.184, 21 | "pound" => 0.453592, 22 | "ounce" => 0.0283495, 23 | "carrat" => 0.0002, 24 | "atomic-mass-unit" => 1.660540199e-27, 25 | ) 26 | 27 | function weight_conversion(value, from_type, to_type) 28 | if !haskey(KILOGRAM_CHART, to_type) || !haskey(WEIGHT_TYPE_CHART, from_type) 29 | throw( 30 | error( 31 | "Invalid 'from_type' or 'to_type' value: $(from_type), $(to_type)\n", 32 | "Supported values are: $(WEIGHT_TYPE_CHART)", 33 | ), 34 | ) 35 | end 36 | return value * KILOGRAM_CHART[to_type] * WEIGHT_TYPE_CHART[from_type] 37 | end 38 | -------------------------------------------------------------------------------- /src/data_structures/DataStructure.jl: -------------------------------------------------------------------------------- 1 | export DataStructure 2 | """ 3 | DataStructure 4 | 5 | `DataStructure` algorithms. 6 | """ 7 | module DataStructure 8 | 9 | using TheAlgorithms 10 | 11 | export AbstractBinarySearchTree_arr 12 | export AbstractBinaryTree 13 | export AbstractBinaryTree_arr 14 | export BinaryHeap 15 | export BinaryTree 16 | export ch 17 | export depth 18 | export DisjointSet 19 | export find 20 | export height 21 | export insert! 22 | export isleaf 23 | export left 24 | export MaxHeap 25 | export merge! 26 | export MinHeap 27 | export right 28 | export set_ch 29 | export Splay 30 | export top 31 | export LinkedList 32 | export FenwickTree 33 | 34 | include("binary_heap.jl") 35 | include("binary_tree/splay.jl") 36 | include("disjoint_set/disjoint_set.jl") 37 | include("linked_list.jl") 38 | include("fenwick_tree.jl") 39 | 40 | end 41 | -------------------------------------------------------------------------------- /src/data_structures/binary_tree/basic_binary_search_tree.jl: -------------------------------------------------------------------------------- 1 | include("basic_binary_tree.jl") 2 | """ 3 | array-based binary search tree 4 | left tree values < root value < right tree values 5 | """ 6 | abstract type AbstractBinarySearchTree_arr <: AbstractBinaryTree_arr end 7 | function Base.findfirst( 8 | value::T, 9 | tree::Tree, 10 | place::Int = tree.root, 11 | ) where {T,Tree<:AbstractBinarySearchTree_arr} 12 | if tree.val[place] == value 13 | return place 14 | elseif tree.val[place] > value 15 | if tree.lch[place] == 0 16 | return 0 17 | end 18 | return findfirst(value, tree, tree.lch[place]) 19 | else 20 | if tree.rch[place] == 0 21 | return 0 22 | end 23 | return findfirst(value, tree, tree.rch[place]) 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /src/data_structures/binary_tree/basic_binary_tree.jl: -------------------------------------------------------------------------------- 1 | abstract type AbstractBinaryTree end 2 | """ 3 | array-based binary tree 4 | """ 5 | abstract type AbstractBinaryTree_arr <: AbstractBinaryTree end 6 | mutable struct BinaryTree{T} <: AbstractBinaryTree_arr where {T} 7 | n::Int 8 | root::Int 9 | par::Vector{Int} 10 | lch::Vector{Int} 11 | rch::Vector{Int} 12 | val::Vector{T} 13 | end 14 | function BinaryTree{T}(size::Int, rootval::T) where {T} 15 | x = BinaryTree( 16 | 1, 17 | 1, 18 | zeros(T, size), 19 | zeros(T, size), 20 | zeros(T, size), 21 | Vector{T}(undef, size), 22 | ) 23 | x.val[1] = rootval 24 | return x 25 | end 26 | 27 | function Base.insert!(tree::BinaryTree, from::Int, value, place::Bool) 28 | tree.n += 1 29 | tree.par[tree.n] = from 30 | if place 31 | tree.rch[from] = tree.n 32 | else 33 | tree.lch[from] = tree.n 34 | end 35 | return tree.val[tree.n] = value 36 | end 37 | 38 | function Base.insert!(tree::BinaryTree, from::Int, value) 39 | if tree.lch[from] == 0 40 | insert!(tree, from, value, false) 41 | elseif tree.rch[from] == 0 42 | insert!(tree, from, value, true) 43 | else 44 | return false 45 | end 46 | return true 47 | end 48 | 49 | # for AbstractBinaryTree_arr 50 | function isleaf( 51 | tree::Tree, 52 | from::Int, 53 | )::Bool where {Tree<:AbstractBinaryTree_arr} 54 | return tree.lch[from] == 0 && tree.rch[from] == 0 55 | end 56 | 57 | function ch( 58 | tree::Tree, 59 | from::Int, 60 | select::Bool, 61 | ) where {Tree<:AbstractBinaryTree_arr} 62 | if select 63 | return tree.rch[from] 64 | else 65 | return tree.lch[from] 66 | end 67 | end 68 | 69 | function set_ch( 70 | tree::Tree, 71 | from::Int, 72 | select::Bool, 73 | value::T, 74 | ) where {Tree<:AbstractBinaryTree_arr,T} 75 | if select 76 | tree.rch[from] = value 77 | else 78 | tree.lch[from] = value 79 | end 80 | end 81 | 82 | function height( 83 | tree::Tree, 84 | from::Int = tree.root, 85 | ) where {Tree<:AbstractBinaryTree_arr} 86 | count = 0 87 | if tree.lch[from] != 0 88 | count = height(tree, tree.lch[from]) + 1 89 | end 90 | if tree.rch[from] != 0 91 | count = max(height(tree, tree.rch[from]) + 1, count) 92 | end 93 | return count 94 | end 95 | 96 | function depth(tree::Tree, from::Int) where {Tree<:AbstractBinaryTree_arr} 97 | count = 0 98 | while from != tree.root 99 | count += 1 100 | from = tree.par[from] 101 | end 102 | return count 103 | end 104 | 105 | function left( 106 | tree::Tree, 107 | from::Int = tree.root, 108 | ) where {Tree<:AbstractBinaryTree_arr} 109 | if tree.lch[from] == 0 110 | return from 111 | else 112 | return left(tree, tree.lch[from]) 113 | end 114 | end 115 | 116 | function right( 117 | tree::Tree, 118 | from::Int = tree.root, 119 | ) where {Tree<:AbstractBinaryTree_arr} 120 | if tree.rch[from] == 0 121 | return from 122 | else 123 | return right(tree, tree.rch[from]) 124 | end 125 | end 126 | -------------------------------------------------------------------------------- /src/data_structures/binary_tree/splay.jl: -------------------------------------------------------------------------------- 1 | include("basic_binary_search_tree.jl") 2 | mutable struct Splay{T} <: AbstractBinarySearchTree_arr where {T} 3 | n::Int 4 | root::Int 5 | par::Vector{Int} 6 | lch::Vector{Int} 7 | rch::Vector{Int} 8 | val::Vector{T} 9 | 10 | cnt::Vector{Int} 11 | size::Vector{Int} 12 | end 13 | -------------------------------------------------------------------------------- /src/data_structures/disjoint_set/disjoint_set.jl: -------------------------------------------------------------------------------- 1 | """ 2 | This can contain a maximum of `length(par)` parenting-relations 3 | par is an array of `Int`, which is the index of the parent node. 4 | """ 5 | mutable struct DisjointSet 6 | par::Vector{Int} 7 | function DisjointSet(size) 8 | x = [i for i in 1:size] 9 | return new(x) 10 | end 11 | end 12 | 13 | """ 14 | Find the ancestor of node `x`. 15 | """ 16 | function find(set::DisjointSet, x::Int)::Int 17 | if set.par[x] == x 18 | return x 19 | else 20 | return set.par[x] = find(set, set.par[x]) 21 | end 22 | end 23 | 24 | function Base.merge!(set::DisjointSet, x::Int, y::Int) 25 | x = find(set, x) 26 | y = find(set, y) 27 | return set.par[x] = y 28 | end 29 | -------------------------------------------------------------------------------- /src/dynamic_programming/DynamicProgramming.jl: -------------------------------------------------------------------------------- 1 | export DynamicProgramming 2 | 3 | """ 4 | DynamicProgramming 5 | 6 | `DynamicProgramming` algorithms in Julia. 7 | """ 8 | module DynamicProgramming 9 | 10 | using TheAlgorithms 11 | 12 | export coin_change 13 | include("coin_change.jl") 14 | 15 | end 16 | -------------------------------------------------------------------------------- /src/dynamic_programming/coin_change.jl: -------------------------------------------------------------------------------- 1 | """ 2 | coin_change(coins::Vector{Int}, amount::Int) 3 | 4 | Given a vector `coins` of coin values, calculates the minimum number of coins that sums to `amount`. 5 | It's considered that a unlimited number of coins for each value is available. 6 | 7 | # Arguments: 8 | - `coins`: the coins values available 9 | - `amount`: the total amount that need to be summed to 10 | 11 | # Examples 12 | ```jldoctest 13 | julia> n_coins, coins = coin_change([1, 3, 4, 7], 13); 14 | 15 | julia> n_coins 16 | 3 17 | 18 | julia> coins 19 | 3-element Vector{Int64}: 20 | 3 21 | 3 22 | 7 23 | 24 | julia> n_coins, coins = coin_change([2, 4, 6], 23) 25 | (-1, Int64[]) 26 | 27 | julia> n_coins 28 | -1 29 | 30 | julia> coins 31 | Int64[] 32 | ``` 33 | 34 | # Contributors: 35 | - [Gabriel Soares](https://github.com/gosoares) 36 | """ 37 | function coin_change(coins::Vector{Int}, amount::Int) 38 | _INF = typemax(Int) - 1 39 | # S[v]: minimum number of coins that sums to `v-1`, `_INF` meaning its not possible 40 | S::Vector{Int} = fill(_INF, amount + 1) 41 | # L[v]: last coin used to sum to `v-1` 42 | L = Vector{Int}(undef, amount + 1) 43 | 44 | S[1] = 0 # 0 coins are used to sum to 0 45 | for value in 1:amount 46 | v = value + 1 # index for the vectors 47 | for coin in coins 48 | coin > value && continue 49 | 50 | if (1 + S[v-coin] < S[v]) 51 | S[v] = 1 + S[v-coin] 52 | L[v] = coin 53 | end 54 | end 55 | end 56 | 57 | S[end] == _INF && return -1, Int[] # not possible to sum to `amount` with these coins 58 | 59 | coins_used = Int[] 60 | v = lastindex(L) 61 | while v > 1 62 | push!(coins_used, L[v]) 63 | v -= L[v] 64 | end 65 | 66 | return S[end], coins_used 67 | end 68 | -------------------------------------------------------------------------------- /src/graph/Graph.jl: -------------------------------------------------------------------------------- 1 | export Graph 2 | 3 | """ 4 | Graph 5 | 6 | `Graph` related algorithms in Julia. 7 | """ 8 | module Graph 9 | 10 | using TheAlgorithms 11 | using TheAlgorithms.DataStructure 12 | using DataStructures 13 | 14 | export dijkstra 15 | export get_dijkstra_path 16 | export bfs 17 | export dfs 18 | export bellman_ford 19 | 20 | include("dijkstra.jl") 21 | include("bfs.jl") 22 | include("dfs.jl") 23 | include("bellman_ford.jl") 24 | 25 | end 26 | -------------------------------------------------------------------------------- /src/graph/bellman_ford.jl: -------------------------------------------------------------------------------- 1 | """ 2 | bellman_ford(graph::Vector{Tuple{Int, Int, Int}}, source::Int) 3 | 4 | The Bellman-Ford algorithm is an algorithm which computes the shortest paths from a single source vertex to all other vertices in a weighted graph. 5 | It is slower than Dijkstra's algorithm, which solves the same problem, but it is capable of handling graphs with negative edge weights. 6 | Instead of greedily performing the relaxation on the vertices, Bellman-Ford simply relaxes all edges, and does this |V|-1 times. 7 | 8 | # Arguments: 9 | - `graph`: a directed, weighted graph 10 | - `source`: the source vertex from which to begin the traversal 11 | 12 | # Example 13 | ```jldoctest 14 | graph = [ 15 | (1, 2, 4), (1, 3, 2), 16 | (2, 3, 3), (2, 4, 2), (2, 5, 3), 17 | (3, 2, 1), (3, 4, 4), (3, 5, 5), 18 | (5, 4, -5) 19 | ] 20 | bellman_ford(graph, 1) 21 | 22 | # output 23 | 24 | 5-element Vector{Int64}: 25 | 0 26 | 3 27 | 2 28 | 1 29 | 6 30 | ``` 31 | 32 | Contributed by: [Yannick Brenning](https://github.com/ybrenning) 33 | """ 34 | function bellman_ford(graph::Vector{Tuple{Int,Int,Int}}, source::Int = 1) 35 | vertices = maximum(graph)[1] 36 | distance = [typemax(Int) for _ in 1:vertices] 37 | distance[source] = 0 38 | 39 | # Relax the edges |V| - 1 times 40 | for _ in 1:vertices 41 | for edge in graph 42 | src, dest, weight = edge[1], edge[2], edge[3] 43 | if distance[src] + weight < distance[dest] 44 | distance[dest] = distance[src] + weight 45 | end 46 | end 47 | end 48 | 49 | # Detect negative weight cycle 50 | for edge in graph 51 | src, dest, weight = edge[1], edge[2], edge[3] 52 | if distance[src] + weight < distance[dest] 53 | throw(ErrorException("Graph contains a negative weight cycle")) 54 | end 55 | end 56 | 57 | return distance 58 | end 59 | -------------------------------------------------------------------------------- /src/graph/bfs.jl: -------------------------------------------------------------------------------- 1 | """ 2 | bfs(graph:Vector{Vector{Int}}, source::Int = 1) 3 | 4 | Depth-first search is an algorithm for traversing or searching tree or graph data structures. 5 | The algorithm starts at a given vertex and explores all vertices at the present depth before moving to the next "level". 6 | This implementation is for educational purposes only, so it simply prints out the vertices in the order that they were traversed. 7 | 8 | # Arguments: 9 | - `graph`: a directed, unweighted graph 10 | - `source`: the source vertex from which to begin the traversal 11 | 12 | # Example 13 | ```jldoctest 14 | graph = [ 15 | [2, 3, 6], 16 | [3, 4], 17 | [4], 18 | [1, 2, 5], 19 | [2], 20 | [1, 5] 21 | ] 22 | TheAlgorithms.Graph.bfs(graph, 4) 23 | 24 | # output 25 | 26 | 6-element Vector{Int64}: 27 | 4 28 | 1 29 | 2 30 | 5 31 | 3 32 | 6 33 | ``` 34 | 35 | Contributed by: [Yannick Brenning](https://github.com/ybrenning) 36 | """ 37 | function bfs(graph::Vector{Vector{Int}}, source::Int = 1) 38 | # Use a boolean "visited" array to avoid processing a vertex more than once 39 | visited = [false for _ in 1:length(graph)] 40 | result = Vector{Int}() 41 | 42 | queue = Queue{Int}() 43 | enqueue!(queue, source) 44 | 45 | visited[source] = true 46 | 47 | while length(queue) > 0 48 | curr_v = dequeue!(queue) 49 | push!(result, curr_v) 50 | 51 | # Add every unvisited target to the end of the queue 52 | for i in 1:length(graph[curr_v]) 53 | if !visited[graph[curr_v][i]] 54 | enqueue!(queue, graph[curr_v][i]) 55 | visited[graph[curr_v][i]] = true 56 | end 57 | end 58 | end 59 | 60 | return result 61 | end 62 | -------------------------------------------------------------------------------- /src/graph/dfs.jl: -------------------------------------------------------------------------------- 1 | """ 2 | dfs(graph::Vector{Vector{Int}}, source::Int) 3 | 4 | Depth-first search is an algorithm for traversing or searching tree or graph data structures. 5 | The algorithm starts at a given vertex and explores as far as possible along each branch before backtracking. 6 | This implementation is for educational purposes only, so it simply prints out the vertices in the order that they were traversed. 7 | 8 | # Arguments: 9 | - `graph`: a directed, unweighted graph 10 | - `source`: the source vertex from which to begin the traversal 11 | 12 | # Example 13 | ```jldoctest 14 | graph = [ 15 | [2, 3, 6], 16 | [3, 4], 17 | [4], 18 | [1, 2, 5], 19 | [2], 20 | [1, 5] 21 | ] 22 | dfs(graph, 6) 23 | 24 | # output 25 | 26 | 6-element Vector{Int64}: 27 | 6 28 | 5 29 | 2 30 | 4 31 | 3 32 | 1 33 | ``` 34 | 35 | Contributed by: [Yannick Brenning](https://github.com/ybrenning) 36 | """ 37 | function dfs(graph::Vector{Vector{Int}}, source::Int = 1) 38 | # Use a boolean "visited" array to avoid processing a vertex more than once 39 | visited = [false for _ in 1:length(graph)] 40 | result = Vector{Int}() 41 | 42 | stack = Stack{Int}() 43 | push!(stack, source) 44 | 45 | visited[source] = true 46 | 47 | while length(stack) > 0 48 | curr_v = pop!(stack) 49 | push!(result, curr_v) 50 | 51 | # Add every unvisited target to the top of the stack 52 | for i in 1:length(graph[curr_v]) 53 | if !visited[graph[curr_v][i]] 54 | push!(stack, graph[curr_v][i]) 55 | visited[graph[curr_v][i]] = true 56 | end 57 | end 58 | end 59 | return result 60 | end 61 | -------------------------------------------------------------------------------- /src/graph/dijkstra.jl: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | dijkstra(graph::Vector{Vector{Tuple{Int,Int}}}, source::Int) 4 | 5 | Given a directed graph with weights on the arcs and a source vertex, the dijkstra algorithm 6 | calculates the distance from the source to all other vertices, and the solution tree associated 7 | with those distances. The solution tree is given by a vector `prev` which stores the source of the 8 | arc that arrives at each vertex. By definition: distance[source] = prev[source] = 0. If a vertex v 9 | is not reachable from the source, then distance[v] = prev[v] = -1. 10 | 11 | # Arguments: 12 | - `graph`: a directed graph with weights on the arcs 13 | - `source`: the source vertex from which the distances will be calculated 14 | 15 | # Example 16 | ```jldoctest 17 | graph = [ 18 | [(2, 8), (3, 6), (4, 4)], 19 | [(3, 1), (5, 5)], 20 | [(5, 4)], 21 | [(2, 3), (5, 9)], 22 | [(1, 2), (3, 2), (4, 5)], 23 | [(1, 1), (4, 3)], 24 | ] 25 | distances, prev = dijkstra(graph, 1) 26 | 27 | println("v | dist | path") 28 | for v in eachindex(graph) 29 | distance = distances[v] == -1 ? " NR" : lpad(distances[v], 4) # NR: Non Reachable 30 | path = join(get_dijkstra_path(prev, v), " -> ") 31 | println("\$v | \$distance | \$path") 32 | end 33 | 34 | # output 35 | 36 | v | dist | path 37 | 1 | 0 | 1 38 | 2 | 7 | 1 -> 4 -> 2 39 | 3 | 6 | 1 -> 3 40 | 4 | 4 | 1 -> 4 41 | 5 | 10 | 1 -> 3 -> 5 42 | 6 | NR | 43 | ``` 44 | 45 | Contributed By: [Gabriel Soares](https://github.com/gosoares) 46 | """ 47 | function dijkstra(graph::Vector{Vector{Tuple{Int,Int}}}, source::Int) 48 | # V = {1, 2, ..., length(graph)}: set of vertices 49 | # A = {(i, j): i and j are adjacents; i,j in V}: set of arcs 50 | # graph[i] = {(j, distance[i to j]): (i, j) in A}: adjacency list 51 | 52 | # distance[j] min distance from source to j 53 | distance::Vector{Int} = fill(typemax(Int), length(graph)) 54 | prev::Vector{Int} = fill(-1, length(graph)) 55 | visited::Vector{Bool} = falses(length(graph)) 56 | pq = MinHeap{Tuple{Int,Int}}() # (distance, vertex) | priority queue 57 | 58 | distance[source] = 0 59 | prev[source] = 0 # to mark the source 60 | push!(pq, (0, source)) 61 | 62 | while !isempty(pq) 63 | # get the vertex that was not yet visited and the distance from the source is minimal 64 | dv, v = pop!(pq) 65 | visited[v] && continue 66 | visited[v] = true 67 | 68 | for (u, dvu) in graph[v] # dvu: distance from v to u 69 | # check if u can be reached through v with a smaller distance than the current 70 | if !visited[u] && dv + dvu < distance[u] 71 | distance[u] = dv + dvu 72 | prev[u] = v 73 | push!(pq, (distance[u], u)) 74 | end 75 | end 76 | end 77 | 78 | replace!(distance, typemax(Int) => -1) # distance[v] = -1 means that v is not reachable from source 79 | return distance, prev 80 | end 81 | 82 | """ 83 | get_dijkstra_path(tree::Vector{Int}, dest::Int) 84 | 85 | Given a solution `tree` from the [`dijkstra`](@ref) algorithm, extract the path from the source to 86 | `dest`, including them. 87 | 88 | # Arguments: 89 | - `tree`: solution tree from the [`dijkstra`](@ref) algorithm 90 | - `dest`: path's destionation vertex 91 | """ 92 | function get_dijkstra_path(tree::Vector{Int}, dest::Int) 93 | path = Int[] 94 | tree[dest] == -1 && return path # not reachable 95 | 96 | while dest != 0 97 | push!(path, dest) 98 | dest = tree[dest] 99 | end 100 | return reverse!(path) 101 | end 102 | -------------------------------------------------------------------------------- /src/knapsack/KnapSack.jl: -------------------------------------------------------------------------------- 1 | """ 2 | KnapSack 3 | 4 | `KnapSack` algorithms. 5 | """ 6 | 7 | module KnapSack 8 | 9 | export complete_pack! 10 | export zero_one_pack! 11 | 12 | include("dynamic_programming.jl") 13 | include("greedy_algorithm.jl") 14 | 15 | end 16 | -------------------------------------------------------------------------------- /src/knapsack/dynamic_programming.jl: -------------------------------------------------------------------------------- 1 | """ 2 | zero_one_pack!(capacity::N, weights::V, values::V, dp::V) where {N <: Number,V <: AbstractVector} 3 | This does 0-1 (each item can be chosen only once) knapsack : 4 | pack capacity = capacity 5 | weight of each item = weights 6 | value of each item = values 7 | dp array is what the function works on 8 | It returns the ans (dp[capacity]) 9 | ``` 10 | julia> dp=zeros(Int,30) 11 | julia> zero_one_pack!(20,[1,3,11],[2,5,30],dp) 12 | 37 13 | ``` 14 | """ 15 | function zero_one_pack!( 16 | capacity::N, 17 | weights::V, 18 | values::V, 19 | dp::V, 20 | ) where {N<:Number,V<:AbstractVector} 21 | for i in 1:length(weights) 22 | j = capacity 23 | while j > weights[i] # reversed loop 24 | dp[j] = max(dp[j], dp[j-weights[i]] + values[i]) 25 | j -= 1 26 | end 27 | dp[weights[i]] = max(dp[weights[i]], values[i]) # dp[j]=max(dp[j],dp[0]+values[i]) 28 | end 29 | return dp[capacity] 30 | end 31 | 32 | """ 33 | This does complete/infinite (each item can be chosen infinite times) knapsack : 34 | pack capacity = capacity 35 | weight of each item = weights 36 | value of each item = values 37 | dp array is what the function works on 38 | It returns the ans (dp[capacity]) 39 | ``` 40 | julia> dp=zeros(Int,30) 41 | julia> complete_pack!(20,[1,2,9],[1,3,20],dp) 42 | 43 43 | ``` 44 | """ 45 | function complete_pack!( 46 | capacity::N, 47 | weights::V, 48 | values::V, 49 | dp::V, 50 | ) where {N<:Number,V<:AbstractVector} 51 | for i in 1:length(weights) 52 | dp[weights[i]] = max(dp[weights[i]], values[i]) # dp[j]=max(dp[j],dp[0]+values[i]) 53 | for j in (weights[i]+1):capacity 54 | dp[j] = max(dp[j], dp[j-weights[i]] + values[i]) 55 | end 56 | end 57 | return dp[capacity] 58 | end 59 | -------------------------------------------------------------------------------- /src/knapsack/greedy_algorithm.jl: -------------------------------------------------------------------------------- 1 | """ 2 | For greedy algorithm, it will take the element based on the optimal value in the array at each loop in the function 3 | 4 | This does 0-1 (each item can be chosen only once) knapsack : 5 | pack capacity = capacity 6 | weight of each item = weights 7 | value of each item = values 8 | 9 | Each loop the function will find the highest value in the array and check if the capacity is enough to store it, if enough then 10 | the value will be added into the total_max_value. 11 | After that the highest current value will be deleted. 12 | 13 | ``` 14 | julia> zero_one_pack!(20,[1,3,11],[2,5,30]) 15 | 37 16 | ``` 17 | """ 18 | function zero_one_pack!( 19 | capacity::N, 20 | weights::V, 21 | values::V, 22 | ) where {N<:Number,V<:AbstractVector} 23 | total_max_value = 0 24 | while capacity > 0 && (length(weights) != 0 || length(values) != 0) 25 | max_value, index = findmax(values) # get the highest value and index in the vector 26 | if capacity >= weights[index] 27 | total_max_value += max_value 28 | capacity -= weights[index] 29 | end 30 | splice!(values, index) 31 | splice!(weights, index) 32 | end 33 | return total_max_value 34 | end 35 | 36 | """ 37 | This does complete/infinite (each item can be chosen infinite times) knapsack : 38 | pack capacity = capacity 39 | weight of each item = weights 40 | value of each item = values 41 | 42 | Each loop the function will find the highest value in the array and check if the capacity is enough to store it, if enough then 43 | the value will be added into the total_max_value until the capacity cannot hold the weight of the highest current value. 44 | After that the highest current value will be deleted. 45 | 46 | ``` 47 | julia> complete_pack!(20,[1,2,9],[1,3,20]) 48 | 43 49 | ``` 50 | """ 51 | function complete_pack!( 52 | capacity::N, 53 | weights::V, 54 | values::V, 55 | ) where {N<:Number,V<:AbstractVector} 56 | total_max_value = 0 57 | while capacity > 0 && (length(weights) != 0 || length(values) != 0) 58 | max_value, index = findmax(values) 59 | while capacity >= weights[index] 60 | total_max_value += max_value 61 | capacity -= weights[index] 62 | end 63 | splice!(values, index) 64 | splice!(weights, index) 65 | end 66 | return total_max_value 67 | end 68 | -------------------------------------------------------------------------------- /src/longest_increasing_subsequence/LongSubSeq.jl: -------------------------------------------------------------------------------- 1 | """ 2 | LongSubSeq 3 | 4 | `LongSubSeq` for longest increasing subsequence algorithms. 5 | """ 6 | module LongSubSeq 7 | 8 | export lis 9 | include("dynamic_programming.jl") 10 | include("binary_search.jl") 11 | 12 | end 13 | -------------------------------------------------------------------------------- /src/longest_increasing_subsequence/binary_search.jl: -------------------------------------------------------------------------------- 1 | """ 2 | lis(arr::Array{<:Integer}, ::Val{:bs}) 3 | 4 | # Arguments: 5 | - `arr`: sequence of integers 6 | 7 | # Examples/Tests 8 | ```julia 9 | julia> lis([3, 10, 2, 1, 20], Val(:bs)) 10 | [3, 10, 20] 11 | 12 | julia> lis([2, 2, 3], Val(:bs)) 13 | [2, 3] 14 | ``` 15 | 16 | # Brief: 17 | Given a sequence of integers, the function finds the longest, strictly increasing, subsequence in that sequence. 18 | 19 | # For more information: 20 | https://cp-algorithms.com/sequences/longest_increasing_subsequence.html 21 | 22 | # Contributed by: 23 | - [Igor Malheiros](https://github.com/igormalheiros) 24 | """ 25 | 26 | function lis(arr::Array{T}, ::Val{:bs}) where {T<:Integer} 27 | len = length(arr) 28 | memo = ones(T, len) 29 | p = ones(Int, len) 30 | 31 | lis_arr = T[] 32 | 33 | len == 0 && return lis_arr # if `arr` is empty 34 | 35 | lis_len = 1 36 | memo[1] = arr[1] 37 | 38 | for i in 2:len 39 | # binary search in current `memo`, it uses @view and slicing for in-place verification 40 | p[i] = searchsortedfirst((@view memo[1:lis_len]), arr[i]) 41 | # if arr[i] is greater than the greatest element in `memo`, it increases `lis_len` 42 | lis_len = max(lis_len, p[i]) 43 | # updates `memo` 44 | memo[p[i]] = arr[i] 45 | end 46 | 47 | # Restoring 48 | last_pos = lis_len 49 | for i in len:-1:1 50 | if p[i] == last_pos 51 | pushfirst!(lis_arr, arr[i]) 52 | last_pos -= 1 53 | end 54 | end 55 | 56 | return lis_arr 57 | end 58 | -------------------------------------------------------------------------------- /src/longest_increasing_subsequence/dynamic_programming.jl: -------------------------------------------------------------------------------- 1 | """ 2 | lis(arr::Array{<:Integer}, ::Val{:dp}) 3 | 4 | # Arguments: 5 | - `arr`: sequence of integers 6 | 7 | # Examples/Tests 8 | ```julia 9 | julia> lis([3, 10, 2, 1, 20], Val(:dp)) 10 | [3, 10, 20] 11 | 12 | julia> lis([2, 2, 3], Val(:dp)) 13 | [2, 3] 14 | ``` 15 | 16 | # Brief: 17 | Given a sequence of integers, the function finds the longest, strictly increasing, subsequence in that sequence. 18 | 19 | # For more information: 20 | https://cp-algorithms.com/sequences/longest_increasing_subsequence.html 21 | 22 | # Contributed by: 23 | - [Igor Malheiros](https://github.com/igormalheiros) 24 | """ 25 | 26 | function lis(arr::Array{T}, ::Val{:dp}) where {T<:Integer} 27 | len = length(arr) 28 | memo = ones(Int, len) 29 | p = zeros(Int, len) 30 | 31 | lis_arr = T[] 32 | 33 | len == 0 && return lis_arr # if arr is empty 34 | 35 | lis_value = 1 36 | lis_pos = 1 37 | 38 | for i in 2:len 39 | for j in 1:i 40 | if arr[j] < arr[i] && memo[i] < memo[j] + 1 41 | memo[i] = memo[j] + 1 42 | p[i] = j 43 | end 44 | end 45 | # Updates the longest increasing value and position 46 | if memo[i] > lis_value 47 | lis_value = memo[i] 48 | lis_pos = i 49 | end 50 | end 51 | 52 | # Restoring 53 | while lis_pos != 0 54 | pushfirst!(lis_arr, arr[lis_pos]) 55 | lis_pos = p[lis_pos] 56 | end 57 | 58 | return lis_arr 59 | end 60 | -------------------------------------------------------------------------------- /src/machine_learning/ML.jl: -------------------------------------------------------------------------------- 1 | export ML 2 | """ 3 | ML 4 | 5 | `ML` machine learning algorithms. 6 | """ 7 | 8 | module ML 9 | 10 | using TheAlgorithms 11 | 12 | export KMeans 13 | include("k_means.jl") 14 | 15 | end 16 | -------------------------------------------------------------------------------- /src/machine_learning/linear_regression.jl: -------------------------------------------------------------------------------- 1 | using Statistics 2 | 3 | """ 4 | linear_regression(X::Matrix, Y::Matrix, alpha::Float64, iterations::Int64) 5 | 6 | Linear Regression Algorithm using Gradient Descent 7 | to find the best fit line for the data. 8 | 9 | Arguments : 10 | - X : Training data set of shape [m x n] 11 | - Y : Labels corresponding to the training data set of shape [m x 1] 12 | - alpha : Learning rate 13 | - iterations : Number of iterations to train 14 | Returns : 15 | - W : Weight vector 16 | - b : Bias 17 | - J_history : Cost Function History 18 | 19 | 20 | 21 | gradient_descent(W::Matrix, b, X::Matrix, Y::Matrix, alpha::Float64, num_iters::Int64) 22 | 23 | Performs gradient descent to learn W and b 24 | 25 | Arguments 26 | - `W`: matrix of weights 27 | - `b`: bias vector 28 | - `X`: matrix of features 29 | - `Y`: vector of labels 30 | - `alpha`: learning rate ( generally ranges from 0.01 to 0.00001 ) 31 | - `num_iters`: number of iterations to run gradient descent 32 | 33 | Returns: 34 | - `W`: matrix of weights 35 | - `b`: bias vector 36 | - `J_history`: vector of cost values after each iteration 37 | 38 | 39 | 40 | # Contributors:- [Navaneeth Sharma](https://github.com/Navaneeth-Sharma) 41 | """ 42 | 43 | function gradient_descent( 44 | W::Matrix, 45 | b, 46 | X::Matrix, 47 | Y::Matrix, 48 | alpha::Float64, 49 | num_iters::Int64, 50 | ) 51 | m = length(Y) 52 | J_history = [] 53 | for i in 1:num_iters 54 | W = W - alpha .* (1 / m) * (X * (X'W .+ b - Y')) 55 | b = b - alpha .* (1 / m) * sum((X'W .+ b - Y')) 56 | push!(J_history, 1 / 2m * sum((X'W .+ b - Y') .^ 2)) 57 | end 58 | return W, b, J_history 59 | end 60 | 61 | function linear_regression( 62 | X::Matrix, 63 | Y::Matrix, 64 | alpha::Float64, 65 | num_iters::Int64, 66 | ) 67 | W = zeros(1, size(X, 1)) 68 | b = 0 69 | W, b, J_history = gradient_descent(W, b, X, Y, alpha, num_iters) 70 | return W, b, J_history 71 | end 72 | 73 | # Function to predict the output of a given data vector 74 | predict(X::Matrix, W::Matrix, b::Float64) = X'W .+ b; 75 | 76 | # Example usage 77 | X = [1, 3, 2, 5, 7, 8, 8, 9, 10, 12] 78 | Y = [2, 4, 3, 6, 8, 9, 9, 10, 11, 13] 79 | 80 | X = reshape(X, 1, length(X)); 81 | Y = reshape(Y, 1, length(Y)); 82 | 83 | W, b, J_history = linear_regression(X, Y, 0.01, 1000); 84 | 85 | output = predict(X, W, b) 86 | println("The predicted is: $output") 87 | -------------------------------------------------------------------------------- /src/math/Math.jl: -------------------------------------------------------------------------------- 1 | export Math 2 | """ 3 | Math 4 | 5 | `Math` algorithms. 6 | """ 7 | module Math 8 | 9 | using TheAlgorithms 10 | 11 | export abs_max 12 | export abs_min 13 | export abs_val 14 | export aliquot_sum 15 | export amicable_pairs 16 | export area_circle 17 | export area_ellipse 18 | export area_heron_triangle 19 | export area_parallelogram 20 | export area_polygon 21 | export area_rectangle 22 | export area_regular_polygon 23 | export area_rhombus 24 | export area_square 25 | export area_trapezium 26 | export area_triangle 27 | export average_absolute_deviation 28 | export bab_sqrt 29 | export bin_length 30 | export bin_length_long 31 | export bin_length_short 32 | export catalan 33 | export ceil 34 | export collatz_sequence 35 | export combination 36 | export divisors 37 | export eratosthenes 38 | export euler_method 39 | export is_mersenne_prime 40 | export totient 41 | export factorial_iterative 42 | export factorial_recursive 43 | export fib_recursive 44 | export fib_recursive_memo 45 | export fib_iterative 46 | export floor 47 | export get_mersenne_primes 48 | export is_armstrong 49 | export line_length 50 | export krishnamurthy 51 | export mean 52 | export median 53 | export mode 54 | export monte_carlo_integration 55 | export num_divisors 56 | export partitions_recursive 57 | export prime_check 58 | export prime_factors 59 | export perfect_cube 60 | export perfect_number 61 | export perfect_square 62 | export permutation 63 | export prime_check 64 | export prime_factors 65 | export riemann_integration 66 | export runge_kutta_integration 67 | export simpsons_integration 68 | export sum_ap 69 | export sum_gp 70 | export sum_divisors 71 | export surfarea_cube 72 | export surfarea_cuboid 73 | export surfarea_sphere 74 | export trapazoidal_area 75 | export trapezoid_integration 76 | export verlet_integration 77 | export vol_cube 78 | export vol_cuboid 79 | export vol_cone 80 | export vol_right_circ_cone 81 | export vol_prism 82 | export vol_pyramid 83 | export vol_sphere 84 | export vol_circular_cylinder 85 | export least_common_multiple 86 | 87 | include("abs.jl") 88 | include("amicable_numbers.jl") 89 | include("area.jl") 90 | include("armstrong_number.jl") 91 | include("average_absolute_deviation.jl") 92 | include("average_mean.jl") 93 | include("average_median.jl") 94 | include("average_mode.jl") 95 | include("babylonian_sqrt.jl") 96 | include("binary_length.jl") 97 | include("catalan_number.jl") 98 | include("ceil.jl") # needed by average_median 99 | include("collatz_sequence.jl") 100 | include("combination.jl") 101 | include("divisors.jl") 102 | include("euler_method.jl") 103 | include("eulers_totient.jl") 104 | include("factorial.jl") 105 | include("fibonacci.jl") 106 | include("floor.jl") 107 | include("krishnamurthy_number.jl") 108 | include("line_length.jl") 109 | include("mersenne_prime.jl") 110 | include("monte_carlo_integration.jl") 111 | include("partitions.jl") 112 | include("perfect_cube.jl") 113 | include("perfect_number.jl") 114 | include("perfect_square.jl") 115 | include("permutation.jl") 116 | include("prime_check.jl") 117 | include("prime_factors.jl") 118 | include("riemann_integration.jl") 119 | include("runge_kutta_integration.jl") 120 | include("sieve_of_eratosthenes.jl") 121 | include("simpsons_integration.jl") 122 | include("sum_of_arithmetic_series.jl") 123 | include("sum_of_geometric_progression.jl") 124 | include("trapezoid_integration.jl") 125 | include("verlet.jl") 126 | include("volume.jl") 127 | include("least_common_multiple.jl") 128 | 129 | end 130 | -------------------------------------------------------------------------------- /src/math/abs.jl: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | abs_val(num) 4 | 5 | Program to find the absolute value of a number 6 | 7 | # Example 8 | ```julia 9 | abs_val(-100) # returns 100 10 | abs_val(0) # returns 0 11 | abs(123.1) # returns 123.1 12 | -1000 == abs_val(-1000) #returns false 13 | 1000 == abs_val(1000) #returns true 14 | ``` 15 | 16 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 17 | """ 18 | function abs_val(num::N) where {N<:Real} 19 | return num < 0 ? -num : num 20 | end 21 | 22 | """ 23 | abs_max(x) 24 | 25 | Program to find the max absolute value in a vector 26 | 27 | # Example 28 | ```julia 29 | abs_max([1,3,4]) # returns 4 30 | abs_max([-3,1,2]) # returns -3 31 | abs_max([-7,-3,6]) #returns -7 32 | ``` 33 | 34 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 35 | """ 36 | function abs_max(x::Vector{N}) where {N<:Real} 37 | _max = x[1] 38 | for i in x 39 | if abs(i) > abs(_max) 40 | _max = i 41 | end 42 | end 43 | return _max 44 | end 45 | 46 | """ 47 | abs_min(num) 48 | 49 | Program to find the min absolute value in a vector 50 | 51 | # Example 52 | ```julia 53 | abs_min([1,3,4]) # returns 1 54 | abs_min([-3,1,2]) # returns 1 55 | abs_min([-7,-3,6]) #returns -3 56 | ``` 57 | 58 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 59 | """ 60 | function abs_min(x::Vector{N}) where {N<:Real} 61 | _min = x[1] 62 | for i in x 63 | if abs(i) < abs(_min) 64 | _min = i 65 | end 66 | end 67 | return _min 68 | end 69 | -------------------------------------------------------------------------------- /src/math/amicable_numbers.jl: -------------------------------------------------------------------------------- 1 | """ 2 | amicable_pairs(n::Int) 3 | Two unique natural numbers are said to form an amicable pair when them sum of proper divisors of each is equal to the other number. 4 | 5 | # Input parameters: 6 | - `n` : Finds amicable pairs below n. 7 | 8 | # Examples/Tests: 9 | ```julia 10 | amicable_pairs(10) # returns [] 11 | amicable_pairs(400) # returns [220 => 284] 12 | amicable_pairs(2000) # returns [220 => 284, 1184 => 1210] 13 | amicable_pairs(-1) # throws DomainError 14 | ``` 15 | 16 | # Reference 17 | - https://mathworld.wolfram.com/AmicablePair.html 18 | 19 | Contributed by [Praneeth Jain](https://www.github.com/PraneethJain) 20 | """ 21 | function amicable_pairs(n::Int) 22 | n <= 0 && throw(DomainError("Input must be a postive integer")) 23 | 24 | # Find the sum of factors for every number from 1 to n 25 | factor_sums = zeros(Int, n) 26 | for i in 1:n 27 | for j in 2i:i:n 28 | factor_sums[j] += i 29 | end 30 | end 31 | 32 | result = Vector{Pair{Int,Int}}() 33 | for (x, y) in enumerate(factor_sums) 34 | # Factor sum of x is y 35 | if (y > 0 && x > y && n > y && factor_sums[y] == x) 36 | # Factor sum of y is x. x > y to avoid double counting. 37 | push!(result, y => x) 38 | end 39 | end 40 | return result 41 | end 42 | -------------------------------------------------------------------------------- /src/math/armstrong_number.jl: -------------------------------------------------------------------------------- 1 | """ 2 | is_armstrong(x) 3 | 4 | Program to check if a number is an [Armstrong/Narcissistic number](https://en.wikipedia.org/wiki/Narcissistic_number) in decimal system. 5 | 6 | Armstrong number is a number that is the sum of its own digits raised to the power of the number of digits. 7 | 8 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) 9 | 10 | A positive integer is called an Armstrong number (of order n) if 11 | 12 | `abcd... = a^n + b^n + c^n + d^n +....` 13 | """ 14 | function is_armstrong(x) 15 | # If the number is less than 0, then it is not a armstrong number. 16 | if x < 0 17 | return false 18 | elseif x == 0 19 | return true 20 | else 21 | # Finding the total number of digits in the number 22 | length = Int(floor(log10(x) + 1)) 23 | result = 0 24 | temp = x 25 | for i in 1:length 26 | val = temp % 10 27 | # Finding each digit raised to the power total digit and add it to the total sum 28 | result = result + Int(trunc(val))^length 29 | temp = temp / 10 30 | end 31 | return x == result ? true : false 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /src/math/average_absolute_deviation.jl: -------------------------------------------------------------------------------- 1 | """ 2 | average_absolute_deviation(numbers) 3 | The average absolute deviation of a data set is the average of the absolute deviations from the mean. 4 | It is a measure of statistical dispersion or variability. 5 | 6 | # Input parameters: 7 | - `numbers` : The numbers to find the average absolute deviation of. 8 | 9 | # Examples/Tests: 10 | ```julia 11 | average_absolute_deviation([1, 2, 3, 4, 5]) # returns 1.2 12 | average_absolute_deviation([0]) # returns 0.0 13 | average_absolute_deviation([5.5, 64.3, 100.4]) # returns 34.16 14 | ``` 15 | 16 | # Reference 17 | - https://mathworld.wolfram.com/AverageAbsoluteDeviation.html 18 | 19 | Contributed by [Praneeth Jain](https://www.github.com/PraneethJain) 20 | """ 21 | function average_absolute_deviation(numbers::Vector{T}) where {T<:Number} 22 | len = length(numbers) 23 | mean = sum(numbers) / len 24 | return round(sum(abs(num - mean) for num in numbers) / len, digits = 2) 25 | end 26 | -------------------------------------------------------------------------------- /src/math/average_mean.jl: -------------------------------------------------------------------------------- 1 | """ 2 | mean(nums) 3 | 4 | Find mean of a vector of numbers 5 | 6 | # Example 7 | 8 | ```julia 9 | mean([3, 6, 9, 12, 15, 18, 21]) # returns 12.0 10 | mean([5, 10, 15, 20, 25, 30, 35]) # returns 20.0 11 | mean([1, 2, 3, 4, 5, 6, 7, 8]) # returns 4.5 12 | ``` 13 | 14 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 15 | """ 16 | function mean(nums::Vector{T}) where {T<:Number} 17 | return sum(nums) / length(nums) 18 | end 19 | -------------------------------------------------------------------------------- /src/math/average_median.jl: -------------------------------------------------------------------------------- 1 | """ 2 | median(nums) 3 | 4 | Finds median of a vector of numbers 5 | 6 | ## Example 7 | 8 | ```julia 9 | median([2,1,3,4]) # returns 2.5 10 | median([2, 70, 6, 50, 20, 8, 4]) # returns 8 11 | median([0]) # returns 0 12 | ``` 13 | 14 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 15 | """ 16 | function median(nums::Vector{T}) where {T<:Number} 17 | sorted = sort(nums) 18 | len = length(sorted) 19 | mid_index = div(len, 2) 20 | return if len % 2 == 0 21 | (sorted[mid_index+1] + sorted[mid_index]) / 2 22 | else 23 | sorted[mid_index+1] 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /src/math/average_mode.jl: -------------------------------------------------------------------------------- 1 | """ 2 | mode(nums) 3 | 4 | Finds mode of a vector of numbers 5 | 6 | # Example 7 | 8 | ```julia 9 | mode([2, 3, 4, 5, 3, 4, 2, 5, 2, 2, 4, 2, 2, 2]) # returns [2] 10 | mode([3, 4, 5, 3, 4, 2, 5, 2, 2, 4, 4, 2, 2, 2]) # returns [2] 11 | mode([3, 4, 5, 3, 4, 2, 5, 2, 2, 4, 4, 4, 2, 2, 4, 2]) # returns [2, 4] 12 | mode(["x", "y", "y", "z"]) # returns ["y"] 13 | mode(["x", "x" , "y", "y", "z"]) # returns ["x", "y"] 14 | ``` 15 | 16 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) 17 | """ 18 | function mode(nums) 19 | dict = Dict() # nums => Number of repetitions 20 | result = [] # Array of the modes so far 21 | max = 0 # Max of repetitions so far 22 | 23 | for i in nums 24 | # Add one to the dict[i] entry (create one if none) 25 | if i in keys(dict) 26 | dict[i] += 1 27 | else 28 | dict[i] = 1 29 | end 30 | # Result updated if no of repetitions of i >= max 31 | if dict[i] >= max 32 | if dict[i] > max 33 | empty!(result) 34 | max += 1 35 | end 36 | append!(result, [i]) 37 | end 38 | end 39 | 40 | return result 41 | end 42 | -------------------------------------------------------------------------------- /src/math/babylonian_sqrt.jl: -------------------------------------------------------------------------------- 1 | """ 2 | bab_sqrt(S::Real; tolerance = 1e-6, guess = nothing) 3 | 4 | The Babylonian Method of calculating a square root is a simple iterative method to determine square roots. A full description of the algorithm can be found on [Wikipedia](https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) 5 | 6 | # Arguments: 7 | - `S`: The number to calculate the square root for. 8 | 9 | # Positional Arguments 10 | - `tolerance`: How close the square of the square root needs to be from the input value. `abs(S - xn^2) < tolerance` 11 | - `guess`: The initial value to use for `xn` 12 | 13 | # Examples/Tests 14 | ```julia 15 | julia> bab_sqrt(100) 16 | 10.000000000107445 17 | 18 | julia> bab_sqrt(100, guess = 15) 19 | 10.000000000131072 20 | 21 | julia> bab_sqrt(π, guess = 1) 22 | 1.7724538555800293 23 | 24 | julia> bab_sqrt(π, guess = 1, tolerance = 2) 25 | 2.0707963267948966 26 | ``` 27 | 28 | # Algorithm: 29 | 30 | ```julia 31 | while tolerance <= abs(xn^2 - S) 32 | xn = (1 / 2) * (xn + S / xn) 33 | end 34 | ``` 35 | 36 | # References: 37 | [Methods of computing square roots](https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) 38 | 39 | ``` 40 | 41 | # Contributed by:- [Anson Biggs](https://ansonbiggs.com) 42 | """ 43 | function bab_sqrt(S::Real; tolerance = 1e-6, guess = nothing) 44 | 45 | # Can only calculate for positive numbers 46 | if S < 0 47 | throw(DomainError("Input must be greater than zero")) 48 | end 49 | 50 | xn = guess 51 | if xn === nothing 52 | xn = S / 2 53 | elseif xn < 0 54 | xn = abs(xn) 55 | end 56 | 57 | while tolerance <= abs(xn^2 - S) 58 | xn = (1 / 2) * (xn + S / xn) 59 | end 60 | return xn 61 | end 62 | -------------------------------------------------------------------------------- /src/math/binary_length.jl: -------------------------------------------------------------------------------- 1 | """ 2 | bin_length(binNum) 3 | Returns the length of binNum's binary representation. 4 | 5 | # Input parameters: 6 | - `binNum` : The number to find the binary length of. 7 | 8 | # Examples/Tests: 9 | ```julia 10 | bin_length(1) # returns 1 11 | bin_length(2) # returns 2 12 | bin_length(3) # returns 2 13 | bin_length(4) # returns 3 14 | bin_length(5) # returns 3 15 | bin_length(12) # returns 4 16 | bin_length(256) # returns 9 17 | bin_length(1024) # returns 11 18 | bin_length(-1) # throws DomainError 19 | ``` 20 | 21 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 22 | """ 23 | function bin_length(binNum::T) where {T<:Integer} 24 | binNum <= 0 && throw(DomainError("binNum must be a positive integer")) 25 | return floor(log2(binNum)) + 1 26 | end 27 | 28 | """ 29 | This algorithm features use of the OEIS entry A070939 - 30 | length of Binary Representation of n. It finds 31 | the length of any binary number and returns said length. 32 | 33 | https://oeis.org/A070939 34 | 35 | This function, as believed, is O(n) 36 | 37 | The idea follows that the sequence is dependent on 38 | a repeating pattern of 2. Short for sequence, seq is the 39 | number of digits required before an increase in finNum 40 | or final number as seen here with the first few 41 | iterations - i on the left, final number on the right: 42 | 43 | 1 : 1 44 | 2 : 2 45 | 3 : 2 46 | 4 : 3 47 | 5 : 3 48 | 6 : 3 49 | 7 : 3 50 | 8 : 4 51 | cont. 52 | 53 | As you can see, for every version of i, there is an appropriate 54 | modified number that only repeats for the sequence of the last 55 | doubled amount. 56 | 57 | #Contributions: 58 | Contributed by F35H: https://github.com/F35H 59 | """ 60 | function bin_length_long(binNum::T) where {T<:Integer} 61 | binNum <= 0 && throw(DomainError("binNum must be a positive integer")) 62 | 63 | finNum = 0 64 | seq = 1 65 | 66 | for i in 1:binNum 67 | if (i == seq) 68 | finNum += 1 69 | seq *= 2 70 | end 71 | end 72 | 73 | return finNum 74 | end 75 | 76 | """ 77 | This algorithm features use of the OEIS entry A070939 - 78 | length of Binary Representation of n. It finds 79 | the length of any binary number and returns said length. 80 | 81 | https://oeis.org/A070939 82 | 83 | This function, as believed, is O(log(n)) 84 | 85 | The idea follows that the sequence is dependent on 86 | a repeating pattern of 2. The final number being finNum 87 | increases on every doubling of i. 88 | 89 | 1 : 1 90 | 2 : 2 91 | 3 : 2 92 | 4 : 3 93 | 5 : 3 94 | 6 : 3 95 | 7 : 3 96 | 8 : 4 97 | cont. 98 | 99 | As you can see, for every version of i, there is an appropriate 100 | final number that iterates on every doubling of i. 101 | 102 | Contributors: 103 | - [F45H](https://github.com/F35H) 104 | """ 105 | function bin_length_short(binNum::T) where {T<:Integer} 106 | binNum <= 0 && throw(DomainError("binNum must be a positive integer")) 107 | 108 | finNum = 0 109 | i = 1 110 | 111 | while i <= binNum 112 | i *= 2 113 | finNum += 1 114 | end 115 | 116 | return finNum 117 | end 118 | -------------------------------------------------------------------------------- /src/math/catalan_number.jl: -------------------------------------------------------------------------------- 1 | """ 2 | catalan(n::Int) 3 | In combinatorial mathematics, the Catalan numbers are a sequence of natural numbers that occur in various counting problems, often involving recursively defined objects. 4 | 5 | 6 | # Input parameters: 7 | - `n` : index of the catalan number. 8 | 9 | # Examples/Tests: 10 | ```julia 11 | catalan(0) # returns 1 12 | catalan(3) # returns 5 13 | catalan(8) # returns 1430 14 | catalan(-1) # throws DomainError 15 | ``` 16 | 17 | # Reference 18 | - https://mathworld.wolfram.com/CatalanNumber.html 19 | 20 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 21 | """ 22 | function catalan(n::Int) 23 | n < 0 && throw(DomainError("Only defined for non-negative n")) 24 | n = big(n) 25 | return factorial(2n) ÷ (factorial(n)^2 * (n + 1)) 26 | end 27 | -------------------------------------------------------------------------------- /src/math/ceil.jl: -------------------------------------------------------------------------------- 1 | """ 2 | ceil(x) 3 | 4 | Finds the ceiling of x as an functionInteger 5 | 6 | # Example 7 | ```julia 8 | ceil(1.3) # 2.0 9 | ceil(2.0) # returns 2.0 10 | ceil(-1.5) #returns -1.0 11 | ``` 12 | 13 | # Reference 14 | - https://en.wikipedia.org/wiki/Floor_and_ceiling_functions 15 | 16 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) 17 | """ 18 | ceil(x) = x - trunc(x) <= 0 ? trunc(x) : trunc(x) + 1 19 | -------------------------------------------------------------------------------- /src/math/collatz_sequence.jl: -------------------------------------------------------------------------------- 1 | """ 2 | collatz_sequence(n) 3 | 4 | Collatz conjecture: start with any positive integer n. The next term is 5 | obtained as follows: 6 | If n term is even, the next term is: n / 2 . 7 | If n is odd, the next term is: 3 * n + 1. 8 | The conjecture states the sequence will always reach 1 for any starting value n. 9 | """ 10 | 11 | function collatz_sequence(n::N) where {N<:Integer} 12 | sequence = [n] 13 | while n != 1 14 | n = n % 2 == 1 ? 3 * n + 1 : div(n, 2) 15 | append!(sequence, n) 16 | end 17 | return sequence 18 | end 19 | -------------------------------------------------------------------------------- /src/math/combination.jl: -------------------------------------------------------------------------------- 1 | """ 2 | combination(n, r) 3 | 4 | returns the number of ways picking r unordered outcomes from 5 | n possibilities, without repetition 6 | 7 | # Arguments: 8 | - `n`: Positive integers of items to choose from 9 | - 'r': Positive integers of items to choose 10 | 11 | Contributed By:- [Mayur Dahibhate](https://github.com/mayurdahibhate) 12 | """ 13 | 14 | function combination(n, r) 15 | function factorial(n) 16 | fact = 1 17 | 18 | if n == 0 || n == 1 19 | return fact 20 | end 21 | 22 | for i in 1:n 23 | fact = fact * i 24 | end 25 | 26 | return fact 27 | end 28 | 29 | comb = factorial(n) / (factorial(r) * factorial(n - r)) 30 | 31 | return convert(Int64, comb) 32 | end 33 | -------------------------------------------------------------------------------- /src/math/divisors.jl: -------------------------------------------------------------------------------- 1 | """ 2 | divisors(n::Int) 3 | Returns the divisors of n as a vector. 4 | 5 | # Input parameters: 6 | - `n` : The number to find the factors of. 7 | 8 | # Examples/Tests: 9 | ```julia 10 | divisors(6) # returns [1, 2, 3, 6] 11 | divisors(10) # returns [1, 2, 5, 10] 12 | divisors(1345) # returns [1, 5, 269, 1345] 13 | divisors(-1) # throws DomainError 14 | ``` 15 | 16 | # Reference 17 | - https://mathworld.wolfram.com/Divisor.html 18 | 19 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 20 | """ 21 | function divisors(n::Int) 22 | n <= 0 && throw(DomainError("factors only works for positive integers")) 23 | return [i for i in 1:n if n % i == 0] 24 | end 25 | 26 | """ 27 | sum_divisors(n::Int) 28 | Returns the sum of the divisors of n. 29 | 30 | # Input parameters: 31 | - `n` : The number to find the sum of divisors of. 32 | 33 | # Examples/Tests: 34 | ```julia 35 | sum_divisors(6) # returns 12 36 | sum_divisors(10) # returns 18 37 | sum_divisors(1345) # returns 1620 38 | sum_divisors(-1) # throws DomainError 39 | ``` 40 | 41 | # Reference 42 | - https://mathworld.wolfram.com/Divisor.html 43 | 44 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 45 | """ 46 | function sum_divisors(n::Int) 47 | return sum(divisors(n)) 48 | end 49 | 50 | """ 51 | aliquot_sum(n::Int) 52 | The aliquot sum of a positive integer n is the sum of all the proper divisors of n, i.e, all divisors of n other than n itself. 53 | 54 | # Input parameters: 55 | - `n` : The number to find the aliquot sum of. 56 | 57 | # Examples/Tests: 58 | ```julia 59 | aliquot_sum(6) # returns 6 60 | aliquot_sum(10) # returns 8 61 | aliquot_sum(1345) # returns 275 62 | aliquot_sum(-1) # throws DomainError 63 | ``` 64 | 65 | # Reference 66 | - https://en.wikipedia.org/wiki/Aliquot_sum 67 | 68 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 69 | """ 70 | function aliquot_sum(n::Int) 71 | return sum_divisors(n) - n 72 | end 73 | 74 | """ 75 | num_divisors(n::Int) 76 | Efficiently finds the number of divisors of n. 77 | 78 | # Input parameters: 79 | - `n` : The number to find the number of divisors of. 80 | 81 | # Examples/Tests: 82 | ```julia 83 | num_divisors(1) # returns 1 84 | num_divisors(13) # returns 2 85 | num_divisors(420) # returns 24 86 | num_divisors(1345) # returns 4 87 | num_divisors(-1) # throws DomainError 88 | ``` 89 | 90 | # Reference 91 | - https://cp-algorithms.com/algebra/divisors.html#number-of-divisors 92 | 93 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 94 | """ 95 | function num_divisors(n::Int) 96 | n <= 0 && throw(DomainError("expected a positive integer")) 97 | result = 1 98 | limit = isqrt(n) 99 | for i in 2:limit 100 | e = 0 101 | while n % i == 0 102 | e += 1 103 | n /= i 104 | end 105 | result *= e + 1 106 | end 107 | 108 | if n > 1 109 | result *= 2 110 | end 111 | 112 | return result 113 | end 114 | -------------------------------------------------------------------------------- /src/math/euler_method.jl: -------------------------------------------------------------------------------- 1 | """ 2 | euler_method(f, x0, span, h=1.0e-2) 3 | 4 | Calculate the solution to a differential equation using forward euler method. 5 | """ 6 | function euler_method(f, x0, span, h = 1.0e-2) 7 | s, e = span 8 | steps = Int(floor((e - s) / h)) 9 | x = Vector{Float64}(undef, steps) 10 | t = Vector{Float64}(undef, steps) 11 | x[1] = x0 12 | t[1] = 0 13 | for i in 1:(steps-1) 14 | x[i+1] = x[i] + h * f(x[i], t[i]) 15 | t[i+1] = t[i] + h 16 | end 17 | return x, t 18 | end 19 | -------------------------------------------------------------------------------- /src/math/eulers_totient.jl: -------------------------------------------------------------------------------- 1 | """ 2 | totient(n::Int) 3 | The totient function phi(n) is defined as the number of positive integers <=n that are relatively prime to n. 4 | Since a number less than or equal to and relatively prime to a given number is called a totative, the totient function phi(n) can be simply defined as the number of totatives of n. 5 | 6 | # Input parameters: 7 | - `n` : The number to find the totient of. 8 | 9 | # Examples/Tests: 10 | ```julia 11 | totient(1) # returns 1 12 | totient(2) # returns 1 13 | totient(3) # returns 2 14 | totient(10) # returns 4 15 | totient(24) # returns 8 16 | totient(50) # returns 20 17 | totient(-1) # throws DomainError 18 | ``` 19 | 20 | # Reference 21 | - https://mathworld.wolfram.com/TotientFunction.html 22 | 23 | Contributed by [Praneeth Jain](https://www.github.com/PraneethJain) 24 | """ 25 | function totient(n::Int) 26 | n <= 0 && throw(DomainError("totient() only works for positive integers")) 27 | return count(i -> (gcd(i, n) == 1), 1:n) 28 | end 29 | -------------------------------------------------------------------------------- /src/math/factorial.jl: -------------------------------------------------------------------------------- 1 | """ 2 | factorial_iterative(n) 3 | 4 | Finds factorial of a number using Iterative method 5 | 6 | # Example 7 | ```julia 8 | factorial_iterative(5) # returns 120 9 | factorial_iterative(-1) # returns error 10 | ``` 11 | # Reference 12 | - factorial of a positive integer -- https://en.wikipedia.org/wiki/Factorial 13 | 14 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 15 | """ 16 | function factorial_iterative(n::Integer) 17 | if n < 0 18 | throw( 19 | error( 20 | "factorial_iterative() only accepts non-negative integral values", 21 | ), 22 | ) 23 | end 24 | if n == 0 || n == 1 25 | return one(BigInt) # keep same result type 26 | else 27 | factorial = one(BigInt) 28 | for i in 1:n 29 | factorial *= i 30 | end 31 | return factorial 32 | end 33 | end 34 | 35 | """ 36 | factorial_recursive(n) 37 | 38 | Finds factorial of a number using recursive method 39 | 40 | # Example 41 | ```julia 42 | factorial_recursive(5) # returns 120 43 | ``` 44 | # Reference 45 | - factorial of a positive integer -- https://en.wikipedia.org/wiki/Factorial 46 | 47 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 48 | """ 49 | function factorial_recursive(n::Integer)::BigInt 50 | if n < 0 51 | throw( 52 | error( 53 | "factorial_recursive() only accepts non-negative integral values", 54 | ), 55 | ) 56 | end 57 | if n == 0 || n == 1 58 | return one(BigInt) # keep same result type 59 | end 60 | return n * factorial_recursive(n - 1) 61 | end 62 | -------------------------------------------------------------------------------- /src/math/fibonacci.jl: -------------------------------------------------------------------------------- 1 | """ 2 | fib_recursive(n::Int) 3 | 4 | Finds the first n fibonacci number using recursive method. 5 | 6 | # Arguments: 7 | - `n` : Number of fibonacci numbers required 8 | 9 | # Examples/Tests 10 | ```julia 11 | fib_recursive(1) # returns [0] 12 | fib_recursive(2) # returns [0, 1] 13 | fib_recursive(6) # returns [0, 1, 1, 2, 3, 5] 14 | fib_recursive(10) # returns [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 15 | fib_recursive(-1) # throws DomainError 16 | ``` 17 | 18 | # Reference 19 | - https://mathworld.wolfram.com/FibonacciNumber.html 20 | 21 | Contributed by [Praneeth Jain](https://www.github.com/PraneethJain) 22 | """ 23 | function fib_recursive(n::Int) 24 | n <= 0 && throw(DomainError("n is negative")) 25 | function get_nth_term(i::Int) 26 | if i == 1 27 | return 0 28 | elseif i == 2 29 | return 1 30 | else 31 | return get_nth_term(i - 1) + get_nth_term(i - 2) 32 | end 33 | end 34 | return [get_nth_term(i) for i in 1:n] 35 | end 36 | 37 | """ 38 | fib_recursive_memo(n::Int) 39 | 40 | Finds the first n fibonacci number using recursive method and memoization. 41 | 42 | # Arguments: 43 | - `n` : Number of fibonacci numbers required 44 | 45 | # Examples/Tests 46 | ```julia 47 | fib_recursive_memo(1) # returns [0] 48 | fib_recursive_memo(2) # returns [0, 1] 49 | fib_recursive_memo(6) # returns [0, 1, 1, 2, 3, 5] 50 | fib_recursive_memo(10) # returns [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 51 | fib_recursive_memo(-1) # throws DomainError 52 | ``` 53 | 54 | # Reference 55 | - https://mathworld.wolfram.com/FibonacciNumber.html 56 | 57 | Contributed by [Praneeth Jain](https://www.github.com/PraneethJain) 58 | """ 59 | function fib_recursive_memo(n::Int) 60 | n <= 0 && throw(DomainError("n is negative")) 61 | cache = Dict(1 => 0, 2 => 1) 62 | function get_nth_term(i::Int) 63 | if haskey(cache, i) 64 | return cache[i] 65 | else 66 | value = get_nth_term(i - 1) + get_nth_term(i - 2) 67 | cache[i] = value 68 | return value 69 | end 70 | end 71 | return [get_nth_term(i) for i in 1:n] 72 | end 73 | 74 | """ 75 | fib_iterative(n::Int) 76 | 77 | Finds the first n fibonacci number using iterative method. 78 | 79 | # Arguments: 80 | - `n` : Number of fibonacci numbers required 81 | 82 | # Examples/Tests 83 | ```julia 84 | fib_iterative(1) # returns [0] 85 | fib_iterative(2) # returns [0, 1] 86 | fib_iterative(6) # returns [0, 1, 1, 2, 3, 5] 87 | fib_iterative(10) # returns [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 88 | fib_iterative(-1) # throws DomainError 89 | ``` 90 | 91 | # Reference 92 | - https://mathworld.wolfram.com/FibonacciNumber.html 93 | 94 | Contributed by [Praneeth Jain](https://www.github.com/PraneethJain) 95 | """ 96 | function fib_iterative(n::Int) 97 | if n <= 0 98 | throw(DomainError("n is negative")) 99 | elseif n == 1 100 | return [0] 101 | else 102 | result = [0, 1] 103 | a, b = 0, 1 104 | for i in 2:n-1 105 | a, b = b, a + b 106 | push!(result, b) 107 | end 108 | return result 109 | end 110 | end 111 | -------------------------------------------------------------------------------- /src/math/floor.jl: -------------------------------------------------------------------------------- 1 | """ 2 | floor(x) 3 | 4 | Finds the floor of x as an Integer 5 | 6 | # Example 7 | ```julia 8 | floor(1.3) # 1 9 | floor(2.0) # returns 2.0 10 | floor(-1.7) # returns -2.0 11 | ``` 12 | 13 | # Reference 14 | - https://en.wikipedia.org/wiki/Floor_and_ceiling_functions 15 | 16 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) 17 | """ 18 | floor(x) = x - trunc(x) >= 0 ? trunc(x) : trunc(x) - 1 19 | -------------------------------------------------------------------------------- /src/math/krishnamurthy_number.jl: -------------------------------------------------------------------------------- 1 | """ 2 | krishnamurthy(number) 3 | 4 | Check if a number is a Krishnamurthy number or not 5 | 6 | # Details 7 | 8 | It is also known as Peterson Number. 9 | 10 | A Krishnamurthy Number is a number whose sum of the 11 | factorial of the digits equals to the original 12 | number itself. 13 | 14 | For example: 145 = 1! + 4! + 5! 15 | So, 145 is a Krishnamurthy Number 16 | 17 | # Example 18 | 19 | ```julia 20 | krishnamurthy(145) # returns true 21 | krishnamurthy(240) # returns false 22 | krishnamurthy(1) # returns true 23 | ``` 24 | 25 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) 26 | """ 27 | function krishnamurthy(number) 28 | if number != trunc(number) || number < 0 29 | throw( 30 | error("krishnamurthy() only accepts non-negative integral values"), 31 | ) 32 | end 33 | total = 0 34 | temp = number 35 | while temp > 0 36 | temp, digit = divrem(temp, 10) 37 | total += factorial_iterative(digit) 38 | end 39 | return total == number 40 | end 41 | -------------------------------------------------------------------------------- /src/math/least_common_multiple.jl: -------------------------------------------------------------------------------- 1 | """ 2 | least_common_multiple(a::Int, b::Int) 3 | 4 | Finds the least common multiple of two integers 5 | 6 | # Arguments: 7 | - `a`: First of two integers 8 | - `b`: Second of two integers 9 | 10 | # Examples/Tests: 11 | ```julia 12 | least_common_multiple(12, 76) # returns 228 13 | least_common_multiple(5, -10) # returns 10 14 | ``` 15 | 16 | # References: 17 | - https://en.wikipedia.org/wiki/Least_common_multiple 18 | - https://www.javatpoint.com/python-find-lcm 19 | """ 20 | 21 | function least_common_multiple(a::Int, b::Int) 22 | if a >= b 23 | common_multiple = a 24 | else 25 | common_multiple = b 26 | end 27 | 28 | while (common_multiple % a != 0) || (common_multiple % b != 0) 29 | common_multiple += 1 30 | end 31 | 32 | return common_multiple 33 | end 34 | -------------------------------------------------------------------------------- /src/math/line_length.jl: -------------------------------------------------------------------------------- 1 | """ 2 | line_length(f, x_start, x_end, steps=100) 3 | 4 | Approximates the arc length of a line segment by treating the curve as a 5 | sequence of linear lines and summing their lengths. 6 | 7 | Arguments: 8 | - f: function that returns the arc 9 | - x_start: starting x value 10 | - x_end: ending x_value 11 | - steps: steps to take for accurace, more the steps greater the accuracy 12 | """ 13 | function line_length(f, x_start, x_end, steps = 100) 14 | x1 = x_start 15 | fx1 = f(x1) 16 | len = 0.0 17 | 18 | for step in 1:steps 19 | x2 = ((x_end - x_start) / steps) + x1 20 | fx2 = f(x2) 21 | len += hypot(x2 - x1, fx2 - fx1) 22 | 23 | x1 = x2 24 | fx1 = fx2 25 | end 26 | 27 | return len 28 | end 29 | -------------------------------------------------------------------------------- /src/math/mersenne_prime.jl: -------------------------------------------------------------------------------- 1 | """ 2 | is_mersenne_prime(n::Int) 3 | A mersenne prime is a prime number that is one less than a power of 2. 4 | Checks whether the given integer is a mersenne prime. 5 | 6 | # Input parameters: 7 | - `n` : The number to be checked. 8 | 9 | # Examples/Tests: 10 | ```julia 11 | is_mersenne_prime(3) # returns true 12 | is_mersenne_prime(15) # returns false 13 | is_mersenne_prime(8191) # returns true 14 | ``` 15 | 16 | # Reference 17 | - https://mathworld.wolfram.com/MersennePrime.html 18 | 19 | Contributed by [Praneeth Jain](https://www.github.com/PraneethJain) 20 | """ 21 | function is_mersenne_prime(n::Int) 22 | num = n 23 | n += 1 24 | while n % 2 == 0 25 | n /= 2 26 | end 27 | return n == 1 && prime_check(num) 28 | end 29 | 30 | """ 31 | get_mersenne_primes(n::Int) 32 | A mersenne prime is a prime number that is one less than a power of 2. 33 | Returns a list of mersenne primes upto n. 34 | 35 | # Input parameters: 36 | - `n` : The limit upto which mersenne primes are to be generated. 37 | 38 | # Examples/Tests: 39 | ```julia 40 | get_mersenne_primes(100) # returns [3, 7, 31] 41 | get_mersenne_primes(1000) # returns [3, 7, 31, 127] 42 | get_mersenne_primes(10000) # returns [3, 7, 31, 127, 8191] 43 | ``` 44 | 45 | # Reference 46 | - https://mathworld.wolfram.com/MersennePrime.html 47 | 48 | Contributed by [Praneeth Jain](https://www.github.com/PraneethJain) 49 | """ 50 | function get_mersenne_primes(limit::Int) 51 | return [i for i in 1:limit if is_mersenne_prime(i)] 52 | end 53 | -------------------------------------------------------------------------------- /src/math/monte_carlo_integration.jl: -------------------------------------------------------------------------------- 1 | """ 2 | monte_carlo_integration(f::Function, a::Real, b::Real, n::Int) 3 | 4 | Monte carlo integration is a very easy and scalable way to do multidimentional integrals. 5 | However, only single variable integrals are considered. 6 | 7 | # Arguments 8 | - `f`: the function to integrate. (at the momment only single variable is suported) 9 | - `a`: start in the integration limits. 10 | - `b`: endin the integration limits. 11 | - `N`: Number of points to sample. For most simple functions, 1000 to 10,000 should be okay. 12 | 13 | # Examples 14 | ```julia 15 | julia> monte_carlo_integration(x -> 3*x^2, 0, 1, 100000) # integrate a polynomial 16 | 1.0000037602209 17 | 18 | julia> monte_carlo_integration(x -> sin(x), 0, pi, 1000) # integrate the sin function 19 | 2.0018927826323756 20 | ``` 21 | 22 | # References 23 | - https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/monte-carlo-methods-in-practice/monte-carlo-integration 24 | - https://kingaa.github.io/sbied/pfilter/monteCarlo.html 25 | 26 | # Contributors 27 | - [AugustoCL](https://github.com/AugustoCL) 28 | - [Ved Mahajan](https://github.com/Ved-Mahajan) 29 | """ 30 | function monte_carlo_integration(f::Function, a::Real, b::Real, n::Int) 31 | Δₓ = ((b - a) / n) 32 | 33 | Σ = 0.0 34 | for _ in 1:n 35 | # generate uniform(a, b) using uniform(0, 1) 36 | Xᵢ = a + (b - a) * rand() 37 | Σ += f(Xᵢ) 38 | end 39 | 40 | return Δₓ * Σ 41 | end 42 | -------------------------------------------------------------------------------- /src/math/partitions.jl: -------------------------------------------------------------------------------- 1 | """ 2 | partitions_recursive(n) 3 | 4 | Finds partitions of an integer using recursion. 5 | 6 | A partition of a positive integer n, also called an integer partition, 7 | is a way of writing n as a sum of positive integers. 8 | 9 | There are 7 partitions of 5: 10 | 5 11 | 4 + 1 12 | 3 + 2 13 | 3 + 1 + 1 14 | 2 + 2 + 1 15 | 2 + 1 + 1 + 1 16 | 1 + 1 + 1 + 1 + 1 17 | 18 | Partitions of n is equal to the sum of partitions of n with k parts. 19 | 20 | ``P \\left ( n \\right ) = \\sum_{k=1}^{n} P_{k} \\left ( n \\right )`` 21 | 22 | Partitions of n with k parts is the sum of 23 | partitions of n-1 with k-1 parts and, 24 | partitions of n-k with k parts. 25 | 26 | ``P_{k}\\left ( n \\right ) = 27 | P_{k-1}\\left ( n - 1 \\right ) + P_{k}\\left ( n - k \\right )`` 28 | 29 | # Example 30 | ```julia 31 | partitions_recursive(0) # returns 1 32 | partitions_recursive(1) # returns 1 33 | partitions_recursive(10) # returns 42 34 | partitions_recursive(-1) # returns DomainError 35 | ``` 36 | # References 37 | - Partitions of a positive integer -- https://en.wikipedia.org/wiki/Partition_function_(number_theory) 38 | - Partitions of a positive integer -- https://www.whitman.edu/mathematics/cgt_online/book/section03.03.html 39 | 40 | # Contributor 41 | - [Vaishakh C R](https://github.com/Whiteshark-314) 42 | """ 43 | function partitions_recursive(n::N)::BigInt where {N<:Integer} 44 | n < 0 && throw( 45 | DomainError( 46 | "partitions_recursive() only accepts positive integral values", 47 | ), 48 | ) 49 | if n == 0 50 | return one(BigInt) 51 | end 52 | k = collect(1:n) 53 | return sum(partitions_k_parts.(n, k)) 54 | end 55 | 56 | function partitions_k_parts(n, k) 57 | n < 0 || 58 | k < 0 && throw( 59 | DomainError( 60 | "partitions_k_parts() only accepts positive integral values", 61 | ), 62 | ) 63 | if (n == 0 && k == 0) || (n > 0 && k == 1) || n == k 64 | return one(BigInt) 65 | elseif k == 0 || k > n 66 | return zero(BigInt) 67 | end 68 | return partitions_k_parts(n - 1, k - 1) + partitions_k_parts(n - k, k) 69 | end 70 | -------------------------------------------------------------------------------- /src/math/perfect_cube.jl: -------------------------------------------------------------------------------- 1 | """ 2 | perfect_cube(number) 3 | 4 | Check if a number is a perfect cube or not. 5 | 6 | # Example 7 | ```jula 8 | perfect_cube(27) # returns true 9 | perfect_cube(4) # returns false 10 | ``` 11 | 12 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 13 | """ 14 | function perfect_cube(number::N) where {N<:Integer} 15 | val = trunc(cbrt(number)) 16 | return (val * val * val) == number 17 | end 18 | -------------------------------------------------------------------------------- /src/math/perfect_number.jl: -------------------------------------------------------------------------------- 1 | """ 2 | perfect_number(number) 3 | 4 | Checks if a number is a perfect_number number or not 5 | 6 | # Details 7 | 8 | perfect_number number is a positive integer that is equal to the sum of 9 | its positive divisors, excluding the number itself. 10 | 11 | For example : 6 is perfect_number number 12 | 13 | Divisors of 6 => [1,2,3] 14 | 15 | Sum of divisors => 1+2+3 = 6 16 | 17 | 6 == sum(divisors) # which is true 18 | 19 | # Example 20 | 21 | ```julia 22 | perfect_number(27) # returns false 23 | perfect_number(28) # returns true 24 | perfect_number(496) # returns true 25 | perfect_number(8128) # returns true 26 | perfect_number(123) # returns false 27 | ``` 28 | 29 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 30 | """ 31 | function perfect_number(number::N) where {N<:Number} 32 | divisors = Vector{Int}() 33 | for i in 1:(number÷2+1) 34 | if number % i == 0 35 | push!(divisors, i) 36 | end 37 | end 38 | return sum(divisors) == number 39 | end 40 | -------------------------------------------------------------------------------- /src/math/perfect_square.jl: -------------------------------------------------------------------------------- 1 | """ 2 | perfect_square(number) 3 | 4 | Check if a number is a perfect square or not. 5 | 6 | # Example 7 | ```jula 8 | perfect_square(9) # returns True 9 | perfect_square(16) # returns True 10 | perfect_square(1) # returns True 11 | perfect_square(0) # returns True 12 | perfect_square(10) # returns False 13 | perfect_square(-9) # returns False 14 | ``` 15 | 16 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 17 | """ 18 | function perfect_square(number::N) where {N<:Integer} 19 | number < 0 && return false 20 | val = isqrt(number) 21 | return val * val == number 22 | end 23 | -------------------------------------------------------------------------------- /src/math/permutation.jl: -------------------------------------------------------------------------------- 1 | """ 2 | permutation(n, r) 3 | 4 | returns the number of ways to choose r items from n items 5 | with order and without repetition 6 | 7 | # Arguments: 8 | - `n`: Positive integers of items to choose from 9 | - 'r': Positive integers of items to choose 10 | 11 | Contributed By:- [Mayur Dahibhate](https://github.com/mayurdahibhate) 12 | """ 13 | 14 | function permutation(n, r) 15 | function factorial(n) 16 | fact = 1 17 | 18 | if n == 0 || n == 1 19 | return fact 20 | end 21 | 22 | for i in 1:n 23 | fact = fact * i 24 | end 25 | 26 | return fact 27 | end 28 | 29 | perm = factorial(n) / factorial(n - r) 30 | 31 | return convert(Int64, perm) 32 | end 33 | -------------------------------------------------------------------------------- /src/math/prime_check.jl: -------------------------------------------------------------------------------- 1 | """ 2 | prime_check(number) 3 | 4 | Checks to see if a number is a prime or not 5 | 6 | A number is prime if it has exactly two factors: 1 and itself. 7 | 8 | # Example 9 | 10 | ```julia 11 | prime_check(2) # returns true 12 | prime_check(3) # returns true 13 | prime_check(5) # returns true 14 | prime_check(7) # returns true 15 | prime_check(11) # returns true 16 | prime_check(13) # returns true 17 | prime_check(17) # returns true 18 | prime_check(19) # returns true 19 | prime_check(23) # returns true 20 | prime_check(29) # returns true 21 | prime_check(30) # returns false 22 | ``` 23 | 24 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) and [Rratic](https://github.com/Rratic) 25 | """ 26 | function prime_check(number::N) where {N<:Integer} 27 | if 1 < number < 4 28 | # 2, 3 are primes 29 | return true 30 | elseif number < 2 || number % 2 == 0 31 | # Negative ,0,1, and even numbers except 2 are not primes 32 | return false 33 | end 34 | for i in 3:2:(isqrt(number)+1) 35 | if number % i == 0 36 | return false 37 | end 38 | end 39 | return true 40 | end 41 | -------------------------------------------------------------------------------- /src/math/prime_factors.jl: -------------------------------------------------------------------------------- 1 | """ 2 | prime_factors(number) 3 | 4 | Returns prime factors of `number` as a vector 5 | 6 | # Example 7 | 8 | ```julia 9 | prime_factors(50) # returns [2,5,5] 10 | prime_factors(0) # returns [] 11 | prime_factors(100) # returns [2, 2, 5, 5] 12 | prime_factors(2560) # returns [2, 2, 2, 2, 2, 2, 2, 2, 2, 5] 13 | ``` 14 | 15 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) 16 | """ 17 | function prime_factors(number::N) where {N<:Integer} 18 | i = 2 19 | factors = Vector{Int}() 20 | while i * i <= number 21 | if number % i == 1 22 | i += 1 23 | else 24 | number ÷= i 25 | push!(factors, i) 26 | end 27 | end 28 | if number > 1 == 1 29 | push!(factors, number) 30 | end 31 | return factors 32 | end 33 | -------------------------------------------------------------------------------- /src/math/riemann_integration.jl: -------------------------------------------------------------------------------- 1 | """ 2 | riemann_integration(f::Function, a::Real, b::Real, n::Int, approx::Symbol = :midpoint) 3 | 4 | a Riemann sum is a certain kind of approximation of an integral by a finite sum. 5 | The sum is calculated by partitioning the region into shapes (rectangles, trapezoids, parabolas, or cubics) that together form a region that is similar to the region being measured, then calculating the area for each of these shapes, and finally adding all of these small areas together. 6 | 7 | Because the region filled by the small shapes is usually not exactly the same shape as the region being measured, the Riemann sum will differ from the area being measured. 8 | This error can be reduced by dividing up the region more finely, using smaller and smaller shapes. 9 | As the shapes get smaller and smaller, the sum approaches the Riemann integral. 10 | 11 | # Arguments 12 | - `f`: the function to integrate. (at the momment only single variable is suported) 13 | - `a`: Start of the integration limit. 14 | - `b`: End of the integration limit. 15 | - `n`: Number of points to sample. (as n increase, error decrease) 16 | - `approx`: Indicate the method of approximation (midpoint, left or right) 17 | 18 | # Examples 19 | ```julia 20 | julia> riemann_integration(x -> x, 1, 3, 1_000, :midpoint) # 4.0 21 | julia> riemann_integration(x -> x, 1, 3, 1_000, :left) # 3.997997997997998 22 | julia> riemann_integration(x -> x, 1, 3, 1_000, :right) # 4.002002002002002 23 | julia> riemann_integration(x -> 3*x^2, 0, 1, 100000) # integrate a polynomial 24 | 0.9999999999750021 25 | julia> riemann_integration(x -> sin(x), 0, pi, 1000) # integrate the sin function 26 | 2.0000008241146774 27 | ``` 28 | 29 | # Refereces 30 | - https://www.khanacademy.org/math/ap-calculus-ab/ab-integration-new/ab-6-2/a/riemann-sums-review 31 | - https://math.libretexts.org/Courses/Mount_Royal_University/MATH_2200%3A_Calculus_for_Scientists_II/2%3A_Techniques_of_Integration/2.5%3A_Numerical_Integration_-_Midpoint%2C_Trapezoid%2C_Simpson's_rule 32 | - https://abel.math.harvard.edu/~knill/teaching/math1a_2011/handouts/40-numerical.pdf 33 | - https://en.wikipedia.org/wiki/Riemann_integral 34 | 35 | 36 | Contributed By:- [AugustoCL](https://github.com/AugustoCL) 37 | """ 38 | function riemann_integration( 39 | f::Function, 40 | a::Real, 41 | b::Real, 42 | n::Int, 43 | approx::Symbol = :midpoint, 44 | ) 45 | # width of the rectangles 46 | Δₓ = (b - a) / n 47 | 48 | # methods of approximation (:midpoint, :left, :right) 49 | if approx == :midpoint 50 | sum_range = (a+Δₓ/2):Δₓ:(b-Δₓ/2) 51 | elseif approx == :left 52 | sum_range = a:Δₓ:(b-Δₓ) 53 | elseif approx == :right 54 | sum_range = (a+Δₓ):Δₓ:b 55 | else 56 | throw( 57 | ArgumentError( 58 | "The symbol :$approx is not a valid argument. Insert :midpoint, :left or :right", 59 | ), 60 | ) 61 | end 62 | 63 | # sum of the height of the rectangles 64 | Σ = 0.0 65 | for i in 2:length(sum_range) 66 | a = sum_range[i-1] 67 | b = sum_range[i] 68 | xᵢ = a + (b - a) * rand() # draw a uniform(a,b) for each subinterval [a,b] 69 | Σ += f(xᵢ) 70 | end 71 | 72 | # approximate integral of f 73 | return Δₓ * Σ 74 | end 75 | -------------------------------------------------------------------------------- /src/math/runge_kutta_integration.jl: -------------------------------------------------------------------------------- 1 | """ 2 | runge_kutta_integration(f::Function, x0::Real, y0::Real, h::Real, x_stop::Real) 3 | 4 | Numerically solve initial value problems of the form ``y' = f(x, y)`` to find ``y(x)`` using the Runge-Kutta 4th order integration scheme. 5 | 6 | Starting with the differential equation ``\\frac{\\mathrm{d}y}{\\mathrm{d}x} = y' = f(x, y)`` and the initial condition ``y(x_0) = y_0``, each step calculates 4 approximations of the gradient 7 | ```math 8 | \\begin{align*} 9 | k_1 &= f(x_n, y_n),\\\\ 10 | k_2 &= f(x_n + \\frac{h}{2}, y_n + k_1\\frac{h}{2}),\\\\ 11 | k_3 &= f(x_n + \\frac{h}{2}, y_n + k_2\\frac{h}{2}),\\\\ 12 | k_4 &= f(x_n + h, y_n + k_3h), 13 | \\end{align*} 14 | ``` 15 | and uses the weighted average of them, 16 | 17 | ```math 18 | \\bar{k} = \\frac{k_1 + 2k_2 + 2k_3 + k_4}{6}, 19 | ``` 20 | 21 | to find the approximate value of ``y(x_{n+1})`` and update ``x`` and ``y`` accordingly 22 | 23 | ```math 24 | \\begin{align*} 25 | x &\\rightarrow x_{n+1} = x_n + h\\\\ 26 | y &\\rightarrow y_{n+1} = y_n + h\\bar{k}. 27 | \\end{align*} 28 | ``` 29 | 30 | # Arguments: 31 | - `f`: The function ``y' = f(x, y)`` to solve for ``y(x)``. 32 | - `x0`: The starting value of x. 33 | - `y0`: The starting value of y. 34 | - `h`: The step size, should be >0. 35 | - `x_stop`: The final value of x to solve to, i.e. integrate over the range `[x0, x_stop]` 36 | 37 | # Examples 38 | ```julia 39 | julia> # If you have a constant slope of y' = 1, the analytic solution is y = x 40 | julia> runge_kutta_integration((x, y)->1, 0, 0, 1, 3) 41 | ([0.0, 1.0, 2.0, 3.0], [0.0, 1.0, 2.0, 3.0]) 42 | 43 | julia> # Consider solving y' = exp(x), which has the analytic solution y = exp(x). 44 | julia> runge_kutta_integration((x, y)->exp(x), 0, 1., 0.1, 0.1) 45 | ([0.0, 0.1], [1.0, 1.105170921726329]) 46 | 47 | julia> exp.([0.0, 0.1]) 48 | 2-element Vector{Float64}: 49 | 1.0 50 | 1.1051709180756477 51 | 52 | ``` 53 | 54 | # References 55 | - [https://en.wikipedia.org/wiki/Initial_value_problem](https://en.wikipedia.org/wiki/Initial_value_problem) 56 | - [https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods](https://en.wikipedia.org/wiki/Initial_value_problem) 57 | 58 | # Contributors: 59 | - [E-W-Jones](https://github.com/E-W-Jones) 60 | """ 61 | function runge_kutta_integration( 62 | f::Function, 63 | x0::Real, 64 | y0::Real, 65 | h::Real, 66 | x_stop::Real, 67 | ) 68 | h > 0 || throw(DomainError(h, "The step size `h` should be >0.")) 69 | 70 | x = Float64(x0) 71 | y = Float64(y0) 72 | output_x = [x] 73 | output_y = [y] 74 | 75 | while x < x_stop 76 | k1 = f(x, y) 77 | k2 = f(x + h / 2, y + k1 * h / 2) 78 | k3 = f(x + h / 2, y + k2 * h / 2) 79 | k4 = f(x + h, y + k3 * h) 80 | 81 | y += h * (k1 + 2k2 + 2k3 + k4) / 6 82 | x += h 83 | 84 | push!(output_x, x) 85 | push!(output_y, y) 86 | end 87 | 88 | return output_x, output_y 89 | end 90 | -------------------------------------------------------------------------------- /src/math/sieve_of_eratosthenes.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Sieve of Eratosthenes is an algorithm for finding all the primes upto a limit `n`. 3 | 4 | Reference: 5 | -https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes 6 | """ 7 | function eratosthenes(n) 8 | primes = fill(true, n) 9 | primes[1] = false 10 | for p in 2:n 11 | primes[p] || continue 12 | for i in 2:div(n, p) 13 | primes[p*i] = false 14 | end 15 | end 16 | return findall(primes) 17 | end 18 | -------------------------------------------------------------------------------- /src/math/simpsons_integration.jl: -------------------------------------------------------------------------------- 1 | """ 2 | simpsons_integration(f::Function, a::Real, b::Real, n::Int) 3 | 4 | Simpson's rule uses a quadratic polynomial on each subinterval of a partition to approximate the function f(x) and to compute the definite integral. 5 | This is an improvement over the trapezoid rule which approximates f(x) by a straight line on each subinterval of a partition. 6 | For more details of the method, check the link in the reference. 7 | 8 | # Arguments 9 | - `f`: The function to integrate. (ar the moment only single variable is suported) 10 | - `a`: Start of the integration limit. 11 | - `b`: End of the integration limit. 12 | - `n`: Number of points to sample. (as n increase, error decrease) 13 | 14 | # Examples/Test 15 | ```julia 16 | # aproximate pi with f(x) = 4 / (1 + x^2) 17 | julia> simpsons_integration(x -> 4 / (1 + x^2), 0, 1, 100_000) 18 | 3.1415926535897936 19 | julia> simpsons_integration(x -> 4 / (1 + x^2), 0, 1, 100_000) ≈ pi 20 | true 21 | ``` 22 | 23 | # References: 24 | - https://personal.math.ubc.ca/~pwalls/math-python/integration/simpsons-rule/ 25 | 26 | # Contributed By:- [AugustoCL](https://github.com/AugustoCL) 27 | """ 28 | function simpsons_integration(f::Function, a::Real, b::Real, n::Int) 29 | # width of the segments 30 | Δₓ = (b - a) / n 31 | 32 | # rules of the method (check link in references) 33 | a₁(i) = 2i - 2 34 | a₂(i) = 2i - 1 35 | 36 | # sum of the heights 37 | Σ = sum(1:(n/2)) do i 38 | return f(a + a₁(i) * Δₓ) + 4f(a + a₂(i) * Δₓ) + f(a + 2i * Δₓ) 39 | end 40 | 41 | # approximate integral of f 42 | return (Δₓ / 3) * Σ 43 | end 44 | -------------------------------------------------------------------------------- /src/math/sum_of_arithmetic_series.jl: -------------------------------------------------------------------------------- 1 | """ 2 | sum_ap(first_term, diff, num_terms) 3 | 4 | Finds sum of a arithmetic progression series 5 | 6 | # Input parameters 7 | 8 | - first_term : first term of the series 9 | - diff : common difference between consecutive terms 10 | - num_terms : number of terms in the series till which we count sum 11 | 12 | # Example 13 | 14 | ```julia 15 | sum_ap(1, 1, 10) # returns 55.0 16 | sum_ap(1, 10, 100) # returns 49600.0 17 | ``` 18 | 19 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) 20 | """ 21 | function sum_ap(first_term, diff, num_terms) 22 | #formula for sum of the ap series 23 | sum = (num_terms / 2) * (2 * first_term + (num_terms - 1) * diff) 24 | return sum 25 | end 26 | -------------------------------------------------------------------------------- /src/math/sum_of_geometric_progression.jl: -------------------------------------------------------------------------------- 1 | """ 2 | sum_gp(first_term, ratio, num_terms) 3 | 4 | Finds sum of n terms in a geometric progression 5 | 6 | # Input parameters 7 | 8 | - first_term : first term of the series 9 | - raio : common ratio between consecutive terms -> a2/a1 or a3/a2 or a4/a3 10 | - num_terms : number of terms in the series till which we count sum 11 | 12 | # Example 13 | 14 | ```julia 15 | sum_gp(1, 2, 10) # 1023.0 16 | sum_gp(1, 10, 5) # 11111.0 17 | sum_gp(0, 2, 10) # 0.0 18 | sum_gp(1, 0, 10) # 1.0 19 | sum_gp(1, 2, 0) # -0.0 20 | sum_gp(-1, 2, 10) # -1023.0 21 | sum_gp(1, -2, 10) # -341.0 22 | ``` 23 | 24 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) 25 | """ 26 | function sum_gp(first_term, ratio, num_terms) 27 | # case where ratio is 1 28 | if ratio == 1 29 | return num_terms * first_term 30 | end 31 | # ormula for finding sum of n terms of a geometric progression 32 | return (first_term / (1 - ratio)) * (1 - ratio^num_terms) 33 | end 34 | -------------------------------------------------------------------------------- /src/math/trapezoid_integration.jl: -------------------------------------------------------------------------------- 1 | """ 2 | trapezoid_integration(f::Function, a::Real, b::Real, n::Int) 3 | 4 | The trapezoidal rule works by approximating the region under the graph of the function f(x) as a trapezoid and calculating its area. 5 | 6 | # Arguments 7 | - `f`: the function to integrate. (at the momment only single variable is suported) 8 | - `a`: Start of the integration limit. 9 | - `b`: End of the integration limit. 10 | - `n`: Number of points to sample. (as n increase, error decrease) 11 | 12 | # Examples/Test 13 | ```julia 14 | julia> trapezoid_integration(x -> 4 / (1 + x^2), 0, 1, 100_000) 15 | 3.1415926535731526 16 | julia> trapezoid_integration(x -> 4 / (1 + x^2), 0, 1, 100_000) ≈ pi 17 | true 18 | ``` 19 | # References: 20 | -https://personal.math.ubc.ca/~pwalls/math-python/integration/trapezoid-rule/ 21 | -https://en.wikipedia.org/wiki/Trapezoidal_rule 22 | 23 | # Contributed By:- [AugustoCL](https://github.com/AugustoCL) 24 | """ 25 | function trapezoid_integration(f::Function, a::Real, b::Real, n::Int) 26 | # width of the trapezoids 27 | Δₓ = (b - a) / n 28 | 29 | # sum of the height of the trapezoids 30 | Σ = 0.5 * f(a) + sum(f(i) for i in (a+Δₓ):Δₓ:(b-Δₓ)) + 0.5 * f(b) 31 | 32 | # approximate integral of f 33 | return Δₓ * Σ 34 | end 35 | -------------------------------------------------------------------------------- /src/math/verlet.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Verlet integration is an integration method used to integrate newtons - law of motion. It is frequently used to find trajectories in molecular dynamics simulation. 3 | The function takes `four` inputs viz, 4 | - `f` : the differential equation 5 | - `x0` : the initial condition. This is a Vector with the first element as initial value for position (x_0) and the second initial condition for velocity (v_0) 6 | - `tspan`: is the time span for integration. It is a tuple (initial time, final time) 7 | This functionr returns a tuple (x,t): 8 | - `x` is the solution 9 | - `t` is the array containing the time points 10 | Reference: 11 | - https://www.algorithm-archive.org/contents/verlet_integration/verlet_integration.html 12 | Contributed by: [Ved Mahajan](https://github.com/Ved-Mahajan) 13 | """ 14 | function verlet_integration(f, x0, tspan, Δt = 1.0e-3) 15 | s, e = tspan 16 | N = Int(floor((e - s) / Δt)) 17 | x = Vector{Float64}(undef, N) 18 | t = collect(s:Δt:(e-Δt)) 19 | x[1] = x0[1] 20 | x[2] = x0[1] + x0[2] * Δt + 0.5 * f(x0[1]) * (Δt)^2 21 | 22 | for i in 2:(N-1) 23 | x[i+1] = 2 * x[i] - x[i-1] + f(x[i]) * (Δt)^2 24 | end 25 | return x, t 26 | end 27 | -------------------------------------------------------------------------------- /src/matrix/MatrixAlgo.jl: -------------------------------------------------------------------------------- 1 | export MatrixAlgo 2 | """ 3 | MatrixAlgo 4 | 5 | `MatrixAlgo` for matrix algorithms. 6 | """ 7 | module MatrixAlgo 8 | 9 | using TheAlgorithms 10 | 11 | export determinant 12 | export gauss_jordan 13 | export lu_decompose 14 | export rotation_matrix 15 | 16 | include("lu_decompose.jl") # used by determinant.jl 17 | include("determinant.jl") 18 | include("gauss_jordan_elim.jl") 19 | include("rotation_matrix.jl") 20 | 21 | end 22 | -------------------------------------------------------------------------------- /src/matrix/determinant.jl: -------------------------------------------------------------------------------- 1 | """ 2 | determinant(mat) 3 | 4 | Given a non singluar matrix, calculate its determinant using LU decomposition. 5 | 6 | L and U are lower triangular and upper triangular matrices respectively such that 7 | 8 | A = L*U 9 | 10 | If we want to find the determinant, then 11 | 12 | det(A) = det(LU) = det(L)*det(U) 13 | 14 | Determinant of triangualar matrices is the product of their diagonal entries. Hence, makes finding the determinant easy. 15 | """ 16 | function determinant(mat) 17 | n, m = size(mat) 18 | if n != m 19 | throw(DomainError(mat, "The matrix should be a square matrix.")) 20 | end 21 | L, U = lu_decompose(mat) 22 | l_prod = prod([L[i, i] for i in 1:n]) 23 | u_prod = prod([U[i, i] for i in 1:n]) 24 | 25 | return l_prod * u_prod 26 | end 27 | -------------------------------------------------------------------------------- /src/matrix/gauss_jordan_elim.jl: -------------------------------------------------------------------------------- 1 | """ 2 | gauss_jordan(A::AbstractMatrix{T}) where T<:Number 3 | 4 | Gaussian elimination, also known as row reduction, is an algorithm for solving systems of linear equations. 5 | It consists of a sequence of operations performed on the corresponding matrix of coefficients. 6 | This method can also be used to compute the rank of a matrix, the determinant of a square matrix, and the inverse of an invertible matrix. 7 | https://en.wikipedia.org/wiki/Gaussian_elimination 8 | 9 | # Examples/Tests 10 | ```julia 11 | julia> M1 = [1 2 3; 4 5 6]; 12 | julia> M2 = [1 2 3; 4 8 12]; 13 | 14 | julia> @test gauss_jordan(M1) == [1 0 -1; 0 1 2] # Test Passed 15 | julia> @test_throws AssertionError gauss_jordan(M2) # Test Passed - Thrown: AssertionError 16 | ``` 17 | 18 | # Contributed By:- [AugustoCL](https://github.com/AugustoCL) 19 | """ 20 | function gauss_jordan(A::AbstractMatrix{T}) where {T<:Number} 21 | 22 | # check if matrix is singular 23 | m, n = size(A) 24 | if m == n 25 | @assert determinant(A) ≠ 0.0 "Must insert a non-singular matrix" 26 | else 27 | @assert determinant(A[:, 1:(end-1)]) ≠ 0.0 "Must insert a non-singular matrix or a system matrix [A b]" 28 | end 29 | 30 | # execute the gauss-jordan elimination 31 | for i in axes(A, 1) 32 | if A[i, i] == 0.0 33 | for n in (i+1):m # iterate in lines below to check if could be swap 34 | if A[n, i] ≠ 0.0 # condition to swap row 35 | L = copy(A[i, :]) # copy line to swap 36 | A[i, :] = A[n, :] # swap occur 37 | A[n, :] = L 38 | break 39 | end 40 | end 41 | end 42 | 43 | @. A[i, :] = A[i, :] ./ A[i, i] # divide pivot line by pivot element 44 | 45 | for j in axes(A, 1) # iterate each line for each pivot column, except pivot line 46 | if j ≠ i # jump pivot line 47 | @. A[j, :] = A[j, :] - A[i, :] * A[j, i] # apply gauss jordan in each line 48 | end 49 | end 50 | end 51 | 52 | return A 53 | end 54 | 55 | # using multiple dispatch to avoid InexactError with Integers 56 | function gauss_jordan(A::AbstractMatrix{T}) where {T<:Integer} 57 | return gauss_jordan(convert(Matrix{Float64}, A)) 58 | end 59 | -------------------------------------------------------------------------------- /src/matrix/lu_decompose.jl: -------------------------------------------------------------------------------- 1 | """ 2 | lu_decompose(mat) 3 | Decomposes a `n x n` non singular matrix into a lower triangular matrix (L) and an upper triangular matrix (U) 4 | """ 5 | function lu_decompose(mat) 6 | n = first(size(mat)) 7 | L = zeros(n, n) 8 | U = zeros(n, n) 9 | 10 | for i in 1:n 11 | for j in i:n 12 | s = 0 13 | for k in 1:i 14 | s += L[i, k] * U[k, j] 15 | end 16 | U[i, j] = mat[i, j] - s 17 | end 18 | 19 | for k in i:n 20 | if i == k 21 | L[i, i] = 1 22 | else 23 | s = 0 24 | for j in 1:i 25 | s += L[k, j] * U[j, i] 26 | end 27 | L[k, i] = (mat[k, i] - s) / U[i, i] 28 | end 29 | end 30 | end 31 | 32 | return L, U 33 | end 34 | -------------------------------------------------------------------------------- /src/matrix/rotation_matrix.jl: -------------------------------------------------------------------------------- 1 | """ 2 | A 2D Rotation matrix is a mtrix that rotates a vector in a 2D real space by an angle theta. 3 | For more info: https://en.wikipedia.org/wiki/Rotation_matrix 4 | 5 | This function takes the angle `theta` in radians as input and returns a 2D Matrix which will rotate the vector by angle `theta`. 6 | """ 7 | function rotation_matrix(θ) 8 | rot_mat = Matrix{Float64}(undef, 2, 2) 9 | rot_mat[1, 1] = cos(θ) 10 | rot_mat[1, 2] = -sin(θ) 11 | rot_mat[2, 1] = sin(θ) 12 | rot_mat[2, 2] = cos(θ) 13 | 14 | return rot_mat 15 | end 16 | -------------------------------------------------------------------------------- /src/project_euler/ProjectEuler.jl: -------------------------------------------------------------------------------- 1 | """ 2 | ProjectEuler 3 | 4 | `ProjectEuler` naive solutions in Julia. 5 | """ 6 | module ProjectEuler 7 | 8 | export problem_001 9 | export problem_002 10 | export problem_003 11 | export problem_004 12 | export problem_005 13 | export problem_006 14 | export problem_007 15 | export problem_008 16 | export problem_009 17 | export problem_010 18 | export problem_011 19 | export problem_012 20 | export problem_013 21 | export problem_014 22 | export problem_015 23 | export problem_016 24 | export problem_017 25 | export problem_018 26 | export problem_019 27 | export problem_020 28 | 29 | include("../math/divisors.jl") 30 | include("../math/sieve_of_eratosthenes.jl") 31 | include("problem_001.jl") 32 | include("problem_002.jl") 33 | include("problem_003.jl") 34 | include("problem_004.jl") 35 | include("problem_005.jl") 36 | include("problem_006.jl") 37 | include("problem_007.jl") 38 | include("problem_008.jl") 39 | include("problem_009.jl") 40 | include("problem_010.jl") 41 | include("problem_011.jl") 42 | include("problem_012.jl") 43 | include("problem_013.jl") 44 | include("problem_014.jl") 45 | include("problem_015.jl") 46 | include("problem_016.jl") 47 | include("problem_017.jl") 48 | include("problem_018.jl") 49 | include("problem_019.jl") 50 | include("problem_020.jl") 51 | 52 | end 53 | -------------------------------------------------------------------------------- /src/project_euler/problem_001.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Multiples of 3 or 5 3 | 4 | If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. 5 | 6 | Find the sum of all the multiples of 3 or 5 below 1000. 7 | 8 | # Input parameters: 9 | - `limit` : Upper limit for the numbers. 10 | 11 | # Examples/Tests: 12 | ```julia 13 | problem_001(10) # returns 23 14 | problem_001(1000) # returns 233168 15 | problem_001(-1) # throws DomainError 16 | ``` 17 | 18 | # Reference 19 | - https://projecteuler.net/problem=1 20 | 21 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 22 | """ 23 | function problem_001(limit::Int) 24 | limit <= 1 && throw(DomainError("limit must be integer greater than 1")) 25 | return sum([i for i in 1:limit-1 if i % 3 == 0 || i % 5 == 0]) 26 | end 27 | -------------------------------------------------------------------------------- /src/project_euler/problem_002.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Even Fibonacci numbers 3 | 4 | Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 5 | 6 | 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 7 | 8 | By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. 9 | 10 | # Input parameters: 11 | - `limit` : Upper limit for the numbers. 12 | 13 | # Examples/Tests: 14 | ```julia 15 | problem_002(10) # returns 10 16 | problem_002(4_000_000) # returns 4613732 17 | problem_002(-1) # throws DomainError 18 | ``` 19 | 20 | # Reference 21 | - https://projecteuler.net/problem=2 22 | 23 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 24 | """ 25 | function problem_002(limit::Int) 26 | limit <= 1 && throw(DomainError("limit must be integer greater than 1")) 27 | a, b = 1, 2 28 | even_fib_sum = 0 29 | while b <= limit 30 | if iseven(b) 31 | even_fib_sum += b 32 | end 33 | a, b = b, a + b 34 | end 35 | return even_fib_sum 36 | end 37 | -------------------------------------------------------------------------------- /src/project_euler/problem_003.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Largest prime factor 3 | 4 | The prime factors of 13195 are 5, 7, 13 and 29. 5 | 6 | What is the largest prime factor of the number 600851475143 ? 7 | 8 | # Input parameters: 9 | - `number` : Number to find the largest prime factor of. 10 | 11 | # Examples/Tests: 12 | ```julia 13 | problem_003(17) # returns 17 14 | problem_003(13195) # returns 29 15 | problem_003(600851475143) # returns 6857 16 | problem_003(-1) # throws DomainError 17 | ``` 18 | 19 | # Reference 20 | - https://projecteuler.net/problem=3 21 | 22 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 23 | """ 24 | function problem_003(number::Number) 25 | number <= 1 && throw(DomainError("Number must be integer greater than 1")) 26 | prime_factor::Int64 = 2 27 | while prime_factor < number 28 | if number % prime_factor == 0 29 | number ÷= prime_factor 30 | else 31 | prime_factor += 1 32 | end 33 | end 34 | return prime_factor 35 | end 36 | -------------------------------------------------------------------------------- /src/project_euler/problem_004.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Largest palindrome product 3 | 4 | A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99. 5 | 6 | Find the largest palindrome made from the product of two 3-digit numbers. 7 | 8 | # Examples/Tests: 9 | ```julia 10 | problem_004() # returns 906609 11 | ``` 12 | 13 | # Reference 14 | - https://projecteuler.net/problem=4 15 | 16 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 17 | """ 18 | function problem_004() 19 | max = 0 20 | for i in 100:999 21 | for j in 100:999 22 | num = i * j 23 | if num > max && is_palindrome(num) 24 | max = num 25 | end 26 | end 27 | end 28 | return max 29 | end 30 | 31 | function is_palindrome(n::Int) 32 | rev = 0 33 | num = n 34 | while num != 0 35 | rev = 10 * rev + num % 10 36 | num ÷= 10 37 | end 38 | return rev == n 39 | end 40 | -------------------------------------------------------------------------------- /src/project_euler/problem_005.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Smallest multiple 3 | 4 | 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. 5 | 6 | What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20? 7 | 8 | # Input parameters: 9 | - `limit`: Limit upto which to find the smallest multiple. 10 | 11 | # Examples/Tests: 12 | ```julia 13 | problem_005(10) # returns 2520 14 | problem_005(20) # returns 232792560 15 | problem_005(-1) # throws DomainError 16 | ``` 17 | 18 | # Reference 19 | - https://projecteuler.net/problem=5 20 | 21 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 22 | """ 23 | function problem_005(limit::Int) 24 | limit <= 1 && throw(DomainError("Limit must be greater than 1")) 25 | result = 1 26 | for i in 1:limit 27 | result *= i ÷ gcd(i, result) 28 | end 29 | return result 30 | end 31 | -------------------------------------------------------------------------------- /src/project_euler/problem_006.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Sum square difference 3 | 4 | The sum of the squares of the first ten natural numbers is, 5 | 1^2 + 2^2 + ... + 10^2 = 385 6 | 7 | The square of the sum of the first ten natural numbers is, 8 | (1 + 2 + ... + 10)^2 = 55^2 = 3025 9 | 10 | Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 - 385 = 2640. 11 | Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum. 12 | 13 | # Input parameters: 14 | - `n` : limit upto which to find the sum square difference. 15 | 16 | # Examples/Tests: 17 | ```julia 18 | problem_006(10) # returns 2640 19 | problem_006(100) # returns 25164150 20 | problem_006(-1) # throws DomainError 21 | ``` 22 | 23 | # Reference 24 | - https://projecteuler.net/problem=6 25 | 26 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 27 | """ 28 | function problem_006(n::Int) 29 | n <= 0 && throw(DomainError("n must be a natural number")) 30 | # Sum of squares of first n natural numbers is n*(n+1)*(2n+1)/6 31 | # Square of sum of first n natural numbers is (n*(n+1)/2)^2 32 | return (n * (n + 1) ÷ 2)^2 - (n * (n + 1) * (2n + 1) ÷ 6) 33 | end 34 | -------------------------------------------------------------------------------- /src/project_euler/problem_007.jl: -------------------------------------------------------------------------------- 1 | """ 2 | 10001st prime 3 | 4 | By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. 5 | 6 | What is the 10 001st prime number? 7 | 8 | # Input parameters: 9 | - `n` : Will find the nth prime. 10 | 11 | # Examples/Tests: 12 | ```julia 13 | problem_007(1) # returns 2 14 | problem_007(6) # returns 13 15 | problem_007(10001) # returns 104743 16 | problem_007(-1) # throws DomainError 17 | ``` 18 | 19 | # Reference 20 | - https://projecteuler.net/problem=7 21 | 22 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 23 | """ 24 | function problem_007(n::Int) 25 | if n < 1 26 | throw(DomainError("n must be a natural number")) 27 | elseif 1 <= n <= 3 28 | return Dict(1 => 2, 2 => 3, 3 => 5)[n] 29 | else 30 | # The nth prime is always lower than n(log(n) + log(log(n))) 31 | upper_limit = Base.ceil(Int, n * (log(n) + log(log(n)))) 32 | return eratosthenes(upper_limit)[n] 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /src/project_euler/problem_008.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Largest product in a series 3 | 4 | The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832. 5 | 6 | Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product? 7 | 8 | # Input parameters: 9 | - `num_str` : The number to find the greatest product in, in string form. 10 | - `n` : Number of consecutive numbers to find the product of. 11 | 12 | # Examples/Tests: 13 | ```julia 14 | num_str = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450" 15 | problem_008("1234", 2) # returns 12 16 | problem_008(num_str, 4) # returns 5832 17 | problem_008(num_str, 13) # returns 23514624000 18 | problem_008("12345", 6) # throws DomainError 19 | ``` 20 | 21 | # Reference 22 | - https://projecteuler.net/problem=8 23 | 24 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 25 | """ 26 | function problem_008(num_str::String, n::Int) 27 | n > length(num_str) && 28 | throw(DomainError("n can't be bigger than length of num_str")) 29 | 30 | return maximum([ 31 | mapreduce(x -> parse(Int64, x), *, num_str[i:i+n-1]) for 32 | i in 1:length(num_str)-n+1 33 | ]) 34 | end 35 | -------------------------------------------------------------------------------- /src/project_euler/problem_009.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Special Pythagorean triplet 3 | 4 | A Pythagorean triplet is a set of three natural numbers, a < b < c, for which, 5 | a2 + b2 = c2 6 | 7 | For example, 32 + 42 = 9 + 16 = 25 = 52. 8 | 9 | There exists exactly one Pythagorean triplet for which a + b + c = 1000. 10 | Find the product abc. 11 | 12 | # Examples/Tests: 13 | ```julia 14 | problem_009() # returns 31875000 15 | ``` 16 | 17 | # Reference 18 | - https://projecteuler.net/problem=9 19 | - https://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple 20 | 21 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 22 | """ 23 | function problem_009() 24 | #= 25 | By Euclid's method for generating pythagorean triples: 26 | a = m^2 - n^2 27 | b = 2mn 28 | c = m^2 + n^2 29 | 30 | a + b + c = 2m^2 + 2mn 31 | 32 | Since a + b + c = 1000 33 | 2m^2 + 2mn = 1000 34 | on simplifying, 35 | n = 500/m - m 36 | as n is an integer, m has to be a factor of 500 37 | =# 38 | for m in divisors(500) 39 | n = 500 / m - m 40 | a = m^2 - n^2 41 | b = 2m * n 42 | c = m^2 + n^2 43 | 44 | a <= 0 && continue 45 | 46 | a + b + c == 1000 && return a * b * c 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /src/project_euler/problem_010.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Summation of primes 3 | 4 | The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. 5 | 6 | Find the sum of all the primes below two million. 7 | 8 | # Input parameters: 9 | - `n` : Upper limit of primes. 10 | 11 | # Examples/Tests: 12 | ```julia 13 | problem_010(1) # returns 0 14 | problem_010(10) # returns 17 15 | problem_010(2000000) # returns 142913828922 16 | problem_010(-1) # throws DomainError 17 | ``` 18 | 19 | # Reference 20 | - https://projecteuler.net/problem=10 21 | 22 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 23 | """ 24 | function problem_010(n::Int) 25 | n < 1 && throw(DomainError("n must be a natural number")) 26 | return reduce(+, eratosthenes(Int64(n)), init = Int64(0)) 27 | end 28 | -------------------------------------------------------------------------------- /src/project_euler/problem_012.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Highly Divisible Triangular Number 3 | 4 | The sequence of triangle numbers is generated by adding the natural numbers. 5 | So the 7th triangle number would be 1+2+3+4+5+6+7 = 28. The first ten terms 6 | would be 1,3,6,10,15,21,28,36,45,55,... 7 | What is the value of the first triangle number to have over 500 divisors? 8 | 9 | # Input parameters: 10 | - `n` : the triangle number must have over n divisors. 11 | 12 | # Examples/Tests: 13 | ```julia 14 | problem_012(5) # returns 28 15 | problem_012(333) # returns 17907120 16 | problem_012(500) # returns 76576500 17 | problem_012(-1) # throws DomainError 18 | ``` 19 | 20 | # Reference 21 | - https://projecteuler.net/problem=12 22 | 23 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 24 | """ 25 | function problem_012(n::Int) 26 | n < 1 && throw(DomainError("n must be a natural number")) 27 | i = 1 28 | while num_divisors(i * (i + 1) ÷ 2) <= n 29 | i += 1 30 | end 31 | return i * (i + 1) ÷ 2 32 | end 33 | -------------------------------------------------------------------------------- /src/project_euler/problem_014.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Longest Collatz Sequence 3 | 4 | The following iterative sequence is defined for the set of positive integers: 5 | n -> n/2 (n is even) 6 | n -> 3n+1 (n is odd) 7 | Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1. 8 | Which starting number, under one million, produces the longest chain? 9 | 10 | # Input parameters: 11 | - `n` : upper bound on the starting number 12 | 13 | # Examples/Tests: 14 | ```julia 15 | problem_014(10) # returns 9 16 | problem_014(250) # returns 231 17 | problem_014(1000000) # returns 837799 18 | problem_014(-1) # throws DomainError 19 | ``` 20 | 21 | # Reference 22 | - https://projecteuler.net/problem=14 23 | 24 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 25 | """ 26 | function problem_014(n::Int64) 27 | n < 1 && throw(DomainError("n must be a natural number")) 28 | return argmax(collatz_length, 1:n) 29 | end 30 | 31 | cache = Dict{Int64,Int64}(1 => 1) 32 | function collatz_length(x::Int64) 33 | # If result already in cache, then return it 34 | haskey(cache, x) && return cache[x] 35 | 36 | # Recursively call the function and update the cache 37 | return cache[x] = if x % 2 == 0 38 | 1 + collatz_length(x ÷ 2) 39 | else 40 | 2 + collatz_length((3x + 1) ÷ 2) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /src/project_euler/problem_015.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Lattice Paths 3 | 4 | Starting in the top left corner of a grid, and only being able to move to the 5 | right and down, there are exactly 6 routes to the bottom right corner. How many 6 | such routes are there through a 20 x 20 grid? 7 | grid? 8 | 9 | # Input parameters: 10 | - `n` : number of rows in the grid 11 | - `m` : number of columns in the grid 12 | 13 | # Examples/Tests: 14 | ```julia 15 | problem_015(2, 2) # returns 6 16 | problem_015(5, 3) # returns 56 17 | problem_015(20, 20) # returns 137846528820 18 | problem_015(0, 5) # throws DomainError 19 | problem_015(-3, 0) # throws DomainError 20 | ``` 21 | 22 | # Reference 23 | - https://projecteuler.net/problem=15 24 | 25 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 26 | """ 27 | function problem_015(n::T, m::T) where {T<:Integer} 28 | #= 29 | The path is a combination of rights and downs, with a total of n + m operations 30 | We need to count the number of such combinations of n rights and m downs 31 | This is equivalent to finding the binomial coefficient (n+m, m) or (n+m, n) 32 | Note that both of them are equivalent 33 | =# 34 | (n <= 1 || m <= 1) && throw(DomainError("n and m must be greater than 1")) 35 | return binomial(BigInt(n + m), BigInt(n)) 36 | end 37 | -------------------------------------------------------------------------------- /src/project_euler/problem_016.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Power Digit Sum 3 | 4 | 2^15 = 32768 and the sum of its digits is 3+2+7+6+8=26. 5 | What is the sum of the digits of the number 2^1000? 6 | grid? 7 | 8 | # Input parameters: 9 | - `a` : base 10 | - `n` : exponent 11 | 12 | # Examples/Tests: 13 | ```julia 14 | problem_016(1, 1) # returns 1 15 | problem_016(2, 15) # returns 26 16 | problem_016(2, 1000) # returns 1366 17 | problem_016(2, -4) # throws DomainError 18 | ``` 19 | 20 | # Reference 21 | - https://projecteuler.net/problem=16 22 | 23 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 24 | """ 25 | function problem_016(a::T, n::T) where {T<:Integer} 26 | (a <= 0 || n <= 0) && throw(DomainError("a and n must be greater than 1")) 27 | return sum(parse(Int, digit) for digit in string(big(a)^n)) 28 | end 29 | -------------------------------------------------------------------------------- /src/project_euler/problem_017.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Number Letter Counts 3 | 4 | If the numbers 1 to 5 are written out in words, then there are 3+3+5+4+4=19 letters used in total. 5 | If all the numbers from 1 to 1000 inclusive were written out in words, how many letters would be used? 6 | 7 | # Examples/Tests: 8 | ```julia 9 | problem_017() # returns 21124 10 | ``` 11 | 12 | # Reference 13 | - https://projecteuler.net/problem=17 14 | 15 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 16 | """ 17 | function problem_017() 18 | # Hardcore letter counts for unpredictable values 19 | letter_count = Dict( 20 | 0 => 0, # Base case 21 | 1 => 3, # "one" 22 | 2 => 3, # "two" 23 | 3 => 5, # "three" 24 | 4 => 4, # "four" 25 | 5 => 4, # "five" 26 | 6 => 3, # "six" 27 | 7 => 5, # "seven" 28 | 8 => 5, # "eight" 29 | 9 => 4, # "nine" 30 | 10 => 3, # "ten" 31 | 11 => 6, # "eleven" 32 | 12 => 6, # "twelve" 33 | 13 => 8, # "thirteen" 34 | 14 => 8, # "fourteen" 35 | 15 => 7, # "fifteen" 36 | 16 => 7, # "sixteen" 37 | 17 => 9, # "seventeen" 38 | 18 => 8, # "eighteen" 39 | 19 => 8, # "nineteen" 40 | 20 => 6, # "twenty" 41 | 30 => 6, # "thirty" 42 | 40 => 5, # "forty" 43 | 50 => 5, # "fifty" 44 | 60 => 5, # "sixty" 45 | 70 => 7, # "seventy" 46 | 80 => 6, # "eighty" 47 | 90 => 6, # "ninety" 48 | 1000 => 11, # "one thousand" 49 | ) 50 | 51 | # For two digit numbers, add the tens place count and the units place count 52 | for num in 21:99 53 | letter_count[num] = letter_count[num-num%10] + letter_count[num%10] 54 | end 55 | 56 | # For three digit numbers, add the hundreds digit and then the rest 57 | for num in 100:999 58 | hundreds_digit = num ÷ 100 59 | rest = num % 100 60 | letter_count[num] = 61 | letter_count[hundreds_digit] + letter_count[rest] + 7 # 7 for the "hundred" 62 | if rest > 0 63 | letter_count[num] += 3 # 3 for the "and" 64 | end 65 | end 66 | 67 | return sum(values(letter_count)) 68 | end 69 | -------------------------------------------------------------------------------- /src/project_euler/problem_018.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Maximum Path Sum I 3 | 4 | By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23. 5 | 6 | 3 7 | 7 4 8 | 2 4 6 9 | 8 5 9 3 10 | 11 | Find the maximum total from top to bottom of the triangle below. 12 | 13 | # Examples/Tests: 14 | ```julia 15 | problem_018() # returns 1074 16 | ``` 17 | 18 | # Reference 19 | - https://projecteuler.net/problem=18 20 | 21 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 22 | """ 23 | function problem_018() 24 | triangle = [ 25 | [75], 26 | [95 64], 27 | [17 47 82], 28 | [18 35 87 10], 29 | [20 04 82 47 65], 30 | [19 01 23 75 03 34], 31 | [88 02 77 73 07 63 67], 32 | [99 65 04 28 06 16 70 92], 33 | [41 41 26 56 83 40 80 70 33], 34 | [41 48 72 33 47 32 37 16 94 29], 35 | [53 71 44 65 25 43 91 52 97 51 14], 36 | [70 11 33 28 77 73 17 78 39 68 17 57], 37 | [91 71 52 38 17 14 91 43 58 50 27 29 48], 38 | [63 66 04 68 89 53 67 30 73 16 69 87 40 31], 39 | [04 62 98 27 23 09 70 98 73 93 38 53 60 04 23], 40 | ] 41 | 42 | #= 43 | We create a dp table, where the state dp[i][j] is the maximum sum ending at (i, j). 44 | The transition is dp[i][j] = triangle[i][j] + max(dp[i-1][j-1], dp[i-1][j]). 45 | We then return the max of the last row, which is the required maximum total. 46 | =# 47 | 48 | dp = deepcopy(triangle) 49 | for (row_num, row) in enumerate(triangle) 50 | row_num == 1 && continue 51 | for col_num in eachindex(row) 52 | if col_num == 1 53 | prev_best = dp[row_num-1][col_num] 54 | elseif col_num == row_num 55 | prev_best = dp[row_num-1][col_num-1] 56 | else 57 | prev_best = 58 | max(dp[row_num-1][col_num], dp[row_num-1][col_num-1]) 59 | end 60 | 61 | dp[row_num][col_num] += prev_best 62 | end 63 | end 64 | 65 | return maximum(last(dp)) 66 | end 67 | -------------------------------------------------------------------------------- /src/project_euler/problem_019.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Counting Sundays 3 | 4 | How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)? 5 | 6 | # Input parameters: 7 | - `start_year` : start from 1st January of start_year 8 | - `end_year` : check till 31st December of end_year 9 | 10 | # Examples/Tests: 11 | ```julia 12 | problem_019(1901, 2000) # returns 171 13 | problem_019(1901, 2200) # returns 515 14 | problem_019(2020, 2023) # returns 6 15 | problem_019(-1, 2023) # throws DomainError 16 | ``` 17 | 18 | # Reference 19 | - https://projecteuler.net/problem=19 20 | 21 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 22 | """ 23 | function problem_019(start_year::T, end_year::T) where {T<:Integer} 24 | (start_year <= 0 || end_year <= 0) && 25 | throw(DomainError("years must be greater than 1")) 26 | 27 | days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] 28 | 29 | res = 0 30 | cur_day = zeller_congruence(1, 1, start_year) 31 | is_leap(year) = year % 400 == 0 || (year % 100 != 0 && year % 4 == 0) 32 | for year in start_year:end_year 33 | for (month_index, num_days) in enumerate(days_in_month) 34 | cur_day += num_days 35 | if month_index == 2 && is_leap(year) # Leap year and February 36 | cur_day += 1 # then extra day 37 | end 38 | cur_day %= 7 39 | res += cur_day == 0 40 | end 41 | end 42 | 43 | return res 44 | end 45 | 46 | """ 47 | Zeller's Congruence 48 | 49 | Given a date, returns the day of the week 50 | 51 | 0 => Sunday 1 => Monday, 2 => Tuesday, ... , 6 => Saturday 52 | 53 | # Input parameters: 54 | - `day` : day of the month 55 | - `month` : month of the year (1 indexed) 56 | - `year` : year 57 | 58 | # Reference 59 | - https://en.wikipedia.org/wiki/Zeller%27s_congruence 60 | """ 61 | function zeller_congruence(day::T, month::T, year::T) where {T<:Integer} 62 | if month <= 2 63 | month += 12 # January and February are counted as the previous year's 13th and 14th month 64 | year -= 1 65 | end 66 | q = day 67 | m = month 68 | K = year % 100 69 | J = year ÷ 100 70 | 71 | h = q + (13 * (m + 1)) ÷ 4 + K + K ÷ 4 + J ÷ 4 - 2 * J 72 | return (h + 4) % 7 73 | end 74 | -------------------------------------------------------------------------------- /src/project_euler/problem_020.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Factorial Digit Sum 3 | 4 | Find the sum of the digits in the number 100!. 5 | 6 | # Input parameters: 7 | - `n` : number to find sum of digits of factorial of 8 | 9 | # Examples/Tests: 10 | ```julia 11 | problem_020(10) # returns 27 12 | problem_020(37) # returns 153 13 | problem_020(100) # returns 648 14 | problem_020(-1) # throws DomainError 15 | ``` 16 | 17 | # Reference 18 | - https://projecteuler.net/problem=20 19 | 20 | Contributed by: [Praneeth Jain](https://www.github.com/PraneethJain) 21 | """ 22 | function problem_020(n::T) where {T<:Integer} 23 | n < 0 && throw(DomainError("n must be a non-negative integer")) 24 | return mapreduce( 25 | x -> Int(x) - Int('0'), 26 | +, 27 | collect(string(factorial(big(n)))), 28 | ) 29 | end 30 | -------------------------------------------------------------------------------- /src/project_rosalind/ProjectRosalind.jl: -------------------------------------------------------------------------------- 1 | """ 2 | ProjectRosalind 3 | 4 | `ProjectRosalind` naive solutions and algorithms. 5 | """ 6 | module ProjectRosalind 7 | 8 | export count_nucleotides 9 | export dna2rna 10 | export reverse_complement 11 | export rabbits 12 | 13 | include("count_nucleotide.jl") 14 | include("dna2_rna.jl") 15 | include("reverse_complement.jl") 16 | include("rabbits.jl") 17 | 18 | end 19 | -------------------------------------------------------------------------------- /src/project_rosalind/count_nucleotide.jl: -------------------------------------------------------------------------------- 1 | """ 2 | count_nucleotides(s::AbstractString) 3 | Given: A DNA string s 4 | 5 | of length at most 1000 nt. 6 | 7 | Return: Four integers (separated by spaces) counting the respective number of times that the symbols 'A', 'C', 'G', and 'T' occur in s 8 | """ 9 | function count_nucleotides(s::AbstractString) 10 | return join(map(y -> count(x -> x == y, s), ['A', 'C', 'G', 'T']), " ") 11 | end 12 | -------------------------------------------------------------------------------- /src/project_rosalind/dna2_rna.jl: -------------------------------------------------------------------------------- 1 | """ 2 | dna2rna(s::AbstractString) 3 | Given: A DNA string t 4 | 5 | having length at most 1000 nt. 6 | 7 | Return: The transcribed RNA string of t 8 | """ 9 | function dna2rna(s::AbstractString) 10 | return replace(s, 'T' => 'U') 11 | end 12 | -------------------------------------------------------------------------------- /src/project_rosalind/rabbits.jl: -------------------------------------------------------------------------------- 1 | """ 2 | rabbits(n::Integer, k::Integer) 3 | 4 | Problem: https://rosalind.info/problems/fib/ 5 | 6 | Given: Two numbers: 7 | - n => number of months 8 | - k => number of rabbits litter per each pair 9 | 10 | Returns: Number of rabbits after n months 11 | 12 | Contributed by:- [Nikola Mircic](https://github.com/Nikola-Mircic) 13 | """ 14 | 15 | function rabbits(n::Integer, k::Integer) 16 | # For calculating the number of rabbit pairs, we will only need the last two months 17 | # and instead of the array with n elements, we will only use two variables 18 | a = 1 # First generation 19 | b = 1 # Second generation 20 | # Calculate the number of rabbits for each generation from 3rd to nth 21 | for i in 3:n 22 | # Every rabbit pair older than month will give 3 new pairs 23 | # so the number of rabbits in k-th month is a[k] = a[k-1] + a[k-2] * 3 24 | t = b 25 | b = b + 3 * a 26 | a = t 27 | end 28 | return b 29 | end 30 | -------------------------------------------------------------------------------- /src/project_rosalind/reverse_complement.jl: -------------------------------------------------------------------------------- 1 | """ 2 | reverse_complement(s::AbstractString) 3 | Given: A DNA string s of length at most 1000 bp. 4 | 5 | Return: The reverse complement s^c of s. 6 | """ 7 | 8 | function reverse_complement(s::AbstractString) 9 | rules = Dict('A' => 'T', 'T' => 'A', 'G' => 'C', 'C' => 'G') 10 | return map(x -> rules[x], reverse(s)) 11 | end 12 | -------------------------------------------------------------------------------- /src/scheduling/Scheduling.jl: -------------------------------------------------------------------------------- 1 | export Scheduling 2 | """ 3 | Scheduling 4 | 5 | `Scheduling` algorithms in Julia. 6 | """ 7 | module Scheduling 8 | 9 | using TheAlgorithms 10 | 11 | export fcfs 12 | 13 | include("fcfs.jl") 14 | 15 | end 16 | -------------------------------------------------------------------------------- /src/scheduling/fcfs.jl: -------------------------------------------------------------------------------- 1 | """ 2 | fcfs(n, process_id, burst_time) 3 | 4 | Implementation of first come first served scheduling algorithm 5 | 6 | # Output 7 | Tuple of vectors (process_id, burst_time, waiting_time, turnaround_time, avg_waiting_time, avg_turnaround_time) 8 | 9 | # Example 10 | 11 | ```julia 12 | n = 3 # number of processes 13 | process_id = Any[1, 2, 3] # process ids 14 | burst_times = Any[3, 4, 5] # burst times 15 | fcfs(n, process_id, burst_times) 16 | ``` 17 | # Reference 18 | 19 | https://en.wikipedia.org/wiki/Scheduling_(computing)#First_come,_first_served 20 | 21 | Contributed By:- [Ashwani Rathee](https://github.com/ashwani-rathee) 22 | """ 23 | function fcfs(n, process_id, burst_time) 24 | waiting_time = [] 25 | push!(waiting_time, 0) 26 | for i in 2:n 27 | # Calculates waiting time 28 | push!(waiting_time, burst_time[i-1] + waiting_time[i-1]) 29 | end 30 | 31 | turnaround_time = [] 32 | for i in 1:n 33 | # Calculates turnaround time 34 | push!(turnaround_time, burst_time[i] + waiting_time[i]) 35 | end 36 | 37 | # Calculates Average waiting time 38 | avg_waiting_time = sum(waiting_time) / length(waiting_time) 39 | 40 | # Calculates Average turnaround time 41 | avg_turnaround_time = sum(turnaround_time) / length(turnaround_time) 42 | 43 | return process_id, 44 | burst_time, 45 | waiting_time, 46 | turnaround_time, 47 | avg_waiting_time, 48 | avg_turnaround_time 49 | end 50 | -------------------------------------------------------------------------------- /src/searches/Searches.jl: -------------------------------------------------------------------------------- 1 | export Searches 2 | """ 3 | Searches 4 | 5 | `Searches` - search algorithms. 6 | """ 7 | module Searches 8 | 9 | using TheAlgorithms 10 | 11 | export binary_search 12 | export exponential_search 13 | export interpolation_search 14 | export jump_search 15 | export linear_search 16 | 17 | include("binary_search.jl") 18 | include("exponential_search.jl") 19 | include("interpolation_search.jl") 20 | include("jump_search.jl") 21 | include("linear_search.jl") 22 | end 23 | -------------------------------------------------------------------------------- /src/searches/exponential_search.jl: -------------------------------------------------------------------------------- 1 | """ 2 | exponential_search(arr::AbstractArray{T,1}, x::T) where {T <: Real} 3 | 4 | Exponential Search in 1-D array 5 | Time Complexity: O(Log n) 6 | # Exponential Search 7 | It works in O(Log n) time 8 | Exponential search involves two steps: 9 | - Find range where element is present 10 | - Do Binary Search in above found range. 11 | ### Time Complexity : 12 | O(Log n) 13 | Applications of Exponential Search: 14 | Exponential Binary Search is particularly useful for unbounded searches, where size of array is infinite. Please refer Unbounded Binary Search for an example. 15 | It works better than Binary Search for bounded arrays, and also when the element to be searched is closer to the first element. 16 | 17 | Contributed By:- [Ash](https://github.com/ashwani-rathee) 18 | """ 19 | function exponential_search(arr::AbstractArray{T,1}, x::T) where {T<:Real} 20 | n = size(arr)[1] 21 | if (arr[1] == x) 22 | return 1 23 | end 24 | 25 | i = 1 26 | while (i < n && arr[i] <= x) 27 | i = i * 2 28 | end 29 | return binary_search(arr, Int(ceil(i / 2)), min(i, n), x) 30 | end 31 | -------------------------------------------------------------------------------- /src/searches/interpolation_search.jl: -------------------------------------------------------------------------------- 1 | """ 2 | # Interpolation Search 3 | Used for sorted array which is uniformly distributed. 4 | Binary Search always goes to the middle element to check. On the other hand, interpolation search may go to different locations according to the value of the key being searched. For example, if the value of the key is closer to the last element, interpolation search is likely to start search toward the end side. 5 | The idea of formula is to return higher value of pos when element to be searched is closer to arr[hi]. And smaller value when closer to arr[lo] 6 | pos = lo + [ (x-arr[lo])*(hi-lo) / (arr[hi]-arr[Lo]) ] 7 | - arr[] ==> Array where elements need to be searched 8 | - x ==> Element to be searched 9 | - lo ==> Starting index in arr[] 10 | - hi ==> Ending index in arr[] 11 | ## Derivation => 12 | Let's assume that the elements of the array are linearly distributed. 13 | General equation of line : y = m*x + c. 14 | y is the value in the array and x is its index. 15 | Now putting value of lo,hi and x in the equation 16 | - arr[hi] = m*hi+c ----(1) 17 | - arr[lo] = m*lo+c ----(2) 18 | - x = m*pos + c ----(3) 19 | m = (arr[hi] - arr[lo] )/ (hi - lo) 20 | subtracting eqxn (2) from (3) 21 | - x - arr[lo] = m * (pos - lo) 22 | - lo + (x - arr[lo])/m = pos 23 | - pos = lo + (x - arr[lo]) *(hi - lo)/(arr[hi] - arr[lo]) 24 | ## Algorithm: 25 | Rest of the Interpolation algorithm is the same except the above partition logic. 26 | - Step1: In a loop, calculate the value of “pos” using the probe position formula. 27 | - Step2: If it is a match, return the index of the item, and exit. 28 | - Step3: If the item is less than arr[pos], calculate the probe position of the left sub-array. Otherwise calculate the same in the right sub-array. 29 | - Step4: Repeat until a match is found or the sub-array reduces to zero. 30 | 31 | """ 32 | 33 | """ 34 | interpolation_search(arr::AbstractArray{T,1}, l::T, r::T, x::T) where {T <: Real} 35 | 36 | Interpolation Search in 1-D array 37 | Time Complexity: O(log2(log2 n)) 38 | """ 39 | function interpolation_search( 40 | arr::AbstractArray{T,1}, 41 | l::T, 42 | r::T, 43 | x::T, 44 | ) where {T<:Real} 45 | n = size(arr)[1] 46 | if (r >= l && x >= arr[l] && x <= arr[r]) 47 | mid = Int(ceil(l + (((x - arr[l]) * (r - l)) / (arr[r] - arr[l])))) 48 | if (arr[mid] == x) 49 | return mid 50 | elseif (arr[mid] > x) 51 | interpolation_search(arr, l, mid - 1, x) 52 | else 53 | interpolation_search(arr, mid + 1, r, x) 54 | end 55 | else 56 | return -1 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /src/searches/jump_search.jl: -------------------------------------------------------------------------------- 1 | """ 2 | # Jump Search(sorted array) 3 | Jump Search is a searching algorithm for sorted arrays. The basic idea is to check fewer elements (than linear search) by jumping ahead by fixed steps or skipping some elements in place of searching all elements. 4 | For example, suppose we have an array arr[] of size n and block (to be jumped) size m. Then we search at the indexes arr[0], arr[m], arr[2m]…..arr[km] and so on. Once we find the interval (arr[km] < x < arr[(k+1)m]), we perform a linear search operation from the index km to find the element x. 5 | Let’s consider the following array: (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610). Length of the array is 16. Jump search will find the value of 55 with the following steps assuming that the block size to be jumped is 4. 6 | - STEP 1: Jump from index 0 to index 4; 7 | - STEP 2: Jump from index 4 to index 8; 8 | - STEP 3: Jump from index 8 to index 12; 9 | - STEP 4: Since the element at index 12 is greater than 55 we will jump back a step to come to index 8. 10 | - STEP 5: Perform linear search from index 8 to get the element 55. 11 | ## What is the optimal block size to be skipped? 12 | In the worst case, we have to do n/m jumps and if the last checked value is greater than the element to be searched for, we perform m-1 comparisons more for linear search. Therefore the total number of comparisons in the worst case will be ((n/m) + m-1). The value of the function ((n/m) + m-1) will be minimum when m = √n. Therefore, the best step size is m = √n. 13 | """ 14 | 15 | """ 16 | jump_search(arr::AbstractArray{T,1}, x::T, jump::T = Int(ceil(sqrt(n)))) where {T <: Real} 17 | Jump Search in 1-D array 18 | Time Complexity : O(√ n) 19 | Time complexity of Jump Search is between Linear Search ( ( O(n) ) and Binary Search ( O (Log n) ) 20 | """ 21 | function jump_search( 22 | arr::AbstractArray{T,1}, 23 | x::T, 24 | jump::T = Int(ceil(sqrt(n))), 25 | ) where {T<:Real} 26 | n = size(arr)[1] 27 | start = 1 28 | final = jump 29 | while (arr[final] <= x && final < n) 30 | start = final 31 | final = final + jump 32 | if (final > n - 1) 33 | final = n 34 | end 35 | end 36 | for i in start:final 37 | if (arr[i] == x) 38 | return i 39 | end 40 | end 41 | return -1 42 | end 43 | -------------------------------------------------------------------------------- /src/searches/linear_search.jl: -------------------------------------------------------------------------------- 1 | """ 2 | linear_search(array, key) 3 | A simple search of `array`, element per element until `key` is found. 4 | """ 5 | function linear_search(array, key) 6 | for i in 1:length(array) 7 | if array[i] == key 8 | return i 9 | end 10 | end 11 | return -1 12 | end 13 | -------------------------------------------------------------------------------- /src/sorts/Sorts.jl: -------------------------------------------------------------------------------- 1 | export Sorts 2 | 3 | """ 4 | Sorts 5 | 6 | `Sorts` are sorting algorithms in Julia. 7 | """ 8 | module Sorts 9 | 10 | using TheAlgorithms 11 | 12 | export bogo_sort! 13 | export bubble_sort! 14 | export bucket_sort! 15 | export counting_sort! 16 | export exchange_sort! 17 | export heap_sort! 18 | export insertion_sort! 19 | export merge_sort! 20 | export quick_sort! 21 | export selection_sort! 22 | 23 | include("bogo_sort.jl") 24 | include("bubble_sort.jl") 25 | include("bucket_sort.jl") 26 | include("counting_sort.jl") 27 | include("exchange_sort.jl") 28 | include("heap_sort.jl") 29 | include("insertion_sort.jl") 30 | include("merge_sort.jl") 31 | include("quick_sort.jl") 32 | include("selection_sort.jl") 33 | 34 | end 35 | -------------------------------------------------------------------------------- /src/sorts/bogo_sort.jl: -------------------------------------------------------------------------------- 1 | """ 2 | BogoSort(array) 3 | 4 | Sort an array by randomly shuffling its elements and checking if the resulting array is sorted. 5 | 6 | Bogo Sort Steps 7 | 1. Randomly rearrange elements in array 8 | 2. Check if sorted. If not, repeat step 1 9 | """ 10 | 11 | using Random 12 | 13 | function bogo_sort!(array::Vector{T}) where {T} 14 | while !issorted(array) 15 | Random.shuffle!(array) 16 | end 17 | return (array) 18 | end 19 | -------------------------------------------------------------------------------- /src/sorts/bubble_sort.jl: -------------------------------------------------------------------------------- 1 | function bubble_sort!(array::Vector{T}) where {T} 2 | for i in 1:length(array) 3 | flag = false 4 | for j in 1:(length(array)-i) 5 | if array[j] > array[j+1] 6 | array[j], array[j+1] = array[j+1], array[j] 7 | flag = true 8 | end 9 | end 10 | 11 | if !flag 12 | return nothing 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /src/sorts/bucket_sort.jl: -------------------------------------------------------------------------------- 1 | """ 2 | # Bucket Sort 3 | 4 | Bucket Sort is a divide and conquer sorting algorithm. 5 | It distributes elements into buckets and sort each bucket before merging all buckets 6 | Buckets are arrays that each stores a different range of elements 7 | Insertion sort is used to sort the buckets because its fast in small-sized arrays 8 | 9 | ## Bucket Calculation 10 | 11 | number of buckets = length of array 12 | size of buckets = (largest element - smallest element + 1) / length of array 13 | 14 | ## Bucket Sort Steps 15 | 16 | 1. Create an array of buckets 17 | 2. Add each elements into its respective bucket 18 | 3. Sort each non-empty bucket 19 | 4. Concatenate elements of non-empty buckets 20 | 21 | ## Example 22 | 23 | 1. Array of [3, 5, 2, 9] has 4 buckets 24 | 2. The size of buckets = (9 - 2 + 1) / 4 = 2 25 | 3. The range of elements can be assign to each bucket, x 26 | bucket 1: 2 <= x < 4 27 | bucket 2: 4 <= x < 6 28 | bucket 3: 6 <= x < 8 29 | bucket 4: 8 <= x <= 9 30 | 4. The distribution of elements in the buckets = [3, 2][5][][9] 31 | 5. After sorting the elements each bucket = [2, 3][5][][9] 32 | 6. Concatenate all elements = [2, 3, 5, 9] 33 | 34 | # Example 35 | ```julia 36 | BucketSort!([3, 5, 2, 9]) # returns [2, 3, 5, 9] 37 | ``` 38 | 39 | Contributed By:- [Ming Liang](https://github.com/DrakonDarquesse) 40 | """ 41 | 42 | function bucket_sort!(arr::Vector{T}, l::Int = length(arr)) where {T} 43 | if l == 0 44 | return nothing 45 | end 46 | 47 | max = maximum(arr) 48 | min = minimum(arr) 49 | r = (max - min + 1) / l 50 | buckets = Array{T,1}[[] for a in 1:l] 51 | 52 | for i in arr 53 | push!(buckets[Base.floor(Int, (i - min) / r)+1], i) 54 | end 55 | 56 | for bucket in buckets 57 | for i in 1:length(bucket) 58 | val = bucket[i] 59 | idx = i 60 | while idx > 1 && val < bucket[idx-1] 61 | bucket[idx] = bucket[idx-1] 62 | idx = idx - 1 63 | end 64 | 65 | bucket[idx] = val 66 | end 67 | end 68 | return copy!(arr, vcat(buckets...)) 69 | end 70 | -------------------------------------------------------------------------------- /src/sorts/counting_sort.jl: -------------------------------------------------------------------------------- 1 | """ 2 | # Counting Sort 3 | OVERVIEW: 4 | Counting Sort is a sorting algorithm that sort elements within a specific range. 5 | The sorting technique is to count the existing element and stored its occurrence time in a new list, then only print it out. 6 | 7 | STEPS: 8 | Assume the input as --> x=[-3, 1, -5, 0, -3] 9 | minimum = -5 10 | - STEP 1: Create a list size within the range, in this case is -5 --> 1 which have range of 7 (-5, -4, -3, -2, -1, 0, 1), so list with size 7 and assign all to 0 is created 11 | - STEP 2: Count the occurances of element in the list 12 | First number = -3 it is the third number in the range, so count[3]+=1 13 | Final view: 14 | index : ( 1, 2, 3, 4, 5, 6, 7) 15 | range : (-5, -4, -3, -2, -1, 0, 1) 16 | count : [ 1, 0, 2, 0, 0, 1, 1] <-- the list will store this occurrence 17 | - STEP 3: Make the count list accumulate the occurances 18 | The final count is (1, 1, 3, 3, 3, 4, 5) 19 | - STEP 4: Assign the elements in x into correct possition by creating a new list (will call 'output' in this sample) 20 | the 1st element in 'x' is -3, it is third in range, so it will call the index of 3 in 'count', which is 3 and assign the -3 in to 3rd position in 'output', 21 | then the third element in range will deduct by 1, so the next repeated element will get the correct position, new 'count' --> [1, 1, 2, 3, 3, 4, 5] 22 | 23 | the 2nd element in 'x' is 1, it is last in range, so it will call the index of 7 in 'count', which is 5 and assign the 1 in to 5th position in 'output', 24 | new 'count' --> [1, 1, 2, 3, 3, 4, 4] 25 | ...... 26 | ...... 27 | *If you want the order of original array to have the same order as the output array use can change this to decremental for loop 28 | - STEP 5: Assign the 'output' list back to 'x' 29 | 30 | FINAL RESULT --> [-5, -3, -3, 0, 1] 31 | """ 32 | function counting_sort!( 33 | arr::Vector{T}, 34 | l::Int = 1, 35 | r::Int = length(arr), 36 | ) where {T} 37 | if l >= r 38 | return nothing 39 | end 40 | max = maximum(arr) 41 | min = minimum(arr) 42 | range = max - min + 1 43 | count = Vector{T}(undef, range) 44 | output = Vector{T}(undef, r) 45 | 46 | for i in 1:range 47 | count[i] = 0 48 | end 49 | 50 | # Store count of the item that appear in the 'arr' (STEP 2) 51 | for i in 1:r 52 | count[arr[i]-min+1] += 1 53 | end 54 | 55 | # Calculate cumulative frequency in 'count' (STEP 3) 56 | for i in 2:length(count) 57 | count[i] += count[i-1] 58 | end 59 | 60 | # Build the 'output' by assigning the item into correct position (STEP 4) 61 | for i in 1:r 62 | index = arr[i] - min + 1 63 | output[count[index]] = arr[i] 64 | count[index] -= 1 65 | end 66 | 67 | # Copy the 'output' to 'arr', so that 'arr' contain sorted item (STEP 5) 68 | for i in 1:r 69 | arr[i] = output[i] 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /src/sorts/exchange_sort.jl: -------------------------------------------------------------------------------- 1 | """ 2 | ExchangeSort(arr) 3 | 4 | Sort an array by exchanging elements that are not in their proper position, hence Exchange Sort 5 | 6 | Exchange Sort Steps 7 | 1. Compares each element of an array 8 | 2. Swap those elements that are not in their proper position 9 | 10 | Example 11 | 1. An array of [1, 2, 4, 3, 5] and compare each elements 12 | 2. Since 4 is greater than 3 13 | 3. Swap both position 14 | 4. Returns [1, 2, 3, 4, 5] 15 | 16 | Program to sort an array 17 | 18 | # Example 19 | ```julia 20 | ExchangeSort([5, 4, 3, 2, 1]) # returns [1, 2, 3, 4, 5] 21 | ExchangeSort([1, 2, 3, 4, 5]) # returns [1, 2, 3, 4, 5] 22 | ExchangeSort(['5', '4', '3', '2', '1']) # returns ['1', '2', '3', '4', '5'] 23 | ``` 24 | 25 | Contributed By:- [Gervin Fung](https://github.com/GervinFung) 26 | """ 27 | 28 | function exchange_sort!(arr::Vector{T}) where {T} 29 | size = length(arr) 30 | for i in 1:size 31 | for j in i:size 32 | if (arr[i] > arr[j]) 33 | temp = arr[j] 34 | arr[j] = arr[i] 35 | arr[i] = temp 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /src/sorts/heap_sort.jl: -------------------------------------------------------------------------------- 1 | """ 2 | idx_for(i::Int) 3 | 4 | Simple helper function for converting 0-based indices to Julia's 1-based indices. 5 | """ 6 | function idx_for(i::Int) 7 | return i + 1 8 | end 9 | 10 | """ 11 | heap_sort!(arr::Vector{T}, gt = >, N::Int = length(arr)) where {T} 12 | 13 | Sort the given vector (in-place) using the Heapsort algorithm. 14 | 15 | Heapsort consists of two stages: 16 | 1. Building a (max) heap of the array 17 | 2. Repeatedly extracting the largest element and inserting it at the front of the sorted part of the array 18 | 19 | After the largest element has been extracted, the tree is updated to maintain the heap property via a "sifting" operation. 20 | 21 | Storing a heap in an array is pretty straightforward - for every node with index n, its children are stored at indices 22 | 2n + 1 and 2n + 2 (for 0-based indices). Index 0 contains the root node. 23 | Since Julia's indices are 1-based, we need to change this a little bit. We're using a trivial helper function 24 | idx_for to convert from 0-based to 1-based. 25 | 26 | See https://en.wikipedia.org/wiki/Heapsort for a complete explanation of Heapsort. 27 | 28 | Contributed By:- [Frank Schmitt](https://github.com/frankschmitt) 29 | """ 30 | function heap_sort!(arr::Vector{T}, gt = >, N::Int = length(arr)) where {T} 31 | if isempty(arr) 32 | return 33 | end 34 | n = N 35 | i = div(n, 2) 36 | t = -1 37 | 38 | while true 39 | if i > 0 # First stage - Sorting the heap 40 | i -= 1 # Save its index to i 41 | t = arr[idx_for(i)] # Save parent value to t 42 | else # Second stage - Extracting elements in-place 43 | n -= 1 # Make the new heap smaller 44 | if (n == 0) 45 | return # When the heap is empty, we are done 46 | end 47 | t = arr[idx_for(n)] # Save last value (it will be overwritten) 48 | arr[idx_for(n)] = arr[idx_for(0)] # Save largest value at the end of arr 49 | end 50 | 51 | parent = i # We will start pushing down t from parent 52 | child = i * 2 + 1 # parent's left child 53 | 54 | # Sift operation - pushing the value of t down the heap 55 | while child < n 56 | if ( 57 | child + 1 < n && 58 | gt(arr[idx_for(child + 1)], arr[idx_for(child)]) 59 | ) 60 | child += 1 # Choose the largest child 61 | end 62 | if (gt(arr[idx_for(child)], t)) # If any child is bigger than the parent 63 | arr[idx_for(parent)] = arr[idx_for(child)] # Move the largest child up 64 | parent = child # Move parent pointer to this child 65 | child = parent * 2 + 1 # find the next child 66 | else 67 | break # t's place is found 68 | end 69 | end 70 | arr[idx_for(parent)] = t 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /src/sorts/insertion_sort.jl: -------------------------------------------------------------------------------- 1 | function insertion_sort!(arr::Vector{T}) where {T} 2 | for i in 1:length(arr)-1 3 | temp = arr[i+1] 4 | j = i 5 | while j > 0 && arr[j] > temp 6 | arr[j+1] = arr[j] 7 | j -= 1 8 | end 9 | arr[j+1] = temp 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /src/sorts/merge_sort.jl: -------------------------------------------------------------------------------- 1 | function merge_sort!( 2 | arr::Vector{T}, 3 | l::Int = 1, 4 | r::Int = length(arr), 5 | temp::Vector{T} = Vector{T}(undef, r - l + 1), 6 | ) where {T} 7 | if l >= r 8 | return 9 | end 10 | # split 11 | mid = (l + r) >> 1 12 | merge_sort!(arr, l, mid) 13 | merge_sort!(arr, mid + 1, r) 14 | # merge 15 | l_pos = l # pos of the left part 16 | r_pos = mid + 1 # pos of the right part 17 | for t_pos in 1:r-l+1 18 | if l_pos <= mid && (r_pos > r || arr[l_pos] < arr[r_pos]) 19 | temp[t_pos] = arr[l_pos] 20 | l_pos += 1 21 | else 22 | temp[t_pos] = arr[r_pos] 23 | r_pos += 1 24 | end 25 | end 26 | for i in l:r 27 | arr[i] = temp[i-l+1] 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /src/sorts/quick_sort.jl: -------------------------------------------------------------------------------- 1 | function quick_sort!(arr::Vector{T}, l::Int = 1, r::Int = length(arr)) where {T} 2 | if l >= r 3 | return 4 | end 5 | mid = arr[(l+r)>>1] 6 | l_pos = l 7 | r_pos = r 8 | while l_pos <= r_pos 9 | while arr[l_pos] < mid 10 | l_pos += 1 11 | end 12 | while arr[r_pos] > mid 13 | r_pos -= 1 14 | end 15 | if l_pos <= r_pos 16 | t = arr[l_pos] 17 | arr[l_pos] = arr[r_pos] 18 | arr[r_pos] = t 19 | l_pos += 1 20 | r_pos -= 1 21 | end 22 | end 23 | if l < r_pos 24 | quick_sort!(arr, l, r_pos) 25 | end 26 | if l_pos < r 27 | quick_sort!(arr, l_pos, r) 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /src/sorts/selection_sort.jl: -------------------------------------------------------------------------------- 1 | function selection_sort!(arr::Vector{T}) where {T} 2 | l = length(arr) 3 | for i in 1:l-1 4 | place = i 5 | for j in i+1:l 6 | if arr[j] < arr[place] 7 | place = j 8 | end 9 | end 10 | temp = arr[i] 11 | arr[i] = arr[place] 12 | arr[place] = temp 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /src/statistics/StatAlgo.jl: -------------------------------------------------------------------------------- 1 | export StatAlgo 2 | """ 3 | StatAlgo 4 | 5 | `StatAlgo` in Julia 6 | """ 7 | module StatAlgo 8 | 9 | using TheAlgorithms 10 | 11 | export pearson_correlation 12 | export variance 13 | 14 | include("pearson_correlation.jl") 15 | include("variance.jl") 16 | 17 | end 18 | -------------------------------------------------------------------------------- /src/statistics/pearson_correlation.jl: -------------------------------------------------------------------------------- 1 | """ 2 | pearson_correlation(x, y) 3 | 4 | Find the pearson correlation between two variables. 5 | 6 | # Example: 7 | 8 | julia> PearsonCorrelation([12,11,16,17,19,21],[11,51,66,72,12,15]) 9 | -0.2092706263573845 10 | 11 | Contribution by: [Aru Bhardwaj](https://github.com/arubhardwaj) 12 | 13 | 14 | """ 15 | 16 | function pearson_correlation(x, y) 17 | mean_x = sum(x) / length(x) 18 | mean_y = sum(y) / length(y) 19 | XY = (x .- mean_x) .* (y .- mean_y) 20 | XXs = sum((x .- mean_x) .* (x .- mean_x)) 21 | YYs = sum((y .- mean_y) .* (y .- mean_y)) 22 | return (sum(XY) / (sqrt(XXs .* YYs))) 23 | end 24 | -------------------------------------------------------------------------------- /src/statistics/variance.jl: -------------------------------------------------------------------------------- 1 | """ 2 | variance(a) 3 | 4 | Find the variance from a set of data. 5 | 6 | # Arguments: 7 | - `a`: holds the set of data 8 | 9 | # Reference 10 | - According to Ronald E. Walpole, `variance` is used to measure the variability of a set of data. -- Introduction to Statistics by Ronald E. Walpole 11 | 12 | # Contributors: 13 | - [Aru Bhardwaj](https://github.com/arubhardwaj) 14 | """ 15 | function variance(a) 16 | avg = sum(a) / length(a) 17 | x = sum((a .- avg) .^ 2) 18 | s_sq = x / (length(a) - 1) 19 | return (s_sq) 20 | end 21 | -------------------------------------------------------------------------------- /src/strings/StringAlgo.jl: -------------------------------------------------------------------------------- 1 | export StringAlgo 2 | """ 3 | StringAlgo 4 | 5 | `StringAlgo` in Julia. 6 | """ 7 | module StringAlgo 8 | 9 | using TheAlgorithms 10 | 11 | export contain_substring_with_kmp 12 | export ispangram 13 | export detect_anagrams 14 | export is_palindrome 15 | export word_count 16 | export hamming_distance 17 | export rabin_karp 18 | export LCS 19 | export naive_pattern_search 20 | 21 | include("detect_anagrams.jl") 22 | include("is_palindrome.jl") 23 | include("kmp_substring_search.jl") 24 | include("pangram.jl") 25 | include("word_count.jl") 26 | include("hamming_distance.jl") 27 | include("rabin_karp.jl") 28 | include("lcs.jl") 29 | include("naive_pattern_search.jl") 30 | 31 | end 32 | -------------------------------------------------------------------------------- /src/strings/detect_anagrams.jl: -------------------------------------------------------------------------------- 1 | """ 2 | detect_anagrams(subject, candidates) 3 | A function that checks if a list of words 4 | is an [Anagram](https://en.wikipedia.org/wiki/Anagram) or not of a subject word. 5 | 6 | is the original word = subject 7 | is list of words to be compared if they are an anagram of `subject` = candidates 8 | 9 | ``` 10 | julia> subject = "listen" 11 | julia> candidates = ["inlets", "enlists", "google", "banana"] 12 | julia> detect_anagrams(subject, candidates) 13 | 1-element Vector{String}: 14 | "inlets" 15 | ``` 16 | 17 | Contributed By:- [Soc V. E.](https://github.com/ReneganRonin) 18 | Based on my exercism's Julia track problem solution on [Anagrams](https://exercism.io/my/solutions/0a1d39faa5694624b7750be3ebf6c974). 19 | 20 | Instructions: 21 | 22 | An anagram is a rearrangement of letters to form a new word. Given a word and a list of candidates, select the sublist of anagrams of the given word. 23 | Given "listen" and a list of candidates like "enlists" "google" "inlets" "banana" the program should return a list containing "inlets". 24 | 25 | Inspired by the [Extreme Startup game](https://github.com/rchatley/extreme_startup) 26 | """ 27 | function detect_anagrams(subject, candidates) 28 | function condition(i) 29 | return sort(collect(lowercase(subject))) == sort(collect(lowercase(i))) 30 | end 31 | collection = collect( 32 | word for word in candidates if lowercase(word) != lowercase(subject) 33 | ) 34 | return filter(condition, collection) 35 | end 36 | -------------------------------------------------------------------------------- /src/strings/hamming_distance.jl: -------------------------------------------------------------------------------- 1 | """ 2 | function hamming_distance(s1::String, s2::String) 3 | 4 | In information theory, the Hamming distance between two strings of equal length is the number of positions at which the corresponding symbols are different. 5 | In other words, it measures the minimum number of substitutions required to change one string into the other, or the minimum number of errors that could have transformed one string into the other. 6 | In a more general context, the Hamming distance is one of several string metrics for measuring the edit distance between two sequences. It is named after the American mathematician Richard Hamming. 7 | 8 | Reference (https://en.wikipedia.org/wiki/Hamming_distance) 9 | 10 | # Arguments: 11 | - `s1`: First string to compare 12 | - `s2`: Second string to compare 13 | 14 | # Examples/Tests 15 | ```julia 16 | julia> hamming_distance("karolin", "kathrin") 17 | 3 18 | 19 | julia> hamming_distance("0000", "1111") 20 | 4 21 | 22 | julia> hamming_distance("ABCDEFG", "AZCDWGM") 23 | 4 24 | ``` 25 | 26 | # Contributors: 27 | - [Sedat Aybars Nazlica](https://github.com/saybarsnazlica) 28 | """ 29 | 30 | function hamming_distance(s1::String, s2::String) 31 | @assert length(s1) == length(s2) "String lengths must be the same" 32 | 33 | distance = 0 34 | 35 | for i in 1:length(s1) 36 | if s1[i] != s2[i] 37 | distance += 1 38 | end 39 | end 40 | return distance 41 | end 42 | -------------------------------------------------------------------------------- /src/strings/is_palindrome.jl: -------------------------------------------------------------------------------- 1 | """ 2 | is_palindrome(s) 3 | A set of functions to check if a given string 4 | is a palindrome. 5 | 6 | Arguments: 7 | - s - a string =# 8 | """ 9 | 10 | function is_palindrome(s) # Named function 11 | s = lowercase(s) 12 | return s == reverse(s) 13 | end 14 | 15 | s -> s == reverse(s) # Anonymous 16 | -------------------------------------------------------------------------------- /src/strings/lcs.jl: -------------------------------------------------------------------------------- 1 | """ 2 | LCS(a, b) 3 | 4 | # Brief: 5 | A function that finds the longest common subsequence of two strings a and b. 6 | 7 | # For more informations: 8 | https://www.programiz.com/dsa/longest-common-subsequence 9 | 10 | # Contributed by:- [Nikola Mircic](https://github.com/Nikola-Mircic) 11 | """ 12 | 13 | function LCS(a::String, b::String) 14 | # Create a matrix to store previous results 15 | # sol[i+1, j+1] is length of lcs for a[1:i] and b[1:j] 16 | sol = zeros(length(a) + 1, length(b) + 1) 17 | 18 | # Calculate sol 19 | for i in 1:length(a) 20 | for j in 1:length(b) 21 | if a[i] == b[j] 22 | # If a character a[i] is equal to a character b[j], 23 | # new length of lcs will be equal to length without it plus one 24 | sol[i+1, j+1] = sol[i, j] + 1 25 | else 26 | # If characters are different, length will be maximum of two previously calculated lcs 27 | # One is without a[i], and second one is lcs when b[i] is not inluded 28 | sol[i+1, j+1] = max(sol[i+1, j], sol[i, j+1]) 29 | end 30 | end 31 | end 32 | 33 | result = "" 34 | 35 | # Start going trough the matrix from the last value and check which character 36 | # increases the length of lcs, and witch is copied value 37 | i = length(a) + 1 38 | j = length(b) + 1 39 | while i > 1 && j > 1 40 | if sol[i, j] == sol[i, j-1] 41 | # Copied left value 42 | j -= 1 43 | elseif sol[i, j] == sol[i-1, j] 44 | # Copied value above 45 | i -= 1 46 | else 47 | # Value is increased here 48 | result = b[j-1] * result # or a[i-1] * result 49 | i -= 1 50 | j -= 1 51 | end 52 | end 53 | 54 | return result 55 | end 56 | -------------------------------------------------------------------------------- /src/strings/naive_pattern_search.jl: -------------------------------------------------------------------------------- 1 | """ 2 | naive_pattern_search(text, pattern) 3 | 4 | Program to find the given pattern in the given text 5 | 6 | # Arguments: 7 | - 'text': A string to find the pattern 8 | - 'pattern': A string to find in the given text 9 | 10 | # Examples/Tests 11 | ```julia 12 | julia> naive_pattern_search("ABCDEF", "DEF") 13 | "DEF found at index: 3" 14 | 15 | julia> naive_pattern_search("Hello world!", "eggs") 16 | "No matches found" 17 | ``` 18 | 19 | # References: 20 | (https://www.geeksforgeeks.org/naive-algorithm-for-pattern-searching/) 21 | (https://www.tutorialspoint.com/Naive-Pattern-Searching) 22 | 23 | # Contributors: 24 | - [Laptop-Salad](https://github.com/Laptop-Salad) 25 | 26 | """ 27 | 28 | function naive_pattern_search(text, pattern) 29 | for index in 0:(length(text)-length(pattern)+1) 30 | matches = 0 31 | for character in eachindex(pattern) 32 | if pattern[character] == text[index+character] 33 | matches += 1 34 | 35 | if matches == length(pattern) 36 | return string(pattern, " found at index: ", index) 37 | end 38 | else 39 | break 40 | end 41 | end 42 | end 43 | return "No matches found" 44 | end 45 | -------------------------------------------------------------------------------- /src/strings/pangram.jl: -------------------------------------------------------------------------------- 1 | """ 2 | ispangram(input) 3 | 4 | Program to determine the sentence is pangram or not.The program will return true if it is pangram and false if it is not.A full description of the algorithm can be found on [exercism](https://exercism.org/tracks/julia/exercises/pangram) 5 | 6 | # Arguments: 7 | - `input`: The sentence to find if its pangram or not. 8 | 9 | # Examples/Tests 10 | ```julia 11 | julia> ispangram(Pack my box with five dozen liquor jugs) 12 | true 13 | 14 | julia> ispangram(The quick brown fox jumps over the lazy dog) 15 | true 16 | 17 | julia> wordcount(hello world!!!) 18 | false 19 | 20 | ``` 21 | 22 | # Algorithm: 23 | 24 | ```julia 25 | 26 | for letter in input 27 | if 'A' <= letter <= 'Z' 28 | x &= ~(1<<(letter-'A')) 29 | elseif 'a' <= letter <= 'z' 30 | x &= ~(1<<(letter-'a')) 31 | end 32 | x == 0 && return true 33 | end 34 | 35 | ``` 36 | 37 | # References: 38 | (https://exercism.org/tracks/julia/exercises/pangram) 39 | 40 | ``` 41 | 42 | # Contributed by:- [Ihjass Thasbekha](https://github.com/Ihjass) 43 | """ 44 | function ispangram(input) 45 | x = 2^26 - 1 46 | for letter in input 47 | if 'A' <= letter <= 'Z' 48 | x &= ~(1 << (letter - 'A')) 49 | elseif 'a' <= letter <= 'z' 50 | x &= ~(1 << (letter - 'a')) 51 | end 52 | x == 0 && return true 53 | end 54 | return false 55 | end 56 | -------------------------------------------------------------------------------- /src/strings/rabin_karp.jl: -------------------------------------------------------------------------------- 1 | """ 2 | rabin_karp(text, pattern) 3 | 4 | # Brief: 5 | A function that finds all occurrences of a pattern in the given text. 6 | Instead of checking each character ot the pattern with each character block of the text, 7 | for each character block calculate the hash value, and only if that value matches hash value of the pattern, 8 | compare them character by character. These blocks are the same length as the pattern. 9 | 10 | # Returns: 11 | A list with starting indices where the pattern was found 12 | 13 | # References: 14 | https://www.geeksforgeeks.org/rabin-karp-algorithm-for-pattern-searching/ 15 | 16 | # Contributed by: [Nikola Mircic](https://github.com/Nikola-Mircic) 17 | """ 18 | function rabin_karp(text::String, pattern::String) 19 | indices = Array{Int64}(undef, 0)# An array to store matching indices 20 | 21 | txt_len = length(text) # Length of the text 22 | ptn_len = length(pattern) # Length of the pattern 23 | 24 | # Convert string to an array of chars, and then to an array of integers 25 | text = text |> collect .|> Int 26 | pattern = pattern |> collect .|> Int 27 | 28 | # If the text is shorter than the pattern, return empty vector 29 | if txt_len < ptn_len 30 | return indices 31 | end 32 | 33 | t_hash = 1 # A hash value of the current block 34 | p_hash = 1 # A hash value of the pattern 35 | 36 | d = 256 # Maximum number of different characters in the text 37 | m_hash = 2048 # Maximum hash value 38 | pow = 1 # d^(pattern length - 1) to easily remove the first character from the hash value 39 | 40 | # Calculate the pow 41 | for _ in 1:(ptn_len-1) 42 | pow = (pow * d) % m_hash 43 | end 44 | 45 | # Calculate the first hash value 46 | for i in 1:ptn_len 47 | t_hash = (t_hash * d + text[i]) % m_hash 48 | p_hash = (p_hash * d + pattern[i]) % m_hash 49 | end 50 | 51 | for i in 1:(txt_len-ptn_len+1) 52 | # If hash values match 53 | if p_hash == t_hash 54 | test = true 55 | for j in 0:(ptn_len-1) 56 | if text[i+j] != pattern[j+1] # The hash values are the same, but the strings are different 57 | test = false 58 | break 59 | end 60 | end 61 | if test # The hash values are the same, and the strings are equals 62 | push!(indices, i) 63 | end 64 | end 65 | 66 | # If the current block is not the last one, calculate the hash value for the next block 67 | if i <= txt_len - ptn_len 68 | t_hash = (d * (t_hash - text[i] * pow) + text[i+ptn_len]) % m_hash 69 | 70 | if t_hash < 0 71 | t_hash += m_hash 72 | end 73 | end 74 | end 75 | 76 | return indices 77 | end 78 | -------------------------------------------------------------------------------- /src/strings/word_count.jl: -------------------------------------------------------------------------------- 1 | """ 2 | wordcount(sentence) 3 | 4 | Program to find word count in the given sentence. The program will return count with the word. 5 | A full description of the algorithm can be found on [exercism](https://exercism.org/tracks/julia/exercises/word-count) 6 | 7 | # Arguments: 8 | - `sentence`: The sentence to find the word count. 9 | 10 | # Examples/Tests 11 | ```julia 12 | julia> wordcount(The quick brown fox jumps over the lazy dog) 13 | Dict{Any, Any}("jumps" => 1, "the" => 2, "brown" => 1, "over" => 1, "quick" => 1, "lazy" => 1, "dog" => 1, "fox" => 1) 14 | 15 | julia> wordcount(the sky is blue and beautiful) 16 | Dict{Any, Any}("and" => 1, "the" => 1, "sky" => 1, "blue" => 1, "is" => 1, "beautiful" => 1) 17 | 18 | ``` 19 | 20 | # Algorithm: 21 | 22 | ```julia 23 | 24 | for word in eachmatch(reg_expression, sentence) 25 | if !haskey(counts, word.match) 26 | counts[word.match] = 1 27 | else 28 | counts[word.match] += 1 29 | end 30 | end 31 | 32 | ``` 33 | 34 | # References: 35 | (https://exercism.org/tracks/julia/exercises/word-count) 36 | 37 | ``` 38 | 39 | # Contributed by:- [Ihjass Thasbekha](https://github.com/Ihjass) 40 | """ 41 | function word_count(sentence) 42 | lowercase_sentence = lowercase(sentence) 43 | counts = Dict() 44 | regex = r"(\w+('\w)?)" 45 | for w in eachmatch(regex, lowercase_sentence) 46 | if !haskey(counts, w.match) 47 | counts[w.match] = 1 48 | else 49 | counts[w.match] += 1 50 | end 51 | end 52 | return counts 53 | end 54 | -------------------------------------------------------------------------------- /test/Project.toml: -------------------------------------------------------------------------------- 1 | [deps] 2 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 3 | Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 4 | -------------------------------------------------------------------------------- /test/basic.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.Basic 2 | 3 | @testset "Basic" begin 4 | @testset "Basic: prefix_sum" begin 5 | @test Basic.prefix_sum([1, 1, 1]) == [1, 2, 3] 6 | @test Basic.prefix_sum([1, 2, 3]) == [1, 3, 6] 7 | @test Basic.prefix_sum(BigInt[]) == BigInt[] 8 | @test Basic.prefix_sum([0.0, 0.0, 0.0]) == [0.0, 0.0, 0.0] 9 | @test Basic.prefix_sum([1 + 2im, 2 - 3im]) == [1 + 2im, 3 - 1im] 10 | end 11 | 12 | @testset "Basic: DifferenceArray" begin 13 | arr = [1, 3, 6, 10, 15, 21] 14 | diff_arr = DifferenceArray.create_diff_arr(arr) 15 | @test diff_arr == [1, 2, 3, 4, 5, 6] 16 | 17 | #Increase elements with index from [3, 5] by 1 18 | DifferenceArray.add_to_arr(diff_arr, 3, 5, 1) 19 | @test DifferenceArray.calculate_arr(diff_arr) == [1, 3, 7, 11, 16, 21] 20 | 21 | #Increase all elements by 1 22 | DifferenceArray.add_to_arr(diff_arr, 1, 6, 1) 23 | @test DifferenceArray.calculate_arr(diff_arr) == [2, 4, 8, 12, 17, 22] 24 | end 25 | 26 | @testset "Basic: The Tower of Hanoi" begin 27 | # a, b, c represents the names of the first, second and third rod respectively 28 | @test Hanoi.solve('a', 'b', 'c', 1) == ['a' => 'c'] # One ring, just move it from the first to the third rod 29 | @test Hanoi.solve('a', 'b', 'c', 2) == 30 | ['a' => 'b', 'a' => 'c', 'b' => 'c'] 31 | @test Hanoi.solve('a', 'b', 'c', 3) == [ 32 | 'a' => 'c', 33 | 'a' => 'b', 34 | 'c' => 'b', 35 | 'a' => 'c', 36 | 'b' => 'a', 37 | 'b' => 'c', 38 | 'a' => 'c', 39 | ] 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /test/cipher.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.Cipher 2 | @testset "Cipher" begin 3 | @testset "Cipher: atbash" begin 4 | input = "test" 5 | @test atbash_encode(input) == "gvhg" 6 | input = "abcdefghijklmnopqrstuvwxyz" 7 | @test atbash_encode(input) == "zyxwv utsrq ponml kjihg fedcb a" 8 | input = "hello" 9 | @test atbash_encode(input) == "svool" 10 | end 11 | 12 | @testset "Cipher: caesar" begin 13 | @test caesar(0, "stealth") == "stealth" 14 | @test caesar(90, "ghsozhv") == "stealth" 15 | 16 | @test caesar(1, "ABC") == "BCD" 17 | @test caesar(-1, "BCD") == "ABC" 18 | 19 | @test caesar(2, "f(x)") == "h(z)" 20 | 21 | @test caesar(5, 'a') == 'f' 22 | 23 | # rot = 13 24 | # s = "abcdefghijklmnopqrstuvwxyz" 25 | # @test rotate(rot, s) == "nopqrstuvwxyzabcdefghijklm" 26 | # rot = 5 27 | # s = "omg" 28 | # @test rotate(rot, s) == "trl" 29 | # rot = 0 30 | # s = "hello" 31 | # @test rotate(rot, s) == "hello" 32 | 33 | @testset "Cipher: affine" begin 34 | alphabet = "abcdefghijklmnopqrstuvwxyz" 35 | input = "secrets" 36 | a = 3 37 | b = 1 38 | @test affine(input, alphabet, a, b) == "dnhangd" 39 | alphabet = "0123456789" 40 | input = "1234" 41 | a = 7 42 | b = 2 43 | @test affine(input, alphabet, a, b) == "9630" 44 | end 45 | end 46 | 47 | @testset "Cipher: vigenere" begin 48 | text = "Hello, World!" 49 | key = "key" 50 | @test encrypt_vigenere(text, key) == "Rijvs, Uyvjn!" 51 | text = "QUICKBROWNFOX" 52 | key = "LAZYDOG" 53 | @test encrypt_vigenere(text, key) == "BUHANPXZWMDRL" 54 | text = "Rijvs, Uyvjn!" 55 | key = "key" 56 | @test decrypt_vigenere(text, key) == "Hello, World!" 57 | text = "BUHANPXZWMDRL" 58 | key = "LAZYDOG" 59 | @test decrypt_vigenere(text, key) == "QUICKBROWNFOX" 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /test/dynamic_programming.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.DynamicProgramming 2 | @testset "Dynamic Programming" begin 3 | @testset "Coin Change" begin 4 | n_coins, coins = coin_change([1, 3, 4, 7], 13) 5 | @test length(coins) == n_coins == 3 6 | @test sum(coins) == 13 7 | 8 | n_coins, coins = coin_change([4, 3, 5, 1], 7) 9 | @test length(coins) == n_coins == 2 10 | @test sum(coins) == 7 11 | 12 | n_coins, coins = coin_change([1], 29) 13 | @test sum(coins) == length(coins) == n_coins == 29 14 | 15 | n_coins, coins = coin_change([2, 4, 6], 23) 16 | @test n_coins == -1 17 | @test isempty(coins) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/graph.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.Graph 2 | @testset "Graph" begin 3 | @testset "Dijkstra" begin 4 | graph::Vector{Vector{Tuple{Int,Int}}} = [ 5 | [(2, 8), (3, 6), (4, 4)], 6 | [(3, 1), (5, 5)], 7 | [(5, 4)], 8 | [(2, 3), (5, 9)], 9 | [(1, 2), (3, 2), (4, 5)], 10 | [(1, 1), (4, 3)], 11 | ] 12 | 13 | distances, prev = dijkstra(graph, 1) 14 | @test distances == [0, 7, 6, 4, 10, -1] 15 | @test prev == [0, 4, 1, 1, 3, -1] 16 | @test get_dijkstra_path(prev, 1) == [1] 17 | @test get_dijkstra_path(prev, 2) == [1, 4, 2] 18 | @test get_dijkstra_path(prev, 3) == [1, 3] 19 | @test get_dijkstra_path(prev, 4) == [1, 4] 20 | @test get_dijkstra_path(prev, 5) == [1, 3, 5] 21 | @test get_dijkstra_path(prev, 6) == [] 22 | end 23 | 24 | @testset "BellmanFord" begin 25 | graph::Vector{Tuple{Int,Int,Int}} = [ 26 | (1, 2, 4), 27 | (1, 3, 2), 28 | (2, 3, 3), 29 | (2, 4, 2), 30 | (2, 5, 3), 31 | (3, 2, 1), 32 | (3, 4, 4), 33 | (3, 5, 5), 34 | (5, 4, -5), 35 | ] 36 | 37 | @test bellman_ford(graph, 1) == [0, 3, 2, 1, 6] 38 | 39 | negative_edge_cycle::Vector{Tuple{Int,Int,Int}} = 40 | [(1, 3, 3), (2, 1, -6), (3, 2, 2)] 41 | 42 | @test_throws ErrorException bellman_ford(negative_edge_cycle, 1) 43 | end 44 | 45 | @testset "bfs" begin 46 | graph = [[2, 3, 6], [3, 4], [4], [1, 2, 5], [2], [1, 5]] 47 | 48 | @test bfs(graph, 4) == [4, 1, 2, 5, 3, 6] 49 | @test bfs(graph) == [1, 2, 3, 6, 4, 5] 50 | end 51 | 52 | @testset "dfs" begin 53 | graph = [[2, 3, 6], [3, 4], [4], [1, 2, 5], [2], [1, 5]] 54 | 55 | @test dfs(graph, 6) == [6, 5, 2, 4, 3, 1] 56 | @test dfs(graph) == [1, 6, 5, 3, 4, 2] 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /test/knapsack.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.KnapSack 2 | @testset "Knapsack" begin 3 | @testset "Knapsack: DpZeroOnePack!" begin 4 | dp = zeros(Int, 30) 5 | @test zero_one_pack!(20, [1, 3, 11], [2, 5, 30], dp) == 37 6 | dp = zeros(Int, 30) 7 | @test zero_one_pack!(10, [1, 3, 11], [20, 5, 80], dp) == 25 8 | end 9 | 10 | @testset "Knapsack: DpCompletePack!" begin 11 | dp = zeros(Int, 30) 12 | @test complete_pack!(20, [1, 2, 9], [1, 3, 20], dp) == 43 13 | dp = zeros(Int, 30) 14 | @test complete_pack!(10, [1, 3, 11], [20, 5, 80], dp) == 200 15 | end 16 | 17 | @testset "Knapsack: GaZeroOnePack!" begin 18 | dp = zeros(Int, 30) 19 | @test zero_one_pack!(20, [1, 3, 11], [2, 5, 30]) == 37 20 | dp = zeros(Int, 30) 21 | @test zero_one_pack!(10, [1, 3, 11], [20, 5, 80]) == 25 22 | end 23 | 24 | @testset "Knapsack: GaCompletePack!" begin 25 | dp = zeros(Int, 30) 26 | @test complete_pack!(20, [1, 2, 9], [1, 3, 20]) == 43 27 | dp = zeros(Int, 30) 28 | @test complete_pack!(10, [1, 3, 11], [20, 5, 80]) == 200 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /test/longest_increasing_subsequence.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.LongSubSeq 2 | 3 | @testset "Longest Increasing Subsequence" begin 4 | @testset "LIS: Dynamic Programming approach!" begin 5 | @test lis([3, 10, 2, 1, 20], Val(:dp)) == [3, 10, 20] 6 | # negative elements 7 | @test lis([-10, -2, -1, -20], Val(:dp)) == [-10, -2, -1] 8 | # repeated elements 9 | @test lis([2, 2, 3, 3], Val(:dp)) == [2, 3] 10 | # one element 11 | @test lis([2], Val(:dp)) == [2] 12 | # empty array 13 | @test lis(Int[], Val(:dp)) == Int[] 14 | # two possible results: 15 | @test lis([3, 2], Val(:dp)) in [[2], [3]] 16 | # two possible results: 17 | @test lis([50, 3, 10, 7, 40, 80], Val(:dp)) in 18 | [[3, 7, 40, 80], [3, 10, 40, 80]] 19 | # two possible results: 20 | @test lis([3, 4, -1, 5, 8, 2, 3, 12, 7, 9, 10], Val(:dp)) in 21 | [[-1, 2, 3, 7, 9, 10], [3, 4, 5, 8, 9, 10]] 22 | # Boolean array 23 | @test lis([true, false, false, true], Val(:dp)) == [false, true] 24 | # other Integer subtypes 25 | for T in [ 26 | UInt128, 27 | UInt16, 28 | UInt32, 29 | UInt64, 30 | UInt8, 31 | BigInt, 32 | Int128, 33 | Int16, 34 | Int32, 35 | Int64, 36 | Int8, 37 | ] 38 | @test lis(T[3, 10, 2, 1, 20], Val(:dp)) == T[3, 10, 20] 39 | end 40 | end 41 | 42 | @testset "LIS: Binary Search approach!" begin 43 | @test lis([3, 10, 2, 1, 20], Val(:bs)) == [3, 10, 20] 44 | # negative elements 45 | @test lis([-10, -2, -1, -20], Val(:bs)) == [-10, -2, -1] 46 | # repeated elements 47 | @test lis([2, 2, 3, 3], Val(:bs)) == [2, 3] 48 | # one element 49 | @test lis([2], Val(:bs)) == [2] 50 | # empty array 51 | @test lis(Int[], Val(:bs)) == Int[] 52 | # two possible results: 53 | @test lis([3, 2], Val(:bs)) in [[2], [3]] 54 | # two possible results: 55 | @test lis([50, 3, 10, 7, 40, 80], Val(:bs)) in 56 | [[3, 7, 40, 80], [3, 10, 40, 80]] 57 | # two possible results: 58 | @test lis([3, 4, -1, 5, 8, 2, 3, 12, 7, 9, 10], Val(:bs)) in 59 | [[-1, 2, 3, 7, 9, 10], [3, 4, 5, 8, 9, 10]] 60 | # Boolean array 61 | @test lis([true, false, false, true], Val(:bs)) == [false, true] 62 | # other Integer subtypes 63 | for T in [ 64 | UInt128, 65 | UInt16, 66 | UInt32, 67 | UInt64, 68 | UInt8, 69 | BigInt, 70 | Int128, 71 | Int16, 72 | Int32, 73 | Int64, 74 | Int8, 75 | ] 76 | @test lis(T[3, 10, 2, 1, 20], Val(:bs)) == T[3, 10, 20] 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /test/machine_learning.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.ML 2 | 3 | @testset "Machine learning" begin 4 | @testset "Machine learning: K-Means clustering" begin 5 | # poinst is a vector of 2D points. 6 | points = [[0, 0], [1, 1], [5.0, 5.0], [10.0, 10.0]] 7 | @test KMeans.cluster(1, -1, points) == [[4.0, 4.0]] # 1 cluster, undefined number of iterations 8 | @test KMeans.cluster(1, 10, points) == [[4.0, 4.0]] # 1 cluster, 10 iterations 9 | # If we are looking for 2 clusters, it is obvious that the first one will be between the first two 10 | # points ([0, 0] and [1, 1]), and the second one will be between the last two points ([5, 5] and [10, 10]) 11 | @test KMeans.cluster(2, -1, points) == [[0.5, 0.5], [7.5, 7.5]] 12 | # When the number of clusters is equal to the number of points, 13 | # each cluster will be assigned to a single point 14 | @test KMeans.cluster(4, -1, points) == points 15 | # When there are not enough points to create k clusters, 16 | # each cluster will have its coordinates set to 0 17 | KMeans.cluster(5, -1, points) == 18 | [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]] 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /test/matrix.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.MatrixAlgo 2 | 3 | @testset "Matrix" begin 4 | @testset "Matrix: Determinant" begin 5 | M1 = [1 0; 2 2] 6 | M2 = rand(3, 3) 7 | M3 = rand(4, 4) 8 | 9 | @test determinant(M1) == det(M1) 10 | @test round(determinant(M2), digits = 4) == round(det(M2), digits = 4) 11 | @test round(determinant(M3), digits = 4) == round(det(M3), digits = 4) 12 | 13 | @test_throws DomainError determinant([1 2]) 14 | @test_throws DomainError determinant([1 2; 3 4; 5 6]) 15 | end 16 | 17 | @testset "Matrix: LU Decompose" begin 18 | mat = [ 19 | 2 -1 -2 20 | -4 6 3 21 | -4 -2 8 22 | ] 23 | 24 | L = [ 25 | 1 0 0 26 | -2 1 0 27 | -2 -1 1 28 | ] 29 | U = [ 30 | 2 -1 -2 31 | 0 4 -1 32 | 0 0 3 33 | ] 34 | 35 | @test lu_decompose(mat) == (L, U) 36 | end 37 | 38 | @testset "Matrix: rotation matrix" begin 39 | theta = pi / 6 40 | a = [1; 0] 41 | b = [0; 1] 42 | @test rotation_matrix(theta) * a == [cos(theta); sin(theta)] 43 | @test rotation_matrix(theta) * b == [-sin(theta); cos(theta)] 44 | end 45 | 46 | @testset "Matrix: Gauss-Jordan Elimination" begin 47 | M1 = [1 2 3; 4 5 6] 48 | M2 = [1 2 3; 4 8 12] 49 | M3 = [1 2; 4 8] 50 | M4 = [ 51 | 1 4 8 1 4 52 | 4 5 6 8 11 53 | 1 3 2 4 8 54 | 4 5 67 23 0 55 | ] 56 | M5 = Float64[ 57 | 1 4 8 1 4 58 | 4 5 6 8 11 59 | 1 3 2 4 8 60 | 4 5 67 23 0 61 | ] 62 | M6 = [ 63 | 1 4 8 64 | 4 0 6 65 | 1 3 2 66 | ] 67 | 68 | R3 = [ 69 | 1.0 0.0 0.0 0.0 -1.10637 70 | 0.0 1.0 0.0 0.0 1.89743 71 | 0.0 0.0 1.0 0.0 -0.444913 72 | 0.0 0.0 0.0 1.0 1.07598 73 | ] 74 | 75 | @test gauss_jordan(M1) == Float64[1 0 -1; 0 1 2] 76 | @test_throws AssertionError gauss_jordan(M2) 77 | @test_throws AssertionError gauss_jordan(M3) 78 | @test isapprox(gauss_jordan(M4), R3, atol = 1e-5) 79 | @test isapprox(gauss_jordan(M5), R3, atol = 1e-5) 80 | @test isapprox( 81 | gauss_jordan(M6), 82 | Float64[1 0 0; 0 1 0; -0 -0 1], 83 | atol = 1e-5, 84 | ) 85 | 86 | @test gauss_jordan([0.0 1.0 5.0; 1.0 -2.0 -3.0]) == 87 | [1.0 0.0 7.0; 0.0 1.0 5.0] 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /test/project_rosalind.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.ProjectRosalind 2 | 3 | @testset "Project Rosalind" begin 4 | @testset "Project Rosalind: Count Nucleotides" begin 5 | @test count_nucleotides( 6 | "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC", 7 | ) == "20 12 17 21" 8 | end 9 | 10 | @testset "Project Rosalind: DNA to RNA" begin 11 | @test dna2rna("GATGGAACTTGACTACGTAAATT") == "GAUGGAACUUGACUACGUAAAUU" 12 | end 13 | 14 | @testset "Project Rosalind: Reverse Complement" begin 15 | @test reverse_complement("AAAACCCGGT") == "ACCGGGTTTT" 16 | end 17 | 18 | @testset "Project Rosalind: Rabbits" begin 19 | @test rabbits(5, 3) == 19 20 | @test rabbits(15, 2) == 75316 21 | @test rabbits(10, 3) == 1159 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /test/runtests.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms 2 | using Test 3 | 4 | using LinearAlgebra 5 | 6 | @testset "TheAlgorithms" begin 7 | include("basic.jl") 8 | include("conversions.jl") 9 | include("cipher.jl") 10 | include("data_structures.jl") 11 | include("dynamic_programming.jl") 12 | include("graph.jl") 13 | include("knapsack.jl") 14 | include("longest_increasing_subsequence.jl") 15 | include("machine_learning.jl") 16 | include("math.jl") 17 | include("matrix.jl") 18 | include("project_euler.jl") 19 | include("project_rosalind.jl") 20 | include("scheduling.jl") 21 | include("searches.jl") 22 | include("sorts.jl") 23 | include("statistics.jl") 24 | include("strings.jl") 25 | end 26 | -------------------------------------------------------------------------------- /test/scheduling.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.Scheduling 2 | 3 | @testset "Scheduling" begin 4 | @testset "Scheduling: FCFS" begin 5 | n = 3 6 | process_id = Any[1, 2, 3] 7 | burst_times = Any[10, 5, 8] 8 | @test fcfs(n, process_id, burst_times) == ( 9 | Any[1, 2, 3], 10 | Any[10, 5, 8], 11 | Any[0, 10, 15], 12 | Any[10, 15, 23], 13 | 8.333333333333334, 14 | 16.0, 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /test/searches.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.Searches 2 | 3 | @testset "Searches" begin 4 | @testset "Searches: Binary" begin 5 | @testset "binary_search - first method" begin 6 | sample = [0, 23, 52, 552, 555, 602, 1004] 7 | reversed_sample = reverse(sample) 8 | unsorted_sample = [124, 53, 21, 163] 9 | @test binary_search(sample, 52) == 3:3 10 | @test binary_search(sample, 602) == 6:6 11 | @test binary_search(sample, 45) == 3:2 12 | @test binary_search(reversed_sample, 52; rev = true) == 5:5 13 | @test binary_search(reversed_sample, 602; rev = true) == 2:2 14 | @test binary_search(reversed_sample, 45; rev = true) == 6:5 15 | @test_throws ErrorException binary_search(unsorted_sample, 21) # throws an error 16 | end 17 | @testset "binary_search - second method" begin 18 | # Second method used for exponential search 19 | arr = [1, 2, 3, 4, 13, 15, 20] 20 | # The next three values used are the result of the while-loop inside `exponential search` 21 | @test binary_search(arr, 4, 7, 4) == 4 22 | @test binary_search(arr, 4, 7, 20) == 7 23 | @test binary_search(arr, 4, 7, 10) == -1 24 | @test binary_search(arr, 4, 7, 21) == -1 25 | end 26 | end 27 | 28 | @testset "Searches: Linear" begin 29 | array = [1, 30, 4, 70, 8, 11] 30 | @test linear_search(array, 1) == 1 31 | @test linear_search(array, 30) == 2 32 | @test linear_search(array, 8) == 5 33 | @test linear_search(array, 11) == 6 34 | @test linear_search(array, 12) == -1 35 | @test linear_search(array, 10) == -1 36 | @test linear_search(array, 0) == -1 37 | end 38 | 39 | @testset "Searches: Exponential" begin 40 | arr = [1, 2, 3, 4, 13, 15, 20] 41 | @test exponential_search(arr, 1) == 1 42 | @test exponential_search(arr, 4) == 4 43 | @test exponential_search(arr, 20) == 7 44 | @test exponential_search(arr, 5) == -1 45 | @test exponential_search(arr, 100) == -1 46 | end 47 | 48 | @testset "Searches: Interpolation" begin 49 | arr = [1, 2, 3, 4, 13, 15, 20] 50 | l = 1 51 | r = size(arr)[1] 52 | 53 | @test interpolation_search(arr, l, r, 1) == 1 54 | @test interpolation_search(arr, l, r, 2) == 2 55 | @test interpolation_search(arr, l, r, 3) == 3 56 | @test interpolation_search(arr, l, r, 4) == 4 57 | @test interpolation_search(arr, l, r, 13) == 5 58 | @test interpolation_search(arr, l, r, 15) == 6 59 | @test interpolation_search(arr, l, r, 20) == 7 60 | @test interpolation_search(arr, l, r, 5) == -1 61 | @test interpolation_search(arr, l, r, 14) == -1 62 | @test interpolation_search(arr, l, r, 19) == -1 63 | @test interpolation_search(arr, l, r, 0) == -1 64 | @test interpolation_search(arr, l, r, 1000) == -1 65 | end 66 | 67 | @testset "Searches: Jump" begin 68 | arr = [1, 2, 3, 4, 13, 31] 69 | @test jump_search(arr, 31, 1) == 6 70 | @test jump_search(arr, 13, 3) == 5 71 | @test jump_search(arr, 3, 5) == 3 72 | @test jump_search(arr, 1, 3) == 1 73 | @test jump_search(arr, 10000, 3) == -1 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /test/sorts.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.Sorts 2 | 3 | @testset "Sorts" begin 4 | @testset "bogo_sort" begin 5 | x = [3, 1, 4, 2] 6 | bogo_sort!(x) 7 | @test x == [1, 2, 3, 4] 8 | end 9 | 10 | @testset "deterministic sorts" begin 11 | sorts = [ 12 | bubble_sort! 13 | bucket_sort! 14 | counting_sort! 15 | exchange_sort! 16 | heap_sort! 17 | insertion_sort! 18 | merge_sort! 19 | quick_sort! 20 | selection_sort! 21 | ] 22 | 23 | for f in sorts 24 | x = [3, 5, 1, 4, 2] 25 | f(x) 26 | @test x == [1, 2, 3, 4, 5] 27 | 28 | y = [5, 2, 2, 2, 1, 5, 2, 34, 6, 4, 3, 2, 1, 2, 3, 4, 10, 1] 29 | f(y) 30 | @test y == [1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 10, 34] 31 | 32 | z = [] 33 | f(z) 34 | @test z == [] 35 | 36 | s = [1] 37 | f(s) 38 | @test s == [1] 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /test/statistics.jl: -------------------------------------------------------------------------------- 1 | using TheAlgorithms.StatAlgo 2 | 3 | @testset "Statistics" begin 4 | @testset "Statistics: Pearson Correlation" begin 5 | a = 1:10 6 | b = 1:10 7 | @test pearson_correlation(a, b) == 1 8 | 9 | x = [12, 15, 17, 21, 18] 10 | y = [6, 9, -1, 3, 1] 11 | 12 | @test pearson_correlation(x, y) == -0.5201361507569889 13 | end 14 | 15 | @testset "Statistics: Variance" begin 16 | a = 1:10 17 | 18 | @test variance(a) == 9.166666666666666 19 | 20 | a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 21 | 22 | @test variance(a) == 9.166666666666666 23 | 24 | a = [12, 15, 17, 20] 25 | 26 | @test variance(a) == 11.333333333333334 27 | end 28 | end 29 | --------------------------------------------------------------------------------