diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..dda50c14f8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @Panquesito7 @tjgurwara99 @alexpantyukhin diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index fcff12b9ef..875cc4efab 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - name: Discord community - url: https://discord.gg/c7MnfGFGa6 + url: https://the-algorithms.com/discord/ about: Have any questions or found any bugs? Please contact us via Discord diff --git a/.github/ISSUE_TEMPLATE/other.yml b/.github/ISSUE_TEMPLATE/other.yml index 901d227ba9..d6dc0cfe9f 100644 --- a/.github/ISSUE_TEMPLATE/other.yml +++ b/.github/ISSUE_TEMPLATE/other.yml @@ -1,13 +1,10 @@ -name: Other +name: Other issue description: Use this for any other issues. Do NOT create blank issues title: "[OTHER]" -labels: [triage] +labels: ["awaiting triage"] body: - - type: markdown - attributes: - value: "# Other issue" - type: textarea - id: issuedescription + id: description attributes: label: What would you like to share? description: Provide a clear and concise explanation of your issue. diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000000..caabb2d152 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,2 @@ +Leetcode folder changes: +- leetcode/**/* diff --git a/.github/workflows/awesome_workflow.yml b/.github/workflows/awesome_workflow.yml index 582bc9c6f9..d57946e53c 100644 --- a/.github/workflows/awesome_workflow.yml +++ b/.github/workflows/awesome_workflow.yml @@ -1,100 +1,34 @@ name: Awesome CI Workflow - on: [push, pull_request] -# push: -# branches: [ master ] -# pull_request: -# branches: [ master ] +permissions: + contents: write jobs: MainSequence: name: Code Formatter runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 # v2 is broken for git diff - - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-python@v4 - name: requirements run: | - sudo apt -qq -y update - sudo apt -qq install clang-tidy-10 clang-format-10 + sudo apt-get -qq update + sudo apt-get -qq install clang-tidy clang-format + # checks are passing with less errors when used with this version. + # The default installs v6.0 which did not work out well in my tests - name: Setup Git Specs run: | - git config --global user.name github-actions - git config --global user.email '${GITHUB_ACTOR}@users.noreply.github.com' - git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY + git config --global user.name github-actions[bot] + git config --global user.email 'github-actions@users.noreply.github.com' - name: Filename Formatter - run: | - IFS=$'\n' - for fname in `find . -type f -name '*.c' -o -name '*.h'` - do - echo "${fname}" - new_fname=`echo ${fname} | tr ' ' '_'` - echo " ${new_fname}" - new_fname=`echo ${new_fname} | tr 'A-Z' 'a-z'` - echo " ${new_fname}" - new_fname=`echo ${new_fname} | tr '-' '_'` - echo " ${new_fname}" - if [ ${fname} != ${new_fname} ] - then - echo " ${fname} --> ${new_fname}" - git "mv" "${fname}" ${new_fname} - fi - done - git commit -am "formatting filenames ${GITHUB_SHA::8}" || true - - name: Update DIRECTORY.md - shell: python - run: | - import os - from typing import Iterator - - URL_BASE = "https://github.com/TheAlgorithms/C/blob/master" - g_output = [] - - def good_filepaths(top_dir: str = ".") -> Iterator[str]: - cpp_exts = tuple(".c .c++ .cc .cpp .cu .cuh .cxx .h .h++ .hh .hpp .hxx".split()) - for dirpath, dirnames, filenames in os.walk(top_dir): - dirnames[:] = [d for d in dirnames if d[0] not in "._"] - for filename in filenames: - if os.path.splitext(filename)[1].lower() in cpp_exts: - yield os.path.join(dirpath, filename).lstrip("./") - - def md_prefix(i): - return f"{i * ' '}*" if i else "\n##" - - def print_path(old_path: str, new_path: str) -> str: - global g_output - old_parts = old_path.split(os.sep) - for i, new_part in enumerate(new_path.split(os.sep)): - if i + 1 > len(old_parts) or old_parts[i] != new_part: - if new_part: - g_output.append(f"{md_prefix(i)} {new_part.replace('_', ' ').title()}") - return new_path - - def build_directory_md(top_dir: str = ".") -> str: - global g_output - old_path = "" - for filepath in sorted(good_filepaths(), key=str.lower): - filepath, filename = os.path.split(filepath) - if filepath != old_path: - old_path = print_path(old_path, filepath) - indent = (filepath.count(os.sep) + 1) if filepath else 0 - url = "/".join((URL_BASE, filepath, filename)).replace(" ", "%20") - filename = os.path.splitext(filename.replace("_", " ").title())[0] - g_output.append(f"{md_prefix(indent)} [{filename}]({url})") - return "# List of all files\n" + "\n".join(g_output) - - with open("DIRECTORY.md", "w") as out_file: - out_file.write(build_directory_md(".") + "\n") - - name: Commit DIRECTORY.md - run: | - git diff DIRECTORY.md - git add DIRECTORY.md - git commit -m "updating DIRECTORY.md" || true + uses: TheAlgorithms/scripts/formatter@main + with: + filetypes: .c,.h - name: Get file changes run: | - git remote -v git branch - git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY git diff --diff-filter=dr --name-only origin/master > git_diff.txt echo "Files changed-- `cat git_diff.txt`" - name: Configure for static lint checks @@ -103,66 +37,37 @@ jobs: # be able to catch any errors for other platforms. run: cmake -B build -S . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - name: Lint modified files - shell: python - run: | - import os - import subprocess - import sys - - print("Python {}.{}.{}".format(*sys.version_info)) # Python 3.8 - with open("git_diff.txt") as in_file: - modified_files = sorted(in_file.read().splitlines()) - print("{} files were modified.".format(len(modified_files))) - - cpp_exts = tuple(".c .c++ .cc .cpp .cu .cuh .cxx .h .h++ .hh .hpp .hxx".split()) - cpp_files = [file for file in modified_files if file.lower().endswith(cpp_exts)] - print(f"{len(cpp_files)} C++ files were modified.") - if not cpp_files: - sys.exit(0) - - subprocess.run(["clang-tidy-10", "-p=build", "--fix", *cpp_files, "--"], - check=True, text=True, stderr=subprocess.STDOUT) - - subprocess.run(["clang-format-10", "-i", *cpp_files], - check=True, text=True, stderr=subprocess.STDOUT) - - upper_files = [file for file in cpp_files if file != file.lower()] - if upper_files: - print(f"{len(upper_files)} files contain uppercase characters:") - print("\n".join(upper_files) + "\n") - - space_files = [file for file in cpp_files if " " in file or "-" in file] - if space_files: - print(f"{len(space_files)} files contain space or dash characters:") - print("\n".join(space_files) + "\n") - - nodir_files = [file for file in cpp_files if file.count(os.sep) != 1 and "project_euler" not in file and "data_structure" not in file] - if len(nodir_files) > 1: - nodir_file_bad_files = len(nodir_files) - 1 - print(f"{len(nodir_files)} files are not in one and only one directory:") - print("\n".join(nodir_files) + "\n") - else: - nodir_file_bad_files = 0 - - bad_files = nodir_file_bad_files + len(upper_files + space_files) - if bad_files: - sys.exit(bad_files) - + shell: bash + run: python3 scripts/file_linter.py - name: Commit and push changes run: | - git commit -am "clang-format and clang-tidy fixes for ${GITHUB_SHA::8}" || true - git push --force origin HEAD:$GITHUB_REF || true - + git diff DIRECTORY.md + git commit -am "clang-format and clang-tidy fixes for ${GITHUB_SHA::8}" || true + git push origin HEAD:$GITHUB_REF || true build: name: Compile checks runs-on: ${{ matrix.os }} + permissions: + pull-requests: write needs: [MainSequence] strategy: matrix: - os: [ubuntu-latest, macOS-latest] + os: [windows-latest, ubuntu-latest, macOS-latest] steps: - - uses: actions/checkout@master + - uses: actions/checkout@v3 with: submodules: true - - run: cmake -B ./build -S . - - run: cmake --build build + - run: | + cmake -B ./build -S . + cmake --build build --config Release + - name: Label on PR fail + uses: actions/github-script@v6 + if: ${{ failure() && matrix.os == 'ubuntu-latest' && github.event_name == 'pull_request' }} + with: + script: | + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['Autochecks are failing'] + }) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..16da8867bf --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,61 @@ +name: "Code Scanning - Action" + +on: + push: + branches: [master] + pull_request: + branches: [master] + schedule: + # ┌───────────── minute (0 - 59) + # │ ┌───────────── hour (0 - 23) + # │ │ ┌───────────── day of the month (1 - 31) + # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) + # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) + # │ │ │ │ │ + # │ │ │ │ │ + # │ │ │ │ │ + # * * * * * + - cron: '30 1 * * 0' + +jobs: + CodeQL-Build: + # CodeQL runs on ubuntu-latest, windows-latest, and macos-latest + runs-on: ubuntu-latest + + permissions: + # required for all workflows + security-events: write + + # only required for workflows in private repositories + actions: read + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + # Override language selection by uncommenting this and choosing your languages + with: + languages: cpp + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below). + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # ✏️ If the Autobuild fails above, remove it and uncomment the following + # three lines and modify them (or add more) to build your code if your + # project uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/codeql_analysis.yml b/.github/workflows/codeql_analysis.yml deleted file mode 100644 index aa3ddbd7f7..0000000000 --- a/.github/workflows/codeql_analysis.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: "CodeQL" -on: [push, pull_request] - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - language: [ 'cpp' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - - steps: - - name: Checkout repository - uses: actions/checkout@main - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@main - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@main - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@main diff --git a/.github/workflows/directory_writer.yml b/.github/workflows/directory_writer.yml new file mode 100644 index 0000000000..527a55e27d --- /dev/null +++ b/.github/workflows/directory_writer.yml @@ -0,0 +1,29 @@ +name: Directory writer +on: + schedule: + # ┌───────────── minute (0 - 59) + # │ ┌───────────── hour (0 - 23) + # │ │ ┌───────────── day of the month (1 - 31) + # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) + # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) + # │ │ │ │ │ + # │ │ │ │ │ + # │ │ │ │ │ + # * * * * * + - cron: '0 0 * * *' + workflow_dispatch: +jobs: + build: + if: github.repository == 'TheAlgorithms/C' # We only need this to run in our repository. + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Build directory + uses: TheAlgorithms/scripts/directory_md@main + with: + language: C + working-directory: . + filetypes: .c,.h + ignored-directories: leetcode/,scripts/ diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 881ea1c337..134c04bb13 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -8,7 +8,7 @@ jobs: build: runs-on: macos-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v3 with: submodules: true - name: Install requirements @@ -19,7 +19,7 @@ jobs: - name: build run: cmake --build build -t doc - name: gh-pages - uses: actions/checkout@master + uses: actions/checkout@v3 with: ref: "gh-pages" clean: false diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000000..fe3f22d579 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,14 @@ +name: "Pull Request Labeler" +on: +- pull_request_target + +jobs: + triage: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v4 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/leetcode_directory_writer.yml b/.github/workflows/leetcode_directory_writer.yml new file mode 100644 index 0000000000..9d4ab38b89 --- /dev/null +++ b/.github/workflows/leetcode_directory_writer.yml @@ -0,0 +1,45 @@ +# The objective of this GitHub Action is to update the leetcode DIRECTORY.md file (if needed) +# when doing a git push +name: leetcode_directory_writer +on: + push: + paths: + - "leetcode/src/**.c" + branches: + - master +jobs: + build: + if: github.repository == 'TheAlgorithms/C' # We only need this to run in our repository. + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - name: Add python dependencies + run: | + pip install requests + - name: Write LeetCode DIRECTORY.md + run: | + python3 scripts/leetcode_directory_md.py 2>&1 | tee leetcode/DIRECTORY.md + - name: Setup Git configurations + shell: bash + run: | + git config --global user.name github-actions[bot] + git config --global user.email 'github-actions@users.noreply.github.com' + - name: Committing changes + shell: bash + run: | + git checkout -b leetcode-directory-${{ github.sha }} + git commit -m "docs: updating `leetcode/DIRECTORY.md`" + git push origin leetcode-directory-${{ github.sha }}:leetcode-directory-${{ github.sha }} + - name: Creating the pull request + shell: bash + run: | + if [[ $(git log --branches --not --remotes) ]]; then + gh pr create --base ${GITHUB_REF##*/} --head leetcode-directory-${{ github.sha }} --title 'docs: updating `leetcode/DIRECTORY.md`' --body 'Updated LeetCode directory (see the diff. for changes).' || true + fi + env: + GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 406e56b7fe..0018600db5 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -9,9 +9,9 @@ jobs: - uses: actions/stale@v4 with: stale-issue-message: 'This issue has been automatically marked as abandoned because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.' - close-issue-message: 'Please ping one of the maintainers once you add more information and updates here. If this is not the case and you need some help, feel free to ask for help in our [Gitter](https://gitter.im/TheAlgorithms) channel or our [Discord server](https://discord.gg/c7MnfGFGa6). Thank you for your contributions!' + close-issue-message: 'Please ping one of the maintainers once you add more information and updates here. If this is not the case and you need some help, feel free to ask for help in our [Gitter](https://gitter.im/TheAlgorithms) channel or our [Discord server](https://the-algorithms.com/discord/). Thank you for your contributions!' stale-pr-message: 'This pull request has been automatically marked as abandoned because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.' - close-pr-message: 'Please ping one of the maintainers once you commit the changes requested or make improvements on the code. If this is not the case and you need some help, feel free to ask for help in our [Gitter](https://gitter.im/TheAlgorithms) channel or our [Discord server](https://discord.gg/c7MnfGFGa6). Thank you for your contributions!' + close-pr-message: 'Please ping one of the maintainers once you commit the changes requested or make improvements on the code. If this is not the case and you need some help, feel free to ask for help in our [Gitter](https://gitter.im/TheAlgorithms) channel or our [Discord server](https://the-algorithms.com/discord/). Thank you for your contributions!' exempt-issue-labels: 'dont-close,approved' exempt-pr-labels: 'dont-close,approved' days-before-stale: 30 diff --git a/.gitignore b/.gitignore index 59f569ad15..8b6b444d53 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.out .vscode/ build/ +git_diff.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index dafc51c743..01a43e6617 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,17 @@ -cmake_minimum_required(VERSION 3.6) +cmake_minimum_required(VERSION 3.22) project(Algorithms_in_C - LANGUAGES C - VERSION 1.0.0 - DESCRIPTION "Set of algorithms implemented in C." -) + LANGUAGES C + VERSION 1.0.0 + DESCRIPTION "Set of algorithms implemented in C." + ) # Set compilation standards set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED YES) - -if(MSVC) +if (MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) # add_compile_options(/Za) -endif(MSVC) +endif (MSVC) # check for math library # addresses a bug when linking on OSX @@ -61,7 +60,11 @@ add_subdirectory(conversions) add_subdirectory(client_server) add_subdirectory(project_euler) add_subdirectory(machine_learning) +add_subdirectory(process_scheduling_algorithms) add_subdirectory(numerical_methods) +add_subdirectory(math) +add_subdirectory(cipher) +add_subdirectory(dynamic_programming) ## Configure Doxygen documentation system cmake_policy(SET CMP0054 NEW) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aeb000ca8a..01638a59c4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,29 +2,33 @@ ## Before contributing -Welcome to [TheAlgorithms/C](https://github.com/TheAlgorithms/C)! Before submitting pull requests, please make sure that you have **read the whole guidelines**. If you have any doubts about this contribution guide, please open [an issue](https://github.com/TheAlgorithms/C/issues/new/choose) or ask in our [Discord server](https://discord.gg/c7MnfGFGa6), and clearly state your concerns. +Welcome to [TheAlgorithms/C](https://github.com/TheAlgorithms/C)! Before submitting pull requests, please make sure that you have **read the whole guidelines**. If you have any doubts about this contribution guide, please open [an issue](https://github.com/TheAlgorithms/C/issues/new/choose) or ask on our [Discord server](https://the-algorithms.com/discord/), and clearly state your concerns. ## Contributing ### Maintainer/reviewer -**Please check the [reviewer code](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/REVIEWER_CODE.md) file for maintainers and reviewers.** +**Please check the [reviewer code](https://github.com/TheAlgorithms/C/blob/master/REVIEWER_CODE.md) file for maintainers and reviewers.** ### Contributor Being a contributor at The Algorithms, we request you to follow the points mentioned below: - You did your own work. - - No plagiarism allowed. Any plagiarized work will not be merged. + - No plagiarism is allowed. Any plagiarized work will not be merged. - Your work will be distributed under the [GNU General Public License v3.0](https://github.com/TheAlgorithms/C/blob/master/LICENSE) once your pull request has been merged. - Please follow the repository guidelines and standards mentioned below. **New implementation** New implementations are welcome! -You can add new algorithms or data structures which are **not present in the repository** or that can **improve** the old implementations (**documentation**, **improving test cases**, removing bugs or in any other resonable sense) +You can add new algorithms or data structures that are **not present in the repository** or that can **improve** the old implementations (**documentation**, **improving test cases**, removing bugs, or in any other reasonable sense) **Issues** Please avoid opening issues asking to be "assigned” to a particular algorithm. This merely creates unnecessary noise for maintainers. Instead, please submit your implementation in a pull request, and it will be evaluated by project maintainers. +### LeetCode solutions + +For LeetCode solutions, please check its [**guide**](https://github.com/TheAlgorithms/C/blob/master/leetcode/README.md) to make a proper solution file. + ### Making Changes #### Code @@ -36,8 +40,8 @@ You can add new algorithms or data structures which are **not present in the rep - You can suggest reasonable changes to existing algorithms. - Strictly use snake_case (underscore_separated) in filenames. - If you have added or modified code, please make sure the code compiles before submitting. -- Our automated testing runs [__CMake__](https://cmake.org/) on all the pull requests, so please be sure that your code passes before submitting. -- Please conform to [Doxygen](https://www.doxygen.nl/manual/docblocks.html) standard and document the code as much as possible. This not only facilitates the readers but also generates the correct info on website. +- Our automated testing runs [**CMake**](https://cmake.org/) on all the pull requests, so please be sure that your code passes before submitting. +- Please conform to [Doxygen](https://www.doxygen.nl/manual/docblocks.html) standards and document the code as much as possible. This not only facilitates the readers but also generates the correct info on the website. - **Be consistent in the use of these guidelines.** #### Documentation @@ -53,13 +57,110 @@ You can add new algorithms or data structures which are **not present in the rep - Make sure to add examples and test cases in your `main()` function. - If you find an algorithm or document without tests, please feel free to create a pull request or issue describing suggested changes. - Please try to add one or more `test()` functions that will invoke the algorithm implementation on random test data with the expected output. Use the `assert()` function to confirm that the tests will pass. Requires including the `assert.h` library. +- Test cases should fully verify that your program works as expected. Rather than asking the user for input, it's best to make sure the given output is the correct output. + +##### Self-test examples + +1. [ROT13 Cipher](https://github.com/TheAlgorithms/C/blob/master/cipher/rot13.c) (complex). + +```c + // NOTE: the `rot13` function is defined in another part of the code. + + char test_01[] = "The more I C, the less I see."; + rot13(test_01); + assert(strcmp(test_01, "Gur zber V P, gur yrff V frr.") == 0); + + char test_02[] = "Which witch switched the Swiss wristwatches?"; + rot13(test_02); + assert(strcmp(test_02, "Juvpu jvgpu fjvgpurq gur Fjvff jevfgjngpurf?") == 0); + + char test_03[] = "Juvpu jvgpu fjvgpurq gur Fjvff jevfgjngpurf?"; + rot13(test_03); + assert(strcmp(test_03, "Which witch switched the Swiss wristwatches?") == 0); +``` + +2. [Sudoku Solver](https://github.com/TheAlgorithms/C/blob/master/misc/sudoku_solver.c) (medium). + +```c + uint8_t test_array[] = {3, 0, 6, 5, 0, 8, 4, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 7, 0, 0, 0, 0, 3, 1, 0, 0, 3, 0, 1, 0, 0, + 8, 0, 9, 0, 0, 8, 6, 3, 0, 0, 5, 0, 5, 0, 0, 9, 0, + 6, 0, 0, 1, 3, 0, 0, 0, 0, 2, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 7, 4, 0, 0, 5, 2, 0, 6, 3, 0, 0}; + struct sudoku a = {.N = 9, .N2 = 3, .a = test_array}; + assert(solve(&a)); // ensure that solution is obtained + // NOTE: `solve` is defined in another part of the code. + + uint8_t expected[] = {3, 1, 6, 5, 7, 8, 4, 9, 2, 5, 2, 9, 1, 3, 4, 7, 6, + 8, 4, 8, 7, 6, 2, 9, 5, 3, 1, 2, 6, 3, 4, 1, 5, 9, + 8, 7, 9, 7, 4, 8, 6, 3, 1, 2, 5, 8, 5, 1, 7, 9, 2, + 6, 4, 3, 1, 3, 8, 9, 4, 7, 2, 5, 6, 6, 9, 2, 3, 5, + 1, 8, 7, 4, 7, 4, 5, 2, 8, 6, 3, 1, 9}; + for (int i = 0; i < a.N; i++) + for (int j = 0; j < a.N; j++) + assert(a.a[i * a.N + j] == expected[i * a.N + j]); +``` + +3. Small C program that showcases and explains the use of tests. + +```c +#include /// for IO operations +#include /// for assert +#include /// for bool + +/** + * @brief Verifies if the given array + * contains the given number on it. + * @param arr the array to be used for checking + * @param number the number to check if it's inside the array + * @return false if the number was NOT found in the array + * @return true if the number WAS found in the array + */ +bool is_number_on_array(const int *arr, const int number) { + for (int i = 0; i < sizeof(arr); i++) { + if (arr[i] == number) { + return true; + } + else { + // Number not in the current index, keep searching. + } + } + + return false; +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void tests() { + int arr[] = { 9, 14, 21, 98, 67 }; + + assert(is_number_on_array(arr, 9) == true); + assert(is_number_on_array(arr, 4) == false); + assert(is_number_on_array(arr, 98) == true); + assert(is_number_on_array(arr, 512) == false); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + tests(); // run self-test implementations + return 0; +} +``` #### Typical structure of a program ```c /** * @file - * @brief Add one line description here + * @brief Add one line description here. Should contain a Wikipedia + * link or another source explaining the algorithm/implementation. * @details * This is a multi-line * description containing links, references, @@ -104,6 +205,9 @@ static void test() { assert(func(...) == ...); // this ensures that the algorithm works as expected // can have multiple checks + + // this lets the user know that the tests passed + printf("All tests have successfully passed!\n"); } /** @@ -129,12 +233,12 @@ my_new_c_struct.c is correct format - It will be used to dynamically create a directory of files and implementation. - File name validation will run on Docker to ensure validity. -- If an implementation of the algorithm already exists and your version is different from that implemented, please use incremental numeric digit as a suffix. For example: if `median_search.c` already exists in the `search` folder, and you are contributing a new implementation, the filename should be `median_search2.c` and for a third implementation, `median_search3.c`. +- If an implementation of the algorithm already exists and your version is different from that implemented, please use an incremental numeric digit as a suffix. For example: if `median_search.c` already exists in the `search` folder, and you are contributing a new implementation, the filename should be `median_search2.c`. For a third implementation, `median_search3.c`, and so on. #### Directory guidelines - We recommend adding files to existing directories as much as possible. -- Use lowercase words with ``"_"`` as separator ( no spaces or ```"-"``` allowed ) +- Use lowercase words with ``"_"`` as a separator ( no spaces or ```"-"``` allowed ) - For instance ```markdown @@ -145,9 +249,45 @@ some_new_fancy_category is correct - Filepaths will be used to dynamically create a directory of our algorithms. - Filepath validation will run on GitHub Actions to ensure compliance. +##### Integrating CMake in a new directory + +In case a new directory is 100% required, `CMakeLists.txt` file in the root directory needs to be updated, and a new `CMakeLists.txt` file needs to be created within the new directory. + +An example of how your new `CMakeLists.txt` file should look like. Note that if there are any extra libraries/setup required, you must include that in this file as well. + +```cmake +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. The RELATIVE flag makes it easier to extract an executable's name +# automatically. + +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c ) +foreach( testsourcefile ${APP_SOURCES} ) + string( REPLACE ".c" "" testname ${testsourcefile} ) # File type. Example: `.c` + add_executable( ${testname} ${testsourcefile} ) + + if(OpenMP_C_FOUND) + target_link_libraries(${testname} OpenMP::OpenMP_C) + endif() + if(MATH_LIBRARY) + target_link_libraries(${testname} ${MATH_LIBRARY}) + endif() + install(TARGETS ${testname} DESTINATION "bin/") # Folder name. Do NOT include `<>` + +endforeach( testsourcefile ${APP_SOURCES} ) +``` + +The `CMakeLists.txt` file in the root directory should be updated to include the new directory.\ +Include your new directory after the last subdirectory. Example: + +```cmake +... +add_subdirectory(numerical_methods) +add_subdirectory() +``` + #### Commit Guidelines -- It is recommended to keep your changes grouped logically within individual commits. Maintainers find it easier to understand changes that are logically spilt across multiple commits. Try to modify just one or two files in the same directory. Pull requests that span multiple directories are often rejected. +- It is recommended to keep your changes grouped logically within individual commits. Maintainers find it easier to understand changes that are logically spilled across multiple commits. Try to modify just one or two files in the same directory. Pull requests that span multiple directories are often rejected. ```bash git add file_xyz.c @@ -161,6 +301,7 @@ fix: xyz algorithm bug feat: add xyx algorithm, struct xyz test: add test for xyz algorithm docs: add comments and explanation to xyz algorithm +chore: update Gitpod badge ``` Common prefixes: @@ -169,6 +310,7 @@ Common prefixes: - feat: A new feature - docs: Documentation changes - test: Correct existing tests or add new ones +- chore: Miscellaneous changes that do not match any of the above. ### Pull Requests @@ -184,7 +326,7 @@ cmake -B build -S . #### Static Code Analyzer -We use [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) as a static code analyzer with a configuration in [.clang-tidy](.clang-tidy). +We use [`clang-tidy`](https://clang.llvm.org/extra/clang-tidy/) as a static code analyzer with a configuration in [`.clang-tidy`](.clang-tidy). ```bash clang-tidy --fix --quiet -p build subfolder/file_to_check.c -- @@ -192,7 +334,7 @@ clang-tidy --fix --quiet -p build subfolder/file_to_check.c -- #### Code Formatter -[__clang-format__](https://clang.llvm.org/docs/ClangFormat.html) is used for code forrmating. +[**`clang-format`**](https://clang.llvm.org/docs/ClangFormat.html) is used for code formatting. - Installation (only needs to be installed once.) - Mac (using home-brew): `brew install clang-format` @@ -204,7 +346,7 @@ clang-tidy --fix --quiet -p build subfolder/file_to_check.c -- #### GitHub Actions - Enable GitHub Actions on your fork of the repository. -After enabling, it will execute `clang-tidy` and `clang-format` after every a push (not a commit). +After enabling, it will execute `clang-tidy` and `clang-format` after every push (not a commit). - Click on the tab "Actions", then click on the big green button to enable it. ![GitHub Actions](https://user-images.githubusercontent.com/51391473/94609466-6e925100-0264-11eb-9d6f-3706190eab2b.png) diff --git a/DIRECTORY.md b/DIRECTORY.md index b5a7be6641..1339bc6ffc 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1,420 +1,361 @@ -# List of all files ## Audio - * [Alaw](https://github.com/TheAlgorithms/C/blob/master/audio/alaw.c) + * [Alaw](https://github.com/TheAlgorithms/C/blob/HEAD/audio/alaw.c) + +## Cipher + * [Affine](https://github.com/TheAlgorithms/C/blob/HEAD/cipher/affine.c) + * [Rot13](https://github.com/TheAlgorithms/C/blob/HEAD/cipher/rot13.c) ## Client Server - * [Client](https://github.com/TheAlgorithms/C/blob/master/client_server/client.c) - * [Remote Command Exec Udp Client](https://github.com/TheAlgorithms/C/blob/master/client_server/remote_command_exec_udp_client.c) - * [Remote Command Exec Udp Server](https://github.com/TheAlgorithms/C/blob/master/client_server/remote_command_exec_udp_server.c) - * [Server](https://github.com/TheAlgorithms/C/blob/master/client_server/server.c) - * [Tcp Full Duplex Client](https://github.com/TheAlgorithms/C/blob/master/client_server/tcp_full_duplex_client.c) - * [Tcp Full Duplex Server](https://github.com/TheAlgorithms/C/blob/master/client_server/tcp_full_duplex_server.c) - * [Tcp Half Duplex Client](https://github.com/TheAlgorithms/C/blob/master/client_server/tcp_half_duplex_client.c) - * [Tcp Half Duplex Server](https://github.com/TheAlgorithms/C/blob/master/client_server/tcp_half_duplex_server.c) - * [Udp Client](https://github.com/TheAlgorithms/C/blob/master/client_server/udp_client.c) - * [Udp Server](https://github.com/TheAlgorithms/C/blob/master/client_server/udp_server.c) + * [Bool](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/bool.h) + * [Client](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/client.c) + * [Fork](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/fork.h) + * [Remote Command Exec Udp Client](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/remote_command_exec_udp_client.c) + * [Remote Command Exec Udp Server](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/remote_command_exec_udp_server.c) + * [Server](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/server.c) + * [Tcp Full Duplex Client](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/tcp_full_duplex_client.c) + * [Tcp Full Duplex Server](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/tcp_full_duplex_server.c) + * [Tcp Half Duplex Client](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/tcp_half_duplex_client.c) + * [Tcp Half Duplex Server](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/tcp_half_duplex_server.c) + * [Udp Client](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/udp_client.c) + * [Udp Server](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/udp_server.c) ## Conversions - * [Binary To Decimal](https://github.com/TheAlgorithms/C/blob/master/conversions/binary_to_decimal.c) - * [Binary To Hexadecimal](https://github.com/TheAlgorithms/C/blob/master/conversions/binary_to_hexadecimal.c) - * [Binary To Octal](https://github.com/TheAlgorithms/C/blob/master/conversions/binary_to_octal.c) - * [C Atoi Str To Integer](https://github.com/TheAlgorithms/C/blob/master/conversions/c_atoi_str_to_integer.c) - * [Decimal To Any Base](https://github.com/TheAlgorithms/C/blob/master/conversions/decimal_to_any_base.c) - * [Decimal To Binary](https://github.com/TheAlgorithms/C/blob/master/conversions/decimal_to_binary.c) - * [Decimal To Binary Recursion](https://github.com/TheAlgorithms/C/blob/master/conversions/decimal_to_binary_recursion.c) - * [Decimal To Hexa](https://github.com/TheAlgorithms/C/blob/master/conversions/decimal_to_hexa.c) - * [Decimal To Octal](https://github.com/TheAlgorithms/C/blob/master/conversions/decimal_to_octal.c) - * [Decimal To Octal Recursion](https://github.com/TheAlgorithms/C/blob/master/conversions/decimal_to_octal_recursion.c) - * [Hexadecimal To Octal](https://github.com/TheAlgorithms/C/blob/master/conversions/hexadecimal_to_octal.c) - * [Hexadecimal To Octal2](https://github.com/TheAlgorithms/C/blob/master/conversions/hexadecimal_to_octal2.c) - * [Infix To Postfix](https://github.com/TheAlgorithms/C/blob/master/conversions/infix_to_postfix.c) - * [Infix To Postfix2](https://github.com/TheAlgorithms/C/blob/master/conversions/infix_to_postfix2.c) - * [Int To String](https://github.com/TheAlgorithms/C/blob/master/conversions/int_to_string.c) - * [Octal To Binary](https://github.com/TheAlgorithms/C/blob/master/conversions/octal_to_binary.c) - * [Octal To Decimal](https://github.com/TheAlgorithms/C/blob/master/conversions/octal_to_decimal.c) - * [Octal To Hexadecimal](https://github.com/TheAlgorithms/C/blob/master/conversions/octal_to_hexadecimal.c) - * [To Decimal](https://github.com/TheAlgorithms/C/blob/master/conversions/to_decimal.c) + * [Binary To Decimal](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/binary_to_decimal.c) + * [Binary To Hexadecimal](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/binary_to_hexadecimal.c) + * [Binary To Octal](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/binary_to_octal.c) + * [C Atoi Str To Integer](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/c_atoi_str_to_integer.c) + * [Celsius To Fahrenheit](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/celsius_to_fahrenheit.c) + * [Decimal To Any Base](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/decimal_to_any_base.c) + * [Decimal To Binary](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/decimal_to_binary.c) + * [Decimal To Binary Recursion](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/decimal_to_binary_recursion.c) + * [Decimal To Hexa](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/decimal_to_hexa.c) + * [Decimal To Octal](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/decimal_to_octal.c) + * [Decimal To Octal Recursion](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/decimal_to_octal_recursion.c) + * [Hexadecimal To Octal](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/hexadecimal_to_octal.c) + * [Hexadecimal To Octal2](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/hexadecimal_to_octal2.c) + * [Infix To Postfix](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/infix_to_postfix.c) + * [Infix To Postfix2](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/infix_to_postfix2.c) + * [Int To String](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/int_to_string.c) + * [Octal To Binary](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/octal_to_binary.c) + * [Octal To Decimal](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/octal_to_decimal.c) + * [Octal To Hexadecimal](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/octal_to_hexadecimal.c) + * [Roman Numerals To Decimal](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/roman_numerals_to_decimal.c) + * [To Decimal](https://github.com/TheAlgorithms/C/blob/HEAD/conversions/to_decimal.c) ## Data Structures * Array - * [Carray](https://github.com/TheAlgorithms/C/blob/master/data_structures/array/carray.c) - * [Carray](https://github.com/TheAlgorithms/C/blob/master/data_structures/array/carray.h) - * [Carray Tests](https://github.com/TheAlgorithms/C/blob/master/data_structures/array/carray_tests.c) + * [Carray](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/array/carray.c) + * [Carray](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/array/carray.h) + * [Carray Tests](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/array/carray_tests.c) * Binary Trees - * [Avl Tree](https://github.com/TheAlgorithms/C/blob/master/data_structures/binary_trees/avl_tree.c) - * [Binary Search Tree](https://github.com/TheAlgorithms/C/blob/master/data_structures/binary_trees/binary_search_tree.c) - * [Create Node](https://github.com/TheAlgorithms/C/blob/master/data_structures/binary_trees/create_node.c) - * [Recursive Traversals](https://github.com/TheAlgorithms/C/blob/master/data_structures/binary_trees/recursive_traversals.c) - * [Red Black Tree](https://github.com/TheAlgorithms/C/blob/master/data_structures/binary_trees/red_black_tree.c) - * [Segment Tree](https://github.com/TheAlgorithms/C/blob/master/data_structures/binary_trees/segment_tree.c) - * [Threaded Binary Trees](https://github.com/TheAlgorithms/C/blob/master/data_structures/binary_trees/threaded_binary_trees.c) - * [Words Alphabetical](https://github.com/TheAlgorithms/C/blob/master/data_structures/binary_trees/words_alphabetical.c) + * [Avl Tree](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/binary_trees/avl_tree.c) + * [Binary Search Tree](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/binary_trees/binary_search_tree.c) + * [Create Node](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/binary_trees/create_node.c) + * [Recursive Traversals](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/binary_trees/recursive_traversals.c) + * [Red Black Tree](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/binary_trees/red_black_tree.c) + * [Segment Tree](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/binary_trees/segment_tree.c) + * [Threaded Binary Trees](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/binary_trees/threaded_binary_trees.c) + * [Words Alphabetical](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/binary_trees/words_alphabetical.c) * Dictionary - * [Dict](https://github.com/TheAlgorithms/C/blob/master/data_structures/dictionary/dict.c) - * [Dict](https://github.com/TheAlgorithms/C/blob/master/data_structures/dictionary/dict.h) - * [Test Program](https://github.com/TheAlgorithms/C/blob/master/data_structures/dictionary/test_program.c) + * [Dict](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/dictionary/dict.c) + * [Dict](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/dictionary/dict.h) + * [Test Program](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/dictionary/test_program.c) * Dynamic Array - * [Dynamic Array](https://github.com/TheAlgorithms/C/blob/master/data_structures/dynamic_array/dynamic_array.c) - * [Dynamic Array](https://github.com/TheAlgorithms/C/blob/master/data_structures/dynamic_array/dynamic_array.h) - * [Main](https://github.com/TheAlgorithms/C/blob/master/data_structures/dynamic_array/main.c) + * [Dynamic Array](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/dynamic_array/dynamic_array.c) + * [Dynamic Array](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/dynamic_array/dynamic_array.h) + * [Main](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/dynamic_array/main.c) * Graphs - * [Bellman Ford](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/bellman_ford.c) - * [Bfs](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/bfs.c) - * [Bfs Queue](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/bfs_queue.c) - * [Dfs](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/dfs.c) - * [Dfs Recursive](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/dfs_recursive.c) - * [Dijkstra](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/dijkstra.c) - * [Euler](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/euler.c) - * [Floyd Warshall](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/floyd_warshall.c) - * [Graph](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/graph.c) - * [Graph](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/graph.h) - * [Hamiltonian](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/hamiltonian.c) - * [Kruskal](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/kruskal.c) - * [Queue](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/queue.c) - * [Queue](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/queue.h) - * [Strongly Connected Components](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/strongly_connected_components.c) - * [Topological Sort](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/topological_sort.c) - * [Transitive Closure](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/transitive_closure.c) + * [Bellman Ford](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/bellman_ford.c) + * [Bfs](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/bfs.c) + * [Bfs Queue](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/bfs_queue.c) + * [Dfs](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/dfs.c) + * [Dfs Recursive](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/dfs_recursive.c) + * [Dijkstra](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/dijkstra.c) + * [Euler](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/euler.c) + * [Floyd Warshall](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/floyd_warshall.c) + * [Graph](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/graph.c) + * [Graph](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/graph.h) + * [Hamiltonian](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/hamiltonian.c) + * [Kruskal](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/kruskal.c) + * [Queue](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/queue.c) + * [Queue](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/queue.h) + * [Strongly Connected Components](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/strongly_connected_components.c) + * [Topological Sort](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/topological_sort.c) + * [Transitive Closure](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/graphs/transitive_closure.c) * Hash Set - * [Hash Set](https://github.com/TheAlgorithms/C/blob/master/data_structures/hash_set/hash_set.c) - * [Hash Set](https://github.com/TheAlgorithms/C/blob/master/data_structures/hash_set/hash_set.h) - * [Main](https://github.com/TheAlgorithms/C/blob/master/data_structures/hash_set/main.c) + * [Hash Set](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/hash_set/hash_set.c) + * [Hash Set](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/hash_set/hash_set.h) + * [Main](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/hash_set/main.c) * Heap - * [Max Heap](https://github.com/TheAlgorithms/C/blob/master/data_structures/heap/max_heap.c) - * [Min Heap](https://github.com/TheAlgorithms/C/blob/master/data_structures/heap/min_heap.c) + * [Max Heap](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/heap/max_heap.c) + * [Min Heap](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/heap/min_heap.c) * Linked List - * [Ascending Priority Queue](https://github.com/TheAlgorithms/C/blob/master/data_structures/linked_list/ascending_priority_queue.c) - * [Circular Linked List](https://github.com/TheAlgorithms/C/blob/master/data_structures/linked_list/circular_linked_list.c) - * [Doubly Linked List](https://github.com/TheAlgorithms/C/blob/master/data_structures/linked_list/doubly_linked_list.c) - * [Merge Linked Lists](https://github.com/TheAlgorithms/C/blob/master/data_structures/linked_list/merge_linked_lists.c) - * [Middle Element In List](https://github.com/TheAlgorithms/C/blob/master/data_structures/linked_list/middle_element_in_list.c) - * [Queue Linked List](https://github.com/TheAlgorithms/C/blob/master/data_structures/linked_list/queue_linked_list.c) - * [Singly Link List Deletion](https://github.com/TheAlgorithms/C/blob/master/data_structures/linked_list/singly_link_list_deletion.c) - * [Stack Using Linked Lists](https://github.com/TheAlgorithms/C/blob/master/data_structures/linked_list/stack_using_linked_lists.c) + * [Ascending Priority Queue](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/ascending_priority_queue.c) + * [Circular Doubly Linked List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/circular_doubly_linked_list.c) + * [Circular Linked List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/circular_linked_list.c) + * [Doubly Linked List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/doubly_linked_list.c) + * [Merge Linked Lists](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/merge_linked_lists.c) + * [Middle Element In List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/middle_element_in_list.c) + * [Queue Linked List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/queue_linked_list.c) + * [Singly Link List Deletion](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/singly_link_list_deletion.c) + * [Stack Using Linked Lists](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/stack_using_linked_lists.c) * List - * [List](https://github.com/TheAlgorithms/C/blob/master/data_structures/list/list.c) - * [List](https://github.com/TheAlgorithms/C/blob/master/data_structures/list/list.h) - * [Main](https://github.com/TheAlgorithms/C/blob/master/data_structures/list/main.c) + * [List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/list/list.c) + * [List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/list/list.h) + * [Main](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/list/main.c) * Queue - * [Include](https://github.com/TheAlgorithms/C/blob/master/data_structures/queue/include.h) - * [Queue](https://github.com/TheAlgorithms/C/blob/master/data_structures/queue/queue.c) - * [Stack](https://github.com/TheAlgorithms/C/blob/master/data_structures/stack.c) + * [Include](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/queue/include.h) + * [Queue](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/queue/queue.c) + * [Stack](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/stack.c) * Stack - * [Main](https://github.com/TheAlgorithms/C/blob/master/data_structures/stack/main.c) - * [Parenthesis](https://github.com/TheAlgorithms/C/blob/master/data_structures/stack/parenthesis.c) - * [Stack](https://github.com/TheAlgorithms/C/blob/master/data_structures/stack/stack.c) - * [Stack](https://github.com/TheAlgorithms/C/blob/master/data_structures/stack/stack.h) + * [Dynamic Stack](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/stack/dynamic_stack.c) + * [Main](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/stack/main.c) + * [Parenthesis](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/stack/parenthesis.c) + * [Stack](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/stack/stack.c) + * [Stack](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/stack/stack.h) * Stack Linked List - * [Main](https://github.com/TheAlgorithms/C/blob/master/data_structures/stack/stack_linked_list/main.c) - * [Stack](https://github.com/TheAlgorithms/C/blob/master/data_structures/stack/stack_linked_list/stack.c) - * [Stack](https://github.com/TheAlgorithms/C/blob/master/data_structures/stack/stack_linked_list/stack.h) + * [Main](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/stack/stack_linked_list/main.c) + * [Stack](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/stack/stack_linked_list/stack.c) + * [Stack](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/stack/stack_linked_list/stack.h) * Trie - * [Trie](https://github.com/TheAlgorithms/C/blob/master/data_structures/trie/trie.c) + * [Trie](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/trie/trie.c) + * [Vector](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/vector.c) ## Developer Tools - * [Malloc Dbg](https://github.com/TheAlgorithms/C/blob/master/developer_tools/malloc_dbg.c) - * [Malloc Dbg](https://github.com/TheAlgorithms/C/blob/master/developer_tools/malloc_dbg.h) - * [Min Printf](https://github.com/TheAlgorithms/C/blob/master/developer_tools/min_printf.h) - * [Test Malloc Dbg](https://github.com/TheAlgorithms/C/blob/master/developer_tools/test_malloc_dbg.c) - * [Test Min Printf](https://github.com/TheAlgorithms/C/blob/master/developer_tools/test_min_printf.c) + * [Malloc Dbg](https://github.com/TheAlgorithms/C/blob/HEAD/developer_tools/malloc_dbg.c) + * [Malloc Dbg](https://github.com/TheAlgorithms/C/blob/HEAD/developer_tools/malloc_dbg.h) + * [Min Printf](https://github.com/TheAlgorithms/C/blob/HEAD/developer_tools/min_printf.h) + * [Test Malloc Dbg](https://github.com/TheAlgorithms/C/blob/HEAD/developer_tools/test_malloc_dbg.c) + * [Test Min Printf](https://github.com/TheAlgorithms/C/blob/HEAD/developer_tools/test_min_printf.c) + +## Dynamic Programming + * [Lcs](https://github.com/TheAlgorithms/C/blob/HEAD/dynamic_programming/lcs.c) + * [Matrix Chain Order](https://github.com/TheAlgorithms/C/blob/HEAD/dynamic_programming/matrix_chain_order.c) ## Exercism * Acronym - * [Acronym](https://github.com/TheAlgorithms/C/blob/master/exercism/acronym/acronym.c) - * [Acronym](https://github.com/TheAlgorithms/C/blob/master/exercism/acronym/acronym.h) + * [Acronym](https://github.com/TheAlgorithms/C/blob/HEAD/exercism/acronym/acronym.c) + * [Acronym](https://github.com/TheAlgorithms/C/blob/HEAD/exercism/acronym/acronym.h) * Hello World - * [Hello World](https://github.com/TheAlgorithms/C/blob/master/exercism/hello_world/hello_world.c) - * [Hello World](https://github.com/TheAlgorithms/C/blob/master/exercism/hello_world/hello_world.h) + * [Hello World](https://github.com/TheAlgorithms/C/blob/HEAD/exercism/hello_world/hello_world.c) + * [Hello World](https://github.com/TheAlgorithms/C/blob/HEAD/exercism/hello_world/hello_world.h) * Isogram - * [Isogram](https://github.com/TheAlgorithms/C/blob/master/exercism/isogram/isogram.c) - * [Isogram](https://github.com/TheAlgorithms/C/blob/master/exercism/isogram/isogram.h) + * [Isogram](https://github.com/TheAlgorithms/C/blob/HEAD/exercism/isogram/isogram.c) + * [Isogram](https://github.com/TheAlgorithms/C/blob/HEAD/exercism/isogram/isogram.h) * Rna Transcription - * [Rna Transcription](https://github.com/TheAlgorithms/C/blob/master/exercism/rna_transcription/rna_transcription.c) - * [Rna Transcription](https://github.com/TheAlgorithms/C/blob/master/exercism/rna_transcription/rna_transcription.h) + * [Rna Transcription](https://github.com/TheAlgorithms/C/blob/HEAD/exercism/rna_transcription/rna_transcription.c) + * [Rna Transcription](https://github.com/TheAlgorithms/C/blob/HEAD/exercism/rna_transcription/rna_transcription.h) * Word Count - * [Word Count](https://github.com/TheAlgorithms/C/blob/master/exercism/word_count/word_count.c) - * [Word Count](https://github.com/TheAlgorithms/C/blob/master/exercism/word_count/word_count.h) + * [Word Count](https://github.com/TheAlgorithms/C/blob/HEAD/exercism/word_count/word_count.c) + * [Word Count](https://github.com/TheAlgorithms/C/blob/HEAD/exercism/word_count/word_count.h) ## Games - * [Naval Battle](https://github.com/TheAlgorithms/C/blob/master/games/naval_battle.c) - * [Tic Tac Toe](https://github.com/TheAlgorithms/C/blob/master/games/tic_tac_toe.c) + * [Hangman](https://github.com/TheAlgorithms/C/blob/HEAD/games/hangman.c) + * [Naval Battle](https://github.com/TheAlgorithms/C/blob/HEAD/games/naval_battle.c) + * [Tic Tac Toe](https://github.com/TheAlgorithms/C/blob/HEAD/games/tic_tac_toe.c) ## Geometry - * [Geometry Datatypes](https://github.com/TheAlgorithms/C/blob/master/geometry/geometry_datatypes.h) - * [Quaternions](https://github.com/TheAlgorithms/C/blob/master/geometry/quaternions.c) - * [Vectors 3D](https://github.com/TheAlgorithms/C/blob/master/geometry/vectors_3d.c) + * [Geometry Datatypes](https://github.com/TheAlgorithms/C/blob/HEAD/geometry/geometry_datatypes.h) + * [Quaternions](https://github.com/TheAlgorithms/C/blob/HEAD/geometry/quaternions.c) + * [Vectors 3D](https://github.com/TheAlgorithms/C/blob/HEAD/geometry/vectors_3d.c) ## Graphics - * [Spirograph](https://github.com/TheAlgorithms/C/blob/master/graphics/spirograph.c) + * [Spirograph](https://github.com/TheAlgorithms/C/blob/HEAD/graphics/spirograph.c) ## Greedy Approach - * [Djikstra](https://github.com/TheAlgorithms/C/blob/master/greedy_approach/djikstra.c) - * [Prim](https://github.com/TheAlgorithms/C/blob/master/greedy_approach/prim.c) + * [Dijkstra](https://github.com/TheAlgorithms/C/blob/HEAD/greedy_approach/dijkstra.c) + * [Prim](https://github.com/TheAlgorithms/C/blob/HEAD/greedy_approach/prim.c) ## Hash - * [Hash Adler32](https://github.com/TheAlgorithms/C/blob/master/hash/hash_adler32.c) - * [Hash Crc32](https://github.com/TheAlgorithms/C/blob/master/hash/hash_crc32.c) - * [Hash Djb2](https://github.com/TheAlgorithms/C/blob/master/hash/hash_djb2.c) - * [Hash Sdbm](https://github.com/TheAlgorithms/C/blob/master/hash/hash_sdbm.c) - * [Hash Xor8](https://github.com/TheAlgorithms/C/blob/master/hash/hash_xor8.c) - -## Leetcode - * Src - * [1](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/1.c) - * [101](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/101.c) - * [104](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/104.c) - * [108](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/108.c) - * [1089](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/1089.c) - * [109](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/109.c) - * [11](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/11.c) - * [110](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/110.c) - * [112](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/112.c) - * [1184](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/1184.c) - * [1189](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/1189.c) - * [12](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/12.c) - * [1207](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/1207.c) - * [121](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/121.c) - * [125](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/125.c) - * [13](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/13.c) - * [136](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/136.c) - * [141](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/141.c) - * [142](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/142.c) - * [153](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/153.c) - * [160](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/160.c) - * [169](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/169.c) - * [173](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/173.c) - * [189](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/189.c) - * [190](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/190.c) - * [191](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/191.c) - * [2](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/2.c) - * [20](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/20.c) - * [201](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/201.c) - * [203](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/203.c) - * [206](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/206.c) - * [21](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/21.c) - * [215](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/215.c) - * [217](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/217.c) - * [226](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/226.c) - * [231](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/231.c) - * [234](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/234.c) - * [24](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/24.c) - * [242](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/242.c) - * [26](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/26.c) - * [268](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/268.c) - * [27](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/27.c) - * [278](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/278.c) - * [28](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/28.c) - * [283](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/283.c) - * [287](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/287.c) - * [29](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/29.c) - * [3](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/3.c) - * [344](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/344.c) - * [35](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/35.c) - * [367](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/367.c) - * [38](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/38.c) - * [387](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/387.c) - * [389](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/389.c) - * [4](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/4.c) - * [404](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/404.c) - * [442](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/442.c) - * [461](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/461.c) - * [476](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/476.c) - * [509](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/509.c) - * [520](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/520.c) - * [53](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/53.c) - * [561](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/561.c) - * [6](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/6.c) - * [617](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/617.c) - * [647](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/647.c) - * [66](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/66.c) - * [674](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/674.c) - * [7](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/7.c) - * [700](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/700.c) - * [701](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/701.c) - * [704](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/704.c) - * [709](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/709.c) - * [771](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/771.c) - * [8](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/8.c) - * [82](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/82.c) - * [83](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/83.c) - * [852](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/852.c) - * [876](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/876.c) - * [9](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/9.c) - * [905](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/905.c) - * [917](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/917.c) - * [938](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/938.c) - * [94](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/94.c) - * [965](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/965.c) - * [977](https://github.com/TheAlgorithms/C/blob/master/leetcode/src/977.c) + * [Hash Adler32](https://github.com/TheAlgorithms/C/blob/HEAD/hash/hash_adler32.c) + * [Hash Blake2B](https://github.com/TheAlgorithms/C/blob/HEAD/hash/hash_blake2b.c) + * [Hash Crc32](https://github.com/TheAlgorithms/C/blob/HEAD/hash/hash_crc32.c) + * [Hash Djb2](https://github.com/TheAlgorithms/C/blob/HEAD/hash/hash_djb2.c) + * [Hash Sdbm](https://github.com/TheAlgorithms/C/blob/HEAD/hash/hash_sdbm.c) + * [Hash Xor8](https://github.com/TheAlgorithms/C/blob/HEAD/hash/hash_xor8.c) ## Machine Learning - * [Adaline Learning](https://github.com/TheAlgorithms/C/blob/master/machine_learning/adaline_learning.c) - * [K Means Clustering](https://github.com/TheAlgorithms/C/blob/master/machine_learning/k_means_clustering.c) - * [Kohonen Som Topology](https://github.com/TheAlgorithms/C/blob/master/machine_learning/kohonen_som_topology.c) - * [Kohonen Som Trace](https://github.com/TheAlgorithms/C/blob/master/machine_learning/kohonen_som_trace.c) + * [Adaline Learning](https://github.com/TheAlgorithms/C/blob/HEAD/machine_learning/adaline_learning.c) + * [K Means Clustering](https://github.com/TheAlgorithms/C/blob/HEAD/machine_learning/k_means_clustering.c) + * [Kohonen Som Topology](https://github.com/TheAlgorithms/C/blob/HEAD/machine_learning/kohonen_som_topology.c) + * [Kohonen Som Trace](https://github.com/TheAlgorithms/C/blob/HEAD/machine_learning/kohonen_som_trace.c) + +## Math + * [Armstrong Number](https://github.com/TheAlgorithms/C/blob/HEAD/math/armstrong_number.c) + * [Cantor Set](https://github.com/TheAlgorithms/C/blob/HEAD/math/cantor_set.c) + * [Cartesian To Polar](https://github.com/TheAlgorithms/C/blob/HEAD/math/cartesian_to_polar.c) + * [Catalan](https://github.com/TheAlgorithms/C/blob/HEAD/math/catalan.c) + * [Collatz](https://github.com/TheAlgorithms/C/blob/HEAD/math/collatz.c) + * [Euclidean Algorithm Extended](https://github.com/TheAlgorithms/C/blob/HEAD/math/euclidean_algorithm_extended.c) + * [Factorial](https://github.com/TheAlgorithms/C/blob/HEAD/math/factorial.c) + * [Factorial Large Number](https://github.com/TheAlgorithms/C/blob/HEAD/math/factorial_large_number.c) + * [Factorial Trailing Zeroes](https://github.com/TheAlgorithms/C/blob/HEAD/math/factorial_trailing_zeroes.c) + * [Fibonacci](https://github.com/TheAlgorithms/C/blob/HEAD/math/fibonacci.c) + * [Fibonacci Dp](https://github.com/TheAlgorithms/C/blob/HEAD/math/fibonacci_dp.c) + * [Fibonacci Fast](https://github.com/TheAlgorithms/C/blob/HEAD/math/fibonacci_fast.c) + * [Fibonacci Formula](https://github.com/TheAlgorithms/C/blob/HEAD/math/fibonacci_formula.c) + * [Gcd](https://github.com/TheAlgorithms/C/blob/HEAD/math/gcd.c) + * [Is Armstrong](https://github.com/TheAlgorithms/C/blob/HEAD/math/is_armstrong.c) + * [Large Factorials](https://github.com/TheAlgorithms/C/blob/HEAD/math/large_factorials.c) + * [Lcm](https://github.com/TheAlgorithms/C/blob/HEAD/math/lcm.c) + * [Lerp](https://github.com/TheAlgorithms/C/blob/HEAD/math/lerp.c) + * [Palindrome](https://github.com/TheAlgorithms/C/blob/HEAD/math/palindrome.c) + * [Prime](https://github.com/TheAlgorithms/C/blob/HEAD/math/prime.c) + * [Prime Factoriziation](https://github.com/TheAlgorithms/C/blob/HEAD/math/prime_factoriziation.c) + * [Prime Sieve](https://github.com/TheAlgorithms/C/blob/HEAD/math/prime_sieve.c) + * [Strong Number](https://github.com/TheAlgorithms/C/blob/HEAD/math/strong_number.c) ## Misc - * [Armstrong Number](https://github.com/TheAlgorithms/C/blob/master/misc/armstrong_number.c) - * [Cantor Set](https://github.com/TheAlgorithms/C/blob/master/misc/cantor_set.c) - * [Cartesian To Polar](https://github.com/TheAlgorithms/C/blob/master/misc/cartesian_to_polar.c) - * [Catalan](https://github.com/TheAlgorithms/C/blob/master/misc/catalan.c) - * [Collatz](https://github.com/TheAlgorithms/C/blob/master/misc/collatz.c) - * [Demonetization](https://github.com/TheAlgorithms/C/blob/master/misc/demonetization.c) - * [Factorial](https://github.com/TheAlgorithms/C/blob/master/misc/factorial.c) - * [Factorial Large Number](https://github.com/TheAlgorithms/C/blob/master/misc/factorial_large_number.c) - * [Factorial Trailing Zeroes](https://github.com/TheAlgorithms/C/blob/master/misc/factorial_trailing_zeroes.c) - * [Fibonacci](https://github.com/TheAlgorithms/C/blob/master/misc/fibonacci.c) - * [Fibonacci Dp](https://github.com/TheAlgorithms/C/blob/master/misc/fibonacci_dp.c) - * [Fibonacci Fast](https://github.com/TheAlgorithms/C/blob/master/misc/fibonacci_fast.c) - * [Gcd](https://github.com/TheAlgorithms/C/blob/master/misc/gcd.c) - * [Is Armstrong](https://github.com/TheAlgorithms/C/blob/master/misc/is_armstrong.c) - * [Large Factorials](https://github.com/TheAlgorithms/C/blob/master/misc/large_factorials.c) - * [Lcm](https://github.com/TheAlgorithms/C/blob/master/misc/lcm.c) - * [Lerp](https://github.com/TheAlgorithms/C/blob/master/misc/lerp.c) - * [Lexicographic Permutations](https://github.com/TheAlgorithms/C/blob/master/misc/lexicographic_permutations.c) - * [Longest Subsequence](https://github.com/TheAlgorithms/C/blob/master/misc/longest_subsequence.c) - * [Mirror](https://github.com/TheAlgorithms/C/blob/master/misc/mirror.c) - * [Palindrome](https://github.com/TheAlgorithms/C/blob/master/misc/palindrome.c) - * [Pid](https://github.com/TheAlgorithms/C/blob/master/misc/pid.c) - * [Poly Add](https://github.com/TheAlgorithms/C/blob/master/misc/poly_add.c) - * [Postfix Evaluation](https://github.com/TheAlgorithms/C/blob/master/misc/postfix_evaluation.c) - * [Prime](https://github.com/TheAlgorithms/C/blob/master/misc/prime.c) - * [Prime Factoriziation](https://github.com/TheAlgorithms/C/blob/master/misc/prime_factoriziation.c) - * [Prime Seive](https://github.com/TheAlgorithms/C/blob/master/misc/prime_seive.c) - * [Quartile](https://github.com/TheAlgorithms/C/blob/master/misc/quartile.c) - * [Rselect](https://github.com/TheAlgorithms/C/blob/master/misc/rselect.c) - * [Strong Number](https://github.com/TheAlgorithms/C/blob/master/misc/strong_number.c) - * [Sudoku Solver](https://github.com/TheAlgorithms/C/blob/master/misc/sudoku_solver.c) - * [Tower Of Hanoi](https://github.com/TheAlgorithms/C/blob/master/misc/tower_of_hanoi.c) - * [Union Find](https://github.com/TheAlgorithms/C/blob/master/misc/union_find.c) + * [Demonetization](https://github.com/TheAlgorithms/C/blob/HEAD/misc/demonetization.c) + * [Hamming Distance](https://github.com/TheAlgorithms/C/blob/HEAD/misc/hamming_distance.c) + * [Lexicographic Permutations](https://github.com/TheAlgorithms/C/blob/HEAD/misc/lexicographic_permutations.c) + * [Longest Subsequence](https://github.com/TheAlgorithms/C/blob/HEAD/misc/longest_subsequence.c) + * [Mcnaughton Yamada Thompson](https://github.com/TheAlgorithms/C/blob/HEAD/misc/mcnaughton_yamada_thompson.c) + * [Mirror](https://github.com/TheAlgorithms/C/blob/HEAD/misc/mirror.c) + * [Pid](https://github.com/TheAlgorithms/C/blob/HEAD/misc/pid.c) + * [Poly Add](https://github.com/TheAlgorithms/C/blob/HEAD/misc/poly_add.c) + * [Postfix Evaluation](https://github.com/TheAlgorithms/C/blob/HEAD/misc/postfix_evaluation.c) + * [Quartile](https://github.com/TheAlgorithms/C/blob/HEAD/misc/quartile.c) + * [Rselect](https://github.com/TheAlgorithms/C/blob/HEAD/misc/rselect.c) + * [Run Length Encoding](https://github.com/TheAlgorithms/C/blob/HEAD/misc/run_length_encoding.c) + * [Shunting Yard](https://github.com/TheAlgorithms/C/blob/HEAD/misc/shunting_yard.c) + * [Sudoku Solver](https://github.com/TheAlgorithms/C/blob/HEAD/misc/sudoku_solver.c) + * [Tower Of Hanoi](https://github.com/TheAlgorithms/C/blob/HEAD/misc/tower_of_hanoi.c) + * [Union Find](https://github.com/TheAlgorithms/C/blob/HEAD/misc/union_find.c) ## Numerical Methods - * [Durand Kerner Roots](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/durand_kerner_roots.c) - * [Gauss Elimination](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/gauss_elimination.c) - * [Gauss Seidel Method](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/gauss_seidel_method.c) - * [Lagrange Theorem](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/lagrange_theorem.c) - * [Lu Decompose](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/lu_decompose.c) - * [Mean](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/mean.c) - * [Median](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/median.c) - * [Newton Raphson Root](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/newton_raphson_root.c) - * [Ode Forward Euler](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/ode_forward_euler.c) - * [Ode Midpoint Euler](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/ode_midpoint_euler.c) - * [Ode Semi Implicit Euler](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/ode_semi_implicit_euler.c) - * [Qr Decompose](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/qr_decompose.h) - * [Qr Decomposition](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/qr_decomposition.c) - * [Qr Eigen Values](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/qr_eigen_values.c) - * [Realtime Stats](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/realtime_stats.c) - * [Simpsons 1 3Rd Rule](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/simpsons_1_3rd_rule.c) - * [Variance](https://github.com/TheAlgorithms/C/blob/master/numerical_methods/variance.c) + * [Bisection Method](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/bisection_method.c) + * [Durand Kerner Roots](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/durand_kerner_roots.c) + * [Gauss Elimination](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/gauss_elimination.c) + * [Gauss Seidel Method](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/gauss_seidel_method.c) + * [Lagrange Theorem](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/lagrange_theorem.c) + * [Lu Decompose](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/lu_decompose.c) + * [Mean](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/mean.c) + * [Median](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/median.c) + * [Newton Raphson Root](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/newton_raphson_root.c) + * [Ode Forward Euler](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/ode_forward_euler.c) + * [Ode Midpoint Euler](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/ode_midpoint_euler.c) + * [Ode Semi Implicit Euler](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/ode_semi_implicit_euler.c) + * [Qr Decompose](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/qr_decompose.h) + * [Qr Decomposition](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/qr_decomposition.c) + * [Qr Eigen Values](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/qr_eigen_values.c) + * [Realtime Stats](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/realtime_stats.c) + * [Secant Method](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/secant_method.c) + * [Simpsons 1 3Rd Rule](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/simpsons_1_3rd_rule.c) + * [Variance](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/variance.c) + +## Process Scheduling Algorithms + * [Non Preemptive Priority Scheduling](https://github.com/TheAlgorithms/C/blob/HEAD/process_scheduling_algorithms/non_preemptive_priority_scheduling.c) ## Project Euler * Problem 1 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_1/sol1.c) - * [Sol2](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_1/sol2.c) - * [Sol3](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_1/sol3.c) - * [Sol4](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_1/sol4.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_1/sol1.c) + * [Sol2](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_1/sol2.c) + * [Sol3](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_1/sol3.c) + * [Sol4](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_1/sol4.c) * Problem 10 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_10/sol1.c) - * [Sol2](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_10/sol2.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_10/sol1.c) + * [Sol2](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_10/sol2.c) * Problem 12 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_12/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_12/sol1.c) * Problem 13 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_13/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_13/sol1.c) * Problem 14 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_14/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_14/sol1.c) * Problem 15 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_15/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_15/sol1.c) * Problem 16 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_16/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_16/sol1.c) * Problem 19 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_19/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_19/sol1.c) * Problem 2 - * [So1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_2/so1.c) + * [So1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_2/so1.c) * Problem 20 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_20/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_20/sol1.c) * Problem 21 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_21/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_21/sol1.c) * Problem 22 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_22/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_22/sol1.c) * Problem 23 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_23/sol1.c) - * [Sol2](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_23/sol2.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_23/sol1.c) + * [Sol2](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_23/sol2.c) * Problem 25 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_25/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_25/sol1.c) * Problem 26 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_26/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_26/sol1.c) * Problem 3 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_3/sol1.c) - * [Sol2](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_3/sol2.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_3/sol1.c) + * [Sol2](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_3/sol2.c) * Problem 4 - * [Sol](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_4/sol.c) + * [Sol](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_4/sol.c) * Problem 401 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_401/sol1.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_401/sol1.c) * Problem 5 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_5/sol1.c) - * [Sol2](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_5/sol2.c) - * [Sol3](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_5/sol3.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_5/sol1.c) + * [Sol2](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_5/sol2.c) + * [Sol3](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_5/sol3.c) * Problem 6 - * [Sol](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_6/sol.c) + * [Sol](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_6/sol.c) * Problem 7 - * [Sol](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_7/sol.c) - * [Sol2](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_7/sol2.c) + * [Sol](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_7/sol.c) + * [Sol2](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_7/sol2.c) * Problem 8 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_8/sol1.c) - * [Sol2](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_8/sol2.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_8/sol1.c) + * [Sol2](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_8/sol2.c) * Problem 9 - * [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_9/sol1.c) - * [Sol2](https://github.com/TheAlgorithms/C/blob/master/project_euler/problem_9/sol2.c) + * [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_9/sol1.c) + * [Sol2](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_9/sol2.c) ## Searching - * [Binary Search](https://github.com/TheAlgorithms/C/blob/master/searching/binary_search.c) - * [Exponential Search](https://github.com/TheAlgorithms/C/blob/master/searching/exponential_search.c) - * [Fibonacci Search](https://github.com/TheAlgorithms/C/blob/master/searching/fibonacci_search.c) - * [Floyd Cycle Detection Algorithm](https://github.com/TheAlgorithms/C/blob/master/searching/floyd_cycle_detection_algorithm.c) - * [Interpolation Search](https://github.com/TheAlgorithms/C/blob/master/searching/interpolation_search.c) - * [Jump Search](https://github.com/TheAlgorithms/C/blob/master/searching/jump_search.c) - * [Linear Search](https://github.com/TheAlgorithms/C/blob/master/searching/linear_search.c) - * [Modified Binary Search](https://github.com/TheAlgorithms/C/blob/master/searching/modified_binary_search.c) - * [Other Binary Search](https://github.com/TheAlgorithms/C/blob/master/searching/other_binary_search.c) + * [Binary Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/binary_search.c) + * [Exponential Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/exponential_search.c) + * [Fibonacci Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/fibonacci_search.c) + * [Floyd Cycle Detection Algorithm](https://github.com/TheAlgorithms/C/blob/HEAD/searching/floyd_cycle_detection_algorithm.c) + * [Interpolation Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/interpolation_search.c) + * [Jump Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/jump_search.c) + * [Linear Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/linear_search.c) + * [Modified Binary Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/modified_binary_search.c) + * [Other Binary Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/other_binary_search.c) * Pattern Search - * [Boyer Moore Search](https://github.com/TheAlgorithms/C/blob/master/searching/pattern_search/boyer_moore_search.c) - * [Naive Search](https://github.com/TheAlgorithms/C/blob/master/searching/pattern_search/naive_search.c) - * [Rabin Karp Search](https://github.com/TheAlgorithms/C/blob/master/searching/pattern_search/rabin_karp_search.c) - * [Sentinel Linear Search](https://github.com/TheAlgorithms/C/blob/master/searching/sentinel_linear_search.c) - * [Ternary Search](https://github.com/TheAlgorithms/C/blob/master/searching/ternary_search.c) + * [Boyer Moore Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/pattern_search/boyer_moore_search.c) + * [Naive Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/pattern_search/naive_search.c) + * [Rabin Karp Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/pattern_search/rabin_karp_search.c) + * [Sentinel Linear Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/sentinel_linear_search.c) + * [Ternary Search](https://github.com/TheAlgorithms/C/blob/HEAD/searching/ternary_search.c) ## Sorting - * [Bead Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/bead_sort.c) - * [Binary Insertion Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/binary_insertion_sort.c) - * [Bogo Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/bogo_sort.c) - * [Bubble Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/bubble_sort.c) - * [Bubble Sort 2](https://github.com/TheAlgorithms/C/blob/master/sorting/bubble_sort_2.c) - * [Bubble Sort Recursion](https://github.com/TheAlgorithms/C/blob/master/sorting/bubble_sort_recursion.c) - * [Bucket Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/bucket_sort.c) - * [Cocktail Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/cocktail_sort.c) - * [Comb Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/comb_sort.c) - * [Counting Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/counting_sort.c) - * [Cycle Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/cycle_sort.c) - * [Gnome Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/gnome_sort.c) - * [Heap Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/heap_sort.c) - * [Heap Sort 2](https://github.com/TheAlgorithms/C/blob/master/sorting/heap_sort_2.c) - * [Insertion Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/insertion_sort.c) - * [Insertion Sort Recursive](https://github.com/TheAlgorithms/C/blob/master/sorting/insertion_sort_recursive.c) - * [Merge Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/merge_sort.c) - * [Merge Sort Nr](https://github.com/TheAlgorithms/C/blob/master/sorting/merge_sort_nr.c) - * [Multikey Quick Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/multikey_quick_sort.c) - * [Odd Even Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/odd_even_sort.c) - * [Pancake Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/pancake_sort.c) - * [Partition Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/partition_sort.c) - * [Pigeonhole Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/pigeonhole_sort.c) - * [Quick Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/quick_sort.c) - * [Radix Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/radix_sort.c) - * [Radix Sort 2](https://github.com/TheAlgorithms/C/blob/master/sorting/radix_sort_2.c) - * [Random Quick Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/random_quick_sort.c) - * [Selection Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/selection_sort.c) - * [Selection Sort Recursive](https://github.com/TheAlgorithms/C/blob/master/sorting/selection_sort_recursive.c) - * [Shaker Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/shaker_sort.c) - * [Shell Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/shell_sort.c) - * [Shell Sort2](https://github.com/TheAlgorithms/C/blob/master/sorting/shell_sort2.c) - * [Stooge Sort](https://github.com/TheAlgorithms/C/blob/master/sorting/stooge_sort.c) + * [Bead Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/bead_sort.c) + * [Binary Insertion Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/binary_insertion_sort.c) + * [Bogo Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/bogo_sort.c) + * [Bubble Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/bubble_sort.c) + * [Bubble Sort 2](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/bubble_sort_2.c) + * [Bubble Sort Recursion](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/bubble_sort_recursion.c) + * [Bucket Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/bucket_sort.c) + * [Cocktail Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/cocktail_sort.c) + * [Comb Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/comb_sort.c) + * [Counting Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/counting_sort.c) + * [Cycle Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/cycle_sort.c) + * [Gnome Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/gnome_sort.c) + * [Heap Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/heap_sort.c) + * [Heap Sort 2](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/heap_sort_2.c) + * [Insertion Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/insertion_sort.c) + * [Insertion Sort Recursive](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/insertion_sort_recursive.c) + * [Merge Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/merge_sort.c) + * [Merge Sort Nr](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/merge_sort_nr.c) + * [Multikey Quick Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/multikey_quick_sort.c) + * [Odd Even Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/odd_even_sort.c) + * [Pancake Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/pancake_sort.c) + * [Partition Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/partition_sort.c) + * [Patience Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/patience_sort.c) + * [Pigeonhole Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/pigeonhole_sort.c) + * [Quick Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/quick_sort.c) + * [Radix Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/radix_sort.c) + * [Radix Sort 2](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/radix_sort_2.c) + * [Random Quick Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/random_quick_sort.c) + * [Selection Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/selection_sort.c) + * [Selection Sort Recursive](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/selection_sort_recursive.c) + * [Shaker Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/shaker_sort.c) + * [Shell Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/shell_sort.c) + * [Shell Sort2](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/shell_sort2.c) + * [Stooge Sort](https://github.com/TheAlgorithms/C/blob/HEAD/sorting/stooge_sort.c) diff --git a/LICENSE b/LICENSE index ecc818272d..1e132df443 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (C) 2016-2022 TheAlgorithms and contributors +Copyright (C) 2016-2023 TheAlgorithms and contributors GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 diff --git a/README.md b/README.md index e0b0ad64b5..9670d2bb07 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,14 @@ [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/TheAlgorithms/C) -[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/TheAlgorithms/C.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/TheAlgorithms/C/context:cpp) -[![CodeQL CI](https://github.com/TheAlgorithms/C/actions/workflows/codeql_analysis.yml/badge.svg)](https://github.com/TheAlgorithms/C/actions/workflows/codeql_analysis.yml) +[![CodeQL CI](https://github.com/TheAlgorithms/C/actions/workflows/codeql.yml/badge.svg)](https://github.com/TheAlgorithms/C/actions/workflows/codeql_analysis.yml) [![Gitter chat](https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square)](https://gitter.im/TheAlgorithms) [![contributions welcome](https://img.shields.io/static/v1.svg?label=Contributions&message=Welcome&color=0059b3&style=flat-square)](https://github.com/TheAlgorithms/C/blob/master/CONTRIBUTING.md) ![GitHub repo size](https://img.shields.io/github/repo-size/TheAlgorithms/C?color=red&style=flat-square) [![Doxygen CI](https://github.com/TheAlgorithms/C/workflows/Doxygen%20CI/badge.svg)](https://TheAlgorithms.github.io/C) [![Awesome CI](https://github.com/TheAlgorithms/C/workflows/Awesome%20CI%20Workflow/badge.svg)](https://github.com/TheAlgorithms/C/actions?query=workflow%3A%22Awesome+CI+Workflow%22) [![Income](https://img.shields.io/liberapay/receives/TheAlgorithms.svg?logo=liberapay)](https://liberapay.com/TheAlgorithms) -[![Discord chat](https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=5865F2)](https://discord.gg/c7MnfGFGa6) +[![Discord chat](https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=5865F2)](https://the-algorithms.com/discord/) [![Donate](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/TheAlgorithms/donate) ## Overview @@ -22,7 +21,7 @@ The repository is a collection of open-source implementations of a variety of al * The repository provides implementations of various algorithms in one of the most fundamental general purpose languages - [C](https://en.wikipedia.org/wiki/C_(programming_language)). * Well documented source code with detailed explanations provide a valuable resource for educators and students alike. * Each source code is atomic using standard C library [`libc`](https://en.wikipedia.org/wiki/C_standard_library) and _no external libraries_ are required for their compilation and execution. Thus the fundamentals of the algorithms can be studied in much depth. -* Source codes are [compiled and tested](https://github.com/TheAlgorithms/C/actions?query=workflow%3A%22Awesome+CI+Workflow%22) for every commit on the latest versions of three major operating systems viz., Windows, MacOS and Ubuntu (Linux) using MSVC 16 2019, AppleClang 11.0 and GNU 7.5.0 respectively. +* Source codes are [compiled and tested](https://github.com/TheAlgorithms/C/actions?query=workflow%3A%22Awesome+CI+Workflow%22) for every commit on the latest versions of two major operating systems viz., MacOS and Ubuntu (Linux) using AppleClang 14.0.0 and GNU 11.3.0 respectively. * Strict adherence to [C11](https://en.wikipedia.org/wiki/C11_(C_standard_revision)) standard ensures portability of code to embedded systems as well like ESP32, ARM Cortex, etc. with little to no changes. * Self-checks within programs ensure correct implementations with confidence. * Modular implementations and OpenSource licensing enable the functions to be utilized conveniently in other applications. diff --git a/cipher/CMakeLists.txt b/cipher/CMakeLists.txt new file mode 100644 index 0000000000..c1d93bbc91 --- /dev/null +++ b/cipher/CMakeLists.txt @@ -0,0 +1,18 @@ +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. The RELATIVE flag makes it easier to extract an executable's name +# automatically. + +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c ) +foreach( testsourcefile ${APP_SOURCES} ) + string( REPLACE ".c" "" testname ${testsourcefile} ) # File type. Example: `.c` + add_executable( ${testname} ${testsourcefile} ) + + if(OpenMP_C_FOUND) + target_link_libraries(${testname} OpenMP::OpenMP_C) + endif() + if(MATH_LIBRARY) + target_link_libraries(${testname} ${MATH_LIBRARY}) + endif() + install(TARGETS ${testname} DESTINATION "bin/cipher") # Folder name. Do NOT include `<>` + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/cipher/affine.c b/cipher/affine.c new file mode 100644 index 0000000000..49a91cd799 --- /dev/null +++ b/cipher/affine.c @@ -0,0 +1,207 @@ +/** + * @file + * @brief An [affine cipher](https://en.wikipedia.org/wiki/Affine_cipher) is a + * letter substitution cipher that uses a linear transformation to substitute + * letters in a message. + * @details Given an alphabet of length M with characters with numeric values + * 0-(M-1), an arbitrary character x can be transformed with the expression (ax + * + b) % M into our ciphertext character. The only caveat is that a must be + * relatively prime with M in order for this transformation to be invertible, + * i.e., gcd(a, M) = 1. + * @author [Daniel Murrow](https://github.com/dsmurrow) + */ + +#include /// for assertions +#include /// for IO +#include /// for div function and div_t struct as well as malloc and free +#include /// for strlen, strcpy, and strcmp + +/** + * @brief number of characters in our alphabet (printable ASCII characters) + */ +#define ALPHABET_SIZE 95 + +/** + * @brief used to convert a printable byte (32 to 126) to an element of the + * group Z_95 (0 to 94) + */ +#define Z95_CONVERSION_CONSTANT 32 + +/** + * @brief a structure representing an affine cipher key + */ +typedef struct +{ + int a; ///< what the character is being multiplied by + int b; ///< what is being added after the multiplication with `a` +} affine_key_t; + +/** + * @brief finds the value x such that (a * x) % m = 1 + * + * @param a number we are finding the inverse for + * @param m the modulus the inversion is based on + * + * @returns the modular multiplicative inverse of `a` mod `m` + */ +int modular_multiplicative_inverse(unsigned int a, unsigned int m) +{ + int x[2] = {1, 0}; + div_t div_result; + + if (m == 0) { + return 0; + } + a %= m; + if (a == 0) { + return 0; + } + + div_result.rem = a; + + while (div_result.rem > 0) + { + div_result = div(m, a); + + m = a; + a = div_result.rem; + + // Calculate value of x for this iteration + int next = x[1] - (x[0] * div_result.quot); + + x[1] = x[0]; + x[0] = next; + } + + return x[1]; +} + +/** + * @brief Given a valid affine cipher key, this function will produce the + * inverse key. + * + * @param key They key to be inverted + * + * @returns inverse of key + */ +affine_key_t inverse_key(affine_key_t key) +{ + affine_key_t inverse; + + inverse.a = modular_multiplicative_inverse(key.a, ALPHABET_SIZE); + + // Turn negative results positive + inverse.a += ALPHABET_SIZE; + inverse.a %= ALPHABET_SIZE; + + inverse.b = -(key.b % ALPHABET_SIZE) + ALPHABET_SIZE; + + return inverse; +} + +/** + * @brief Encrypts character string `s` with key + * + * @param s string to be encrypted + * @param key affine key used for encryption + * + * @returns void + */ +void affine_encrypt(char *s, affine_key_t key) +{ + for (int i = 0; s[i] != '\0'; i++) + { + int c = (int)s[i] - Z95_CONVERSION_CONSTANT; + + c *= key.a; + c += key.b; + c %= ALPHABET_SIZE; + + s[i] = (char)(c + Z95_CONVERSION_CONSTANT); + } +} + +/** + * @brief Decrypts an affine ciphertext + * + * @param s string to be decrypted + * @param key Key used when s was encrypted + * + * @returns void + */ +void affine_decrypt(char *s, affine_key_t key) +{ + affine_key_t inverse = inverse_key(key); + + for (int i = 0; s[i] != '\0'; i++) + { + int c = (int)s[i] - Z95_CONVERSION_CONSTANT; + + c += inverse.b; + c *= inverse.a; + c %= ALPHABET_SIZE; + + s[i] = (char)(c + Z95_CONVERSION_CONSTANT); + } +} + +/** + * @brief Tests a given string + * + * @param s string to be tested + * @param a value of key.a + * @param b value of key.b + * + * @returns void + */ +void test_string(const char *s, const char *ciphertext, int a, int b) +{ + char *copy = malloc((strlen(s) + 1) * sizeof(char)); + strcpy(copy, s); + + affine_key_t key = {a, b}; + + affine_encrypt(copy, key); + assert(strcmp(copy, ciphertext) == 0); // assert that the encryption worked + + affine_decrypt(copy, key); + assert(strcmp(copy, s) == + 0); // assert that we got the same string we started with + + free(copy); +} + +/** + * @brief Test multiple strings + * + * @returns void + */ +static void tests() +{ + test_string("Hello!", "&3ddy2", 7, 11); + test_string("TheAlgorithms/C", "DNC}=jHS2zN!7;E", 67, 67); + test_string("0123456789", "840,($ {ws", 91, 88); + test_string("7W@;cdeRT9uL", "JDfa*we?z&bL", 77, 76); + test_string("~Qr%^-+++$leM", "r'qC0$sss;Ahf", 8, 90); + test_string("The quick brown fox jumps over the lazy dog", + "K7: .*6<4 =-0(1 90' 5*2/, 0):- +7: 3>%& ;08", 94, 0); + test_string( + "One-1, Two-2, Three-3, Four-4, Five-5, Six-6, Seven-7, Eight-8, " + "Nine-9, Ten-10", + "H&60>\\2*uY0q\\2*p4660E\\2XYn40x\\2XDB60L\\2VDI0 " + "\\2V6B6&0S\\2%D=p;0'\\2tD&60Z\\2*6&0>j", + 51, 18); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief main function + * + * @returns 0 upon successful program exit + */ +int main() +{ + tests(); + return 0; +} diff --git a/cipher/rot13.c b/cipher/rot13.c new file mode 100644 index 0000000000..1a6022f40e --- /dev/null +++ b/cipher/rot13.c @@ -0,0 +1,60 @@ +/** + * @file + * @brief [ROT13](https://en.wikipedia.org/wiki/ROT13) is a simple letter + * substitution cipher that replaces a letter with the 13th letter after it in + * the alphabet. + * @details ROT13 transforms a piece of text by examining its alphabetic + * characters and replacing each one with the letter 13 places further along in + * the alphabet, wrapping back to the beginning if necessary. A becomes N, B + * becomes O, and so on up to M, which becomes Z, then the sequence continues at + * the beginning of the alphabet: N becomes A, O becomes B, and so on to Z, + * which becomes M. + * @author [Jeremias Moreira Gomes](https://github.com/j3r3mias) + */ + +#include /// for IO operations +#include /// for string operations +#include /// for assert + +/** + * @brief Apply the ROT13 cipher + * @param s contains the string to be processed + */ +void rot13(char *s) { + for (int i = 0; s[i]; i++) { + if (s[i] >= 'A' && s[i] <= 'Z') { + s[i] = 'A' + ((s[i] - 'A' + 13) % 26); + } else if (s[i] >= 'a' && s[i] <= 'z') { + s[i] = 'a' + ((s[i] - 'a' + 13) % 26); + } + } +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + char test_01[] = "The more I C, the less I see."; + rot13(test_01); + assert(strcmp(test_01, "Gur zber V P, gur yrff V frr.") == 0); + + char test_02[] = "Which witch switched the Swiss wristwatches?"; + rot13(test_02); + assert(strcmp(test_02, "Juvpu jvgpu fjvgpurq gur Fjvff jevfgjngpurf?") == 0); + + char test_03[] = "Juvpu jvgpu fjvgpurq gur Fjvff jevfgjngpurf?"; + rot13(test_03); + assert(strcmp(test_03, "Which witch switched the Swiss wristwatches?") == 0); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} diff --git a/client_server/CMakeLists.txt b/client_server/CMakeLists.txt index 66a6b04392..58d0aeb87c 100644 --- a/client_server/CMakeLists.txt +++ b/client_server/CMakeLists.txt @@ -1,9 +1,12 @@ +include(CheckIncludeFile) + if(WIN32) - check_include_file(winsock2.h WINSOCK_HEADER) + CHECK_INCLUDE_FILE(winsock2.h WINSOCK_HEADER) else() - check_include_file(arpa/inet.h ARPA_HEADERS) + CHECK_INCLUDE_FILE(arpa/inet.h ARPA_HEADERS) endif() +include(CheckSymbolExists) if(ARPA_HEADERS OR WINSOCK_HEADER) # If necessary, use the RELATIVE flag, otherwise each source file may be listed # with full pathname. RELATIVE may makes it easier to extract an executable name @@ -13,16 +16,21 @@ if(ARPA_HEADERS OR WINSOCK_HEADER) # AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES) foreach( testsourcefile ${APP_SOURCES} ) # I used a simple string replace, to cut off .cpp. - string( REPLACE ".c" "" testname ${testsourcefile} ) - add_executable( ${testname} ${testsourcefile} ) - - if(OpenMP_C_FOUND) - target_link_libraries(${testname} PRIVATE OpenMP::OpenMP_C) + string(REPLACE ".c" "" testname ${testsourcefile}) + + if(NOT WIN32) + if(${testname} STREQUAL "fork" OR ${testname} STREQUAL "bool") + continue() + endif() endif() - if(MATH_LIBRARY) + add_executable(${testname} ${testsourcefile}) + + if (OpenMP_C_FOUND) + target_link_libraries(${testname} PRIVATE OpenMP::OpenMP_C) + endif () + if (MATH_LIBRARY) target_link_libraries(${testname} PRIVATE ${MATH_LIBRARY}) - endif() - + endif () # if(HAS_UNISTD) # target_compile_definitions(${testname} PRIVATE HAS_UNISTD) # endif() @@ -32,7 +40,7 @@ if(ARPA_HEADERS OR WINSOCK_HEADER) # target_compile_definitions(${testname} PRIVATE WINSOCK_HEADER) # endif() - if(WINSOCK_HEADER) + if (WINSOCK_HEADER) target_link_libraries(${testname} PRIVATE ws2_32) # link winsock library on windows endif() diff --git a/client_server/bool.h b/client_server/bool.h new file mode 100644 index 0000000000..25cc9a72df --- /dev/null +++ b/client_server/bool.h @@ -0,0 +1,55 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2007 - INRIA + * + * Copyright (C) 2012 - 2016 - Scilab Enterprises + * + * This file is hereby licensed under the terms of the GNU GPL v2.0, + * pursuant to article 5.3.4 of the CeCILL v.2.1. + * This file was originally licensed under the terms of the CeCILL v2.1, + * and continues to be available under such terms. + * For more information, see the COPYING file which you should have received + * along with this program. + * + */ +#ifndef __BOOL_H__ +#define __BOOL_H__ + +/* define boolean type */ +#ifdef BOOL +#undef BOOL +#endif + +#ifdef TRUE +#undef TRUE +#endif + +#ifdef FALSE +#undef FALSE +#endif + + +#ifndef _MSC_VER +typedef enum +{ + FALSE = 0, + TRUE = 1 +} BOOL; + +#else +/* Please notice that BOOL is defined in */ +/* BUT windef.h includes all others windows include */ +/* it is better to redefine as */ +typedef int BOOL; +#define FALSE 0 +#define TRUE 1 + +#endif +/* converts BOOL to bool */ +#define BOOLtobool(w) ((w != FALSE) ? true : false) + +/* converts bool to BOOL */ +#define booltoBOOL(w) ((w == true) ? TRUE : FALSE) + +#endif /* __BOOL_H__ */ +/*--------------------------------------------------------------------------*/ diff --git a/client_server/fork.h b/client_server/fork.h new file mode 100644 index 0000000000..3221d20454 --- /dev/null +++ b/client_server/fork.h @@ -0,0 +1,298 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) DIGITEO - 2010 - Allan CORNET + * + * Copyright (C) 2012 - 2016 - Scilab Enterprises + * + * This file is hereby licensed under the terms of the GNU GPL v2.0, + * pursuant to article 5.3.4 of the CeCILL v.2.1. + * This file was originally licensed under the terms of the CeCILL v2.1, + * and continues to be available under such terms. + * For more information, see the COPYING file which you should have received + * along with this program. + * + */ +/*--------------------------------------------------------------------------*/ +#ifndef __FORK_H__ +#define __FORK_H__ + +/* http://technet.microsoft.com/en-us/library/bb497007.aspx */ +/* http://undocumented.ntinternals.net/ */ + +#include +#include + +#include "bool.h" + +/** + * simulate fork on Windows + */ +int fork(void); + +/** + * check if symbols to simulate fork are present + * and load these symbols + */ +BOOL haveLoadedFunctionsForFork(void); + +/*--------------------------------------------------------------------------*/ +typedef LONG NTSTATUS; +/*--------------------------------------------------------------------------*/ +typedef struct _SYSTEM_HANDLE_INFORMATION +{ + ULONG ProcessId; + UCHAR ObjectTypeNumber; + UCHAR Flags; + USHORT Handle; + PVOID Object; + ACCESS_MASK GrantedAccess; +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; +/*--------------------------------------------------------------------------*/ +typedef struct _OBJECT_ATTRIBUTES +{ + ULONG Length; + HANDLE RootDirectory; + PVOID /* really PUNICODE_STRING */ ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; /* type SECURITY_DESCRIPTOR */ + PVOID SecurityQualityOfService; /* type SECURITY_QUALITY_OF_SERVICE */ +} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; +/*--------------------------------------------------------------------------*/ +typedef enum _MEMORY_INFORMATION_ +{ + MemoryBasicInformation, + MemoryWorkingSetList, + MemorySectionName, + MemoryBasicVlmInformation +} MEMORY_INFORMATION_CLASS; +/*--------------------------------------------------------------------------*/ +typedef struct _CLIENT_ID +{ + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID, *PCLIENT_ID; +/*--------------------------------------------------------------------------*/ +typedef struct _USER_STACK +{ + PVOID FixedStackBase; + PVOID FixedStackLimit; + PVOID ExpandableStackBase; + PVOID ExpandableStackLimit; + PVOID ExpandableStackBottom; +} USER_STACK, *PUSER_STACK; +/*--------------------------------------------------------------------------*/ +typedef LONG KPRIORITY; +typedef ULONG_PTR KAFFINITY; +typedef KAFFINITY *PKAFFINITY; +/*--------------------------------------------------------------------------*/ +typedef struct _THREAD_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PVOID TebBaseAddress; + CLIENT_ID ClientId; + KAFFINITY AffinityMask; + KPRIORITY Priority; + KPRIORITY BasePriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; +/*--------------------------------------------------------------------------*/ +typedef enum _SYSTEM_INFORMATION_CLASS +{ + SystemHandleInformation = 0x10 +} SYSTEM_INFORMATION_CLASS; +/*--------------------------------------------------------------------------*/ +typedef NTSTATUS(NTAPI *ZwWriteVirtualMemory_t)( + IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, + IN ULONG NumberOfBytesToWrite, OUT PULONG NumberOfBytesWritten OPTIONAL); +/*--------------------------------------------------------------------------*/ +typedef NTSTATUS(NTAPI *ZwCreateProcess_t)( + OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE InheriteFromProcessHandle, + IN BOOLEAN InheritHandles, IN HANDLE SectionHandle OPTIONAL, + IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL); +/*--------------------------------------------------------------------------*/ +typedef NTSTATUS(WINAPI *ZwQuerySystemInformation_t)( + SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, + ULONG SystemInformationLength, PULONG ReturnLength); +typedef NTSTATUS(NTAPI *ZwQueryVirtualMemory_t)( + IN HANDLE ProcessHandle, IN PVOID BaseAddress, + IN MEMORY_INFORMATION_CLASS MemoryInformationClass, + OUT PVOID MemoryInformation, IN ULONG MemoryInformationLength, + OUT PULONG ReturnLength OPTIONAL); +/*--------------------------------------------------------------------------*/ +typedef NTSTATUS(NTAPI *ZwGetContextThread_t)(IN HANDLE ThreadHandle, + OUT PCONTEXT Context); +typedef NTSTATUS(NTAPI *ZwCreateThread_t)( + OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, + OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, + IN PUSER_STACK UserStack, IN BOOLEAN CreateSuspended); +/*--------------------------------------------------------------------------*/ +typedef NTSTATUS(NTAPI *ZwResumeThread_t)(IN HANDLE ThreadHandle, + OUT PULONG SuspendCount OPTIONAL); +typedef NTSTATUS(NTAPI *ZwClose_t)(IN HANDLE ObjectHandle); +typedef NTSTATUS(NTAPI *ZwQueryInformationThread_t)( + IN HANDLE ThreadHandle, IN THREAD_INFORMATION_CLASS ThreadInformationClass, + OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, + OUT PULONG ReturnLength OPTIONAL); +/*--------------------------------------------------------------------------*/ +static ZwCreateProcess_t ZwCreateProcess = NULL; +static ZwQuerySystemInformation_t ZwQuerySystemInformation = NULL; +static ZwQueryVirtualMemory_t ZwQueryVirtualMemory = NULL; +static ZwCreateThread_t ZwCreateThread = NULL; +static ZwGetContextThread_t ZwGetContextThread = NULL; +static ZwResumeThread_t ZwResumeThread = NULL; +static ZwClose_t ZwClose = NULL; +static ZwQueryInformationThread_t ZwQueryInformationThread = NULL; +static ZwWriteVirtualMemory_t ZwWriteVirtualMemory = NULL; +/*--------------------------------------------------------------------------*/ +#define NtCurrentProcess() ((HANDLE)-1) +#define NtCurrentThread() ((HANDLE)-2) +/* we use really the Nt versions - so the following is just for completeness */ +#define ZwCurrentProcess() NtCurrentProcess() +#define ZwCurrentThread() NtCurrentThread() +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +/*--------------------------------------------------------------------------*/ +/* setjmp env for the jump back into the fork() function */ +static jmp_buf jenv; +/*--------------------------------------------------------------------------*/ +/* entry point for our child thread process - just longjmp into fork */ +static int child_entry(void) +{ + longjmp(jenv, 1); + return 0; +} +/*--------------------------------------------------------------------------*/ +static BOOL haveLoadedFunctionsForFork(void) +{ + HMODULE ntdll = GetModuleHandle("ntdll"); + if (ntdll == NULL) + { + return FALSE; + } + + if (ZwCreateProcess && ZwQuerySystemInformation && ZwQueryVirtualMemory && + ZwCreateThread && ZwGetContextThread && ZwResumeThread && + ZwQueryInformationThread && ZwWriteVirtualMemory && ZwClose) + { + return TRUE; + } + + ZwCreateProcess = + (ZwCreateProcess_t)GetProcAddress(ntdll, "ZwCreateProcess"); + ZwQuerySystemInformation = (ZwQuerySystemInformation_t)GetProcAddress( + ntdll, "ZwQuerySystemInformation"); + ZwQueryVirtualMemory = + (ZwQueryVirtualMemory_t)GetProcAddress(ntdll, "ZwQueryVirtualMemory"); + ZwCreateThread = (ZwCreateThread_t)GetProcAddress(ntdll, "ZwCreateThread"); + ZwGetContextThread = + (ZwGetContextThread_t)GetProcAddress(ntdll, "ZwGetContextThread"); + ZwResumeThread = (ZwResumeThread_t)GetProcAddress(ntdll, "ZwResumeThread"); + ZwQueryInformationThread = (ZwQueryInformationThread_t)GetProcAddress( + ntdll, "ZwQueryInformationThread"); + ZwWriteVirtualMemory = + (ZwWriteVirtualMemory_t)GetProcAddress(ntdll, "ZwWriteVirtualMemory"); + ZwClose = (ZwClose_t)GetProcAddress(ntdll, "ZwClose"); + + if (ZwCreateProcess && ZwQuerySystemInformation && ZwQueryVirtualMemory && + ZwCreateThread && ZwGetContextThread && ZwResumeThread && + ZwQueryInformationThread && ZwWriteVirtualMemory && ZwClose) + { + return TRUE; + } + else + { + ZwCreateProcess = NULL; + ZwQuerySystemInformation = NULL; + ZwQueryVirtualMemory = NULL; + ZwCreateThread = NULL; + ZwGetContextThread = NULL; + ZwResumeThread = NULL; + ZwQueryInformationThread = NULL; + ZwWriteVirtualMemory = NULL; + ZwClose = NULL; + } + return FALSE; +} +/*--------------------------------------------------------------------------*/ +int fork(void) +{ + HANDLE hProcess = 0, hThread = 0; + OBJECT_ATTRIBUTES oa = {sizeof(oa)}; + MEMORY_BASIC_INFORMATION mbi; + CLIENT_ID cid; + USER_STACK stack; + PNT_TIB tib; + THREAD_BASIC_INFORMATION tbi; + + CONTEXT context = {CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS | + CONTEXT_FLOATING_POINT}; + + if (setjmp(jenv) != 0) + { + return 0; /* return as a child */ + } + + /* check whether the entry points are initilized and get them if necessary + */ + if (!ZwCreateProcess && !haveLoadedFunctionsForFork()) + { + return -1; + } + + /* create forked process */ + ZwCreateProcess(&hProcess, PROCESS_ALL_ACCESS, &oa, NtCurrentProcess(), + TRUE, 0, 0, 0); + + /* set the Eip for the child process to our child function */ + ZwGetContextThread(NtCurrentThread(), &context); + + /* In x64 the Eip and Esp are not present, their x64 counterparts are Rip + and Rsp respectively. + */ +#if _WIN64 + context.Rip = (ULONG)child_entry; +#else + context.Eip = (ULONG)child_entry; +#endif + +#if _WIN64 + ZwQueryVirtualMemory(NtCurrentProcess(), (PVOID)context.Rsp, + MemoryBasicInformation, &mbi, sizeof mbi, 0); +#else + ZwQueryVirtualMemory(NtCurrentProcess(), (PVOID)context.Esp, + MemoryBasicInformation, &mbi, sizeof mbi, 0); +#endif + + stack.FixedStackBase = 0; + stack.FixedStackLimit = 0; + stack.ExpandableStackBase = (PCHAR)mbi.BaseAddress + mbi.RegionSize; + stack.ExpandableStackLimit = mbi.BaseAddress; + stack.ExpandableStackBottom = mbi.AllocationBase; + + /* create thread using the modified context and stack */ + ZwCreateThread(&hThread, THREAD_ALL_ACCESS, &oa, hProcess, &cid, &context, + &stack, TRUE); + + /* copy exception table */ + ZwQueryInformationThread(NtCurrentThread(), ThreadMemoryPriority, &tbi, + sizeof tbi, 0); + tib = (PNT_TIB)tbi.TebBaseAddress; + ZwQueryInformationThread(hThread, ThreadMemoryPriority, &tbi, sizeof tbi, + 0); + ZwWriteVirtualMemory(hProcess, tbi.TebBaseAddress, &tib->ExceptionList, + sizeof tib->ExceptionList, 0); + + /* start (resume really) the child */ + ZwResumeThread(hThread, 0); + + /* clean up */ + ZwClose(hThread); + ZwClose(hProcess); + + /* exit with child's pid */ + return (int)cid.UniqueProcess; +} + +#endif /* __FORK_H__ */ +/*--------------------------------------------------------------------------*/ diff --git a/client_server/remote_command_exec_udp_client.c b/client_server/remote_command_exec_udp_client.c index 8a2afa0c52..6669919f5a 100644 --- a/client_server/remote_command_exec_udp_client.c +++ b/client_server/remote_command_exec_udp_client.c @@ -14,17 +14,26 @@ * using UDP is shown using the server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define close _close +#include +#include +#include /// For the type in_addr_t and in_port_t +#else #include /// For the type in_addr_t and in_port_t -#include /// To indicate what went wrong if an error occurs #include /// For structures returned by the network database library - formatted internet addresses and port numbers #include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +#include /// To indicate what went wrong if an error occurs +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 10000 /// Define port over which communication will take place diff --git a/client_server/remote_command_exec_udp_server.c b/client_server/remote_command_exec_udp_server.c index 619c116cf2..67d623904e 100644 --- a/client_server/remote_command_exec_udp_server.c +++ b/client_server/remote_command_exec_udp_server.c @@ -14,17 +14,26 @@ * using UDP is shown using the server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define close _close +#include +#include +#include /// For the type in_addr_t and in_port_t +#else #include /// For the type in_addr_t and in_port_t -#include /// To indicate what went wrong if an error occurs #include /// For structures returned by the network database library - formatted internet addresses and port numbers #include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +#include /// To indicate what went wrong if an error occurs +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 10000 /// Define port over which communication will take place diff --git a/client_server/tcp_full_duplex_client.c b/client_server/tcp_full_duplex_client.c index 2fb2bb79eb..12836c598e 100644 --- a/client_server/tcp_full_duplex_client.c +++ b/client_server/tcp_full_duplex_client.c @@ -10,23 +10,36 @@ * instead of the server only sending and the client only receiving data, * The server and client can both send and receive data simultaneously. This is * implemented by using the `fork` function call so that in the server the child - * process can recieve data and parent process can send data, and in the client + * process can receive data and parent process can send data, and in the client * the child process can send data and the parent process can receive data. It * runs an infinite loop and can send and receive messages indefinitely until * the user exits the loop. In this way, the Full Duplex Form of communication * can be represented using the TCP server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define pid_t int +#define close _close +#include +#include +#include +#include +#include "fork.h" +#define sleep(a) Sleep(a * 1000) +#else #include /// For the type in_addr_t and in_port_t #include /// For structures returned by the network database library - formatted internet addresses and port numbers #include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 10000 /// Define port over which communication will take place @@ -141,6 +154,7 @@ int main() */ pid_t pid; pid = fork(); + if (pid == 0) /// Value of 0 is for child process { while (1) diff --git a/client_server/tcp_full_duplex_server.c b/client_server/tcp_full_duplex_server.c index 29a7ca302e..aab2ea8dfa 100644 --- a/client_server/tcp_full_duplex_server.c +++ b/client_server/tcp_full_duplex_server.c @@ -3,30 +3,43 @@ * @author [NVombat](https://github.com/NVombat) * @brief Server-side implementation of [TCP Full Duplex * Communication](http://www.tcpipguide.com/free/t_SimplexFullDuplexandHalfDuplexOperation.htm) - * @see tcp_full_duplex_server.c + * @see tcp_full_duplex_client.c * * @details * The algorithm is based on the simple TCP client and server model. However, * instead of the server only sending and the client only receiving data, * The server and client can both send and receive data simultaneously. This is * implemented by using the `fork` function call so that in the server the child - * process can recieve data and parent process can send data, and in the client + * process can receive data and parent process can send data, and in the client * the child process can send data and the parent process can receive data. It * runs an infinite loop and can send and receive messages indefinitely until * the user exits the loop. In this way, the Full Duplex Form of communication * can be represented using the TCP server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define pid_t int +#define close _close +#include +#include +#include +#include +#include "fork.h" +#define sleep(a) Sleep(a * 1000) +#else #include /// For the type in_addr_t and in_port_t #include /// For structures returned by the network database library - formatted internet addresses and port numbers #include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 10000 /// Define port over which communication will take place @@ -162,7 +175,15 @@ int main() * place simultaneously this represents FULL DUPLEX COMMUNICATION */ pid_t pid; + + #ifdef _WIN32 + #ifdef FORK_WINDOWS + pid = fork(); + #endif + #else pid = fork(); + #endif + if (pid == 0) /// Value of 0 is for child process { while (1) diff --git a/client_server/tcp_half_duplex_client.c b/client_server/tcp_half_duplex_client.c index 51cc98b9a3..0d77dedc17 100644 --- a/client_server/tcp_half_duplex_client.c +++ b/client_server/tcp_half_duplex_client.c @@ -15,15 +15,24 @@ * can be represented using the TCP server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define close _close +#include +#include +#include +#else #include /// For structures returned by the network database library - formatted internet addresses and port numbers -#include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +// #include /// For in_addr and sockaddr_in structures +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 8100 /// Define port over which communication will take place diff --git a/client_server/tcp_half_duplex_server.c b/client_server/tcp_half_duplex_server.c index 9a1a7c1d05..266d9896bc 100644 --- a/client_server/tcp_half_duplex_server.c +++ b/client_server/tcp_half_duplex_server.c @@ -15,15 +15,24 @@ * can be represented using the TCP server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define close _close +#include +#include +#include +#else #include /// For structures returned by the network database library - formatted internet addresses and port numbers -#include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +// #include /// For in_addr and sockaddr_in structures +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 8100 /// Define port over which communication will take place diff --git a/conversions/binary_to_decimal.c b/conversions/binary_to_decimal.c index 352d07c160..41721e5d9c 100644 --- a/conversions/binary_to_decimal.c +++ b/conversions/binary_to_decimal.c @@ -1,24 +1,68 @@ /** - * Modified 07/12/2017, Kyler Smith + * @brief Converts a number from [Binary to Decimal](https://en.wikipedia.org/wiki/Binary-coded_decimal). + * @details * - */ + * Binary to decimal conversion is a process to convert a number + * having a binary representation to its equivalent decimal representation. + * + * The base of both number systems is different. + * Binary number system is base 2 number system while decimal number system is base 10 number system. + * The numbers used in binary number system are 0 and 1 while decimal number system has numbers from 0 to 9. + * The conversion of binary number to decimal number is done by multiplying + * each digit of the binary number, starting from the rightmost digit, with the power of 2 and adding the result. + * + * @author [Anup Kumar Pawar](https://github.com/AnupKumarPanwar) + * @author [David Leal](https://github.com/Panquesito7) +*/ -#include +#include /// for IO operations +#include /// for assert +#include /// for pow +#include /// for uint64_t -int main() -{ - int remainder, number = 0, decimal_number = 0, temp = 1; - printf("\n Enter any binary number= "); - scanf("%d", &number); +/** + * @brief Converts the given binary number + * to its equivalent decimal number/value. + * @param number The binary number to be converted + * @returns The decimal equivalent of the binary number +*/ +int convert_to_decimal(uint64_t number) { + int decimal_number = 0, i = 0; - // Iterate over the number until the end. - while (number > 0) - { - remainder = number % 10; + while (number > 0) { + decimal_number += (number % 10) * pow(2, i); number = number / 10; - decimal_number += remainder * temp; - temp = temp * 2; // used as power of 2 + i++; } - printf("%d\n", decimal_number); + return decimal_number; +} + +/** + * @brief Self-test implementations + * @returns void +*/ +static void tests() { + assert(convert_to_decimal(111) == 7); + assert(convert_to_decimal(101) == 5); + assert(convert_to_decimal(1010) == 10); + assert(convert_to_decimal(1101) == 13); + assert(convert_to_decimal(100001) == 33); + assert(convert_to_decimal(10101001) == 169); + assert(convert_to_decimal(111010) == 58); + assert(convert_to_decimal(100000000) == 256); + assert(convert_to_decimal(10000000000) == 1024); + assert(convert_to_decimal(101110111) == 375); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief Main function + * @returns 0 on exit +*/ +int main() +{ + tests(); // run self-test implementations + return 0; } diff --git a/conversions/celsius_to_fahrenheit.c b/conversions/celsius_to_fahrenheit.c new file mode 100644 index 0000000000..3c1bda9e09 --- /dev/null +++ b/conversions/celsius_to_fahrenheit.c @@ -0,0 +1,74 @@ +/** + * @file + * @brief Conversion of temperature in degrees from [Celsius](https://en.wikipedia.org/wiki/Celsius) + * to [Fahrenheit](https://en.wikipedia.org/wiki/Fahrenheit). + * + * @author [Focusucof](https://github.com/Focusucof) + */ + +#include /// for assert +#include /// for IO operations + +/** + * @brief Convert celsius to Fahrenheit + * @param celsius Temperature in degrees celsius double + * @returns Double of temperature in degrees Fahrenheit + */ + double celcius_to_fahrenheit(double celsius) { + return (celsius * 9.0 / 5.0) + 32.0; + } + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + // 1st test + double input = 0.0; + double expected = 32.0; + + double output = celcius_to_fahrenheit(input); + + // 1st test + printf("TEST 1\n"); + printf("Input: %f\n", input); + printf("Expected Output: %f\n", expected); + printf("Output: %f\n", output); + assert(output == expected); + printf("== TEST PASSED ==\n\n"); + + // 2nd test + input = 100.0; + expected = 212.0; + + output = celcius_to_fahrenheit(input); + + printf("TEST 2\n"); + printf("Input: %f\n", input); + printf("Expected Output: %f\n", expected); + printf("Output: %f\n", output); + assert(output == expected); + printf("== TEST PASSED ==\n\n"); + + // 3rd test + input = 22.5; + expected = 72.5; + + output = celcius_to_fahrenheit(input); + + printf("TEST 3\n"); + printf("Input: %f\n", input); + printf("Expected Output: %f\n", expected); + printf("Output: %f\n", output); + assert(output == expected); + printf("== TEST PASSED ==\n\n"); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} diff --git a/conversions/roman_numerals_to_decimal.c b/conversions/roman_numerals_to_decimal.c new file mode 100644 index 0000000000..7cf8c9c78c --- /dev/null +++ b/conversions/roman_numerals_to_decimal.c @@ -0,0 +1,121 @@ +/** + * @file + * @brief Conversion of [roman numerals](https://en.wikipedia.org/wiki/Roman_numerals) to decimal + * @details Roman numerals are an ancient Roman numeral system consisting of the symbols I, V, X, L, C, D, and M + * + * @author [Focusucof](https://github.com/Focusucof) + */ + +#include /// for assert +#include /// for IO operations +#include /// for strlen() + +/** + * @brief Convert roman numeral symbol to a decimal value helper function + * @param symbol Roman numeral char + * @returns Integer of decimal value for given symbol + */ +int symbol(char symbol) { + int value = 0; + switch(symbol) { + case 'I': + value = 1; + break; + case 'V': + value = 5; + break; + case 'X': + value = 10; + break; + case 'L': + value = 50; + break; + case 'C': + value = 100; + break; + case 'D': + value = 500; + break; + case 'M': + value = 1000; + break; + } + return value; +} + +/** + * @brief Converts roman numerals into a decimal number + * @param input Input roman numeral as a C-string + * @returns The converted number in decimal form + */ +int roman_to_decimal(char input[]) { + int result = 0; // result in decimal + + for(int i = 0; i < strlen(input); i++) { + if(strlen(input) > i + 1) { + if(symbol(input[i]) >= symbol(input[i + 1])) { + result += symbol(input[i]); // add value to sum + } else { + result += symbol(input[i + 1]) - symbol(input[i]); // if the current symbol is smaller than the next (ex. IV), subtract it from the next symbol + i++; // skip over an extra symbol + } + } else { + result += symbol(input[i]); // add value to sum + } + } + return result; +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + // 1st test + char input[] = "MCMIV"; + int expected = 1904; + + int output = roman_to_decimal(input); + + printf("TEST 1\n"); + printf("Input: %s\n", input); + printf("Expected Output: %d\n", expected); + printf("Output: %d\n", output); + assert(output == expected); + printf("== TEST PASSED ==\n\n"); + + // 2nd test + char input2[] = "MMMDCCXXIV"; + expected = 3724; + + output = roman_to_decimal(input2); + + printf("TEST 2\n"); + printf("Input: %s\n", input2); + printf("Expected Output: %d\n", expected); + printf("Output: %d\n", output); + assert(output == expected); + printf("== TEST PASSED ==\n\n"); + + // 3rd test + char input3[] = "III"; + expected = 3; + + output = roman_to_decimal(input3); + + printf("TEST 3\n"); + printf("Input: %s\n", input3); + printf("Expected Output: %d\n", expected); + printf("Output: %d\n", output); + assert(output == expected); + printf("== TEST PASSED ==\n\n"); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} diff --git a/data_structures/array/carray.c b/data_structures/array/carray.c index 58840f41b6..7b812eb7ac 100644 --- a/data_structures/array/carray.c +++ b/data_structures/array/carray.c @@ -128,6 +128,7 @@ int switchValuesCArray(CArray *array, int position1, int position2) int temp = array->array[position1]; array->array[position1] = array->array[position2]; array->array[position2] = temp; + return SUCCESS; } return INVALID_POSITION; } diff --git a/data_structures/binary_trees/avl_tree.c b/data_structures/binary_trees/avl_tree.c index 67d24ae0c6..604638735d 100644 --- a/data_structures/binary_trees/avl_tree.c +++ b/data_structures/binary_trees/avl_tree.c @@ -169,12 +169,12 @@ avlNode *delete (avlNode *node, int queryNum) delete (node->right, queryNum); /*Recursive deletion in R subtree*/ else { - /*Single or No Child*/ + /*Single or No Children*/ if ((node->left == NULL) || (node->right == NULL)) { avlNode *temp = node->left ? node->left : node->right; - /* No Child*/ + /* No Children*/ if (temp == NULL) { temp = node; @@ -187,7 +187,7 @@ avlNode *delete (avlNode *node, int queryNum) } else { - /*Two Child*/ + /*Two Children*/ /*Get the smallest key in the R subtree*/ avlNode *temp = minNode(node->right); diff --git a/data_structures/binary_trees/words_alphabetical.c b/data_structures/binary_trees/words_alphabetical.c index 1b0c42e551..46508f48c2 100644 --- a/data_structures/binary_trees/words_alphabetical.c +++ b/data_structures/binary_trees/words_alphabetical.c @@ -9,7 +9,7 @@ * where words are separated by a space, newline, or underscore. * This program prints (writes or outputs) to another file (`wordcount.txt`), * the individual words contained in 'file.txt' with their frequencies (number - * of occurences) each on a newline and in alphabetical order. This program uses + * of occurrences) each on a newline and in alphabetical order. This program uses * the binary tree data structure to accomplish this task. * @author [Randy Kwalar](https://github.com/RandyKdev) */ @@ -28,7 +28,7 @@ struct Node { char *word; ///< the word (value) of the node - uint64_t frequency; ///< number of occurences of the word + uint64_t frequency; ///< number of occurrences of the word struct Node *left; ///< pointer to the left child node struct Node *right; ///< pointer to the right child node }; diff --git a/data_structures/dynamic_array/dynamic_array.c b/data_structures/dynamic_array/dynamic_array.c index 7ecf359ccb..19631cb1d1 100644 --- a/data_structures/dynamic_array/dynamic_array.c +++ b/data_structures/dynamic_array/dynamic_array.c @@ -18,7 +18,6 @@ void *add(dynamic_array_t *da, const void *value) { void **newItems = realloc(da->items, (da->capacity <<= 1) * sizeof(void **)); - free(da->items); da->items = newItems; } @@ -79,4 +78,4 @@ void *retrive_copy_of_value(const void *value) memcpy(value_copy, value, sizeof(void *)); return value_copy; -} \ No newline at end of file +} diff --git a/data_structures/graphs/kruskal.c b/data_structures/graphs/kruskal.c index 49d1c54c9f..0f72c6b52f 100644 --- a/data_structures/graphs/kruskal.c +++ b/data_structures/graphs/kruskal.c @@ -27,11 +27,11 @@ struct Graph // Creates a graph with V vertices and E edges struct Graph *createGraph(int V, int E) { - struct Graph *graph = new Graph(); + struct Graph* graph = (struct Graph*)(malloc(sizeof(struct Graph))); graph->V = V; graph->E = E; - graph->edge = new Edge[E]; + graph->edge = (struct Edge*)malloc(sizeof(struct Edge) * E); return graph; } diff --git a/data_structures/linked_list/circular_doubly_linked_list.c b/data_structures/linked_list/circular_doubly_linked_list.c new file mode 100644 index 0000000000..d2302e06b9 --- /dev/null +++ b/data_structures/linked_list/circular_doubly_linked_list.c @@ -0,0 +1,304 @@ +/** + * @file + * + * @details + * Circular [Doubly Linked + * List](https://en.wikipedia.org/wiki/Doubly_linked_list) combines the + * properties of a doubly linked list and a circular linked list in which two + * consecutive elements are linked or connected by the previous. Next, the + * pointer and the last node point to the first node via the next pointer, and + * the first node points to the last node via the previous pointer. + * + * In this implementation, functions to insert at the head, insert at the last + * index, delete the first node, delete the last node, display list, and get + * list size functions are coded. + * + * @author [Sahil Kandhare](https://github.com/SahilK-027) + * + */ + +#include /// to verify assumptions made by the program and print a diagnostic message if this assumption is false. +#include /// to provide a set of integer types with universally consistent definitions that are operating system-independent +#include /// for IO operations +#include /// for including functions involving memory allocation such as `malloc` + +/** + * @brief Circular Doubly linked list struct + */ +typedef struct node +{ + struct node *prev, *next; ///< List pointers + uint64_t value; ///< Data stored on each node +} ListNode; + +/** + * @brief Create a list node + * @param data the data that the node initialises with + * @return ListNode* pointer to the newly created list node + */ +ListNode *create_node(uint64_t data) +{ + ListNode *new_list = (ListNode *)malloc(sizeof(ListNode)); + new_list->value = data; + new_list->next = new_list; + new_list->prev = new_list; + return new_list; +} + +/** + * @brief Insert a node at start of list + * @param head start pointer of list + * @param data the data that the node initialises with + * @return ListNode* pointer to the newly created list node + * inserted at the head + */ +ListNode *insert_at_head(ListNode *head, uint64_t data) +{ + if (head == NULL) + { + head = create_node(data); + return head; + } + else + { + ListNode *temp; + ListNode *new_node = create_node(data); + temp = head->prev; + new_node->next = head; + head->prev = new_node; + new_node->prev = temp; + temp->next = new_node; + head = new_node; + return head; + } +} + +/** + * @brief Insert a node at end of list + * + * @param head start pointer of list + * @param data the data that the node initialises with + * @return ListNode* pointer to the newly added list node that was + * inserted at the head of list. + */ +ListNode *insert_at_tail(ListNode *head, uint64_t data) +{ + if (head == NULL) + { + head = create_node(data); + return head; + } + else + { + ListNode *temp1, *temp2; + ListNode *new_node = create_node(data); + temp1 = head; + temp2 = head->prev; + new_node->prev = temp2; + new_node->next = temp1; + temp1->prev = new_node; + temp2->next = new_node; + return head; + } +} + +/** + * @brief Function for deletion of the first node in list + * + * @param head start pointer of list + * @return ListNode* pointer to the list node after deleting first node + */ +ListNode *delete_from_head(ListNode *head) +{ + if (head == NULL) + { + printf("The list is empty\n"); + return head; + } + ListNode *temp1, *temp2; + temp1 = head; + temp2 = temp1->prev; + if (temp1 == temp2) + { + free(temp2); + head = NULL; + return head; + } + temp2->next = temp1->next; + (temp1->next)->prev = temp2; + head = temp1->next; + free(temp1); + return head; +} + +/** + * @brief Function for deletion of the last node in list + * + * @param head start pointer of list + * @return ListNode* pointer to the list node after deleting first node + */ +ListNode *delete_from_tail(ListNode *head) +{ + if (head == NULL) + { + printf("The list is empty\n"); + return head; + } + + ListNode *temp1, *temp2; + temp1 = head; + temp2 = temp1->prev; + if (temp1 == temp2) + { + free(temp2); + head = NULL; + return head; + } + (temp2->prev)->next = temp1; + temp1->prev = temp2->prev; + free(temp2); + return head; +} + +/** + * @brief The function that will return current size of list + * + * @param head start pointer of list + * @return int size of list + */ +int getsize(ListNode *head) +{ + if (!head) + { + return 0; + } + int size = 1; + ListNode *temp = head->next; + while (temp != head) + { + temp = temp->next; + size++; + } + return size; +} + +/** + * @brief Display list function + * @param head start pointer of list + * @returns void + */ + +void display_list(ListNode *head) +{ + printf("\nContents of your linked list: "); + ListNode *temp; + temp = head; + if (head != NULL) + { + while (temp->next != head) + { + printf("%" PRIu64 " <-> ", temp->value); + temp = temp->next; + } + if (temp->next == head) + { + printf("%" PRIu64, temp->value); + } + } + else + { + printf("The list is empty"); + } + printf("\n"); +} + +/** + * @brief access the list by index + * @param list pointer to the target list + * @param index access location + * @returns the value at the specified index, + * wrapping around if the index is larger than the size of the target + * list + */ +uint64_t get(ListNode *list, const int index) +{ + if (list == NULL || index < 0) + { + exit(EXIT_FAILURE); + } + ListNode *temp = list; + for (int i = 0; i < index; ++i) + { + temp = temp->next; + } + return temp->value; +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() +{ + ListNode *testList = NULL; + unsigned int array[] = {2, 3, 4, 5, 6}; + + assert(getsize(testList) == 0); + + printf("Testing inserting elements:\n"); + for (int i = 0; i < 5; ++i) + { + display_list(testList); + testList = insert_at_head(testList, array[i]); + assert(testList->value == array[i]); + assert(getsize(testList) == i + 1); + } + + printf("\nTesting removing elements:\n"); + for (int i = 4; i > -1; --i) + { + display_list(testList); + assert(testList->value == array[i]); + testList = delete_from_head(testList); + assert(getsize(testList) == i); + } + + printf("\nTesting inserting at tail:\n"); + for (int i = 0; i < 5; ++i) + { + display_list(testList); + testList = insert_at_tail(testList, array[i]); + assert(get(testList, i) == array[i]); + assert(getsize(testList) == i + 1); + } + + printf("\nTesting removing from tail:\n"); + for (int i = 4; i > -1; --i) + { + display_list(testList); + testList = delete_from_tail(testList); + assert(getsize(testList) == i); + // If list is not empty, assert that accessing the just removed element + // will wrap around to the list head + if (testList != NULL) + { + assert(get(testList, i) == testList->value); + } + else + { + // If the list is empty, assert that the elements were removed after + // the correct number of iterations + assert(i == 0); + } + } +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() +{ + test(); // run self-test implementations + return 0; +} diff --git a/data_structures/linked_list/circular_linked_list.c b/data_structures/linked_list/circular_linked_list.c index 7297217a25..6d923ae705 100644 --- a/data_structures/linked_list/circular_linked_list.c +++ b/data_structures/linked_list/circular_linked_list.c @@ -16,7 +16,7 @@ struct node *first=NULL ; struct node *last=NULL ; /* first and last are global variables and need not be passed to any function. Any changes made to variables first and last by any of the functions in the program will be reflected in the entire program */ -/* This function is responsible for creating the Circularly Linked List right from the BEGINING. */ +/* This function is responsible for creating the Circularly Linked List right from the BEGINNING. */ void create() { int i , n ; diff --git a/data_structures/linked_list/singly_link_list_deletion.c b/data_structures/linked_list/singly_link_list_deletion.c index 2df425ce01..f94aef54ba 100644 --- a/data_structures/linked_list/singly_link_list_deletion.c +++ b/data_structures/linked_list/singly_link_list_deletion.c @@ -4,39 +4,64 @@ when passed with a key of the node. */ #include +#include +#include struct node { int info; struct node *link; }; struct node *start = NULL; -/////////////////////////////////////////////////////////// -struct node *createnode() // function to create node +////////////////////////////////////////////////////////////////// +struct node *createnode() // function to create node { struct node *t; t = (struct node *)malloc(sizeof(struct node)); return (t); } -//////////////////////////////////////////////////////// -void insert() // function to insert at first location +////////////////////////////////////////////////////////////////// +int insert(int pos, int d) { - struct node *p; - p = createnode(); - printf("\nenter the number to insert"); - scanf("%d", &p->info); - p->link = NULL; - if (start == NULL) + struct node *new; + new = createnode(); + new->info = d; + if (pos == 1) { - start = p; + new->link = NULL; + if (start == NULL) + { + start = new; + } + else + { + new->link = start; + start = new; + } } else { - p->link = start; - start = p; + struct node *pre = start; + for (int i = 2; i < pos; i++) + { + if (pre == NULL) + { + break; + } + pre = pre->link; + } + if(pre==NULL) + { + printf("Position not found!"); + return 0; + } + new->link = pre->link; + pre->link = new; } -} -/////////////////////////////////////////////////////////// -void deletion() // function to delete from first position + return 0; + } + +/////////////////////////////////////////////////////////////////// +int deletion(int pos) // function to delete from any position { struct node *t; if (start == NULL) @@ -45,14 +70,34 @@ void deletion() // function to delete from first position } else { - struct node *p; - p = start; - start = start->link; - free(p); + if (pos == 1) + { + struct node *p; + p = start; + start = start->link; + free(p); + } + else + { + struct node *prev = start; + for (int i = 2; i < pos; i++) + { + if (prev == NULL) + { + printf("Position not found!"); + return 0; + } + prev = prev->link; + } + struct node *n = prev->link; // n points to required node to be deleted + prev->link = n->link; + free(n); + } } + return 0; } -/////////////////////////////////////////////////////// -void viewlist() // function to display values +/////////////////////////////////////////////////////////////////// +void viewlist() // function to display values { struct node *p; if (start == NULL) @@ -69,32 +114,64 @@ void viewlist() // function to display values } } } -////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////// +static void test() +{ + insert(1, 39); + assert(start->info == 39); + insert(2, 10); + insert(3, 11); + deletion(1); + assert(start->info != 39); + printf("Self-tests successfully passed!\n"); +} +////////////////////////////////////////////////////////////////// int main() { - int n; - while (1) + int n = 0, pos = 0, p = 0, num = 0, c = 0; + printf("\n1.self test mode"); + printf("\n2.interactive mode"); + printf("\nenter your choice:"); + scanf("%d", &c); + if (c == 1) + { + test(); + } + else if (c == 2) { - printf("\n1.add value at first location"); - printf("\n2.delete value from first location"); - printf("\n3.view value"); - printf("\nenter your choice"); - scanf("%d", &n); - switch (n) + while (1) { - case 1: - insert(); - break; - case 2: - deletion(); - break; - case 3: - viewlist(); - break; - default: - printf("\ninvalid choice"); + printf("\n1.add value at the given location"); + printf("\n2.delete value at the given location"); + printf("\n3.view list"); + printf("\nenter your choice :"); + scanf("%d", &n); + switch (n) + { + case 1: + printf("enter the position where the element is to be added :"); + scanf("%d", &p); + printf("enter the element is to be added :"); + scanf("%d", &num); + insert(p, num); + break; + case 2: + printf("enter the position where the element is to be deleted :"); + scanf("%d", &pos); + deletion(pos); + break; + case 3: + viewlist(); + break; + default: + printf("\ninvalid choice"); + } } } - return (0); + else + { + printf("Invalid choice"); + } + return 0; } diff --git a/data_structures/linked_list/stack_using_linked_lists.c b/data_structures/linked_list/stack_using_linked_lists.c index bf16ec2fab..a3c473a72c 100644 --- a/data_structures/linked_list/stack_using_linked_lists.c +++ b/data_structures/linked_list/stack_using_linked_lists.c @@ -48,7 +48,7 @@ void push(struct node *p) temp->link = top; top = temp; - printf("Inserted succesfully.\n"); + printf("Inserted successfully.\n"); } void pop(struct node *p) { diff --git a/data_structures/list/list.c b/data_structures/list/list.c index 9731acf0a8..762ffdfaad 100644 --- a/data_structures/list/list.c +++ b/data_structures/list/list.c @@ -30,13 +30,13 @@ int List_length(L list) { int n; for (n = 0; list; list = list->next) n++; - return n; + return n - 1; } /* Convert list to array */ void **List_toArray(L list) { - int i, n = List_length(list); + int i, n = List_length(list) + 1; void **array = (void **)malloc((n + 1) * sizeof(*array)); for (i = 0; i < n; i++) diff --git a/data_structures/stack/dynamic_stack.c b/data_structures/stack/dynamic_stack.c new file mode 100644 index 0000000000..482896eabd --- /dev/null +++ b/data_structures/stack/dynamic_stack.c @@ -0,0 +1,250 @@ +/** + * @file + * + * @brief + * Dynamic [Stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)), + * just like Dynamic Array, is a stack data structure whose the length or + * capacity (maximum number of elements that can be stored) increases or + * decreases in real time based on the operations (like insertion or deletion) + * performed on it. + * + * In this implementation, functions such as PUSH, POP, PEEK, show_capacity, + * isempty, and stack_size are coded to implement dynamic stack. + * + * @author [SahilK-027](https://github.com/SahilK-027) + * + */ +#include /// to verify assumptions made by the program and print a diagnostic message if this assumption is false. +#include /// to provide a set of integer types with universally consistent definitions that are operating system-independent +#include /// for IO operations +#include /// for including functions involving memory allocation such as `malloc` +/** + * @brief DArrayStack Structure of stack. + */ +typedef struct DArrayStack +{ + int capacity, top; ///< to store capacity and top of the stack + int *arrPtr; ///< array pointer +} DArrayStack; + +/** + * @brief Create a Stack object + * + * @param cap Capacity of stack + * @return DArrayStack* Newly created stack object pointer + */ +DArrayStack *create_stack(int cap) +{ + DArrayStack *ptr; + ptr = (DArrayStack *)malloc(sizeof(DArrayStack)); + ptr->capacity = cap; + ptr->top = -1; + ptr->arrPtr = (int *)malloc(sizeof(int) * cap); + printf("\nStack of capacity %d is successfully created.\n", ptr->capacity); + return (ptr); +} + +/** + * @brief As this is stack implementation using dynamic array this function will + * expand the size of the stack by twice as soon as the stack is full. + * + * @param ptr Stack pointer + * @param cap Capacity of stack + * @return DArrayStack*: Modified stack + */ +DArrayStack *double_array(DArrayStack *ptr, int cap) +{ + int newCap = 2 * cap; + int *temp; + temp = (int *)malloc(sizeof(int) * newCap); + for (int i = 0; i < (ptr->top) + 1; i++) + { + temp[i] = ptr->arrPtr[i]; + } + free(ptr->arrPtr); + ptr->arrPtr = temp; + ptr->capacity = newCap; + return ptr; +} + +/** + * @brief As this is stack implementation using dynamic array this function will + * shrink the size of stack by twice as soon as the stack's capacity and size + * has significant difference. + * + * @param ptr Stack pointer + * @param cap Capacity of stack + * @return DArrayStack*: Modified stack + */ +DArrayStack *shrink_array(DArrayStack *ptr, int cap) +{ + int newCap = cap / 2; + int *temp; + temp = (int *)malloc(sizeof(int) * newCap); + for (int i = 0; i < (ptr->top) + 1; i++) + { + temp[i] = ptr->arrPtr[i]; + } + free(ptr->arrPtr); + ptr->arrPtr = temp; + ptr->capacity = newCap; + return ptr; +} + +/** + * @brief The push function pushes the element onto the stack. + * + * @param ptr Stack pointer + * @param data Value to be pushed onto stack + * @return int Position of top pointer + */ +int push(DArrayStack *ptr, int data) +{ + if (ptr->top == (ptr->capacity) - 1) + { + ptr = double_array(ptr, ptr->capacity); + ptr->top++; + ptr->arrPtr[ptr->top] = data; + } + else + { + ptr->top++; + ptr->arrPtr[ptr->top] = data; + } + printf("Successfully pushed : %d\n", data); + return ptr->top; +} + +/** + * @brief The pop function to pop an element from the stack. + * + * @param ptr Stack pointer + * @return int Popped value + */ +int pop(DArrayStack *ptr) +{ + if (ptr->top == -1) + { + printf("Stack is empty UNDERFLOW \n"); + return -1; + } + int ele = ptr->arrPtr[ptr->top]; + ptr->arrPtr[ptr->top] = 0; + ptr->top = (ptr->top - 1); + if ((ptr->capacity) % 2 == 0) + { + if (ptr->top <= (ptr->capacity / 2) - 1) + { + ptr = shrink_array(ptr, ptr->capacity); + } + } + printf("Successfully popped: %d\n", ele); + return ele; +} + +/** + * @brief To retrieve or fetch the first element of the Stack or the element + * present at the top of the Stack. + * + * @param ptr Stack pointer + * @return int Top of the stack + */ +int peek(DArrayStack *ptr) +{ + if (ptr->top == -1) + { + printf("Stack is empty UNDERFLOW \n"); + return -1; + } + return ptr->arrPtr[ptr->top]; +} + +/** + * @brief To display the current capacity of the stack. + * + * @param ptr Stack pointer + * @return int Current capacity of the stack + */ +int show_capacity(DArrayStack *ptr) { return ptr->capacity; } + +/** + * @brief The function is used to check whether the stack is empty or not and + * return true or false accordingly. + * + * @param ptr Stack pointer + * @return int returns 1 -> true OR returns 0 -> false + */ +int isempty(DArrayStack *ptr) +{ + if (ptr->top == -1) + { + return 1; + } + return 0; +} + +/** + * @brief Used to get the size of the Stack or the number of elements present in + * the Stack. + * + * @param ptr Stack pointer + * @return int size of stack + */ +int stack_size(DArrayStack *ptr) { return ptr->top + 1; } + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() +{ + DArrayStack *NewStack; + int capacity = 1; + NewStack = create_stack(capacity); + uint64_t arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + + printf("\nTesting Empty stack: "); + assert(stack_size(NewStack) == 0); + assert(isempty(NewStack) == 1); + printf("Size of an empty stack is %d\n", stack_size(NewStack)); + + printf("\nTesting PUSH operation:\n"); + for (int i = 0; i < 12; ++i) + { + int topVal = push(NewStack, arr[i]); + printf("Size: %d, Capacity: %d\n\n", stack_size(NewStack), + show_capacity(NewStack)); + assert(topVal == i); + assert(peek(NewStack) == arr[i]); + assert(stack_size(NewStack) == i + 1); + assert(isempty(NewStack) == 0); + } + + printf("\nTesting POP operation:\n"); + for (int i = 11; i > -1; --i) + { + peek(NewStack); + assert(peek(NewStack) == arr[i]); + int ele = pop(NewStack); + assert(ele == arr[i]); + assert(stack_size(NewStack) == i); + } + + printf("\nTesting Empty stack size: "); + assert(stack_size(NewStack) == 0); + assert(isempty(NewStack) == 1); + printf("Size of an empty stack is %d\n", stack_size(NewStack)); + + printf("\nTesting POP operation on empty stack: "); + assert(pop(NewStack) == -1); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() +{ + test(); // run self-test implementations + return 0; +} diff --git a/data_structures/stack/main.c b/data_structures/stack/main.c index ebdabc4670..d3f20c0a93 100644 --- a/data_structures/stack/main.c +++ b/data_structures/stack/main.c @@ -1,11 +1,11 @@ // program for stack using array - #include void push(); void pop(); void peek(); void update(); +void display(); int a[100], top = -1; @@ -14,12 +14,13 @@ int main() int x; while (1) { - printf("\n0.exit"); - printf("\n1.push"); - printf("\n2.pop"); - printf("\n3.peek"); - printf("\n4.update"); - printf("\nenter your choice? "); + printf("\n0 or CTRL-C to Exit "); + printf("\n1. Push"); + printf("\n2. Pop"); + printf("\n3. Peek"); + printf("\n4. Update"); + printf("\n5. Display"); + printf("\nEnter your choice? \n"); scanf("%d", &x); switch (x) { @@ -37,8 +38,11 @@ int main() case 4: update(); break; + case 5: + display(); + break; default: - printf("\ninvalid choice"); + printf("\nInvalid choice,\nPlease try again.\n"); } } return (0); @@ -48,7 +52,7 @@ int main() void push() { int n = 0; - printf("\nenter the value to insert? "); + printf("\nEnter the value to be inserted: "); scanf("%d", &n); top += 1; a[top] = n; @@ -59,14 +63,14 @@ void pop() { if (top == -1) { - printf("\nstack is empty"); + printf("\nStack is empty"); } else { int item; item = a[top]; top -= 1; - printf("\npoped item is %d ", item); + printf("\nPoped item is %d ", item); } } @@ -74,25 +78,40 @@ void pop() void peek() { if (top >= 0) - printf("\n the top element is %d", a[top]); + printf("\nThe top element is %d", a[top]); else - printf("\nstack is empty"); + printf("\nStack is empty"); } // function to update the element of stack void update() { int i, n; - printf("\nenter the position to update? "); + printf("\nEnter the position to update? "); scanf("%d", &i); - printf("\nenter the item to insert? "); + printf("\nEnter the item to insert? "); scanf("%d", &n); if (top - i + 1 < 0) { - printf("\nunderflow condition"); + printf("\nUnderflow condition "); } else { a[top - i + 1] = n; } -} \ No newline at end of file +} +// function to view entire stack +void display() +{ + if (top == -1) + { + printf("\nStack is empty"); + } + else + { + for (int i = top; i >= 0; i--) + { + printf("%d\n", a[i]); + } + } +} diff --git a/data_structures/vector.c b/data_structures/vector.c new file mode 100644 index 0000000000..ed3b930e36 --- /dev/null +++ b/data_structures/vector.c @@ -0,0 +1,168 @@ +/** + * @file + * @brief This is a vector implemenation in C. A vector is an expandable array. + * @details This vector implementation in C comes with some wrapper functions that lets the user work with data without having to worrying about memory. + */ + +#include /// for IO operations +#include /// for malloc() and free() +#include /// for testing using assert() + +/** This is the struct that defines the vector. */ +typedef struct { + int len; ///< contains the length of the vector + int current; ///< holds the current item + int* contents; ///< the internal array itself +} Vector; + +/** + * This function initilaizes the vector and gives it a size of 1 + * and initializes the first index to 0. + * @params Vector* (a pointer to the Vector struct) + * @params int (the actual data to be passed to the vector) + * @returns none + */ +void init(Vector* vec, int val) { + vec->contents = (int*)malloc(sizeof(int)); + vec->contents[0] = val; + vec->current = 0; + vec->len = 1; +} + +/** + * This function clears the heap memory allocated by the Vector. + * @params Vector* (a pointer to the Vector struct) + * @returns: none + */ +void delete(Vector* vec) { + free(vec->contents); +} + +/** + * This function clears the contents of the Vector. + * @params Vector* (a pointer to the Vector struct) + * @returns: none + */ +void clear(Vector* vec) { + delete(vec); + init(vec, 0); +} + +/** + * This function returns the length the Vector. + * @params Vector* (a pointer to the Vector struct) + * @returns: int + */ +int len(Vector* vec) { + return vec->len; +} + +/** + * This function pushes a value to the end of the Vector. + * @params Vector* (a pointer to the Vector struct) + * @params int (the value to be pushed) + * @returns: none + */ +void push(Vector* vec, int val) { + vec->contents = realloc(vec->contents, (sizeof(int) * (vec->len + 1))); + vec->contents[vec->len] = val; + vec->len++; +} + +/** + * This function get the item at the specified index of the Vector. + * @params Vector* (a pointer to the Vector struct) + * @params int (the index to get value from) + * @returns: int + */ +int get(Vector* vec, int index) { + if(index < vec->len) { + return vec->contents[index]; + } + return -1; +} + +/** + * This function sets an item at the specified index of the Vector. + * @params Vector* (a pointer to the Vector struct) + * @params int (the index to set value at) + * @returns: none + */ +void set(Vector* vec, int index, int val) { + if(index < vec->len) { + vec->contents[index] = val; + } +} + +/** + * This function gets the next item from the Vector each time it's called. + * @params Vector* (a pointer to the Vector struct) + * @returns: int + */ +int next(Vector* vec) { + if(vec->current == vec->len) { + vec->current = 0; + } + int current_val = vec->contents[vec->current]; + vec->current++; + return current_val; +} + +/** + * This function returns the pointer to the begining of the Vector. + * @params Vector* (a pointer to the Vector struct) + * @returns: void* + */ +void* begin(Vector* vec) { + return (void*)vec->contents; +} + +/** + * This function prints the entire Vector as a list. + * @params Vector* (a pointer to the Vector struct) + * @returns: none + */ +void print(Vector* vec) { + int size = vec->len; + printf("[ "); + for(int count = 0; count < size; count++) { + printf("%d ", vec->contents[count]); + } + printf("]\n"); +} + +/** + * This function tests the functions used to work with Vectors. + * @returns: none + */ +static void test() { + Vector vec; + init(&vec, 10); + assert(get(&vec, 0) == 10); + push(&vec, 20); + assert(get(&vec, 1) == 20); + set(&vec, 0, 11); + assert(get(&vec, 0) == 11); + assert(next(&vec) == 11); + set(&vec, 1, 22); + assert(get(&vec, 1) == 22); + assert(len(&vec) == 2); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); + + Vector vec; + init(&vec, 10); + push(&vec, 20); + print(&vec); + set(&vec, 0, 11); + set(&vec, 1, 22); + print(&vec); + printf("Length: %d\n", len(&vec)); + return 0; +} diff --git a/developer_tools/min_printf.h b/developer_tools/min_printf.h index 69dec7a61b..395331c18f 100644 --- a/developer_tools/min_printf.h +++ b/developer_tools/min_printf.h @@ -19,7 +19,11 @@ #define MIN_PRINTF_H #include /// for `malloc` and `free` functions -#include /// for `write` function +#ifdef _WIN32 + #include /// for `write` function +#else + #include /// for `write` function +#endif #include /// for `va_start` and `va_arg` functions #define INT_MAX_LENGTH 10 /// used as standard length of string to store integers @@ -159,7 +163,7 @@ void print_int_value(int n, int width, int precision) while (n > 0) { *s++ = n % 10 + '0'; // Converts last digit of number to character and store it in p - ++size; // Increment size variable as one more digit is occured + ++size; // Increment size variable as one more digit is occurred n /= 10; // Removes the last digit from the number n as we have successfully stored it in p } *s = '\0'; diff --git a/dynamic_programming/CMakeLists.txt b/dynamic_programming/CMakeLists.txt new file mode 100644 index 0000000000..a65bbb7da6 --- /dev/null +++ b/dynamic_programming/CMakeLists.txt @@ -0,0 +1,18 @@ +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. The RELATIVE flag makes it easier to extract an executable's name +# automatically. + +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c ) +foreach( testsourcefile ${APP_SOURCES} ) + string( REPLACE ".c" "" testname ${testsourcefile} ) # File type. Example: `.c` + add_executable( ${testname} ${testsourcefile} ) + + if(OpenMP_C_FOUND) + target_link_libraries(${testname} OpenMP::OpenMP_C) + endif() + if(MATH_LIBRARY) + target_link_libraries(${testname} ${MATH_LIBRARY}) + endif() + install(TARGETS ${testname} DESTINATION "bin/dynamic_programming") # Folder name. Do NOT include `<>` + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/dynamic_programming/lcs.c b/dynamic_programming/lcs.c new file mode 100644 index 0000000000..bf360b7321 --- /dev/null +++ b/dynamic_programming/lcs.c @@ -0,0 +1,165 @@ +/** + * @file + * @brief [Longest Common + * Subsequence](https://en.wikipedia.org/wiki/Longest_common_subsequence_problem) + * algorithm + * @details + * From Wikipedia: The longest common subsequence (LCS) problem is the problem + * of finding the longest subsequence common to all sequences in a set of + * sequences (often just two sequences). + * @author [Kurtz](https://github.com/itskurtz) + */ + +#include /* for io operations */ +#include /* for memory management & exit */ +#include /* for string manipulation & ooperations */ +#include /* for asserts */ + +enum {LEFT, UP, DIAG}; + +/** + * @brief Computes LCS between s1 and s2 using a dynamic-programming approach + * @param s1 first null-terminated string + * @param s2 second null-terminated string + * @param l1 length of s1 + * @param l2 length of s2 + * @param L matrix of size l1 x l2 + * @param B matrix of size l1 x l2 + * @returns void + */ +void lcslen(const char *s1, const char *s2, int l1, int l2, int **L, int **B) { + /* B is the directions matrix + L is the LCS matrix */ + int i, j; + + /* loop over the simbols in my sequences + save the directions according to the LCS */ + for (i = 1; i <= l1; ++i) { + for (j = 1; j <= l2; ++j) { + if (s1[i-1] == s2[j-1]) { + L[i][j] = 1 + L[i-1][j-1]; + B[i][j] = DIAG; + } + else if (L[i-1][j] < L[i][j-1]) { + L[i][j] = L[i][j-1]; + B[i][j] = LEFT; + } + else { + L[i][j] = L[i-1][j]; + B[i][j] = UP; + } + } + } +} + +/** + * @brief Builds the LCS according to B using a traceback approach + * @param s1 first null-terminated string + * @param l1 length of s1 + * @param l2 length of s2 + * @param L matrix of size l1 x l2 + * @param B matrix of size l1 x l2 + * @returns lcs longest common subsequence + */ +char *lcsbuild(const char *s1, int l1, int l2, int **L, int **B) { + int i, j, lcsl; + char *lcs; + lcsl = L[l1][l2]; + + /* my lcs is at least the empty symbol */ + lcs = (char *)calloc(lcsl+1, sizeof(char)); /* null-terminated \0 */ + if (!lcs) { + perror("calloc: "); + return NULL; + } + + i = l1, j = l2; + while (i > 0 && j > 0) { + /* walk the matrix backwards */ + if (B[i][j] == DIAG) { + lcs[--lcsl] = s1[i-1]; + i = i - 1; + j = j - 1; + } + else if (B[i][j] == LEFT) + { + j = j - 1; + } + else + { + i = i - 1; + } + } + return lcs; +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + /* https://en.wikipedia.org/wiki/Subsequence#Applications */ + int **L, **B, j, l1, l2; + + char *s1 = "ACGGTGTCGTGCTATGCTGATGCTGACTTATATGCTA"; + char *s2 = "CGTTCGGCTATCGTACGTTCTATTCTATGATTTCTAA"; + char *lcs; + + l1 = strlen(s1); + l2 = strlen(s2); + + L = (int **)calloc(l1+1, sizeof(int *)); + B = (int **)calloc(l1+1, sizeof(int *)); + + if (!L) { + perror("calloc: "); + exit(1); + } + if (!B) { + perror("calloc: "); + exit(1); + } + for (j = 0; j <= l1; j++) { + L[j] = (int *)calloc(l2+1, sizeof(int)); + if (!L[j]) { + perror("calloc: "); + exit(1); + } + B[j] = (int *)calloc(l2+1, sizeof(int)); + if (!L[j]) { + perror("calloc: "); + exit(1); + } + } + + lcslen(s1, s2, l1, l2, L, B); + lcs = lcsbuild(s1, l1, l2, L, B); + + assert(L[l1][l2] == 27); + assert(strcmp(lcs, "CGTTCGGCTATGCTTCTACTTATTCTA") == 0); + + printf("S1: %s\tS2: %s\n", s1, s2); + printf("LCS len:%3d\n", L[l1][l2]); + printf("LCS: %s\n", lcs); + + free(lcs); + for (j = 0; j <= l1; j++) + { + free(L[j]), free(B[j]); + } + free(L); + free(B); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief Main function + * @param argc commandline argument count (ignored) + * @param argv commandline array of arguments (ignored) + * @returns 0 on exit + */ +int main(int argc, char *argv[]) { + test(); // run self-test implementations + return 0; +} diff --git a/dynamic_programming/matrix_chain_order.c b/dynamic_programming/matrix_chain_order.c new file mode 100644 index 0000000000..7b48f4ca5e --- /dev/null +++ b/dynamic_programming/matrix_chain_order.c @@ -0,0 +1,119 @@ +/** + * @file + * @brief [Matrix Chain + * Order](https://en.wikipedia.org/wiki/Matrix_chain_multiplication) + * @details + * From Wikipedia: Matrix chain multiplication (or the matrix chain ordering + * problem) is an optimization problem concerning the most efficient way to + * multiply a given sequence of matrices. The problem is not actually to perform + * the multiplications, but merely to decide the sequence of the matrix + * multiplications involved. + * @author [CascadingCascade](https://github.com/CascadingCascade) + */ + +#include /// for assert +#include /// for INT_MAX macro +#include /// for IO operations +#include /// for malloc() and free() + +/** + * @brief Finds the optimal sequence using the classic O(n^3) algorithm. + * @param l length of cost array + * @param p costs of each matrix + * @param s location to store results + * @returns number of operations + */ +int matrixChainOrder(int l, const int *p, int *s) +{ + // mat stores the cost for a chain that starts at i and ends on j (inclusive + // on both ends) + int **mat = malloc(l * sizeof(int *)); + for (int i = 0; i < l; ++i) + { + mat[i] = malloc(l * sizeof(int)); + } + + for (int i = 0; i < l; ++i) + { + mat[i][i] = 0; + } + // cl denotes the difference between start / end indices, cl + 1 would be + // chain length. + for (int cl = 1; cl < l; ++cl) + { + for (int i = 0; i < l - cl; ++i) + { + int j = i + cl; + mat[i][j] = INT_MAX; + for (int div = i; div < j; ++div) + { + int q = mat[i][div] + mat[div + 1][j] + p[i] * p[div] * p[j]; + if (q < mat[i][j]) + { + mat[i][j] = q; + s[i * l + j] = div; + } + } + } + } + int result = mat[0][l - 1]; + + // Free dynamically allocated memory + for (int i = 0; i < l; ++i) + { + free(mat[i]); + } + free(mat); + + return result; +} + +/** + * @brief Recursively prints the solution + * @param l dimension of the solutions array + * @param s solutions + * @param i starting index + * @param j ending index + * @returns void + */ +void printSolution(int l, int *s, int i, int j) +{ + if (i == j) + { + printf("A%d", i); + return; + } + putchar('('); + printSolution(l, s, i, s[i * l + j]); + printSolution(l, s, s[i * l + j] + 1, j); + putchar(')'); +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() +{ + int sizes[] = {35, 15, 5, 10, 20, 25}; + int len = 6; + int *sol = malloc(len * len * sizeof(int)); + int r = matrixChainOrder(len, sizes, sol); + assert(r == 18625); + printf("Result : %d\n", r); + printf("Optimal ordering : "); + printSolution(len, sol, 0, 5); + free(sol); + + printf("\n"); +} + +/** + * @brief Main function + * @returns 0 + */ +int main() +{ + test(); // run self-test implementations + return 0; +} diff --git a/exercism/word_count/word_count.c b/exercism/word_count/word_count.c index 206a16dc6c..ac2ceea479 100644 --- a/exercism/word_count/word_count.c +++ b/exercism/word_count/word_count.c @@ -70,7 +70,7 @@ int word_count(const char *input_text, word_count_word_t *words) words->count = 0; - /* make sure none error is occured */ + /* make sure none error is occurred */ if (loop) { /* collects the last word up to the \0-character. and counts it.*/ @@ -88,4 +88,4 @@ int word_count(const char *input_text, word_count_word_t *words) /* returns the number of words or an error code */ return count_all; -} \ No newline at end of file +} diff --git a/games/hangman.c b/games/hangman.c new file mode 100644 index 0000000000..5d2697df75 --- /dev/null +++ b/games/hangman.c @@ -0,0 +1,291 @@ +/** + * @file + * @brief C implementation of [Hangman Game](https://en.wikipedia.org/wiki/Hangman_(game)) + * @details + * Simple, readable version of hangman. + * Changed graphic to duck instead of traditional stick figure (same number of guesses). + * @author [AtlantaEmrys2002](https://github.com/AtlantaEmrys2002) +*/ + +#include /// for main() - tolower() +#include /// for main(), new_word(), new_guess(), won() - I/O operations +#include /// for all functions - exit(), rand() and file functions +#include /// for main() - for string operations strlen, strchr, strcpy +#include /// for new_game() - used with srand() for declaring new game instance + +/* + * @brief game_instance structure that holds current state of game + */ +struct game_instance{ + + char current_word[30]; ///< word to be guessed by player + char hidden[30]; ///< hidden version of word that is displayed to player + int size; ///< size of word + int incorrect; ///< number of incorrect guesses + char guesses[25]; ///< previous guesses + int guesses_size; ///< size of guesses array + +}; + +// function prototypes +struct game_instance new_game(void); // creates a new game +int new_guess(char, const char guesses[], int size); // checks if player has already played letter +int in_word(char, const char word[], unsigned int size); // checks if letter is in word +void picture(int score); // outputs image of duck (instead of hang man) +void won(const char word[], int score); // checks if player has won or lost + +/** + * @brief Main Function + * @returns 0 on exit + */ +int main() { + + struct game_instance game = new_game(); // new game created + char guess; // current letter guessed by player + + // main loop - asks player for guesses + while ((strchr(game.hidden, '_') != NULL) && game.incorrect <= 12) { + do { + printf("\n****************************\n"); + printf("Your word: "); + + for (int i = 0; i < game.size; i++) { + printf("%c ", game.hidden[i]); + } + + if (game.guesses_size > 0) { + printf("\nSo far, you have guessed: "); + for (int i = 0; i < game.guesses_size; i++) { + printf("%c ", game.guesses[i]); + } + } + + printf("\nYou have %d guesses left.", (12 - game.incorrect)); + printf("\nPlease enter a letter: "); + scanf(" %c", &guess); + guess = tolower(guess); + + } while (new_guess(guess, game.guesses, game.guesses_size) != -1); + + game.guesses[game.guesses_size] = guess; // adds new letter to guesses array + game.guesses_size++; // updates size of guesses array + + if (in_word(guess, game.current_word, game.size) == 1) { + printf("That letter is in the word!"); + for (int i = 0; i < game.size; i++) { + if ((game.current_word[i]) == guess) { + game.hidden[i] = guess; + } + } + } else { + printf("That letter is not in the word.\n"); + (game.incorrect)++; + } + picture(game.incorrect); + } + + won(game.current_word, game.incorrect); + return 0; +} + +/** + * @brief checks if letter has been guessed before + * @param new_guess letter that has been guessed by player + * @param guesses array of player's previous guesses + * @param size size of guesses[] array + * @returns 1 if letter has been guessed before + * @returns -1 if letter has not been guessed before + */ +int new_guess(char new_guess, const char guesses[], int size) { + + for (int j = 0; j < size; j++) { + if (guesses[j] == new_guess) { + printf("\nYou have already guessed that letter."); + return 1; + } + } + + return -1; +} + +/** + * @brief checks if letter is in current word + * @param letter letter guessed by player + * @param word current word + * @param size length of word + * @returns 1 if letter is in word + * @returns -1 if letter is not in word + */ +int in_word(char letter, const char word[], unsigned int size) { + + for (int i = 0; i < size; i++) { + if ((word[i]) == letter) { + return 1; + } + } + + return -1; +} + +/** + * @brief creates a new game - generates a random word and stores in global variable current_word + * @returns current_game - a new game instance containing randomly selected word, its length and hidden version of word + */ +struct game_instance new_game() { + + char word[30]; // used throughout function + + FILE *fptr; + fptr = fopen("games/words.txt", "r"); + + if (fptr == NULL){ + fprintf(stderr, "File not found.\n"); + exit(EXIT_FAILURE); + } + + // counts number of words in file - assumes each word on new line + int line_number = 0; + while (fgets(word, 30, fptr) != NULL) { + line_number++; + } + + rewind(fptr); + + // generates random number + int random_num; + srand(time(NULL)); + random_num = rand() % line_number; + + // selects randomly generated word + int s = 0; + while (s <= random_num){ + fgets(word, 30, fptr); + s++; + } + + // formats string correctly + if (strchr(word, '\n') != NULL){ + word[strlen(word) - 1] = '\0'; + } + + fclose(fptr); + + // creates new game instance + struct game_instance current_game; + strcpy(current_game.current_word, word); + current_game.size = strlen(word); + for (int i = 0; i < (strlen(word)); i++) { + current_game.hidden[i] = '_'; + } + current_game.incorrect = 0; + current_game.guesses_size = 0; + + return current_game; +} + +/** + * @brief checks if player has won or lost + * @param word the word player has attempted to guess + * @param score how many incorrect guesses player has made + * @returns void + */ +void won(const char word[], int score) { + if (score > 12) { + printf("\nYou lost! The word was: %s.\n", word); + } + else { + printf("\nYou won! You had %d guesses left.\n", (12 - score)); + } +} + +/* + * @brief gradually draws duck as player gets letters incorrect + * @param score how many incorrect guesses player has made + * @returns void + */ +void picture(int score) { + + switch(score) { + + case 12: + printf("\n _\n" + " __( ' )> \n" + " \\_ < _ ) "); + break; + + case 11: + printf("\n _\n" + " __( ' )\n" + " \\_ < _ ) "); + break; + + case 10: + printf("\n _\n" + " __( )\n" + " \\_ < _ ) "); + break; + + case 9: + printf("\n \n" + " __( )\n" + " \\_ < _ ) "); + break; + + case 8: + printf("\n \n" + " __( \n" + " \\_ < _ ) "); + break; + + case 7: + printf("\n \n" + " __ \n" + " \\_ < _ ) "); + break; + + case 6: + printf("\n \n" + " _ \n" + " \\_ < _ ) "); + break; + + case 5: + printf("\n \n" + " _ \n" + " _ < _ ) "); + break; + + case 4: + printf("\n \n" + " \n" + " _ < _ ) "); + break; + + case 3: + printf("\n \n" + " \n" + " < _ ) "); + break; + + case 2: + printf("\n \n" + " \n" + " _ ) "); + break; + + case 1: + printf("\n \n" + " \n" + " ) "); + break; + + case 0: + break; + + default: + printf("\n _\n" + " __( ' )> QUACK!\n" + " \\_ < _ ) "); + break; + } +} diff --git a/games/naval_battle.c b/games/naval_battle.c index 6e02762cdf..ec7f540c6e 100644 --- a/games/naval_battle.c +++ b/games/naval_battle.c @@ -885,7 +885,7 @@ int main() if (plays % 2 != 0) { printMessageScore(pts1, pts2); - printMessage("Player's turn 1"); + printMessage("Player 1's turn"); printsTray(Player2, 1); scanf("%d %c", &line, &column); @@ -911,7 +911,7 @@ int main() else { printMessageScore(pts1, pts2); - printMessage("Player's turn 1"); + printMessage("Player 2's turn"); printsTray(Player1, 1); scanf("%d %c", &line, &column); diff --git a/games/tic_tac_toe.c b/games/tic_tac_toe.c index 07b7bd689f..fbaf0e22be 100644 --- a/games/tic_tac_toe.c +++ b/games/tic_tac_toe.c @@ -283,7 +283,7 @@ void place() int e = rand() % 9; - if (e >= 0 && e <= 8) + if (e >= 0) { if (game_table[e] != 'x' && game_table[e] != 'o') { diff --git a/games/words.txt b/games/words.txt new file mode 100644 index 0000000000..0db94bf699 --- /dev/null +++ b/games/words.txt @@ -0,0 +1,8 @@ +dog +cat +tree +flower +table +programming +language +testing \ No newline at end of file diff --git a/graphics/CMakeLists.txt b/graphics/CMakeLists.txt index 046160b60f..89fc65659b 100644 --- a/graphics/CMakeLists.txt +++ b/graphics/CMakeLists.txt @@ -6,9 +6,9 @@ if(OpenGL_FOUND) include(ExternalProject) ExternalProject_Add ( FREEGLUT-PRJ - URL https://sourceforge.net/projects/freeglut/files/freeglut/3.2.1/freeglut-3.2.1.tar.gz + URL https://github.com/FreeGLUTProject/freeglut/releases/download/v3.2.1/freeglut-3.2.1.tar.gz URL_MD5 cd5c670c1086358598a6d4a9d166949d - CMAKE_GENERATOR ${CMAKE_GENERATOR} --config Release + CMAKE_GENERATOR ${CMAKE_GENERATOR} CMAKE_GENERATOR_TOOLSET ${CMAKE_GENERATOR_TOOLSET} CMAKE_GENERATOR_PLATFORM ${CMAKE_GENERATOR_PLATFORM} CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release diff --git a/graphics/spirograph.c b/graphics/spirograph.c index 2a4aebc15f..2615bf7d5b 100644 --- a/graphics/spirograph.c +++ b/graphics/spirograph.c @@ -131,7 +131,7 @@ static inline void glutBitmapString(void *font, char *string) * * @param x array containing absicca of points (must be pre-allocated) * @param y array containing ordinates of points (must be pre-allocated) - * @param N number of points in the the arrays + * @param N number of points in the arrays */ void display_graph(const double *x, const double *y, size_t N, double l, double k) diff --git a/hash/README.md b/hash/README.md index 20e201edf8..90942636cf 100644 --- a/hash/README.md +++ b/hash/README.md @@ -5,3 +5,4 @@ * xor8 (8 bit) * adler_32 (32 bit) * crc32 (32 bit) +* BLAKE2b diff --git a/hash/hash_blake2b.c b/hash/hash_blake2b.c new file mode 100644 index 0000000000..3c7b75781b --- /dev/null +++ b/hash/hash_blake2b.c @@ -0,0 +1,551 @@ +/** + * @addtogroup hash Hash algorithms + * @{ + * @file + * @author [Daniel Murrow](https://github.com/dsmurrow) + * @brief [Blake2b cryptographic hash + * function](https://www.rfc-editor.org/rfc/rfc7693) + * + * The Blake2b cryptographic hash function provides + * hashes for data that are secure enough to be used in + * cryptographic applications. It is designed to perform + * optimally on 64-bit platforms. The algorithm can output + * digests between 1 and 64 bytes long, for messages up to + * 128 bits in length. Keyed hashing is also supported for + * keys up to 64 bytes in length. + */ +#include /// for asserts +#include /// for fixed-width integer types e.g. uint64_t and uint8_t +#include /// for IO +#include /// for malloc, calloc, and free. As well as size_t + +/* Warning suppressed is in blake2b() function, more + * details are over there */ +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wshift-count-overflow" +#elif _MSC_VER +#pragma warning(disable : 4293) +#endif + +/** + * @brief the size of a data block in bytes + */ +#define bb 128 + +/** + * @brief max key length for BLAKE2b + */ +#define KK_MAX 64 + +/** + * @brief max length of BLAKE2b digest in bytes + */ +#define NN_MAX 64 + +/** + * @brief ceiling division macro without floats + * + * @param a dividend + * @param b divisor + */ +#define CEIL(a, b) (((a) / (b)) + ((a) % (b) != 0)) + +/** + * @brief returns minimum value + */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +/** + * @brief returns maximum value + */ +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +/** + * @brief macro to rotate 64-bit ints to the right + * Ripped from RFC 7693 + */ +#define ROTR64(n, offset) (((n) >> (offset)) ^ ((n) << (64 - (offset)))) + +/** + * @brief zero-value initializer for u128 type + */ +#define U128_ZERO \ + { \ + 0, 0 \ + } + +/** 128-bit number represented as two uint64's */ +typedef uint64_t u128[2]; + +/** Padded input block containing bb bytes */ +typedef uint64_t block_t[bb / sizeof(uint64_t)]; + +static const uint8_t R1 = 32; ///< Rotation constant 1 for mixing function G +static const uint8_t R2 = 24; ///< Rotation constant 2 for mixing function G +static const uint8_t R3 = 16; ///< Rotation constant 3 for mixing function G +static const uint8_t R4 = 63; ///< Rotation constant 4 for mixing function G + +static const uint64_t blake2b_iv[8] = { + 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, 0x3C6EF372FE94F82B, + 0xA54FF53A5F1D36F1, 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, + 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179}; ///< BLAKE2b Initialization vector + ///< blake2b_iv[i] = floor(2**64 * + ///< frac(sqrt(prime(i+1)))), + ///< where prime(i) is the i:th + ///< prime number + +static const uint8_t blake2b_sigma[12][16] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, + {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, + {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, + {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, + {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, + {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, + {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, + {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, + {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, + 3}}; ///< word schedule permutations for each round of the algorithm + +/** + * @brief put value of n into dest + * + * @param dest 128-bit number to get copied from n + * @param n value put into dest + * + * @returns void + */ +static inline void u128_fill(u128 dest, size_t n) +{ + dest[0] = n & UINT64_MAX; + + if (sizeof(n) > 8) + { + /* The C standard does not specify a maximum length for size_t, + * although most machines implement it to be the same length as + * uint64_t. On machines where size_t is 8 bytes long this will issue a + * compiler warning, which is why it is suppressed. But on a machine + * where size_t is greater than 8 bytes, this will work as normal. */ + dest[1] = n >> 64; + } + else + { + dest[1] = 0; + } +} + +/** + * @brief increment an 128-bit number by a given amount + * + * @param dest the value being incremented + * @param n what dest is being increased by + * + * @returns void + */ +static inline void u128_increment(u128 dest, uint64_t n) +{ + /* Check for overflow */ + if (UINT64_MAX - dest[0] <= n) + { + dest[1]++; + } + + dest[0] += n; +} + +/** + * @brief blake2b mixing function G + * + * Shuffles values in block v depending on + * provided indeces a, b, c, and d. x and y + * are also mixed into the block. + * + * @param v array of words to be mixed + * @param a first index + * @param b second index + * @param c third index + * @param d fourth index + * @param x first word being mixed into v + * @param y second word being mixed into y + * + * @returns void + */ +static void G(block_t v, uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint64_t x, + uint64_t y) +{ + v[a] += v[b] + x; + v[d] = ROTR64(v[d] ^ v[a], R1); + v[c] += v[d]; + v[b] = ROTR64(v[b] ^ v[c], R2); + v[a] += v[b] + y; + v[d] = ROTR64(v[d] ^ v[a], R3); + v[c] += v[d]; + v[b] = ROTR64(v[b] ^ v[c], R4); +} + +/** + * @brief compression function F + * + * Securely mixes the values in block m into + * the state vector h. Value at v[14] is also + * inverted if this is the final block to be + * compressed. + * + * @param h the state vector + * @param m message vector to be compressed into h + * @param t 128-bit offset counter + * @param f flag to indicate whether this is the final block + * + * @returns void + */ +static void F(uint64_t h[8], block_t m, u128 t, int f) +{ + int i; + block_t v; + + /* v[0..7] := h[0..7] */ + for (i = 0; i < 8; i++) + { + v[i] = h[i]; + } + /* v[8..15] := IV[0..7] */ + for (; i < 16; i++) + { + v[i] = blake2b_iv[i - 8]; + } + + v[12] ^= t[0]; /* v[12] ^ (t mod 2**w) */ + v[13] ^= t[1]; /* v[13] ^ (t >> w) */ + + if (f) + { + v[14] = ~v[14]; + } + + for (i = 0; i < 12; i++) + { + const uint8_t *s = blake2b_sigma[i]; + + G(v, 0, 4, 8, 12, m[s[0]], m[s[1]]); + G(v, 1, 5, 9, 13, m[s[2]], m[s[3]]); + G(v, 2, 6, 10, 14, m[s[4]], m[s[5]]); + G(v, 3, 7, 11, 15, m[s[6]], m[s[7]]); + + G(v, 0, 5, 10, 15, m[s[8]], m[s[9]]); + G(v, 1, 6, 11, 12, m[s[10]], m[s[11]]); + G(v, 2, 7, 8, 13, m[s[12]], m[s[13]]); + G(v, 3, 4, 9, 14, m[s[14]], m[s[15]]); + } + + for (i = 0; i < 8; i++) + { + h[i] ^= v[i] ^ v[i + 8]; + } +} + +/** + * @brief driver function to perform the hashing as described in specification + * + * pseudocode: (credit to authors of RFC 7693 listed above) + * FUNCTION BLAKE2( d[0..dd-1], ll, kk, nn ) + * | + * | h[0..7] := IV[0..7] // Initialization Vector. + * | + * | // Parameter block p[0] + * | h[0] := h[0] ^ 0x01010000 ^ (kk << 8) ^ nn + * | + * | // Process padded key and data blocks + * | IF dd > 1 THEN + * | | FOR i = 0 TO dd - 2 DO + * | | | h := F( h, d[i], (i + 1) * bb, FALSE ) + * | | END FOR. + * | END IF. + * | + * | // Final block. + * | IF kk = 0 THEN + * | | h := F( h, d[dd - 1], ll, TRUE ) + * | ELSE + * | | h := F( h, d[dd - 1], ll + bb, TRUE ) + * | END IF. + * | + * | RETURN first "nn" bytes from little-endian word array h[]. + * | + * END FUNCTION. + * + * @param dest destination of hashing digest + * @param d message blocks + * @param dd length of d + * @param ll 128-bit length of message + * @param kk length of secret key + * @param nn length of hash digest + * + * @returns 0 upon successful hash + */ +static int BLAKE2B(uint8_t *dest, block_t *d, size_t dd, u128 ll, uint8_t kk, + uint8_t nn) +{ + uint8_t bytes[8]; + uint64_t i, j; + uint64_t h[8]; + u128 t = U128_ZERO; + + /* h[0..7] = IV[0..7] */ + for (i = 0; i < 8; i++) + { + h[i] = blake2b_iv[i]; + } + + h[0] ^= 0x01010000 ^ (kk << 8) ^ nn; + + if (dd > 1) + { + for (i = 0; i < dd - 1; i++) + { + u128_increment(t, bb); + F(h, d[i], t, 0); + } + } + + if (kk != 0) + { + u128_increment(ll, bb); + } + F(h, d[dd - 1], ll, 1); + + /* copy bytes from h to destination buffer */ + for (i = 0; i < nn; i++) + { + if (i % sizeof(uint64_t) == 0) + { + /* copy values from uint64 to 8 u8's */ + for (j = 0; j < sizeof(uint64_t); j++) + { + uint16_t offset = 8 * j; + uint64_t mask = 0xFF; + mask <<= offset; + + bytes[j] = (h[i / 8] & (mask)) >> offset; + } + } + + dest[i] = bytes[i % 8]; + } + + return 0; +} + +/** + * @brief blake2b hash function + * + * This is the front-end function that sets up the argument for BLAKE2B(). + * + * @param message the message to be hashed + * @param len length of message (0 <= len < 2**128) (depends on sizeof(size_t) + * for this implementation) + * @param key optional secret key + * @param kk length of optional secret key (0 <= kk <= 64) + * @param nn length of output digest (1 <= nn < 64) + * + * @returns NULL if heap memory couldn't be allocated. Otherwise heap allocated + * memory nn bytes large + */ +uint8_t *blake2b(const uint8_t *message, size_t len, const uint8_t *key, + uint8_t kk, uint8_t nn) +{ + uint8_t *dest = NULL; + uint64_t long_hold; + size_t dd, has_key, i; + size_t block_index, word_in_block; + u128 ll; + block_t *blocks; + + if (message == NULL) + { + len = 0; + } + if (key == NULL) + { + kk = 0; + } + + kk = MIN(kk, KK_MAX); + nn = MIN(nn, NN_MAX); + + dd = MAX(CEIL(kk, bb) + CEIL(len, bb), 1); + + blocks = calloc(dd, sizeof(block_t)); + if (blocks == NULL) + { + return NULL; + } + + dest = malloc(nn * sizeof(uint8_t)); + if (dest == NULL) + { + free(blocks); + return NULL; + } + + /* If there is a secret key it occupies the first block */ + for (i = 0; i < kk; i++) + { + long_hold = key[i]; + long_hold <<= 8 * (i % 8); + + word_in_block = (i % bb) / 8; + /* block_index will always be 0 because kk <= 64 and bb = 128*/ + blocks[0][word_in_block] |= long_hold; + } + + has_key = kk > 0 ? 1 : 0; + + for (i = 0; i < len; i++) + { + /* long_hold exists because the bit-shifting will overflow if we don't + * store the value */ + long_hold = message[i]; + long_hold <<= 8 * (i % 8); + + block_index = has_key + (i / bb); + word_in_block = (i % bb) / 8; + + blocks[block_index][word_in_block] |= long_hold; + } + + u128_fill(ll, len); + + BLAKE2B(dest, blocks, dd, ll, kk, nn); + + free(blocks); + + return dest; +} + +/** @} */ + +/** + * @brief Self-test implementations + * @returns void + */ +static void assert_bytes(const uint8_t *expected, const uint8_t *actual, + uint8_t len) +{ + uint8_t i; + + assert(expected != NULL); + assert(actual != NULL); + assert(len > 0); + + for (i = 0; i < len; i++) + { + assert(expected[i] == actual[i]); + } +} + +/** + * @brief testing function + * + * @returns void + */ +static void test() +{ + uint8_t *digest = NULL; + + /* "abc" example straight out of RFC-7693 */ + uint8_t abc[3] = {'a', 'b', 'c'}; + uint8_t abc_answer[64] = { + 0xBA, 0x80, 0xA5, 0x3F, 0x98, 0x1C, 0x4D, 0x0D, 0x6A, 0x27, 0x97, + 0xB6, 0x9F, 0x12, 0xF6, 0xE9, 0x4C, 0x21, 0x2F, 0x14, 0x68, 0x5A, + 0xC4, 0xB7, 0x4B, 0x12, 0xBB, 0x6F, 0xDB, 0xFF, 0xA2, 0xD1, 0x7D, + 0x87, 0xC5, 0x39, 0x2A, 0xAB, 0x79, 0x2D, 0xC2, 0x52, 0xD5, 0xDE, + 0x45, 0x33, 0xCC, 0x95, 0x18, 0xD3, 0x8A, 0xA8, 0xDB, 0xF1, 0x92, + 0x5A, 0xB9, 0x23, 0x86, 0xED, 0xD4, 0x00, 0x99, 0x23}; + + digest = blake2b(abc, 3, NULL, 0, 64); + assert_bytes(abc_answer, digest, 64); + + free(digest); + + uint8_t key[64] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f}; + uint8_t key_answer[64] = { + 0x10, 0xeb, 0xb6, 0x77, 0x00, 0xb1, 0x86, 0x8e, 0xfb, 0x44, 0x17, + 0x98, 0x7a, 0xcf, 0x46, 0x90, 0xae, 0x9d, 0x97, 0x2f, 0xb7, 0xa5, + 0x90, 0xc2, 0xf0, 0x28, 0x71, 0x79, 0x9a, 0xaa, 0x47, 0x86, 0xb5, + 0xe9, 0x96, 0xe8, 0xf0, 0xf4, 0xeb, 0x98, 0x1f, 0xc2, 0x14, 0xb0, + 0x05, 0xf4, 0x2d, 0x2f, 0xf4, 0x23, 0x34, 0x99, 0x39, 0x16, 0x53, + 0xdf, 0x7a, 0xef, 0xcb, 0xc1, 0x3f, 0xc5, 0x15, 0x68}; + + digest = blake2b(NULL, 0, key, 64, 64); + assert_bytes(key_answer, digest, 64); + + free(digest); + + uint8_t zero[1] = {0}; + uint8_t zero_key[64] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f}; + uint8_t zero_answer[64] = { + 0x96, 0x1f, 0x6d, 0xd1, 0xe4, 0xdd, 0x30, 0xf6, 0x39, 0x01, 0x69, + 0x0c, 0x51, 0x2e, 0x78, 0xe4, 0xb4, 0x5e, 0x47, 0x42, 0xed, 0x19, + 0x7c, 0x3c, 0x5e, 0x45, 0xc5, 0x49, 0xfd, 0x25, 0xf2, 0xe4, 0x18, + 0x7b, 0x0b, 0xc9, 0xfe, 0x30, 0x49, 0x2b, 0x16, 0xb0, 0xd0, 0xbc, + 0x4e, 0xf9, 0xb0, 0xf3, 0x4c, 0x70, 0x03, 0xfa, 0xc0, 0x9a, 0x5e, + 0xf1, 0x53, 0x2e, 0x69, 0x43, 0x02, 0x34, 0xce, 0xbd}; + + digest = blake2b(zero, 1, zero_key, 64, 64); + assert_bytes(zero_answer, digest, 64); + + free(digest); + + uint8_t filled[64] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f}; + uint8_t filled_key[64] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f}; + uint8_t filled_answer[64] = { + 0x65, 0x67, 0x6d, 0x80, 0x06, 0x17, 0x97, 0x2f, 0xbd, 0x87, 0xe4, + 0xb9, 0x51, 0x4e, 0x1c, 0x67, 0x40, 0x2b, 0x7a, 0x33, 0x10, 0x96, + 0xd3, 0xbf, 0xac, 0x22, 0xf1, 0xab, 0xb9, 0x53, 0x74, 0xab, 0xc9, + 0x42, 0xf1, 0x6e, 0x9a, 0xb0, 0xea, 0xd3, 0x3b, 0x87, 0xc9, 0x19, + 0x68, 0xa6, 0xe5, 0x09, 0xe1, 0x19, 0xff, 0x07, 0x78, 0x7b, 0x3e, + 0xf4, 0x83, 0xe1, 0xdc, 0xdc, 0xcf, 0x6e, 0x30, 0x22}; + + digest = blake2b(filled, 64, filled_key, 64, 64); + assert_bytes(filled_answer, digest, 64); + + free(digest); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief main function + * + * @returns 0 on successful program exit + */ +int main() +{ + test(); + return 0; +} diff --git a/leetcode/DIRECTORY.md b/leetcode/DIRECTORY.md new file mode 100644 index 0000000000..d4436ea420 --- /dev/null +++ b/leetcode/DIRECTORY.md @@ -0,0 +1,157 @@ + +# LeetCode + +### LeetCode Algorithm + +| # | Title | Solution | Difficulty | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------- | ---------- | +| 1 | [Two Sum](https://leetcode.com/problems/two-sum) | [C](./src/1.c) | Easy | +| 2 | [Add Two Numbers](https://leetcode.com/problems/add-two-numbers) | [C](./src/2.c) | Medium | +| 3 | [Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters) | [C](./src/3.c) | Medium | +| 4 | [Median of Two Sorted Arrays](https://leetcode.com/problems/median-of-two-sorted-arrays) | [C](./src/4.c) | Hard | +| 5 | [Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring) | [C](./src/5.c) | Medium | +| 6 | [Zigzag Conversion](https://leetcode.com/problems/zigzag-conversion) | [C](./src/6.c) | Medium | +| 7 | [Reverse Integer](https://leetcode.com/problems/reverse-integer) | [C](./src/7.c) | Medium | +| 8 | [String to Integer (atoi)](https://leetcode.com/problems/string-to-integer-atoi) | [C](./src/8.c) | Medium | +| 9 | [Palindrome Number](https://leetcode.com/problems/palindrome-number) | [C](./src/9.c) | Easy | +| 10 | [Regular Expression Matching](https://leetcode.com/problems/regular-expression-matching) | [C](./src/10.c) | Hard | +| 11 | [Container With Most Water](https://leetcode.com/problems/container-with-most-water) | [C](./src/11.c) | Medium | +| 12 | [Integer to Roman](https://leetcode.com/problems/integer-to-roman) | [C](./src/12.c) | Medium | +| 13 | [Roman to Integer](https://leetcode.com/problems/roman-to-integer) | [C](./src/13.c) | Easy | +| 14 | [Longest Common Prefix](https://leetcode.com/problems/longest-common-prefix) | [C](./src/14.c) | Easy | +| 16 | [3Sum Closest](https://leetcode.com/problems/3sum-closest) | [C](./src/16.c) | Medium | +| 17 | [Letter Combinations of a Phone Number](https://leetcode.com/problems/letter-combinations-of-a-phone-number) | [C](./src/17.c) | Medium | +| 19 | [Remove Nth Node From End of List](https://leetcode.com/problems/remove-nth-node-from-end-of-list) | [C](./src/19.c) | Medium | +| 20 | [Valid Parentheses](https://leetcode.com/problems/valid-parentheses) | [C](./src/20.c) | Easy | +| 21 | [Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists) | [C](./src/21.c) | Easy | +| 24 | [Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs) | [C](./src/24.c) | Medium | +| 26 | [Remove Duplicates from Sorted Array](https://leetcode.com/problems/remove-duplicates-from-sorted-array) | [C](./src/26.c) | Easy | +| 27 | [Remove Element](https://leetcode.com/problems/remove-element) | [C](./src/27.c) | Easy | +| 28 | [Find the Index of the First Occurrence in a String](https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string) | [C](./src/28.c) | Easy | +| 29 | [Divide Two Integers](https://leetcode.com/problems/divide-two-integers) | [C](./src/29.c) | Medium | +| 32 | [Longest Valid Parentheses](https://leetcode.com/problems/longest-valid-parentheses) | [C](./src/32.c) | Hard | +| 35 | [Search Insert Position](https://leetcode.com/problems/search-insert-position) | [C](./src/35.c) | Easy | +| 37 | [Sudoku Solver](https://leetcode.com/problems/sudoku-solver) | [C](./src/37.c) | Hard | +| 38 | [Count and Say](https://leetcode.com/problems/count-and-say) | [C](./src/38.c) | Medium | +| 42 | [Trapping Rain Water](https://leetcode.com/problems/trapping-rain-water) | [C](./src/42.c) | Hard | +| 45 | [Jump Game II](https://leetcode.com/problems/jump-game-ii) | [C](./src/45.c) | Medium | +| 50 | [Pow(x, n)](https://leetcode.com/problems/powx-n) | [C](./src/50.c) | Medium | +| 53 | [Maximum Subarray](https://leetcode.com/problems/maximum-subarray) | [C](./src/53.c) | Medium | +| 62 | [Unique Paths](https://leetcode.com/problems/unique-paths) | [C](./src/62.c) | Medium | +| 63 | [Unique Paths II](https://leetcode.com/problems/unique-paths-ii) | [C](./src/63.c) | Medium | +| 66 | [Plus One](https://leetcode.com/problems/plus-one) | [C](./src/66.c) | Easy | +| 75 | [Sort Colors](https://leetcode.com/problems/sort-colors) | [C](./src/75.c) | Medium | +| 79 | [Word Search](https://leetcode.com/problems/word-search) | [C](./src/79.c) | Medium | +| 82 | [Remove Duplicates from Sorted List II](https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii) | [C](./src/82.c) | Medium | +| 83 | [Remove Duplicates from Sorted List](https://leetcode.com/problems/remove-duplicates-from-sorted-list) | [C](./src/83.c) | Easy | +| 94 | [Binary Tree Inorder Traversal](https://leetcode.com/problems/binary-tree-inorder-traversal) | [C](./src/94.c) | Easy | +| 98 | [Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree) | [C](./src/98.c) | Medium | +| 101 | [Symmetric Tree](https://leetcode.com/problems/symmetric-tree) | [C](./src/101.c) | Easy | +| 104 | [Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree) | [C](./src/104.c) | Easy | +| 108 | [Convert Sorted Array to Binary Search Tree](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree) | [C](./src/108.c) | Easy | +| 109 | [Convert Sorted List to Binary Search Tree](https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree) | [C](./src/109.c) | Medium | +| 110 | [Balanced Binary Tree](https://leetcode.com/problems/balanced-binary-tree) | [C](./src/110.c) | Easy | +| 112 | [Path Sum](https://leetcode.com/problems/path-sum) | [C](./src/112.c) | Easy | +| 118 | [Pascal's Triangle](https://leetcode.com/problems/pascals-triangle) | [C](./src/118.c) | Easy | +| 119 | [Pascal's Triangle II](https://leetcode.com/problems/pascals-triangle-ii) | [C](./src/119.c) | Easy | +| 121 | [Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock) | [C](./src/121.c) | Easy | +| 124 | [Binary Tree Maximum Path Sum](https://leetcode.com/problems/binary-tree-maximum-path-sum) | [C](./src/124.c) | Hard | +| 125 | [Valid Palindrome](https://leetcode.com/problems/valid-palindrome) | [C](./src/125.c) | Easy | +| 136 | [Single Number](https://leetcode.com/problems/single-number) | [C](./src/136.c) | Easy | +| 141 | [Linked List Cycle](https://leetcode.com/problems/linked-list-cycle) | [C](./src/141.c) | Easy | +| 142 | [Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii) | [C](./src/142.c) | Medium | +| 153 | [Find Minimum in Rotated Sorted Array](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array) | [C](./src/153.c) | Medium | +| 160 | [Intersection of Two Linked Lists](https://leetcode.com/problems/intersection-of-two-linked-lists) | [C](./src/160.c) | Easy | +| 169 | [Majority Element](https://leetcode.com/problems/majority-element) | [C](./src/169.c) | Easy | +| 173 | [Binary Search Tree Iterator](https://leetcode.com/problems/binary-search-tree-iterator) | [C](./src/173.c) | Medium | +| 189 | [Rotate Array](https://leetcode.com/problems/rotate-array) | [C](./src/189.c) | Medium | +| 190 | [Reverse Bits](https://leetcode.com/problems/reverse-bits) | [C](./src/190.c) | Easy | +| 191 | [Number of 1 Bits](https://leetcode.com/problems/number-of-1-bits) | [C](./src/191.c) | Easy | +| 201 | [Bitwise AND of Numbers Range](https://leetcode.com/problems/bitwise-and-of-numbers-range) | [C](./src/201.c) | Medium | +| 203 | [Remove Linked List Elements](https://leetcode.com/problems/remove-linked-list-elements) | [C](./src/203.c) | Easy | +| 206 | [Reverse Linked List](https://leetcode.com/problems/reverse-linked-list) | [C](./src/206.c) | Easy | +| 215 | [Kth Largest Element in an Array](https://leetcode.com/problems/kth-largest-element-in-an-array) | [C](./src/215.c) | Medium | +| 217 | [Contains Duplicate](https://leetcode.com/problems/contains-duplicate) | [C](./src/217.c) | Easy | +| 223 | [Rectangle Area](https://leetcode.com/problems/rectangle-area) | [C](./src/223.c) | Medium | +| 226 | [Invert Binary Tree](https://leetcode.com/problems/invert-binary-tree) | [C](./src/226.c) | Easy | +| 230 | [Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst) | [C](./src/230.c) | Medium | +| 231 | [Power of Two](https://leetcode.com/problems/power-of-two) | [C](./src/231.c) | Easy | +| 234 | [Palindrome Linked List](https://leetcode.com/problems/palindrome-linked-list) | [C](./src/234.c) | Easy | +| 236 | [Lowest Common Ancestor of a Binary Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree) | [C](./src/236.c) | Medium | +| 242 | [Valid Anagram](https://leetcode.com/problems/valid-anagram) | [C](./src/242.c) | Easy | +| 268 | [Missing Number](https://leetcode.com/problems/missing-number) | [C](./src/268.c) | Easy | +| 274 | [H-Index](https://leetcode.com/problems/h-index) | [C](./src/274.c) | Medium | +| 278 | [First Bad Version](https://leetcode.com/problems/first-bad-version) | [C](./src/278.c) | Easy | +| 283 | [Move Zeroes](https://leetcode.com/problems/move-zeroes) | [C](./src/283.c) | Easy | +| 287 | [Find the Duplicate Number](https://leetcode.com/problems/find-the-duplicate-number) | [C](./src/287.c) | Medium | +| 344 | [Reverse String](https://leetcode.com/problems/reverse-string) | [C](./src/344.c) | Easy | +| 367 | [Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square) | [C](./src/367.c) | Easy | +| 387 | [First Unique Character in a String](https://leetcode.com/problems/first-unique-character-in-a-string) | [C](./src/387.c) | Easy | +| 389 | [Find the Difference](https://leetcode.com/problems/find-the-difference) | [C](./src/389.c) | Easy | +| 404 | [Sum of Left Leaves](https://leetcode.com/problems/sum-of-left-leaves) | [C](./src/404.c) | Easy | +| 434 | [Number of Segments in a String](https://leetcode.com/problems/number-of-segments-in-a-string) | [C](./src/434.c) | Easy | +| 442 | [Find All Duplicates in an Array](https://leetcode.com/problems/find-all-duplicates-in-an-array) | [C](./src/442.c) | Medium | +| 461 | [Hamming Distance](https://leetcode.com/problems/hamming-distance) | [C](./src/461.c) | Easy | +| 476 | [Number Complement](https://leetcode.com/problems/number-complement) | [C](./src/476.c) | Easy | +| 485 | [Max Consecutive Ones](https://leetcode.com/problems/max-consecutive-ones) | [C](./src/485.c) | Easy | +| 509 | [Fibonacci Number](https://leetcode.com/problems/fibonacci-number) | [C](./src/509.c) | Easy | +| 520 | [Detect Capital](https://leetcode.com/problems/detect-capital) | [C](./src/520.c) | Easy | +| 540 | [Single Element in a Sorted Array](https://leetcode.com/problems/single-element-in-a-sorted-array) | [C](./src/540.c) | Medium | +| 561 | [Array Partition](https://leetcode.com/problems/array-partition) | [C](./src/561.c) | Easy | +| 567 | [Permutation in String](https://leetcode.com/problems/permutation-in-string) | [C](./src/567.c) | Medium | +| 617 | [Merge Two Binary Trees](https://leetcode.com/problems/merge-two-binary-trees) | [C](./src/617.c) | Easy | +| 647 | [Palindromic Substrings](https://leetcode.com/problems/palindromic-substrings) | [C](./src/647.c) | Medium | +| 669 | [Trim a Binary Search Tree](https://leetcode.com/problems/trim-a-binary-search-tree) | [C](./src/669.c) | Medium | +| 674 | [Longest Continuous Increasing Subsequence](https://leetcode.com/problems/longest-continuous-increasing-subsequence) | [C](./src/674.c) | Easy | +| 684 | [Redundant Connection](https://leetcode.com/problems/redundant-connection) | [C](./src/684.c) | Medium | +| 700 | [Search in a Binary Search Tree](https://leetcode.com/problems/search-in-a-binary-search-tree) | [C](./src/700.c) | Easy | +| 701 | [Insert into a Binary Search Tree](https://leetcode.com/problems/insert-into-a-binary-search-tree) | [C](./src/701.c) | Medium | +| 704 | [Binary Search](https://leetcode.com/problems/binary-search) | [C](./src/704.c) | Easy | +| 709 | [To Lower Case](https://leetcode.com/problems/to-lower-case) | [C](./src/709.c) | Easy | +| 771 | [Jewels and Stones](https://leetcode.com/problems/jewels-and-stones) | [C](./src/771.c) | Easy | +| 807 | [Max Increase to Keep City Skyline](https://leetcode.com/problems/max-increase-to-keep-city-skyline) | [C](./src/807.c) | Medium | +| 841 | [Keys and Rooms](https://leetcode.com/problems/keys-and-rooms) | [C](./src/841.c) | Medium | +| 852 | [Peak Index in a Mountain Array](https://leetcode.com/problems/peak-index-in-a-mountain-array) | [C](./src/852.c) | Medium | +| 876 | [Middle of the Linked List](https://leetcode.com/problems/middle-of-the-linked-list) | [C](./src/876.c) | Easy | +| 901 | [Online Stock Span](https://leetcode.com/problems/online-stock-span) | [C](./src/901.c) | Medium | +| 905 | [Sort Array By Parity](https://leetcode.com/problems/sort-array-by-parity) | [C](./src/905.c) | Easy | +| 917 | [Reverse Only Letters](https://leetcode.com/problems/reverse-only-letters) | [C](./src/917.c) | Easy | +| 931 | [Minimum Falling Path Sum](https://leetcode.com/problems/minimum-falling-path-sum) | [C](./src/931.c) | Medium | +| 938 | [Range Sum of BST](https://leetcode.com/problems/range-sum-of-bst) | [C](./src/938.c) | Easy | +| 953 | [Verifying an Alien Dictionary](https://leetcode.com/problems/verifying-an-alien-dictionary) | [C](./src/953.c) | Easy | +| 965 | [Univalued Binary Tree](https://leetcode.com/problems/univalued-binary-tree) | [C](./src/965.c) | Easy | +| 977 | [Squares of a Sorted Array](https://leetcode.com/problems/squares-of-a-sorted-array) | [C](./src/977.c) | Easy | +| 979 | [Distribute Coins in Binary Tree](https://leetcode.com/problems/distribute-coins-in-binary-tree) | [C](./src/979.c) | Medium | +| 985 | [Sum of Even Numbers After Queries](https://leetcode.com/problems/sum-of-even-numbers-after-queries) | [C](./src/985.c) | Medium | +| 997 | [Find the Town Judge](https://leetcode.com/problems/find-the-town-judge) | [C](./src/997.c) | Easy | +| 1008 | [Construct Binary Search Tree from Preorder Traversal](https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal) | [C](./src/1008.c) | Medium | +| 1009 | [Complement of Base 10 Integer](https://leetcode.com/problems/complement-of-base-10-integer) | [C](./src/1009.c) | Easy | +| 1019 | [Next Greater Node In Linked List](https://leetcode.com/problems/next-greater-node-in-linked-list) | [C](./src/1019.c) | Medium | +| 1026 | [Maximum Difference Between Node and Ancestor](https://leetcode.com/problems/maximum-difference-between-node-and-ancestor) | [C](./src/1026.c) | Medium | +| 1089 | [Duplicate Zeros](https://leetcode.com/problems/duplicate-zeros) | [C](./src/1089.c) | Easy | +| 1137 | [N-th Tribonacci Number](https://leetcode.com/problems/n-th-tribonacci-number) | [C](./src/1137.c) | Easy | +| 1147 | [Longest Chunked Palindrome Decomposition](https://leetcode.com/problems/longest-chunked-palindrome-decomposition) | [C](./src/1147.c) | Hard | +| 1184 | [Distance Between Bus Stops](https://leetcode.com/problems/distance-between-bus-stops) | [C](./src/1184.c) | Easy | +| 1189 | [Maximum Number of Balloons](https://leetcode.com/problems/maximum-number-of-balloons) | [C](./src/1189.c) | Easy | +| 1207 | [Unique Number of Occurrences](https://leetcode.com/problems/unique-number-of-occurrences) | [C](./src/1207.c) | Easy | +| 1283 | [Find the Smallest Divisor Given a Threshold](https://leetcode.com/problems/find-the-smallest-divisor-given-a-threshold) | [C](./src/1283.c) | Medium | +| 1524 | [Number of Sub-arrays With Odd Sum](https://leetcode.com/problems/number-of-sub-arrays-with-odd-sum) | [C](./src/1524.c) | Medium | +| 1653 | [Minimum Deletions to Make String Balanced](https://leetcode.com/problems/minimum-deletions-to-make-string-balanced) | [C](./src/1653.c) | Medium | +| 1657 | [Determine if Two Strings Are Close](https://leetcode.com/problems/determine-if-two-strings-are-close) | [C](./src/1657.c) | Medium | +| 1695 | [Maximum Erasure Value](https://leetcode.com/problems/maximum-erasure-value) | [C](./src/1695.c) | Medium | +| 1704 | [Determine if String Halves Are Alike](https://leetcode.com/problems/determine-if-string-halves-are-alike) | [C](./src/1704.c) | Easy | +| 1752 | [Check if Array Is Sorted and Rotated](https://leetcode.com/problems/check-if-array-is-sorted-and-rotated) | [C](./src/1752.c) | Easy | +| 1769 | [Minimum Number of Operations to Move All Balls to Each Box](https://leetcode.com/problems/minimum-number-of-operations-to-move-all-balls-to-each-box) | [C](./src/1769.c) | Medium | +| 1833 | [Maximum Ice Cream Bars](https://leetcode.com/problems/maximum-ice-cream-bars) | [C](./src/1833.c) | Medium | +| 1838 | [Frequency of the Most Frequent Element](https://leetcode.com/problems/frequency-of-the-most-frequent-element) | [C](./src/1838.c) | Medium | +| 2024 | [Maximize the Confusion of an Exam](https://leetcode.com/problems/maximize-the-confusion-of-an-exam) | [C](./src/2024.c) | Medium | +| 2095 | [Delete the Middle Node of a Linked List](https://leetcode.com/problems/delete-the-middle-node-of-a-linked-list) | [C](./src/2095.c) | Medium | +| 2125 | [Number of Laser Beams in a Bank](https://leetcode.com/problems/number-of-laser-beams-in-a-bank) | [C](./src/2125.c) | Medium | +| 2130 | [Maximum Twin Sum of a Linked List](https://leetcode.com/problems/maximum-twin-sum-of-a-linked-list) | [C](./src/2130.c) | Medium | +| 2222 | [Number of Ways to Select Buildings](https://leetcode.com/problems/number-of-ways-to-select-buildings) | [C](./src/2222.c) | Medium | +| 2256 | [Minimum Average Difference](https://leetcode.com/problems/minimum-average-difference) | [C](./src/2256.c) | Medium | +| 2270 | [Number of Ways to Split Array](https://leetcode.com/problems/number-of-ways-to-split-array) | [C](./src/2270.c) | Medium | +| 2279 | [Maximum Bags With Full Capacity of Rocks](https://leetcode.com/problems/maximum-bags-with-full-capacity-of-rocks) | [C](./src/2279.c) | Medium | +| 2304 | [Minimum Path Cost in a Grid](https://leetcode.com/problems/minimum-path-cost-in-a-grid) | [C](./src/2304.c) | Medium | +| 2482 | [Difference Between Ones and Zeros in Row and Column](https://leetcode.com/problems/difference-between-ones-and-zeros-in-row-and-column) | [C](./src/2482.c) | Medium | +| 2501 | [Longest Square Streak in an Array](https://leetcode.com/problems/longest-square-streak-in-an-array) | [C](./src/2501.c) | Medium | diff --git a/leetcode/README.md b/leetcode/README.md index 0cd07e3d96..8f938b440a 100644 --- a/leetcode/README.md +++ b/leetcode/README.md @@ -1,94 +1,69 @@ -LeetCode -======== - -### LeetCode Algorithm - - -| # | Title | Solution | Difficulty | -|---| ----- | -------- | ---------- | -|1|[Two Sum](https://leetcode.com/problems/two-sum/) | [C](./src/1.c)|Easy| -|2|[Add Two Numbers](https://leetcode.com/problems/add-two-numbers/) | [C](./src/2.c)|Medium| -|3|[Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/) | [C](./src/3.c)|Medium| -|4|[Median of Two Sorted Arrays](https://leetcode.com/problems/median-of-two-sorted-arrays/) | [C](./src/4.c)|Hard| -|6|[ZigZag conversion](https://leetcode.com/problems/zigzag-conversion/) | [C](./src/4.c)|Medium| -|7|[Reverse Integer](https://leetcode.com/problems/reverse-integer/) | [C](./src/7.c)|Easy| -|8|[String to Integer (atoi)](https://leetcode.com/problems/string-to-integer-atoi) | [C](./src/8.c)|Medium| -|9|[Palindrome Number](https://leetcode.com/problems/palindrome-number/) | [C](./src/9.c)|Easy| -|11| [Container With Most Water](https://leetcode.com/problems/container-with-most-water/) | [C](./src/11.c)|Medium| -|12|[Integer to Roman](https://leetcode.com/problems/integer-to-roman) | [C](./src/12.c)|Medium| -|13|[Roman to Integer](https://leetcode.com/problems/roman-to-integer/) | [C](./src/13.c)|Easy| -|20|[Valid Parentheses](https://leetcode.com/problems/valid-parentheses/) | [C](./src/20.c)|Easy| -|21|[Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/) | [C](./src/21.c)|Easy| -|24|[Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/) | [C](./src/24.c)|Medium| -|26|[Remove Duplicates from Sorted Array](https://leetcode.com/problems/remove-duplicates-from-sorted-array/) | [C](./src/26.c)|Easy| -|27|[Remove Element](https://leetcode.com/problems/remove-element/) | [C](./src/27.c)|Easy| -|28|[Implement strStr()](https://leetcode.com/problems/implement-strstr/) | [C](./src/28.c)|Easy| -|29|[Divide Two Integers](https://leetcode.com/problems/divide-two-integers/) | [C](./src/29.c)|Medium| -|35|[Search Insert Position](https://leetcode.com/problems/search-insert-position/) | [C](./src/35.c)|Easy| -|38|[Count and Say](https://leetcode.com/problems/count-and-say/) | [C](./src/38.c)|Easy| -|53|[Maximum Subarray](https://leetcode.com/problems/maximum-subarray/) | [C](./src/53.c)|Easy| -|66|[Plus One](https://leetcode.com/problems/plus-one/) | [C](./src/66.c)|Easy| -|82|[Remove Duplicates from Sorted List II](https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/) | [C](./src/82.c)|Medium| -|83|[Remove Duplicates from Sorted List](https://leetcode.com/problems/remove-duplicates-from-sorted-list/) | [C](./src/83.c)|Easy| -|94|[Binary Tree Inorder Traversal](https://leetcode.com/problems/binary-tree-inorder-traversal/) | [C](./src/94.c)|Medium| -|101|[Symmetric Tree](https://leetcode.com/problems/symmetric-tree/) | [C](./src/101.c)|Easy| -|104|[Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) | [C](./src/104.c)|Easy| -|108|[Convert Sorted Array to Binary Search Tree](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/) | [C](./src/108.c)|Easy| -|109|[Convert Sorted List to Binary Search Tree](https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/) | [C](./src/109.c)|Medium| -|110|[Balanced Binary Tree](https://leetcode.com/problems/balanced-binary-tree/) | [C](./src/110.c)|Easy| -|112|[Path Sum](https://leetcode.com/problems/path-sum/) | [C](./src/112.c)|Easy| -|121|[Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/) | [C](./src/121.c)|Easy| -|125|[Valid Palindrome](https://leetcode.com/problems/valid-palindrome/) | [C](./src/125.c)|Easy| -|136|[Single Number](https://leetcode.com/problems/single-number/) | [C](./src/136.c)|Easy| -|141|[Linked List Cycle](https://leetcode.com/problems/linked-list-cycle/) | [C](./src/141.c)|Easy| -|142|[Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii/) | [C](./src/142.c)|Medium| -|153|[Find Minimum in Rotated Sorted Array](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/) | [C](./src/153.c)|Medium| -|160|[Intersection of Two Linked Lists](https://leetcode.com/problems/intersection-of-two-linked-lists/) | [C](./src/160.c)|Easy| -|169|[Majority Element](https://leetcode.com/problems/majority-element/) | [C](./src/169.c)|Easy| -|173|[Binary Search Tree Iterator](https://leetcode.com/problems/binary-search-tree-iterator/) | [C](./src/173.c)|Medium| -|189|[Rotate Array](https://leetcode.com/problems/rotate-array) | [C](./src/189.c)|Easy| -|190|[Reverse Bits](https://leetcode.com/problems/reverse-bits/) | [C](./src/190.c)|Easy| -|191|[Number of 1 Bits](https://leetcode.com/problems/number-of-1-bits/) | [C](./src/191.c)|Easy| -|201|[Bitwise AND of Numbers Range](https://leetcode.com/problems/bitwise-and-of-numbers-range/) | [C](./src/201.c)|Medium| -|203|[Remove Linked List Elements](https://leetcode.com/problems/remove-linked-list-elements/) | [C](./src/203.c)|Easy| -|206|[Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/) | [C](./src/206.c)|Easy| -|215|[Kth Largest Element in an Array](https://leetcode.com/problems/kth-largest-element-in-an-array/) | [C](./src/215.c)|Medium| -|217|[Contains Duplicate](https://leetcode.com/problems/contains-duplicate/) | [C](./src/217.c)|Easy| -|226|[Invert Binary Tree](https://leetcode.com/problems/invert-binary-tree/) | [C](./src/226.c)|Easy| -|231|[Power of Two](https://leetcode.com/problems/power-of-two/) | [C](./src/231.c)|Easy| -|234|[Palindrome Linked List](https://leetcode.com/problems/palindrome-linked-list/) | [C](./src/234.c)|Easy| -|242|[Valid Anagram](https://leetcode.com/problems/valid-anagram/) | [C](./src/242.c)|Easy| -|268|[Missing Number](https://leetcode.com/problems/missing-number/) | [C](./src/268.c)|Easy| -|278|[First Bad Version](https://leetcode.com/problems/first-bad-version/) | [C](./src/278.c)|Easy| -|283|[Move Zeroes](https://leetcode.com/problems/move-zeroes/) | [C](./src/283.c)|Easy| -|287|[Find the Duplicate Number](https://leetcode.com/problems/find-the-duplicate-number/) | [C](./src/287.c)|Medium| -|344|[Reverse String](https://leetcode.com/problems/reverse-string/) | [C](./src/344.c)|Easy| -|367|[Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/) | [C](./src/367.c)|Easy| -|387|[First Unique Character in a String](https://leetcode.com/problems/first-unique-character-in-a-string/) | [C](./src/387.c)|Easy| -|389|[Find the Difference](https://leetcode.com/problems/find-the-difference/) | [C](./src/389.c)|Easy| -|404|[Sum of Left Leaves](https://leetcode.com/problems/sum-of-left-leaves/) | [C](./src/404.c)|Easy| -|442|[Find All Duplicates in an Array](https://leetcode.com/problems/find-all-duplicates-in-an-array/) | [C](./src/442.c)|Medium| -|461|[Hamming Distance](https://leetcode.com/problems/hamming-distance/) | [C](./src/461.c) |Easy| -|476|[Number Complement](https://leetcode.com/problems/number-complement/) | [C](./src/476.c)|Easy| -|509|[Fibonacci Number](https://leetcode.com/problems/fibonacci-number/) | [C](./src/509.c)|Easy| -|520|[Detect Capital](https://leetcode.com/problems/detect-capital/) | [C](./src/520.c)|Easy| -|561|[Array Partition I](https://leetcode.com/problems/array-partition-i/) | [C](./src/561.c)|Easy| -|617|[Merge Two Binary Trees](https://leetcode.com/problems/merge-two-binary-trees/) | [C](./src/617.c)|Easy| -|647|[Palindromic Substring](https://leetcode.com/problems/palindromic-substrings/) | [C](./src/647.c)|Medium| -|674|[Longest Continuous Increasing Subsequence](https://leetcode.com/problems/longest-continuous-increasing-subsequence/) | [C](./src/674.c)|Easy| -|700|[Search in a Binary Search Tree](https://leetcode.com/problems/search-in-a-binary-search-tree/) | [C](./src/700.c)|Easy| -|701|[Insert into a Binary Search Tree](https://leetcode.com/problems/insert-into-a-binary-search-tree/) | [C](./src/701.c)|Medium| -|704|[Binary Search](https://leetcode.com/problems/binary-search/) | [C](./src/704.c)|Easy| -|709|[To Lower Case](https://leetcode.com/problems/to-lower-case/) | [C](./src/709.c)|Easy| -|771|[Jewels and Stones](https://leetcode.com/problems/jewels-and-stones/) | [C](./src/771.c)|Easy| -|852|[Peak Index in a Mountain Array](https://leetcode.com/problems/peak-index-in-a-mountain-array/) | [C](./src/852.c)|Easy| -|876|[Middle of the Linked List](https://leetcode.com/problems/middle-of-the-linked-list/) | [C](./src/876.c)|Easy| -|905|[Sort Array By Parity](https://leetcode.com/problems/sort-array-by-parity/) | [C](./src/905.c)|Easy| -|917|[Reverse Only Letters](https://leetcode.com/problems/reverse-only-letters/) | [C](./src/917.c)|Easy| -|938|[Range Sum of BST](https://leetcode.com/problems/range-sum-of-bst/) | [C](./src/938.c)|Easy| -|965|[Univalued Binary Tree](https://leetcode.com/problems/univalued-binary-tree/) | [C](./src/965.c)|Easy| -|977|[Squares of a Sorted Array](https://leetcode.com/problems/squares-of-a-sorted-array/) | [C](./src/977.c)|Easy| -|1089|[Duplicate Zeros](https://leetcode.com/problems/duplicate-zeros/) | [C](./src/1089.c)|Easy| -|1184|[Distance Between Bus Stops](https://leetcode.com/problems/distance-between-bus-stops/) | [C](./src/1184.c)|Easy| -|1189|[Maximum Number of Balloons](https://leetcode.com/problems/maximum-number-of-balloons/) | [C](./src/1189.c)|Easy| -|1207|[Unique Number of Occurrences](https://leetcode.com/problems/unique-number-of-occurrences/) | [C](./src/1207.c)|Easy| +# 📚 Contributing 📚 + +We're glad you're interested in adding C LeetCode solutions to the repository.\ +Here we'll be explaining how to contribute to LeetCode solutions properly. + +## 💻 Cloning/setting up the project 💻 + +First off, you'll need to fork the repository [**here**](https://github.com/TheAlgorithms/C/fork).\ +Then, you'll need to clone the repository to your local machine. + +```bash +git clone https://github.com/your-username/C.git +``` + +After that, you'll need to create a new branch for your solution. + +```bash +git checkout -b solution/your-solution-name +``` + +## 📝 Adding a new solution 📝 + +All LeetCode problems can be found [**here**](https://leetcode.com/problemset/all/).\ +If you have a solution to any of these problems (which are not being [**repeated**](https://github.com/TheAlgorithms/C/blob/master/leetcode/DIRECTORY.md)), that's great! Here are the steps: + +1. Add a new file in `leetcode/src` with the number of the problem. + - For example: if the problem's number is 98, the filename should be `98.c`. +2. Provide a small description of the solution at the top of the file. A function should go below that. For example: + +```c +/** + * Return an array of arrays of size *returnSize. + * The sizes of the arrays are returned as *returnColumnSizes array. + * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free(). + */ +``` + +3. Do not provide a `main` function. Use the required standalone functions instead. +4. Doxygen documentation isn't used in LeetCode solutions. Simple/small documentation or comments should be fine. +5. Don't include libraries/headers such as `stdio.h`. Your file should be the solution to the problem only. + +> **Note** +> There was a requirement to update the `leetcode/DIRECTORY.md` file with details of the solved problem. It's not required anymore. The information about the problem is fetched automatically throughout the LeetCode API. + +## 📦 Committing your changes 📦 + +Once you're done with adding a new LeetCode solution, it's time we make a pull request. + +1. First, stage your changes. + +```bash +git add leetcode/src/98.c # Use `git add .` to stage all changes. +``` + +2. Then, commit your changes. + +```bash +git commit -m "feat: add LeetCode problem 98" -m "Commit description" # Optional +``` + +3. Finally, push your changes to your forked repository. + +```bash +git push origin solution/your-solution-name:solution/your-solution-name +``` + +4. You're done now! You just have to make a [**pull request**](https://github.com/TheAlgorithms/C/compare). 🎉 + +If you need any help, don't hesitate to ask and join our [**Discord server**](https://the-algorithms.com/discord)! 🙂 diff --git a/leetcode/src/10.c b/leetcode/src/10.c new file mode 100644 index 0000000000..26ed6a3b89 --- /dev/null +++ b/leetcode/src/10.c @@ -0,0 +1,59 @@ +/* +Prompt: + +Given an input string s and a pattern p, implement regular expression matching with support for '.' and '*' where: +- '.' Matches any single character. +- '*' Matches zero or more of the preceding element. +The matching should cover the entire input string (not partial). + +Constraints: + +1 <= s.length <= 20 +1 <= p.length <= 30 +s contains only lowercase English letters. +p contains only lowercase English letters, '.', and '*'. + +It is guaranteed for each appearance of the character '*', there will be a previous valid character to match. +*/ + +bool isMatch(char* s, char* p); +bool matchStar(char ch, char* s, char* p); + +/* +Uses Rob pikes Regexp matcher - https://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html +Implementation: + // match: search for regexp anywhere in text + int match(char *regexp, char *text) + { + if (regexp[0] == '^') + return matchhere(regexp+1, text); + do { + if (matchhere(regexp, text)) + return 1; + } while (*text++ != '\0'); + return 0; + } +*/ + +bool matchStar(char ch, char* s, char* p) { + do { + if (isMatch(s, p)) + return true; + } while (*s != '\0' && (*s++ == ch || ch == '.')); + + return false; +} + +bool isMatch(char* s, char* p) { + if (*p == '\0') + return *s == '\0'; + + if (p[1] == '*') + return matchStar(p[0], s, p + 2); + + if (*s != '\0' && (p[0] == '.' || *p == *s)) { + return isMatch(s + 1, p + 1); + } + + return false; +} diff --git a/leetcode/src/1008.c b/leetcode/src/1008.c new file mode 100644 index 0000000000..ce4871ecd4 --- /dev/null +++ b/leetcode/src/1008.c @@ -0,0 +1,39 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * struct TreeNode *left; + * struct TreeNode *right; + * }; + */ + +struct TreeNode* bstFromPreorder(int* preorder, int preorderSize) +{ + struct TreeNode* new; + int left_ptr; + + new = malloc(sizeof(struct TreeNode)); + new->val = preorder[0]; + + if (preorderSize == 1) + { + new->right = NULL; + new->left = NULL; + return new; + } + + left_ptr = 1; + while ((left_ptr < preorderSize) && (preorder[left_ptr] < preorder[0])) + left_ptr++; + if (left_ptr == 1) + new->left = NULL; + else + new->left = bstFromPreorder(preorder + 1, left_ptr - 1); + if (left_ptr < preorderSize) + new->right = + bstFromPreorder(preorder + left_ptr, preorderSize - left_ptr); + else + new->right = NULL; + + return new; +} diff --git a/leetcode/src/1009.c b/leetcode/src/1009.c new file mode 100644 index 0000000000..77480d71a7 --- /dev/null +++ b/leetcode/src/1009.c @@ -0,0 +1,15 @@ +// Bit manipulation. +// - Find the bit length of n using log2 +// - Create bit mask of bit length of n +// - Retun ~n and bit of ones mask +// Runtime: O(log2(n)) +// Space: O(1) + +int bitwiseComplement(int n){ + if (n == 0){ + return 1; + } + + int binary_number_length = ceil(log2(n)); + return (~n) & ((1 << binary_number_length) - 1); +} diff --git a/leetcode/src/1019.c b/leetcode/src/1019.c new file mode 100644 index 0000000000..31eca53d72 --- /dev/null +++ b/leetcode/src/1019.c @@ -0,0 +1,29 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * struct ListNode *next; + * }; + */ + +int* nextLargerNodes(struct ListNode* head, int* returnSize) +{ + int *output, count = 0; + struct ListNode *tmp = head, *tmp2; + for (; tmp != NULL; tmp = tmp->next, count++) + ; + output = (int*)calloc(count, sizeof(int)); + *returnSize = count; + for (tmp = head, count = 0; tmp->next != NULL; tmp = tmp->next, count++) + { + for (tmp2 = tmp->next; tmp2 != NULL; tmp2 = tmp2->next) + { + if (tmp2->val > tmp->val) + { + output[count] = tmp2->val; + break; + } + } + } + return output; +} diff --git a/leetcode/src/1026.c b/leetcode/src/1026.c new file mode 100644 index 0000000000..0dda623023 --- /dev/null +++ b/leetcode/src/1026.c @@ -0,0 +1,38 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * struct TreeNode *left; + * struct TreeNode *right; + * }; + */ + +#define max(a,b) (((a)>(b))?(a):(b)) +#define min(a,b) (((a)<(b))?(a):(b)) + +void recursiveSolve(struct TreeNode* node, int* result, int minVal, int maxVal){ + if (node == NULL){ + return; + } + + *result = max(*result, abs(minVal - node->val)); + *result = max(*result, abs(maxVal - node->val)); + + minVal = min(minVal, node->val); + maxVal = max(maxVal, node->val); + + recursiveSolve(node->left, result, minVal, maxVal); + recursiveSolve(node->right, result, minVal, maxVal); +} + +// Depth First Search +// If The maximum diff is exists it should be the difference of the MAX or MIN value in the tree path to the LEAF +// Runtime: O(n) +// Space: O(1) +int maxAncestorDiff(struct TreeNode* root){ + int result = 0; + int maxVal = root->val; + int minVal = root->val; + recursiveSolve(root, &result, minVal, maxVal); + return result; +} diff --git a/leetcode/src/1137.c b/leetcode/src/1137.c new file mode 100644 index 0000000000..0bb7fdc38a --- /dev/null +++ b/leetcode/src/1137.c @@ -0,0 +1,29 @@ +// Dynamic Programming +// Runtime: O(n) +// Space: O(1) +int tribonacci(int n){ + int t0 = 0; + int t1 = 1; + int t2 = 1; + + if (n == 0) { + return t0; + } + + if (n == 1){ + return t1; + } + + if (n == 2){ + return t2; + } + + for (int i = 0; i < n - 2; i++){ + int nextT = t0 + t1 + t2; + t0 = t1; + t1 = t2; + t2 = nextT; + } + + return t2; +} diff --git a/leetcode/src/1147.c b/leetcode/src/1147.c new file mode 100644 index 0000000000..501060d098 --- /dev/null +++ b/leetcode/src/1147.c @@ -0,0 +1,49 @@ +#define max(a,b) (((a)>(b))?(a):(b)) + +bool equalSubstrings(char* text, int firstIndex, int secondIndex, int length){ + for (int i = 0; i < length; i++){ + if (text[firstIndex + i] != text[secondIndex + i]){ + return false; + } + } + + return true; +} + +int longestDecompositionDpCached(char* text, int textLen, int index, int* dp){ + if (2 * index >= textLen){ + return 0; + } + + if (dp[index] == 0){ + dp[index] = longestDecompositionDp(text, textLen, index, dp); + } + + return dp[index]; +} + +int longestDecompositionDp(char* text, int textLen, int index, int* dp){ + char ch = text[index]; + int result = 1; + + for (int i = 0; i < (textLen - 2 * index) / 2; i++){ + if (ch == text[textLen - 1 - index - i] + && equalSubstrings(text, index, textLen - 1 - index - i, i + 1)){ + return max(result, 2 + longestDecompositionDpCached(text, textLen, index + i + 1, dp)); + } + } + + return result; +} + +// Dynamic programming. Up -> down approach. +// Runtime: O(n*n) +// Space: O(n) +int longestDecomposition(char * text){ + int textLen = strlen(text); + int* dp = calloc(textLen, sizeof(int)); + int result = longestDecompositionDpCached(text, textLen, 0, dp); + + free(dp); + return result; +} diff --git a/leetcode/src/118.c b/leetcode/src/118.c new file mode 100644 index 0000000000..a926efdcb1 --- /dev/null +++ b/leetcode/src/118.c @@ -0,0 +1,26 @@ +/** + * Return an array of arrays of size *returnSize. + * The sizes of the arrays are returned as *returnColumnSizes array. + * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free(). + */ +int** generate(int numRows, int* returnSize, int** returnColumnSizes){ + *returnSize = numRows; + int **ans = (int**)malloc(numRows*sizeof(int*)); + *returnColumnSizes = (int*)malloc(numRows*sizeof(int)); + + for (int i=0; i 0; c--) + { + ans[c] = ans[c] + ans[c-1]; + } + } + + return ans; +} diff --git a/leetcode/src/124.c b/leetcode/src/124.c new file mode 100644 index 0000000000..a846dfcb44 --- /dev/null +++ b/leetcode/src/124.c @@ -0,0 +1,36 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * struct TreeNode *left; + * struct TreeNode *right; + * }; + */ + +#define max(a,b) (((a)>(b))?(a):(b)) + +int recursiveSolve(struct TreeNode* node, int* result){ + if (node == NULL){ + return 0; + } + + int leftSum = max(recursiveSolve(node->left, result), 0); + int rightSum = max(recursiveSolve(node->right, result), 0); + + // Check if it's possible to make a maximum path from left right and current node + int maxValueNode = node->val + leftSum + rightSum; + *result = max(maxValueNode, *result); + + // Choose the max sum val path + return node->val + max(leftSum, rightSum); +} + +// Depth First Search +// Runtime: O(n), n - the number of nodes in tree. +// Space: O(1) +int maxPathSum(struct TreeNode* root){ + const int LOWER_BOUND = -2147483648 + int result = LOWER_BOUND; + recursiveSolve(root, &result); + return result; +} diff --git a/leetcode/src/1283.c b/leetcode/src/1283.c new file mode 100644 index 0000000000..ccdf9e2980 --- /dev/null +++ b/leetcode/src/1283.c @@ -0,0 +1,44 @@ +#define max(a,b) (((a)>(b))?(a):(b)) + +long getSum(int* nums, int numsSize, int divizor){ + long result = 0; + for (int i = 0; i < numsSize; i++){ + int value = nums[i] / divizor; + if (value * divizor != nums[i]){ + value++; + } + + result += value; + } + + return result; +} + +// Divide and conquer +// Runtime: O(n*log(n)) +// Space: O(1) +int smallestDivisor(int* nums, int numsSize, int threshold){ + int maxNum = 0; + for (int i = 0; i < numsSize; i++){ + maxNum = max(maxNum, nums[i]); + } + + int left = 1; + int right = maxNum; + while (left <= right){ + int middle = (left + right) / 2; + long middleSum = getSum(nums, numsSize, middle); + if (middleSum <= threshold && (middle == 1 || getSum(nums, numsSize, middle - 1) > threshold)){ + return middle; + } + + if (middleSum > threshold){ + left = middle + 1; + } + else{ + right = middle - 1; + } + } + + return -1; +} diff --git a/leetcode/src/14.c b/leetcode/src/14.c new file mode 100644 index 0000000000..8f5a22d840 --- /dev/null +++ b/leetcode/src/14.c @@ -0,0 +1,25 @@ +int findMaxConsecutiveOnes(int* nums, int numsSize){ + int i=0; + int maxCount=0; + int count = 0; + + while(i // for qsort() + +int cmp(const void* a, const void* b) { + const int *A = a, *B = b; + return (*A > *B) - (*A < *B); +} + +int threeSumClosest(int* nums, int nums_size, int target) { + int i, j, k, result, sum3; + qsort(nums, nums_size, sizeof(int), cmp); + result = nums[0] + nums[1] + nums[2]; + for (i = 0; i < nums_size - 2; i++) { + j = i + 1; + k = nums_size - 1; + while (j < k) { + sum3 = nums[i] + nums[j] + nums[k]; + if (abs(target - sum3) < abs(target - result)) { + result = sum3; + } + if (sum3 < target) { + j++; + } else if (sum3 > target) { + k--; + } else { + return sum3; + } + } + } + return result; +} diff --git a/leetcode/src/1653.c b/leetcode/src/1653.c new file mode 100644 index 0000000000..04ac0c16b6 --- /dev/null +++ b/leetcode/src/1653.c @@ -0,0 +1,29 @@ +#define min(X, Y) ((X) < (Y) ? (X) : (Y)) + +// Dynamic programming approach. Down -> Up. +// Runtime: O(n) +// Space: O(1) +int minimumDeletions(char * s){ + int len = strlen(s); + + int aStateValue = s[0] == 'b'; + + int bStateValue = 0; + + int newAStateValue; + int newBStateValue; + + for(int i = 1; i < len; i++){ + newAStateValue = aStateValue + (s[i] == 'b'); + + newBStateValue = min( + aStateValue, + bStateValue + (s[i] == 'a') + ); + + aStateValue = newAStateValue; + bStateValue = newBStateValue; + } + + return min(aStateValue, bStateValue); +} diff --git a/leetcode/src/1657.c b/leetcode/src/1657.c new file mode 100644 index 0000000000..10aa60d258 --- /dev/null +++ b/leetcode/src/1657.c @@ -0,0 +1,51 @@ +const charLength = 26; + +int* charsCount(char* word){ + int* result = calloc(charLength, sizeof(int)); + int wordLen = strlen(word); + for (int i = 0; i < wordLen; i++){ + result[word[i] - 'a']++; + } + + return result; +} + +int diff(const int *i, const int *j) +{ + return *i - *j; +} + +// Counting +// Runtime: O(n) +// Space: O(1) +bool closeStrings(char * word1, char * word2){ + int* word1CharsCounter = charsCount(word1); + int* word2CharsCounter = charsCount(word2); + + // The lengths of both string should be equal + if (strlen(word1) != strlen(word2)){ + return false; + } + + // The char should appear in both strings + for (int i = 0; i < charLength; i++){ + if ((word1CharsCounter[i] != 0 && word2CharsCounter[i] == 0) || + (word1CharsCounter[i] == 0 && word2CharsCounter[i] != 0)){ + return false; + } + } + + qsort(word1CharsCounter, charLength, sizeof (int), (int(*) (const void *, const void *)) diff); + qsort(word2CharsCounter, charLength, sizeof (int), (int(*) (const void *, const void *)) diff); + + // appearing of chars should be the same in both strings. + for (int i = 0; i < charLength; i++){ + if (word1CharsCounter[i] != word2CharsCounter[i]){ + return false; + } + } + + free(word1CharsCounter); + free(word2CharsCounter); + return true; +} diff --git a/leetcode/src/1695.c b/leetcode/src/1695.c new file mode 100644 index 0000000000..c0a57247a0 --- /dev/null +++ b/leetcode/src/1695.c @@ -0,0 +1,29 @@ +// Window sliding. Runtime: O(n), Space: O(n) +int maximumUniqueSubarray(int* nums, int numsSize){ + short* numsSet = (short*)calloc(10001, sizeof(short)); + numsSet[nums[0]] = 1; + + int maxSum = nums[0]; + + int windowSumm = maxSum; + int leftIndex = 0; + + int num = 0; + for(int i = 1; i < numsSize; i++){ + num = nums[i]; + while (numsSet[num] != 0){ + numsSet[nums[leftIndex]] = 0; + windowSumm -= nums[leftIndex]; + leftIndex++; + } + + numsSet[num] = 1; + windowSumm += num; + + if (maxSum < windowSumm){ + maxSum = windowSumm; + } + } + + return maxSum; +} diff --git a/leetcode/src/17.c b/leetcode/src/17.c new file mode 100644 index 0000000000..ff6e77d048 --- /dev/null +++ b/leetcode/src/17.c @@ -0,0 +1,78 @@ +/** + * Letter Combinations of a Phone Number problem + * The algorithm determines the final size of the return array (combs) and allocates + * corresponding letter for each element, assuming that the return array is alphabetically sorted. + * It does so by running two loops for each letter: + * - the first loop determines the starting positions of the sequence of subsequent letter positions + * - the second loop determines the length of each subsequent sequence for each letter + * The size and space complexity are both O("size of final array"), as even though there are 4 loops, + * each element in the final array is accessed only once. + */ + +#include // for the malloc() function +#include // for the strlen() function + +char *get_letters(char digit) { + switch (digit) { + case '2': + return "abc"; + case '3': + return "def"; + case '4': + return "ghi"; + case '5': + return "jkl"; + case '6': + return "mno"; + case '7': + return "pqrs"; + case '8': + return "tuv"; + case '9': + return "wxyz"; + default: + return ""; + } +} + +char **letterCombinations(char *digits, int *return_size) { + char *cp; + int i, j, k, l, ind, k_tot, l_tot, digits_size = 0; + + if (*digits == '\0') { + *return_size = 0; + return NULL; + } + + *return_size = 1; + cp = digits; + while (*cp != '\0') { + *return_size *= strlen(get_letters(*cp)); + digits_size++; + cp++; + } + + char **combs = malloc(sizeof(char*) * (*return_size)); + for (i = 0; i < *return_size; i++) { + combs[i] = malloc(sizeof(char) * (digits_size + 1)); + combs[i][digits_size] = '\0'; + } + + k_tot = 1; + l_tot = (*return_size); + for (i = 0; i < digits_size; i++) { // loop accross digits + cp = get_letters(digits[i]); + l_tot /= strlen(cp); + for (j = 0; j < strlen(cp); j++) { // loop accross letters of the digit + for (k = 0; k < k_tot; k++) { // loop across the subset starting positions for each letter + for (l = 0; l < l_tot; l++) { // loop accross each subset positions for each letter + ind = k * l_tot * strlen(cp) + l + l_tot * j; + combs[ind][i] = cp[j]; + } + } + } + k_tot *= strlen(cp); + } + + return combs; +} diff --git a/leetcode/src/1704.c b/leetcode/src/1704.c new file mode 100644 index 0000000000..25251983bc --- /dev/null +++ b/leetcode/src/1704.c @@ -0,0 +1,38 @@ +bool isVowel(char chr){ + switch(chr){ + case 'a': + case 'e': + case 'i': + case 'o': + case 'u': + case 'A': + case 'E': + case 'I': + case 'O': + case 'U': + return true; + } + + return false; +} + +// Counting +// Runtime: O(n) +// Space: O(1) +bool halvesAreAlike(char * s){ + int lenS = strlen(s); + int halfVowels = 0; + int currVowels = 0; + + for (int i = 0; i < lenS; i++){ + if (isVowel(s[i])){ + currVowels++; + } + + if (2 * (i + 1) == lenS){ + halfVowels = currVowels; + } + } + + return 2 * halfVowels == currVowels; +} diff --git a/leetcode/src/1752.c b/leetcode/src/1752.c new file mode 100644 index 0000000000..492a82b484 --- /dev/null +++ b/leetcode/src/1752.c @@ -0,0 +1,18 @@ +bool check(int* nums, int numsSize){ + if (numsSize == 1) { + return true; + } + + bool wasShift = false; + for(int i = 1; i < numsSize; i++) { + if (nums[i - 1] > nums[i]) { + if (wasShift) { + return false; + } + + wasShift = true; + } + } + + return !wasShift || nums[0] >= nums[numsSize-1]; +} diff --git a/leetcode/src/1769.c b/leetcode/src/1769.c new file mode 100644 index 0000000000..e1a81d0492 --- /dev/null +++ b/leetcode/src/1769.c @@ -0,0 +1,41 @@ +/** + * Note: The returned array must be malloced, assume caller calls free(). + */ + +// Count one's from right. Each step from right side decrease for one for each 1's and increase from left: +// 1001*0101 -> left: 4 + 1, right: 2 + 4 +// 10010*101 -> left: (4+1) + (1+1), right: (2-1) + (4-1) +// Runtime: O(n) +// Space: O(1) +int* minOperations(char* boxes, int* returnSize){ + int leftOnes = 0; + int leftCommonDistance = 0; + + int rightOnes = 0; + int rightCommonDistance = 0; + + int boxesLength = strlen(boxes); + + *returnSize = boxesLength; + int* result = malloc(boxesLength * sizeof(int)); + + for (int i = 0; i < boxesLength; i++){ + if (boxes[i] == '1'){ + rightOnes += 1; + rightCommonDistance += i; + } + } + + for (int i = 0; i < boxesLength; i++){ + if (boxes[i] == '1'){ + rightOnes -= 1; + leftOnes += 1; + } + + result[i] = rightCommonDistance + leftCommonDistance; + rightCommonDistance -= rightOnes; + leftCommonDistance += leftOnes; + } + + return result; +} diff --git a/leetcode/src/1833.c b/leetcode/src/1833.c new file mode 100644 index 0000000000..e77d8a2921 --- /dev/null +++ b/leetcode/src/1833.c @@ -0,0 +1,24 @@ +int compare(const void* i, const void* j) +{ + return *((int*)i) - *((int*)j); +} + +// Greedy + sorting +// Runtime: O(n*log(n)) +// Space: O(1) +int maxIceCream(int* costs, int costsSize, int coins){ + qsort(costs, costsSize, sizeof(int), compare); + + int result = 0; + int leftCoins = coins; + for (int i = 0; i < costsSize; i++){ + if (costs[i] > leftCoins){ + break; + } + + leftCoins -= costs[i]; + result++; + } + + return result; +} diff --git a/leetcode/src/1838.c b/leetcode/src/1838.c new file mode 100644 index 0000000000..fe4469bf3b --- /dev/null +++ b/leetcode/src/1838.c @@ -0,0 +1,36 @@ +#define max(a,b) (((a)>(b))?(a):(b)) + +int compare(const int* i, const int* j) +{ + return *i - *j; +} + +// Sort + prefix sum + windows sliding +// Runtime: O(n*log(n)) +// Space: O(n) +int maxFrequency(int* nums, int numsSize, int k){ + qsort(nums, numsSize, sizeof (int), (int(*) (const void*, const void*)) compare); + long* prefixSum = malloc(numsSize * sizeof(long)); + + prefixSum[0] = nums[0]; + for(int i = 0; i < numsSize - 1; i++){ + prefixSum[i + 1] = prefixSum[i] + nums[i]; + } + + int leftWindowPosition = 0; + int result = 0; + + for(int rightWindowPosition = 0; rightWindowPosition < numsSize; rightWindowPosition++){ + long rightSum = prefixSum[rightWindowPosition]; + long leftSum = prefixSum[leftWindowPosition]; + + while ((long)nums[rightWindowPosition] * (rightWindowPosition - leftWindowPosition) - (rightSum - leftSum) > k){ + leftWindowPosition += 1; + } + + result = max(result, rightWindowPosition - leftWindowPosition + 1); + } + + free(prefixSum); + return result; +} diff --git a/leetcode/src/19.c b/leetcode/src/19.c new file mode 100644 index 0000000000..c189f8f288 --- /dev/null +++ b/leetcode/src/19.c @@ -0,0 +1,27 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * struct ListNode *next; + * }; + */ + +struct ListNode *removeNthFromEnd(struct ListNode *head, int n) { + struct ListNode entry, *p_free, *p = head; + int i, sz = 0; + entry.next = head; + while (p != NULL) { + p = p->next; + sz++; + } + for (i = 0, p = &entry; i < sz - n; i++, p = p -> next) + ; + p_free = p->next; + if (n != 1) { + p->next = p->next->next; + } else { + p->next = NULL; + } + free(p_free); + return entry.next; +} diff --git a/leetcode/src/2024.c b/leetcode/src/2024.c new file mode 100644 index 0000000000..5796f0b03f --- /dev/null +++ b/leetcode/src/2024.c @@ -0,0 +1,33 @@ +#define max(X, Y) ((X) > (Y) ? (X) : (Y)) + +int maximizeTarget(char * answerKey, char targetChar, int k){ + int leftIndex = -1; + int result = 0; + int currTargetChars = 0; + int lenAnswerKey = strlen(answerKey); + + for (int rightIndex = 0; rightIndex < lenAnswerKey; rightIndex++){ + char ch = answerKey[rightIndex]; + if (ch == targetChar){ + currTargetChars++; + } + + while (rightIndex - leftIndex > currTargetChars + k) { + leftIndex++; + if (answerKey[leftIndex] == targetChar){ + currTargetChars--; + } + } + + result = max(result, rightIndex - leftIndex); + } + + return result; +} + +// Use sliding window approach + two pointers. +// Runtime: O(n) +// Space: O(1) +int maxConsecutiveAnswers(char * answerKey, int k){ + return max(maximizeTarget(answerKey, 'T', k), maximizeTarget(answerKey, 'F', k)); +} diff --git a/leetcode/src/2095.c b/leetcode/src/2095.c new file mode 100644 index 0000000000..196b0892a7 --- /dev/null +++ b/leetcode/src/2095.c @@ -0,0 +1,38 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * struct ListNode *next; + * }; + */ + +struct ListNode* deleteMiddle(struct ListNode* head) +{ + if (head == NULL || head->next == NULL) + return NULL; + struct ListNode *fast, *slow, *prev; + int n = 0; + fast = head; + slow = head; + while (fast != NULL) + { + n = n + 1; + fast = fast->next; + } + fast = head; + while (fast->next != NULL && fast->next->next != NULL) // finds mid node + { + prev = slow; + slow = slow->next; + fast = fast->next->next; + } + if (n % 2 == 0) + { + prev = slow; + slow = slow->next; + prev->next = slow->next; + } + else + prev->next = slow->next; + return head; +} diff --git a/leetcode/src/2125.c b/leetcode/src/2125.c new file mode 100644 index 0000000000..0f65b24dff --- /dev/null +++ b/leetcode/src/2125.c @@ -0,0 +1,30 @@ +int coundDevices(char* bankRow){ + int result = 0; + int bankRowSize = strlen(bankRow); + for(int i = 0; i < bankRowSize; i++){ + if (bankRow[i] == '1'){ + result++; + } + } + + return result; +} + +// Counting devices in each row +// Runtime: O(n*m), n-number of bank rows, m - max size of row. +// Space: O(1) +int numberOfBeams(char ** bank, int bankSize){ + int prevRowDevices = 0; + int result = 0; + for(int i = 0; i < bankSize; i++){ + int devices = coundDevices(bank[i]); + if (devices == 0){ + continue; + } + + result += devices * prevRowDevices; + prevRowDevices = devices; + } + + return result; +} diff --git a/leetcode/src/2130.c b/leetcode/src/2130.c new file mode 100644 index 0000000000..6dbacc1d20 --- /dev/null +++ b/leetcode/src/2130.c @@ -0,0 +1,30 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * struct ListNode *next; + * }; + */ + +int pairSum(struct ListNode* head) +{ + struct ListNode* dup = head; + int count = 0, i = 0, max = 0; + while (head != NULL) + { + count++; + head = head->next; + } + int* arr = malloc(count * sizeof(int)); + while (dup != NULL) + { + arr[i++] = dup->val; + dup = dup->next; + } + for (i = 0; i < count / 2; ++i) + { + if (arr[i] + arr[count - i - 1] > max) + max = arr[i] + arr[count - i - 1]; + } + return max; +} diff --git a/leetcode/src/2222.c b/leetcode/src/2222.c new file mode 100644 index 0000000000..795ff077d3 --- /dev/null +++ b/leetcode/src/2222.c @@ -0,0 +1,30 @@ +long numberOfWaysForChar(char * s, char c){ + long firstBuildingAppearNumber = 0; + long secondBuildingAppearNumber = 0; + long result = 0; + + int sLength = strlen(s); + for (int i = 0; i < sLength; i++){ + if (s[i] == c){ + result += secondBuildingAppearNumber; + + firstBuildingAppearNumber += 1; + continue; + } + + secondBuildingAppearNumber += firstBuildingAppearNumber; + } + + return result; + +} + +// numberOfWays returns the sum of number ways of selecting first building +// and the number of ways of selecting second building which gives us the +// number of ways of selecting three building such that no +// consecutive buildings are in the same category. +// Runtime: O(n) +// Space: O(n) +long long numberOfWays(char * s){ + return numberOfWaysForChar(s, '0') + numberOfWaysForChar(s, '1'); +} diff --git a/leetcode/src/223.c b/leetcode/src/223.c new file mode 100644 index 0000000000..6f424dc9e4 --- /dev/null +++ b/leetcode/src/223.c @@ -0,0 +1,24 @@ +#define min(X, Y) ((X) < (Y) ? (X) : (Y)) + +int intersectionSize(int p11, int p12, int p21, int p22){ + if (p11 >= p22 || p12 <= p21){ + return 0; + } + + if (p11 < p21){ + return min(p12 - p21, p22 - p21); + } + + return min(p22 - p11, p12 - p11); +} + +// Calculation area of the A, then area of the B then minus intersection of A and B +// Runtime: O(1) +// Space: O(1) +int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2){ + int areaA = (ay2 - ay1) * (ax2 - ax1); + int areaB = (by2 - by1) * (bx2 - bx1); + int areaInteresection = intersectionSize(ax1, ax2, bx1, bx2) * intersectionSize(ay1, ay2, by1, by2); + + return areaA + areaB - areaInteresection; +} diff --git a/leetcode/src/2256.c b/leetcode/src/2256.c new file mode 100644 index 0000000000..06e4d123a5 --- /dev/null +++ b/leetcode/src/2256.c @@ -0,0 +1,37 @@ +// Prefix sum. +// - Calculate whole nums sum. +// - Calculate currIndex sum. +// - Compare averages +// Runtime: O(n) +// Space: O(1) + +int minimumAverageDifference(int* nums, int numsSize){ + long numsSum = 0; + for (int i = 0; i < numsSize; i++){ + numsSum += nums[i]; + } + + long currSum = 0; + long minAverage = 9223372036854775807; // Long max + int minIndex = 0; + + for (int i = 0; i < numsSize; i++){ + currSum += nums[i]; + + int leftItemsNumber = (numsSize - i - 1); + long leftItemsNumberAverage = 0; + if (leftItemsNumber != 0){ + leftItemsNumberAverage = (numsSum - currSum) / leftItemsNumber; + } + + long currItemsNumberAverage = currSum / (i + 1); + long averageDiff = abs(currItemsNumberAverage - leftItemsNumberAverage); + + if (averageDiff < minAverage){ + minAverage = averageDiff; + minIndex = i; + } + } + + return minIndex; +} diff --git a/leetcode/src/2270.c b/leetcode/src/2270.c new file mode 100644 index 0000000000..b797f56770 --- /dev/null +++ b/leetcode/src/2270.c @@ -0,0 +1,21 @@ +// Prefix sum. +// Collect sum fromleft part and compare it with left sum. +// Runtime: O(n) +// Space: O(1) +int waysToSplitArray(int* nums, int numsSize){ + long sumNums = 0; + for (int i = 0; i < numsSize; i++){ + sumNums += nums[i]; + } + + long prefixSum = 0; + int result = 0; + for (int i = 0; i < numsSize - 1; i++){ + prefixSum += nums[i]; + if (prefixSum >= sumNums - prefixSum){ + result += 1; + } + } + + return result; +} diff --git a/leetcode/src/2279.c b/leetcode/src/2279.c new file mode 100644 index 0000000000..8dc05d981e --- /dev/null +++ b/leetcode/src/2279.c @@ -0,0 +1,29 @@ +int compare(const int* i, const int* j) +{ + return *i - *j; +} + +// Sorting. +// Runtime: O(n*log(n)) +// Space: O(n) +int maximumBags(int* capacity, int capacitySize, int* rocks, int rocksSize, int additionalRocks) { + int* capacityLeft = malloc(capacitySize * sizeof(int)); + for (int i = 0; i < capacitySize; i++) { + capacityLeft[i] = capacity[i] - rocks[i]; + } + + qsort(capacityLeft, capacitySize, sizeof (int), (int(*) (const void*, const void*)) compare); + + int bags = 0; + for (int i = 0; i < capacitySize; i++) { + if (additionalRocks < capacityLeft[i]){ + break; + } + + additionalRocks -= capacityLeft[i]; + bags++; + } + + free(capacityLeft); + return bags; +} diff --git a/leetcode/src/230.c b/leetcode/src/230.c new file mode 100644 index 0000000000..61fa0e77f8 --- /dev/null +++ b/leetcode/src/230.c @@ -0,0 +1,35 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * struct TreeNode *left; + * struct TreeNode *right; + * }; + */ + +struct TreeNode* findKthSmallest(struct TreeNode* node, int* k){ + if (node == NULL){ + return NULL; + } + + struct TreeNode* resultNode = findKthSmallest(node->left, k); + + if (resultNode != NULL){ + return resultNode; + } + + *k -= 1; + + if (*k == 0){ + return node; + } + + return findKthSmallest(node->right, k); +} + +// Depth-First Search +// Runtime: O(n) +// Space: O(1) +int kthSmallest(struct TreeNode* root, int k){ + return findKthSmallest(root, &k)->val; +} diff --git a/leetcode/src/2304.c b/leetcode/src/2304.c new file mode 100644 index 0000000000..d8cfcb2521 --- /dev/null +++ b/leetcode/src/2304.c @@ -0,0 +1,42 @@ +#define min(x,y)(((x)<(y))?(x):(y)) + +// DP up -> down. We are going down from gridline to gridline +// and collect the minumum cost path. +// Runtime : O(gridSize*gridColSize*gridColSize) +// Space: O(gridColSize) +int minPathCost(int** grid, int gridSize, int* gridColSize, int** moveCost, int moveCostSize, int* moveCostColSize){ + int* dp = (int*)calloc(gridColSize[0], sizeof(int)); + int* newDp = (int*)calloc(gridColSize[0], sizeof(int)); + + for(int i = 0; i < gridSize - 1; i++){ + int currGridColSize = gridColSize[i]; + for(int j = 0; j < currGridColSize; j++){ + newDp[j] = -1; + } + + for(int j = 0; j < currGridColSize; j++){ + int currGridItem = grid[i][j]; + for(int z = 0; z < currGridColSize; z++){ + int currMoveCost = dp[j] + moveCost[currGridItem][z] + currGridItem; + + newDp[z] = (newDp[z] == -1) ? currMoveCost : min(newDp[z], currMoveCost); + } + } + + for(int j = 0; j < currGridColSize; j++){ + dp[j] = newDp[j]; + } + } + + // Find minimum value. + int minValue = dp[0] + grid[gridSize - 1][0]; + for(int j = 1; j < gridColSize[0]; j++){ + minValue = min(minValue, dp[j] + grid[gridSize - 1][j]); + } + + // free resources + free(dp); + free(newDp); + + return minValue; +} diff --git a/leetcode/src/231.c b/leetcode/src/231.c index a2d3b1e7c6..81ea2b0454 100644 --- a/leetcode/src/231.c +++ b/leetcode/src/231.c @@ -1,7 +1,6 @@ -bool isPowerOfTwo(int n) -{ - if (!n) - return false; - while (n % 2 == 0) n /= 2; - return n == 1; -} \ No newline at end of file +// Without loops/recursion. +// Runtime: O(1) +// Space: O(1) +bool isPowerOfTwo(int n){ + return (n > 0) && ((n & (n - 1)) == 0); +} diff --git a/leetcode/src/236.c b/leetcode/src/236.c new file mode 100644 index 0000000000..71235c4e64 --- /dev/null +++ b/leetcode/src/236.c @@ -0,0 +1,82 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * struct TreeNode *left; + * struct TreeNode *right; + * }; + */ + +// The list for TreeNodes. +struct ListItem { + struct TreeNode* node; // TreeNode pointer + struct ListItem* next; // Pointer to the next ListItem +}; + +bool findTargetPath(struct TreeNode* node, struct TreeNode* target, struct ListItem* path){ + if (node == NULL){ + return false; + } + + struct ListItem* pathItem = malloc(sizeof(struct ListItem)); + pathItem->node = node; + pathItem->next = NULL; + path->next = pathItem; + + if (node->val == target->val){ + return true; + } + + if (findTargetPath(node->left, target, pathItem)){ + return true; + } + + if (findTargetPath(node->right, target, pathItem)){ + return true; + } + + path->next = NULL; + free(pathItem); + return false; +} + +void freeList(struct ListItem* target){ + if (target->next != NULL){ + freeList(target->next); + } + + free(target); +} + + +// Find full path for p and q. +// Find the longest common path in paths. + +// Runtime: O(n) +// Space: O(n) +struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) { + struct ListItem* pPath = malloc(sizeof(struct ListItem)); + struct ListItem* qPath = malloc(sizeof(struct ListItem)); + + findTargetPath(root, p, pPath); + findTargetPath(root, q, qPath); + + struct TreeNode* lowestTreeNode = NULL; + struct ListItem* pPathCursor = pPath->next; + struct ListItem* qPathCursor = qPath->next; + while(pPathCursor != NULL && qPathCursor != NULL) { + if (pPathCursor->node->val == qPathCursor->node->val){ + lowestTreeNode = pPathCursor->node; + pPathCursor = pPathCursor->next; + qPathCursor = qPathCursor->next; + continue; + } + + break; + } + + freeList(pPath); + freeList(qPath); + + return lowestTreeNode; +} diff --git a/leetcode/src/2482.c b/leetcode/src/2482.c new file mode 100644 index 0000000000..df9f702dec --- /dev/null +++ b/leetcode/src/2482.c @@ -0,0 +1,42 @@ +/** + * Return an array of arrays of size *returnSize. + * The sizes of the arrays are returned as *returnColumnSizes array. + * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free(). + */ + +// Calculating ones on each row and column. +// Runtime: O(n * m) +// Space: O(n + m) +int** onesMinusZeros(int** grid, int gridSize, int* gridColSize, int* returnSize, int** returnColumnSizes){ + int n = gridSize; + int m = gridColSize[0]; + + int** result = malloc(gridSize * sizeof(int*)); + for (int i = 0; i < n; i++){ + result[i] = malloc(m * sizeof(int)); + } + + int* onesRows = calloc(n, sizeof(int)); + int* onesCols = calloc(m, sizeof(int)); + for (int i = 0; i < n; i++){ + for (int j = 0; j < m; j++){ + if (grid[i][j] == 1){ + onesRows[i] += 1; + onesCols[j] += 1; + } + } + } + + for (int i = 0; i < gridSize; i++){ + for (int j = 0; j < gridColSize[i]; j++){ + result[i][j] = onesRows[i] + onesCols[j] - (m - onesRows[i]) - (n - onesCols[j]); + } + } + + free(onesRows); + free(onesCols); + + *returnSize = gridSize; + *returnColumnSizes = gridColSize; + return result; +} diff --git a/leetcode/src/2501.c b/leetcode/src/2501.c new file mode 100644 index 0000000000..87cfa2702b --- /dev/null +++ b/leetcode/src/2501.c @@ -0,0 +1,52 @@ +#define max(a,b) (((a)>(b))?(a):(b)) + +int longestSquareStreakDp(int* numsSet, int numsSetSize, int* dp, long num){ + if (dp[num] != 0){ + return dp[num]; + } + + long numSquare = num * num; + + dp[num] = 1; + if (numSquare <= numsSetSize && numsSet[numSquare] == 1){ + dp[num] += longestSquareStreakDp(numsSet, numsSetSize, dp, numSquare); + } + + return dp[num]; +} + +// Dynamic approach. Up -> down. +// Runtime: O(numsSize) +// Space: O(max(nums)) +int longestSquareStreak(int* nums, int numsSize){ + // Find nums maximum + int numMax = 0; + for(int i = 0; i < numsSize; i++){ + numMax = max(numMax, nums[i]); + } + + int* numsSet = calloc(numMax + 1, sizeof(int)); + int* dp = calloc(numMax + 1, sizeof(int)); + + // Init set of nums + for(int i = 0; i < numsSize; i++){ + numsSet[nums[i]] = 1; + } + + // Find result + int result = -1; + for(int i = 0; i < numsSize; i++){ + long num = nums[i]; + long numSquare = num * num; + + if (numSquare > numMax || numsSet[numSquare] == 0){ + continue; + } + + result = max(result, 1 + longestSquareStreakDp(numsSet, numMax, dp, numSquare)); + } + + free(dp); + free(numsSet); + return result; +} diff --git a/leetcode/src/274.c b/leetcode/src/274.c new file mode 100644 index 0000000000..e233fd04f0 --- /dev/null +++ b/leetcode/src/274.c @@ -0,0 +1,21 @@ +int diff(const int* i, const int* j) + +{ + return *i - *j; +} + + +// Sorting. +// Runtime: O(n*log(n)) +// Space: O(1) +int hIndex(int* citations, int citationsSize){ + qsort(citations, citationsSize, sizeof(int), (int(*) (const void*, const void*)) diff); + + for(int i = 0; i < citationsSize; i++){ + if (citations[citationsSize - 1 - i] <= i){ + return i; + } + } + + return citationsSize; +} diff --git a/leetcode/src/32.c b/leetcode/src/32.c new file mode 100644 index 0000000000..ce05249af9 --- /dev/null +++ b/leetcode/src/32.c @@ -0,0 +1,60 @@ +#define max(x,y)(((x)>(y))?(x):(y)) + +const int notCalculated = -2; +const int notValid = -1; + +int getEndValidIndexFromDp(int* dp, char* s, int index, int lenS){ + if (index >= lenS){ + return notValid; + } + + if (dp[index] == notCalculated){ + dp[index] = getEndValidIndex(dp, s, index, lenS); + } + + return dp[index]; +} + +int getEndValidIndex(int* dp, char* s, int index, int lenS){ + if (s[index] == '('){ + if (index + 1 >= lenS){ + return notValid; + } + + if (s[index + 1] == ')'){ + return max(index + 1, getEndValidIndexFromDp(dp, s, index + 2, lenS)); + } + + int nextEndValidIndex = getEndValidIndexFromDp(dp, s, index + 1, lenS); + if (nextEndValidIndex == notValid || nextEndValidIndex + 1 >= lenS || s[nextEndValidIndex + 1] != ')') { + return notValid; + } + + return max(nextEndValidIndex + 1, getEndValidIndexFromDp(dp, s, nextEndValidIndex + 2, lenS)); + } + + return notValid; +} + +// Dynamic Programming. UP -> down approach. +// Runtime: O(n) +// Space: O(n) +int longestValidParentheses(char * s){ + int lenS = strlen(s); + if (lenS == 0){ + return 0; + } + + int* dp = malloc(lenS * sizeof(int)); + for(int i = 0; i < lenS; i++){ + dp[i] = notCalculated; + } + + int result = 0; + for(int i = 0; i < lenS; i++){ + result = max(result, getEndValidIndexFromDp(dp, s, i, lenS) - i + 1); + } + + free(dp); + return result; +} diff --git a/leetcode/src/37.c b/leetcode/src/37.c new file mode 100644 index 0000000000..7d8cae115e --- /dev/null +++ b/leetcode/src/37.c @@ -0,0 +1,88 @@ +int** initSet(int size){ + int** result = (int**) malloc(size * sizeof(int*)); + for (int i = 0; i < size; i++) { + result[i] = (int*)calloc(size, sizeof(int)); + } + + return result; +} + +// Returns the id of triplet which the point (i, j) belongs to +int getTripletId(int i, int j){ + return (i / 3) * 3 + (j / 3); +} + +// Recursive function which populates sudoku board. +bool sudokuSolver(int startI, int startJ, char** board, int boardSize, int* boardColSize, int** horizontalsSets, int** verticalsSets, int** tripletsSets){ + for (int i = startI; i < boardSize; i++) { + for (int j = startJ; j < boardColSize[i]; j++) { + if (board[i][j] != '.'){ + continue; + } + + // Find the sets of the current point (i, j) + int* horizontalSet = horizontalsSets[i]; + int* verticalSet = verticalsSets[j]; + int* tripletsSet = tripletsSets[getTripletId(i, j)]; + + for (int z = 1; z < 10; z++) { + if (horizontalSet[z] || verticalSet[z] || tripletsSet[z]){ + continue; + } + + // If the z doesn't belong to occupations sets, we check this value to be in place + horizontalSet[z] = 1; + verticalSet[z] = 1; + tripletsSet[z] = 1; + + if (sudokuSolver(i, j + 1, board, boardSize, boardColSize, horizontalsSets, verticalsSets, tripletsSets)){ + board[i][j] = z + '0'; + return true; + } + + horizontalSet[z] = 0; + verticalSet[z] = 0; + tripletsSet[z] = 0; + } + + // We tried all possible values in range 1-10. No variants - returns false; + return false; + } + + // startJ to begin of the row. + startJ = 0; + } + + // Reach it when the end of the board - then all previous values are setup correctly. + return true; +} + +// Use backtracking +void solveSudoku(char** board, int boardSize, int* boardColSize){ + // Declare sets for cheking occupation of numbers by horizontals, verticals lines and triplets. + int** horizontalsSets = initSet(boardSize + 1); + int** verticalsSets = initSet(boardSize + 1); + int** tripletsSets = initSet(getTripletId(boardSize + 1, boardSize + 1)); + + // Populate sets with values from the board. + for (int i = 0; i < boardSize; i++) { + for (int j = 0; j < boardColSize[i]; j++) { + if (board[i][j] == '.'){ + continue; + } + + int value = board[i][j] - '0'; + horizontalsSets[i][value] = 1; + verticalsSets[j][value] = 1; + tripletsSets[getTripletId(i, j)][value] = 1; + } + } + + // Solving + sudokuSolver(0, 0, board, boardSize, boardColSize, horizontalsSets, verticalsSets, tripletsSets); + + // Free resources + free(horizontalsSets); + free(verticalsSets); + free(tripletsSets); +} diff --git a/leetcode/src/42.c b/leetcode/src/42.c new file mode 100644 index 0000000000..7c49239740 --- /dev/null +++ b/leetcode/src/42.c @@ -0,0 +1,27 @@ +#define max(x,y)(((x)>(y))?(x):(y)) +#define min(x,y)(((x)<(y))?(x):(y)) + +// Max stack. Runtime: O(n), Space: O(n) +// Algorithm description: +// - Calculate the stack of maximums from right board. +// - For each index find left maximum and right maximum of height +// - The each index if heights could place nor greater than minimum of left and right max minus curr height +// - Sum all index in result +int trap(int* height, int heightSize){ + int* rightMaxStack = malloc(heightSize * sizeof(int)); + rightMaxStack[heightSize - 1] = height[heightSize - 1]; + + for (int i = heightSize - 2; i >= 0; i--){ + rightMaxStack[i] = max(rightMaxStack[i + 1], height[i]); + } + + int leftMax = 0; + int result = 0; + for (int i = 0; i < heightSize; i++){ + leftMax = max(leftMax, height[i]); + result += max(0, min(leftMax, rightMaxStack[i]) - height[i]); + } + + free(rightMaxStack); + return result; +} diff --git a/leetcode/src/434.c b/leetcode/src/434.c new file mode 100644 index 0000000000..a2d05d5cad --- /dev/null +++ b/leetcode/src/434.c @@ -0,0 +1,20 @@ +// Given a string s, returns the number of segments in the string. +int countSegments(char * s){ + int sLen = strlen(s); + int prevSpace = 1; + int result = 0; + char currChar; + + for (int i = 0; i < sLen; i++){ + currChar = s[i]; + + //A string of whitespaces will only be counted once as the condition below is only true when we transition from whitespace to non-whitespace. + //Since we start with assumed whitespace (prevSpace = 1), initial whitespaces are handled as well, if any + if (s[i] != ' ' && prevSpace) { + result++; + } + prevSpace = (currChar == ' '); + } + + return result; +} diff --git a/leetcode/src/45.c b/leetcode/src/45.c new file mode 100644 index 0000000000..4deaab4594 --- /dev/null +++ b/leetcode/src/45.c @@ -0,0 +1,50 @@ +// Breadth-first search, imitation. +// Runtime: O(n) +// Space: O(n) +int jump(int* nums, int numsSize) { + if (numsSize == 1) { + return 0; + } + + int step = 1; + int* visitedCells = calloc(numsSize, sizeof(int)); + + int* queue = malloc(numsSize * sizeof(int)); + queue[0] = 0; + int queueLength = 1; + + while (queueLength > 0){ + int* nextQueue = malloc(numsSize * sizeof(int)); + int nextQueueLength = 0; + + for (int i = 0; i < queueLength; i++) { + int cell = queue[i]; + int jump = nums[cell]; + + if (cell + jump >= numsSize - 1) { + free(visitedCells); + free(queue); + free(nextQueue); + return step; + } + + // populate next queue wave for searching + for (int nextCell = cell; nextCell <= cell + jump; nextCell++) { + if (visitedCells[nextCell] == 0){ + nextQueue[nextQueueLength++] = nextCell; + visitedCells[nextCell] = 1; + } + } + } + + step++; + free(queue); + + queue = nextQueue; + queueLength = nextQueueLength; + } + + free(visitedCells); + free(queue); + return -1; +} diff --git a/leetcode/src/485.c b/leetcode/src/485.c new file mode 100644 index 0000000000..a288761590 --- /dev/null +++ b/leetcode/src/485.c @@ -0,0 +1,23 @@ +int max(a,b){ + if(a>b) + return a; + else + return b; +} + +int findMaxConsecutiveOnes(int* nums, int numsSize){ + int count = 0; + int result = 0; + + for (int i = 0; i < numsSize; i++) + { + if (nums[i] == 0) + count = 0; + else + { + count++; + result = max(result, count); + } + } + return result; +} diff --git a/leetcode/src/5.c b/leetcode/src/5.c new file mode 100644 index 0000000000..e54bf598da --- /dev/null +++ b/leetcode/src/5.c @@ -0,0 +1,52 @@ +/** + * Find longest palindrome by traversing the string and checking how + * long palindrome can be constructed from each element by going left and right. + * Checking palindromes of types '..aa..' and '..bab..' + */ + +#include /// for allocating new string via malloc() +#include /// for copying the contents of the string via strncpy() + +char * longestPalindrome(char * s) { + int si_max = 0, ei_max = 0, sz_max = 0, sz, i, delta_i; + char ch, *s_longest; + if (s[1] == '\0') return s; + + for (ch = s[1], i = 1; ch != '\0'; ch = s[++i]) { + if (s[i - 1] == ch) { + sz = 2; + delta_i = 1; + while (i - 1 - delta_i >= 0 && s[i + delta_i] != '\0' && s[i - 1 - delta_i] == s[i + delta_i]) { + sz += 2; + delta_i += 1; + } + if (sz > sz_max) { + sz_max = sz; + si_max = i - 1 - delta_i + 1; + ei_max = i + delta_i - 1; + } + } + } + + for (ch = s[0], i = 1; ch != '\0'; ch = s[++i]) { + sz = 1; + delta_i = 1; + while (i - delta_i >= 0 && s[i + delta_i] != '\0' && s[i - delta_i] == s[i + delta_i]) { + sz += 2; + delta_i += 1; + } + if (sz > sz_max) { + sz_max = sz; + si_max = i - delta_i + 1; + ei_max = i + delta_i - 1; + } + } + + if ((s_longest = (char *) malloc(sizeof(s))) == NULL) { + return NULL; + } + strncpy(s_longest, s + si_max, sz_max); + s_longest[sz_max] = '\0'; + + return s_longest; +} diff --git a/leetcode/src/50.c b/leetcode/src/50.c new file mode 100644 index 0000000000..1e539e0421 --- /dev/null +++ b/leetcode/src/50.c @@ -0,0 +1,39 @@ +double powPositive(double x, int n){ + if (n == 1){ + return x; + } + + double val = powPositive(x, n / 2); + double result = val * val; + + // if n is odd + if (n & 1 > 0){ + result *= x; + } + + return result; +} + +// Divide and conquer. +// Runtime: O(log(n)) +// Space: O(1) +double myPow(double x, int n){ + if (n == 0){ + return 1; + } + + const int LOWER_BOUND = -2147483648; + + // n is the minimum int, couldn't be converted in -n because maximum is 2147483647. + // this case we use (1 / pow(x, -(n + 1))) * n + if (n == LOWER_BOUND){ + return 1 / (powPositive(x, -(n + 1)) * x); + } + + // 1 / pow(x, -(n + 1)) + if (n < 0){ + return 1 / powPositive(x, -n); + } + + return powPositive(x, n); +} diff --git a/leetcode/src/540.c b/leetcode/src/540.c new file mode 100644 index 0000000000..094bb132b0 --- /dev/null +++ b/leetcode/src/540.c @@ -0,0 +1,32 @@ +/** + * Time complexity: O(log n). + * Space complexity: O(1). + * @details The array has a pattern that consists in of the existing sub-array to + * the left of the non-repeating number will satisfy the condition that + * each pair of repeated elements have their first occurrence at the even index + * and their second occurrence at the odd index, and that the sub-array to + * the right of the non-repeating number will satisfy the condition that + * each pair of repeated elements have their first occurrence at the odd index + * and their second occurrence at the even index. With this pattern in mind, + * we can solve the problem using binary search. + */ + +int singleNonDuplicate(int* nums, int numsSize) { + int left = 0, right = numsSize - 1; + while (left < right) { + int mid = (right + left) / 2; + if (mid % 2 == 0) { + if (nums[mid] == nums[mid + 1]) + left = mid + 2; + else + right = mid; + } + else { + if (nums[mid] == nums[mid - 1]) + left = mid + 1; + else + right = mid - 1; + } + } + return nums[left]; +} diff --git a/leetcode/src/567.c b/leetcode/src/567.c new file mode 100644 index 0000000000..268579a03d --- /dev/null +++ b/leetcode/src/567.c @@ -0,0 +1,67 @@ +const int EnglishLettersNumber = 26; + +void countCharsForStringSlice(int* charsCounter, char* s, int length, int sign) { + for (int i = 0; i < length; i++) { + + charsCounter[s[i] - 'a'] += sign; + } +} + +// Sliding window +// Calculate number of chars in the current slide. +// Runtime: O(n) +// Space: O(1) - only number of english lowercase letters. +bool checkInclusion(char* s1, char* s2) { + int lengthS1 = strlen(s1); + int lengthS2 = strlen(s2); + + if (lengthS1 > lengthS2) { + + return false; + } + + int* charsCounter = calloc(EnglishLettersNumber, sizeof(int)); + + // We keep counters of s1 with '-' sign. It has to be offset by s2 chars + countCharsForStringSlice(charsCounter, s1, lengthS1, -1); + countCharsForStringSlice(charsCounter, s2, lengthS1, 1); + + int diffChars = 0; + for (int i = 0; i < EnglishLettersNumber; i++) { + if (charsCounter[i] != 0) { + diffChars++; + } + } + + if (diffChars == 0) { + return true; + } + + for (int i = 0; i < lengthS2 - lengthS1; i++) { + int charNumberLeft = s2[i] - 'a'; + int charNumberRight = s2[i + lengthS1] - 'a'; + + charsCounter[charNumberLeft] -= 1; + if (charsCounter[charNumberLeft] == 0) { + diffChars -= 1; + } + else if (charsCounter[charNumberLeft] == -1) { + diffChars += 1; + } + + charsCounter[charNumberRight] += 1; + if (charsCounter[charNumberRight] == 0) { + diffChars -= 1; + } + else if (charsCounter[charNumberRight] == 1) { + diffChars += 1; + } + + if (diffChars == 0) { + return true; + } + } + + free(charsCounter); + return false; +} diff --git a/leetcode/src/62.c b/leetcode/src/62.c new file mode 100644 index 0000000000..b2ac88d687 --- /dev/null +++ b/leetcode/src/62.c @@ -0,0 +1,39 @@ +// Dynamic programming can be applied here, because every solved sub-problem has +// an optimal sub-solution +// Searching backwards from end to start, we can incrementally calculate number +// of paths to destination. i.e. start from bottom-right, and calculate +// leftwards (lowest row should all be 1). then go to second-last-row, rightmost +// column, and calculate leftwards the last cell to be calculated is the start +// location (0, 0). The iteration ordering is intentional: the inner loop +// iterates the contents of each vector, the outer loop iterates each vector. +// This is more cache-friendly. + +// Example below, calculated from right-to-left, bottom-to-top. +// 7 by 3 grid +// 28 21 15 10 6 3 1 +// 7 6 5 4 3 2 1 +// 1 1 1 1 1 1 1 + +int uniquePaths(int m, int n) +{ + int dp[m][n]; + + for (int column = 0; column < n; column++) + { + dp[0][column] = 1; + } + + for (int row = 1; row < m; row++) + { + dp[row][0] = 1; + } + + for (int row = 1; row < m; row++) + { + for (int column = 1; column < n; column++) + { + dp[row][column] = dp[row - 1][column] + dp[row][column - 1]; + } + } + return dp[m - 1][n - 1]; +} diff --git a/leetcode/src/63.c b/leetcode/src/63.c new file mode 100644 index 0000000000..d26106fd90 --- /dev/null +++ b/leetcode/src/63.c @@ -0,0 +1,39 @@ +/* +I walk through the grids and record the path numbers at the +same time. +By using a 2D array called paths, it will add up possible so +urce path and save the number. +Noted that: +if the destination has obstacle, we can't reach it +the first grid (paths[0][0]) always set as 1 our previous +path source is either from top or left border of grid has +different condition +*/ + +int uniquePathsWithObstacles(int** obstacleGrid, int obstacleGridSize, + int* obstacleGridColSize) +{ + if (obstacleGrid[obstacleGridSize - 1][*obstacleGridColSize - 1] == 1) + { + return 0; + } + int paths[obstacleGridSize][*obstacleGridColSize]; + for (int i = 0; i < obstacleGridSize; i++) + { + for (int j = 0; j < *obstacleGridColSize; j++) + { + if (obstacleGrid[i][j]) + { + paths[i][j] = 0; + } + else + { + paths[i][j] = (i == 0 && j == 0) + ? 1 + : ((i == 0 ? 0 : paths[i - 1][j]) + + (j == 0 ? 0 : paths[i][j - 1])); + } + } + } + return paths[obstacleGridSize - 1][*obstacleGridColSize - 1]; +} diff --git a/leetcode/src/669.c b/leetcode/src/669.c new file mode 100644 index 0000000000..f8842a3463 --- /dev/null +++ b/leetcode/src/669.c @@ -0,0 +1,30 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * struct TreeNode *left; + * struct TreeNode *right; + * }; + */ + + +// Depth-First Search +// Runtime: O(n) +// Space: O(1) +struct TreeNode* trimBST(struct TreeNode* root, int low, int high){ + if (root == NULL){ + return NULL; + } + + if (root->val > high){ + return trimBST(root->left, low, high); + } + + if (root->val < low){ + return trimBST(root->right, low, high); + } + + root->left = trimBST(root->left, low, high); + root->right = trimBST(root->right, low, high); + return root; +} diff --git a/leetcode/src/684.c b/leetcode/src/684.c new file mode 100644 index 0000000000..e5de7faa1e --- /dev/null +++ b/leetcode/src/684.c @@ -0,0 +1,49 @@ +/** + * Note: The returned array must be malloced, assume caller calls free(). + */ +int find(int* sets, int index){ + while (sets[index] != index){ + index = sets[index]; + } + + return index; +} + +void unionSet(int* sets, int i1, int i2){ + int i1Parent = find(sets, i1); + int i2Parent = find(sets, i2); + + sets[i1Parent] = i2Parent; +} + +// Union find +// Runtime: O(n) +// Space: O(n) +int* findRedundantConnection(int** edges, int edgesSize, int* edgesColSize, int* returnSize){ + int setsSize = edgesSize + 1; + int* sets = malloc(setsSize * sizeof(int)); + for (int i = 0; i < setsSize; i++){ + sets[i] = i; + } + + int* result = malloc(2 * sizeof(int)); + *returnSize = 2; + + for (int i = 0; i < edgesSize; i++){ + int* edge = edges[i]; + + int i0Parent = find(sets, edge[0]); + int i1Parent = find(sets, edge[1]); + + if (i0Parent == i1Parent){ + result[0] = edge[0]; + result[1] = edge[1]; + continue; + } + + unionSet(sets, i0Parent, i1Parent); + } + + free(sets); + return result; +} diff --git a/leetcode/src/69.c b/leetcode/src/69.c new file mode 100644 index 0000000000..63c0d02519 --- /dev/null +++ b/leetcode/src/69.c @@ -0,0 +1,23 @@ +//using the binary search method is one of the efficient ones for this problem statement. +int mySqrt(int x){ +int start=0; + int end=x; + long long int ans=0; + while(start <= end){ + long long int mid=(start+end)/2; + long long int val=mid*mid; + if( val == x){ + return mid; + } +//if mid is less than the square root of the number(x) store the value of mid in ans. + if( val < x){ + ans = mid; + start = mid+1; + } +//if mid is greater than the square root of the number(x) then ssign the value mid-1 to end. + if( val > x){ + end = mid-1; + } + } + return ans; +} diff --git a/leetcode/src/75.c b/leetcode/src/75.c new file mode 100644 index 0000000000..2cf402f2c8 --- /dev/null +++ b/leetcode/src/75.c @@ -0,0 +1,24 @@ +void swap(int *x, int *y){ + if (x==y) + return; + *x = *x + *y; + *y= *x - *y; + *x= *x - *y; +} + +void sortColors(int* arr, int n){ + int start=0, mid=0, end=n-1; + while(mid<=end){ + if(arr[mid]==1) + mid++; + else if(arr[mid]==0){ + swap(&arr[mid],&arr[start]); + mid++; + start++; + } + else{ + swap(&arr[mid],&arr[end]); + end--; + } + } +} diff --git a/leetcode/src/79.c b/leetcode/src/79.c new file mode 100644 index 0000000000..3ac9d11fbc --- /dev/null +++ b/leetcode/src/79.c @@ -0,0 +1,60 @@ +int getPointKey(int i, int j, int boardSize, int boardColSize){ + return boardSize * boardColSize * i + j; +} + +const int directionsSize = 4; +const int directions[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; + +bool exitsWord(int i, int j, char** board, int boardSize, int* boardColSize, int wordIndex, char* word, int* vistedPointSet){ + if (board[i][j] != word[wordIndex]){ + return false; + } + + if (wordIndex == strlen(word) - 1){ + return true; + } + + for (int k = 0; k < directionsSize; k++){ + int nextI = i + directions[k][0]; + int nextJ = j + directions[k][1]; + + if (nextI < 0 || nextI >= boardSize || nextJ < 0 || nextJ >= boardColSize[i]){ + continue; + } + + int key = getPointKey(nextI, nextJ, boardSize, boardColSize[i]); + if (vistedPointSet[key] == 1){ + continue; + } + + vistedPointSet[key] = 1; + if (exitsWord(nextI, nextJ, board, boardSize, boardColSize, wordIndex + 1, word, vistedPointSet)){ + return true; + } + + vistedPointSet[key] = 0; + } + + return false; +} + + +// Use backtracking. +// Runtime: Runtime: O(n*m*4^len(word)) +bool exist(char** board, int boardSize, int* boardColSize, char* word){ + int* vistedPointSet = (int*) calloc(getPointKey(boardSize, boardColSize[0], boardSize, boardColSize[0]), sizeof(int)); + + for (int i = 0; i < boardSize; i++){ + for (int j = 0; j < boardColSize[i]; j++){ + int key = getPointKey(i, j, boardSize, boardColSize[i]); + vistedPointSet[key] = 1; + if (exitsWord(i, j, board, boardSize, boardColSize, 0, word, vistedPointSet)){ + return true; + }; + + vistedPointSet[key] = 0; + } + } + + return false; +} diff --git a/leetcode/src/807.c b/leetcode/src/807.c new file mode 100644 index 0000000000..1f51bdd753 --- /dev/null +++ b/leetcode/src/807.c @@ -0,0 +1,32 @@ +#define min(a,b) (((a)<(b))?(a):(b)) +#define max(a,b) (((a)>(b))?(a):(b)) + +// Collect maxes on each row and each column. +// Runtime: O(n * n) +// Space: O(n) +int maxIncreaseKeepingSkyline(int** grid, int gridSize, int* gridColSize){ + int* rowsMaxs = calloc(gridSize, sizeof(int)); + int* colsMaxs = calloc(gridSize, sizeof(int)); + + // Find max of each row and column + for(int i = 0; i < gridSize; i++){ + for (int j = 0; j < gridSize; j++){ + rowsMaxs[i] = max(rowsMaxs[i], grid[i][j]); + colsMaxs[j] = max(colsMaxs[j], grid[i][j]); + } + } + + int result = 0; + for(int i = 0; i < gridSize; i++){ + for (int j = 0; j < gridSize; j++){ + int rowMax = rowsMaxs[i]; + int colMax = colsMaxs[j]; + result += min(rowMax - grid[i][j], colMax - grid[i][j]); + } + } + + free(rowsMaxs); + free(colsMaxs); + + return result; +} diff --git a/leetcode/src/841.c b/leetcode/src/841.c new file mode 100644 index 0000000000..cae224887e --- /dev/null +++ b/leetcode/src/841.c @@ -0,0 +1,27 @@ +void visitRooms(int key, int** rooms, int roomsSize, int* roomsColSize, int* visitedRooms){ + if (visitedRooms[key] == 1){ + return; + } + + visitedRooms[key] = 1; + for (int i = 0; i < roomsColSize[key]; i++){ + visitRooms(rooms[key][i], rooms, roomsSize, roomsColSize, visitedRooms); + } +} + +// Depth-first search +// Runtime: O(n) +// Space: O(n) +bool canVisitAllRooms(int** rooms, int roomsSize, int* roomsColSize){ + int* visitedRooms = calloc(roomsSize, sizeof(int)); + visitRooms(0, rooms, roomsSize, roomsColSize, visitedRooms); + + int visitedRoomsNumber = 0; + for (int i = 0; i < roomsSize; i++){ + if (visitedRooms[i] == 1){ + visitedRoomsNumber++; + } + } + + return visitedRoomsNumber == roomsSize; +} diff --git a/leetcode/src/901.c b/leetcode/src/901.c new file mode 100644 index 0000000000..efa712b69c --- /dev/null +++ b/leetcode/src/901.c @@ -0,0 +1,68 @@ +// Use monotonic stack. +// Keep the stack of monotonically increasing price and index. + +// Runtime: O(n) +// Space: O(n) +typedef struct stack{ + int price; + int index; + struct stack* previous; +} Stack; + + +typedef struct { + int index; + Stack* stackPointer; + Stack* sentry; +} StockSpanner; + + +StockSpanner* stockSpannerCreate() { + Stack* sentry = (Stack *)malloc(sizeof(Stack)); + StockSpanner* result = (StockSpanner *)malloc(sizeof(StockSpanner)); + result->index = 0; + result->sentry = sentry; + result->stackPointer = sentry; + return result; +} + +int stockSpannerNext(StockSpanner* obj, int price) { + while(obj->stackPointer != obj->sentry && obj->stackPointer->price <= price){ + Stack* currStackPointer = obj->stackPointer; + obj->stackPointer = obj->stackPointer->previous; + free(currStackPointer); + } + + obj->index += 1; + int result = obj->index; + if (obj->stackPointer != obj->sentry){ + result -= obj->stackPointer->index; + } + + Stack* newStackItem = (Stack *)malloc(sizeof(Stack)); + newStackItem->index = obj->index; + newStackItem->price = price; + newStackItem->previous = obj->stackPointer; + obj->stackPointer = newStackItem; + + return result; +} + +void stockSpannerFree(StockSpanner* obj) { + while(obj->stackPointer != obj->sentry){ + Stack* currStackPointer = obj->stackPointer; + obj->stackPointer = obj->stackPointer->previous; + free(currStackPointer); + } + + free(obj->sentry); + free(obj); +} + +/** + * Your StockSpanner struct will be instantiated and called as such: + * StockSpanner* obj = stockSpannerCreate(); + * int param_1 = stockSpannerNext(obj, price); + + * stockSpannerFree(obj); + */ diff --git a/leetcode/src/931.c b/leetcode/src/931.c new file mode 100644 index 0000000000..b257c8c33e --- /dev/null +++ b/leetcode/src/931.c @@ -0,0 +1,37 @@ +#define min(a,b) (((a)<(b))?(a):(b)) + +// Dynamic programming. +// Runtime O(n*n) +// Space O(n) +int minFallingPathSum(int** matrix, int matrixSize, int* matrixColSize){ + int* dp = calloc(matrixSize, sizeof(int)); + + for (int i = 0; i < matrixSize; i++){ + int* nextDp = calloc(matrixSize, sizeof(int)); + + for (int j = 0; j < matrixSize; j++){ + nextDp[j] = dp[j] + matrix[i][j]; + + // If not the first column - try to find minimum in prev column + if(j > 0){ + nextDp[j] = min(nextDp[j], dp[j - 1] + matrix[i][j]); + } + + // If not the last column - try to find minimum in next column + if (j < matrixSize - 1){ + nextDp[j] = min(nextDp[j], dp[j + 1] + matrix[i][j]); + } + } + + free(dp); + dp = nextDp; + } + + int result = dp[0]; + for (int j = 1; j < matrixSize; j++){ + result = min(result, dp[j]); + } + + free(dp); + return result; +} diff --git a/leetcode/src/953.c b/leetcode/src/953.c new file mode 100644 index 0000000000..cb13d85d1e --- /dev/null +++ b/leetcode/src/953.c @@ -0,0 +1,40 @@ +#define min(x, y) (((x) < (y)) ? (x) : (y)) + +bool isWordLess(char* word1, char* word2, int* charOrder){ + int word1Length = strlen(word1); + int word2Length = strlen(word2); + + for(int i = 0; i < min(word1Length, word2Length); i++) { + int charWordsDiff = (charOrder[word1[i] - 'a'] - charOrder[word2[i] - 'a']); + + if (charWordsDiff < 0){ + return true; + } + + if (charWordsDiff > 0){ + return false; + } + } + + return word1Length <= word2Length; +} + +// Keep array-hashtable of order letters. +// Runtime: O(n) +// Space: O(1) +bool isAlienSorted(char ** words, int wordsSize, char * order){ + const int lowerCaseLettersNumber = 26; + int charorder[lowerCaseLettersNumber]; + + for(int i = 0; i < lowerCaseLettersNumber; i++) { + charorder[order[i] - 'a'] = i; + } + + for(int i = 0; i < wordsSize - 1; i++) { + if (!isWordLess(words[i], words[i + 1], charorder)){ + return false; + } + } + + return true; +} diff --git a/leetcode/src/979.c b/leetcode/src/979.c new file mode 100644 index 0000000000..b6ad8b1b95 --- /dev/null +++ b/leetcode/src/979.c @@ -0,0 +1,47 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * struct TreeNode *left; + * struct TreeNode *right; + * }; + */ + +struct NodeDistributeInfo { + int distributeMoves; + int distributeExcess; +}; + +struct NodeDistributeInfo* getDisturb(struct TreeNode* node) { + struct NodeDistributeInfo* result = malloc(sizeof(struct NodeDistributeInfo)); + + if (node == NULL) { + result->distributeMoves = 0; + result->distributeExcess = 1; + return result; + } + + struct NodeDistributeInfo* leftDistribute = getDisturb(node->left); + struct NodeDistributeInfo* rightDistribute = getDisturb(node->right); + + int coinsToLeft = 1 - leftDistribute->distributeExcess; + int coinsToRight = 1 - rightDistribute->distributeExcess; + + // Calculate moves as excess and depth between left and right subtrees. + result->distributeMoves = leftDistribute->distributeMoves + rightDistribute->distributeMoves + abs(coinsToLeft) + abs(coinsToRight); + result->distributeExcess = node->val - coinsToLeft - coinsToRight; + + free(leftDistribute); + free(rightDistribute); + + return result; +} + +// Depth-first search . +// On each node-step we try to recombinate coins between left and right subtree. +// We know that coins are the same number that nodes, and we can get coins by depth +// Runtime: O(n) +// Space: O(1) +int distributeCoins(struct TreeNode* root) { + return getDisturb(root)->distributeMoves; +} diff --git a/leetcode/src/98.c b/leetcode/src/98.c new file mode 100644 index 0000000000..775fe9e1b7 --- /dev/null +++ b/leetcode/src/98.c @@ -0,0 +1,24 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * struct TreeNode *left; + * struct TreeNode *right; + * }; + */ + +// Depth first search approach. +// Runtime: O(n) +// Space: O(1) +bool checkIsBst(struct TreeNode* node, bool leftBoundInf, int leftBound, bool rightBoundInf, int rightBound){ + return + (node == NULL) + || (leftBoundInf || node->val > leftBound) + && (rightBoundInf || node->val < rightBound) + && checkIsBst(node->left, leftBoundInf, leftBound, false, node->val) + && checkIsBst(node->right, false, node->val, rightBoundInf, rightBound); +} + +bool isValidBST(struct TreeNode* root){ + return checkIsBst(root, true, INT_MIN, true, INT_MAX); +} diff --git a/leetcode/src/985.c b/leetcode/src/985.c new file mode 100644 index 0000000000..7a2343ab22 --- /dev/null +++ b/leetcode/src/985.c @@ -0,0 +1,39 @@ +/** + * Note: The returned array must be malloced, assume caller calls free(). + */ + +// collecting sum Runtime: O(len(queries)), Space: O(1) +int* sumEvenAfterQueries(int* nums, int numsSize, int** queries, int queriesSize, int* queriesColSize, int* returnSize){ + int summ = 0; + int* result = malloc(queriesSize * sizeof(int)); + *returnSize = queriesSize; + + for(int i = 0; i < numsSize; i++){ + if (nums[i] % 2 == 0) { + summ += nums[i]; + } + } + + for(int i = 0; i < queriesSize; i++){ + int* query = queries[i]; + int val = query[0]; + int index = query[1]; + + // sub index value from summ if it's even + if (nums[index] % 2 == 0) { + summ -= nums[index]; + } + + // modify the nums[index] value + nums[index] += val; + + // add index value from summ if it's even + if (nums[index] % 2 == 0) { + summ += nums[index]; + } + + result[i] = summ; + } + + return result; +} diff --git a/leetcode/src/997.c b/leetcode/src/997.c new file mode 100644 index 0000000000..a599555fc3 --- /dev/null +++ b/leetcode/src/997.c @@ -0,0 +1,29 @@ +// Using hashtable. +// Runtime: O(n + len(trust)) +// Space: O(n) +int findJudge(int n, int** trust, int trustSize, int* trustColSize){ + int* personsToTrust = calloc(n + 1, sizeof(int)); + int* personsFromTrust = calloc(n + 1, sizeof(int)); + + for(int i = 0; i < trustSize; i++){ + int* currentTrust = trust[i]; + personsToTrust[currentTrust[1]] += 1; + personsFromTrust[currentTrust[0]] += 1; + } + + int potentialJudjeNumber = -1; + for(int i = 1; i < n + 1; i++){ + if (personsToTrust[i] == n - 1 && personsFromTrust[i] == 0){ + if (potentialJudjeNumber > -1){ + return -1; + } + + potentialJudjeNumber = i; + } + } + + free(personsToTrust); + free(personsFromTrust); + + return potentialJudjeNumber; +} diff --git a/machine_learning/kohonen_som_trace.c b/machine_learning/kohonen_som_trace.c index c893bd02d2..8ca54218ba 100644 --- a/machine_learning/kohonen_som_trace.c +++ b/machine_learning/kohonen_som_trace.c @@ -6,7 +6,7 @@ * \details * This example implements a powerful self organizing map algorithm. * The algorithm creates a connected network of weights that closely - * follows the given data points. This this creates a chain of nodes that + * follows the given data points. This creates a chain of nodes that * resembles the given input shape. * \author [Krishna Vedala](https://github.com/kvedala) * \see kohonen_som_topology.c diff --git a/math/CMakeLists.txt b/math/CMakeLists.txt new file mode 100644 index 0000000000..517ec8ccbd --- /dev/null +++ b/math/CMakeLists.txt @@ -0,0 +1,18 @@ +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. The RELATIVE flag makes it easier to extract an executable's name +# automatically. + +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c ) +foreach( testsourcefile ${APP_SOURCES} ) + string( REPLACE ".c" "" testname ${testsourcefile} ) # File type. Example: `.c` + add_executable( ${testname} ${testsourcefile} ) + + if(OpenMP_C_FOUND) + target_link_libraries(${testname} OpenMP::OpenMP_C) + endif() + if(MATH_LIBRARY) + target_link_libraries(${testname} ${MATH_LIBRARY}) + endif() + install(TARGETS ${testname} DESTINATION "bin/math") # Folder name. Do NOT include `<>` + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/misc/armstrong_number.c b/math/armstrong_number.c similarity index 100% rename from misc/armstrong_number.c rename to math/armstrong_number.c diff --git a/misc/cantor_set.c b/math/cantor_set.c similarity index 100% rename from misc/cantor_set.c rename to math/cantor_set.c diff --git a/misc/cartesian_to_polar.c b/math/cartesian_to_polar.c similarity index 100% rename from misc/cartesian_to_polar.c rename to math/cartesian_to_polar.c diff --git a/misc/catalan.c b/math/catalan.c similarity index 100% rename from misc/catalan.c rename to math/catalan.c diff --git a/misc/collatz.c b/math/collatz.c similarity index 100% rename from misc/collatz.c rename to math/collatz.c diff --git a/math/euclidean_algorithm_extended.c b/math/euclidean_algorithm_extended.c new file mode 100644 index 0000000000..914eb98ba0 --- /dev/null +++ b/math/euclidean_algorithm_extended.c @@ -0,0 +1,154 @@ +/** + * @{ + * @file + * @brief Program to perform the [extended Euclidean + * algorithm](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm) + * + * @details The extended Euclidean algorithm, on top of finding the GCD (greatest common + * divisor) of two integers a and b, also finds the values x and y such that + * ax+by = gcd(a, b) + */ + +#include /// for tests +#include /// for IO +#include /// for div function and corresponding div_t struct + +/** + * @brief a structure holding the values resulting from the extended Euclidean + * algorithm + */ +typedef struct euclidean_result +{ + int gcd; ///< the greatest common divisor calculated with the Euclidean + ///< algorithm + int x, y; ///< the values x and y such that ax + by = gcd(a, b) +} euclidean_result_t; + +/** + * @brief gives queue-like behavior to an array of two ints, pushing an element + * onto the end and pushing one off the front + * + * @param arr an array of ints acting as a queue + * @param newval the value being pushed into arr + * + * @returns void + */ +static inline void xy_push(int arr[2], int newval) +{ + arr[1] = arr[0]; + arr[0] = newval; +} + +/** + * @brief calculates the value of x or y and push those into the small 'queues' + * + * @details Both x and y are found by taking their value from 2 iterations ago minus the + * product of their value from 1 iteration ago and the most recent quotient. + * + * @param quotient the quotient from the latest iteration of the Euclidean + * algorithm + * @param prev the 'queue' holding the values of the two previous iterations + * + * @returns void + */ +static inline void calculate_next_xy(int quotient, int prev[2]) +{ + int next = prev[1] - (prev[0] * quotient); + xy_push(prev, next); +} + +/** + * @brief performs the extended Euclidean algorithm on integer inputs a and b + * + * @param a first integer input + * @param b second integer input + * + * @returns euclidean_result_t containing the gcd, and values x and y such that + * ax + by = gcd + */ +euclidean_result_t extended_euclidean_algorithm(int a, int b) +{ + int previous_remainder = 1; + int previous_x_values[2] = {0, 1}; + int previous_y_values[2] = {1, 0}; + div_t div_result; + euclidean_result_t result; + + /* swap values of a and b */ + if (abs(a) < abs(b)) + { + a ^= b; + b ^= a; + a ^= b; + } + + div_result.rem = b; + + while (div_result.rem > 0) + { + div_result = div(a, b); + + previous_remainder = b; + + a = b; + b = div_result.rem; + + calculate_next_xy(div_result.quot, previous_x_values); + calculate_next_xy(div_result.quot, previous_y_values); + } + + result.gcd = previous_remainder; + result.x = previous_x_values[1]; + result.y = previous_y_values[1]; + + return result; +} + +/** @} */ + +/** + * @brief perform one single check on the result of the algorithm with provided + * parameters and expected output + * + * @param a first paramater for Euclidean algorithm + * @param b second parameter for Euclidean algorithm + * @param gcd expected value of result.gcd + * @param x expected value of result.x + * @param y expected value of result.y + * + * @returns void + */ +static inline void single_test(int a, int b, int gcd, int x, int y) +{ + euclidean_result_t result; + + result = extended_euclidean_algorithm(a, b); + assert(result.gcd == gcd); + assert(result.x == x); + assert(result.y == y); +} + +/** + * @brief Perform tests on known results + * @returns void + */ +static void test() +{ + single_test(40, 27, 1, -2, 3); + single_test(71, 41, 1, -15, 26); + single_test(48, 18, 6, -1, 3); + single_test(99, 303, 3, -16, 49); + single_test(14005, 3507, 1, -305, 1218); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief Main Function + * @returns 0 upon successful program exit + */ +int main() +{ + test(); // run self-test implementations + return 0; +} diff --git a/misc/factorial.c b/math/factorial.c similarity index 100% rename from misc/factorial.c rename to math/factorial.c diff --git a/misc/factorial_large_number.c b/math/factorial_large_number.c similarity index 100% rename from misc/factorial_large_number.c rename to math/factorial_large_number.c diff --git a/misc/factorial_trailing_zeroes.c b/math/factorial_trailing_zeroes.c similarity index 100% rename from misc/factorial_trailing_zeroes.c rename to math/factorial_trailing_zeroes.c diff --git a/math/fibonacci.c b/math/fibonacci.c new file mode 100644 index 0000000000..60752e7ae5 --- /dev/null +++ b/math/fibonacci.c @@ -0,0 +1,124 @@ +/** + * @file + * @brief Program to print the nth term of the Fibonacci series. + * @details + * Fibonacci series generally starts from 0 and 1. Every next term in + * the series is equal to the sum of the two preceding terms. + * For further info: https://en.wikipedia.org/wiki/Fibonacci_sequence + * + * @author [Luiz Carlos Aguiar C](https://github.com/IKuuhakuI) + * @author [Niranjan](https://github.com/niranjank2022) + */ + +#include /// for assert() +#include /// for errno - to determine whether there is an error while using strtol() +#include /// for input, output +#include /// for exit() - to exit the program +#include /// to calculate time taken by fib() +/** + * @brief Determines the nth Fibonacci term + * @param number - n in "nth term" and it can't be negative as well as zero + * @return nth term in unsigned type + * @warning + * Only till 47th and 48th fibonacci element can be stored in `int` and + * `unsigned int` respectively (takes more than 20 seconds to print) + */ +unsigned int fib(int number) +{ + // Check for negative integers + if (number <= 0) + { + fprintf(stderr, "Illegal Argument Is Passed!\n"); + exit(EXIT_FAILURE); + } + + // Base conditions + if (number == 1) + return 0; + + if (number == 2) + return 1; + + // Recursive call to the function + return fib(number - 1) + fib(number - 2); +} + +/** + * @brief Get the input from the user + * @return valid argument to the fibonacci function + */ +int getInput(void) +{ + int num, excess_len; + char buffer[3], *endPtr; + + while (1) + { // Repeat until a valid number is entered + printf("Please enter a valid number:"); + fgets(buffer, 3, stdin); // Inputs the value from user + + excess_len = 0; + if (!(buffer[0] == '\n' || + buffer[1] == '\n' || + buffer[2] == '\n')) { + while (getchar() != '\n') excess_len++; + } + + num = strtol(buffer, &endPtr, + 10); // Attempts to convert the string to integer + + // Checking the input + if ( // The number is too large + (excess_len > 0 || num > 48) || + // Characters other than digits are included in the input + (*endPtr != '\0' && *endPtr != '\n') || + // No characters are entered + endPtr == buffer) + { + continue; + } + + break; + } + + printf("\nEntered digit: %d (it might take sometime)\n", num); + return num; +} + +/** + * @brief self-test implementation + * @return void + */ +static void test() +{ + assert(fib(5) == 3); + assert(fib(2) == 1); + assert(fib(9) == 21); +} + +/** + * @brief Main function + * @return 0 on exit + */ +int main() +{ + // Performing the test + test(); + printf("Tests passed...\n"); + + // Getting n + printf( + "Enter n to find nth fibonacci element...\n" + "Note: You would be asked to enter input until valid number ( less " + "than or equal to 48 ) is entered.\n"); + + int number = getInput(); + clock_t start, end; + + start = clock(); + printf("Fibonacci element %d is %u ", number, fib(number)); + end = clock(); + + printf("in %.3f seconds.\n", ((double)(end - start)) / CLOCKS_PER_SEC ); + return 0; +} diff --git a/misc/fibonacci_dp.c b/math/fibonacci_dp.c similarity index 100% rename from misc/fibonacci_dp.c rename to math/fibonacci_dp.c diff --git a/misc/fibonacci_fast.c b/math/fibonacci_fast.c similarity index 100% rename from misc/fibonacci_fast.c rename to math/fibonacci_fast.c diff --git a/math/fibonacci_formula.c b/math/fibonacci_formula.c new file mode 100644 index 0000000000..cf86d0ed55 --- /dev/null +++ b/math/fibonacci_formula.c @@ -0,0 +1,59 @@ +/** + * @file + * @brief Finding Fibonacci number of any `n` number using [Binet's closed form formula](https://en.wikipedia.org/wiki/Fibonacci_number#Binet's_formula) + * compute \f$f_{nth}\f$ Fibonacci number using the binet's formula: + * Fn = 1√5 * (1+√5 / 2)^n+1 − 1√5 * (1−√5 / 2)^n+1 + * @author [GrandSir](https://github.com/GrandSir/) + */ + +#include /// for pow and sqrt +#include /// for printf +#include /// for assert + +/** + * @param n index of number in Fibonacci sequence + * @returns nth value of fibonacci sequence for all n >= 0 + */ +int fib(unsigned int n) { + float seq = (1 / sqrt(5) * pow(((1 + sqrt(5)) / 2), n + 1)) - (1 / sqrt(5) * pow(((1 - sqrt(5)) / 2), n + 1)); + + // removing unnecessary fractional part by implicitly converting float to int + return seq; +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test () { + /* this ensures that the first 10 number of fibonacci sequence + * (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89) + * matches with algorithm + */ + assert(fib(0) == 1); + assert(fib(1) == 1); + assert(fib(2) == 2); + assert(fib(3) == 3); + assert(fib(4) == 5); + assert(fib(5) == 8); + assert(fib(6) == 13); + assert(fib(7) == 21); + assert(fib(8) == 34); + assert(fib(9) == 55); + assert(fib(10) == 89); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + + for(int i = 0; i <= 10; i++){ + printf("%d. fibonacci number is: %d\n", i, fib(i)); + } + return 0; +} diff --git a/misc/gcd.c b/math/gcd.c similarity index 100% rename from misc/gcd.c rename to math/gcd.c diff --git a/misc/is_armstrong.c b/math/is_armstrong.c similarity index 100% rename from misc/is_armstrong.c rename to math/is_armstrong.c diff --git a/misc/large_factorials.c b/math/large_factorials.c similarity index 100% rename from misc/large_factorials.c rename to math/large_factorials.c diff --git a/misc/lcm.c b/math/lcm.c similarity index 100% rename from misc/lcm.c rename to math/lcm.c diff --git a/misc/lerp.c b/math/lerp.c similarity index 100% rename from misc/lerp.c rename to math/lerp.c diff --git a/misc/palindrome.c b/math/palindrome.c similarity index 100% rename from misc/palindrome.c rename to math/palindrome.c diff --git a/misc/prime.c b/math/prime.c similarity index 100% rename from misc/prime.c rename to math/prime.c diff --git a/misc/prime_factoriziation.c b/math/prime_factoriziation.c similarity index 100% rename from misc/prime_factoriziation.c rename to math/prime_factoriziation.c diff --git a/misc/prime_seive.c b/math/prime_sieve.c similarity index 96% rename from misc/prime_seive.c rename to math/prime_sieve.c index 6287bfff3c..c7a32c6502 100644 --- a/misc/prime_seive.c +++ b/math/prime_sieve.c @@ -1,6 +1,6 @@ /** * @file - * @brief [Prime Seive](https://leetcode.com/problems/count-primes/) + * @brief [Prime Sieve](https://leetcode.com/problems/count-primes/) * algorithm implementation. * @author [Divyansh Kushwaha](https://github.com/webdesignbydivyansh) */ diff --git a/misc/strong_number.c b/math/strong_number.c similarity index 100% rename from misc/strong_number.c rename to math/strong_number.c diff --git a/misc/fibonacci.c b/misc/fibonacci.c deleted file mode 100644 index 3af489624d..0000000000 --- a/misc/fibonacci.c +++ /dev/null @@ -1,23 +0,0 @@ -#include - -// Fibonnacci function -int fib(int number) -{ - if (number == 1 || number == 2) - return 1; - else - return fib(number - 1) + fib(number - 2); -} - -int main() -{ - int number; - - // Asks for the number that is in n position in Fibonnacci sequence - printf("Number: "); - scanf("%d", &number); - - printf("%d \n", fib(number)); - - return 0; -} \ No newline at end of file diff --git a/misc/hamming_distance.c b/misc/hamming_distance.c new file mode 100644 index 0000000000..e479bf144e --- /dev/null +++ b/misc/hamming_distance.c @@ -0,0 +1,62 @@ +/** + * @file + * @brief [Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance) + * algorithm implementation. + * @details + * In information theory, the Hamming distance between two strings of + * equal length is the number of positions at which the corresponding symbols + * are different. + * @author [Aybars Nazlica](https://github.com/aybarsnazlica) + */ + +#include /// for assert +#include /// for IO operations + +/** + * @brief Function to calculate the Hamming distance between two strings + * @param param1 string 1 + * @param param2 string 2 + * @returns Hamming distance + */ +int hamming_distance(char* str1, char* str2) +{ + int i = 0, distance = 0; + + while (str1[i] != '\0') + { + if (str1[i] != str2[i]) + { + distance++; + } + i++; + } + + return distance; +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() +{ + char str1[] = "karolin"; + char str2[] = "kathrin"; + + assert(hamming_distance(str1, str2) == 3); + + char str3[] = "00000"; + char str4[] = "11111"; + + assert(hamming_distance(str3, str4) == 5); + printf("All tests have successfully passed!\n"); +} +/** + * @brief Main function + * @returns 0 on exit + */ +int main() +{ + test(); // run self-test implementations + return 0; +} diff --git a/misc/mcnaughton_yamada_thompson.c b/misc/mcnaughton_yamada_thompson.c new file mode 100644 index 0000000000..9f13ae03e4 --- /dev/null +++ b/misc/mcnaughton_yamada_thompson.c @@ -0,0 +1,721 @@ +/** + * @file + * @brief [McNaughton–Yamada–Thompson algorithm](https://en.wikipedia.org/wiki/Thompson%27s_construction) + * @details + * From Wikipedia: + * In computer science, Thompson's construction algorithm, + * also called the McNaughton–Yamada–Thompson algorithm, + * is a method of transforming a regular expression into + * an equivalent nondeterministic finite automaton (NFA). + * This implementation implements the all three operations + * (implicit concatenation, '|' for union, '*' for Kleene star) + * required by the formal definition of regular expressions. + * @author [Sharon Cassidy](https://github.com/CascadingCascade) + */ + +#include /// for assert() +#include /// for IO operations +#include /// for string operations +#include /// for memory management + +/* Begin declarations, I opted to place various helper / utility functions + * close to their usages and didn't split their declaration / definition */ + +/** + * @brief Definition for a binary abstract syntax tree (AST) node + */ +struct ASTNode { + char content; ///< the content of this node + struct ASTNode* left; ///< left child + struct ASTNode* right; ///< right child +}; + +struct ASTNode* createNode(char content); +void destroyNode(struct ASTNode* node); +char* preProcessing(const char* input); +struct ASTNode* buildAST(const char* input); + +/** + * @brief Definition for a NFA state transition rule + */ +struct transRule { + struct NFAState* target; ///< pointer to the state to transit to + char cond; ///< the input required to activate this transition +}; + +struct transRule* createRule(struct NFAState* state, char c); +void destroyRule(struct transRule* rule); + +/** + * @brief Definition for a NFA state. Each NFAState object is initialized + * to have a capacity of three rules, since there will only be at most two + * outgoing rules and one empty character circular rule in this algorithm + */ +struct NFAState { + int ruleCount; ///< number of transition rules this state have + struct transRule** rules; ///< the transition rules +}; + +struct NFAState* createState(void); +void destroyState(struct NFAState* state); + +/** + * @brief Definition for the NFA itself. + * statePool[0] is defined to be its starting state, + * and statePool[1] is defined to be its accepting state. + * for simplicity's sake all NFAs are initialized to have + * a small fixed capacity, although due to the recursive nature + * of this algorithm this capacity is believed to be sufficient + */ +struct NFA { + int stateCount; ///< the total number of states this NFA have + struct NFAState** statePool; ///< the pool of all available states + int ruleCount; ///< the total number of transition rules in this NFA + struct transRule** rulePool; ///< the pool of all transition rules + int CSCount; ///< the number of currently active states + struct NFAState** currentStates; ///< the pool of all active states + int subCount; ///< the number of sub NFAs + struct NFA** subs; ///< the pool of all sub NFAs + int wrapperFlag; ///< whether this NFA is a concatenation wrapper +}; + +struct NFA* createNFA(void); +void destroyNFA(struct NFA* nfa); +void addState(struct NFA* nfa, struct NFAState* state); +void addRule(struct NFA* nfa, struct transRule* rule, int loc); +void postProcessing(struct NFA* nfa); +void transit(struct NFA* nfa, char input); +int isAccepting(const struct NFA* nfa); + +/* End definitions, begin abstract syntax tree construction */ + +/** + * @brief helper function to determine whether a character should be + * considered a character literal + * @param ch the character to be tested + * @returns `1` if it is a character literal + * @returns `0` otherwise + */ +int isLiteral(const char ch) { + return !(ch == '(' || ch == ')' || ch == '*' || ch == '\n' || ch == '|'); +} + +/** + * @brief performs preprocessing on a regex string, + * making all implicit concatenations explicit + * @param input target regex string + * @returns pointer to the processing result + */ +char* preProcessing(const char* input) { + const size_t len = strlen(input); + if(len == 0) { + char* str = malloc(1); + str[0] = '\0'; + return str; + } + + char* str = malloc(len * 2); + size_t op = 0; + + for (size_t i = 0; i < len - 1; ++i) { + char c = input[i]; + str[op++] = c; + // one character lookahead + char c1 = input[i + 1]; + + if( (isLiteral(c) && isLiteral(c1)) || + (isLiteral(c) && c1 == '(') || + (c == ')' && c1 == '(') || + (c == ')' && isLiteral(c1)) || + (c == '*' && isLiteral(c1)) || + (c == '*' && c1 == '(') + ) { + // '\n' is used to represent concatenation + // in this implementation + str[op++] = '\n'; + } + } + + str[op++] = input[len - 1]; + str[op] = '\0'; + return str; +} + +/** + * @brief utility function to locate the first occurrence + * of a character in a string while respecting parentheses + * @param str target string + * @param key the character to be located + * @returns the index of its first occurrence, `0` if it could not be found + */ +size_t indexOf(const char* str, char key) { + int depth = 0; + + for (size_t i = 0; i < strlen(str); ++i) { + const char c = str[i]; + + if(depth == 0 && c == key) { + return i; + } + if(c == '(') depth++; + if(c == ')') depth--; + } + // Due to the way this function is intended to be used, + // it's safe to assume the character will not appear as + // the string's first character + // thus `0` is used as the `not found` value + return 0; +} + +/** + * @brief utility function to create a subString + * @param str target string + * @param begin starting index, inclusive + * @param end ending index, inclusive + * @returns pointer to the newly created subString + */ +char* subString(const char* str, size_t begin, size_t end) { + char* res = malloc(end - begin + 2); + strncpy(res, str + begin, end - begin + 1); + res[end - begin + 1] = '\0'; + return res; +} + +/** + * @brief recursively constructs a AST from a preprocessed regex string + * @param input regex + * @returns pointer to the resulting tree + */ +struct ASTNode* buildAST(const char* input) { + + struct ASTNode* node = createNode('\0'); + node->left = NULL; + node->right = NULL; + const size_t len = strlen(input); + size_t index; + + // Empty input + if(len == 0) return node; + + // Character literals + if(len == 1) { + node->content = input[0]; + return node; + } + + // Discard parentheses + if(input[0] == '(' && input[len - 1] == ')') { + char* temp = subString(input, 1, len - 2); + destroyNode(node); + node = buildAST(temp); + + free(temp); + return node; + } + + // Union + index = indexOf(input, '|'); + if(index) { + node->content = '|'; + + char* temp1 = subString(input, 0, index - 1); + char* temp2 = subString(input, index + 1, len - 1); + node->left = buildAST(temp1); + node->right = buildAST(temp2); + + free(temp2); + free(temp1); + return node; + } + + // Concatenation + index = indexOf(input, '\n'); + if(index) { + node->content = '\n'; + + char* temp1 = subString(input, 0, index - 1); + char* temp2 = subString(input, index + 1, len - 1); + node->left = buildAST(temp1); + node->right = buildAST(temp2); + + free(temp2); + free(temp1); + return node; + } + + // Kleene star + // Testing with indexOf() is unnecessary here, + // Since all other possibilities have been exhausted + node->content = '*'; + char* temp = subString(input, 0, len - 2); + node->left = buildAST(temp); + node->right = NULL; + + free(temp); + return node; +} + +/* End AST construction, begins the actual algorithm itself */ + +/** + * @brief helper function to recursively redirect transition rule targets + * @param nfa target NFA + * @param src the state to redirect away from + * @param dest the state to redirect to + * @returns void + */ +void redirect(struct NFA* nfa, struct NFAState* src, struct NFAState* dest) { + for (int i = 0; i < nfa->subCount; ++i) { + redirect(nfa->subs[i], src, dest); + } + for (int i = 0; i < nfa->ruleCount; ++i) { + struct transRule* rule = nfa->rulePool[i]; + if (rule->target == src) { + rule->target = dest; + } + } +} + +struct NFA* compileFromAST(struct ASTNode* root) { + + struct NFA* nfa = createNFA(); + + // Empty input + if (root->content == '\0') { + addRule(nfa, createRule(nfa->statePool[1], '\0'), 0); + return nfa; + } + + // Character literals + if (isLiteral(root->content)) { + addRule(nfa, createRule(nfa->statePool[1], root->content), 0); + return nfa; + } + + switch (root->content) { + + case '\n': { + struct NFA* ln = compileFromAST(root->left); + struct NFA* rn = compileFromAST(root->right); + + // Redirects all rules targeting ln's accepting state to + // target rn's starting state + redirect(ln, ln->statePool[1], rn->statePool[0]); + + // Manually creates and initializes a special + // "wrapper" NFA + destroyNFA(nfa); + struct NFA* wrapper = malloc(sizeof(struct NFA)); + wrapper->stateCount = 2; + wrapper->statePool = malloc(sizeof(struct NFAState*) * 2); + wrapper->subCount = 0; + wrapper->subs = malloc(sizeof(struct NFA*) * 2); + wrapper->ruleCount = 0; + wrapper->rulePool = malloc(sizeof(struct transRule*) * 3); + wrapper->CSCount = 0; + wrapper->currentStates = malloc(sizeof(struct NFAState*) * 2); + wrapper->wrapperFlag = 1; + wrapper->subs[wrapper->subCount++] = ln; + wrapper->subs[wrapper->subCount++] = rn; + + // Maps the wrapper NFA's starting and ending states + // to its sub NFAs + wrapper->statePool[0] = ln->statePool[0]; + wrapper->statePool[1] = rn->statePool[1]; + + return wrapper; + } + case '|': { + + struct NFA* ln = compileFromAST(root->left); + struct NFA* rn = compileFromAST(root->right); + nfa->subs[nfa->subCount++] = ln; + nfa->subs[nfa->subCount++] = rn; + + // Adds empty character transition rules + addRule(nfa, createRule(ln->statePool[0], '\0'), 0); + addRule(ln, createRule(nfa->statePool[1], '\0'), 1); + addRule(nfa, createRule(rn->statePool[0], '\0'), 0); + addRule(rn, createRule(nfa->statePool[1], '\0'), 1); + + return nfa; + } + case '*': { + struct NFA* ln = compileFromAST(root->left); + nfa->subs[nfa->subCount++] = ln; + + addRule(ln, createRule(ln->statePool[0], '\0'), 1); + addRule(nfa, createRule(ln->statePool[0], '\0'), 0); + addRule(ln, createRule(nfa->statePool[1], '\0'), 1); + addRule(nfa, createRule(nfa->statePool[1], '\0'), 0); + + return nfa; + } + } + + // Fallback, shouldn't happen in normal operation + destroyNFA(nfa); + return NULL; +} + +/* Ends the algorithm, begins NFA utility functions*/ + +/** + * @brief adds a state to a NFA + * @param nfa target NFA + * @param state the NFA state to be added + * @returns void + */ +void addState(struct NFA* nfa, struct NFAState* state) { + nfa->statePool[nfa->stateCount++] = state; +} + +/** + * @brief adds a transition rule to a NFA + * @param nfa target NFA + * @param rule the rule to be added + * @param loc which state this rule should be added to + * @returns void + */ +void addRule(struct NFA* nfa, struct transRule* rule, int loc) { + nfa->rulePool[nfa->ruleCount++] = rule; + struct NFAState* state = nfa->statePool[loc]; + state->rules[state->ruleCount++] = rule; +} + +/** + * @brief performs postprocessing on a compiled NFA, + * add circular empty character transition rules where + * it's needed for the NFA to function correctly + * @param nfa target NFA + * @returns void + */ +void postProcessing(struct NFA* nfa) { + // Since the sub NFA's states and rules are managed + // through their own pools, recursion is necessary + for (int i = 0; i < nfa->subCount; ++i) { + postProcessing(nfa->subs[i]); + } + + // If a state does not have any empty character accepting rule, + // we add a rule that circles back to itself + // So this state will be preserved when + // empty characters are inputted + for (int i = 0; i < nfa->stateCount; ++i) { + + struct NFAState* pState = nfa->statePool[i]; + int f = 0; + for (int j = 0; j < pState->ruleCount; ++j) { + if(pState->rules[j]->cond == '\0') { + f = 1; + break; + } + } + + if (!f) { + addRule(nfa, createRule(pState, '\0'), i); + } + } +} + +/** + * @brief helper function to determine an element's presence in an array + * @param states target array + * @param len length of the target array + * @param state the element to search for + * @returns `1` if the element is present, `0` otherwise + */ +int contains(struct NFAState** states, int len, struct NFAState* state) { + int f = 0; + for (int i = 0; i < len; ++i) { + if(states[i] == state) { + f = 1; + break; + } + } + return f; +} + +/** + * @brief helper function to manage empty character transitions + * @param target target NFA + * @param states pointer to results storage location + * @param sc pointer to results count storage location + * @returns void + */ +void findEmpty(struct NFAState* target, struct NFAState** states, int *sc) { + for (int i = 0; i < target->ruleCount; ++i) { + const struct transRule *pRule = target->rules[i]; + + if (pRule->cond == '\0' && !contains(states, *sc, pRule->target)) { + states[(*sc)++] = pRule->target; + // the use of `states` and `sc` is necessary + // to sync data across recursion levels + findEmpty(pRule->target, states, sc); + } + } +} + +/** + * @brief moves a NFA forward + * @param nfa target NFA + * @param input the character to be fed into the NFA + * @returns void + */ +void transit(struct NFA* nfa, char input) { + struct NFAState** newStates = malloc(sizeof(struct NFAState*) * 10); + int NSCount = 0; + + if (input == '\0') { + // In case of empty character input, it's possible for + // a state to transit to another state that's more than + // one rule away, we need to take that into account + for (int i = nfa->CSCount - 1; i > -1; --i) { + struct NFAState *pState = nfa->currentStates[i]; + nfa->CSCount--; + + struct NFAState** states = malloc(sizeof(struct NFAState*) * 10); + int sc = 0; + findEmpty(pState, states, &sc); + + for (int j = 0; j < sc; ++j) { + if(!contains(newStates,NSCount, states[j])) { + newStates[NSCount++] = states[j]; + } + } + free(states); + } + } else { + // Iterates through all current states + for (int i = nfa->CSCount - 1; i > -1; --i) { + struct NFAState *pState = nfa->currentStates[i]; + // Gradually empties the current states pool, so + // it can be refilled + nfa->CSCount--; + + // Iterates through rules of this state + for (int j = 0; j < pState->ruleCount; ++j) { + const struct transRule *pRule = pState->rules[j]; + + if(pRule->cond == input) { + if(!contains(newStates, NSCount, pRule->target)) { + newStates[NSCount++] = pRule->target; + } + } + } + } + } + + nfa->CSCount = NSCount; + for (int i = 0; i < NSCount; ++i) { + nfa->currentStates[i] = newStates[i]; + } + free(newStates); +} + +/** + * @brief determines whether the NFA is currently in its accepting state + * @param nfa target NFA + * @returns `1` if the NFA is in its accepting state + * @returns `0` otherwise + */ +int isAccepting(const struct NFA* nfa) { + for (int i = 0; i < nfa->CSCount; ++i) { + if(nfa->currentStates[i] == nfa->statePool[1]) { + return 1; + } + } + return 0; +} + +/* Ends NFA utilities, begins testing function*/ + +/** + * @brief Testing helper function + * @param regex the regular expression to be used + * @param string the string to match against + * @param expected expected results + * @returns void + */ +void testHelper(const char* regex, const char* string, const int expected) { + char* temp = preProcessing(regex); + struct ASTNode* node = buildAST(temp); + + struct NFA* nfa = compileFromAST(node); + postProcessing(nfa); + + // reallocates the outermost NFA's current states pool + // because it will actually be used to store all the states + nfa->currentStates = realloc(nfa->currentStates, sizeof(struct NFAState*) * 100); + // Starts the NFA by adding its starting state to the pool + nfa->currentStates[nfa->CSCount++] = nfa->statePool[0]; + + // feeds empty characters into the NFA before and after + // every normal character + for (size_t i = 0; i < strlen(string); ++i) { + transit(nfa, '\0'); + transit(nfa, string[i]); + } + transit(nfa, '\0'); + + assert(isAccepting(nfa) == expected); + + destroyNFA(nfa); + destroyNode(node); + free(temp); +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test(void) { + testHelper("(c|a*b)", "c", 1); + testHelper("(c|a*b)", "aab", 1); + testHelper("(c|a*b)", "ca", 0); + testHelper("(c|a*b)*", "caaab", 1); + testHelper("(c|a*b)*", "caba", 0); + testHelper("", "", 1); + testHelper("", "1", 0); + testHelper("(0|(1(01*(00)*0)*1)*)*","11",1); + testHelper("(0|(1(01*(00)*0)*1)*)*","110",1); + testHelper("(0|(1(01*(00)*0)*1)*)*","1100",1); + testHelper("(0|(1(01*(00)*0)*1)*)*","10000",0); + testHelper("(0|(1(01*(00)*0)*1)*)*","00000",1); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main(void) { + test(); // run self-test implementations + return 0; +} + +/* I opted to place these more-or-less boilerplate code and their docs + * at the end of file for better readability */ + +/** + * @brief creates and initializes a AST node + * @param content data to initializes the node with + * @returns pointer to the newly created node + */ +struct ASTNode* createNode(const char content) { + struct ASTNode* node = malloc(sizeof(struct ASTNode)); + node->content = content; + node->left = NULL; + node->right = NULL; + return node; +} + +/** + * @brief recursively destroys a AST + * @param node the root node of the tree to be deleted + * @returns void + */ +void destroyNode(struct ASTNode* node) { + if(node->left != NULL) { + destroyNode(node->left); + } + + if(node->right != NULL) { + destroyNode(node->right); + } + + free(node); +} + +/** + * @brief creates and initializes a transition rule + * @param state transition target + * @param c transition condition + * @returns pointer to the newly created rule + */ +struct transRule* createRule(struct NFAState* state, char c) { + struct transRule* rule = malloc(sizeof(struct transRule)); + rule->target = state; + rule->cond = c; + return rule; +} + +/** + * @brief destroys a transition rule object + * @param rule pointer to the object to be deleted + * @returns void + */ +void destroyRule(struct transRule* rule) { + free(rule); +} + +/** + * @brief creates and initializes a NFA state + * @returns pointer to the newly created NFA state + */ +struct NFAState* createState(void) { + struct NFAState* state = malloc(sizeof(struct NFAState)); + state->ruleCount = 0; + state->rules = malloc(sizeof(struct transRule*) * 3); + return state; +} + +/** + * @brief destroys a NFA state + * @param state pointer to the object to be deleted + * @returns void + */ +void destroyState(struct NFAState* state) { + free(state->rules); + free(state); +} + +/** + * @brief creates and initializes a NFA + * @returns pointer to the newly created NFA + */ +struct NFA* createNFA(void) { + struct NFA* nfa = malloc(sizeof(struct NFA)); + + nfa->stateCount = 0; + nfa->statePool = malloc(sizeof(struct NFAState*) * 5); + nfa->ruleCount = 0; + nfa->rulePool = malloc(sizeof(struct transRule*) * 10); + nfa->CSCount = 0; + nfa->currentStates = malloc(sizeof(struct NFAState*) * 5); + nfa->subCount = 0; + nfa->subs = malloc(sizeof(struct NFA*) * 5); + nfa->wrapperFlag = 0; + + addState(nfa, createState()); + addState(nfa, createState()); + return nfa; +} + +/** + * @brief recursively destroys a NFA + * @param nfa pointer to the object to be deleted + * @returns void + */ +void destroyNFA(struct NFA* nfa) { + for (int i = 0; i < nfa->subCount; ++i) { + destroyNFA(nfa->subs[i]); + } + + // In case of a wrapper NFA, do not free its states + // because it doesn't really have any states of its own + if (!nfa->wrapperFlag) { + for (int i = 0; i < nfa->stateCount; ++i) { + destroyState(nfa->statePool[i]); + } + } + for (int i = 0; i < nfa->ruleCount; ++i) { + destroyRule(nfa->rulePool[i]); + } + free(nfa->statePool); + free(nfa->currentStates); + free(nfa->rulePool); + free(nfa->subs); + free(nfa); +} diff --git a/misc/poly_add.c b/misc/poly_add.c index 53e76c3967..8280315e09 100644 --- a/misc/poly_add.c +++ b/misc/poly_add.c @@ -30,17 +30,11 @@ struct term */ void free_poly(struct term *poly) { - if (!poly) + while (poly) { - return; // NULL pointer does not need delete - } - else - { - while (!poly->next) - { - free(poly->next); // Deletes next term - } - free(poly); // delete the current term + struct term *next = poly->next; + free(poly); + poly = next; } } @@ -54,31 +48,19 @@ void free_poly(struct term *poly) void create_polynomial(struct term **poly, int coef, int pow) { // Creating the polynomial using temporary linked lists - struct term *temp1, *temp2; - temp1 = *poly; // Contains the null pointer + struct term **temp1 = poly; - // Initiating first term - if (temp1 == NULL) + while (*temp1) { - temp2 = (struct term *)malloc( - sizeof(struct term)); // Dynamic node creation - temp2->coef = coef; - temp2->pow = pow; - // Updating the null pointer with the address of the first node of the - // polynomial just created - *poly = temp2; - temp2->next = NULL; // Increasing the pointer temp2 - } - // Creating the rest of the nodes - else - { - temp2->next = (struct term *)malloc( - sizeof(struct term)); // Dynamic node creation - temp2 = temp2->next; // Increasing the pointer temp2 - temp2->coef = coef; - temp2->pow = pow; - temp2->next = NULL; + temp1 = &(*temp1)->next; } + + // Now temp1 reaches to the end of the list + *temp1 = (struct term *)malloc( + sizeof(struct term)); // Create the term and linked as the tail + (*temp1)->coef = coef; + (*temp1)->pow = pow; + (*temp1)->next = NULL; } /** diff --git a/misc/run_length_encoding.c b/misc/run_length_encoding.c new file mode 100644 index 0000000000..59e3342fb1 --- /dev/null +++ b/misc/run_length_encoding.c @@ -0,0 +1,92 @@ +/** + * @file + * @author [serturx](https://github.com/serturx/) + * @brief Encode a null terminated string using [Run-length encoding](https://en.wikipedia.org/wiki/Run-length_encoding) + * @details + * Run-length encoding is a lossless compression algorithm. + * It works by counting the consecutive occurences symbols + * and encodes that series of consecutive symbols into the + * counted symbol and a number denoting the number of + * consecutive occorences. + * + * For example the string "AAAABBCCD" gets encoded into "4A2B2C1D" + * + */ + +#include /// for IO operations +#include /// for string functions +#include /// for malloc/free +#include /// for assert + +/** + * @brief Encodes a null-terminated string using run-length encoding + * @param str String to encode + * @return char* Encoded string + */ + +char* run_length_encode(char* str) { + int str_length = strlen(str); + int encoded_index = 0; + + //allocate space for worst-case scenario + char* encoded = malloc(2 * strlen(str)); + + //temp space for int to str conversion + char int_str[20]; + + for(int i = 0; i < str_length; ++i) { + int count = 0; + char current = str[i]; + + //count occurences + while(current == str[i + count]) count++; + + i += count - 1; + + //convert occurrence amount to string and write to encoded string + sprintf(int_str, "%d", count); + int int_str_length = strlen(int_str); + strncpy(&encoded[encoded_index], int_str, strlen(int_str)); + + //write current char to encoded string + encoded_index += strlen(int_str); + encoded[encoded_index] = current; + ++encoded_index; + } + + //null terminate string and move encoded string to compacted memory space + encoded[encoded_index] = '\0'; + char* compacted_string = malloc(strlen(encoded) + 1); + strcpy(compacted_string, encoded); + + free(encoded); + + return compacted_string; +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + char* test; + test = run_length_encode("aaaaaaabbbaaccccdefaadr"); + assert(!strcmp(test, "7a3b2a4c1d1e1f2a1d1r")); + free(test); + test = run_length_encode("lidjhvipdurevbeirbgipeahapoeuhwaipefupwieofb"); + assert(!strcmp(test, "1l1i1d1j1h1v1i1p1d1u1r1e1v1b1e1i1r1b1g1i1p1e1a1h1a1p1o1e1u1h1w1a1i1p1e1f1u1p1w1i1e1o1f1bq")); + free(test); + test = run_length_encode("htuuuurwuquququuuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahghghrw"); + assert(!strcmp(test, "1h1t4u1r1w1u1q1u1q1u1q3u76a1h1g1h1g1h1r1w")); + free(test); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + printf("All tests have passed!\n"); + return 0; +} diff --git a/misc/shunting_yard.c b/misc/shunting_yard.c new file mode 100644 index 0000000000..7cf7bc44b2 --- /dev/null +++ b/misc/shunting_yard.c @@ -0,0 +1,238 @@ +/** + * @file + * @brief [Shunting Yard Algorithm](https://en.wikipedia.org/wiki/Shunting_yard_algorithm) + * @details From Wikipedia: In computer science, + * the shunting yard algorithm is a method for parsing arithmetical or logical expressions, or a combination of both, specified in infix notation. + * It can produce either a postfix notation string, also known as Reverse Polish notation (RPN), or an abstract syntax tree (AST). + * The algorithm was invented by Edsger Dijkstra and named the "shunting yard" algorithm because its operation resembles that of a railroad shunting yard. + * @author [CascadingCascade](https://github.com/CascadingCascade) + */ + +#include /// for assertion +#include /// for IO operations +#include /// for memory management +#include /// for string operations +#include /// for isdigit() + +/** + * @brief Helper function that returns each operator's precedence + * @param operator the operator to be queried + * @returns the operator's precedence + */ +int getPrecedence(char operator) { + switch (operator) { + case '+': + case '-': { + return 1; + } + case '*': + case '/': { + return 2; + } + case '^': { + return 3; + } + default:{ + fprintf(stderr,"Error: Invalid operator\n"); + return -1; + } + } +} + +/** + * @brief Helper function that returns each operator's associativity + * @param operator the operator to be queried + * @returns '1' if the operator is left associative + * @returns '0' if the operator is right associative + */ +int getAssociativity(char operator) { + switch (operator) { + case '^': { + return 0; + } + case '+': + case '-': + case '*': + case '/': { + return 1; + } + default: { + fprintf(stderr,"Error: Invalid operator\n"); + return -1; + } + } +} + +/** + * @brief An implementation of the shunting yard that converts infix notation to reversed polish notation + * @param input pointer to input string + * @param output pointer to output location + * @returns `1` if a parentheses mismatch is detected + * @returns `0` if no mismatches are detected + */ +int shuntingYard(const char *input, char *output) { + const unsigned int inputLength = strlen(input); + char* operatorStack = (char*) malloc(sizeof(char) * inputLength); + + // This pointer points at where we should insert the next element, + // Hence stackPointer - 1 is used when accessing elements + unsigned int stackPointer = 0; + + // We will parse the input with strtok(), + // Since strtok() is destructive, we make a copy of the input to preserve the original string + char* str = malloc(sizeof(char) * inputLength + 1); + strcpy(str,input); + char* token = strtok(str," "); + + // We will push to output with strcat() and strncat(), + // This initializes output to be a string with a length of zero + output[0] = '\0'; + + while (token != NULL) { + // If it's a number, push it to the output directly + if (isdigit(token[0])) { + strcat(output,token); + strcat(output," "); + + token = strtok(NULL," "); + continue; + } + + switch (token[0]) { + // If it's a left parenthesis, push it to the operator stack for later matching + case '(': { + operatorStack[stackPointer++] = token[0]; + break; + } + + // If it's a right parenthesis, search for a left parenthesis to match it + case ')': { + // Guard statement against accessing an empty stack + if(stackPointer < 1) { + fprintf(stderr,"Error: Mismatched parentheses\n"); + free(operatorStack); + free(str); + return 1; + } + + while (operatorStack[stackPointer - 1] != '(') { + // strncat() with a count of 1 is used to append characters to output + const unsigned int i = (stackPointer--) - 1; + strncat(output, &operatorStack[i], 1); + strcat(output," "); + + // If the operator stack is exhausted before a match can be found, + // There must be a mismatch + if(stackPointer == 0) { + fprintf(stderr,"Error: Mismatched parentheses\n"); + free(operatorStack); + free(str); + return 1; + } + } + + // Discards the parentheses now the matching is complete, + // Simply remove the left parenthesis from the stack is enough, + // Since the right parenthesis didn't enter the stack in the first place + stackPointer--; + break; + } + + // If it's an operator(o1), we compare it to whatever is at the top of the operator stack(o2) + default: { + // Places the operator into the stack directly if it's empty + if(stackPointer < 1) { + operatorStack[stackPointer++] = token[0]; + break; + } + + // We need to check if there's actually a valid operator at the top of the stack + if((stackPointer - 1 > 0) && operatorStack[stackPointer - 1] != '(') { + const int precedence1 = getPrecedence(token[0]); + const int precedence2 = getPrecedence(operatorStack[stackPointer - 1]); + const int associativity = getAssociativity(token[0]); + + // We pop operators from the stack, if... + while ( // ... their precedences are equal, and o1 is left associative, ... + ((associativity && precedence1 == precedence2) || + // ... or o2 simply have a higher precedence, ... + precedence2 > precedence1) && + // ... and there are still operators available to be popped. + ((stackPointer - 1 > 0) && operatorStack[stackPointer - 1] != '(')) { + + strncat(output,&operatorStack[(stackPointer--) - 1],1); + strcat(output," "); + } + } + + // We'll save o1 for later + operatorStack[stackPointer++] = token[0]; + break; + } + } + + token = strtok(NULL," "); + } + + free(str); + + // Now all input has been exhausted, + // Pop everything from the operator stack, then push them to the output + while (stackPointer > 0) { + // If there are still leftover left parentheses in the stack, + // There must be a mismatch + if(operatorStack[stackPointer - 1] == '(') { + fprintf(stderr,"Error: Mismatched parentheses\n"); + free(operatorStack); + return 1; + } + + const unsigned int i = (stackPointer--) - 1; + strncat(output, &operatorStack[i], 1); + if (i != 0) { + strcat(output," "); + } + } + + free(operatorStack); + return 0; +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + char* in = malloc(sizeof(char) * 50); + char* out = malloc(sizeof(char) * 50); + int i; + + strcpy(in,"3 + 4 * ( 2 - 1 )"); + printf("Infix: %s\n",in); + i = shuntingYard(in, out); + printf("RPN: %s\n",out); + printf("Return code: %d\n\n",i); + assert(strcmp(out,"3 4 2 1 - * +") == 0); + assert(i == 0); + + strcpy(in,"3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"); + printf("Infix: %s\n",in); + i = shuntingYard(in, out); + printf("RPN: %s\n",out); + printf("Return code: %d\n\n",i); + assert(strcmp(out,"3 4 2 * 1 5 - 2 3 ^ ^ / +") == 0); + assert(i == 0); + + printf("Testing successfully completed!\n"); + free(in); + free(out); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // Run self-test implementations + return 0; +} diff --git a/numerical_methods/bisection_method.c b/numerical_methods/bisection_method.c new file mode 100644 index 0000000000..ce790f441f --- /dev/null +++ b/numerical_methods/bisection_method.c @@ -0,0 +1,111 @@ +/** + * @file + * @brief In mathematics, the [Bisection + * Method](https://en.wikipedia.org/wiki/Bisection_method) is a root-finding + * method that applies to any continuous function for which one knows two values + * with opposite signs. + * @details + * The method consists of repeatedly bisecting the interval + * defined by the two values and then selecting the subinterval in which the + * function changes sign, and therefore must contain a root. It is a very + * simple and robust method, but it is also relatively slow. Because of this, + * it is often used to obtain a rough approximation to a solution which is + * then used as a starting point for more rapidly converging methods. + * @author [Aybars Nazlica](https://github.com/aybarsnazlica) + */ + +#include /// for assert +#include /// for fabs +#include /// for IO operations + +#define EPSILON 0.0001 // a small positive infinitesimal quantity +#define NMAX 50 // maximum number of iterations + +/** + * @brief Function to check if two input values have the same sign (the property + * of being positive or negative) + * @param a Input value + * @param b Input value + * @returns 1.0 if the input values have the same sign, + * @returns -1.0 if the input values have different signs + */ +double sign(double a, double b) +{ + return (a > 0 && b > 0) + (a < 0 && b < 0) - (a > 0 && b < 0) - + (a < 0 && b > 0); +} + +/** + * @brief Continuous function for which we want to find the root + * @param x Real input variable + * @returns The evaluation result of the function using the input value + */ +double func(double x) +{ + return x * x * x + 2.0 * x - 10.0; // f(x) = x**3 + 2x - 10 +} + +/** + * @brief Root-finding method for a continuous function given two values with + * opposite signs + * @param x_left Lower endpoint value of the interval + * @param x_right Upper endpoint value of the interval + * @param tolerance Error threshold + * @returns `root of the function` if bisection method succeed within the + * maximum number of iterations + * @returns `-1` if bisection method fails + */ +double bisection(double x_left, double x_right, double tolerance) +{ + int n = 1; // step counter + double middle; // midpoint + + while (n <= NMAX) + { + middle = (x_left + x_right) / 2; // bisect the interval + double error = middle - x_left; + + if (fabs(func(middle)) < EPSILON || error < tolerance) + { + return middle; + } + + if (sign(func(middle), func(x_left)) > 0.0) + { + x_left = middle; // new lower endpoint + } + else + { + x_right = middle; // new upper endpoint + } + + n++; // increase step counter + } + return -1; // method failed (maximum number of steps exceeded) +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() +{ + /* Compares root value that is found by the bisection method within a given + * floating point error*/ + assert(fabs(bisection(1.0, 2.0, 0.0001) - 1.847473) < + EPSILON); // the algorithm works as expected + assert(fabs(bisection(100.0, 250.0, 0.0001) - 249.999928) < + EPSILON); // the algorithm works as expected + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() +{ + test(); // run self-test implementations + return 0; +} diff --git a/numerical_methods/secant_method.c b/numerical_methods/secant_method.c new file mode 100644 index 0000000000..946285388c --- /dev/null +++ b/numerical_methods/secant_method.c @@ -0,0 +1,80 @@ +/** + * @file + * @brief [Secant Method](https://en.wikipedia.org/wiki/Secant_method) implementation. Find a + * continuous function's root by using a succession of roots of secant lines to + * approximate it, starting from the given points' secant line. + * @author [Samuel Pires](https://github.com/disnoca) + */ + +#include /// for assert +#include /// for fabs +#include /// for io operations + +#define TOLERANCE 0.0001 // root approximation result tolerance +#define NMAX 100 // maximum number of iterations + +/** + * @brief Continuous function for which we want to find the root + * @param x Real input variable + * @returns The evaluation result of the function using the input value + */ +double func(double x) +{ + return x * x - 3.; // x^2 = 3 - solution is sqrt(3) +} + +/** + * @brief Root-finding method for a continuous function given two points + * @param x0 One of the starting secant points + * @param x1 One of the starting secant points + * @param tolerance Determines how accurate the returned value is. The returned + * value will be within `tolerance` of the actual root + * @returns `root of the function` if secant method succeed within the + * maximum number of iterations + * @returns `-1` if secant method fails + */ +double secant_method(double x0, double x1, double tolerance) +{ + int n = 1; // step counter + + while (n++ < NMAX) + { + // calculate secant line root + double x2 = x1 - func(x1) * (x1 - x0) / (func(x1) - func(x0)); + + // update values + x0 = x1; + x1 = x2; + + // return value if it meets tolerance + if (fabs(x1 - x0) < tolerance) + return x2; + } + + return -1; // method failed (maximum number of steps exceeded) +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() +{ + // compares root values found by the secant method within the tolerance + assert(secant_method(0.2, 0.5, TOLERANCE) - sqrt(3) < TOLERANCE); + assert(fabs(secant_method(-2, -5, TOLERANCE)) - sqrt(3) < TOLERANCE); + assert(secant_method(-3, 2, TOLERANCE) - sqrt(3) < TOLERANCE); + assert(fabs(secant_method(1, -1.5, TOLERANCE)) - sqrt(3) < TOLERANCE); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() +{ + test(); // run self-test implementations + return 0; +} diff --git a/process_scheduling_algorithms/CMakeLists.txt b/process_scheduling_algorithms/CMakeLists.txt new file mode 100644 index 0000000000..1d2a56e057 --- /dev/null +++ b/process_scheduling_algorithms/CMakeLists.txt @@ -0,0 +1,20 @@ +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. RELATIVE may makes it easier to extract an executable name +# automatically. +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c ) +# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c ) +# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES) +foreach( testsourcefile ${APP_SOURCES} ) + # I used a simple string replace, to cut off .cpp. + string( REPLACE ".c" "" testname ${testsourcefile} ) + add_executable( ${testname} ${testsourcefile} ) + + if(OpenMP_C_FOUND) + target_link_libraries(${testname} OpenMP::OpenMP_C) + endif() + if(MATH_LIBRARY) + target_link_libraries(${testname} ${MATH_LIBRARY}) + endif() + install(TARGETS ${testname} DESTINATION "bin/process_scheduling_algorithms") + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/process_scheduling_algorithms/non_preemptive_priority_scheduling.c b/process_scheduling_algorithms/non_preemptive_priority_scheduling.c new file mode 100644 index 0000000000..2dd8ee8fc0 --- /dev/null +++ b/process_scheduling_algorithms/non_preemptive_priority_scheduling.c @@ -0,0 +1,369 @@ +/** + * @file + * @brief + * [Non-Preemptive Priority + * Scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)) + * is a scheduling algorithm that selects the tasks to execute based on + * priority. + * + * @details + * In this algorithm, processes are executed according to their + * priority. The process with the highest priority is to be executed first and + * so on. In this algorithm, a variable is maintained known as the time quantum. + * The length of the time quantum is decided by the user. The process which is + * being executed is interrupted after the expiration of the time quantum and + * the next process with the highest priority is executed. This cycle of + * interrupting the process after every time quantum and resuming the next + * process with the highest priority continues until all the processes have + * been executed. + * @author [Aryan Raj](https://github.com/aryaraj132) + */ +#include /// for assert +#include /// for boolean data type +#include /// for IO operations (`printf`) +#include /// for memory allocation eg: `malloc`, `realloc`, `free`, `exit` +/** + * @brief Structure to represent a process + */ + typedef struct node { + int ID; ///< ID of the process node + int AT; ///< Arrival Time of the process node + int BT; ///< Burst Time of the process node + int priority; ///< Priority of the process node + int CT; ///< Completion Time of the process node + int WT; ///< Waiting Time of the process node + int TAT; ///< Turn Around Time of the process node + struct node *next; ///< pointer to the node + } node; + +/** + * @brief To insert a new process in the queue + * @param root pointer to the head of the queue + * @param id process ID + * @param at arrival time + * @param bt burst time + * @param prior priority of the process + * @returns void + */ +void insert(node **root, int id, int at, int bt, int prior) +{ + // create a new node and initialize it + node *new = (node *)malloc(sizeof(node)); + node *ptr = *root; + new->ID = id; + new->AT = at; + new->BT = bt; + new->priority = prior; + new->next = NULL; + new->CT = 0; + new->WT = 0; + new->TAT = 0; + // if the root is null, make the new node the root + if (*root == NULL) + { + *root = new; + return; + } + // else traverse to the end of the queue and insert the new node there + while (ptr->next != NULL) + { + ptr = ptr->next; + } + ptr->next = new; + return; +} +/* + * @brief To delete a process from the queue + * @param root pointer to the head of the queue + * @param id process ID + * @returns void + */ +void delete(node **root, int id) +{ + node *ptr = *root, *prev; + // if the root is null, return + if (ptr == NULL) + { + return; + } + // if the root is the process to be deleted, make the next node the root + if (ptr->ID == id) + { + *root = ptr->next; + free(ptr); + return; + } + // else traverse the queue and delete the process + while (ptr != NULL && ptr->ID != id) + { + prev = ptr; + ptr = ptr->next; + } + if (ptr == NULL) + { + return; + } + prev->next = ptr->next; + free(ptr); +} +/** + * @brief To show the process queue + * @param head pointer to the head of the queue + * @returns void + */ +void show_list(node *head) +{ + printf("Process Priority AT BT CT TAT WT \n"); + while (head != NULL) + { + printf("P%d. %d %d %d %d %d %d \n", head->ID, head->priority, head->AT, + head->BT, head->CT, head->TAT, head->WT); + head = head->next; + } +} +/** + * @brief To length process queue + * @param root pointer to the head of the queue + * @returns int total length of the queue + */ +int l_length(node **root) +{ + int count = 0; + node *ptr = *root; + while (ptr != NULL) + { + count++; + ptr = ptr->next; + } + return count; +} +/** + * @brief To update the completion time, turn around time and waiting time of + * the processes + * @param root pointer to the head of the queue + * @param id process ID + * @param ct current time + * @param wt waiting time + * @param tat turn around time + * @returns void + */ +void update(node **root, int id, int ct, int wt, int tat) +{ + node *ptr = *root; + // If process to be updated is head node + if (ptr != NULL && ptr->ID == id) + { + if (ct != 0) + { + ptr->CT = ct; + } + if (wt != 0) + { + ptr->WT = wt; + } + if (tat != 0) + { + ptr->TAT = tat; + } + return; + } + // else traverse the queue and update the values + while (ptr != NULL && ptr->ID != id) + { + ptr = ptr->next; + } + if (ct != 0) + { + ptr->CT = ct; + } + if (wt != 0) + { + ptr->WT = wt; + } + if (tat != 0) + { + ptr->TAT = tat; + } + return; +} +/** + * @brief To compare the priority of two processes based on their arrival time + * and priority + * @param a pointer to the first process + * @param b pointer to the second process + * @returns true if the priority of the first process is greater than the + * the second process + * @returns false if the priority of the first process is NOT greater than the + * second process + */ +bool compare(node *a, node *b) +{ + if (a->AT == b->AT) + { + return a->priority < b->priority; + } + else + { + return a->AT < b->AT; + } +} +/** + * @brief To calculate the average completion time of all the processes + * @param root pointer to the head of the queue + * @returns float average completion time + */ +float calculate_ct(node **root) +{ + // calculate the total completion time of all the processes + node *ptr = *root, *prior, *rpt; + int ct = 0, i, time = 0; + int n = l_length(root); + float avg, sum = 0; + node *duproot = NULL; + // create a duplicate queue + while (ptr != NULL) + { + insert(&duproot, ptr->ID, ptr->AT, ptr->BT, ptr->priority); + ptr = ptr->next; + } + ptr = duproot; + rpt = ptr->next; + // sort the queue based on the arrival time and priority + while (rpt != NULL) + { + if (!compare(ptr, rpt)) + { + ptr = rpt; + } + rpt = rpt->next; + } + // ptr is the process to be executed first. + ct = ptr->AT + ptr->BT; + time = ct; + sum += ct; + // update the completion time, turn around time and waiting time of the + // process + update(root, ptr->ID, ct, 0, 0); + delete (&duproot, ptr->ID); + // repeat the process until all the processes are executed + for (i = 0; i < n - 1; i++) + { + ptr = duproot; + while (ptr != NULL && ptr->AT > time) + { + ptr = ptr->next; + } + rpt = ptr->next; + while (rpt != NULL) + { + if (rpt->AT <= time) + { + if (rpt->priority < ptr->priority) + { + ptr = rpt; + } + } + rpt = rpt->next; + } + ct += ptr->BT; + time += ptr->BT; + sum += ct; + update(root, ptr->ID, ct, 0, 0); + delete (&duproot, ptr->ID); + } + avg = sum / n; + return avg; +} +/** + * @brief To calculate the average turn around time of all the processes + * @param root pointer to the head of the queue + * @returns float average turn around time + */ +float calculate_tat(node **root) +{ + float avg, sum = 0; + int n = l_length(root); + node *ptr = *root; + // calculate the completion time if not already calculated + if (ptr->CT == 0) + { + calculate_ct(root); + } + // calculate the total turn around time of all the processes + while (ptr != NULL) + { + ptr->TAT = ptr->CT - ptr->AT; + sum += ptr->TAT; + ptr = ptr->next; + } + avg = sum / n; + return avg; +} +/** + * @brief To calculate the average waiting time of all the processes + * @param root pointer to the head of the queue + * @returns float average waiting time + */ +float calculate_wt(node **root) +{ + float avg, sum = 0; + int n = l_length(root); + node *ptr = *root; + // calculate the completion if not already calculated + if (ptr->CT == 0) + { + calculate_ct(root); + } + // calculate the total waiting time of all the processes + while (ptr != NULL) + { + ptr->WT = (ptr->TAT - ptr->BT); + sum += ptr->WT; + ptr = ptr->next; + } + avg = sum / n; + return avg; +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() +{ + // Entered processes + // printf("ID Priority Arrival Time Burst Time \n"); + // printf("1 0 5 1 \n"); + // printf("2 1 4 2 \n"); + // printf("3 2 3 3 \n"); + // printf("4 3 2 4 \n"); + // printf("5 4 1 5 \n"); + + node *root = NULL; + insert(&root, 1, 0, 5, 1); + insert(&root, 2, 1, 4, 2); + insert(&root, 3, 2, 3, 3); + insert(&root, 4, 3, 2, 4); + insert(&root, 5, 4, 1, 5); + float avgCT = calculate_ct(&root); + float avgTAT = calculate_tat(&root); + float avgWT = calculate_wt(&root); + assert(avgCT == 11); + assert(avgTAT == 9); + assert(avgWT == 6); + printf("[+] All tests have successfully passed!\n"); + // printf("Average Completion Time is : %f \n", calculate_ct(&root)); + // printf("Average Turn Around Time is : %f \n", calculate_tat(&root)); + // printf("Average Waiting Time is : %f \n", calculate_wt(&root)); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() +{ + test(); // run self-test implementations + + return 0; +} diff --git a/scripts/file_linter.py b/scripts/file_linter.py new file mode 100644 index 0000000000..bce3ad86fb --- /dev/null +++ b/scripts/file_linter.py @@ -0,0 +1,40 @@ +import os +import subprocess +import sys + +print("Python {}.{}.{}".format(*sys.version_info)) # Python 3.8 +with open("git_diff.txt") as in_file: + modified_files = sorted(in_file.read().splitlines()) + print("{} files were modified.".format(len(modified_files))) + + cpp_exts = tuple(".c .c++ .cc .cpp .cu .cuh .cxx .h .h++ .hh .hpp .hxx".split()) + cpp_files = [file for file in modified_files if file.lower().endswith(cpp_exts)] + print(f"{len(cpp_files)} C++ files were modified.") + if not cpp_files: + sys.exit(0) + subprocess.run(["clang-tidy", "-p=build", "--fix", *cpp_files, "--"], + check=True, text=True, stderr=subprocess.STDOUT) + subprocess.run(["clang-format", "-i", *cpp_files], + check=True, text=True, stderr=subprocess.STDOUT) + + upper_files = [file for file in cpp_files if file != file.lower()] + if upper_files: + print(f"{len(upper_files)} files contain uppercase characters:") + print("\n".join(upper_files) + "\n") + + space_files = [file for file in cpp_files if " " in file or "-" in file] + if space_files: + print(f"{len(space_files)} files contain space or dash characters:") + print("\n".join(space_files) + "\n") + + nodir_files = [file for file in cpp_files if file.count(os.sep) != 1 and "project_euler" not in file and "data_structure" not in file] + if len(nodir_files) > 1: + nodir_file_bad_files = len(nodir_files) - 1 + print(f"{len(nodir_files)} files are not in one and only one directory:") + print("\n".join(nodir_files) + "\n") + else: + nodir_file_bad_files = 0 + bad_files = nodir_file_bad_files + len(upper_files + space_files) + + if bad_files: + sys.exit(bad_files) diff --git a/scripts/leetcode_directory_md.py b/scripts/leetcode_directory_md.py new file mode 100644 index 0000000000..4c9a7dc01b --- /dev/null +++ b/scripts/leetcode_directory_md.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 + +from dataclasses import dataclass +from os import listdir +from pathlib import Path + +import requests + + +@dataclass +class Task: + """The task dataclass. Container for task info""" + + id: str + title: str + solution: str + difficulty: str + + +def fetch_leetcode_folder_tasks(solutions_folder: Path) -> list[Task]: + """Fetch leetcode tasks from the Leetcode""" + + # Fetch tasks info from the leetcode API. + resp = requests.get("https://leetcode.com/api/problems/algorithms/", timeout=10) + content_dict = resp.json() + + raw_tasks_id_dict = {} + + for task in content_dict["stat_status_pairs"]: + task_stat = task["stat"] + raw_tasks_id_dict[str(task_stat["frontend_question_id"])] = task + + # Generate result tasks info to be inserted into the document + tasks_list = [] + + difficulty = {1: "Easy", 2: "Medium", 3: "Hard"} + + for fl in listdir(solutions_folder): + task_id = fl.split(".")[0] + + raw_task = raw_tasks_id_dict.get(task_id, None) + if raw_task is None: + continue + + raw_task_stat = raw_task["stat"] + tasks_list.append( + Task( + id=f'{raw_task_stat["frontend_question_id"]}', + title=f'[{raw_task_stat["question__title"]}](https://leetcode.com/problems/{raw_task_stat["question__title_slug"]})', + solution=f"[C](./src/{fl})", + difficulty=f'{difficulty.get(raw_task["difficulty"]["level"], "")}', + ) + ) + + return tasks_list + + +HEADER_ID = "#" +HEADER_TITLE = "Title" +HEADER_SOLUTION = "Solution" +HEADER_DIFFICULTY = "Difficulty" +SEPARATOR = "-" + + +def print_directory_md(tasks_list: list[Task]) -> None: + """Print tasks into the stdout""" + + def get_max_len(get_item): + return max(list(map(lambda x: len(get_item(x)), tasks_list))) + + id_max_length = max(get_max_len(lambda x: x.id), len(HEADER_ID)) + title_max_length = max(get_max_len(lambda x: x.title), len(HEADER_TITLE)) + solution_max_length = max(get_max_len(lambda x: x.solution), len(HEADER_SOLUTION)) + difficulty_max_length = max( + get_max_len(lambda x: x.difficulty), len(HEADER_DIFFICULTY) + ) + + def formatted_string(header, title, solution, difficulty): + return ( + f"| {header.rjust(id_max_length)} " + + f"| {title.ljust(title_max_length)} " + + f"| {solution.ljust(solution_max_length)} " + + f"| {difficulty.ljust(difficulty_max_length)} |" + ) + + tasks_rows = [] + + tasks_rows.append( + formatted_string(HEADER_ID, HEADER_TITLE, HEADER_SOLUTION, HEADER_DIFFICULTY) + ) + tasks_rows.append( + formatted_string( + id_max_length * SEPARATOR, + title_max_length * SEPARATOR, + solution_max_length * SEPARATOR, + difficulty_max_length * SEPARATOR, + ) + ) + + tasks_list.sort(key=lambda x: int(x.id.strip())) + + for task in tasks_list: + tasks_rows.append( + formatted_string(task.id, task.title, task.solution, task.difficulty) + ) + + print( + """ +# LeetCode + +### LeetCode Algorithm +""" + ) + + for item in tasks_rows: + print(item) + + +if __name__ == "__main__": + top_dir = Path(".") + solutions_folder = top_dir / "leetcode" / "src" + + tasks_list = fetch_leetcode_folder_tasks(solutions_folder) + print_directory_md(tasks_list) diff --git a/searching/exponential_search.c b/searching/exponential_search.c index 7f30b4430c..efb1ec7105 100644 --- a/searching/exponential_search.c +++ b/searching/exponential_search.c @@ -3,8 +3,9 @@ * \brief [Exponential Search](https://github.com/TheAlgorithms/Algorithms-Explanation/blob/master/en/Search%20Algorithms/Exponential%20Search.md) * \author [Alessio Farinelli](https://github.com/faridevnz) */ -#include /// for assert +#include /// for assert #include /// for int64_t, uint16_t +#include /// for printf #define ELEMENT -10 @@ -81,7 +82,7 @@ int main() static void test() { // empty array - int64_t arr_empty[] = {}; + int64_t arr_empty[] = { 0 }; assert(exponential_search(arr_empty, 0, 10) == -1); // elent not found int64_t arr_found[] = {1, 2, 3}; @@ -104,4 +105,6 @@ static void test() // find an element in an array of length n int64_t arr_middle[] = {-1, 2, 4, 6, 8}; assert(exponential_search(arr_middle, 5, 6) == 3); + + printf("All tests have successfully passed!\n"); } diff --git a/searching/floyd_cycle_detection_algorithm.c b/searching/floyd_cycle_detection_algorithm.c index 44c48177f7..285a72c637 100644 --- a/searching/floyd_cycle_detection_algorithm.c +++ b/searching/floyd_cycle_detection_algorithm.c @@ -24,7 +24,7 @@ */ uint32_t duplicateNumber(const uint32_t *in_arr, size_t n) { - if (n <= 1) { // to find duplicate in an array its size should be atleast 2 + if (n <= 1) { // to find duplicate in an array its size should be at least 2 return -1; } uint32_t tortoise = in_arr[0]; ///< variable tortoise is used for the longer diff --git a/sorting/merge_sort.c b/sorting/merge_sort.c index c61767a154..ac1046f489 100644 --- a/sorting/merge_sort.c +++ b/sorting/merge_sort.c @@ -33,6 +33,11 @@ void swap(int *a, int *b) void merge(int *a, int l, int r, int n) { int *b = (int *)malloc(n * sizeof(int)); /* dynamic memory must be freed */ + if (b == NULL) + { + printf("Can't Malloc! Please try again."); + exit(EXIT_FAILURE); + } int c = l; int p1, p2; p1 = l; @@ -101,18 +106,32 @@ void merge_sort(int *a, int n, int l, int r) int main(void) { int *a, n, i; + printf("Enter Array size: "); scanf("%d", &n); + if (n <= 0) /* exit program if arraysize is not greater than 0 */ + { + printf("Array size must be Greater than 0!\n"); + return 1; + } a = (int *)malloc(n * sizeof(int)); + if (a == NULL) /* exit program if can't malloc memory */ + { + printf("Can't Malloc! Please try again."); + return 1; + } for (i = 0; i < n; i++) { + printf("Enter number[%d]: ", i); scanf("%d", &a[i]); } merge_sort(a, n, 0, n - 1); + printf("Sorted Array: "); for (i = 0; i < n; i++) { - printf(" %d", a[i]); + printf("%d ", a[i]); } + printf("\n"); free(a); diff --git a/sorting/patience_sort.c b/sorting/patience_sort.c new file mode 100644 index 0000000000..5e069bf240 --- /dev/null +++ b/sorting/patience_sort.c @@ -0,0 +1,160 @@ +/** + * @file + * @brief [Patience Sort](https://en.wikipedia.org/wiki/Patience_sorting) + * @details From Wikipedia: + * In computer science, patience sorting is a sorting algorithm inspired by, and named after, the card game patience. + * Given an array of n elements from some totally ordered domain, consider this array as a collection of cards and simulate the patience sorting game. + * When the game is over, recover the sorted sequence by repeatedly picking off the minimum visible card; + * in other words, perform a k-way merge of the p piles, each of which is internally sorted. + * @author [CascadingCascade](https://github.com/CascadingCascade) + */ + +#include /// for assertions +#include /// for IO operations +#include /// for memory management + +/** + * @brief Sorts the target array by dividing it into a variable number of internally sorted piles then merge the piles + * @param array pointer to the array to be sorted + * @param length length of the target array + * @returns void + */ +void patienceSort(int *array, int length) { + // An array of pointers used to store each pile + int* *piles = (int* *) malloc(sizeof(int*) * length); + for (int i = 0; i < length; ++i) { + piles[i] = malloc(sizeof(int) * length); + } + + // pileSizes keep track of the indices of each pile's topmost element, hence 0 means only one element + // Note how calloc() is used to initialize the sizes of all piles to zero + int *pileSizes = (int*) calloc(length,sizeof(int)); + + // This initializes the first pile, note how using an array of pointers allowed us to access elements through two subscripts + // The first subscript indicates which pile we are accessing, the second subscript indicates the location being accessed in that pile + piles[0][0] = array[0]; + int pileCount = 1; + + for (int i = 1; i < length; ++i) { + // This will be used to keep track whether an element has been added to an existing pile + int flag = 1; + + for (int j = 0; j < pileCount; ++j) { + if(piles[j][pileSizes[j]] > array[i]) { + // We have found a pile this element can be added to + piles[j][pileSizes[j] + 1] = array[i]; + pileSizes[j]++; + flag--; + break; + } + } + + if(flag) { + // The element in question can not be added to any existing piles, creating a new pile + piles[pileCount][0] = array[i]; + pileCount++; + } + } + + // This will keep track of the minimum value of all 'exposed' elements and which pile that value is from + int min, minLocation; + + for (int i = 0; i < length; ++i) { + // Since there's no guarantee the first pile will be depleted slower than other piles, + // Example: when all elements are equal, in that case the first pile will be depleted immediately + // We can't simply initialize min to the top most element of the first pile, + // this loop finds a value to initialize min to. + for (int j = 0; j < pileCount; ++j) { + if(pileSizes[j] < 0) { + continue; + } + min = piles[j][pileSizes[j]]; + minLocation = j; + break; + } + + for (int j = 0; j < pileCount; ++j) { + if(pileSizes[j] < 0) { + continue; + } + if(piles[j][pileSizes[j]] < min) { + min = piles[j][pileSizes[j]]; + minLocation = j; + } + } + + array[i] = min; + pileSizes[minLocation]--; + } + + // Deallocate memory + free(pileSizes); + for (int i = 0; i < length; ++i) { + free(piles[i]); + } + free(piles); +} + +/** + * @brief Helper function to print an array + * @param array pointer to the array + * @param length length of the target array + * @returns void + */ +void printArray(int *array,int length) { + printf("Array:"); + for (int i = 0; i < length; ++i) { + printf("%d",array[i]); + if (i != length - 1) putchar(','); + } + putchar('\n'); +} + +/** + * @brief Testing Helper function + * @param array pointer to the array to be used for testing + * @param length length of the target array + * @returns void + */ + +void testArray(int *array,int length) { + printf("Before sorting:\n"); + printArray(array,length); + + patienceSort(array,length); + + printf("After sorting:\n"); + printArray(array,length); + + for (int i = 0; i < length - 1; ++i) { + assert(array[i] <= array[i + 1]); + } + printf("All assertions have passed!\n\n"); +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + int testArray1[] = {2,8,7,1,3,5,6,4}; + int testArray2[] = {2,2,5,1,3,5,6,4}; + int testArray3[] = {1,2,3,4,5,6,7,8}; + int testArray4[] = {8,7,6,5,4,3,2,1}; + + testArray(testArray1,8); + testArray(testArray2,8); + testArray(testArray3,8); + testArray(testArray4,8); + + printf("Testing successfully completed!\n"); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} diff --git a/sorting/radix_sort_2.c b/sorting/radix_sort_2.c index 9d6cabb2f2..e527e92fba 100644 --- a/sorting/radix_sort_2.c +++ b/sorting/radix_sort_2.c @@ -22,7 +22,7 @@ void countSort(int *arr, int n, int place) int i, freq[range] = {0}; int *output = (int *)malloc(n * sizeof(int)); - // Store count of occurences in freq[] + // Store count of occurrences in freq[] for (i = 0; i < n; i++) freq[(arr[i] / place) % range]++; // Change freq[i] so that it contains the actual position of the digit in