Created
February 14, 2015 11:51
-
-
Save esnya/a542addc69396b15a42c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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