Идеи для отслеживания лучших результатов по множеству критериевC#

Место общения программистов C#
Ответить
Anonymous
 Идеи для отслеживания лучших результатов по множеству критериев

Сообщение Anonymous »

Я пишу программу на C#, которая выполняет множество сценариев. Он учитывает каждую комбинацию баффов и дебаффов в игре, которую я пытаюсь сбалансировать. Он оценивает два целочисленных параметра (целое число и скорость) для каждой комбинации. У меня есть структура под названием Result, в которой хранятся два целых числа. Я хотел бы создать список лучших параметров по следующим критериям: я хочу сохранить один результат для каждого значения оценки, в зависимости от того, какое из них имеет самое высокое значение скорости, и два результата для каждого значения скорости, самого низкого и самого высокого значения оценки.
Например, если список уже содержит записи ниже:
  • score=-2, скорость=1
  • оценка=5, скорость=1
  • оценка=-1, скорость=2
  • оценка=5, скорость=2
  • оценка=-1, скорость=3
  • оценка=4, скорость=3
  • оценка=0, скорость=4
  • оценка=-3, скорость=5
  • оценка=5, скорость=5
  • оценка=-1, скорость=5
  • оценка=1, скорость=5
  • score=2, скорость=5
  • score=3, скорость=3
Когда я доберусь до оценки, которая дает эти новые результаты (предположим, что каждый приведенный ниже случай применяется к приведенному выше списку как есть. Изменения, перечисленные в результате оценки, не изменят список для следующего случай):
оценка=-5, скорость=1. мы никогда раньше не видели оценку -5, поэтому мы определенно сохраняем это. Он также занимает новое место с наименьшим баллом при скорости 1, обогнав элемент с номером 0 в списке. Однако элемент 0 по-прежнему сохраняет самую высокую скорость с показателем -2, поэтому он не будет удален.
score=-1, скорость=1. Этот результат ни в одной категории не лучше, чем тот, что указан в списке, и никаких изменений не произойдет.
score=4, скорость=3. Этот результат уже есть в списке, поэтому ни в одной категории он определенно не лучше того, что есть в списке, и никаких изменений не произойдет.
score=-3, скорость=2. У предмета 7 тоже показатель -3, но скорость у него выше, так что расстраиваться здесь не стоит. Тем не менее, он занимает новое место с наименьшим баллом при скорости 2, обгоняя позицию под номером 2 в списке. Элемент 2 не содержит дополнительных «лучших» рекордов, поэтому он будет удален из списка по мере добавления этого результата.
score=4,speed=5. Это отменяет пункт 5 как наивысшую скорость при счете 4. Пункт 5 по-прежнему имеет наивысший балл при скорости 3, поэтому не будет удален. Элементы 7 и 8 по-прежнему имеют самый низкий и самый высокий балл при скорости 5 (соответственно), поэтому ни один из них не нужно оценивать, чтобы определить, следует ли их удалить.
Я ищу рекомендации или предложения о том, что может быть хорошим способом сделать это. Если я смогу сделать это относительно чисто в том же цикле, который я оцениваю аналогично тому, как я описал выше, я думаю, что это будет предпочтительнее (с точки зрения производительности и простоты). Однако я не смог найти четкого решения, поэтому ниже приведен приблизительный набросок кода, выполняющего оценку, и первая попытка (функция SaveBestResults) чего-то, что, как я думаю, выполнит работу во втором (и третьем, и четвертом, и пятом...) цикле. Прохождение списка, даже несколько раз, технически должно быть линейным, верно? Но проблема в том, что цикл создания _allResults выполняется примерно за время O(n^k) (n — количество элементов для каждого слота, а k — количество слотов). А это означает, что _allResults будет содержать что-то вроде n^k элементов. У меня есть некоторые идеи, как оптимизировать верхний цикл, но пока мне не нравится сохранять только лучшие результаты.
public struct Result
{
public int score;
public int speed;
}

public struct BuffsAndDebuffs
{
// contents not important for this question
}

public class MyClass
{
private List _allResults = new List();
private List _bestResults = new List();

public MyClass(List allAddons)
{
foreach (BuffsAndDebuffs temp in allAddons)
{
// this will be a multi-level loop to generate all possible combinations
Result result = DecodeResult(temp); // dummy placeholder
_allResults.Add(result);
}
SaveBestResults();
foreach (Result temp in _bestResults)
{
// these results will be saved to a file for me to evaluate
}
}

public void SaveBestResults()
{
// set the starting values far outside what will be found in the list
// to make sure they get set
int minSpeed = 1000;
int maxSpeed = -1000;
int minScore = 1000;
int maxScore = -1000;

// find the min and max bounds for looping through speeds and scores
foreach (Result result in _allResults)
{
if (result.result.speed < minSpeed)
{
minSpeed = result.result.speed;
}
if (result.result.speed > maxSpeed)
{
maxSpeed = result.result.speed;
}
if (result.result.score < minScore)
{
minScore = result.result.score;
}
if (result.result.score > maxScore)
{
maxScore = result.result.score;
}
}

// find the lowest and highest scores for each given speed
for (int targetSpeed = minSpeed; targetSpeed highestScoreForSp.result.score)
)
{
highestScoreForSp = result;
}
if
(
(result.result.speed == targetSpeed) &&
(result.result.score < LowestScoreForSp.result.score)
)
{
LowestScoreForSp = result;
}
}

// check if we found a matching speed
// (because it will have been set when we saved the result during the loop above)
// and that there isn't a duplicate in the list already
// (it is possible for one result to top the list in multiple categories).
if
(
(highestScoreForSp.result.speed == targetSpeed) &&
!_bestResults.Contains(highestScoreForSp)
)
{
// technically, there can't be any duplicates yet for highestScoreForSp
// but it doesn't hurt (other than execution time) to check.
_bestResults.Add(highestScoreForSp);
}
if
(
(LowestScoreForSp.result.speed == targetSpeed) &&
!_bestResults.Contains(LowestScoreForSp)
)
{
_bestResults.Add(LowestScoreForSp);
}
}

// find the highest speed for each given score
for (int targetScore = minScore; targetScore highestSpeedForSc.result.speed)
)
{
highestSpeedForSc = result;
}
}

// check if we found a matching score
// (because it will have been set when we saved the result during the loop above)
// and that there isn't a duplicate in the list already
// (it is possible for one result to top the list in multiple categories).
if
(
(highestSpeedForSc.result.score == targetScore) &&
!_bestResults.Contains(highestSpeedForSc)
)
{
_bestResults.Add(highestSpeedForSc);
}
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/798 ... e-criteria
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»