Skip to content

Instantly share code, notes, and snippets.

@Ilchert
Last active March 1, 2019 15:25
Show Gist options
  • Save Ilchert/1605b071eb18d4e8c595fc4db237f565 to your computer and use it in GitHub Desktop.
Save Ilchert/1605b071eb18d4e8c595fc4db237f565 to your computer and use it in GitHub Desktop.
Combination task on long
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp
{
class Program
{
private const int DataSize = 80000;
private const int DataItemSize = 20;
static void Main()
{
var sw = new Stopwatch();
sw.Start();
var comparer = Comparer<long>.Default;
var data = PrepareData(comparer);
sw.Stop();
Console.WriteLine(sw.Elapsed);
sw.Restart();
const int firstIndex = 0;
const int lastIndex = DataItemSize - 1;
for (int leftIndex = 0; leftIndex < DataSize - 1; leftIndex++)
{
var boundsExceed = false;
for (int rightIndex = leftIndex + 1; rightIndex < DataSize; rightIndex++)
{
var resultItem = new ResultItem(leftIndex, rightIndex);
var left = data[leftIndex];
var right = data[rightIndex];
if (boundsExceed)
{
Out(resultItem);
continue;
}
//hot path
var boundComp = left[lastIndex].CompareTo(right[firstIndex]);
if (boundComp < 0)
{
Out(resultItem);
boundsExceed = true;
continue;
}
if (boundComp == 0)
{
resultItem.ItemsCount = 1;
Out(resultItem);
continue;
}
//main comparison
var startLeft = InternalBinarySearch(left, right[firstIndex]);
if (startLeft < 0)
startLeft = ~startLeft;
var endRight = InternalBinarySearch(right, left[lastIndex]);
if (endRight < 0)
{
endRight = Math.Min(~endRight, lastIndex);
}
byte itemsCount = 0;
var startRight = 0;
while (startLeft < DataItemSize && startRight <= endRight)
{
var cmp = left[startLeft].CompareTo(right[startRight]);
if (cmp < 0)
{
startLeft++;
}
else if (cmp > 0)
{
startRight++;
}
else
{
itemsCount++;
startLeft++;
startRight++;
}
}
resultItem.ItemsCount = itemsCount;
Out(resultItem);
}
}
Console.WriteLine(sw.Elapsed);
}
private static void Out(ResultItem item)
{
}
internal static int InternalBinarySearch<T>(
long[] array,
T value)
{
int index = 0;
int length = array.Length;
int num1 = index;
int num2 = index + length - 1;
while (num1 <= num2)
{
int index1 = num1 + (num2 - num1 >> 1);
int num3 = array[index1].CompareTo(value);
if (num3 == 0)
return index1;
if (num3 < 0)
num1 = index1 + 1;
else
num2 = index1 - 1;
}
return ~num1;
}
public static long[][] PrepareData(IComparer<long> comparer)
{
//prepare data
var data = new long[DataSize][];
for (int i = 0; i < DataSize; i++)
{
data[i] = new long[DataItemSize];
for (int j = 0; j < DataItemSize; j++)
data[i][j] = RandomLong();
}
//sort items
for (int i = 0; i < DataSize; i++)
Array.Sort(data[i], comparer);
//again sort
Array.Sort(data, (l, r) => comparer.Compare(l[0], r[0]));
return data;
}
public struct ResultItem
{
public int LeftIndex;
public int RightIndex;
public byte ItemsCount;
public ResultItem(int leftIndex, int rightIndex)
{
LeftIndex = leftIndex;
RightIndex = rightIndex;
ItemsCount = 0;
}
}
private static readonly Random random = new Random();
public static long RandomLong()
{
Span<byte> data = stackalloc byte[8];
random.NextBytes(data);
return BitConverter.ToInt64(data) % 281474976710656;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment