From 635c78a885cd3ec3427364a0c82a1678fc3efbe5 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Thu, 20 Apr 2023 16:37:34 +0800 Subject: [PATCH] docs: add Group description --- src/klotski_core/group/group.h | 57 ++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/klotski_core/group/group.h b/src/klotski_core/group/group.h index 5c682ed..e1b1ea9 100644 --- a/src/klotski_core/group/group.h +++ b/src/klotski_core/group/group.h @@ -1,5 +1,62 @@ #pragma once +/// Group is a concept in klotski. For any case, moving all its blocks any finite +/// number of times can generate a limited number of layouts, they are called a +/// `group`. Of course, there are some special groups whose size is only `1`, +/// that is, only itself. (all blocks can no longer be moved) + +/// For a case, by definition, it must have a `2x2` block, at least two spaces, and +/// the others are filled by any number of `1x1`, `1x2` and `2x1`, so their numbers +/// satisfy the following inequality. +/// +/// n_1x1 + (n_1x2 + n_2x1) * 2 + n_2x2 * 4 < (20 - 2) +/// => n_1x1 + (n_1x2 + n_2x1) * 2 < 14 +/// +/// Through calculation, it can be known that these three independent variables can +/// get `204` combinations. However, on a `5x4` chessboard, it is never possible to +/// put seven `2x1` blocks, so there are actually `203` combinations, and they are +/// numbered from `0` to `202`, called `type_id`. + +/// According to the number of blocks in the layout, you can use the following +/// formula to get an intermediate value `flag`, and arrange the flags in `203` cases +/// from small to large to get the `type_id` value. Similarly, `type_id` can also be +/// reversed to get the number of blocks, which are one by one corresponding. +/// +/// flag = 0xxx | 0xxx | xxxx (12-bit) +/// (n_1x2 + n_2x1) | (n_2x1) | (n_1x1) +/// (0 ~ 7) | (0 ~ 7) | (0 ~ 14) +/// +/// => flag = ((n_1x2 + n_2x1) << 8) | (n_2x1 << 4) | (n_1x1) +/// +/// Using the table lookup method, the `type_id` of any case can be obtained within +/// O(1), which is encapsulated in `GroupType`. + +/// Since the `type_id` cannot change when moving, all cases belonging to the same +/// `type_id` must be divided into different groups (of course there may be only one). +/// For a group, list the CommonCodes of all its cases, the smallest of which is called +/// the group's `seed`. List all the groups under the same `type_id`, and arrange them +/// from large to small, and arrange the groups of the same size from small to large +/// according to the `seed`, and start numbering from `0` to get the `group_id`. + +/// All cases of the same group will have the same `type_id` and `group_id`, that is +/// to say, for cases with the same two values, there must be a reachable path for them, +/// otherwise they will never be reachable. Arrange the CommonCodes of all cases in +/// the group from small to large, and start numbering from 0 to get `group_index`, +/// which will uniquely determine a legal layout. Use the following method to express. +/// +/// {type_id}-{group_id}-{group_index} +/// +/// Eg1: 1A9BF0C00 -> `169-1-7472` +/// Eg2: 4FEA13400 -> `164-0-30833` + +/// The range of `type_id` is [0, 203), the maximum `group_id` is `2652` (there are +/// 2653 groups when `type_id` is 164), the maximum `group_index` is `964655` (there +/// are 964656 cases when `type_id` is 58 and `group_id` is 0). Therefore, these three +/// numbers meet the following range requirements. +/// +/// type_id < 203 | group_id < 2653 | group_index < 964656 +/// (8-bit ~ 256) | (12-bit ~ 4096) | (20-bit ~ 1048576) + #include #include "raw_code.h" #include "common_code.h"