diff --git a/.codecov.yaml b/.codecov.yaml index 8589ffb1..2c2196ab 100644 --- a/.codecov.yaml +++ b/.codecov.yaml @@ -18,6 +18,10 @@ component_management: name: C# paths: - csharp/** + - component_id: module_java + name: Java + paths: + - java/** - component_id: module_javascript name: JavaScript paths: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 24fd6f33..d1dbf543 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -21,6 +21,7 @@ on: - 'c/**' - 'cplusplus/**' - 'csharp/**' + - 'java/**' - 'javascript/**' - 'python/**' - '!*/README.rst' @@ -60,6 +61,9 @@ jobs: - name: csharp language: csharp build-mode: none + - name: java + language: java-kotlin + build-mode: none - name: javascript language: javascript-typescript build-mode: none diff --git a/.github/workflows/java-lint.yml b/.github/workflows/java-lint.yml new file mode 100644 index 00000000..4fc08d7a --- /dev/null +++ b/.github/workflows/java-lint.yml @@ -0,0 +1,44 @@ +name: Java Lint + +on: + push: + paths: + - 'java/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Set up Git + run: git config --global user.email "actions@github.com" && git config --global user.name "GitHub Actions" + + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Java + uses: actions/setup-java@v3 + with: + java-version: '21' + distribution: 'adopt' + + - name: Build with Maven + run: make ja_dependencies + + - name: Run linter + run: make ja_lint + + - name: Check for differences + run: | + # Get the diff from the last commit to the current working tree + if [ -n "$(git diff HEAD)" ]; then + echo "There are changes detected:" + git diff HEAD + exit 1 + else + echo "No changes detected." + fi \ No newline at end of file diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml new file mode 100644 index 00000000..24926dd4 --- /dev/null +++ b/.github/workflows/java.yml @@ -0,0 +1,50 @@ +name: Java + +on: + push: + paths: + - 'java/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + strategy: + fail-fast: false + matrix: + os: ['ubuntu-latest'] + java-version: [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21] + include: + - os: windows-latest + java-version: 21 + - os: macos-latest + java-version: 21 + - os: macos-13 + java-version: 21 + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Java + uses: actions/setup-java@v3 + with: + java-version: ${{ matrix.java-version }} + distribution: 'adopt' + + - name: Build with Maven + run: make ja_dependencies + + - name: Run tests + run: make ja_test + + - name: Upload code coverage to Codecov + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + flags: Java + files: '**.xml' \ No newline at end of file diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 7f6ee792..53f02dae 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -10,6 +10,7 @@ on: - '**/*.cpp' - '**/*.cs' - '**/*.h' + - '**/*.java' - '**/*.js' - '**/*.py' - '**/*.rs' diff --git a/Makefile b/Makefile index 9d25f446..0f98b450 100644 --- a/Makefile +++ b/Makefile @@ -23,9 +23,9 @@ help: @echo @echo "The following jobs are available under the cs_ prefix" @$(MAKE) cs_help $(MFLAGS) --no-print-directory -# @echo -# @echo "The following jobs are available under the ja_ prefix" -# @$(MAKE) ja_help $(MFLAGS) --no-print-directory + @echo + @echo "The following jobs are available under the ja_ prefix" + @$(MAKE) ja_help $(MFLAGS) --no-print-directory @echo @echo "The following jobs are available under the js_ prefix" @$(MAKE) js_help $(MFLAGS) --no-print-directory @@ -54,8 +54,8 @@ c_%: docs_%: @cd docs && $(MAKE) $* $(MFLAGS) -# ja_%: -# @cd java && $(MAKE) $* $(MFLAGS) +ja_%: + @cd java && $(MAKE) $* $(MFLAGS) js_%: @cd javascript && $(MAKE) $* $(MFLAGS) diff --git a/README.rst b/README.rst index 705c1cf9..35a207d5 100644 --- a/README.rst +++ b/README.rst @@ -13,6 +13,10 @@ Olivia's Project Euler Solutions :target: https://github.com/LivInTheLookingGlass/Euler/actions/workflows/csharp.yml .. |C#-lint| image:: https://img.shields.io/github/actions/workflow/status/LivInTheLookingGlass/Euler/csharp-lint.yml?logo=github&label=Linting :target: https://github.com/LivInTheLookingGlass/Euler/actions/workflows/csharp-lint.yml +.. |Javai| image:: https://img.shields.io/github/actions/workflow/status/LivInTheLookingGlass/Euler/java.yml?logo=github&label=Java%20Tests + :target: https://github.com/LivInTheLookingGlass/Euler/actions/workflows/java.yml +.. |Java-lint| image:: https://img.shields.io/github/actions/workflow/status/LivInTheLookingGlass/Euler/java-lint.yml?logo=github&label=Linting + :target: https://github.com/LivInTheLookingGlass/Euler/actions/workflows/java-lint.yml .. |JavaScript| image:: https://img.shields.io/github/actions/workflow/status/LivInTheLookingGlass/Euler/javascript.yml?logo=github&label=Js%20Tests :target: https://github.com/LivInTheLookingGlass/Euler/actions/workflows/javascript.yml .. |ESLint| image:: https://img.shields.io/github/actions/workflow/status/LivInTheLookingGlass/Euler/eslint.yml?logo=github&label=ESLint @@ -33,6 +37,8 @@ Olivia's Project Euler Solutions :target: https://app.codecov.io/github/LivInTheLookingGlass/Euler?flags%5B0%5D=Cpp .. |Cs-Cov| image:: https://img.shields.io/codecov/c/github/LivInTheLookingGlass/Euler?flag=Csharp&logo=codecov&label=C%23%20Cov :target: https://app.codecov.io/github/LivInTheLookingGlass/Euler?flags%5B0%5D=Csharp +.. |Ja-Cov| image:: https://img.shields.io/codecov/c/github/LivInTheLookingGlass/Euler?flag=Java&logo=codecov&label=Java%20Cov + :target: https://app.codecov.io/github/LivInTheLookingGlass/Euler?flags%5B0%5D=Java .. |Js-Cov| image:: https://img.shields.io/codecov/c/github/LivInTheLookingGlass/Euler?flag=JavaScript&logo=codecov&label=Js%20Cov :target: https://app.codecov.io/github/LivInTheLookingGlass/Euler?flags%5B0%5D=JavaScript .. |Py-Cov| image:: https://img.shields.io/codecov/c/github/LivInTheLookingGlass/Euler?flag=Python&logo=codecov&label=Py%20Cov @@ -67,6 +73,11 @@ Olivia's Project Euler Solutions | | | | |CodeQL| |br| | | | | | |C#-lint| | +------------+--------------------------+--------+-------------------+ +| Java | Java 8+ | 2 | |Javai| |br| | +| | | | |Ja-Cov| |br| | +| | | | |CodeQL| |br| | +| | | | |Java-lint| | ++------------+--------------------------+--------+-------------------+ | JavaScript | Node 12+ |br| | 20 | |JavaScript| |br| | | | Bun 1.0+ |br| | | |Js-Cov| |br| | | | Firefox [2]_ |br| | | |CodeQL| |br| | @@ -124,6 +135,7 @@ Makefile will direct recipes using prefixes - ``make cp_*`` will go to the csharp Makefile - ``make cs_*`` will go to the csharp Makefile - ``make docs_*`` will go to the docs Makefile +- ``make ja_*`` will go to the java Makefile - ``make js_*`` will go to the javascript Makefile - ``make py_*`` will go to the python Makefile - ``make rs_*`` will go to the rust Makefile @@ -131,14 +143,3 @@ Makefile will direct recipes using prefixes - All other recipes will be run for all languages For more information, please see the README documents in each section. - -Roadmap -------- - -1. Make sure no language is below Makefile in code percentage -2. For each language in: Ruby, ... - a. Create a new section - b. Make stubs for test code - c. Write minimal documentation - d. Port problems 1-n, until higher than Makefile percentage - e. Repeat step 1 diff --git a/docs/conf.py b/docs/conf.py index 1d540de3..87fc0fef 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -208,3 +208,15 @@ def setup(app): } )) + app.add_domain(custom_domain( + 'JavaDomain', + 'java', + 'Java', + { + 'class': { + }, + 'method': { + }, + } + )) + diff --git a/docs/csharp.rst b/docs/csharp.rst index 51a9f32a..ce35265b 100644 --- a/docs/csharp.rst +++ b/docs/csharp.rst @@ -5,8 +5,8 @@ Euler C# Implementation :start-line: 2 :end-before: Makefile -.. include:: ../rust/README.rst - :start-after: Alias for ``cargo clean`` +.. include:: ../csharp/README.rst + :start-after: dependencies for this section. :end-before: Problems Solved Usage diff --git a/docs/index.rst b/docs/index.rst index e09dc2c9..a49e906d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -31,6 +31,7 @@ Problems Solved .. |C| replace:: **C** .. |Cp| replace:: **C++** .. |C#| replace:: **C#** +.. |Ja| replace:: **Java** .. |Js| replace:: **JavaScript** .. |Py| replace:: **Python** .. |Rs| replace:: **Rust** @@ -56,176 +57,176 @@ Problems Solved .. rst-class:: centertable -+-----------+------------+------------+------------+------------+------------+------------+ -| | |C| | |Cp| | |C#| | |Js| | |Py| | |Rs| | -+===========+============+============+============+============+============+============+ -|Coverage | |d| | |d| | |d| | |d| | |d| | |d| | -+-----------+------------+------------+------------+------------+------------+------------+ -|Docs | |d| | |d| | |d| | |d| | |d| | |d| | -+-----------+------------+------------+------------+------------+------------+------------+ -|Linting | |d| | |d| | |d| | |d| | |d| | |d| | -+-----------+------------+------------+------------+------------+------------+------------+ -|Testing | |d| | |d| | |d| | |d| | |d| | |d| | -+-----------+------------+------------+------------+------------+------------+------------+ -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`1` |:c-d:`0001` |:cp-d:`0001`|:cs-d:`0001`|:js-d:`0001`|:py-d:`0001`|:rs-d:`0001`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`2` |:c-d:`0002` |:cp-d:`0002`|:cs-d:`0002`|:js-d:`0002`|:py-d:`0002`|:rs-d:`0002`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`3` |:c-d:`0003` | | |:js-d:`0003`|:py-d:`0003`|:rs-d:`0003`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`4` |:c-d:`0004` |:cp-d:`0004`|:cs-d:`0004`|:js-d:`0004`|:py-d:`0004`|:rs-d:`0004`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`5` |:c-d:`0005` | | | |:py-d:`0005`|:rs-d:`0005`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`6` |:c-d:`0006` |:cp-d:`0006`|:cs-d:`0006`|:js-d:`0006`|:py-d:`0006`|:rs-d:`0006`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`7` |:c-d:`0007` | | |:js-d:`0007`|:py-d:`0007`|:rs-d:`0007`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`8` |:c-d:`0008` |:cp-d:`0008`|:cs-d:`0008`|:js-d:`0008`|:py-d:`0008`|:rs-d:`0008`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`9` |:c-d:`0009` |:cp-d:`0009`|:cs-d:`0009`|:js-d:`0009`|:py-d:`0009`|:rs-d:`0009`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`10` |:c-d:`0010` | | |:js-d:`0010`|:py-d:`0010`|:rs-d:`0010`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`11` |:c-d:`0011` |:cp-d:`0011`|:cs-d:`0011`|:js-d:`0011`|:py-d:`0011`|:rs-d:`0011`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`12` |:c-s:`0012` | | | |:py-d:`0012`|:rs-d:`0012`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`13` |:c-d:`0013` |:cp-d:`0013`|:cs-d:`0013`|:js-d:`0013`|:py-d:`0013`|:rs-d:`0013`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`14` |:c-d:`0014` |:cp-d:`0014`|:cs-d:`0014`|:js-d:`0014`|:py-d:`0014`|:rs-d:`0014`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`15` |:c-d:`0015` |:cp-d:`0015`|:cs-d:`0015`|:js-d:`0015`|:py-d:`0015`|:rs-d:`0015`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`16` |:c-d:`0016` |:cp-d:`0016`|:cs-d:`0016`|:js-d:`0016`|:py-d:`0016`|:rs-d:`0016`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`17` |:c-d:`0017` |:cp-d:`0017`|:cs-d:`0017`|:js-d:`0017`|:py-d:`0017`|:rs-d:`0017`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`18` | | | | |:py-d:`0018`|:rs-d:`0018`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`19` | | | | |:py-d:`0019`|:rs-d:`0019`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`20` |:c-d:`0020` |:cp-d:`0020`|:cs-d:`0020`|:js-d:`0020`|:py-d:`0020`|:rs-d:`0020`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`21` | | | | |:py-d:`0021`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`22` |:c-d:`0022` |:cp-d:`0022`|:cs-d:`0022`|:js-d:`0022`|:py-d:`0022`|:rs-d:`0022`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`23` | | | | |:py-d:`0023`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`24` | | | | |:py-d:`0024`|:rs-d:`0024`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`25` | | | | |:py-d:`0025`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`27` | | | | |:py-d:`0027`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`28` | | | | |:py-d:`0028`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`29` | | | | |:py-d:`0029`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`30` | | | | |:py-d:`0030`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`31` | | | | |:py-d:`0031`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`32` | | | | |:py-d:`0032`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`33` | | | | |:py-d:`0033`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`34` |:c-d:`0034` |:cp-d:`0034`|:cs-d:`0034`|:js-d:`0034`|:py-d:`0034`|:rs-d:`0034`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`35` | | | | |:py-d:`0035`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`36` | | | | |:py-d:`0036`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`37` | | | | |:py-d:`0037`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`38` | | | | |:py-d:`0038`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`39` | | | | |:py-d:`0039`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`40` | | | | |:py-d:`0040`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`41` | | | | |:py-d:`0041`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`42` | | | | |:py-d:`0042`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`43` | | | | |:py-d:`0043`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`44` | | | | |:py-d:`0044`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`45` | | | | |:py-d:`0045`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`46` | | | | |:py-d:`0046`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`47` | | | | |:py-d:`0047`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`48` | | | | |:py-d:`0048`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`49` | | | | |:py-d:`0049`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`50` | | | | |:py-d:`0050`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`52` | | | | |:py-d:`0052`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`53` | | | | |:py-d:`0053`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`55` | | | | |:py-d:`0055`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`56` | | | | |:py-d:`0056`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`57` | | | | |:py-d:`0057`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`58` | | | | |:py-d:`0058`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`59` | | | | |:py-d:`0059`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`60` | | | | |:py-d:`0060`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`63` | | | | |:py-d:`0063`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`67` | | | | |:py-d:`0067`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`69` | | | | |:py-d:`0069`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`71` | | | | |:py-d:`0071`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`73` | | | | |:py-d:`0073`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`74` | | | | |:py-d:`0074`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`76` |:c-d:`0076` |:cp-d:`0076`|:cs-s:`0076`|:js-s:`0076`|:py-d:`0076`|:rs-d:`0076`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`77` | | | | |:py-d:`0077`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`81` | | | | |:py-d:`0081`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`87` | | | | |:py-d:`0087`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`89` | | | | |:py-d:`0089`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`92` | | | | |:py-d:`0092`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`97` | | | | |:py-d:`0097`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`99` | | | | |:py-d:`0099`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`118`| | | | |:py-s:`0118`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`123`| | | | |:py-d:`0123`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`134`| | | | |:py-d:`0134`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`145`| | | | |:py-d:`0145`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`187`| | | | |:py-d:`0187`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`206`| | | | |:py-d:`0206`| | -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`357`| | | | |:py-s:`0357`|:rs-i:`0357`| -+-----------+------------+------------+------------+------------+------------+------------+ -|:prob:`836`|:c-d:`0836` |:cp-d:`0836`|:cs-d:`0836`|:js-d:`0836`|:py-d:`0836`|:rs-d:`0836`| -+-----------+------------+------------+------------+------------+------------+------------+ ++-----------+------------+------------+------------+------------+------------+------------+------------+ +| | |C| | |Cp| | |C#| | |Ja| | |Js| | |Py| | |Rs| | ++===========+============+============+============+============+============+============+============+ +|Coverage | |d| | |d| | |d| | |ip| | |d| | |d| | |d| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|Docs | |d| | |d| | |d| | |ip| | |d| | |d| | |d| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|Linting | |d| | |d| | |d| | |ip| | |d| | |d| | |d| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|Testing | |d| | |d| | |d| | |ip| | |d| | |d| | |d| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`1` |:c-d:`0001` |:cp-d:`0001`|:cs-d:`0001`|:ja-i:`0001`|:js-d:`0001`|:py-d:`0001`|:rs-d:`0001`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`2` |:c-d:`0002` |:cp-d:`0002`|:cs-d:`0002`| |:js-d:`0002`|:py-d:`0002`|:rs-d:`0002`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`3` |:c-d:`0003` | | | |:js-d:`0003`|:py-d:`0003`|:rs-d:`0003`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`4` |:c-d:`0004` |:cp-d:`0004`|:cs-d:`0004`| |:js-d:`0004`|:py-d:`0004`|:rs-d:`0004`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`5` |:c-d:`0005` | | | | |:py-d:`0005`|:rs-d:`0005`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`6` |:c-d:`0006` |:cp-d:`0006`|:cs-d:`0006`| |:js-d:`0006`|:py-d:`0006`|:rs-d:`0006`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`7` |:c-d:`0007` | | | |:js-d:`0007`|:py-d:`0007`|:rs-d:`0007`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`8` |:c-d:`0008` |:cp-d:`0008`|:cs-d:`0008`| |:js-d:`0008`|:py-d:`0008`|:rs-d:`0008`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`9` |:c-d:`0009` |:cp-d:`0009`|:cs-d:`0009`| |:js-d:`0009`|:py-d:`0009`|:rs-d:`0009`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`10` |:c-d:`0010` | | | |:js-d:`0010`|:py-d:`0010`|:rs-d:`0010`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`11` |:c-d:`0011` |:cp-d:`0011`|:cs-d:`0011`| |:js-d:`0011`|:py-d:`0011`|:rs-d:`0011`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`12` |:c-s:`0012` | | | | |:py-d:`0012`|:rs-d:`0012`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`13` |:c-d:`0013` |:cp-d:`0013`|:cs-d:`0013`| |:js-d:`0013`|:py-d:`0013`|:rs-d:`0013`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`14` |:c-d:`0014` |:cp-d:`0014`|:cs-d:`0014`| |:js-d:`0014`|:py-d:`0014`|:rs-d:`0014`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`15` |:c-d:`0015` |:cp-d:`0015`|:cs-d:`0015`| |:js-d:`0015`|:py-d:`0015`|:rs-d:`0015`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`16` |:c-d:`0016` |:cp-d:`0016`|:cs-d:`0016`| |:js-d:`0016`|:py-d:`0016`|:rs-d:`0016`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`17` |:c-d:`0017` |:cp-d:`0017`|:cs-d:`0017`| |:js-d:`0017`|:py-d:`0017`|:rs-d:`0017`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`18` | | | | | |:py-d:`0018`|:rs-d:`0018`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`19` | | | | | |:py-d:`0019`|:rs-d:`0019`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`20` |:c-d:`0020` |:cp-d:`0020`|:cs-d:`0020`| |:js-d:`0020`|:py-d:`0020`|:rs-d:`0020`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`21` | | | | | |:py-d:`0021`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`22` |:c-d:`0022` |:cp-d:`0022`|:cs-d:`0022`| |:js-d:`0022`|:py-d:`0022`|:rs-d:`0022`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`23` | | | | | |:py-d:`0023`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`24` | | | | | |:py-d:`0024`|:rs-d:`0024`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`25` | | | | | |:py-d:`0025`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`27` | | | | | |:py-d:`0027`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`28` | | | | | |:py-d:`0028`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`29` | | | | | |:py-d:`0029`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`30` | | | | | |:py-d:`0030`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`31` | | | | | |:py-d:`0031`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`32` | | | | | |:py-d:`0032`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`33` | | | | | |:py-d:`0033`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`34` |:c-d:`0034` |:cp-d:`0034`|:cs-d:`0034`| |:js-d:`0034`|:py-d:`0034`|:rs-d:`0034`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`35` | | | | | |:py-d:`0035`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`36` | | | | | |:py-d:`0036`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`37` | | | | | |:py-d:`0037`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`38` | | | | | |:py-d:`0038`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`39` | | | | | |:py-d:`0039`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`40` | | | | | |:py-d:`0040`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`41` | | | | | |:py-d:`0041`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`42` | | | | | |:py-d:`0042`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`43` | | | | | |:py-d:`0043`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`44` | | | | | |:py-d:`0044`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`45` | | | | | |:py-d:`0045`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`46` | | | | | |:py-d:`0046`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`47` | | | | | |:py-d:`0047`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`48` | | | | | |:py-d:`0048`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`49` | | | | | |:py-d:`0049`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`50` | | | | | |:py-d:`0050`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`52` | | | | | |:py-d:`0052`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`53` | | | | | |:py-d:`0053`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`55` | | | | | |:py-d:`0055`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`56` | | | | | |:py-d:`0056`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`57` | | | | | |:py-d:`0057`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`58` | | | | | |:py-d:`0058`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`59` | | | | | |:py-d:`0059`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`60` | | | | | |:py-d:`0060`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`63` | | | | | |:py-d:`0063`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`67` | | | | | |:py-d:`0067`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`69` | | | | | |:py-d:`0069`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`71` | | | | | |:py-d:`0071`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`73` | | | | | |:py-d:`0073`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`74` | | | | | |:py-d:`0074`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`76` |:c-d:`0076` |:cp-d:`0076`|:cs-s:`0076`| |:js-s:`0076`|:py-d:`0076`|:rs-d:`0076`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`77` | | | | | |:py-d:`0077`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`81` | | | | | |:py-d:`0081`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`87` | | | | | |:py-d:`0087`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`89` | | | | | |:py-d:`0089`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`92` | | | | | |:py-d:`0092`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`97` | | | | | |:py-d:`0097`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`99` | | | | | |:py-d:`0099`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`118`| | | | | |:py-s:`0118`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`123`| | | | | |:py-d:`0123`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`134`| | | | | |:py-d:`0134`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`145`| | | | | |:py-d:`0145`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`187`| | | | | |:py-d:`0187`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`206`| | | | | |:py-d:`0206`| | ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`357`| | | | | |:py-s:`0357`|:rs-i:`0357`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ +|:prob:`836`|:c-d:`0836` |:cp-d:`0836`|:cs-d:`0836`|:ja-i:`0836`|:js-d:`0836`|:py-d:`0836`|:rs-d:`0836`| ++-----------+------------+------------+------------+------------+------------+------------+------------+ .. toctree:: :maxdepth: 2 @@ -234,6 +235,7 @@ Problems Solved c cplusplus csharp + java javascript python rust diff --git a/docs/java.rst b/docs/java.rst new file mode 100644 index 00000000..78b0c063 --- /dev/null +++ b/docs/java.rst @@ -0,0 +1,81 @@ +Euler Java Implementation +======================= + +.. include:: ../java/README.rst + :start-line: 2 + :end-before: Makefile + +.. include:: ../java/README.rst + :start-after: dependencies for this section. + :end-before: Problems Solved + +Usage +----- + +.. highlight:: make + +This folder contains a Makefile with several recipes, most of which are aliases to ``dotnet`` commands. +This facilitates the root Makefile dispatching tasks to each language, many of which have more complex +build or test processes. + +.. make:target:: test + + Alias for ``maven test -Dtest.single``. + +.. make:target:: test_auto + + .. note:: + + WIP + + Runs tests in parallel with one less thread than you have CPUs. Alias for ``maven test-T 1C``. + +.. make:target:: test_% + + .. note:: + + WIP + + Runs tests in parallel with the specified number of threads. Alias for ``maven test -T $*``. + +.. make:target:: clean + + Alias for ``maven clean``, with some degree of fallback if ``maven`` is not installed. + +.. make:target:: lint + + Alias for ``maven formatter:format``. + +Test Infrastructure +------------------- + +.. java:class:: IEuler + + .. java:method:: Object answer() + +.. java:class:: EulerTest + + .. java:method:: void eulerTestProblem() + + A JUnit theory that, for each registered solution, will test against the known answer and a one minute time limit. + +Library Code +------------ + +.. toctree:: + :numbered: + :maxdepth: 1 + + java/math + java/primes + java/utils + +Problems Solved +--------------- + +.. toctree:: + :glob: + :numbered: + :maxdepth: 1 + + java/p[0-9][0-9][0-9][0-9] \ No newline at end of file diff --git a/docs/java/p0001.rst b/docs/java/p0001.rst new file mode 100644 index 00000000..787a48ad --- /dev/null +++ b/docs/java/p0001.rst @@ -0,0 +1,12 @@ +Java Implementation of Problem 1 +================================ + +View source code :source:`java/src/main/java/euler/p0001.java` + +.. java:class:: p0001 implements Euler.IEuler + + .. java:method:: Object answer() + +.. literalinclude:: ../../java/src/main/java/euler/p0001.java + :language: java + :linenos: diff --git a/docs/java/p0836.rst b/docs/java/p0836.rst new file mode 100644 index 00000000..8fdd696c --- /dev/null +++ b/docs/java/p0836.rst @@ -0,0 +1,12 @@ +Java Implementation of Problem 836 +================================== + +View source code :source:`java/src/main/java/euler/p0836.java` + +.. java:class:: p0836 implements Euler.IEuler + + .. java:method:: Object answer() + +.. literalinclude:: ../../java/src/main/java/euler/p0836.java + :language: java + :linenos: diff --git a/java/Makefile b/java/Makefile new file mode 100644 index 00000000..dc355112 --- /dev/null +++ b/java/Makefile @@ -0,0 +1,28 @@ +MVN?=mvn +BLUE=\033[0;34m +NC=\033[0m # No Color + +help: + @echo " $(BLUE)test$(NC) run through all tests in sequence" + @echo " $(BLUE)test_*$(NC) run through all tests in parallel with the given number of threads. Use auto to allow the test runner to determine it" + @echo " $(BLUE)dependencies$(NC) grabs all dependencies through maven" + @echo " $(BLUE)clean$(NC) clean up any stray files" + @echo " $(BLUE)lint$(NC) Run the maven formatter" + +clean: + $(MVN) clean || echo + +dependencies: + $(MVN) install -B + +test: dependencies + $(MVN) test -Dtest.single + +test_auto: dependencies + $(MVN) test -T 1C + +test_%: dependencies + $(MVN) test -T $* + +lint: + $(MVN) formatter:format \ No newline at end of file diff --git a/java/README.rst b/java/README.rst new file mode 100644 index 00000000..487a1929 --- /dev/null +++ b/java/README.rst @@ -0,0 +1,78 @@ +Java Section +============ + +.. |Java Check| image:: https://github.com/LivInTheLookingGlass/Euler/actions/workflows/java.yml/badge.svg + :target: https://github.com/LivInTheLookingGlass/Euler/actions/workflows/java.yml + +|Java Check| + +All problems are solved in Java 8+. + +Organization +------------ + +All Java files share a common prefix with their problem number. All shared +functions are defined in the include folder. + +Makefile +-------- + +There are three main recipes in this Makefile + +dependencies +~~~~~~~~~~~~ + +This recipe installs all the required and test dependencies. See the +Dependencies section for more info + +test +~~~~ + +This recipe runs tests in multiple threads + +lint +~~~~ + +This recipe runs ``maven``\ s builtin formatter + +Tests +----- + +Prime Infrastructure Test +~~~~~~~~~~~~~~~~~~~~~~~~~ + +This test checks five things: + +1. It checks ``is_prime()`` for numbers up to ``MAX_PRIME``, where that + is defined in the test +2. It checks that ``is_composite()`` returns truthy values on composites + in that range, and falsey values on primes +3. It checks that ``is_composite()`` returns the smallest prime factor + on composite numbers +4. It checks that the prime numbers are generated in the correct order +5. It checks that all these operations are completed in less than 200ns + \* ``MAX_PRIME`` + +Generic Problems +~~~~~~~~~~~~~~~~ + +For each problem it will check the answer against a known dictionary. If +the problem is not in the "known slow" category (meaning that I generate +the correct answer with a poor solution), it will always be run. +Otherwise it tries to detect the ``NO_SLOW`` environment variable and +dynamically skip them. + +A test fails if it gets the wrong answer or if it takes more than 1 +minute. + +Dependencies +------------ + +I try to keep the dependencies of this project as small as possible, +except for test plugins. At the moment there are no non-test +dependencies for this section. + +Problems Solved +--------------- + +- ☒ `1 <./src/main/p0001.java>`__ diff --git a/java/pom.xml b/java/pom.xml new file mode 100644 index 00000000..13e3ece8 --- /dev/null +++ b/java/pom.xml @@ -0,0 +1,54 @@ + + 4.0.0 + euler + java + 1.0-SNAPSHOT + + + + + org.junit.jupiter + junit-jupiter-api + 5.8.2 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.8.2 + test + + + org.junit.jupiter + junit-jupiter-params + 5.8.2 + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + **/*Test.java + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/java/src/main/java/euler/IEuler.java b/java/src/main/java/euler/IEuler.java new file mode 100644 index 00000000..a93a47e3 --- /dev/null +++ b/java/src/main/java/euler/IEuler.java @@ -0,0 +1,5 @@ +package euler; + +public interface IEuler { + Object answer(); +} \ No newline at end of file diff --git a/java/src/main/java/euler/lib/Utilities.java b/java/src/main/java/euler/lib/Utilities.java new file mode 100644 index 00000000..5ecd9fd6 --- /dev/null +++ b/java/src/main/java/euler/lib/Utilities.java @@ -0,0 +1,95 @@ +package euler; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class Utilities { + + private static Path getDataPath(String name) throws IOException { + String absolutePath; + try { + ClassLoader classLoader = Utilities.class.getClassLoader(); + File file = new File(classLoader.getResource("Utilities.class").toURI()); + absolutePath = file.getAbsolutePath(); + } catch (URISyntaxException e) { + e.printStackTrace(); + throw new IOException(); + } + if (absolutePath == null) { + throw new IOException("Unable to determine file path."); + } + Path filePath = Paths.get(absolutePath).getParent().resolve("../../../../../_data").resolve(name); + return filePath.toAbsolutePath(); + } + + public static String getDataFileText(String name) throws IOException { + Path filePath = getDataPath(name); + return new String(Files.readAllBytes(filePath)); + } + + public static byte[] getDataFileBytes(String name) throws IOException { + Path filePath = getDataPath(name); + return Files.readAllBytes(filePath); + } + + public static Object getAnswer(long n) throws IOException { + String csvContent = getDataFileText("answers.csv"); + try (BufferedReader reader = new BufferedReader(new StringReader(csvContent))) { + String line; + while ((line = reader.readLine()) != null) { + String[] arr = line.split("\t"); + if (arr.length < 4) continue; + long key = Long.parseLong(arr[0]); + if (key != n) continue; + + String type = arr[1]; + int bitLength = Integer.parseInt(arr[2]); + String value = arr[3]; + + switch (type) { + case "str": + return value; + case "int": + switch (bitLength) { + case 8: + return (byte)Integer.parseInt(value); + case 16: + return (short)Integer.parseInt(value); + case 32: + return Integer.parseInt(value); + case 64: + return Long.parseLong(value); + default: + // no return, just continue + } + break; + case "uint": + switch (bitLength) { + case 8: + return (byte)Integer.parseUnsignedInt(value); + case 16: + return (short)Integer.parseUnsignedInt(value); + case 32: + return Integer.parseUnsignedInt(value); + case 64: + return Long.parseUnsignedLong(value); + default: + // no return, just continue + } + default: + // no return, just continue + } + + // If no valid type or bit length was found + throw new IOException("Unsupported type/length: " + type + ", " + bitLength); + } + } + throw new IOException("Answer not found."); + } +} \ No newline at end of file diff --git a/java/src/main/java/euler/p0000.java b/java/src/main/java/euler/p0000.java new file mode 100644 index 00000000..144103ee --- /dev/null +++ b/java/src/main/java/euler/p0000.java @@ -0,0 +1,8 @@ +package euler; + +public class p0000 implements IEuler { + @Override + public Object answer() { + return 0; + } +} \ No newline at end of file diff --git a/java/src/main/java/euler/p0001.java b/java/src/main/java/euler/p0001.java new file mode 100644 index 00000000..318888f9 --- /dev/null +++ b/java/src/main/java/euler/p0001.java @@ -0,0 +1,18 @@ +package euler; + +public class p0001 implements IEuler { + @Override + public Object answer() { + int answer = 0; + for (int i = 0; i < 1000; i += 3) + answer += i; + + for (int i = 0; i < 1000; i += 5) + answer += i; + + for (int i = 0; i < 1000; i += 15) + answer -= i; + + return answer; + } +} \ No newline at end of file diff --git a/java/src/main/java/euler/p0836.java b/java/src/main/java/euler/p0836.java new file mode 100644 index 00000000..b8b7a755 --- /dev/null +++ b/java/src/main/java/euler/p0836.java @@ -0,0 +1,8 @@ +package euler; + +public class p0836 implements IEuler { + @Override + public Object answer() { + return "aprilfoolsjoke"; + } +} \ No newline at end of file diff --git a/java/src/test/java/EulerTest.java b/java/src/test/java/EulerTest.java new file mode 100644 index 00000000..4746a0b0 --- /dev/null +++ b/java/src/test/java/EulerTest.java @@ -0,0 +1,53 @@ +package euler; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.api.Assertions; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.stream.Stream; + +public class EulerTest { + private static final long ONE_MINUTE_NS = 60_000_000_000L; // 1 minute in nanoseconds + + // Data provider for parameterized tests + static Stream data() throws IOException { + return Stream.of( + new Object[]{p0000.class, false, 0}, + new Object[]{p0001.class, false, Utilities.getAnswer(1)}, + // new Object[]{p0002.class, false, Utilities.getAnswer(2)}, + // new Object[]{p0004.class, false, Utilities.getAnswer(4)}, + // new Object[]{p0006.class, false, Utilities.getAnswer(6)}, + // new Object[]{p0008.class, false, Utilities.getAnswer(8)}, + // new Object[]{p0009.class, false, Utilities.getAnswer(9)}, + // new Object[]{p0011.class, false, Utilities.getAnswer(11)}, + // new Object[]{p0013.class, false, Utilities.getAnswer(13)}, + // new Object[]{p0014.class, false, Utilities.getAnswer(14)}, + // new Object[]{p0015.class, false, Utilities.getAnswer(15)}, + // new Object[]{p0016.class, false, Utilities.getAnswer(16)}, + // new Object[]{p0017.class, false, Utilities.getAnswer(17)}, + // new Object[]{p0020.class, false, Utilities.getAnswer(20)}, + // new Object[]{p0022.class, false, Utilities.getAnswer(22)}, + // new Object[]{p0034.class, false, Utilities.getAnswer(34)}, + // new Object[]{p0076.class, true, Utilities.getAnswer(76)}, + new Object[]{p0836.class, false, Utilities.getAnswer(836)} + ); + } + + @ParameterizedTest + @MethodSource("data") + void eulerTestProblem(Class problemClass, boolean isSlow, Object expected) throws Exception, IOException { + Assertions.assertTrue(IEuler.class.isAssignableFrom(problemClass), + "Class does not implement IEuler: " + problemClass.getName()); + Method answerMethod = problemClass.getMethod("answer"); + IEuler instance = (IEuler)problemClass.getDeclaredConstructor().newInstance(); + long startTime = System.nanoTime(); + Object result = answerMethod.invoke(instance); // Instance method invocation + long elapsedTime = System.nanoTime() - startTime; + Assertions.assertEquals(expected, result); + if (!isSlow) { + Assertions.assertTrue(elapsedTime <= ONE_MINUTE_NS, "Test took too long"); + } + } +} \ No newline at end of file