Skip to content

Instantly share code, notes, and snippets.

@martinusadyh
Last active August 29, 2015 14:03
Show Gist options
  • Save martinusadyh/8f7a9c77825474aef483 to your computer and use it in GitHub Desktop.
Save martinusadyh/8f7a9c77825474aef483 to your computer and use it in GitHub Desktop.
Implementasi Shunting-Yard Algorithm
// Implementasi custom calculator dengan menggunakan algoritma Shunting-Yard
// Referensi Algoritma : http://en.wikipedia.org/wiki/Shunting-yard_algorithm
// Contoh : http://www.chris-j.co.uk/parsing.php
// Custom calculator untuk melakukan conversi rumus menjadi nilai akhir
// @param String rumus: Informasi tentang rumus yang ingin dihitung.
// Contoh rumus adalah :
// - a+b*c
// - ((a+b)*c*d/(e+f))
// - a/b/c*d
//
// @param Object object: Informasi object dengan property-property yang tertulis
// pada rumus. Contoh :
// var obj = {
// a: 11,
// b: 12,
// c: 13,
// d: 2,
// e: 11,
// f: 2
// };
//
// Contoh cara penggunaan :
// Rumus : ((a+b)*c*d/(e+f))
// Object:
// var obj = {
// a: 11,
// b: 12,
// c: 13,
// d: 2,
// e: 11,
// f: 2
// };
// Penggunaan : hitung("((a+b)*c*d/(e+f))", obj);
//
// @return nilai object BigDecimal
function hitung(rumus, objValue) {
var resultAkhir;
var infix = new Array();
var output = new Array();
var token = new Array();
var foundKey = false;
for (var i=0; i<rumus.length; i++) {
foundKey = false;
var value = null;
for (var key in objValue) {
if (rumus[i] === key) {
rumus.replace(rumus[i], objValue[key]);
value = objValue[key];
foundKey = true;
break;
}
}
if (!foundKey) {
infix.push(rumus[i]);
} else {
infix.push(new BigDecimal(String(value)));
}
} // end for i
for (var i=0; i<infix.length; i++) {
if (typeof infix[i] === 'object') {
output.push(infix[i]);
} else {
switch(infix[i]) {
case '(':
token.push(infix[i]);
break;
case ')':
var done = true;
do {
var tmpToken = token.pop(); // ambil token terakhir
if (tmpToken === "(") {
done = false;
} else {
output.push(tmpToken);
}
} while (done);
break;
case '-':
var tmpToken = token.pop(); // ambil token terakhir
if (tmpToken === "+") {
output.push(tmpToken);
} else {
token.push(tmpToken);
}
token.push(infix[i]);
break;
case '+':
var tmpToken = token.pop(); // ambil token terakhir
if (tmpToken === "-") {
output.push(tmpToken);
} else {
token.push(tmpToken);
}
token.push(infix[i].toString());
break;
case '*':
var tmpToken = token.pop(); // ambil token terakhir
if (tmpToken === "/") {
output.push(tmpToken);
} else {
token.push(tmpToken);
}
token.push(infix[i]);
break;
case '/':
var tmpToken = token.pop(); // ambil token terakhir
if (tmpToken === "*") {
output.push(tmpToken);
} else {
token.push(tmpToken);
}
token.push(infix[i]);
break;
default: console.log("");
}
}
} // end for
// pengecekan stack token, jika msh ada sisa masukkan ke output
if (token.toString().length > 0) {
var isExists = true;
do {
if (token.toString().length > 0) {
var tmpToken = token.pop();
output.push(tmpToken);
} else {
isExists = false;
}
} while(isExists);
}
if (token.toString().length === 0) {
// keluarin semua yang di output masukkan ke token
for (var i=0; i<output.length; i++) {
if (typeof output[i] === "object") {
token.push(output[i]);
} else {
switch(output[i]) {
case '-':
var valAkhir = token.pop();
var valAwal = token.pop();
var valFinal = valAwal.subtract(valAkhir);
token.push(valFinal);
break;
case '+':
var valAkhir = token.pop();
var valAwal = token.pop();
var valFinal = valAwal.add(valAkhir);
token.push(valFinal);
break;
case '*':
var valAkhir = token.pop();
var valAwal = token.pop();
var valFinal = valAwal.multiply(valAkhir);
token.push(valFinal);
break;
case '/':
var valAkhir = token.pop();
var valAwal = token.pop();
var valFinal = valAwal.divide(valAkhir, 16, 4);
token.push(valFinal);
break;
default: console.log("");
} // end switch
} // end else
} // end for
} // end if token
for (var j=0; j<token.length; j++) {
if (typeof token[j] === "object") {
resultAkhir = token[j];
}
}
return resultAkhir;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment