Optimize results parser pending queue

This commit is contained in:
Marek Lemańczyk committed 2025-09-19 00:28:17 +02:00
1 parent bb93c5a995
commit 1168ff9756
1 file changed
+73 -22
+73 -22
View File
@@ -122,7 +122,7 @@ internal static class Program
} }
CandidateResult result = ParseLine(currentLine); CandidateResult result = ParseLine(currentLine);
pendingResults.Add(result); InsertPendingResult(pendingResults, result);
DrainPrimeMatches(pendingResults, primeResults, ref currentPrime, primeEnumerator, false); DrainPrimeMatches(pendingResults, primeResults, ref currentPrime, primeEnumerator, false);
} }
@@ -273,7 +273,7 @@ internal static class Program
bool extractedPrime = ExtractPrimeEntries(pendingResults, primeResults, currentPrime); bool extractedPrime = ExtractPrimeEntries(pendingResults, primeResults, currentPrime);
if (extractedPrime) if (extractedPrime)
{ {
if (!TryAdvancePrime(primeEnumerator, ref currentPrime)) if (!TryAdvancePrime(primeEnumerator, ref currentPrime, pendingResults))
{ {
pendingResults.Clear(); pendingResults.Clear();
return; return;
@@ -288,7 +288,7 @@ internal static class Program
return; return;
} }
if (!TryAdvancePrime(primeEnumerator, ref currentPrime)) if (!TryAdvancePrime(primeEnumerator, ref currentPrime, pendingResults))
{ {
pendingResults.Clear(); pendingResults.Clear();
return; return;
@@ -303,39 +303,61 @@ internal static class Program
List<CandidateResult> primeResults, List<CandidateResult> primeResults,
ulong prime) ulong prime)
{ {
bool found = false; if (pendingResults.Count == 0)
for (int i = 0; i < pendingResults.Count; i++)
{ {
CandidateResult candidate = pendingResults[i]; return false;
if (candidate.P != prime)
{
continue;
} }
primeResults.Add(candidate); int startIndex = FindFirstIndexAtLeast(pendingResults, prime);
pendingResults.RemoveAt(i); if (startIndex >= pendingResults.Count)
i--; {
found = true; return false;
} }
return found; CandidateResult firstCandidate = pendingResults[startIndex];
if (firstCandidate.P != prime)
{
return false;
}
int endIndex = startIndex + 1;
while (endIndex < pendingResults.Count && pendingResults[endIndex].P == prime)
{
endIndex++;
}
for (int i = startIndex; i < endIndex; i++)
{
primeResults.Add(pendingResults[i]);
}
pendingResults.RemoveRange(startIndex, endIndex - startIndex);
return true;
} }
private static void RemoveEntriesBelowPrime(List<CandidateResult> pendingResults, ulong currentPrime) private static void RemoveEntriesBelowPrime(List<CandidateResult> pendingResults, ulong currentPrime)
{ {
for (int i = 0; i < pendingResults.Count; i++) if (pendingResults.Count == 0)
{ {
if (pendingResults[i].P >= currentPrime) return;
{
continue;
} }
pendingResults.RemoveAt(i); int removeCount = FindFirstIndexAtLeast(pendingResults, currentPrime);
i--; if (removeCount == 0)
} {
return;
} }
private static bool TryAdvancePrime(IEnumerator<ulong> primeEnumerator, ref ulong currentPrime) pendingResults.RemoveRange(0, removeCount);
}
private static bool TryAdvancePrime(
IEnumerator<ulong> primeEnumerator,
ref ulong currentPrime,
List<CandidateResult> pendingResults)
{
ulong minimumPending = pendingResults.Count > 0 ? pendingResults[0].P : 0UL;
do
{ {
if (!primeEnumerator.MoveNext()) if (!primeEnumerator.MoveNext())
{ {
@@ -344,9 +366,38 @@ internal static class Program
} }
currentPrime = primeEnumerator.Current; currentPrime = primeEnumerator.Current;
}
while (pendingResults.Count > 0 && currentPrime < minimumPending);
return true; return true;
} }
private static void InsertPendingResult(List<CandidateResult> pendingResults, CandidateResult result)
{
int insertIndex = FindFirstIndexAtLeast(pendingResults, result.P);
pendingResults.Insert(insertIndex, result);
}
private static int FindFirstIndexAtLeast(List<CandidateResult> pendingResults, ulong value)
{
int low = 0;
int high = pendingResults.Count - 1;
while (low <= high)
{
int mid = low + ((high - low) >> 1);
ulong midValue = pendingResults[mid].P;
if (midValue < value)
{
low = mid + 1;
continue;
}
high = mid - 1;
}
return low;
}
private readonly record struct CandidateResult(ulong P, bool IsPerfect, string Csv) private readonly record struct CandidateResult(ulong P, bool IsPerfect, string Csv)
{ {
public string ToCsv() public string ToCsv()