157 lines
3.8 KiB
Java
157 lines
3.8 KiB
Java
interface XExpr {
|
|
}
|
|
|
|
final class ValXExpr implements XExpr {
|
|
long value;
|
|
ValXExpr(long i) {
|
|
value = i;
|
|
}
|
|
}
|
|
|
|
final class VarXExpr implements XExpr {
|
|
long name;
|
|
VarXExpr(long i) {
|
|
name = i;
|
|
}
|
|
}
|
|
|
|
|
|
final class AddXExpr implements XExpr {
|
|
XExpr left;
|
|
XExpr right;
|
|
AddXExpr(XExpr l, XExpr r) {
|
|
left = l;
|
|
right = r;
|
|
}
|
|
}
|
|
|
|
final class MulXExpr implements XExpr {
|
|
XExpr left;
|
|
XExpr right;
|
|
MulXExpr(XExpr l, XExpr r) {
|
|
left = l;
|
|
right = r;
|
|
}
|
|
}
|
|
|
|
|
|
public class cfold {
|
|
static XExpr mk_expr( long n, long v ) {
|
|
if (n == 0) {
|
|
return (v==0 ? new VarXExpr(1) : new ValXExpr(v));
|
|
}
|
|
else {
|
|
return new AddXExpr( mk_expr(n-1, v+1), mk_expr(n - 1, v == 0 ? 0 : v - 1));
|
|
}
|
|
}
|
|
|
|
static XExpr append_add( XExpr e1, XExpr e2 ) {
|
|
if (e1 instanceof AddXExpr a) {
|
|
return new AddXExpr(a.left, append_add(a.right, e2));
|
|
}
|
|
else {
|
|
return new AddXExpr(e1,e2);
|
|
}
|
|
}
|
|
|
|
static XExpr tail_append_add( XExpr e1, XExpr e2 ) {
|
|
AddXExpr hd = null;
|
|
AddXExpr acc = null;
|
|
while(e1 instanceof AddXExpr x) {
|
|
if (acc==null) {
|
|
hd = acc = new AddXExpr(x.left,null);
|
|
}
|
|
else {
|
|
AddXExpr y = new AddXExpr(x.left,null);
|
|
acc.right = y;
|
|
acc = y;
|
|
}
|
|
e1 = x.right;
|
|
}
|
|
if (acc==null) hd = acc = new AddXExpr(e1,e2);
|
|
else acc.right = new AddXExpr(e1,e2);
|
|
return hd;
|
|
}
|
|
|
|
static XExpr append_mul( XExpr e1, XExpr e2 ) {
|
|
if (e1 instanceof MulXExpr a) {
|
|
return new MulXExpr(a.left, append_mul(a.right, e2));
|
|
}
|
|
else {
|
|
return new MulXExpr(e1,e2);
|
|
}
|
|
}
|
|
|
|
static XExpr reassoc( XExpr e ) {
|
|
if (e instanceof AddXExpr a) {
|
|
return append_add( reassoc(a.left), reassoc(a.right) );
|
|
}
|
|
else if (e instanceof MulXExpr m) {
|
|
return append_mul( reassoc(m.left), reassoc(m.right) );
|
|
}
|
|
else return e;
|
|
}
|
|
|
|
static XExpr const_folding( XExpr e ) {
|
|
if (e instanceof AddXExpr x) {
|
|
XExpr e1 = const_folding(x.left);
|
|
XExpr e2 = const_folding(x.right);
|
|
if (e1 instanceof ValXExpr a && e2 instanceof ValXExpr b) {
|
|
return new ValXExpr(a.value + b.value );
|
|
}
|
|
else if (e1 instanceof ValXExpr a && e2 instanceof AddXExpr b && b.right instanceof ValXExpr br) {
|
|
return new AddXExpr( new ValXExpr(a.value + br.value), b.left );
|
|
}
|
|
else if (e1 instanceof ValXExpr a && e2 instanceof AddXExpr b && b.left instanceof ValXExpr bl) {
|
|
return new AddXExpr( new ValXExpr(a.value + bl.value), b.right );
|
|
}
|
|
else {
|
|
return new AddXExpr(e1,e2);
|
|
}
|
|
}
|
|
else if (e instanceof MulXExpr x) {
|
|
XExpr e1 = const_folding(x.left);
|
|
XExpr e2 = const_folding(x.right);
|
|
if (e1 instanceof ValXExpr a && e2 instanceof ValXExpr b) {
|
|
return new ValXExpr(a.value * b.value );
|
|
}
|
|
else if (e1 instanceof ValXExpr a && e2 instanceof MulXExpr b && b.right instanceof ValXExpr br) {
|
|
return new MulXExpr( new ValXExpr(a.value * br.value), b.left );
|
|
}
|
|
else if (e1 instanceof ValXExpr a && e2 instanceof MulXExpr b && b.left instanceof ValXExpr bl) {
|
|
return new MulXExpr( new ValXExpr(a.value * bl.value), b.right );
|
|
}
|
|
else {
|
|
return new MulXExpr(e1,e2);
|
|
}
|
|
}
|
|
else return e;
|
|
}
|
|
|
|
static long eval( XExpr e ) {
|
|
if (e instanceof VarXExpr x) {
|
|
return 0;
|
|
}
|
|
else if (e instanceof ValXExpr x) {
|
|
return x.value;
|
|
}
|
|
else if (e instanceof AddXExpr x) {
|
|
return eval(x.left) + eval(x.right);
|
|
}
|
|
else if (e instanceof MulXExpr x) {
|
|
return eval(x.left) * eval(x.right);
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public static void main(String args[])
|
|
{
|
|
XExpr e = mk_expr(Integer.parseInt(args[0]),1);
|
|
long v1 = eval(e);
|
|
long v2 = eval(const_folding(reassoc(e)));
|
|
System.out.println( v1 + ", " + v2 );
|
|
}
|
|
}
|