Last active
September 6, 2021 18:40
-
-
Save lvguowei/c44effdb034abd99094e30d60d695289 to your computer and use it in GitHub Desktop.
A little java, a few patterns
This file contains 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 java.util.* | |
import kotlin.math.sqrt | |
abstract class Point(val x: Int, val y: Int) { | |
abstract fun distanceToO(): Double | |
fun closerToO(p: Point) = distanceToO() < p.distanceToO() | |
fun minus(p: Point) = CartesianPt(x - p.x, y - p.y) | |
} | |
open class CartesianPt(x: Int, y: Int) : Point(x, y) { | |
override fun distanceToO() = sqrt((x * x + y * y).toDouble()) | |
} | |
open class ManhattanPt(x: Int, y: Int) : Point(x, y) { | |
override fun distanceToO() = (x + y).toDouble() | |
} | |
class ShadowedManhattanPt(x: Int, y: Int, private val dx: Int, private val dy: Int) : ManhattanPt(x, y) { | |
override fun distanceToO() = (super.distanceToO() + dx + dy) | |
} | |
class ShadowedCartesianPt(x: Int, y: Int, private val dx: Int, private val dy: Int) : CartesianPt(x, y) { | |
override fun distanceToO() = CartesianPt(x + dx, y + dy).distanceToO() | |
} | |
abstract class Layer | |
class Base(val o: Any) : Layer() | |
class Slice(val l: Layer) : Layer() | |
abstract class Shish { | |
val ooFn = OnlyOnionsVisitor() | |
val ivFn = IsVegetarianVisitor() | |
abstract fun onlyOnions(): Boolean | |
abstract fun isVegetarian(): Boolean | |
} | |
class Skewer : Shish() { | |
override fun onlyOnions() = ooFn.forSkewer() | |
override fun isVegetarian() = ivFn.forSkewer() | |
} | |
class Onion(val s: Shish) : Shish() { | |
override fun onlyOnions() = ooFn.forOnion(s) | |
override fun isVegetarian() = ivFn.forOnion(s) | |
} | |
class Lamb(val s: Shish) : Shish() { | |
override fun onlyOnions() = ooFn.forLamb(s) | |
override fun isVegetarian() = ivFn.forLamb(s) | |
} | |
class Tomato(val s: Shish) : Shish() { | |
override fun onlyOnions() = ooFn.forTomato(s) | |
override fun isVegetarian() = ivFn.forTomato(s) | |
} | |
class OnlyOnionsVisitor { | |
fun forSkewer() = true | |
fun forOnion(s: Shish) = s.onlyOnions() | |
fun forLamb(s: Shish) = false | |
fun forTomato(s: Shish) = false | |
} | |
class IsVegetarianVisitor { | |
fun forSkewer() = true | |
fun forOnion(s: Shish) = s.isVegetarian() | |
fun forLamb(s: Shish) = false | |
fun forTomato(s: Shish) = s.isVegetarian() | |
} | |
abstract class Kebab { | |
abstract fun isVeggie(): Boolean | |
abstract fun whatHolder(): Any | |
} | |
class Holder(private val o: Any) : Kebab() { | |
override fun isVeggie() = true | |
override fun whatHolder() = o | |
} | |
class Shallot(private val k: Kebab) : Kebab() { | |
override fun isVeggie() = k.isVeggie() | |
override fun whatHolder() = k.whatHolder() | |
} | |
class Shrimp(private val k: Kebab) : Kebab() { | |
override fun isVeggie() = false | |
override fun whatHolder() = k.whatHolder() | |
} | |
class Radish(private val k: Kebab) : Kebab() { | |
override fun isVeggie() = k.isVeggie() | |
override fun whatHolder() = k.whatHolder() | |
} | |
class Pepper(private val k: Kebab) : Kebab() { | |
override fun isVeggie() = k.isVeggie() | |
override fun whatHolder() = k.whatHolder() | |
} | |
abstract class Rod | |
class Dagger : Rod() | |
class Sabre : Rod() | |
class Sword : Rod() | |
abstract class Plate | |
class Gold : Plate() | |
class Silver : Plate() | |
class Brass : Plate() | |
class Copper : Plate() | |
class Wood : Plate() | |
abstract class Pizza { | |
val remFn = RemoveAnchovyVisitor() | |
val topFn = TopAnchovyWithCheeseVisitor() | |
val subFn = SubstituteAnchovyByCheeseVisitor() | |
abstract fun removeAnchovy(): Pizza | |
abstract fun topAnchovyWithCheese(): Pizza | |
abstract fun substituteAnchovyByCheese(): Pizza | |
} | |
class SubstituteAnchovyByCheeseVisitor { | |
fun forCrust() = Crust() | |
fun forCheese(p: Pizza) = Cheese(p.substituteAnchovyByCheese()) | |
fun forOlive(p: Pizza) = Olive(p.substituteAnchovyByCheese()) | |
fun forAnchovy(p: Pizza) = Cheese(p.substituteAnchovyByCheese()) | |
fun forSausage(p: Pizza) = Sausage(p.substituteAnchovyByCheese()) | |
fun forSpinach(p: Pizza) = Spinach(p.substituteAnchovyByCheese()) | |
} | |
class TopAnchovyWithCheeseVisitor { | |
fun forCrust() = Crust() | |
fun forCheese(p: Pizza) = Cheese(p.topAnchovyWithCheese()) | |
fun forOlive(p: Pizza) = Olive(p.topAnchovyWithCheese()) | |
fun forAnchovy(p: Pizza) = Cheese(Anchovy(p.topAnchovyWithCheese())) | |
fun forSausage(p: Pizza) = Sausage(p.topAnchovyWithCheese()) | |
fun forSpinach(p: Pizza) = Spinach(p.topAnchovyWithCheese()) | |
} | |
class RemoveAnchovyVisitor { | |
fun forCrust() = Crust() | |
fun forCheese(p: Pizza) = Cheese(p.removeAnchovy()) | |
fun forOlive(p: Pizza) = Olive(p.removeAnchovy()) | |
fun forAnchovy(p: Pizza) = p.removeAnchovy() | |
fun forSausage(p: Pizza) = Sausage(p.removeAnchovy()) | |
fun forSpinach(p: Pizza) = Spinach(p.removeAnchovy()) | |
} | |
class Crust : Pizza() { | |
override fun removeAnchovy() = remFn.forCrust() | |
override fun topAnchovyWithCheese() = topFn.forCrust() | |
override fun substituteAnchovyByCheese() = subFn.forCrust() | |
} | |
class Cheese(val p: Pizza) : Pizza() { | |
override fun removeAnchovy() = remFn.forCheese(p) | |
override fun topAnchovyWithCheese() = topFn.forCheese(p) | |
override fun substituteAnchovyByCheese() = subFn.forCheese(p) | |
} | |
class Olive(val p: Pizza) : Pizza() { | |
override fun removeAnchovy() = remFn.forOlive(p) | |
override fun topAnchovyWithCheese() = topFn.forOlive(p) | |
override fun substituteAnchovyByCheese() = subFn.forOlive(p) | |
} | |
class Anchovy(val p: Pizza) : Pizza() { | |
override fun removeAnchovy() = remFn.forAnchovy(p) | |
override fun topAnchovyWithCheese() = topFn.forAnchovy(p) | |
override fun substituteAnchovyByCheese() = subFn.forAnchovy(p) | |
} | |
class Sausage(val p: Pizza) : Pizza() { | |
override fun removeAnchovy() = remFn.forSausage(p) | |
override fun topAnchovyWithCheese() = topFn.forSausage(p) | |
override fun substituteAnchovyByCheese() = subFn.forSausage(p) | |
} | |
class Spinach(val p: Pizza) : Pizza() { | |
override fun removeAnchovy(): Pizza = remFn.forSpinach(p) | |
override fun topAnchovyWithCheese() = topFn.forSpinach(p) | |
override fun substituteAnchovyByCheese() = subFn.forSpinach(p) | |
} | |
abstract class Pie { | |
abstract fun accept(ask: PieVisitor): Pie | |
} | |
interface PieVisitor { | |
fun forBot(): Pie | |
fun forTop(t: Any, r: Pie): Pie | |
} | |
class RemV(private val o: Any) : PieVisitor { | |
override fun forBot() = Bot() | |
override fun forTop(t: Any, r: Pie) = | |
if (o == t) | |
r.accept(this) | |
else Top(t, r.accept(this)) | |
} | |
open class SubstV(private val n: Any, private val o: Any): PieVisitor { | |
override fun forBot() = Bot() | |
override fun forTop(t: Any, r: Pie) = | |
if (o == t) | |
Top(n, r.accept(this)) | |
else Top(t, r.accept(this)) | |
} | |
class LtdSubstV(private val c: Int, private val n: Any, private val o: Any) : SubstV(n, o) { | |
override fun forTop(t: Any, r: Pie) = | |
if (c == 0) { | |
Top(t, r) | |
} else if (o == t) { | |
Top(n, r.accept(LtdSubstV(c - 1, n, o))) | |
} else { | |
Top(t, r.accept(this)) | |
} | |
} | |
class Bot : Pie() { | |
override fun accept(ask: PieVisitor) = ask.forBot() | |
override fun toString(): String { | |
return "Bottom |" | |
} | |
} | |
class Top(private val t: Any, private val r: Pie) : Pie() { | |
override fun accept(ask: PieVisitor) = ask.forTop(t, r) | |
override fun toString(): String { | |
return "$t <<< $r" | |
} | |
} | |
abstract class Fish | |
class Anchovy2 : Fish() { | |
override fun equals(other: Any?): Boolean { | |
if (this === other) return true | |
if (javaClass != other?.javaClass) return false | |
return true | |
} | |
override fun hashCode(): Int { | |
return javaClass.hashCode() | |
} | |
} | |
class Salmon : Fish() { | |
override fun equals(other: Any?): Boolean { | |
if (this === other) return true | |
if (javaClass != other?.javaClass) return false | |
return true | |
} | |
override fun hashCode(): Int { | |
return javaClass.hashCode() | |
} | |
} | |
class Tuna : Fish() { | |
override fun equals(other: Any?): Boolean { | |
if (this === other) return true | |
if (javaClass != other?.javaClass) return false | |
return true | |
} | |
override fun hashCode(): Int { | |
return javaClass.hashCode() | |
} | |
} | |
abstract class Fruit | |
class Peach : Fruit() { | |
override fun equals(other: Any?): Boolean { | |
return other is Peach | |
} | |
} | |
class Apple : Fruit() { | |
override fun equals(other: Any?): Boolean { | |
return other is Apple | |
} | |
} | |
class Pear : Fruit() { | |
override fun equals(other: Any?): Boolean { | |
return other is Pear | |
} | |
} | |
class Lemon : Fruit() { | |
override fun equals(other: Any?): Boolean { | |
return other is Lemon | |
} | |
} | |
class Fig : Fruit() { | |
override fun equals(other: Any?): Boolean { | |
return other is Fig | |
} | |
} | |
abstract class Tree { | |
abstract fun accept(ask: TreeVisitor): Any | |
} | |
class Bud : Tree() { | |
override fun accept(ask: TreeVisitor) = ask.forBud() | |
} | |
class Flat(private val f: Fruit, private val t: Tree) : Tree() { | |
override fun accept(ask: TreeVisitor) = ask.forFlat(f, t) | |
} | |
class Split(private val l: Tree, private val r: Tree) : Tree() { | |
override fun accept(ask: TreeVisitor) = ask.forSplit(l, r) | |
} | |
interface TreeVisitor { | |
fun forBud(): Any | |
fun forFlat(f: Fruit, t: Tree): Any | |
fun forSplit(l: Tree, r: Tree): Any | |
} | |
class IsFlat : TreeVisitor { | |
override fun forBud() = true | |
override fun forFlat(f: Fruit, t: Tree) = t.accept(this) | |
override fun forSplit(l: Tree, r: Tree) = false | |
} | |
class IsSplit : TreeVisitor { | |
override fun forBud() = true | |
override fun forFlat(f: Fruit, t: Tree) = false | |
override fun forSplit(l: Tree, r: Tree) = (l.accept(this) as Boolean) && (r.accept(this) as Boolean) | |
} | |
class Occurs(private val a: Fruit) : TreeVisitor { | |
override fun forBud() = 0 | |
override fun forFlat(f: Fruit, t: Tree) = | |
if (a == f) { | |
(t.accept(this) as Int) + 1 | |
} else { | |
t.accept(this) | |
} | |
override fun forSplit(l: Tree, r: Tree) = (l.accept(this) as Int) + (r.accept(this) as Int) | |
} | |
abstract class Expr { | |
abstract fun accept(ask: ExprVisitor): Any | |
} | |
class Plus(private val l: Expr, private val r: Expr) : Expr() { | |
override fun accept(ask: ExprVisitor) = ask.forPlus(l, r) | |
} | |
class Diff(private val l: Expr, private val r: Expr) : Expr() { | |
override fun accept(ask: ExprVisitor) = ask.forDiff(l, r) | |
} | |
class Prod(private val l: Expr, private val r: Expr) : Expr() { | |
override fun accept(ask: ExprVisitor) = ask.forProd(l, r) | |
} | |
class Const(private val c: Any) : Expr() { | |
override fun accept(ask: ExprVisitor) = ask.forConst(c) | |
} | |
interface ExprVisitor { | |
fun forPlus(l: Expr, r: Expr): Any | |
fun forDiff(l: Expr, r: Expr): Any | |
fun forProd(l: Expr, r: Expr): Any | |
fun forConst(c: Any): Any | |
} | |
abstract class Eval : ExprVisitor { | |
override fun forPlus(l: Expr, r: Expr) = plus(l.accept(this), r.accept(this)) | |
override fun forDiff(l: Expr, r: Expr) = diff(l.accept(this), r.accept(this)) | |
override fun forProd(l: Expr, r: Expr) = prod(l.accept(this), r.accept(this)) | |
override fun forConst(c: Any) = c | |
abstract fun plus(l: Any, r: Any): Any | |
abstract fun diff(l: Any, r: Any): Any | |
abstract fun prod(l: Any, r: Any): Any | |
} | |
class IntEval : Eval() { | |
override fun plus(l: Any, r: Any) = l as Int + r as Int | |
override fun diff(l: Any, r: Any) = l as Int - r as Int | |
override fun prod(l: Any, r: Any) = l as Int * r as Int | |
} | |
abstract class Set { | |
fun add(i: Int) = if (mem(i)) this else Add(i, this) | |
abstract fun mem(n: Int): Boolean | |
abstract fun plus(t: Set): Set | |
abstract fun diff(t: Set): Set | |
abstract fun prod(t: Set): Set | |
} | |
class Empty : Set() { | |
override fun mem(n: Int) = false | |
override fun plus(t: Set) = t | |
override fun diff(t: Set) = Empty() | |
override fun prod(t: Set) = Empty() | |
override fun toString() = "." | |
} | |
class Add(private val i: Int, private val s: Set) : Set() { | |
override fun mem(n: Int) = if (i == n) true else s.mem(n) | |
override fun plus(t: Set) = s.plus(t.add(i)) | |
override fun diff(t: Set) = if (t.mem(i)) s.diff(t) else s.diff(t).add(i) | |
override fun prod(t: Set) = if (t.mem(i)) s.prod(t).add(i) else s.prod(t) | |
override fun toString() = "$i $s" | |
} | |
class SetEval : Eval() { | |
override fun plus(l: Any, r: Any) = (l as Set).plus(r as Set) | |
override fun diff(l: Any, r: Any) = (l as Set).diff(r as Set) | |
override fun prod(l: Any, r: Any) = (l as Set).prod(r as Set) | |
} | |
abstract class Shape { | |
abstract fun accept(ask: ShapeVisitor): Boolean | |
} | |
class Circle(private val r: Int) : Shape() { | |
override fun accept(ask: ShapeVisitor) = ask.forCircle(r) | |
} | |
class Square(private val s: Int) : Shape() { | |
override fun accept(ask: ShapeVisitor) = ask.forSquare(s) | |
} | |
class Trans(private val q: Point, private val s: Shape) : Shape() { | |
override fun accept(ask: ShapeVisitor) = ask.forTrans(q, s) | |
} | |
class Union(private val s: Shape, private val t: Shape) : Shape() { | |
override fun accept(ask: ShapeVisitor) = (ask as UnionVisitor).forUnion(s, t) | |
} | |
interface ShapeVisitor { | |
fun forCircle(r: Int): Boolean | |
fun forSquare(s: Int): Boolean | |
fun forTrans(q: Point, s: Shape): Boolean | |
} | |
interface UnionVisitor : ShapeVisitor { | |
fun forUnion(s: Shape, t: Shape): Boolean | |
} | |
open class HasPt(private val p: Point) : ShapeVisitor { | |
override fun forCircle(r: Int) = p.distanceToO() <= r | |
override fun forSquare(s: Int) = p.x <= s && p.y <= s | |
open fun newHasPt(p: Point) = HasPt(p) | |
override fun forTrans(q: Point, s: Shape) = s.accept(newHasPt(p.minus(q))) | |
} | |
class UnionHasPt(p: Point) : HasPt(p), UnionVisitor { | |
override fun newHasPt(p: Point) = UnionHasPt(p) | |
override fun forUnion(s: Shape, t: Shape) = s.accept(this) || t.accept(this) | |
} | |
abstract class PieD { | |
abstract fun accept(ask: PieVisitorI): Any | |
} | |
class Bot2 : PieD() { | |
override fun accept(ask: PieVisitorI) = ask.forBot() | |
} | |
class Top2(private val t: Any, private val r: PieD) : PieD() { | |
override fun accept(ask: PieVisitorI) = ask.forTop(t, r) | |
} | |
interface PieVisitorI { | |
fun forBot(): Any | |
fun forTop(t: Any, r: PieD): Any | |
} | |
class OccursV(private val a: Any) : PieVisitorI { | |
override fun forBot() = 0 | |
override fun forTop(t: Any, r: PieD) = | |
if (t == a) { | |
r.accept(this) as Int + 1 | |
} else { | |
r.accept(this) | |
} | |
} | |
class SubstV2(private val n: Any, private val o: Any) : PieVisitorI { | |
override fun forBot() = Bot() | |
override fun forTop(t: Any, r: PieD) = | |
if (o == t) | |
Top2(n, r.accept(this) as PieD) | |
else | |
Top2(t, r.accept(this) as PieD) | |
} | |
class RemV2(private val o: Any) : PieVisitorI { | |
override fun forBot() = Bot() | |
override fun forTop(t: Any, r: PieD) = | |
if (t == o) | |
r.accept(this) | |
else | |
Top2(t, r.accept(this) as PieD) | |
} | |
interface PiemanI { | |
fun addTop(t: Any): Int | |
fun remTop(t: Any): Int | |
fun substTop(n: Any, o: Any): Int | |
fun occTop(o: Any): Int | |
} | |
class PiemanM : PiemanI { | |
private var p: PieD = Bot2() | |
override fun addTop(t: Any): Int { | |
p = Top2(t, p) | |
return occTop(t) | |
} | |
override fun remTop(t: Any): Int { | |
p = p.accept(RemV2(t)) as PieD | |
return occTop(t) | |
} | |
override fun substTop(n: Any, o: Any): Int { | |
p = p.accept(SubstV2(n, o)) as PieD | |
return occTop(n) | |
} | |
override fun occTop(o: Any) = p.accept(OccursV(o)) as Int | |
} | |
fun main(args: Array<String>) { | |
// println(ManhattanPt(3, 4).distanceToO()) | |
// println(CartesianPt(3, 4).distanceToO()) | |
// println(Top(Anchovy2(), Top(Salmon(), Top(Anchovy2(), Top(Tuna(), Bot())))).accept(RemoveVisitor(Anchovy2()))) | |
// println(Top(Anchovy2(), Top(Salmon(), Top(Anchovy2(), Top(Tuna(), Bot())))).accept(SubstituteVisitor(Anchovy2(), Salmon()))) | |
// println(Top(Anchovy2(), Top(Anchovy2(), Top(Anchovy2(), Top(Tuna(), Bot())))).accept(LtdSubstituteVisitor(2, Salmon(), Anchovy2()))) | |
// println(Plus(Prod(Const(1), Const(2)), Const(3)).accept(IntEval())) | |
// println(Plus(Prod(Const(Empty().add(1).add(2)), Const(Empty().add(2).add(3))), Const(Empty().add(3))).accept(SetEval())) | |
Trans( | |
CartesianPt(3, 7), | |
Union( | |
Square(10), | |
Circle(10) | |
) | |
).accept(UnionHasPt(CartesianPt(13, 17))) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment