The algorithm used in this program has been proven to calculate shanten numbers accurately.
The shanten number is the minimum number of draws needed to reach tenpai.
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Debug
$ make
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release
$ make
Note
A compiler compatible with C++20 or later is required.
This enables the table search algorithm to use the minimal perfect hash function used in Cryolite's nyanten12. Enabling this option can reduce the size of the tables. However, the number of tiles in a hand for which shanten numbers can be calculated is limited to 14 or less.
It fixes the random seed used in the example program.
Build the parameter tables required for calculating shanten numbers. This creates the files index_h.bin and index_s.bin.
$ ./mkind
Tip
Intel Threading Building Blocks (TBB) is optional and, if available, will be automatically linked to enable parallel builds.
-
Prepare a
std::array<int, 34>array representing a hand.-
The
n-th element stores the number of copies of then-th tile.1 2 3 4 5 6 7 8 9 Manzu 0 (1m) 1 (2m) 2 (3m) 3 (4m) 4 (5m) 5 (6m) 6 (7m) 7 (8m) 8 (9m) Pinzu 9 (1p) 10 (2p) 11 (3p) 12 (4p) 13 (5p) 14 (6p) 15 (7p) 16 (8p) 17 (9p) Souzu 18 (1s) 19 (2s) 20 (3s) 21 (4s) 22 (5s) 23 (6s) 24 (7s) 25 (8s) 26 (9s) Jihai 27 (East) 28 (South) 29 (West) 30 (North) 31 (White) 32 (Green) 33 (Red) -
For example, if the hand is 123m245779p13555z, define the array as follows.
std::array<int, 34> hand = { 1, 1, 1, 0, 0, 0, 0, 0, 0, // Manzu 0, 1, 0, 1, 1, 0, 2, 0, 1, // Pinzu 0, 0, 0, 0, 0, 0, 0, 0, 0, // Souzu 1, 0, 1, 0, 3, 0, 0 // Jihai };
-
-
Calculate the shanten number. Each method returns a value of shanten number + 1.
- General Form (
mmelds and a pair):int Calsht::calc_lh(const std::array<int, 34>& t, int m, bool three_player = false) const
- Seven Pairs:
int Calsht::calc_sp(const std::array<int, 34>& t, bool three_player = false) const
- Thirteen Orphans:
int Calsht::calc_to(const std::array<int, 34>& t) const
- Standard Form:
std::tuple<int, unsigned int> Calsht::operator()(const std::array<int, 34>& t, int m, unsigned int mode, bool check_hand = false, bool three_player = false) const
- General Form (
Note
Normally, set m to the number of tiles divided by 3.
Note
mode specifies which winning patterns to calculate shanten numbers for. Use 1 for General Form, 2 for Seven Pairs, and 4 for Thirteen Orphans. When calculating shanten numbers for multiple winning patterns, specify their bitwise OR.
Note
This method returns the shanten number + 1, and the mode. The mode indicates which winning pattern (General Form, Seven Pairs, or Thirteen Orphans) gives the minimum shanten number.
Note
If you set check_hand to true, the hand is validated. If you set three_player to true, the shanten number is calculated for three-player mahjong.
As an example, the following code calculates the shanten number for the hand defined above.
#include <array>
#include <filesystem>
#include <iostream>
#include <mahjong/calsht.hpp>
int main()
{
// Set the location of shanten tables
mahjong::Calsht calsht(std::filesystem::current_path());
std::array<int, 34> hand = {
1, 1, 1, 0, 0, 0, 0, 0, 0, // manzu
0, 1, 0, 1, 1, 0, 2, 0, 1, // pinzu
0, 0, 0, 0, 0, 0, 0, 0, 0, // souzu
1, 0, 1, 0, 3, 0, 0 // jihai
};
const auto [sht, mode] = calsht(hand, 4, 7);
std::cout << sht << std::endl;
std::cout << mode << std::endl;
return 0;
}Output:
3
1
- Randomly generate hands and calculate the frequency of each shanten number and the expected shanten number.
$ ./example 14 100000000 0
-1 278 0.000278
0 69553 0.069553
1 2334287 2.334287
2 19502040 19.502040
3 43925782 43.925782
4 28516861 28.516861
5 5496101 5.496101
6 155098 0.155098
Number of Tiles 14
Number of Hands 100000000
Expected Value 3.155940
GNU Lesser General Public License v3.0.