1 module nxt.ixes; 2 3 import std.meta : allSatisfy; 4 import std.range.primitives : isInputRange, isBidirectionalRange; 5 6 /** Get length of Common Prefix of $(D a) and $(D b). 7 See_Also: http://forum.dlang.org/thread/bmbhovkgqomaidnyakvy@forum.dlang.org#post-bmbhovkgqomaidnyakvy:40forum.dlang.org 8 */ 9 auto commonPrefixLength(alias pred = "a == b", Rs...)(Rs rs) 10 if (rs.length >= 2 && 11 allSatisfy!(isInputRange, Rs)) 12 { 13 import std.algorithm.searching : commonPrefix; 14 static if (rs.length == 2) 15 return commonPrefix!pred(rs[0], rs[1]).length; 16 else 17 { 18 static assert("TODO"); 19 import std.range : zip, StoppingPolicy; 20 import std.algorithm : countUntil, count; 21 const hit = zip(a, b).countUntil!(ab => ab[0] != ab[1]); // TODO: if countUntil return zip(a, b).count upon failre... 22 return hit == -1 ? zip(a, b).count!pred : hit; // TODO: ..then this would not have been needed 23 } 24 } 25 26 @safe pure unittest 27 { 28 assert(commonPrefixLength(`åäö_`, 29 `åäö-`) == 6); 30 } 31 32 @safe pure nothrow unittest 33 { 34 const x = [1, 2, 3, 10], y = [1, 2, 4, 10]; 35 void f() @safe pure nothrow @nogc 36 { 37 assert(commonPrefixLength(x, y) == 2); 38 } 39 f(); 40 assert(commonPrefixLength([1, 2, 3, 10], 41 [1, 2, 3]) == 3); 42 assert(commonPrefixLength([1, 2, 3, 0, 4], 43 [1, 2, 3, 9, 4]) == 3); 44 } 45 46 /** Get length of Suffix of $(D a) and $(D b). 47 See_Also: http://forum.dlang.org/thread/bmbhovkgqomaidnyakvy@forum.dlang.org#post-bmbhovkgqomaidnyakvy:40forum.dlang.org 48 */ 49 auto commonSuffixLength(Rs...)(Rs rs) 50 if (rs.length == 2 && 51 allSatisfy!(isBidirectionalRange, Rs)) 52 { 53 import std.traits : isNarrowString; 54 import std.range: retro; 55 static if (isNarrowString!(typeof(rs[0])) && 56 isNarrowString!(typeof(rs[1]))) 57 { 58 import std.string: representation; 59 return commonPrefixLength(rs[0].representation.retro, 60 rs[1].representation.retro); 61 } 62 else 63 return commonPrefixLength(rs[0].retro, 64 rs[1].retro); 65 } 66 67 @safe pure unittest 68 { 69 const x = [1, 2, 3, 10, 11, 12]; 70 const y = [1, 2, 4, 10, 11, 12]; 71 void f() @safe pure nothrow @nogc 72 { 73 assert(commonPrefixLength(x, y) == 2); 74 } 75 f(); 76 assert(commonSuffixLength(x, y) == 3); 77 assert(commonSuffixLength([10, 1, 2, 3], 78 [1, 2, 3]) == 3); 79 } 80 81 @safe pure unittest 82 { 83 assert(commonSuffixLength(`_åäö`, 84 `-åäö`) == 6); 85 } 86 87 /** Get Count of Prefix of $(D a) and $(D b). 88 See_Also: http://forum.dlang.org/thread/bmbhovkgqomaidnyakvy@forum.dlang.org#post-bmbhovkgqomaidnyakvy:40forum.dlang.org 89 */ 90 auto commonPrefixCount(alias pred = "a == b", Rs...)(Rs rs) 91 if (rs.length == 2 && 92 allSatisfy!(isInputRange, Rs)) 93 { 94 import std.algorithm.searching : commonPrefix, count; 95 import std.traits : isNarrowString; 96 static if (isNarrowString!(typeof(rs[0])) && 97 isNarrowString!(typeof(rs[1]))) 98 { 99 import std.utf: byDchar; 100 return commonPrefix!pred(rs[0].byDchar, 101 rs[1].byDchar).count; 102 } 103 else 104 return commonPrefix!pred(rs[0], rs[1]).count; 105 } 106 107 @safe pure unittest 108 { 109 assert(commonPrefixCount([1, 2, 3, 10], 110 [1, 2, 3]) == 3); 111 assert(commonPrefixCount(`åäö_`, 112 `åäö-`) == 3); 113 } 114 115 /** Get Common Suffix of $(D a) and $(D b). 116 TODO: Copy implementation of commonPrefix into commonSuffix to splitter 117 */ 118 auto commonSuffix(Rs...)(Rs rs) 119 if (rs.length == 2 && 120 allSatisfy!(isBidirectionalRange, Rs)) 121 { 122 import std.range : retro; 123 import std.array : array; 124 import std.algorithm.searching : commonPrefix; 125 return commonPrefix(rs[0].retro, 126 rs[1].retro).array.retro; 127 } 128 129 @safe pure unittest 130 { 131 import std.algorithm.comparison : equal; 132 assert(equal(commonSuffix(`_åäö`, 133 `-åäö`), `åäö`)); 134 } 135 136 // @safe pure unittest 137 // { 138 // import std.algorithm.comparison : equal; 139 // import nxt.splitter_ex : splitterASCIIAmong; 140 // import std.range : retro; 141 // import std.range.primitives : ElementType; 142 // import std.array : array; 143 // assert(equal(commonSuffix(`_å-ä-ö`, 144 // `-å-ä-ö`).retro.splitterASCIIAmong!('-').array, // TODO: how should this be solved? 145 // [`ö`, `ä`, `å`])); 146 // } 147 148 /** Get Count of Common Suffix of $(D a) and $(D b). 149 See_Also: http://forum.dlang.org/thread/bmbhovkgqomaidnyakvy@forum.dlang.org#post-bmbhovkgqomaidnyakvy:40forum.dlang.org 150 */ 151 auto commonSuffixCount(alias pred = "a == b", Rs...)(Rs rs) 152 if (rs.length == 2 && 153 allSatisfy!(isBidirectionalRange, Rs)) 154 { 155 import std.range : retro; 156 return commonPrefixCount!pred(rs[0].retro, 157 rs[1].retro); 158 } 159 160 @safe pure unittest 161 { 162 assert(commonSuffixCount(`_`, `-`) == 0); 163 assert(commonSuffixCount(`_å`, `-å`) == 1); 164 assert(commonSuffixCount(`_åä`, `-åä`) == 2); 165 assert(commonSuffixCount(`_åäö`, `-åäö`) == 3); 166 167 import std.algorithm.comparison : among; 168 assert(commonSuffixCount!((a, b) => (a == b && a == 'ö'))(`_åäö`, `-åäö`) == 1); 169 assert(commonSuffixCount!((a, b) => (a == b && a.among!('ä', 'ö')))(`_åäö`, `-åäö`) == 2); 170 } 171 172 /** Get length of Common Prefix of rs $(D rs). 173 See_Also: http://forum.dlang.org/thread/bmbhovkgqomaidnyakvy@forum.dlang.org#post-bmbhovkgqomaidnyakvy:40forum.dlang.org 174 */ 175 // auto commonPrefixLengthN(R...)(R rs) if (rs.length == 2) 176 // { 177 // import std.range: zip; 178 // return zip!((a, b) => a != b)(rs); 179 // } 180 181 // unittest 182 // { 183 // assert(commonPrefixLengthN([1, 2, 3, 10], 184 // [1, 2, 4, 10]) == 2); 185 // }