Ejemplo n.º 1
0
        private static List <List <int> > GetPossibleSetsFromIndices2(List <int> list)
        {
            var results = new List <List <int> >();

            for (int t1 = 0; t1 < list.Count; t1++)
            {
                for (int t2 = t1; t2 < list.Count; t2++)
                {
                    if (t2 == t1)
                    {
                        continue;
                    }
                    for (int t3 = t2; t3 < list.Count; t3++)
                    {
                        if (t3 == t2 || t3 == t1)
                        {
                            continue;
                        }
                        var result = new List <int> {
                            list[t1], list[t2], list[t3]
                        };
                        if (U.is_chi(result) || U.is_pon(result))
                        {
                            results.Add(result);
                        }
                    }
                }
            }
            return(results);
        }
Ejemplo n.º 2
0
        public override bool is_condition_met(List <List <int> > hand, params object[] args)
        {
            int honors    = 0;
            int terminals = 0;
            int chi       = 0;

            foreach (var group in hand)
            {
                if (U.is_chi(group))
                {
                    chi++;
                }
                if (U.are_tiles_in_indices(group, C.TERMINAL_INDICES))
                {
                    terminals++;
                }
                if (U.are_tiles_in_indices(group, C.HONOR_INDICES))
                {
                    honors++;
                }
            }
            //honroutou
            if (chi == 0)
            {
                return(false);
            }

            return(terminals + honors == 5 && terminals != 0 && honors != 0);
        }
Ejemplo n.º 3
0
        // Replaced the original "get possible sets" block by this, seems more efficient and compact
        // Also: binary count browsing is cool
        // Input: sorted array of indices
        private static List <List <int> > GetPossibleSetsFromIndices(List <int> list)
        {
            var array   = list.ToArray();
            int count   = (int)Math.Pow(2, array.Length);             //We know we'll iterate on 2^n possibilities
            int min     = (int)Math.Pow(2, 3) - 1;                    //start at b'...000000111' since it's the first result of length >= 3
            int max     = count - (int)Math.Pow(2, array.Length - 3); //end at b'11100000...' since it's the last result of length <= 3 (12% faster)
            var results = new List <List <int> >();

            if (list.Count < 3)
            {
                return(results);
            }
            int  lastTile = -1;
            int  currentTile;
            int  nbTile;
            bool ok;

            for (int i = min; i <= max; i++)
            {
                var    result = new List <int>();
                string str    = Convert.ToString(i, 2).PadLeft(array.Length, '0'); //we take i and convert it to a n bit integer, each value of i representing a possibility
                nbTile = 0;
                ok     = true;
                for (int j = 0; j < str.Length; j++)
                {
                    if (str[j] == '1')
                    {
                        if (nbTile == 3)
                        {
                            ok = false;
                            break; // result is too large so let's stop here (might be the only useful optim here...)
                        }
                        currentTile = array[j];
                        if (currentTile - lastTile > 1 && lastTile >= 0)
                        {
                            ok = false;
                            break; // there is no way a group containing 'x,x+2' is a set
                        }
                        result.Add(currentTile);
                        lastTile = currentTile;
                        nbTile++;
                    }
                }
                if (ok && (U.is_chi(result) || U.is_pon(result)))
                {
                    results.Add(result);
                }
            }
            return(results);
        }
Ejemplo n.º 4
0
        //
        //         Find and return all valid set combinations in given suit
        //         :param tiles_34:
        //         :param first_index:
        //         :param second_index:
        //         :param hand_not_completed: in that mode we can return just possible shi or pon sets
        //         :return: list of valid combinations
        //
        List <List <List <int> > > find_valid_combinations(int[] tiles_34, int first_index, int second_index, bool hand_not_completed = false)
        {
            int count_of_sets;
            var indices = new List <int>();

            foreach (var x in Enumerable.Range(first_index, second_index + 1 - first_index))
            {
                if (tiles_34[x] > 0)
                {
                    indices.AddRange(Enumerable.Repeat(x, tiles_34[x]).ToList());
                }
            }
            var count_of_needed_combinations = Convert.ToInt32(indices.Count / 3);

            if (indices.Count == 0 || count_of_needed_combinations == 0)
            {
                return(new List <List <List <int> > >
                {
                    new List <List <int> >()
                });
            }

            // indices are already sorted
            var validMelds = GetPossibleSetsFromIndices(indices);

            if (validMelds.Count == 0)
            {
                return(new List <List <List <int> > >
                {
                    new List <List <int> >()
                });
            }
            // simple case, we have count of sets == count of tiles
            if (count_of_needed_combinations == validMelds.Count)
            {
                var toCheck = validMelds.Select(x => x.ToList() as IEnumerable <int>).Aggregate((z, y) => z.Concat(y));
                if (toCheck.SequenceEqual(indices))
                {
                    return(new List <List <List <int> > >()
                    {
                        validMelds
                    });
                }
            }

            // filter and remove not possible pon sets
            IEnumerable <List <int> > identicalSets;

            foreach (var item in validMelds.ToArray().ToList())
            {
                if (U.is_pon(item))
                {
                    count_of_sets = 1;
                    var count_of_tiles = 0;
                    while (count_of_sets > count_of_tiles)
                    {
                        count_of_tiles = (from x in indices
                                          where x == item[0]
                                          select x).ToList().Count / 3;
                        identicalSets = (from x in validMelds
                                         where x[0] == item[0] && x[1] == item[1] && x[2] == item[2]
                                         select x);
                        count_of_sets = identicalSets.Count();
                        if (count_of_sets > count_of_tiles)
                        {
                            validMelds.Remove(identicalSets.First());
                        }
                    }
                }
            }
            // filter and remove not possible chi sets
            foreach (var item in validMelds.ToArray().ToList())
            {
                if (U.is_chi(item))
                {
                    count_of_sets = 5;
                    // TODO calculate real count of possible sets
                    var count_of_possible_sets = 4;
                    while (count_of_sets > count_of_possible_sets)
                    {
                        identicalSets = (from x in validMelds
                                         where x[0] == item[0] && x[1] == item[1] && x[2] == item[2]
                                         select x);
                        count_of_sets = identicalSets.Count();
                        if (count_of_sets > count_of_possible_sets)
                        {
                            validMelds.Remove(identicalSets.First());
                        }
                    }
                }
            }
            // lit of chi\pon sets for not completed hand
            if (hand_not_completed)
            {
                return(new List <List <List <int> > >()
                {
                    validMelds
                });
            }
            // hard case - we can build a lot of sets from our tiles
            // for example we have 123456 tiles and we can build sets:
            // [1, 2, 3] [4, 5, 6] [2, 3, 4] [3, 4, 5]
            // and only two of them valid in the same time [1, 2, 3] [4, 5, 6]

            int maxIndex   = indices.Max() + 1;
            var indexCount = new int[maxIndex];

            foreach (var index in indices)
            {
                indexCount[index]++;
            }
            var possibleHands = GetPossibleHandsFromSets(validMelds, indexCount, count_of_needed_combinations);

            return(possibleHands);
        }