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 }