Skip to content

Instantly share code, notes, and snippets.

@esnya
Created February 14, 2015 11:51
Show Gist options
  • Save esnya/a542addc69396b15a42c to your computer and use it in GitHub Desktop.
Save esnya/a542addc69396b15a42c to your computer and use it in GitHub Desktop.
import std.stdio;
import std.conv;
class CommutativeRing {
uint line;
CommutativeRing left, right;
CommutativeRing inverseOf;
string op;
this(uint line = __LINE__) {
this.line = line;
}
this(CommutativeRing left, string op, CommutativeRing right, uint line = __LINE__) {
this(line);
this.left = left;
this.op = op;
this.right = right;
}
void print(int depth = 0) {
import std.range;
if (op) {
writeln(' '.repeat(depth * 2), op);
left.print(depth + 1);
right.print(depth + 1);
} else {
writeln(' '.repeat(depth * 2), this);
}
}
override bool opEquals(Object cr) {
//auto a = cast(CommutativeRing)cr;
//auto b = this;
auto a = (cast(CommutativeRing)cr).expand();
auto b = this.expand();
if (a.op && b.op) {
return a.op == b.op &&
( a.left == b.left && a.right == b.right
|| a.left == b.right && a.right == b.left
|| a.left.op == b.right.op && a.left.left == b.left && a.left.right == b.right.left && a.right == b.right.right
|| b.left.op == a.right.op && b.left.left == a.left && b.left.right == a.right.left && b.right == a.right.right);
} else {
return cr is this;
}
}
CommutativeRing opBinary(string op)(CommutativeRing a) if (op == "+" || op == "*") {
if (op == "+" && this == zero) {
return a;
} else if (op == "+" && a == zero) {
return this;
} else if (op == "*" && this == one) {
return a;
} else if (op == "*" && a == one) {
return this;
} else if (inverseOf == a || a.inverseOf == this) {
return CommutativeRing.zero;
} else {
return new CommutativeRing(this, op, a);
}
}
CommutativeRing opUnary(string op : "-")(uint line = __LINE__) {
auto cr = new CommutativeRing(line);
cr.inverseOf = this;
return cr;
}
override string toString() const {
if (this == zero) {
return this.classinfo.name ~ "@Zero";
} else if (inverseOf) {
return inverseOf.toString() ~ "^-1";
} else {
return this.classinfo.name ~ '@' ~ line.to!string();
}
}
protected CommutativeRing expand() {
if (this.op == "*") {
if (this.left.op == "+") {
return (new CommutativeRing(this.left.left, "*", this.right))
+ (new CommutativeRing(this.left.right, "*", this.right));
} else if (this.right.op == "+") {
return (new CommutativeRing(this.left, "*", this.right.left))
+ (new CommutativeRing(this.left, "*", this.right.right));
}
}
return this;
}
shared private static CommutativeRing _zero;
@property static CommutativeRing zero() {
return cast(CommutativeRing)_zero;
}
shared private static CommutativeRing _one;
@property static CommutativeRing one() {
return cast(CommutativeRing)_one;
}
shared static this() {
_zero = cast(shared(CommutativeRing))new CommutativeRing();
_one = cast(shared(CommutativeRing))new CommutativeRing();
}
}
alias CR = CommutativeRing;
unittest {
auto a = new CommutativeRing;
auto b = a;
assert(a == b);
auto c = new CommutativeRing;
assert(c != a);
}
unittest {
auto a = new CR;
auto b = new CR;
auto c = new CR;
// 加法群 (R,+) は アーベル群
// 1.
static assert(is(typeof(a + b) == CR));
// 2.
assert((a + b) + c == a + (b + c));
// 3.
assert(a + CR.zero == CR.zero + a);
assert(a + CR.zero == a);
// 4.
assert(is(typeof(-a) == CR));
assert(a + (-a) == CR.zero);
assert((-a) + a == CR.zero);
// 5.
assert(a + b == b + a);
// 乗法半群 (R,*)
// 1.
static assert(is(typeof(a * b) == CR));
// 2.
assert((a * b) * c == a * (b * c));
// 3.
assert(a * CR.one == a);
assert(CR.one * a == a);
// 分配率
assert(a * (b + c) == (a * b) + (a * c));
assert((a + b) * c == (a * c) + (b * c));
// 可換環
assert(a * b == b * a);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment