my advent of code solutions
at main 176 lines 6.1 kB view raw
1using System.Numerics; 2 3namespace Solutions; 4 5public static class Extensions 6{ 7 /// <summary> 8 /// <c>string.Join</c> Wrapper 9 /// </summary> 10 /// <param name="enumerable"></param> 11 /// <param name="delimiter"></param> 12 /// <typeparam name="T"></typeparam> 13 /// <returns></returns> 14 public static string Join<T>(this IEnumerable<T> enumerable, string delimiter = "") => 15 string.Join(delimiter, enumerable); 16 17 /// <summary> 18 /// Loop over a sequence with an optional number of times. 19 /// </summary> 20 /// <param name="sequence"></param> 21 /// <param name="count"></param> 22 /// <typeparam name="T"></typeparam> 23 /// <returns></returns> 24 public static IEnumerable<T> Repeat<T>(this IEnumerable<T> sequence, int? count = null) 25 { 26 while (count == null || count-- > 0) 27 // ReSharper disable once PossibleMultipleEnumeration 28 foreach (var item in sequence) 29 yield return item; 30 } 31 32 /// <summary> 33 /// Increased accuracy for stopwatch based on frequency. 34 /// </summary> 35 /// <param name="stopwatch"></param> 36 /// <returns></returns> 37 public static double ScaleMilliseconds(this Stopwatch stopwatch) => 38 1_000 * stopwatch.ElapsedTicks / (double)Stopwatch.Frequency; 39 40 /// <summary> 41 /// Given an array, it returns a rotated copy. 42 /// </summary> 43 /// <param name="array">The two-dimensional jagged array to rotate.</param> 44 public static T[][] Rotate<T>(this T[][] array) 45 { 46 var result = new T[array[0].Length][]; 47 for (var i = 0; i < result.Length; i++) 48 result[i] = new T[array.Length]; 49 50 for (var i = 0; i < array.Length; i++) 51 for (var j = 0; j < array[i].Length; j++) 52 result[i][j] = array[array.Length - j - 1][i]; 53 54 return result; 55 } 56 57 /// <summary> 58 /// Given a jagged array, it returns a diagonally flipped copy. 59 /// </summary> 60 /// <param name="array">The two-dimensional jagged array to flip.</param> 61 public static T[][] FlipHorizontally<T>(this IEnumerable<T[]> array) => 62 array.Select(x => x.Reverse().ToArray()).ToArray(); 63 64 /// <summary> 65 /// Does the <see cref="Range"/> include a given int? 66 /// </summary> 67 /// <param name="range"></param> 68 /// <param name="i"></param> 69 /// <returns></returns> 70 public static bool Contains(this Range range, int i) => 71 i >= range.Start.Value && i <= range.End.Value; 72 73 /// <summary> 74 /// Does <paramref name="r1"/> contain the entire range of <paramref name="r2"/>? 75 /// </summary> 76 /// <param name="r1"></param> 77 /// <param name="r2"></param> 78 /// <returns></returns> 79 public static bool Contains(this Range r1, Range r2) => 80 r1.Start.Value <= r2.Start.Value && r1.End.Value >= r2.End.Value; 81 82 /// <summary> 83 /// Do <paramref name="r1"/> and <paramref name="r2"/> overlap? 84 /// </summary> 85 /// <param name="r1"></param> 86 /// <param name="r2"></param> 87 /// <returns></returns> 88 public static bool Overlaps(this Range r1, Range r2) => 89 r1.Start.Value <= r2.End.Value && r1.End.Value >= r2.Start.Value && 90 r2.Start.Value <= r1.End.Value && r2.End.Value >= r1.Start.Value; 91 92 /// <summary> 93 /// Creates a new BigInteger from a binary (Base2) string 94 /// Based on <a href="https://gist.github.com/mjs3339/73042bc0e717f98796ee9fa131e458d4">mjs3339's gist</a> 95 /// </summary> 96 public static BigInteger BigIntegerFromBinaryString(this string binaryValue) 97 { 98 BigInteger res = 0; 99 if (binaryValue.Count(b => b == '1') + binaryValue.Count(b => b == '0') != binaryValue.Length) return res; 100 foreach (var c in binaryValue) 101 { 102 res <<= 1; 103 res += c == '1' ? 1 : 0; 104 } 105 106 return res; 107 } 108 109 /// <summary> 110 /// Generate all permutations of an Enumerable. 111 /// </summary> 112 /// <param name="list"></param> 113 /// <typeparam name="T"></typeparam> 114 /// <returns></returns> 115 public static IEnumerable<IEnumerable<T>> Permute<T>(this IEnumerable<T> list) 116 { 117 var array = list as T[] ?? list.ToArray(); 118 return array.Length == 1 119 ? [array] 120 : array.SelectMany(t => Permute(array.Where(x => !x!.Equals(t))), (v, p) => p.Prepend(v)); 121 } 122 123 /// <summary> 124 /// Raise an integer to a given <paramref name="power"/>. 125 /// </summary> 126 /// <param name="i"></param> 127 /// <param name="power"></param> 128 /// <returns></returns> 129 public static int Pow(this int i, int power) 130 { 131 var pow = (uint)power; 132 var ret = 1; 133 while (pow != 0) 134 { 135 if ((pow & 1) == 1) ret *= i; 136 i *= i; 137 pow >>= 1; 138 } 139 140 return ret; 141 } 142 143 /// <summary> 144 /// Attach the index of each element. 145 /// </summary> 146 /// <param name="source"></param> 147 /// <typeparam name="T"></typeparam> 148 /// <returns></returns> 149 public static IEnumerable<KeyValuePair<int, T>> Indexed<T>(this IEnumerable<T> source) => 150 source.Select((t, i) => new KeyValuePair<int, T>(i, t)); 151 152 /// <summary> 153 /// Wrapper for KeyValuePair to enable passing delegates. 154 /// </summary> 155 /// <param name="source"></param> 156 /// <param name="func"></param> 157 /// <typeparam name="TKey"></typeparam> 158 /// <typeparam name="TValue"></typeparam> 159 /// <returns></returns> 160 public static IEnumerable<KeyValuePair<TKey, TValue>> WhereValue<TKey, TValue>( 161 this IEnumerable<KeyValuePair<TKey, TValue>> source, Func<TValue, bool> func) => 162 source.Where(pair => func(pair.Value)); 163 164 /// <summary> 165 /// Compute the Hamming distance between two strings. 166 /// </summary> 167 /// <param name="s1"></param> 168 /// <param name="other"></param> 169 /// <returns></returns> 170 /// <exception cref="Exception"></exception> 171 public static int HammingDistance(this string s1, string other) 172 { 173 if (s1.Length != other.Length) throw new("Strings must be equal length."); 174 return s1.Zip(other).Count(s => s.First != s.Second); 175 } 176}