public static CombinatorResult <T> Generate <T>(List <T> elements, CombinatorOptions options)
        {
            // figure out what is the combinations' length? If not specified, or each element can only occur once
            // per combination, we use the elements count. Otherwise as specified per the options.
            var cLength = options.Length == 0 || options.IsElementUnique ? elements.Count : options.Length;

            // get the combinations. This returns a full set by default
            var combos = options.IsFullSet ? GetCombinationsFullSet(elements, cLength) : GetCombinationsSparseSet(elements, cLength);

            //// if not a full set, only return the combinations which are of the specified length
            //if(!options.IsFullSet)
            //    combos = combos.Where(r => r.Count == cLength).ToList();

            // filter out combinations which include duplicate elements
            if (options.IsElementUnique)
            {
                combos = combos.Where(r => r.GroupBy(e => e).All(g => g.Count() == 1)).ToList();
            }

            // filter out combinations which contain the same elements, e.g. 'ab' is the same as 'ba'
            // note; identifying similar combinations by sum of hashcodes only works for strings.
            // not ideal given the method is generic, would like to fix this.. maybe hashsets..?
            if (!options.IsOrdered)
            {
                combos = combos.Select(l => (l: l, h: l.Sum(e => (long)e.GetHashCode())))
                         .GroupBy(t => t.h)
                         .Select(g => g.First().l).ToList();
            }

            return(new CombinatorResult <T> {
                Result = combos
            });
        }
Exemple #2
0
        public override string SolvePart1( )
        {
            var options = new CombinatorOptions
            {
                IsFullSet       = true,
                IsElementUnique = true,
                IsOrdered       = false
            };

            var result = Combinator.Generate(new List <string> {
                "0", "1", "2", "3", "4"
            }, options)
                         .Select(r => r.Select(int.Parse))
                         .Select(l => l.Aggregate(0d, (sum, d) => sum += containers[d]))
                         .Count(sum => sum == Liters);

            return(result.ToString( ));
        }