package tiles import ( "errors" "fmt" "log" "reflect" "sort" ) var TileTypes []string = []string{ "1W", "2W", "3W", "4W", "5W", "6W", "7W", "8W", "9W", "1T", "2T", "3T", "4T", "5T", "6T", "7T", "8T", "9T", "1B", "2B", "3B", "4B", "5B", "6B", "7B", "8B", "9B", "DO", "XI", "NA", "BE", "ZH", "FA", "BA"} var TileHuaTypes []string = []string{"ME", "LA", "ZU", "JU", "CH", "XA", "QI", "DN"} // Given two tiles, return if first tile is smaller the second tile, functions used as comparator for ordering // Default order is: 万 < 条 < 饼 < 字(东西南北中发白) func TileComparator(i, j string) (bool, error) { if i == j { return false, nil } ii, ij := -1, -1 for k, v := range TileTypes { if i == v { ii = k } if j == v { ij = k } } if ii == -1 || ij == -1 { return false, errors.New("can't find tile by name") } return ii < ij, nil } func Sort(tiles []string) error { sort.Slice(tiles, func(i, j int) bool { res, err := TileComparator(tiles[i], tiles[j]) if err != nil { log.Fatalf("Sort tiles has error: %v", err) } return res }) return nil } // Check func CheckXushuHelper(tiles [9]int, index int, allCombs [][]int, combTable *[][][]int) { if index >= 9 { // Check invalid shun/ke/gang with more than 1 pair gangAmount := 0 shunKeAmount := 0 pairAmount := 0 for _, combs := range allCombs { if len(combs) == 2 { pairAmount++ } if len(combs) == 3 { shunKeAmount++ } if len(combs) == 4 { gangAmount++ } } if pairAmount > 1 && (gangAmount > 0 || shunKeAmount > 0) { return } *combTable = append(*combTable, allCombs) return } if tiles[index] == 0 { CheckXushuHelper(tiles, index+1, allCombs, combTable) return } if tiles[index] == 4 { tiles[index] = 0 CheckXushuHelper(tiles, index+1, append(allCombs, []int{index, index, index, index}), combTable) if index < 7 { if tiles[index+1] > 0 && tiles[index+2] > 0 { tiles[index] = 3 tiles[index+1] -= 1 tiles[index+2] -= 1 CheckXushuHelper(tiles, index, append(allCombs, []int{index, index + 1, index + 2}), combTable) tiles[index+1] += 1 tiles[index+2] += 1 } } tiles[index] = 2 CheckXushuHelper(tiles, index, append(allCombs, []int{index, index}), combTable) } else if tiles[index] == 3 { tiles[index] = 0 CheckXushuHelper(tiles, index+1, append(allCombs, []int{index, index, index}), combTable) if index < 7 { if tiles[index+1] > 0 && tiles[index+2] > 0 { tiles[index] = 2 tiles[index+1] -= 1 tiles[index+2] -= 1 CheckXushuHelper(tiles, index, append(allCombs, []int{index, index + 1, index + 2}), combTable) tiles[index+1] += 1 tiles[index+2] += 1 } } } else if tiles[index] == 2 { tiles[index] = 0 CheckXushuHelper(tiles, index+1, append(allCombs, []int{index, index}), combTable) if index < 7 { if tiles[index+1] > 0 && tiles[index+2] > 0 { tiles[index] = 1 tiles[index+1] -= 1 tiles[index+2] -= 1 CheckXushuHelper(tiles, index, append(allCombs, []int{index, index + 1, index + 2}), combTable) tiles[index+1] += 1 tiles[index+2] += 1 } } } else { if index < 7 { if tiles[index+1] > 0 && tiles[index+2] > 0 { tiles[index] = 0 tiles[index+1] -= 1 tiles[index+2] -= 1 CheckXushuHelper(tiles, index+1, append(allCombs, []int{index, index + 1, index + 2}), combTable) } else { return } } } } func CheckXushuTile(tiles []string) ([][][]string, error) { limit := len(tiles) if limit <= 0 { return [][][]string{}, nil } var combTable [][][]int if limit <= 3 { var tileNumbers []int for _, tile := range tiles { tileNumbers = append(tileNumbers, int(tile[0])-48) } // bukao isBukao := true for _, num := range tileNumbers[1:] { if ((num - tileNumbers[0]) != 3) && ((num - tileNumbers[0]) != 6) { isBukao = false } } // isbukao + shisanyao if isBukao || reflect.DeepEqual(tileNumbers, []int{1, 9}) || reflect.DeepEqual(tileNumbers, []int{1, 1, 9}) || reflect.DeepEqual(tileNumbers, []int{1, 9, 9}) { var tmpAllCombs [][]int for _, tile := range tiles { tmpAllCombs = append(tmpAllCombs, []int{int(tile[0]) - 49}) } combTable = append(combTable, tmpAllCombs) } } var flatTileVector [9]int for _, tile := range tiles { flatTileVector[int(tile[0])-49] += 1 } CheckXushuHelper(flatTileVector, 0, [][]int{}, &combTable) if len(combTable) <= 0 { return [][][]string{}, fmt.Errorf("tiles are not empty, but can't generate a valid pattern(%v)", tiles) } strColor := tiles[0][1] var readableResult [][][]string for _, combs := range combTable { readableCombs := [][]string{} for _, comb := range combs { readableComb := []string{} for _, tile := range comb { readableComb = append(readableComb, fmt.Sprintf("%d%c", tile+1, strColor)) } readableCombs = append(readableCombs, readableComb) } readableResult = append(readableResult, readableCombs) } return readableResult, nil } func TilesDividedToPatterns(tiles []string) error { _ = Sort(tiles) var wan, tiao, bing, zi []string for _, tile := range tiles { switch tile[1] { case 'W': wan = append(wan, tile) case 'T': tiao = append(tiao, tile) case 'B': bing = append(bing, tile) default: zi = append(zi, tile) } } _, _ = CheckXushuTile(wan) _, _ = CheckXushuTile(tiao) _, _ = CheckXushuTile(bing) log.Println(zi) return nil }