Skip to content

Instantly share code, notes, and snippets.

@kurgm
Created September 1, 2017 03:12
Show Gist options
  • Save kurgm/c6a8b201c9cf42c3357bee14b24a2857 to your computer and use it in GitHub Desktop.
Save kurgm/c6a8b201c9cf42c3357bee14b24a2857 to your computer and use it in GitHub Desktop.
TSG第3回コードゴルフ大会-Unreadable
// See also: https://github.com/hakatashi/esolang-battle/wiki/%E7%AC%AC3%E5%9B%9E%E3%82%B3%E3%83%BC%E3%83%89%E3%82%B4%E3%83%AB%E3%83%95%E5%A4%A7%E4%BC%9A-WriteUp
// I/O
const vars: { [key: number]: number } = {};
let outbuf = "";
function output(c: number) {
outbuf += String.fromCharCode(c);
}
let inbuf = "";
let inbufidx = 0;
function input() {
if (inbufidx >= inbuf.length) {
return -1;
}
return inbuf.charCodeAt(inbufidx++);
}
// ====================================
interface Expr {
eval(): number;
toString(): string;
}
/** Print X as a Unicode character and return X. */
function uprint(X: Expr) { return new Print(X); }
class Print implements Expr {
constructor(private X: Expr) { }
eval() {
const ret = this.X.eval();
output(ret);
return ret;
}
toString() {
return "'" + '"' + this.X;
}
}
/** Return X + 1. */
function uinc(X: Expr) { return new Inc(X); }
class Inc implements Expr {
constructor(private X: Expr) { }
eval() {
return this.X.eval() + 1;
}
toString() {
return "'" + '""' + this.X;
}
}
/** Return 1. */
function uone() { return new One(); }
class One implements Expr {
constructor() { }
eval() {
return 1;
}
toString() {
return "'" + '"""';
}
}
/** Do both X and Y and return what Y returned. */
function udo(X: Expr, Y: Expr) { return new Do(X, Y); }
class Do implements Expr {
constructor(private X: Expr, private Y: Expr) { }
eval() {
this.X.eval();
return this.Y.eval();
}
toString() {
return "'" + '""""' + this.X + this.Y;
}
}
/** Do Y while X is not 0 and return the last result. */
function uwhile(X: Expr, Y: Expr) { return new While(X, Y); }
class While implements Expr {
constructor(private X: Expr, private Y: Expr) { }
eval() {
let ret;
while (this.X.eval()) {
ret = this.Y.eval();
}
if (ret === undefined) {
throw new Error("While's body must be executed"); // kuso
}
return ret;
}
toString() {
return "'" + '"""""' + this.X + this.Y;
}
}
/** Set variable number X to Y and return Y. */
function uset(X: Expr, Y: Expr) { return new Set_(X, Y); }
class Set_ implements Expr {
constructor(private X: Expr, private Y: Expr) { }
eval() {
const y = this.Y.eval();
vars[this.X.eval()] = y;
return y;
}
toString() {
return "'" + '""""""' + this.X + this.Y;
}
}
/** Return the value of variable X, or 0 if the variable has never been assigned. */
function uget(X: Expr) { return new Get(X); }
class Get implements Expr {
constructor(private X: Expr) { }
eval() {
const x = this.X.eval();
if (x in vars) {
return vars[x];
}
return 0;
}
toString() {
return "'" + '"""""""' + this.X;
}
}
/** Return X - 1. */
function udec(X: Expr) { return new Dec(X); }
class Dec implements Expr {
constructor(private X: Expr) { }
eval() {
return this.X.eval() - 1;
}
toString() {
return "'" + '""""""""' + this.X;
}
}
/** If X is not 0 do Y else do Z. Return what Y/Z returned. */
function uif(X: Expr, Y: Expr, Z: Expr) { return new If(X, Y, Z); }
class If implements Expr {
constructor(private X: Expr, private Y: Expr, private Z: Expr) { }
eval() {
if (this.X.eval()) {
return this.Y.eval();
}
return this.Z.eval();
}
toString() {
return "'" + '"""""""""' + this.X + this.Y + this.Z;
}
}
/** Return a single Unicode character which has been read from stdin, or -1 if stdin is exhausted. */
function uin() { return new In(); }
class In implements Expr {
constructor() { }
eval() {
return input();
}
toString() {
return "'" + '""""""""""';
}
}
// Utilities
function num(n: number): Expr {
if (n === 1) return uone();
return uinc(num(n - 1));
}
function progn(...exprs: Expr[]): Expr {
if (exprs.length >= 2) {
return udo(exprs[0], progn(...exprs.slice(1)));
}
return exprs[0];
}
function debug(expr: Expr, marker?: string) { return new Debug(expr, marker); }
class Debug implements Expr {
constructor(private expr: Expr, private marker?: string) { }
eval() {
console.log(this.marker || "DEBUG", "step in")
const ret = this.expr.eval();
console.log(this.marker || "DEBUG", "out:", ret);
return ret;
}
toString() {
return this.expr.toString();
}
}
// ====================================
inbuf = `00100011
10101011
01001110
01001010
10000000
00110111
01111000
00000011
10011001
11111101
11011110
10111110
10110111
01111010
00000100
01111100
00001111
11001000
10100000
00110001
00000011
00010101
00101101
10001000
11010110
00000000
11010100
10101111
00000001
11101100
01111001
00100111
01011011
01100001
01010101
01000010
00001010
00000110
10010011
01101001
00011100
11100111
11111001
00100100
00110111
11010010
00111100
11111110
01110010
01101111
`;
// Memory pointers
const v_in = num(1);
const v_in2 = num(2);
const v_8 = num(3);
const v_48 = num(5);
const v_48_2 = num(4);
const v_i = num(4);
const v_i2 = num(6);
const v_23 = num(3);
const expr: Expr = uwhile(
progn(
uset(v_8, num(9)),
uset(v_in, udec(uone())),
uwhile(
uset(v_8, udec(uget(v_8))),
progn(
uset(v_in2, uget(v_in)),
uif(
uget(v_in2),
uwhile(
uget(v_in2),
progn(
uset(v_in2, udec(uget(v_in2))),
uset(v_in, uinc(uget(v_in)))
)
),
uone()
),
uif(
uinc(uset(v_in2, uin())),
progn(
uset(v_48_2, uset(v_48, num(48))),
uwhile(
uset(v_48_2, udec(uget(v_48_2))),
uset(v_in2, udec(uget(v_in2))),
),
uwhile(
uinc(uset(v_in2, udec(uget(v_in2)))),
uset(v_in, uinc(uget(v_in)))
),
uset(v_in, udec(uget(v_in)))
),
uone()
)
)
),
uinc(uin())
),
progn(
uset(v_i, uone()),
uset(v_23, num(24)),
uif(
uget(v_in),
uwhile(
uif(
uget(v_in),
uset(v_23, udec(uget(v_23))),
uget(v_in)
),
progn(
uset(v_i, uinc(uset(v_i2, uget(v_i)))),
uwhile(
uinc(uset(v_i2, udec(uget(v_i2)))),
uset(v_in, udec(uget(v_in)))
)
)
),
uone()
),
uprint(
uif(
uget(v_in),
uget(v_48),
uinc(uget(v_48))
)
)
)
);
console.log("expr=", expr.toString());
console.log("inbuf=", inbuf);
console.log("return=", expr.eval());
console.log("outbuf=", outbuf);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment