C=_=>z=[t=x*y/100,x/y,x/y*100,,,x*y,t,,,x-y,x-t,,,x+y,x+t][o-16];F=k=>{k>12&k!=27?(k<17?(s-3?z/=100:C(y=z,++o),s=8):k-28?(s-3||C(y=z),x=z,s=1,o=k):(s&1?C(y=s&2?z:x):o&&C(x=z),s=8),V=z.toFixed(),N=V.length-(z<0),1/z&&N<=D?(v=N<D?z.toFixed(D-N).replace(/\.?0+$/,E):V,d=V!=v,v=+v?v:Z):(d=s=0,v="E")):(k<D|k==27?s&2?n-m<D&&(k>9?p=!d:v=(p?(p=0,d=1,v+P):d|+v?v:E)+k):([v,p]=k>9?[Z,1]:[k+E,0],d=0,s=2|s&1):k<11?(s=j-D?s-3?2:3:(o=0,2),d=p=0,v=Z="0"):k<12?s&2&&(v=v.slice(0,v.slice(-2)[0]==P?(d=0)-2:-1),v=!v|v!=+v|v=="-0"?Z:v,p=0):s&&v!=Z&&(v=m?v.slice(1):"-"+v),z=+v);j=k;m=v[0]=="-";l=v.length;n=l-d;O=E;for(i=n-11;i<l;)O+=(v[i++]||" ").big()+(v[i]==P|i==l&!d?i++&&P:" ").small();b.innerHTML=`<center><div> <pre>${O}</pre><p>${K}<style>div{width:14.5em;font:4vh/2.5 s;border:solid;user-select:none}pre{background:#bd9;padding:1em 0}a{width:23%;display:inline-block;cursor:pointer}a:hover{background:#fe9}`};F(j=D=10,K=E="",P=".",["C/AC","⌫","+/–",..."%789÷456×123−0.=+"].map((k,i)=>K+=`<a onclick=F(${k<D?k:i+D})>`+k))
/**
* CALC-1K by Andrés Moreno (an3moreno@gmail.com)
*
* This is a commented version of my submission to the JS1k 2018 competition.
* It uses the same 1-character variables, as they are descriptive enough :)
*/
var b = document.body;
window["F"] = F; // export for Closure Compiler
const D = 10; // maximum displayed digits
const E = "";
const Z = "0";
const P = ".";
/**
* Calculator states.
* @enum
*/
var State = {
ERR : 0, // error
OP : 0b0001, // operation key pressed
IN1 : 0b0010, // entering first input
IN2 : 0b0011, // entering second input
RES : 0b1000 // showing result
};
/**
* Non-digit key codes (digits use their value as key code).
* @enum
*/
var Key = {
CLEAR : 10, // C/AC (clear entry/clear all)
BS : 11, // Backspace
SIGN : 12, // change sign
PERCENT : 13, // %
DIV : 17, // ÷
MUL : 21, // ×
SUB : 25, // −
DOT : 27, // .
EQUALS : 28, // =
ADD : 29 //
};
/**
* Operation codes.
* For the 4 basic operations (DIV/MUL/SUB/ADD), these are the same as the key code.
* Percent operations (PER_*) start with a basic operation but you press % instead of =.
* Example: [6] [÷] [1][0] [%] gives "60" (6 as a percentage of 10 is 60).
* @enum
*/
var Op = {
DIV : 17,
PER_DIV : 18, // x as pecentage of y
MUL : 21,
PER_MUL : 22, // y percent of x
SUB : 25,
PER_SUB : 26, // discount
ADD : 29,
PER_ADD : 30 // markup
};
var /**State*/ s; // current state
var /**Op*/ o; // current operation
var /**number*/ p; // 1 if last key pressed was the decimal point, 0 otherwise
var /**number*/ x; // first operand
var /**number*/ y; // second operand
var /**number*/ z; // result
var /**string*/ v; // displayed value (current input or result)
var /**string*/ V; // integer part of displayed value
var /**number*/ n; // displayed value size (including sign, excluding decimal point)
var /**number*/ N; // displayed value's integer part size (excluding sign)
var /**number*/ m; // 1 if value has a minus sign, 0 otherwise
var /**number*/ d; // 1 if value has decimals, 0 otherwise
var /**string*/ K; // HTML for the keys (A elements)
var /**Key*/ j; // last key pressed (used for C/AC key)
//
// Create HTML for keys (A elements auto-close when a new <A> tag is found)
//
K = "",
["C/AC", "⌫", " /–", ..."%789÷456×123−0.= "].map(
(k, i) => K = `<a onclick=F(${k<D ? k : i D})>` k
);
//
// Start the calculator
//
F(j = Key.CLEAR);
/**
* Calculates the current operation with x and y and stores the result.
*/
function C()
{
var /**number*/ t; // temp variable
// All operations are calculated, we just "select" the right one
t = x*y/100;
z = [x/y, x/y*100, , , x*y, t, , ,x-y, x-t, , ,x y, x t][o - Op.DIV];
}
/**
* Key handler function. Rewrites BODY on every call.
* @param {Key} k Current key pressed.
*/
function F(k)
{
var /**number*/ l; // total length of displayed value
var /**string*/ O; // HTML for display output
var i;
//
// Can you disentangle the following expression?!
//
k > 12 & k != 27 ? (
k < 17 ? (
s - 3 ? z /= 100 : C(y = z, o),
s = 8
) : k - 28 ? (
s - 3 || C(y = z),
x = z,
s = 1,
o = k
) : (
s & 1 ? C(y = s & 2 ? z : x) : o && C(x = z),
s = 8
),
V = z.toFixed(),
N = V.length - (z < 0),
1 / z && N <= D ? (
v = N < D ? z.toFixed(D - N).replace(/\.?0 $/, E) : V,
d = V != v,
v = v ? v : Z
) : (
d = s = 0,
v = "E"
)
) : (
k < D | k == 27 ?
s & 2 ?
n - m < D && (
k > 9 ?
p = !d
:
v = (p ? (p = 0, d = 1, v P) : d | v ? v : E) k
) : (
[v,p] = k > 9 ? [Z, 1] : [k E, 0],
d = 0,
s = 2 | s & 1
) :
k < 11 ? (
s = j - D ? s - 3 ? 2 : 3 : (o = 0, 2),
d = p = 0,
v = Z
) :
k < 12 ?
s & 2 && (
v = v.slice(0, v.slice(-2)[0] == P ? (d = 0) - 2 : -1),
v = !v | v != v | v == "-0" ? Z : v,
p = 0
) :
s && v != Z && (
v = m ? v.slice(1) : "-" v
),
z = v
);
// Save last pressed key
j = k;
// Convert the current value to display output in HTML using BIG and SMALL elements
m = v[0] == "-";
l = v.length;
n = l - d;
O = E;
for (i = n - 11; i < l; ) {
O = (v[i ] || " ").big() // sign/digit or space
(v[i] == P | i == l & !d ? i && P : " ").small(); // decimal point or space
}
// Update the BODY element with some HTML soup (PRE implements display, P implements keys)
// The STYLE element ends up in the last key's A element, but that's OK with browsers
// Apart from that, unclosed elements (all but PRE) auto-close just fine
b.innerHTML = `<center><div> <pre>${O}</pre><p>${K}<style>div{width:14em;font:4vh/2.5 s;border:solid;user-select:none}pre{background:#bd9;padding:1em 0}a{width:22%;display:inline-block;cursor:pointer}a:hover{background:#fe9}`;
}