PageRenderTime 45ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/stuff.d

http://github.com/plol/d-interp
D | 277 lines | 228 code | 45 blank | 4 comment | 36 complexity | e6fdd3023306ff2d722a6add846a4f09 MD5 | raw file
  1. import std.stdio;
  2. import std.typecons, std.functional, std.conv, std.traits, std.range;
  3. import std.format, std.array, std.string, std.algorithm;
  4. import std.typetuple;
  5. template tuples(int n, Rest...) {
  6. static assert (Rest.length % n == 0);
  7. static if (Rest.length == 0) {
  8. alias TypeTuple!() tuples;
  9. } else {
  10. alias TypeTuple!(tuple(Rest[0 .. n]), tuples!(n, Rest[n .. $])) tuples;
  11. }
  12. }
  13. string format(T...)(T t) {
  14. auto app = appender!string();
  15. formattedWrite(app, t);
  16. return app.data;
  17. }
  18. T[] make_set(T)(ref T[] ts) {
  19. auto rest = ts.sort().release().uniq().copy(ts);
  20. ts = ts[0 .. $ - rest.length];
  21. return ts;
  22. }
  23. T[] extend(T)(ref T[] ts, T[] os) {
  24. ts = ts.dup;
  25. ts ~= os;
  26. return ts.make_set();
  27. }
  28. R tail(R)(R r) if (isInputRange!R) {
  29. r.popFront();
  30. return r;
  31. }
  32. struct Trie(K,V) {
  33. alias ElementType!K E;
  34. private Trie[E] nexts;
  35. private V* _word;
  36. ref V value() @property {
  37. return *_word;
  38. }
  39. this(K[] ks, V[] vs) {
  40. zip(ks, vs).sort();
  41. auto completes = vs[0 .. ks.until!"a.length > 0"().walkLength];
  42. assert (completes.length <= 1, text(completes));
  43. if (completes.length == 1) {
  44. _word = &completes[0];
  45. }
  46. ks = ks[completes.length .. $];
  47. vs = vs[completes.length .. $];
  48. while (!ks.empty) {
  49. auto f = ks[0].front;
  50. bool starts_with_diff(K a) { // bug
  51. return a.front != f;
  52. }
  53. size_t len = ks.until!starts_with_diff().walkLength();
  54. foreach (i; 0 .. len) {
  55. ks[i].popFront();
  56. }
  57. nexts[f] = Trie(ks[0 .. len], vs[0 .. len]);
  58. ks = ks[len .. $];
  59. vs = vs[len .. $];
  60. }
  61. }
  62. bool complete() const @property {
  63. return _word !is null;
  64. }
  65. bool opIn_r(E d) {
  66. return (d in nexts) != null;
  67. }
  68. Trie opIndex(E d) {
  69. return nexts[d];
  70. }
  71. Trie opIndex(K s) {
  72. if (s.empty) return this;
  73. auto f = s.front;
  74. s.popFront;
  75. return this[f][s];
  76. }
  77. string toString() {
  78. return "Trie: " ~ toString2();
  79. }
  80. private string toString2() {
  81. bool needs_paren = (complete && nexts.length > 0) || nexts.length > 1;
  82. string s;
  83. if (needs_paren) {
  84. s = "(";
  85. }
  86. if (complete) {
  87. s ~= ":";
  88. s ~= to!string(value);
  89. if (nexts.length != 0) {
  90. s ~= " ";
  91. }
  92. }
  93. // Cannot inline this function as
  94. // something cannot get frame pointer to map
  95. string f(typeof(zip(nexts.keys, nexts.values).front) a) {
  96. return text(a[0], a[1].toString2()); // BUG BUG BUG
  97. }
  98. s ~= zip(nexts.keys, nexts.values)
  99. //.map!(a => text(a[0], a[1].toString2())) // BUG BUG BUG
  100. .map!f() // BUG BUG BUG
  101. .join(", ");
  102. if (needs_paren) {
  103. s ~= ")";
  104. }
  105. return s;
  106. }
  107. void mergeWith(Trie b) {
  108. foreach (c, t; b.nexts) {
  109. if (c in nexts) {
  110. nexts[c].mergeWith(t);
  111. } else {
  112. nexts[c] = t;
  113. }
  114. }
  115. }
  116. }
  117. struct TrieSet(K) {
  118. alias ElementType!K E;
  119. private Tuple!(E, TrieSet)[] nexts;
  120. bool complete;
  121. private auto nextsFor(E e) {
  122. auto dummy = tuple(e, TrieSet());
  123. return assumeSorted!"a[0] < b[0]"(nexts).equalRange(dummy).release();
  124. }
  125. this(K k) {
  126. insert(k);
  127. }
  128. void insert(K k) {
  129. if (k.empty) {
  130. complete = true;
  131. return;
  132. }
  133. auto f = k.front;
  134. k.popFront();
  135. auto nexts1 = nextsFor(f);
  136. if (nexts1.empty) {
  137. nexts ~= tuple(f, TrieSet(k));
  138. insertionSort_1!"a[0] < b[0]"(nexts);
  139. } else {
  140. assert (nexts1.length == 1);
  141. nexts1.front[1].insert(k);
  142. }
  143. }
  144. bool opIn_r(K k) {
  145. if (k.empty) return complete;
  146. auto f = k.front;
  147. k.popFront();
  148. auto nexts1 = nextsFor(f);
  149. return !nexts1.empty && k in nexts1.front[1];
  150. }
  151. string toString() {
  152. string ret = complete ? "(." : "(";
  153. foreach (n; nexts) {
  154. ret ~= text(n[0], ":", n[1]);
  155. }
  156. ret ~= ")";
  157. return ret;
  158. }
  159. }
  160. unittest {
  161. auto t = TrieSet!string("Hello");
  162. t.insert("Howdy");
  163. t.insert("Hello there!");
  164. assert ("Howdy" in t, text(t));
  165. assert ("Hello" in t);
  166. assert ("Hello there!" in t);
  167. assert ("Hello the" !in t);
  168. assert ("" !in t);
  169. assert ("foo" !in t);
  170. }
  171. // assumes all range is sorted except last element, which is moved backwards
  172. void insertionSort_1(alias less="a < b", R)(R r) {
  173. alias binaryFun!less f;
  174. auto idx = r.length - 1;
  175. while (idx > 0 && f(r[idx], r[idx-1])) {
  176. swap(r[idx-1], r[idx]);
  177. idx -= 1;
  178. }
  179. }
  180. unittest {
  181. auto a = [1,2,4,5,6,3];
  182. a.insertionSort_1();
  183. assert (a == [1,2,3,4,5,6], text(a));
  184. auto b = [tuple(1,2),tuple(3,0),tuple(2,1)];
  185. b.insertionSort_1!"a[0] < b[0]"();
  186. assert (b == [tuple(1,2),tuple(2,1),tuple(3,0)], text(b));
  187. }
  188. struct StupidMap(alias f, R) {
  189. R r;
  190. auto front() @property {
  191. return f(r.front);
  192. }
  193. void popFront() {
  194. auto f = r.front;
  195. while (!r.empty && r.front == f) {
  196. r.popFront();
  197. }
  198. }
  199. bool empty() @property {
  200. return r.empty;
  201. }
  202. }
  203. auto stupid_map(alias f, R)(R r) {
  204. return StupidMap!(f, R)(r);
  205. }
  206. struct StupidUniq(R) {
  207. R r;
  208. auto front() @property {
  209. return r.front;
  210. }
  211. void popFront() {
  212. auto f = r.front;
  213. while (!r.empty && r.front == f) {
  214. r.popFront();
  215. }
  216. }
  217. bool empty() @property {
  218. return r.empty;
  219. }
  220. }
  221. auto stupid_uniq(R)(R r) {
  222. return StupidUniq!R(r);
  223. }
  224. string simpleCmp(string o, string[] ms...) {
  225. string ret;
  226. foreach (m; ms) {
  227. ret ~= "if (" ~ m ~ " < " ~ o ~ "." ~ m ~") { return -1; }\n";
  228. ret ~= "if (" ~ m ~ " > " ~ o ~ "." ~ m ~") { return 1; }\n";
  229. }
  230. ret ~= "return 0;";
  231. return ret;
  232. }