Jul 19, 2019

Intervals 2.0

Updated intervals combining (splicing/clipping) method with the new features of C# 7.0. Intervals passed can overlap.
Two weird classes added for convenience. Pair<T> is handy when you have to switch often between 2 objects. IntBool is a value type which can act as both int and bool.

    public static class CombineIntervals
    {
        public static IEnumerable<(T, T)> Combine<T>(this IEnumerable<(T, T)> inc, IEnumerable<(T, T)> exc = null) where T : IComparable
        {
            if (exc == null) exc = Enumerable.Empty<(T, T)>();
            IEnumerable<(T val, bool br, bool ex) > GetBorders(IEnumerable<(T left, T right)> ranges, bool ex)
            {
                foreach (var (left, right) in ranges)
                {
                    yield return (left, true, ex);
                    yield return (right, false, ex);
                }
            }
            var borders = GetBorders(inc, false).Union(GetBorders(exc, true)).OrderBy(x => x.val).ToArray();
            T start = borders[0].val;
            var state = new Pair<IntBool>();
            foreach (var (val, br, ex) in borders)
            {
                if (state[ex].Xor(br))
                {
                    if (br == state[!ex])
                        yield return (start, val);
                    else start = val;
                }
                state[ex] += br ? 1 : -1;
            }
        }
    }
    public struct Pair<T>
    {
        T a; T b;
        public T this[IntBool i]
        {
            get => i ? b : a;
            set
            {
                if (i) b = value;
                else a = value;
            }
        }
        public override string ToString()
        {
            return $"{a}, {b}";
        }
        internal void Deconstruct(out T x, out T y)
        {
            x = a;
            y = b;
        }
    }
    public struct IntBool
    {
        private int val;
        public static implicit operator IntBool (int x) => new IntBool() { val = x };
        public static implicit operator int(IntBool x) => x.val;
        public static implicit operator IntBool(bool x) => new IntBool() { val = x ? 1 : 0 };
        public static implicit operator bool(IntBool x) => x.val > 0;
        public override string ToString() => val.ToString();
        public bool And(bool x) => val == 1 && x;
        public bool Xor(bool x) => val == 1 && !x || val == 0 && x;
    }

May 18, 2016

Get a site's Favicon uri

Using HtmlAgilityPack NuGet package (Ms-Pl license):

    public async static Task<Uri> GetFaviconUri(Uri page)
    {
        var doc = await new HtmlAgilityPack.HtmlWeb().LoadFromWebAsync(page.AbsoluteUri);
        var href = doc.DocumentNode.Descendants("link")
            .Where(n => n.Attributes.Any(a => a.Name == "rel" &&
                a.Value == "icon" || a.Value == "shortcut icon"))
            .FirstOrDefault()?.GetAttributeValue("href", null);
        return href == null ? null : new Uri(page, href);
    }

Jan 31, 2016

Splicing, combining, subtracting intervals of IComparable

Idea is simple, you pass two collections of intervals (Tuple<T, T>), one for included values, another for excluded. Then overlapping intervals of the same kind are combined, and excluding intervals are subtracted from including intervals. As a result you get a new set of intervals.

As T you can use any IComparable, like int, DateTime, double or your custom type.


Code:
using System;
using System.Collections.Generic;
using System.Linq;

namespace Test
{
    /*

        Subtracting intervals of different kind:

    include | *****      ****     *****  ***********  ***     |
    exclude |    ******            **          ************** |
    borders | i  e    e  i  i     iee i  i     e   i  i i   e |
    result  | ***        ****     *  **  ******               |  



        Combining overlapping intervals of the same kind:

    first  | l....r            |
    second |    l............r |
    third  |         l...r     |
    all    | l..l.r..l...r...r |
    border | 1..2.1..2...1...0 |

        (1..0) constitutes a combined interval

    */

    public class Interval
    {
        public enum Border { Left, Right };
        public enum IntervalType { Including, Excluding };

        //border point of an interval
        struct Point<T>
        {
            public T Val;
            public int Brdr;
            public int Intr;
            public Point(T value, Border border, IntervalType interval)
            {
                Val = value;
                Brdr = (border == Border.Left) ? 1 : -1;
                Intr = (int)interval;
            }
            public override string ToString() =>
                (Brdr == 1 ? "L" : "R") + (Intr == 0 ? "+ " : "- ") + Val;
        }

        private static IEnumerable<Point<T>> GetBorders<T>
            (IEnumerable<Tuple<T, T>> src,
            IntervalType intr) =>
                src.Select(p => new[] { p.Item1, p.Item2 }).SelectMany(p => p).
                Select((v, idx) => new Point<T>(v, (Border)(idx % 2), intr));

        public static IEnumerable<Tuple<T, T>> Combine<T>(
            IEnumerable<Tuple<T, T>> Include, IEnumerable<Tuple<T, T>> Exclude)
            where T : IComparable
        {
            var INs = GetBorders(Include, IntervalType.Including);
            var EXs = GetBorders(Exclude, IntervalType.Excluding);

            var intrs = new int[2]; //current interval border control In[0], Ex[1]
            T start = default(T);   //left border of a new resulting interval
            //put all points in a line and loop:
            foreach (var p in INs.Union(EXs).OrderBy(x => x.Val))
            {
                //check for start (close) of a new (cur) interval:
                var change = (intrs[p.Intr] == 0) ^ (intrs[p.Intr] + p.Brdr == 0);
                intrs[p.Intr] += p.Brdr;
                if (!change) continue;

                var In = p.Intr == 0 && intrs[1] == 0;  //w no cur Ex
                var Ex = p.Intr == 1 && intrs[0] > 0;   //breaks cur In
                var Open = intrs[p.Intr] > 0;
                var Close = !Open;

                if (In && Open || Ex && Close)
                {
                    start = p.Val;
                }
                else if (In && Close || Ex && Open)
                {
                    yield return new Tuple<T, T>(start, p.Val);
                }
            }
        }
    }
}


Example of usage:



Code:
class Program
{
    static void Main(string[] args)
    {
        var include = new[] {
            new Tuple<int, int>(10, 100),
            new Tuple<int, int>(200, 300),
            new Tuple<int, int>(400, 500),
            new Tuple<int, int>(420, 480),
        };
        var exclude = new[] {
            new Tuple<int, int>(95, 200),
            new Tuple<int, int>(410, 420),
        };

        foreach (var i in Interval.Combine(include, exclude))
            Console.WriteLine(i.Item1 + "-" + i.Item2);

        Console.ReadLine();
    }
}

The output will be
10-95
205-300
400-410
420-500

NB! border values of excluding intervals are not excluded. E.g. when you subtract (5..10) from [1..7] you end up with [1..5]. To exclude 5, widen the excluding interval like (5..10) => (4..11).

Alias ugly generic type names

Though aliasing (with using keyword) generic types is not possible as of C# 6.0, sometimes you can go with inheritance:


public class MyList<T1, T2> : 
    List<Tuple<IEnumerable<HashSet<T1>>, IComparable<T2>>>
{ }

public void Meth()
{
    var x = new MyList<int, bool>();
}

Jan 30, 2016

Circular Linked List

Code:
public static class CircularLinkedList
{
    public static LinkedListNode<T> NextOrFirst<T>(this LinkedListNode<T> current)
    {
        return current.Next ?? current.List.First;
    }

    public static LinkedListNode<T> PreviousOrLast<T>(this LinkedListNode<T> current)
    {
        return current.Previous ?? current.List.Last;
    }

    public static LinkedListNode<T> Rewind<T>(this LinkedListNode<T> current, int num)
    {
        while (num != 0)
        {
            current = num > 0 ? current.NextOrFirst() : current.PreviousOrLast();
            num -= Math.Sign(num);
        }
        return current;
    }
}

UWP: where are my solution's Content files?

Package.Current.InstalledLocation

Sep 11, 2015

Wrap an object into an IEnumerable of single item

Code:
public static IEnumerable<T> Yield<T>(this T item)
{
    yield return item;
}