Skip to content

Instantly share code, notes, and snippets.

@VisualMelon
Created August 21, 2019 16:08
Show Gist options
  • Save VisualMelon/0c169ba3a3c23c53c0a4a28ff3af7bd4 to your computer and use it in GitHub Desktop.
Save VisualMelon/0c169ba3a3c23c53c0a4a28ff3af7bd4 to your computer and use it in GitHub Desktop.
using System;
using BenchmarkDotNet.Attributes;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Linq;
using System.Collections.Generic;
namespace SpanVsArray
{
class Program
{
static void Main(string[] args)
{
BenchmarkDotNet.Running.BenchmarkRunner.Run<Bench>();
}
}
public class Bench
{
[BenchmarkDotNet.Attributes.Params(5, 10, 30)]
public int N { get; set; }
[Benchmark]
public void OP()
{
PascalTriangle.Generate(N);
}
[Benchmark]
public void Jodrell()
{
JodrellPascal.Triangle(N);
}
[Benchmark]
public void JodrellNoSpan()
{
JodrellPascalNoSpan.Triangle(N);
}
[Benchmark]
public void JodrellNoSpanCache()
{
JodrellPascalNoSpanCache.Triangle(N);
}
[Benchmark]
public void PeterPerRow()
{
Peter.Generate_PerRow_Reflective(N);
}
[Benchmark]
public void PeterMelon()
{
Peter.Generate_Array_Improved_Reflective(N);
}
}
public static class JodrellPascal
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<int[]> Triangle(int n)
{
if (n < 1)
{
return ReadOnlySpan<int[]>.Empty;
}
Span<int[]> triangle = new int[n][];
for (var r = 0; r < n; r++)
{
triangle[r] = Line(r).ToArray();
}
return triangle;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<int> Line(int n)
{
if (n < 0)
{
return ReadOnlySpan<int>.Empty;
}
if (n == 0)
{
return (ReadOnlySpan<int>)new int[]
{
1
};
}
Span<int> result = new int[n + 1];
result[0] = 1;
for (var k = 0; k < n; k++)
{
result[k + 1] = result[k] * (n - k) / (k + 1);
}
return result;
}
}
public static class JodrellPascalNoSpan
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<int[]> Triangle(int n)
{
if (n < 1)
{
return ReadOnlySpan<int[]>.Empty;
}
Span<int[]> triangle = new int[n][];
for (var r = 0; r < n; r++)
{
triangle[r] = Line(r);
}
return triangle;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int[] Line(int n)
{
if (n < 0)
{
return Array.Empty<int>();
}
if (n == 0)
{
return new int[]
{
1
};
}
int[] result = new int[n + 1];
result[0] = 1;
for (var k = 0; k < n; k++)
{
result[k + 1] = result[k] * (n - k) / (k + 1);
}
return result;
}
}
public static class JodrellPascalNoSpanCache
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<int[]> Triangle(int n)
{
if (n < 1)
{
return ReadOnlySpan<int[]>.Empty;
}
Span<int[]> triangle = new int[n][];
for (var r = 0; r < n; r++)
{
triangle[r] = Line(r);
}
return triangle;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int[] Line(int n)
{
if (n < 0)
{
return Array.Empty<int>();
}
if (n == 0)
{
return new int[]
{
1
};
}
int[] result = new int[n + 1];
var last = result[0] = 1;
for (var k = 0; k < n; k++)
{
last = result[k + 1] = last * (n - k) / (k + 1);
}
return result;
}
}
public class PascalTriangle
{
public static IList<IList<int>> Generate(int numRows)
{
IList<IList<int>> result = new List<IList<int>>();
if (numRows == 0)
{
return result;
}
List<int> row = new List<int>();
row.Add(1);
result.Add(row);
if (numRows == 1)
{
return result;
}
for (int i = 1; i < numRows; i++)
{
var prevRow = result[i - 1];
row = new List<int>();
row.Add(1);
for (int j = 0; j < prevRow.Count - 1; j++)
{
row.Add(prevRow[j] + prevRow[j + 1]);
}
row.Add(1);
result.Add(row);
}
return result;
}
}
public class Peter
{
// Using arrays, calculating each row individually, using row reflection:
public static IList<IList<int>> Generate_PerRow_Reflective(int numRows)
{
var result = new int[numRows][];
for (int i = 0; i < numRows; i++)
{
var row = new int[i + 1];
row[0] = 1;
row[i] = 1;
var mid = i / 2;
for (int j = 0; j < mid; j++)
{
var value = row[j] * (i - j) / (j + 1);
row[j + 1] = value;
row[i - j - 1] = value;
}
result[i] = row;
}
return result;
}
// Using arrays instead of lists, caching the previous row's left value, and using row reflection:
public static IList<IList<int>> Generate_Array_Improved_Reflective(int numRows)
{
var result = new int[numRows][];
if (numRows == 0)
return result;
result[0] = new int[] { 1 };
if (numRows == 1)
return result;
for (int i = 1; i < numRows; i++)
{
var prevRow = result[i - 1];
var row = new int[i + 1];
var left = 0;
var mid = (i / 2) + 1;
for (int j = 0; j < mid; j++)
{
int right = prevRow[j];
var sum = left + right;
row[j] = sum;
row[i - j] = sum;
left = right;
}
result[i] = row;
}
return result;
}
}
}
@Rick-at-OSIsoft
Copy link

Very nice data!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment