Created
September 1, 2017 03:12
-
-
Save kurgm/c6a8b201c9cf42c3357bee14b24a2857 to your computer and use it in GitHub Desktop.
TSG第3回コードゴルフ大会-Unreadable
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
// 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