{"id":17998438,"url":"https://github.com/shchmue/euler14","last_synced_at":"2026-04-30T01:33:32.634Z","repository":{"id":114846942,"uuid":"125560849","full_name":"shchmue/euler14","owner":"shchmue","description":"Optimizations on Project Euler problem #14","archived":false,"fork":false,"pushed_at":"2018-03-16T22:13:25.000Z","size":33,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-09T18:12:20.057Z","etag":null,"topics":["euler-problem","numba","python3"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shchmue.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-16T19:26:18.000Z","updated_at":"2018-03-18T18:14:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"88b3db90-4341-4984-a944-482308de05a1","html_url":"https://github.com/shchmue/euler14","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shchmue%2Feuler14","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shchmue%2Feuler14/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shchmue%2Feuler14/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shchmue%2Feuler14/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shchmue","download_url":"https://codeload.github.com/shchmue/euler14/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247135123,"owners_count":20889420,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["euler-problem","numba","python3"],"created_at":"2024-10-29T21:25:21.037Z","updated_at":"2026-04-30T01:33:27.587Z","avatar_url":"https://github.com/shchmue.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Project Euler problem 14 solutions\n\n### About\nA collection of solution optimizations for [Project Euler problem 14](https://projecteuler.net/problem=14) regarding delay records for testing the [Collatz conjecture](https://en.wikipedia.org/wiki/Collatz_conjecture) in Python, C++ and x64 Assembly. I originally solved the problem in 2010 but recently used it to practice different optimization techniques and languages.\n\n### Background\nThe procedure is very straightforward. Starting with some number `n`, follow a simple iterative procedure:\n* if even, divide by 2\n* if odd, multiply by 3 and add 1\n* if 1, finish\n\nThese programs try all starting numbers below a specified limit and find the longest chain. There's no way to predict the length of a chain given the starting value. You can cache results, but that requires `O(n)` space. Chain length grows very slowly\u0026mdash;the longest chain below `10^10` has `1133` steps\u0026mdash;but that's still almost 19 gigabytes with lengths stored as 16-bit ints!\n\nSimply, there is no practical early termination condition.\u003csup\u003e1\u003c/sup\u003e\n\nTherefore I focused first on shrinking search space and second on using faster languages and libraries. Note that unsigned 64-bit ints can handle the intermediate values in chains for any limit up to `10^10`.\n\n\u003csup\u003e1\u003c/sup\u003e Of course there's finishing when you reach a power of 2, but the savings there are minimal, especially when using bit shifts and [count trailing zeros](https://en.wikipedia.org/wiki/Find_first_set).\n\n### Examples of improvements\n* naive solution\n* search space narrowing: `n mod 96` must be in `[1, 7, 9, 15, 25, 27, 31, 33, 39, 43, 57, 63, 73, 75, 79, 91]` - only checking `16/96` or `1/6` of the numbers\u003csup\u003e2\u003c/sup\u003e\n* Python [Numba](http://numba.pydata.org/) library JIT compiler\n* Python [Multiprocessing](https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing.dummy) package\n* efficient wheel implementation of search space scan\n* bit packing the wheel\n* compiler intrinsics (specifically [bit scan forward/count trailing zeros](https://en.wikipedia.org/wiki/Find_first_set))\n* pure x64 assembly implementation\n\n   \u003csup\u003e2\u003c/sup\u003e there are several known records produced by numbers that fall outside this set (including even numbers, eg. `6, 18, 54, 31466382`). However, most with limit `10^N` fall inside it. See http://www.ericr.nl/wondrous/delrecs.html for a list of known records.\n\nBenchmark results are included in `eul14 benchmarks.txt` and all ran on my over-the-hill `Core i7-920 @ 2.67 GHz`\n\n### Code usage\n* Each source file is self-contained and should run in the interpreter or compile as appropriate\n* C++ files require C++11 for timing via `\u003cchrono\u003e`\n* Preprocessor uses either [GCC](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html) or [MSVC++](https://docs.microsoft.com/en-us/cpp/intrinsics/x64-amd64-intrinsics-list) intrinsics\n* Assembly code uses MASM syntax and was tested with [ML64](https://docs.microsoft.com/en-us/cpp/assembler/masm/masm-for-x64-ml64-exe) packaged with Visual Studio 2017\n\n### Future plans\n* C++ multithreading!\n* GPU would be nice but this problem may not be a good candidate due to extreme variability and unpredictability of chain lengths\n\nSpecial thanks to [Eric Roosendaal's 3x + 1 Problem compendium](http://www.ericr.nl/wondrous/) for ideas on narrowing search space\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshchmue%2Feuler14","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshchmue%2Feuler14","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshchmue%2Feuler14/lists"}