[英]How to take X amount of questions, that sum up Y amount of difficulty
I have a table 我有桌子
Questions -> Question(string), Difficulty (int, 1-10) 问题->问题(字符串),难度(int,1-10)
I need to create a method, that as the title mentions, takes X
amount of questions, whose difficulty should sum up Y
. 我需要创建一个方法,正如标题所述,该方法要处理X
个问题,其难度应总结为Y
For example: 例如:
getQuestions(2,10)
-> Question1 (diff: 4), Question2 (diff: 6) getQuestions(2,10)
-> Question1(diff:4),Question2(diff:6)
getQuestions(3,15)
-> Question3 (diff: 5), Question4 (diff: 5), Question5 (diff: 5) getQuestions(3,15)
-> Question3(diff:5),Question4(diff:5),Question5(diff:5)
How can I achieve something like this with LINQ? 如何使用LINQ实现类似的目标?
Here's one way to do it, using a modified version of the recursive solution found here: Finding all possible combinations of numbers to reach a given sum 这是一种方法,使用此处找到的递归解决方案的修改版: 查找所有可能的数字组合以达到给定的总和
First, a public method that will do some quick validation and then call a recursive method to get the results: 首先,将执行一些快速验证的公共方法,然后调用递归方法以获取结果:
/// <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;
}
And then the recursive method that does the heavy lifting: 然后执行繁重工作的递归方法:
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);
}
}
Here's an example usage: 这是一个示例用法:
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);
}
}
And just so you have everything to make this work, here's my Question class used to fake your table: 这样您就可以完成所有工作,这是我的Question类,用于伪造您的表:
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; }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.