Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
using Codebreaker.GameAPIs.Client.Models;

namespace CodeBreaker.Bot.Benchmarks;

Expand Down Expand Up @@ -56,7 +55,7 @@ public void Setup()
[BenchmarkCategory("BlackMatches", "Game6x4", "FullList")]
public List<int> HandleBlackMatches_Game6x4_FullList()
{
return _fullGame6x4Values.HandleBlackMatches(GameType.Game6x4, 2, _testSelection6x4);
return BinaryCodeBreakerAlgorithms.HandleBlackMatches(_fullGame6x4Values, GameType.Game6x4, 2, _testSelection6x4);
}

[Benchmark]
Expand Down
176 changes: 83 additions & 93 deletions src/services/bot/CodeBreaker.Bot.Benchmarks/BenchmarkTestData.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using Codebreaker.GameAPIs.Client.Models;

namespace CodeBreaker.Bot.Benchmarks;

/// <summary>
Expand All @@ -12,83 +10,49 @@ public static class BenchmarkTestData
/// </summary>
public static List<int> CreateGame6x4PossibleValues()
{
static List<int> CreateColors(int colorCount, int shift)
{
List<int> pin = [];
for (int i = 0; i < colorCount; i++)
{
int x = 1 << i + shift;
pin.Add(x);
}
return pin;
}

static List<int> AddColorsToList(List<int> list1, List<int> list2)
{
List<int> result = new(capacity: 1300);
for (int i = 0; i < list1.Count; i++)
{
for (int j = 0; j < list2.Count; j++)
{
int x = list1[i] ^ list2[j];
result.Add(x);
}
}
return result;
}

var digits1 = CreateColors(6, 0);
var digits2 = CreateColors(6, 6);
var list2 = AddColorsToList(digits1, digits2);
var digits3 = CreateColors(6, 12);
var list3 = AddColorsToList(list2, digits3);
var digits4 = CreateColors(6, 18);
var list4 = AddColorsToList(list3, digits4);
list4.Sort();
return list4;
return BinaryCodeBreakerAlgorithms.GenerateAllPossibleCombinations(GameType.Game6x4, 6);
}

/// <summary>
/// Creates a list of possible values for Game8x5
/// </summary>
public static List<int> CreateGame8x5PossibleValues()
{
static List<int> Create8Colors(int shift)
{
List<int> pin = [];
for (int i = 0; i < 8; i++)
{
int x = 1 << (i + shift);
pin.Add(x);
}
return pin;
}
return BinaryCodeBreakerAlgorithms.GenerateAllPossibleCombinations(GameType.Game8x5, 8);
}

static List<int> AddColorsToList(List<int> list1, List<int> list2)
{
List<int> result = new(capacity: list1.Count * list2.Count);
for (int i = 0; i < list1.Count; i++)
{
for (int j = 0; j < list2.Count; j++)
{
int x = list1[i] ^ list2[j];
result.Add(x);
}
}
return result;
}
/// <summary>
/// Creates string-based possible values for Game6x4
/// </summary>
public static List<string[]> CreateGame6x4StringPossibleValues()
{
string[] colors = ["Red", "Blue", "Green", "Yellow", "Orange", "Purple"];
return StringCodeBreakerAlgorithms.GenerateAllPossibleCombinations(GameType.Game6x4, colors);
}

var digits1 = Create8Colors(0);
var digits2 = Create8Colors(6);
var list2 = AddColorsToList(digits1, digits2);
var digits3 = Create8Colors(12);
var list3 = AddColorsToList(list2, digits3);
var digits4 = Create8Colors(18);
var list4 = AddColorsToList(list3, digits4);
var digits5 = Create8Colors(24);
var list5 = AddColorsToList(list4, digits5);
list5.Sort();
return list5;
/// <summary>
/// Creates string-based possible values for Game8x5
/// </summary>
public static List<string[]> CreateGame8x5StringPossibleValues()
{
string[] colors = ["Red", "Blue", "Green", "Yellow", "Orange", "Purple", "Pink", "Brown"];
return StringCodeBreakerAlgorithms.GenerateAllPossibleCombinations(GameType.Game8x5, colors);
}

/// <summary>
/// Creates string-based possible values for Game5x5x4
/// </summary>
public static List<string[]> CreateGame5x5x4StringPossibleValues()
{
string[] shapeColors =
[
"RedCircle", "RedSquare", "RedTriangle", "RedDiamond", "RedStar",
"BlueCircle", "BlueSquare", "BlueTriangle", "BlueDiamond", "BlueStar",
"GreenCircle", "GreenSquare", "GreenTriangle", "GreenDiamond", "GreenStar",
"YellowCircle", "YellowSquare", "YellowTriangle", "YellowDiamond", "YellowStar",
"OrangeCircle", "OrangeSquare", "OrangeTriangle", "OrangeDiamond", "OrangeStar"
];
return StringCodeBreakerAlgorithms.GenerateAllPossibleCombinations(GameType.Game5x5x4, shapeColors);
}

/// <summary>
Expand All @@ -111,6 +75,26 @@ public static List<int> CreateReducedPossibleValues(List<int> fullList, int targ
return reducedList;
}

/// <summary>
/// Creates a reduced string list simulating a game in progress
/// </summary>
public static List<string[]> CreateReducedStringPossibleValues(List<string[]> fullList, int targetSize)
{
if (fullList.Count <= targetSize)
return fullList;

// Create a reduced list by taking every nth element
var step = fullList.Count / targetSize;
var reducedList = new List<string[]>(targetSize);

for (int i = 0; i < fullList.Count && reducedList.Count < targetSize; i += step)
{
reducedList.Add(fullList[i]);
}

return reducedList;
}

/// <summary>
/// Creates typical selection values for testing
/// </summary>
Expand All @@ -126,42 +110,48 @@ public static int CreateTestSelection(GameType gameType)
}

/// <summary>
/// Creates color name mappings for testing
/// Creates typical string selection values for testing
/// </summary>
public static Dictionary<int, string> CreateColorNames(GameType gameType)
public static string[] CreateTestStringSelection(GameType gameType)
{
var colorNames = new Dictionary<int, string>();
int key = 1;
return gameType switch
{
GameType.Game6x4 => ["Red", "Red", "Red", "Red"],
GameType.Game8x5 => ["Red", "Red", "Red", "Red", "Red"],
GameType.Game5x5x4 => ["RedCircle", "RedCircle", "RedCircle", "RedCircle"],
_ => ["Red", "Red", "Red", "Red"]
};
}

/// <summary>
/// Creates color name mappings for algorithms that need them
/// </summary>
public static Dictionary<int, string> CreateColorNames(GameType gameType)
{
if (gameType == GameType.Game5x5x4)
{
// Create shape+color combinations
var colors = new[] { "Red", "Green", "Blue", "Yellow", "Orange" };
var shapes = new[] { "Circle", "Square", "Triangle", "Diamond", "Star" };

foreach (var shape in shapes)
// For Game5x5x4, use shape+color combinations
return new Dictionary<int, string>
{
foreach (var color in colors)
{
colorNames[key] = $"{shape};{color}";
key <<= 1;
}
}
{ 1, "RedCircle" }, { 2, "RedSquare" }, { 3, "RedTriangle" }, { 4, "RedDiamond" }, { 5, "RedStar" },
{ 6, "BlueCircle" }, { 7, "BlueSquare" }, { 8, "BlueTriangle" }, { 9, "BlueDiamond" }, { 10, "BlueStar" },
{ 11, "GreenCircle" }, { 12, "GreenSquare" }, { 13, "GreenTriangle" }, { 14, "GreenDiamond" }, { 15, "GreenStar" },
{ 16, "YellowCircle" }, { 17, "YellowSquare" }, { 18, "YellowTriangle" }, { 19, "YellowDiamond" }, { 20, "YellowStar" },
{ 21, "OrangeCircle" }, { 22, "OrangeSquare" }, { 23, "OrangeTriangle" }, { 24, "OrangeDiamond" }, { 25, "OrangeStar" }
};
}
else
{
// Color-only games
var colors = gameType == GameType.Game8x5
? new[] { "Red", "Green", "Blue", "Yellow", "Orange", "Purple", "Pink", "White" }
: new[] { "Red", "Green", "Blue", "Yellow", "Orange", "Purple" };
? new[] { "Red", "Blue", "Green", "Yellow", "Orange", "Purple", "Pink", "Brown" }
: new[] { "Red", "Blue", "Green", "Yellow", "Orange", "Purple" };

foreach (var color in colors)
var colorMap = new Dictionary<int, string>();
for (int i = 0; i < colors.Length; i++)
{
colorNames[key] = color;
key <<= 1;
colorMap[i + 1] = colors[i]; // Map 1-based indices to color names
}
return colorMap;
}

return colorNames;
}
}
Loading