{"id":22825888,"url":"https://github.com/tylerburdsall/lazy-cartesian-product","last_synced_at":"2025-07-02T17:34:41.266Z","repository":{"id":95611133,"uuid":"132051310","full_name":"tylerburdsall/lazy-cartesian-product","owner":"tylerburdsall","description":".hpp library to efficiently generate combinations using the Lazy Cartesian Product algorithm","archived":false,"fork":false,"pushed_at":"2019-01-01T20:20:22.000Z","size":55,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-04T23:56:11.879Z","etag":null,"topics":["cartesian","cartesian-product","combinations","cpp","cross-join","distinct","generate","generation","hpp","hpp-library","lazy","random","stl","unique"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tylerburdsall.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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-05-03T21:26:09.000Z","updated_at":"2024-02-23T12:44:39.000Z","dependencies_parsed_at":"2023-05-21T02:15:23.726Z","dependency_job_id":null,"html_url":"https://github.com/tylerburdsall/lazy-cartesian-product","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tylerburdsall/lazy-cartesian-product","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerburdsall%2Flazy-cartesian-product","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerburdsall%2Flazy-cartesian-product/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerburdsall%2Flazy-cartesian-product/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerburdsall%2Flazy-cartesian-product/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tylerburdsall","download_url":"https://codeload.github.com/tylerburdsall/lazy-cartesian-product/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerburdsall%2Flazy-cartesian-product/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263184965,"owners_count":23427121,"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":["cartesian","cartesian-product","combinations","cpp","cross-join","distinct","generate","generation","hpp","hpp-library","lazy","random","stl","unique"],"created_at":"2024-12-12T17:12:23.989Z","updated_at":"2025-07-02T17:34:41.230Z","avatar_url":"https://github.com/tylerburdsall.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lazy-cartesian-product\nA small .hpp library that can generate combinations with a focus on memory-efficiency\n\n## Introduction\nWhen generating data, it may be necessary to create a set of distinct possible combinations. This can be useful for statistics, filling up a database, or running some function over the a combination (like generating cost data given combination `{x, y, z}`). A lot of libraries exist to do this, but memory space can quickly run out when the amount of combinations rises to a very large number.\n\nThis library also provides the flexibility of operating on VERY large sets of data. If you have [Boost](https://www.boost.org) installed, you can utilize its features and operate on numbers from 0 - 2^1024 - 1. (See the **Installation** section for more).\n\nIf you would like to see how this library was implemented, [combigen](https://github.com/iamtheburd/combigen) is a CLI tool that helps generate distinct combinations and output them to `.csv` or `.json` format.\n\n## Usage\nInput will always be a `vector\u003cvector\u003cstring\u003e\u003e`. This keeps things nice and simple, and you can always convert back as necessary in your own projects. There are some public functions available from the library:\n\n* `entry_at` - Generates the *nth* combination at entry `index`\n* `generate_samples` - Generates a random (distinct, evenly spread out) subset of possible combinations of size `sample_size`\n* `compute_max_size` - Computes the maximum amount of possible combinations\n* `generate_random_indices` - Given the desired sample size and the maximum size, this function will return a `set` containing an evenly-distributed list of indices throughout the range given.\n\nIf you use the `boost` library, all of the above functions will instead be prepended with `boost_` (see more in **Example Usage**).\n\nThis project is also licensed under the MIT license, so feel free to use and change this however you please.\n\n## Installation\nSimply place the `.hpp` file somewhere in your project and include the class:\n\n```\n...\n#include \"lazy-cartesian-product.hpp\"\n...\n\n\nusing lazycp::lazy-cartesian-product; // For easier access\n...\n```\n\nWhen compiling your project, ensure that it compiles to the C++14 standard (`-std=c++14` flag for g++). \n\n## Prerequisites:\nYou will need the following installed before including this library into your project:\n\n### Linux:\n* C++ compiler capable of compiling to the C++14 or higher standard\n* [Boost](https://www.boost.org) if you plan to operate with large sets of data/numbers\n\nYou can also use your distro's package manager to install the necessary Boost libraries:\n\n#### Debian/Ubuntu\n`$ sudo apt install libboost-all-dev`\n\n#### Fedora\n`$ sudo dnf install boost`\n\n#### Arch/Manjaro/Antergos\n`$ sudo pacman -Sy boost`\n\n\n### Windows:\n* Visual Studio 2015+\n* Boost, either installed system-wide or you've downloaded the precompiled libraries for your system and placed them somewhere easy to remember\n\n### Compiling with Boost functionality\nIf you need to operate on larger sets of data, it is recommended to install the Boost library. Follow the appropriate instructions for your operating system to install `boost` onto your machine.\n\n#### Linux/UNIX/Cygwin\nAssuming you had one file called `main.cpp`, you can simply compile with the following line:\n\n```\n$ g++ -Wall -O2 -std=c++14 -DUSE_BOOST main.cpp -lboost_random  # Note: it is crucial the -lboost_random flag comes last\n```\n\n#### Windows\n1. Open up the x64 version of the Visual Studio compiler (usually found under Start Menu -\u003e Visual Studio 20XX -\u003e x64 Native Tools Command Propmpt for VS 20XX), with XX being your installed version\n2. Navigate to the directory where your project is located\n3. Assuming you are just straight-compiling your source files and downloaded the precompiled libraries, enter this command:\n```\ncl /EHsc /DUSE_BOOST /I C:\\path\\to\\boost_1_68_0 main.cpp /link /LIBPATH:C:\\path\\to\\boost_1_68_0\\lib64-msvc-14.1\n```\n\nIf you would like to see a more complex compilation example take a look at the [combigen Makefile](https://github.com/iamtheburd/combigen/blob/master/Makefile).\n\n## Example Usage\nWhile `lazy-cartesian-product` can be used in many situations, below are a few examples showcasing some of the functions of the library:\n\n### Basic Example (without Boost)\nFirst, we can generate a possible combination at the *nth* entry. For this example, we can find the combination of pizza components at the 5th entry.\n\n```cpp\n#include \u003cstring\u003e\n#include \u003cvector\u003e\n#include \u003ciostream\u003e\n#include \"lazy-cartesian-product.hpp\"   // Assumes the .hpp file is in the same directory\n\nusing std::cout;\nusing std::vector;\n\nusing lazycp::lazy_cartesian_product;   // For easier readability\n\n\nint main (int argc, char* argv[])\n{\n     vector\u003cstring\u003e crusts   = { \"Thin\", \"Thick\", \"Cheese-stuffed\", \"Garlic-rubbed\" };\n     vector\u003cstring\u003e sauces   = { \"Marinara\", \"BBQ\", \"None\" };\n     vector\u003cstring\u003e cheeses  = { \"Mozarella\", \"Cheddar\", \"Parmesan\" };\n     vector\u003cstring\u003e toppings = { \"Extra Cheese\", \"Chicken\", \"Pepperoni\", \"Sausage\" };\n\n     // Put all of the vectors together so lazy-cartesian-product can accept the input\n     vector\u003cvector\u003cstring\u003e\u003e possibilities = { crusts, sauces, cheeses, toppings };\n\n     // Show the combination at the 5th index\n     vector\u003cstring\u003e result = lazy_cartesian_product::entry_at(possibilities, 5);\n\n     // Display this result:\n     //    \"Mozarella, Thin, BBQ, Chicken, \"\n     for (const string \u0026entry: result)\n     {\n        cout \u003c\u003c result \u003c\u003c \", \";\n     }\n     cout \u003c\u003c \"\\n\";\n \n     return 0;\n}\n```\n\n\n### Generate Random Sample (Performance, without Boost)\nNext, we will generate a random sample of combinations. This is especially useful\nfor data analysis when data needs to be generated in an evenly-distributed manner.\nThis example focuses on high-performance at the expense of memory usage (for large-computations, of course).\n\n```cpp\n#include \u003cstring\u003e\n#include \u003cvector\u003e\n#include \u003ciostream\u003e\n#include \"lazy-cartesian-product.hpp\"\n\nusing std::cout;\nusing std::vector;\n\nusing lazycp::lazy_cartesian_product;   \n\n\nint main (int argc, char* argv[])\n{\n     vector\u003cstring\u003e crusts   = { \"Thin\", \"Thick\", \"Cheese-stuffed\", \"Garlic-rubbed\" };\n     vector\u003cstring\u003e sauces   = { \"Marinara\", \"BBQ\", \"None\" };\n     vector\u003cstring\u003e cheeses  = { \"Mozarella\", \"Cheddar\", \"Parmesan\" };\n     vector\u003cstring\u003e toppings = { \"Extra Cheese\", \"Chicken\", \"Pepperoni\", \"Sausage\" };\n\n     vector\u003cvector\u003cstring\u003e\u003e possibilities = { crusts, sauces, cheeses, toppings };\n    \n     // Generate 10 random samples\n     vector\u003cvector\u003cstring\u003e\u003e random_samples = lazy_cartesian_product::generate_samples(possibilities, 10);\n\n     /* Displayed these results:\n            Mozarella, Thin, Marinara, Sausage,\n            Mozarella, Cheese-stuffed, Marinara, Chicken,\n            Mozarella, Cheese-stuffed, None, Extra Cheese,\n            Cheddar, Thin, None, Chicken\n            Cheddar, Thick, Marinara, Extra Cheese\n            Cheddar, Cheese-stuffed, None, Sausage\n            Cheddar, Garlic-rubbed, BBQ, Sausage\n            Cheddar, Garlic-rubbed, None, Extra Cheese\n            Parmesan, Thin, BBQ, Extra Cheese\n            Parmesan, Cheese-stuffed, BBQ, Chicken\n      */\n     for (const vector\u003cstring\u003e \u0026entry: random_samples) \n     {\n        for (const string \u0026item: entry)\n        {\n            cout \u003c\u003c item \u003c\u003c \", \";\n        }\n        cout \u003c\u003c \"\\n\";\n     }\n     return 0;\n}\n```\n\n### Generate Random Sample (Memory-optimized, without Boost)\nFinally, we can generate a random sample of combinations but do so without\nconsuming a lot of memory. By using some of the provided functions, we can\nsacrifice a small amount of computing time so that very little memory space\nis used. As such, the only limiters that remain are I/O performance and availability\nof disk space. This is especially useful for lower-end machines.\n\n\n```cpp\n#include \u003cstring\u003e\n#include \u003cvector\u003e\n#include \u003cset\u003e\n#include \u003ciostream\u003e\n#include \"lazy-cartesian-product.hpp\"\n\nusing std::cout;\nusing std::vector;\nusing std::set;\n\nusing lazycp::lazy_cartesian_product;   \n\n\nint main (int argc, char* argv[])\n{\n     vector\u003cstring\u003e crusts   = { \"Thin\", \"Thick\", \"Cheese-stuffed\", \"Garlic-rubbed\" };\n     vector\u003cstring\u003e sauces   = { \"Marinara\", \"BBQ\", \"None\" };\n     vector\u003cstring\u003e cheeses  = { \"Mozarella\", \"Cheddar\", \"Parmesan\" };\n     vector\u003cstring\u003e toppings = { \"Extra Cheese\", \"Chicken\", \"Pepperoni\", \"Sausage\" };\n\n     vector\u003cvector\u003cstring\u003e\u003e possibilities = { crusts, sauces, cheeses, toppings };\n\n     // First, find the max size of the combinations\n     unsigned long long max_size = lazy_cartesian_product::compute_max_size(possiblities);\n\n     // Next, generate a list of random indices to find\n     set\u003cunsigned long long\u003e random_indices = lazy_cartesian_product::generate_random_indices(100, max_size);\n    \n     // Finally, iterate through the random indices, generate a combination, and display it\n     for (const unsigned long long \u0026index: random_indices)\n     {\n        vector\u003cstring\u003e entry = lazy_cartesian_product::entry_at(possibilities, index);\n        for (const string \u0026item: entry)\n        {\n            cout \u003c\u003c item \u003c\u003c \", \";\n        }\n        cout \u003c\u003c \"\\n\";\n     }\n     return 0;\n}\n```\n\n\n## Example Usage (with Boost)\nThe following examples demonstrate the same functionality as above, but with the Boost library installed.\n\n\n### Basic Example (with Boost)\nFirst, we can generate a possible combination at the *nth* entry. For this example, we can find the combination of pizza components at the 5th entry.\n\n```cpp\n#include \u003cstring\u003e\n#include \u003ciostream\u003e\n#include \"lazy-cartesian-product.hpp\"   // Assumes the .hpp file is in the same directory\n#include \u003cboost/container/vector.hpp\u003e  // Notice how we now use the Boost libraries\n\nusing std::string;\nusing std::cout;\nusing boost::container::vector;\n\nusing lazycp::lazy_cartesian_product;   // For easier readability\n\nint main (int argc, char* argv[])\n{\n     vector\u003cstring\u003e crusts   = { // Some REALLY big amount };\n     vector\u003cstring\u003e sauces   = { ... };\n     vector\u003cstring\u003e cheeses  = { ... };\n     vector\u003cstring\u003e toppings = { ... };\n\n     // Put all of the vectors together so lazy-cartesian-product can accept the input\n     vector\u003cvector\u003cstring\u003e\u003e possibilities = { crusts, sauces, cheeses, toppings };\n\n     // Show the combination at the 18909849082309840923850987th index\n     string index(\"18909849082309840923850987\"); // Now we instead pass in a string\n     vector\u003cstring\u003e result = lazy_cartesian_product::boost_entry_at(possibilities, index);\n\n     // Display result:\n     for (const string \u0026entry: result)\n     {\n        cout \u003c\u003c result \u003c\u003c \", \";\n     }\n     cout \u003c\u003c \"\\n\";\n \n     return 0;\n}\n```\n\n\n### Generate Random Sample (Performance, with Boost)\n\n```cpp\n#include \u003cstring\u003e\n#include \u003ciostream\u003e\n#include \"lazy-cartesian-product.hpp\"\n#include \u003cboost/container/vector.hpp\u003e  \n\nusing std::string;\nusing std::cout;\nusing boost::container::vector;\n\nusing lazycp::lazy_cartesian_product;   \n\n\nint main (int argc, char* argv[])\n{\n     vector\u003cstring\u003e crusts   = { // Some REALLY big amount };\n     vector\u003cstring\u003e sauces   = { ... };\n     vector\u003cstring\u003e cheeses  = { ... };\n     vector\u003cstring\u003e toppings = { ... };\n\n     vector\u003cvector\u003cstring\u003e\u003e possibilities = { crusts, sauces, cheeses, toppings };\n    \n     // Generate an incredibly large sample size\n     string sample_size = \"478928739482739877729118939847\";\n     vector\u003cvector\u003cstring\u003e\u003e random_samples = lazy_cartesian_product::boost_generate_samples(possibilities, sample_size);\n\n     for (const vector\u003cstring\u003e \u0026entry: random_samples) \n     {\n        for (const string \u0026item: entry)\n        {\n            cout \u003c\u003c item \u003c\u003c \", \";\n        }\n        cout \u003c\u003c \"\\n\";\n     }\n     return 0;\n}\n```\n\n### Generate Random Sample (Memory-optimized, with Boost)\n\n```cpp\n#include \u003cstring\u003e\n#include \u003ciostream\u003e\n#include \"lazy-cartesian-product.hpp\"\n#include \u003cboost/container/vector.hpp\u003e  \n#include \u003cboost/container/set.hpp\u003e  \n#include \u003cboost/multiprecision/cpp_int.hpp\u003e    // Now we need the cpp_int library\n\nusing std::string;\nusing std::cout;\nusing boost::container::vector;\nusing boost::container::set;\nusing boost::multiprecision::uint1024_t;       // This way we can compute the max size\n\nusing lazycp::lazy_cartesian_product;   \n\nint main (int argc, char* argv[])\n{\n     vector\u003cstring\u003e crusts   = { // Some REALLY big amount };\n     vector\u003cstring\u003e sauces   = { ... };\n     vector\u003cstring\u003e cheeses  = { ... };\n     vector\u003cstring\u003e toppings = { ... };\n\n\n     vector\u003cvector\u003cstring\u003e\u003e possibilities = { crusts, sauces, cheeses, toppings };\n\n     // First, find the max size of the combinations\n     uint1024_t max_size = lazy_cartesian_product::boost_compute_max_size(possiblities);\n\n     // Next, generate a list of random indices to find (but of type uint1024_t)\n     string sample_size = \"478928739482739877729118939847\";\n     set\u003cuint1024_t\u003e random_indices = lazy_cartesian_product::boost_generate_random_indices(sample_size, max_size);\n    \n     // Finally, iterate through the random indices, generate a combination, and display it\n     for (const uint1024_t \u0026index: random_indices)\n     {\n        // Note: we need to convert the index to a string to find the entry_at, so we use the convert_to function\n        vector\u003cstring\u003e entry = lazy_cartesian_product::boost_entry_at(possibilities, index.convert_to\u003cstring\u003e()); \n        for (const string \u0026item: entry)\n        {\n            cout \u003c\u003c item \u003c\u003c \", \";\n        }\n        cout \u003c\u003c \"\\n\";\n     }\n     return 0;\n}\n```\n\n## TODOs\n* Add better exception-handling\n* Add testing framework\n\n## Contributing\nPull-requests are always welcome!\n\n## License\nMIT License\n\nCopyright (c) 2018 Tyler Burdsall\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftylerburdsall%2Flazy-cartesian-product","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftylerburdsall%2Flazy-cartesian-product","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftylerburdsall%2Flazy-cartesian-product/lists"}