Table of Contents

Wizardry and Steamworks Portable Library Class (PCL)

Some functions are implemented as part of the Wizardry and Steamworks portable library class (PCL) and the full library can be retrieved from SVN by checking out the following repository:

The PCL targets:

  • .NET Framework 4.5.1
  • Microsoft Windows 8.1
  • Windows Phone 8.1

Linq Number of Times

Use the following one-liner to display a line of dashes that goes goes from one end of the terminal to the other:

new List<int>(new int[Console.WindowWidth]).ForEach(i => Console.Write("-"));

which creates an empty list of integers of size Console.WindowWidth and then for each element it writes a dash to the console.

Assemblies in Different Directory

Assemblies can be loaded from a different directory by creating an ASSEMBLY.EXE.conf file, where ASSEMBLY.EXE is the application executable with the following contents:

<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <probing privatePath="lib;bin"/>
      </assemblyBinding>
   </runtime>
</configuration>

This will make the application to look for the assemblies in the lib/ and bin/ paths.

Get Memory Currently In-Use by Process

freeByes will contain the amount of memory used by the current process in bytes.

System.Diagnostics.Process proc = System.Diagnostics.Process.GetCurrentProcess();
int freeBytes = proc.PrivateMemorySize64;

Select Even Element of Array

Given the array:

[ 0, 1, 2, 3, 4, 5, ... ]

the following LINQ expression:

var a = data.Where((value, index) => (index % 2) == 0).ToArray();

will set a to the array:

[ 0, 2, 4, ... ]

Serializing a Structure

Suppose that we have a C# structure that defines a person along with multiple properties for that person and that we want to create a method that will serialize this structure to the key-value data. The ToKeyValueData function in the example below uses reflection to loop over the properties of the Person structure and returns a key-value data compatible string.

public struct Person {
    ...
    public Person(string name, string address, ...) {
        this.name = name;
        this.address = address;
    }
    ...
    ///////////////////////////////////////////////////////////////////////////
    //    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
    ///////////////////////////////////////////////////////////////////////////
    /// <summary>
    /// Serializes a structure to a Wizardry and Steamworks key-value data string.
    /// </summary>
    private string ToKeyValueData() {
        var sb = new StringBuilder();
        object p = new Person();
        foreach(var k in p.GetType().GetProperties()) {
            var v = GetType().GetProperty(k.Name).GetValue(this, null).ToString();
            if(string.IsNullOrEmpty(v)) continue;
            sb.Append(string.Format("{0}={2}", k.Name, v);
                      sb.Append(delimiter);
        }
        if(sb.Length != 0) sb.Length--;
        return sb.ToString();
    }
    ...
    public string name { get; internal set; }
    public string address { get; internal set; }
    ...
}

That is done by enumerating the properties of the Person structure using GetProperties on the type of the structure which gives us a propertyInfo object from which we can extract the name of that property. In order to get the value of that property, we use GetProperty on the name of property and get the value of the instance object (this).

Temporary Structure

There are cases where you want a wrapper that can hold objects in order to avoid declaring temporary variables (from the series, "can I partially allocate an object?"). For example, you perform a loop and store data in the upper-scope:

int time = 0;
int greeting = "";
foreach(var o in ...) {
  switch(o) {
    case ...:
      time = 10;
      break;
    case ...:
      greeting = "Good Day!";
      break;
  }
}

In such cases, a generic object array is more suitable:

object[2] data = new object[2];
foreach(var o in ...) {
  switch(o) {
    case ...:
      data[0] = 10;
      break;
    case ...:
      data[1] = "Good Day!";
      break;
  }
}
if(data.Any(o => o == null)) {
  // data contains at least one null element
}

This works great as a temporary structure, in order to avoid creating a new class or struct which would live much longer than the inlined generic object.

Get Variable Names

using System.Linq.Expressions;
...
string ON;
...
private static string GetName<T>(Expression<Func<T>> e) {
    return ((MemberExpression) e.Body).Member.Name;
}
...
Console.WriteLine(GetName(() => ON));

Monitoring File Activity

When you have to monitor files for changes or access times, C# comes equipped for that task with the FileSystemWatcher class. On UNIX / mono, FileSystemWatcher is implemented using gamin as well as other mechanisms to provide the same functionality.

For example, the following filesystem watcher scans the current directory for:

  • last access changes.
  • last written changes.
  • filename changes.
  • directory name changes.

installs a filter for ini files and then when any ini file in the current directory is changed, it will raise HandleDirectoryChange. HandleDirectoryChange will then print out the file name (in e.Name) to the console:

FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = Directory.GetCurrentDirectory();
watcher.NotifyFilter = NotifyFilters.LastAccess | 
                       NotifyFilters.LastWrite | 
                       NotifyFilters.FileName | 
                       NotifyFilters.DirectoryName;
watcher.Filter = "*.ini";
watched.Changed += HandleDirectoryChange;
...
private static void HandleDirectoryChange(object sender, FileSystemEventArgs e)
{
    Console.WriteLine(e.Name);
}

Note that FileSystemWatcher monitors directories and if you want to monitor just a file, you can set the Filter to the file name, as in:

watcher.Path = Directory.GetCurrentDirectory();
watcher.Filter = "Corrade.ini";

Try to Parse a Nullable Structure

TryParse does not function on nullable types such as int?. The following function can act as a substitute for int.TryParse:

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Attempts to parse a string to a structure.
/// </summary>
/// <param name="input">the input string</param>
/// <param name="variable">the variable holding the parsed type T</param>
/// <returns>true if the variable could be parsed</returns>
public static bool TryParseNullable<T>(string input, out T? variable) where T:struct 
{
    if (string.IsNullOrEmpty(input))
    {
        variable = null;
        return false;
    }
    T? localVariable;
    try
    {
        IConvertible convertibleString = input;
        localVariable = (T)convertibleString.ToType(typeof(T), CultureInfo.CurrentCulture);
    }
    catch (Exception)
    {
        variable = null;
        return false;
    }
    variable = localVariable;
    return true;
}

Get Names and Values of Enumeration Members

Can be done by using reflection:

foreach (FieldInfo fi in typeof(Molecules).GetFields(BindingFlags.Public | BindingFlags.Static))
{
   Console.WriteLine(fi.Name);
   Console.WriteLine(fi.GetValue(null));
}

Group a Sequence by Pairs

Suppose you have a set of elements:

10, 20, 30, 40, 50

and that you want to create sub-sets from successive elements as pairs. Following the example, you want to create the pairs: $(10, 20)$, $(30, 40)$, $(50, 60)$ out of the initial set preferably as key-value pairs.

In that case, there are several solutions, but if you want to use only one LINQ line, then the following expression will return the desired key-value pairs:

list.Select((o, p) => new {o = o, p = p})
    .GroupBy(q => q.p/2, q => q.o)
    .Select(o => o.ToList())
    .TakeWhile(o => o.Count % 2 == 0)
    .ToDictionary(o => o.First(), p => p.Last())

It does that by:

  1. grouping odd and even elements together,
  2. selecting the entire list of groups,
  3. selecting only matching key-value pairs,
  4. creating a key value pair from the first element and the last element in the pair-set.

Serialising Comma-Separated Values to a Dictionary using Regular Expressions

Given a comma-separated string (CSV) such as:

Color, Red, Life, Good, Day, Sunday

where the even strings (Color, Life, Day) represent keys and the odd strings (Red, Good, Sunday) represent values, one can use regular expressions (System.Text.RegularExpressions) to serialise the string into a dictionary of key-value pairs:

using System.Text.RegularExpressions;
//...
Dictionary<string, string> pairs = 
	Regex.Matches(command.Attachments, @"\s*(?<key>.+?)\s*,\s*(?<value>.+?)\s*(,|$)")
		.Cast<Match>()
		.ToDictionary(m => m.Groups["key"].Value, m => m.Groups["value"].Value);

Note that the regex is sufficiently resistant to abuse, for example, it will work fine if the spaces around the strings are garbled:

Color , Red,     Life,Good , Day , Sunday

Another, better variant is to use a splitting regular expression and then collect the even and odd keys with a bit of LINQ:

using System.Text.RegularExpressions;
//...
public static Regex CSVRegEx = new Regex(@"\s*,\s*(?=(?:[^\""]*\""[^\""]*\"")*(?![^\""]*\""))",
            RegexOptions.Compiled);
//...
foreach (KeyValuePair<string, string> a in CSVRegEx.Split(input).Select((value, index) => new {value, index})
    .GroupBy(x => x.index/2, x => x.value)
    .Select(x => x.ToList())
    .TakeWhile(o => o.Count % 2 == 0)
    .ToDictionary(o => o.First(), p => p.Last()))
{
    Console.WriteLine(a);
}

For more details, see group a sequence by pairs.

Convert HashTable to Dictionary

///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Converts a hash table to a dictionary.
/// </summary>
/// <typeparam name="K">key type</typeparam>
/// <typeparam name="V">value type</typeparam>
/// <param name="table">a hash table</param>
/// <returns>a dictionary</returns>
public static Dictionary<K, V> HashtableToDictionary<K, V>(Hashtable table)
{
    return table.Cast<DictionaryEntry>()
        .ToDictionary(kvp => (K)kvp.Key, kvp => (V)kvp.Value);
}

Calculate Memory Size of Object

/// <summary>
/// Calculates the length in bytes of an object 
/// and returns the size 
/// </summary>
/// <param name="TestObject"></param>
/// <returns></returns>
private int GetObjectSize(object TestObject)
{
    BinaryFormatter bf = new BinaryFormatter();
    MemoryStream ms = new MemoryStream();
    byte[] Array;
    bf.Serialize(ms, TestObject);
    Array = ms.ToArray();
    return Array.Length;
}

Convert a UNIX Timestamp to DateTime

Using the wasUNIXTimeStampToDateTime function we can convert a UNIX timestamp to a DateTime object:

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Returns a DateTime object from a given UNIX timestamp.
/// </summary>
/// <param name="timeStamp">the UNIX time stamp to convert</param>
/// <returns>the DateTime object representing the timeStamp</returns>
private static DateTime wasUNIXTimeStampToDateTime(double timeStamp) {
    return new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(timeStamp);
}

an example call is:

DateTime date = wasUNIXTimeStampToDateTime(1406583923);

Convert DateTime to UNIX Timestamp

Given a DateTime object, the wasDateTimeToUnixTimeStamp function returns the UNIX timestamp.

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Returns the UNIX time from a DateTime object.
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
private static double wasDateTimeToUnixTimeStamp(DateTime date) {
    return date.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, 0)).Duration().TotalSeconds;
}

Get an Enumeration Value from Description

Suppose you have an enumeration, with the following structure:

[Flags]
private enum Days : uint
{
    [Description("Monday")]
    ONE = 1,
    [Description("Tuesday")]
    TWO = 2
}

and you want to get the value (the uint 1) of the field that has the description Monday.

In that case, using wasGetEnumValueFromDescription:

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Get enumeration value from its description.
/// </summary>
/// <typeparam name="T">the enumeration type</typeparam>
/// <param name="description">the description of a member</param>
/// <returns>the value or the default of T if case no description found</returns>
private static T wasGetEnumValueFromDescription<T>(string description)
{
    var field = typeof (T).GetFields()
        .SelectMany(f => f.GetCustomAttributes(
            typeof (DescriptionAttribute), false), (
                f, a) => new {Field = f, Att = a}).SingleOrDefault(a => ((DescriptionAttribute) a.Att)
                    .Description == description);
    return field != null ? (T) field.Field.GetRawConstantValue() : default(T);
}

you would make a call such as:

uint day = (uint) wasGetEnumValueFromDescription(new Days(), "Monday");

such that the unit day will hold the value 1 after the call.

Get Description from Enumeration Value

Suppose you have an enumeration, with the following structure:

[Flags]
private enum Days : uint
{
    [Description("Monday")]
    ONE = 1,
    [Description("Tuesday")]
    TWO = 2
}

and you want to get the description (Monday) from the value 1.

Using wasGetDescriptionFromEnumValue:

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Get the description from an enumeration value.
/// </summary>
/// <param name="value">an enumeration value</param>
/// <returns>the description or the empty string</returns>
private static string wasGetDescriptionFromEnumValue(Enum value)
{
    DescriptionAttribute attribute = value.GetType()
        .GetField(value.ToString())
        .GetCustomAttributes(typeof (DescriptionAttribute), false)
        .SingleOrDefault() as DescriptionAttribute;
    return attribute != null ? attribute.Description : string.Empty;
}

you would make a call such as:

string day = wasGetDescriptionFromEnumValue((Days)1);

such that the string day will hold the value Monday after the call.

Get the Description of a Structure Member

Suppose that you have a structure:

private struct Person
{
    [Description("the name")]
    public string Name;
    [Description("the age")]
    public int Age;
}

and that you have instantiated the structure as:

Person person = new Person {
    Name = "Mr. Sparky",
    Age = 34
}

and you want to get the description of the Age member of the struct Person.

In that case, using wasGetStructureMemberDescription:

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Get the description of structure member.
/// </summary>
/// <typeparam name="T">the type of the structure to search</typeparam>
/// <param name="structure">the structure to search</param>
/// <param name="item">the value of the item to search</param>
/// <returns>the description or the empty string</returns>
public static string wasGetStructureMemberDescription<T>(T structure, object item) where T : struct
{
    var field = typeof(T).GetFields()
        .SelectMany(f => f.GetCustomAttributes(typeof(DescriptionAttribute), false),
            (f, a) => new { Field = f, Att = a }).SingleOrDefault(f => f.Field.GetValue(structure).Equals(item));
    return field != null ? ((DescriptionAttribute)field.Att).Description : string.Empty;
}

you would make a call such as:

string ageDescription = wasGetStructureMemberDescription(person, person.Age);

which will leave ageDescription containing the string the age after the call.

Get All Descriptions of an Enumeration

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Returns all the field descriptions of an enumeration.
/// </summary>
/// <param name="enumeration">the enumeration</param>
/// <returns>the field descriptions</returns>
private static IEnumerable<string> wasGetEnumDescriptions(this Enum enumeration)
{
    return from fi in enumeration.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)
        select ((Enum) fi.GetValue(enumeration)).GetAttribute<DescriptionAttribute>()
        into attribute
        where attribute != null && !string.IsNullOrEmpty(attribute.Description)
        select attribute.Description;
}

Bitwise Flag Enumerations

The following are functions that manipulate flag-type enumerations, such as:

[Flags]
private enum Days : uint
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}

and are useful before the .NET release 4.0 which has built-in functions that can manipulate flags.

Set Flags

Sets a flag (or a flag mask) in a flag enumeration.

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
// Original by Dan Tao.
/// <summary>
///     Sets flag in flags.
/// </summary>
/// <param name="flags">an enumeration to set flags on</param>
/// <param name="flag">a flag or mask to set on flags</param>
private static void SetFlags<T>(ref T flags, T flag) where T : struct
{
    flags = (T) (object) ((uint) (object) flags | (uint) (object) flag);
}

For example, using the Days structure:

Days d = new Days();
SetFlags(ref d, Days.Monday | Days.Friday | Days.Sunday);

Unset Flags

Unsets a flag (or flag mask) in a flag enumeration.

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
// Original by Dan Tao.
/// <summary>
///     Unsets a flag.
/// </summary>
/// <param name="flags">an enumeration to unset flags on</param>
/// <param name="flag">a flag or mask to unset of flags</param>
private static void UnsetFlags<T>(ref T flags, T flag) where T : struct
{
    flags = (T) (object) ((uint) (object) flags & (~(uint) (object) flag));
}

For example, using the Days structure:

Days d = new Days();
UnsetFlags(ref d, Days.Friday);

or, for multiple flags:

Days d = new Days();
UnsetFlags(ref d, Days.Friday | Days.Sunday);

Determine if a Flag or Flag Mask is Set

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Determines if the flags in flag are set in the flags structure.
/// </summary>
/// <param name="flags">the structure to check against</param>
/// <param name="flag">a single flag or a mask to check</param>
/// <returns>true if flag is set in flags</returns>
private static bool IsSetFlags<T>(T flags, T flag) where T : struct
{
    return
        Enum.GetValues(typeof (T))
        .Cast<uint>()
        .Where(f => (f & (uint) (object) flag) == f)
        .All(set => ((uint) (object) flags & set) != 0);
}

For example, using the Days structure:

Days d = new Days();
SetFlags(ref d, Days.Monday | Days.Friday | Days.Sunday);
IsSetFlags(ref d, Days.Monday | Days.Friday);

the return value of IsSetFlags will be True.

Get the Values of Set Flags

Gets the values of set flags in an enumeration.

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Gets the flag values in flags.
/// </summary>
/// <param name="flags">an enumeration with certain flags set</param>
/// <returns>the values of the flags set</returns>
private static IEnumerable<uint> GetSetFlagValues<T>(T flags) where T : struct
{
    return Enum.GetValues(typeof(T)).Cast<uint>().Where(f => (f & (uint)(object)flags) == f);
}

For example, using the Days structure:

Days d = new Days();
SetFlags(ref d, Days.Monday | Days.Friday | Days.Sunday);
List<uint> set = GetSetFlagValues(d).ToList();
foreach (uint value in set) {
    Console.WriteLine(value.ToString());
}

will print out:

1
16
64

Get the Names of Set Flags

Gets the names of set flags.

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Gets the names of the flags set in flags.
/// </summary>
/// <param name="flags">an enumeration with certain flags set</param>
/// <returns>the names of the set flags</returns>
private static IEnumerable<string> GetSetFlagNames<T>(T flags) where T : struct
{
    return
        Enum.GetValues(typeof (T))
        .Cast<uint>()
        .Where(f => (f & (uint)(object)flags) == f)
        .Select(f => ((T) (object) f).ToString());
}

For example, using the Days structure:

Days d = new Days();
SetFlags(ref d, Days.Monday | Days.Friday | Days.Sunday);
List<string> set = GetSetFlagNames(d).ToList();
foreach (string name in set) {
    Console.WriteLine(name);
}

will print out:

Monday
Friday
Sunday

Graceful Shutdown of Console Applications

Capturing the closing event of a console under Windows can be done by importing the SetConsoleCtrlHandler function from Kernel32.dll and has been discussed in the windows section. However, kernel32.dll is not available under mono and will not work on Unix platforms. In order to be able to capture both the console close and sending a termination signal such as SIGTERM under Unix, the following variation branches on the platform and uses SetConsoleCtrlHandler under Windows and signals under Unix:

// For Unix signals.
using Mono.Unix;
using Mono.Unix.Native;
// For Windows events.
using System.Runtime.InteropServices;
 
//...
 
        /// <summary>
        ///     Import console handler for windows.
        /// </summary>
        [DllImport("Kernel32.dll")]
        private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
 
        // A delegate for SetConsoleCtrlHandler.
        private delegate bool EventHandler(CtrlType ctrlType);
 
        // Set to static in order to avoid garbage collection.
        private static EventHandler ConsoleEventHandler;
 
        // An enumerated type for the control messages
        // sent to the handler routine.
        private enum CtrlType
        {
            CTRL_C_EVENT = 0,
            CTRL_BREAK_EVENT,
            CTRL_CLOSE_EVENT,
            CTRL_LOGOFF_EVENT = 5,
            CTRL_SHUTDOWN_EVENT
        }
 
        private static bool ConsoleCtrlCheck(CtrlType ctrlType)
        {
            KeyValuePair<char, ManualResetEvent> semaphore = ConnectionSemaphores.FirstOrDefault(s => s.Key.Equals('u'));
            if (semaphore.Value != null)
            {
                semaphore.Value.Set();
            }
 
            // Wait for threads to finish.
            Thread.Sleep(60000);
            return true;
        }
 
        // Main entry point.
        public static void Main()
        {
            // Branch on platform and set-up termination handlers.
            switch (Environment.OSVersion.Platform)
            {
                    // SetConsoleCtrlHandler supported on Windows 2000 or later.
                case PlatformID.Win32NT:
                    // Setup console handler.
                    ConsoleEventHandler += ConsoleCtrlCheck;
                    SetConsoleCtrlHandler(ConsoleEventHandler, true);
                    break;
                    // For Unix signals, catch SIGTERM (daemon).
                case PlatformID.Unix:
                    UnixSignal[] signals =
                    {
                        new UnixSignal(Signum.SIGTERM)
                    };
                    new Thread(() =>
                    {
                        UnixSignal.WaitAny(signals, -1);
 
                        KeyValuePair<char, ManualResetEvent> semaphore =
                            ConnectionSemaphores.FirstOrDefault(s => s.Key.Equals('u'));
                        if (semaphore.Value != null)
                        {
                            semaphore.Value.Set();
                        }
                    }).Start();
                    break;
            }
 
            // Rest of the program
            // ...
        }

This method will branch on Environment.OSVersion.Platform and decide what is suitable for each platform. Note, that if the coding is done on Windows, that the Mono.Posix.dll library has to be added to the list of references in Visual Studio. This can be accomplished by downloading mono for Windows and the DLL can usually be found in: C:\Program Files (x86)\Mono-3.2.3\lib\mono\2.0.

Split String into Groups of Strings

Using LINQ, this can be done by:

int groups = 2;
 
IEnumerable<string> strings = data.Select((c, index) => new {c, index})
    .GroupBy(x => x.index/groups)
    .Select(xg => string.Join("", xg.Select(x => x.c.ToString(CultureInfo.InvariantCulture)).ToArray()));

where groups represents the number of groups to split a string into.

For example, for a string such as:

good day!

and groups set to 2, the resulting substrings will be:

go
od
 d
ay
!

RFC3986 URI Escape and Unescape a Data String

The Uri.EscapeDataString function in C# has a 32766 character limit, after which the function will throw an UriFormatException error (as per the MSDN documentation). The following functions are replacements for both Uri.EscapeDataString and Uri.UnescapeDataString that will accept longer strings.

Unescape

///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>URI Unescapes an RFC3986 string</summary>
/// <param name="data">a string to unescape</param>
/// <returns>the resulting string</returns>
private static string wasUriUnescapeDataString(string data)
{
    return
        Regex.Matches(data, @"%([0-9A-Fa-f]+?){2}")
            .Cast<Match>()
            .Select(m => m.Value)
            .Distinct()
            .Aggregate(data,
                (current, match) =>
                    current.Replace(match,
                        ((char) int.Parse(match.Substring(1), NumberStyles.AllowHexSpecifier)).ToString(
                            CultureInfo.InvariantCulture)));
}

Escape

///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>RFC3986 URI Escapes a string</summary>
/// <param name="data">a string to escape</param>
/// <returns>an RFC3986 escaped string</returns>
private static string wasUriEscapeDataString(string data)
{
    StringBuilder result = new StringBuilder();
    foreach (char c in data.Select(o => o))
    {
        if(char.IsLetter(c) || char.IsDigit(c)) {
            result.Append(c);
            continue;
        }
        result.AppendFormat("%{0:X2}", (int) c);
    }
    return result.ToString();
}

Fibonacci Number Generator

As a translation of the lolcode variant, this Fibonacci number generator will return count-sequential Fibonacci numbers starting with the initialization vector first and second (which can be either 0, 1 or 1, 1).

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Returns count sequential Fibonacci numbers given the initialization
///     vector parameters first and second which can be either 0, 1 or 1, 1.
/// </summary>
/// <param name="count">the amount of Fibonacci numbers </param>
/// <param name="first">the first number, either 0 or 1</param>
/// <param name="second">the second number has to be 1</param>
/// <returns>count sequential Fibonacci numbers</returns>
private static IEnumerable<ulong> wasFibonacci(ulong count, ulong first, ulong second) {
    if (count <= 0) yield break;
    yield return first;
    foreach(ulong f in wasFibonacci(--count, second, first + second))
        yield return f;
}

Determine if Number is a Power of Two

The function IsPowerOfTwo returns true if the number n is a power of two and false otherwise.

private static bool IsPowerOfTwo(uint n) {
    return (n & (n - 1)) == 0 && n != 0;
}

XOR Swap Two Integers

This is actually very elegant in C# using the ref operator which allows us to create a function wasXORSwap that will swap the two integers q and p using the XOR swap algorithm.

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Swaps two integers passed by reference using XOR.
/// </summary>
/// <param name="q">first integer to swap</param>
/// <param name="p">second integer to swap</param>
private static void wasXORSwap(ref int q, ref int p)
{
    q ^= p;
    p ^= q;
    q ^= p;
}

Parallel Insertion of Matrix Values in Flat Array

One interesting problem is the following: suppose that you have a certain terrain, from the bottom-left corner $A(x_{1}, y_{1})$ to the top-right corner $B(x_{2}, y_{2})$ and that the domain of values for $x$ and $y$ is discrete. You want to measure the height for each coordinate $C(x_{i}, y_{j})$ in the rectangle whose diagonal is $\overline{AB}$ and store it in a flat array of values.

This is perhaps visualised better as a grid (or a matrix):

x x B
x x x
A x x 

where each element has a certain height.

It is clear that this will turn out to be an $O^2$ algorithm because every single coordinate will have to be measured. However, if you benefit from threads, then depending on the number of threads that can be run in parallel, the $O^2$ complexity can be reduced considerably. In the visualisation above, we have to visit 9 different coordinates, and, were we to have 9 CPUs, then the entire $O^2$ algorithm could be reduced to an $O1$ algorithm.

In order to write the algorithm, we are first going to compute the index of each element on the grid, in the order that we measure it by. From the visualisation, we have the following grid:

2 5 8
1 4 7
0 3 6 

from $A$ at index $0$ to $B$ at index $8$. We express the index of the array in function of our current $x$ and $y$ coordinate:

\begin{eqnarray*}
\text{index} &=& x_{max} * x + y
\end{eqnarray*}

where:

  • $x$ and $y$ represent the current location,
  • $x_{max}$ represents the width of the grid.

Now we can write the algorithm:

// calculate the sizes for x and y
int sx = x2 - x1 + 1;
int sy = y2 - y1 + 1;
// create an array of the total size (sx*sy)
float[] data = new float[sx*sy];
// loop over the range of x, loop over the range of y
Parallel.ForEach(Enumerable.Range(x1, sx), x => Parallel.ForEach(Enumerable.Range(y1, sy), y =>
{
    // if the height can be determined at a given 
    // x and y, then set the height at the correct 
    // index in the flat array of values.
    float height;
    data[sx * x + y] = Client.Network.CurrentSim.TerrainHeightAtPoint(x, y, out height)
        ? height
        : -1;
}));

One of the nice remarks about this algorithm is that it does not use any form of locking - every single task works on one single index such that no locking is needed for insertion. Even if we were to use locks, we would have a problem, because we could not tell in what order the elements would be inserted. Using the formula however, we can make sure that each task can run independently of other tasks.

Compressing a HTTP Web Request

Using gzip compression to compress a request:

using System.IO.Compression;
 
// ...
 
using (Stream requestStream = request.GetRequestStream())
{
    using(var zipStream = new GZipStream(requestStream, CompressionMode.Compress))
    {
        zipStream.Write(byteData, 0, byteData.Length);         
    }
}

which is different from requesting a compressed response, which is more common.

Permute an Array

wasReversePermuteArrayElements and wasForwardPermuteArrayElements permute an array by shifting their elements either in reverse or forward directions.

Reverse

Suppose you have an array with the elements:

a b c

then a call such as wasReversePermuteArrayElements(array, 1) will return the elements:

b c a
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Permutes an array in reverse a given number of times.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="input">the array</param>
/// <param name="times">the number of times to permute</param>
/// <returns>the array with the elements permuted</returns>
private static T[] wasReversePermuteArrayElements<T>(T[] input, int times)
{
    if (times.Equals(0)) return input;
    T[] slice = new T[input.Length];
    Array.Copy(input, 1, slice, 0, input.Length - 1);
    Array.Copy(input, 0, slice, input.Length - 1, 1);
    return wasReversePermuteAttayElements(slice, --times);
}

Forward

Suppose you have an array with the elements:

a b c

then a call such as wasForwardPermuteArrayElements(array, 1) will return the elements:

c a b
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Permutes an array forward a given number of times.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="input">the array</param>
/// <param name="times">the number of times to permute</param>
/// <returns>the array with the elements permuted</returns>
private static T[] wasForwardPermuteArrayElements<T>(T[] input, int times)
{
    if (times.Equals(0)) return input;
    T[] slice = new T[input.Length];
    Array.Copy(input, input.Length - 1, slice, 0, 1);
    Array.Copy(input, 0, slice, 1, input.Length - 1);
    return wasForwardPermuteArrayElements(slice, --times);
}

Swap Array Elements

The wasArraySwap swaps two elements in an array.

///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Swaps two elements in an array.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="input">the array</param>
/// <param name="p">first element</param>
/// <param name="q">last element</param>
/// <returns>the array with the elements swapped</returns>
private static T[] wasArraySwap<T>(T[] input, T p, T q)
{
    T[] swap = input.Clone() as T[];
    int i = Array.IndexOf(input, p);
    int j = Array.IndexOf(input, q);
    Array.Copy(input, i, swap, j, 1);
    Array.Copy(input, j, swap, i, 1);
    return swap;
}

Concatenate Array Elements

Given several arrays as input, the wasConcatenateArrays function returns a flat array with all the elements from the arrays concatenated.

///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Concatenate multiple arrays.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="arrays">multiple arrays</param>
/// <returns>a flat array with all arrays concatenated</returns>
public static T[] wasConcatenateArrays<T>(params T[][] arrays)
{
    int resultLength = 0;
    foreach (T[] o in arrays)
    {
        resultLength += o.Length;
    }
    T[] result = new T[resultLength];
    int offset = 0;
    for (int x = 0; x < arrays.Length; x++)
    {
        arrays[x].CopyTo(result, offset);
        offset += arrays[x].Length;
    }
    return result;
}

Delete Sub-Array

Given an array, the wasDeleteSubArray function deletes returns all the elements of the array that are not between the start and stop indices. Additionally, the wasDeleteSubArray function allows -1 to be specified as the stop index meaning the end of the array.

///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Delete a sub-array and return the result.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="data">the array</param>
/// <param name="start">the start index</param>
/// <param name="stop">the stop index (-1 denotes the end)</param>
/// <returns>the array without elements between start and stop</returns>
public static T[] wasDeleteSubArray<T>(T[] data, int start, int stop)
{
    if (stop.Equals(-1))
        stop = data.Length - 1;
    T[] result = new T[data.Length - (stop - start) - 1];
    Array.Copy(data, 0, result, 0, start);
    Array.Copy(data, stop + 1, result, start, data.Length - stop - 1);
    return result;
}

Get Sub-Array

The wasGetSubArray function takes as input an array and returns all the elements between the start and stop indices (inclusive). Additionally, the function supports passing -1 to the stop index meaning the end of the array.

///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Gets a sub-array from an array.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="data">the array</param>
/// <param name="start">the start index</param>
/// <param name="stop">the stop index (-1 denotes the end)</param>
/// <returns>the array slice between start and stop</returns>
public static T[] wasGetSubArray<T>(T[] data, int start, int stop)
{
    if (stop.Equals(-1))
        stop = data.Length - 1;
    T[] result = new T[stop - start + 1];
    Array.Copy(data, start, result, 0, stop - start + 1);
    return result;
}

Cryptographic Functions

A list of cryptographic functions created by Wizardry and Steamworks:

that will help you encrypt and decrypt messages.

Sequence Contains All Elements of Sequence

Suppose we have two sets:

var subset = new [] { 2 3 1 };
var set = new [] { 2 3 8 4 2 };

and we want to determine if set contains all the elements of subset.

In that case we can do:

bool contained = !subset.Except(set).Any();

after which contained will be true if subset is contained in set.

Unix Alarm

The alarm function in Unix program is usually used to raise an event after a certain time and, additionally, by calling the alarm function again, to reschedule the delivery of that event. In C#, .NET does not have a built-in alarm-like class so the following is a quick implementation using System.Timers.Timer:

///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>An alarm class similar to the UNIX alarm</summary>
public class wasAlarm
{
    private Timer alarm;
 
    public wasAlarm()
    {
        Signal = new ManualResetEvent(false);
    }
 
    public ManualResetEvent Signal { get; set; }
 
    public void Alarm(int deadline)
    {
        if (alarm == null)
        {
            alarm = new Timer(deadline);
            alarm.Elapsed += (o, p) =>
            {
                Signal.Set();
                alarm.Dispose();
            };
            alarm.Start();
            return;
        }
        alarm.Interval = deadline;
    }
}

Suppose that you have an event, that you do not know how many times it will be called before not being called again, in that case you would first create the alarm:

wasAlarm trigger = new wasAlarm();

then, in the event handler, you would reschedule the alarm, with:

trigger.Alarm(1000);

Finally, you would wait on the alarm to trigger using, for example, WaitOne:

trigger.Signal.WaitOne(timeout, false);

This class is used throughout Corrade.

Adaptive Alarm

alarm() is usually used under UNIX-like systems to deliver a signal once a certain time has elapsed. It is useful for asynchronous code where some tasks can be performed before the alarm is finally triggered. Commonly, the alarm is set at some point and then updated later in order to reschedule the event at an earlier time.

One of the short-comings of the UNIX alarm is that it does not explicitly consider past elapsed times. For example, suppose that you set and reset an alarm as some events happen. You would only reschedule the alarm with a fixed time, every time, regardless whether the previous event has been delivered much earlier than your alarm schedule.

wasAdaptiveAlarm uses Pythagorean means (although this can be extended) to consider the reschedule interval as well as all the past elapsed times. It performs the mean between the current scheduling request and all the previous recorded elapsed times.

///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3      //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     An alarm class similar to the UNIX alarm with the added benefit
///     of a decaying timer that tracks the time between rescheduling.
/// </summary>
/// <remarks>
///     (C) Wizardry and Steamworks 2013 - License: GNU GPLv3
/// </remarks>
public class wasAdaptiveAlarm
{
    [Flags]
    public enum DECAY_TYPE
    {
        NONE = 0,
        ARITHMETIC = 1,
        GEOMETRIC = 2,
        HARMONIC = 4
    }
 
    private readonly DECAY_TYPE decay = DECAY_TYPE.NONE;
    private readonly Stopwatch elapsed = new Stopwatch();
    private readonly HashSet<double> times = new HashSet<double>();
    private System.Timers.Timer alarm;
 
    /// <summary>
    ///     The default constructor using no decay.
    /// </summary>
    public wasAdaptiveAlarm()
    {
        Signal = new ManualResetEvent(false);
    }
 
    /// <summary>
    ///     The constructor for the wasAdaptiveAlarm class taking as parameter a decay type.
    /// </summary>
    /// <param name="decay">the type of decay: arithmetic, geometric, harmonic, heronian or quadratic</param>
    public wasAdaptiveAlarm(DECAY_TYPE decay)
    {
        Signal = new ManualResetEvent(false);
        this.decay = decay;
    }
 
    public ManualResetEvent Signal { get; set; }
 
    public void Alarm(double deadline)
    {
        if (alarm == null)
        {
            alarm = new System.Timers.Timer(deadline);
            alarm.Elapsed += (o, p) =>
            {
                Signal.Set();
                times.Clear();
                alarm.Dispose();
            };
            elapsed.Start();
            alarm.Start();
            return;
        }
        elapsed.Stop();
        times.Add(elapsed.ElapsedMilliseconds);
        elapsed.Reset();
        elapsed.Start();
        switch (decay)
        {
            case DECAY_TYPE.ARITHMETIC:
                alarm.Interval = (deadline + times.Aggregate((a, b) => b + a)) / (1f + times.Count);
                break;
            case DECAY_TYPE.GEOMETRIC:
                alarm.Interval = Math.Pow(deadline * times.Aggregate((a, b) => b * a), 1f / (1f + times.Count));
                break;
            case DECAY_TYPE.HARMONIC:
                alarm.Interval = (1f + times.Count) / (1f / deadline + times.Aggregate((a, b) => 1f / b + 1f / a));
                break;
            default:
                alarm.Interval = deadline;
                break;
        }
    }
}

As a practical example, wasAdaptiveAlarm has been incorporated and used throughout Corrade in order to receive an unknown number events as fast as possible without raising the signal too soon and thereby losing events.

Combine Multiple Paths

In .NET, Path.Combine takes two parameters such that you cannot provide several path elements in order to construct a path. Instead the wasPathCombine takes a variable number of parameters and combines them as a path:

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Combine multiple paths.
/// </summary>
/// <param name="paths">an array of paths</param>
/// <returns>a combined path</returns>
private static string wasPathCombine(params string[] paths)
{
    if (paths.Length.Equals(0)) return string.Empty;
    return paths.Length < 2
        ? paths[0] : Path.Combine(Path.Combine(paths[0], paths[1]), wasPathCombine(paths.Skip(2).ToArray()));
}

Convert a Decimal Number to a Given Base

Inspired from Pavel Vladov's converter, wasIntegerToBase is able to convert a decimal number to any base (up to base 68) by making use of all the printable characters in the ASCII character set.

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Converts the given decimal value to the numeral system with the
///     specified base radix in the range [2, 68].
/// </summary>
/// <param name="value">The value to convert.</param>
/// <param name="radix">The radix of the destination numeral system (in the range [2, 68]).</param>
/// <returns>a string containing the value in base radix</returns>
public static string wasIntegerToBase(long value, int radix) {
    const string alphabet = @ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ !#$%&'()*+,-./:;<=>?@[\]^_`(|)~";
 
    if (radix < 2 || radix > alphabet.Length)
        throw new ArgumentException("The radix must be >= 2 and <= " + alphabet.Length.ToString(CultureInfo.InvariantCulture) + ".");
 
    if (value == 0) return "0";
 
    char[] final = new char[64];
 
    long n = Math.Abs(value);
    int i = 64;
    do {
        int remainder = (int)(n % radix);
        final[--i] = alphabet[remainder];
        n = n / radix;
    } while (n != 0);
 
    StringBuilder sb = new StringBuilder();
    if (value < 0) sb.Append("-");
    sb.Append(final, i, 64 - i);
 
    return sb.ToString();
}

Iterative Fibonacci Implementation

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
using System;
 
namespace Fibonacci {
    public class Fibonacci {
        public static void Main(string[] args) {
            int f0 = 0;
            int f1 = 1;
 
            int i = 0;
            while(i < 10) {
                int s = f0;
                f0 = f1;
                f1 = s + f1;
 
                Console.WriteLine(s);
 
                i = i + 1;
            }
        }
    }
}

Binary Search

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
public static int BinarySearch(int[] a, int i, int min, int max) {
    if(max < min) return -1;
    int mid = (min+max)/2;
    if(a[mid] > i)
        return BinarySearch(a, i, min, mid - 1);
    if(a[mid] < i)
        return BinarySearch(a, i, mid + 1, max);
    return i;
}

Quicksort

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
public static List<int> Quicksort(List<int> l) {
    if (l.Count <= 1) {
        return l;
    }
 
    int pivot = l[l.Count / 2];
 
    List<int> less = new List<int>();
    List<int> more = new List<int>();
 
    foreach (int i in l) {
        if (i < pivot)
        {
            less.Add(i);
        }
        if (i > pivot)
        {
            more.Add(i);
        }
    }
 
    List<int> result = new List<int>();
    result.AddRange(Quicksort(less));
    result.Add(pivot);
    result.AddRange(Quicksort(more));
 
    return result;
}

Get Field or Property from Nested Class by Fully Qualified Name

The GetFP extension will return either a value of a field in a class, the value of a property or null in case no field or properties matched.

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
/// <summary>
///     Get field or property from a class by supplying a path.
/// </summary>
/// <typeparam name="T">the type of the object</typeparam>
/// <param name="o">the object</param>
/// <param name="path">the fully qualified path to the field of property</param>
/// <param name="flags">the binding flags to use</param>
/// <returns>
///     the last object in the fully qualified path or null in case the field or property could not be found
/// </returns>
public static object GetFP<T>(this T o, string path,
    BindingFlags flags = BindingFlags.Instance | BindingFlags.Public) where T : class
{
    if (string.IsNullOrEmpty(path)) return null;
    if (o == null) return null;
 
    var components = path.Split('.');
 
    var memberTypes = o.GetType().GetMember(components[0], flags);
 
    if (memberTypes.Length != 1) return null;
 
    switch (memberTypes[0].MemberType)
    {
        case MemberTypes.Field:
            return components.Length > 1
                ? GetFP(o.GetType().GetField(components[0]).GetValue(o),
                    components.Skip(1).Aggregate((a, i) => a + @"." + i), flags)
                : o.GetType().GetField(path).GetValue(o);
        case MemberTypes.Property:
            return components.Length > 1
                ? GetFP(o.GetType().GetProperty(components[0], flags).GetValue(o),
                    components.Skip(1).Aggregate((a, i) => a + @"." + i), flags)
                : o.GetType().GetProperty(path).GetValue(o);
    }
 
    return null;
}

The search is performed by fully qualified name. For instance:

var o = object.GetFP("Class.Member.Class.Field");

Merge Sort

Recursive

Recursively and using generics.

using System;
 
namespace Sorts.MergeSort.Recursive
{
    public class MergeSort
    {
        private static int[] List { get; set; }
 
        public MergeSort(int[] list)
        {
            List = list;
        }
 
        public int[] Sort()
        {
            return Partition(List);
        }
 
        private static T[] Partition<T>(T[] list) where T : IComparable
        {
            if (list.Length <= 1)
            {
                return list;
            }
 
            var pivot = list.Length / 2;
 
            T[] l = new T[pivot];
 
            Array.Copy(list, 0, l, 0, pivot);
 
            T[] r = new T[list.Length - pivot];
 
            Array.Copy(list, pivot, r, 0, list.Length - pivot);
 
            return Merge(Partition(l), Partition(r));
        }
 
        private static T[] Concatenate<T>(T[] a, T[] b) where T : IComparable
        {
            T[] rest = new T[a.Length + b.Length];
 
            Array.Copy(a, 0, rest, 0, a.Length);
            Array.Copy(b, 0, rest, a.Length, b.Length);
 
            return rest;
        }
 
        private static T[] Concatenate<T>(T a, T[] l) where T : IComparable
        {
            T[] result = new T[l.Length + 1];
            result[0] = a;
 
            Array.Copy(l, 0, result, 1, l.Length);
 
            return result;
        }
 
        private static T Car<T>(T[] l) where T : IComparable
        {
            return l[0];
        }
 
        private static T[] Cdr<T>(T[] l) where T : IComparable
        {
            T[] cdr = new T[l.Length - 1];
 
            Array.Copy(l, 1, cdr, 0, l.Length - 1);
 
            return cdr;
        }
 
        private static T[] Merge<T>(T[] l, T[] r) where T : IComparable
        {
            if (l.Length == 0 || r.Length == 0)
            {
                return Concatenate(l, r);
            }
 
            if (l[0].CompareTo(r[0]) > 0)
            {
                return Concatenate(Car(r), Merge(l, Cdr(r)));
            }
 
            return Concatenate(Car(l), Merge(Cdr(l), r));
        }
    }
}

May have stack issues so should be called by increasing the stack size:

            var t = new Thread(() =>
                {
                    list = new MergeSort.Recursive.MergeSort(list).Sort();
 
                }, 1024 * 1024 * 50);
 
            t.Start();

Iterative

using System;
 
namespace Sorts.MergeSort.Iterative
{
    public class MergeSort
    {
        private static int[] List { get; set; }
 
        public MergeSort(int[] list)
        {
            List = list;
        }
 
        public int[] Sort()
        {
            return Sort(List);
        }
 
        private static T Min<T>(T x, T y) where T : IComparable
        {
            return x.CompareTo(y) < 0 ? x : y;
        }
 
        private static T[] Sort<T>(T[] a) where T : IComparable
        {
            T[] b = new T[a.Length];
 
            for (int size = 1; size < a.Length; size *= 2)
            {
                for (int left = 0; left + size < a.Length; left += size * 2)
                {
                    int l = left + size;
                    int r = Min(l + size, a.Length);
 
                    var k = left;
                    var i = left;
                    var j = l;
                    while (i < l && j < r)
                    {
                        if (a[i].CompareTo(a[j]) < 0)
                        {
                            b[k] = a[i];
                            ++i;
                        }
                        else
                        {
                            b[k] = a[j];
                            ++j;
                        }
 
                        ++k;
                    }
                    while (i < l)
                    {
                        b[k] = a[i];
                        ++i;
                        ++k;
                    }
 
                    while (j < r)
                    {
                        b[k] = a[j];
                        ++j;
                        ++k;
                    }
 
                    for (k = left; k < r; ++k)
                    {
                        a[k] = b[k];
                    }
                }
            }
 
            return a;
        }
    }
}

fuss/csharp.txt ยท Last modified: 2019/08/22 08:32 by office

Access website using Tor Access website using i2p


For the copyright, license, warranty and privacy terms for the usage of this website please see the license, privacy and plagiarism pages.