如何回答X个问题,即Y个难度的总和

本文关键字:何回答 问题 | 更新日期: 2024-09-24 06:56:43

我有一个表

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

我需要创建一个方法,正如标题所提到的,需要X的问题数量,其难度应该是Y的总和。

例如:

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

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

如何使用LINQ实现这样的目标?

如何回答X个问题,即Y个难度的总和

这里有一种方法,使用这里找到的递归解决方案的修改版本:找到所有可能的数字组合,以达到给定的总和

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

/// <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; }
}