如何采取X量的问题,总结Y难度

时间:2015-03-02 17:26:16

标签: c# linq

我有一张桌子

  

问题 - >问题(字符串),难度(int,1-10)

我需要创建一个方法,如标题所示,需要X个问题,其难度应该总结为Y

例如:

getQuestions(2,10) - >问题1(差异:4),问题2(差异:6)

getQuestions(3,15) - >问题3(差异:5),问题4(差异:5),问题5(差异:5)

如何使用LINQ实现这样的功能?

1 个答案:

答案 0 :(得分:1)

这是一种方法,使用此处的递归解决方案的修改版本:Finding all possible combinations of numbers to reach a given sum

首先,一个公共方法将进行一些快速验证,然后调用递归方法来获得结果:

/// <summary>
/// Gets lists of numQuestions length of all combinations 
/// of questions whose difficulties add up to sumDifficulty
/// </summary>
/// <param name="questions">The list of questions to search</param>
/// <param name="numQuestions">The number of questions required</param>
/// <param name="sumDifficulty">The amount that the difficulties should sum to</param>
/// <returns></returns>
public static List<List<Question>> GetQuestions(List<Question> questions,
    int numQuestions, int sumDifficulty)
{
    if (questions == null) throw new ArgumentNullException("questions");

    var results = new List<List<Question>>();

    // Fail fast argument validation
    if (numQuestions < 1 || 
        numQuestions > questions.Count ||
        sumDifficulty < numQuestions * Question.MinDifficulty ||
        sumDifficulty > numQuestions * Question.MaxDifficulty)
    {
        return results;
    }

    // If we only need single questions, no need to do any recursion
    if (numQuestions == 1)
    {
        results.AddRange(questions.Where(q => q.Difficulty == sumDifficulty)
            .Select(q => new List<Question> {q}));

        return results;
    }

    // We can remove any questions who have a difficulty that's higher
    // than the sumDifficulty minus the number of questions plus one
    var candidateQuestions =
        questions.Where(q => q.Difficulty <= sumDifficulty - numQuestions + 1)
            .ToList();

    if (!candidateQuestions.Any())
    {
        return results;
    }

    GetSumsRecursively(candidateQuestions, sumDifficulty, new List<Question>(), 
        numQuestions, results);

    return results;
}

然后是执行繁重任务的递归方法:

private static void GetSumsRecursively(IReadOnlyList<Question> questions, 
    int sumDifficulty, List<Question> candidates, int numQuestions, 
    ICollection<List<Question>> results)
{
    int candidateSum = candidates.Sum(x => x.Difficulty);

    if (candidateSum == sumDifficulty && candidates.Count == numQuestions)
    {
        results.Add(candidates);
    }

    if (candidateSum >= sumDifficulty)
        return;

    for (int i = 0; i < questions.Count; i++)
    {
        var remaining = new List<Question>();

        for (int j = i + 1; j < questions.Count; j++)
        {
            remaining.Add(questions[j]);
        }

        var filteredCandidates = new List<Question>(candidates) {questions[i]};

        GetSumsRecursively(remaining, sumDifficulty, filteredCandidates, 
            numQuestions, results);
    }
}

以下是一个示例用法:

public static void Main()
{
    const int numberOfQuestions = 3;
    const int sumOfDifficulty = 15;

    // Since I don't have your table, I'm using a list of objects to fake it
    var questions = new List<Question>();
    for (int i = 1; i < 11; i++)
    {
        questions.Add(new Question {Difficulty = i % 10 + 1, 
            QuestionString = "Question #" + i});
    }

    var results = GetQuestions(questions, numberOfQuestions, sumOfDifficulty);

    // Write output to console to verify results
    foreach (var result in results)
    {
        Console.WriteLine("{0} = {1}", string.Join(" + ", 
            result.Select(r => r.Difficulty)), sumOfDifficulty);
    }
}

只是这样你才能完成所有工作,这是我用来伪造你的桌子的问题类:

internal class Question
{
    public const int MinDifficulty = 1;
    public const int MaxDifficulty = 10;
    private int _difficulty;

    public int Difficulty
    {
        get { return _difficulty; }
        set
        {
            if (value < MinDifficulty) _difficulty = MinDifficulty;
            else if (value > MaxDifficulty) _difficulty = MaxDifficulty;
            else _difficulty = value;
        }
    }

    public string QuestionString { get; set; }
}