Skip to content

Instantly share code, notes, and snippets.

@namachan10777
Created December 16, 2017 13:31
Show Gist options
  • Save namachan10777/5ded4006636008ea67971837e05cae77 to your computer and use it in GitHub Desktop.
Save namachan10777/5ded4006636008ea67971837e05cae77 to your computer and use it in GitHub Desktop.
import std.stdio;
import std.math;
import std.algorithm.comparison;
struct List(alias N, T) {
private T[] arr;
auto opIndex(I : Interger!(B, T), alias B, alias T)(in I idx) {
static if (B >= 0 && T < N) {
return arr[idx.value];
}
else {
static assert (false, "Out of range");
}
}
}
auto nil(T)() {
return List!(0, T)();
}
auto cons (L : List!(N, T), alias N, T)(L list, T x) {
return List!(N+1, T)(list.arr ~ x);
}
auto hd (L : List!(N, T), alias N, T)(L list) {
static assert (N > 0);
return list.arr[$-1];
}
auto tl (L : List!(N, T), alias N, T)(L list) {
static assert (N > 0);
return List!(N-1, T)(list.arr[0..$-1]);
}
auto join(L1 : List!(N1, T), L2 : List!(N2, T), alias N1, alias N2, T)(L1 l1, L2 l2) {
return List!(N1+N2, T)(l1.arr ~ l2.arr);
}
auto idx (alias IDX, L : List!(N, T), alias N, T)(L list) {
static assert (IDX > 0 && IDX < N);
return list.arr[IDX];
}
unittest {
auto list0 = nil!int;
auto list1 = list0.cons(0);
auto list2 = list0.cons(0).cons(1).cons(2).cons(3);
// list0.hd; //compile error
assert (list1.hd == 0);
// list0.tl; //compile error
assert (list1.tl == nil!int);
// list1.tl.hd; //compile error
assert (list2.idx!2 == 2);
// list2.idx!4 //compile error
}
struct Interger(alias B, alias T) {
static if (B >= 0) {
ulong value;
}
else {
long value;
}
auto opBinary(string op, I : Interger!(XB, XT), alias XB, alias XT)(I x) {
static if (op == "+") {
enum NEW_B = B+XB;
enum NEW_T = T+XT;
return Interger!(NEW_B, NEW_T)(value+x.value);
}
else static if (op == "-") {
enum NEW_B = B-XB;
enum NEW_T = T-XT;
return Interger!(NEW_B, NEW_T)(value-x.value);
}
else static if (op == "*") {
enum NEW_B = min(B*XB, B*XT, T*XB, T*XT);
enum NEW_T = max(B*XB, B*XT, T*XB, T*XT);
return Interger!(NEW_B, NEW_T)(value*x.value);
}
else static if (op == "/") {
static if (XB == 0 && XT == 0) {
static assert (false);
}
else static if (XB == 0) {
enum NEW_B = min(B/XT, T/XT);
enum NEW_T = max(B/XT, T/XT);
}
else static if (XT == 0) {
enum NEW_T = max(B/XB, T/XB);
enum NEW_B = max(B/XB, T/XB);
}
else {
enum NEW_T = max(B/XB, T/XB, B/XT, T/XT);
enum NEW_B = max(B/XB, T/XB, B/XT, T/XT);
}
return Interger!(NEW_B, NEW_T)(value/x.value);
}
else static if (op == "%") {
static if (B < 0 && T < 0) {
enum NEW_B = -max(abs(XB), abs(XT));
enum NEW_T = 0;
}
else static if (B < 0) {
enum NEW_B = -max(abs(XB), abs(XT));
enum NEW_T = max(abs(XB), abs(XT));
}
else {
enum NEW_B = 0;
enum NEW_T = max(abs(XB), abs(XT));
}
return Interger!(NEW_B, NEW_T)(value/x.value);
}
}
}
auto interger(alias N)() {
return Interger!(N, N)(N);
}
struct IndexRange(alias B, alias T) {
long idx = B;
bool empty() {
return idx > T;
}
auto front() {
return Interger!(B, T)(idx);
}
void popFront() {
++idx;
}
}
auto rng(alias B, alias T)() {
return IndexRange!(B, T-1)();
}
unittest {
auto i1 = Interger!(0, 10)(5);
auto i2 = Interger!(0, 3)(2);
auto l = nil!int.cons(0).cons(1).cons(2).cons(3).cons(4).cons(5).cons(6);
/+foreach (i; rng!(-3, 0)) {
writeln(l[i]);
}
foreach (i; rng!(-3, 0)) {
writeln(l[i+interger!3]);
}+/
foreach (i; rng!(-3, 0)) {
writeln(i);
writeln((i+interger!3)*interger!2);
writeln(l[(i+interger!3)*interger!2]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment