for (int i = leadPawnsCnt; i < size; ++i)
for (int j = i; j < size; ++j)
if (d->pieces[i] == pieces[j])
{
std::swap(pieces[i], pieces[j]);
std::swap(squares[i], squares[j]);
break;
}
it seems need to replace "j = i" with "j = i +1"
for (int j = i + 1; j < size; ++j)
Indeed, when i==j, we are swapping pieces[i] with pieces[j], which is useless.
However, in some cases, the break; instruction will help skip some j iterations.
So the master code is OK
But your version would also be OK
Here is how master works with an example
d->pieces is the model sequence {A,B,C,D,E} the "i" loop
pieces is the thing we want to reorder. Let's say it is {A,E,D,C,B}, the "j" loop
i j
00 A==A useless swap, but break j
11 B!=E pass
12 B!=D pass
13 B!=C pass
14 B==B so swap, new sequence is {A,B,D,C,E} break j
22 C!=D pass
23 C==C so swap new sequence is {A,B,C,D,E} break j
33 D==D useless swap, but break j
44 useless swap and break j
Here is how your version works with an example
d->pieces is the model sequence {A,B,C,D,E} the "i" loop
pieces is the thing we want to reorder. Let's say it is {A,E,D,C,B}, the "j" loop
i j
01 A!=E pass
02 A!=D pass
03 A!=C pass
04 A!=B pass
12 B!=D pass
13 B!=C pass
14 B==B so swap, new sequence is {A,B,D,C,E} break j
23 D==D so swap new sequence is {A,B,C,D,E} break j
34 D!=E pass
4x pass
So (in this case) about the same number of instructions
There might one or 2 repetitions in the sequences (for example {ABCDDEE})
in which case the master code might be a little bit faster, but this will need proof.
We could also write the first line as follow.
for (int i = leadPawnsCnt; i < size - 1 ; ++i)
Syzygy tables can hold up to 7 pieces
In the sequence that will be ordered, there is no pawns,
but still some repetitions are possible (there might be 2 white rooks for example)
So will always have a W_KING and B_KING (A and B below) and some pieces remains, and in normal positions there is never three same piece.
So one might want to compare the 2 versions against all permutations of
{AB}
{ABC}
{ABCD}
{ABCC}
{ABCDE}
{ABCDD}
{ABCDEF}
{ABCDEE}
{ABCCDD}
{ABCDEFG}
{ABCDEFF}
{ABCDDEE}
and find best time.
I'm now confident that the proposed int j = i + 1 would be an improvement compared to master
For example for case {ABCDEFF}
I ran all distinct permutations, of int[] perm={1,2,3,4,5,6,6 } and counted number of required comparisons c and swaps sw to transform each of them into int[] target={1,2,3,4,5,6,6 }
pseudocode:
int c = 0;
int sw = 0;
int size = 6;
int[] goal={1,2,3,4,5,6,6 };
int[] perm=goal.Clone();
for each distinct permutation perm
{
int [] test = perm.Clone();
for (int i = 0; i < size; ++i)
for (int j = i + iextra; j < size; ++j) //master is using iextra = 0, pr is using iextra = 1
{
comps+=1;
if (target[i] == test[j])
{
swaps +=1;
std::swap(perms[i], perms[j]);
break;
}
}
}
results are as follow, and shows that for each of the 12 types of permutations,
the proposed change will be better than master,
a) it will take less comparisons in average
b) it will take less swaps in average.
Averages divides by column# 2 (number of permutations)

conclusion: the following is the best version
I also changed the first line from i < size to i < size - 1
for (int i = leadPawnsCnt; i < size - 1; ++i)
for (int j = i + 1; j < size; ++j)
if (d->pieces[i] == pieces[j])
{
std::swap(pieces[i], pieces[j]);
std::swap(squares[i], squares[j]);
break;
}
For reference here is the exact c# code I used to establish the above statistics
Not the most efficient way to enumerate distinct permutations, but juts good enough
to produce the stats.
using System;
using System.Collections.Generic;
class Issue2372
{
static string displayAsString(int[] ar)
{
string res = "";
for (int i = 0; i < ar.Length; ++i)
res += ar[i].ToString();
return res;
}
static void enumperm(int[] ar, int n, int idx, ref HashSet<string> h, int[] goal, ref int iter, ref int swaps, int iextra)
{
if (idx >= n - 1)
{
string hkey = displayAsString(ar);
if (!h.Contains(hkey))
{
h.Add(hkey);
//Console.WriteLine(kkey);
algo(ar, n, goal, ref iter, ref swaps, iextra);
}
}
else
{
enumperm(ar, n, idx + 1, ref h, goal, ref iter, ref swaps, iextra);
for (int j = idx + 1; j < n; j++)
{
swap(ar, idx, j);
enumperm(ar, n, idx + 1, ref h, goal, ref iter, ref swaps, iextra);
swap(ar, idx, j);
}
}
}
static void swap(int[] ar, int i, int j)
{
int c = ar[i];
ar[i] = ar[j];
ar[j] = c;
}
public static void Main()
{
HashSet<string> h = new HashSet<string>();
int[][] goalsequence = new int[][]
{
new int[] { 1, 2 },
new int[] { 1, 2, 3 },
new int[] { 1, 2, 3, 4 },
new int[] { 1, 2, 3, 3 },
new int[] { 1, 2, 3, 4, 5 },
new int[] { 1, 2, 3, 4, 4 },
new int[] { 1, 2, 3, 4, 5, 6 },
new int[] { 1, 2, 3, 4, 5, 5 },
new int[] { 1, 2, 3, 3, 4, 4 },
new int[] { 1, 2, 3, 4, 5, 6, 7 },
new int[] { 1, 2, 3, 4, 5, 6, 6 },
new int[] { 1, 2, 3, 4, 4, 5, 5 }
};
for (int itest = 0; itest < goalsequence.Length; ++itest)
{
int[] perms = (int[]) goalsequence[itest].Clone();
int n = perms.Length;
int[] comps = new int[] { 0, 0 };
int[] swaps = new int[] { 0, 0 };
for (int algo = 0; algo < 2; algo++)
{
h.Clear();
enumperm(perms, n, 0, ref h, goalsequence[itest], ref comps[algo], ref swaps[algo], algo);
}
System.Console.WriteLine(String.Format("{0}: p = {5} master comps={1} swaps={2} pr comps={3} swaps={4}", itest, comps[0], swaps[0], comps[1], swaps[1], h.Count));
}
//wait for uer input before closing program
Console.ReadLine();
}
static void algo(int[] a, int size, int[] goal, ref int comps, ref int swaps, int extra)
{
//using extra = 0, this is similar to sf master
//using extra = 1, this is similar to pr
int[] ar = (int[]) a.Clone();
for (int i = 0; i < size-1; ++i) //using size -1 or size is the same thing
for (int j = i + extra; j < size; ++j)
{
comps++;
if (goal[i] == ar[j])
{
swaps++;
swap(ar, i, j);
break;
}
}
//verification that "goal" was achieved
for (int i = 0; i < size; ++i)
System.Diagnostics.Debug.Assert(goal[i] == ar[i]);
}
}
OK, i just found out that the leading pawns are of the same color.
Say that there is only one. We still have at most 6 pieces to distribute, with our kings A and B
and some possible case where there is 3 or 4 opponent pawns.
So I missed 3 cases, which change the total as follow , and still favor the suggested change in every
case in average.

Most helpful comment
I'm now confident that the proposed int j = i + 1 would be an improvement compared to master
For example for case {ABCDEFF}
I ran all distinct permutations, of int[] perm={1,2,3,4,5,6,6 } and counted number of required comparisons c and swaps sw to transform each of them into int[] target={1,2,3,4,5,6,6 }
pseudocode:
results are as follow, and shows that for each of the 12 types of permutations,
the proposed change will be better than master,
a) it will take less comparisons in average
b) it will take less swaps in average.
Averages divides by column# 2 (number of permutations)
conclusion: the following is the best version
I also changed the first line from i < size to i < size - 1