1 /** 2 Some additional alogorithm functions. 3 4 Copyright: © 2019 Arne Ludwig <arne.ludwig@posteo.de> 5 License: Subject to the terms of the MIT license, as written in the 6 included LICENSE file. 7 Authors: Arne Ludwig <arne.ludwig@posteo.de> 8 */ 9 module dalicious.algorithm.comparison; 10 11 import std.algorithm : 12 copy, 13 countUntil, 14 min, 15 OpenRight, 16 uniq; 17 import std.conv : to; 18 import std.functional : binaryFun, unaryFun; 19 import std.traits : isDynamicArray; 20 import std.typecons : Yes; 21 import std.range.primitives; 22 23 24 /** 25 Order `a` and `b` lexicographically by applying each `fun` to them. For 26 unary functions compares `fun(a) < fun(b)`. 27 */ 28 bool orderLexicographically(T, fun...)(T a, T b) 29 { 30 static foreach (i, getFieldValue; fun) 31 { 32 { 33 auto aValue = unaryFun!getFieldValue(a); 34 auto bValue = unaryFun!getFieldValue(b); 35 36 if (aValue != bValue) 37 { 38 return aValue < bValue; 39 } 40 } 41 } 42 43 return false; 44 } 45 46 47 /** 48 Compare `a` and `b` lexicographically by applying each `fun` to them. For 49 unary functions compares `fun(a) < fun(b)`. 50 */ 51 int cmpLexicographically(T, fun...)(T a, T b) 52 { 53 static foreach (i, alias getFieldValue; fun) 54 { 55 { 56 auto aValue = unaryFun!getFieldValue(a); 57 auto bValue = unaryFun!getFieldValue(b); 58 59 if (aValue < bValue) 60 { 61 return -1; 62 } 63 else if (aValue > bValue) 64 { 65 return 1; 66 } 67 } 68 } 69 70 return 0; 71 } 72 73 74 /// Returns one of a collection of expressions based on the value of the 75 /// switch expression. 76 template staticPredSwitch(T...) 77 { 78 auto staticPredSwitch(E)(E switchExpression) pure nothrow 79 { 80 static assert (T.length > 0, "missing choices"); 81 static assert (T.length % 2 == 1, "missing default clause"); 82 83 static foreach (i; 0 .. T.length - 1) 84 { 85 static if (i % 2 == 0) 86 { 87 if (switchExpression == T[i]) 88 return T[i + 1]; 89 } 90 } 91 92 return T[$ - 1]; 93 } 94 } 95 96 /// 97 unittest 98 { 99 alias numberName = staticPredSwitch!( 100 1, "one", 101 2, "two", 102 3, "three", 103 "many", 104 ); 105 106 static assert("one" == numberName(1)); 107 static assert("two" == numberName(2)); 108 static assert("three" == numberName(3)); 109 static assert("many" == numberName(4)); 110 }