mangood
mangood

Reputation: 61

Some loop with conditions. Specific problem

I have a small problem with mathematics or combinatorics in my C# code. I don't know how to write this easiest.

I have a class Section and TestClass but not a method to return expected result.

public class Section
{
    public int Id { get; set; }
    public int Pages { get; set; }
    public string Name { get; set; }
}

[TestFixture]
public class PermutatorTest
{
    private IList<Section> _sections;
    private int _targetPage;

    [SetUp]
    public void SetUp()
    {
        _targetPage = 30;
        _sections = new List<Section>
        {
            new Section {Id = 1, Pages = 15, Name = "A"},
            new Section {Id = 2, Pages = 15, Name = "B"},
            new Section {Id = 3, Pages = 10, Name = "C" },
            new Section {Id = 4, Pages = 10, Name = "D"},
            new Section {Id = 5, Pages = 10, Name = "E"},
            new Section {Id = 6, Pages = 5, Name = "F"}
        };
    }

    [Test]
    public void GetPermutationsTest()
    {
        // Code to return list of all combinations
    }
}

I want to get each combination which give me 30 as a sum of Pages. it could be return as a string based on name or Id e.g AA or 11 , AB or 12 Of course, the order is not important ( AB and BA is the same... CCD and CDC and DCC too )

Final result should look like this: (30 correct results)

AA
AB
ACF
ADF
AEF
AFFF
BB
BCF
BDF
BEF
BFFF
CCC
CCD
CCE
CDD
CEE
CDE
CFFFF
CDFF
CCFF
CEFF
DDFF
DEFF
DFFFF
DDD
DDE
EFFFF
EEE
EEFF
FFFFFF

e.g. DDE = 10+10+10 = 30 OK CFFFF = 10 + 5 +5 +5 +5 = 30 Ok etc.

I dont have idea for best way to create loops for this, and put records to List Thank you very much for every attempt to help me.

Upvotes: 1

Views: 71

Answers (2)

PaulF
PaulF

Reputation: 6773

This was my original idea I was going to post for you, it just returned a list of strings

public List<String> result;
public void GetResultList(int startOffs, String CurNames, int curTotal)
{
  for (int newOffs = startOffs; newOffs < _sections.Count; newOffs++)
  {
    int newTotal = curTotal + _sections[newOffs].Pages;
    String newNames = CurNames+ _sections[newOffs].Name;
    if (newTotal < _targetPage)
      GetResultList(newOffs, newNames, newTotal);
    else if (newTotal == _targetPage)
      result.Add(newNames);
  }
}

called by initialising the result & start parameters :

result = new List<String>();
GetResultList(0,"",0);

This is a version modified to use your Config class

public void GetResultList(int startOffs, Config CurConfig)
{
  for (int newOffs = startOffs; newOffs < _sections.Count; newOffs++)
  {
    Config newConfig = new Config{ Name = CurConfig.Name + _sections[newOffs].Name,
                                   Ids = CurConfig.Ids + _sections[newOffs].Id.ToString(),
                                   Pages = CurConfig.Pages + _sections[newOffs].Pages};
    if (newConfig.Pages < _targetPage)
      GetResultList(newOffs, newConfig);
    else if (newConfig.Pages == _targetPage)
      _result.Add(newConfig);
  }
}

calling needs the result initialising & a starting Config instance

_result = new List<Config>();
Config s = new Config { Ids = "", Pages=0, Name=""};
GetResultList(0,s);

Upvotes: 1

mangood
mangood

Reputation: 61

Only for Information and Searchers. I know, this code is not so clean but I put it here as a nUnit Test...

it returns what I wanted ... i think.

using System;
using System.Collections.Generic;
using NUnit.Framework;

[TestFixture]
public class PermutatorTest
{
    private IList<Section> _sections;
    private int _targetPage;
    private IList<Config> _result;
    [SetUp]
    public void SetUp()
    {
        _targetPage = 30;
        _sections = new List<Section>
        {
            new Section {Id = 1, Pages = 15, Name = "A"},
            new Section {Id = 2, Pages = 15, Name = "B"},
            new Section {Id = 3, Pages = 10, Name = "C" },
            new Section {Id = 4, Pages = 10, Name = "D"},
            new Section {Id = 5, Pages = 10, Name = "E"},
            new Section {Id = 6, Pages = 5, Name = "F"}
        };

        _result = new List<Config>();
    }

    [Test]
    public void GetPermutationsTest()
    {

        for (var b =0 ; b<=_sections.Count-1; b++)
        {
            var config = new Config
            {
                Name = _sections[b].Name,
                Ids =  _sections[b].Id.ToString(),
                Pages = _sections[b].Pages
            };
            GoDeeperAndAddToResult(config, b);
        }

        Console.WriteLine(_result.Count);

        foreach (var item in _result)
        {
            Console.WriteLine($"{item.Name} - {item.Ids} - {item.Pages}");
        }
    }

    private void GoDeeperAndAddToResult(Config config, int startIndex)
    {
        for (var b = startIndex; b <= _sections.Count-1; b++)
        {
            var section = _sections[b];

            var combName = config.Name;
            var combIds = config.Ids;
            var combPages = config.Pages;

            var maxSec = _targetPage / section.Pages;
            for (var a = 1; a <= maxSec; a++)
            {
                combName = combName + section.Name;
                combIds = combIds + section.Id.ToString();
                combPages = combPages + section.Pages;

                var subConfig = new Config
                {
                    Name = combName,
                    Ids = combIds,
                    Pages = combPages
                };

                if (subConfig.Pages == _targetPage)
                {
                    _result.Add(subConfig);
                    break;
                }
                else if (subConfig.Pages < _targetPage)
                {
                    GoDeeperAndAddToResult(subConfig, b + 1);
                }
                else
                {
                    break;
                }
            }
        }
    }

    public class Config
    {
        public string Name { get; set; }
        public string Ids { get; set; }
        public int Pages { get; set; }
    }

    public class Section
    {
        public int Id { get; set; }
        public int Pages { get; set; }
        public string Name { get; set; }
    }
}

Upvotes: 0

Related Questions