// -*- coding: utf-8 -*-
//Array.prototype._toString = Array.prototype.toString;
//Array.prototype.toString = function() {
//  return "[" + this._toString() + "]";
//}
function Expr(l0, l1, type) {
  this.l0 = l0;
  this.l1 = l1;
  this.type = type;
  if(type == 0) {
    this.level = 1;
    this.n = l0.n*l1.d + l1.n*l0.d;
    this.d = l0.d * l1.d;
  } else if(type == 1) {
    this.level = 1;
    this.n = l0.n*l1.d - l1.n*l0.d;
    this.d = l0.d * l1.d;
  } else if(type == 2) {
    this.level = 2;
    this.n = l0.n * l1.n;
    this.d = l0.d * l1.d;
  } else if(type == 3) {
    this.level = 2;
    this.n = l0.n * l1.d;
    this.d = l0.d * l1.n;
  }
  if(this.d==0 || this.level == l1.level) {
    return {type:null};
  }
  this.normalize();
}
Expr.prototype.toString = function(par_level) {
  var ret = this.l0.toString(this.level) + ["+","-","*","/"][this.type] + this.l1.toString(this.level);
  if(par_level && par_level > this.level) {
    return "(" + ret + ")";
  } else {
    return ret;
  }
}
Expr.prototype.normalize = function() {
  var x = this.n, y = this.d;
  while(y!=0) {
    var t = x%y; x = y; y = t;
  }
  this.n /= x;
  this.d /= x;
  if(this.d < 0) {
    this.n = -this.n;
    this.d = -this.d;
  }
}
function fcmp(x, y) {
  return x.n*y.d - y.n*x.d;
}

$(function(){
  var str = "123456789";
  var n = str.length;
  var dp_max = 6;
  var dp = null;
  $("#calcbutton").click(function() {
    if(dp == null) {
      dp = []
      for(var len = 1; len <= n; len++) {
        dp[len] = [];
        for(var off = 0; off+len <= n; off++) {
          var num_str = str.substr(off, len);
          var num = parseInt(num_str);
          dp[len][off] = [{n: num, d: 1, s:num_str, toString: function(x) {return this.s;}, level:-1 }];
          if(len>dp_max)continue;
          for(var mlen = 1; mlen < len; mlen++) {
            for(var i = 0; i < dp[mlen][off].length; i++) {
              for(var j = 0; j < dp[len-mlen][off+mlen].length; j++) {
                var l0 = dp[mlen][off][i];
                var l1 = dp[len-mlen][off+mlen][j];
                for(var type = 0; type < 4; type++) {
                  var p = new Expr(l0, l1, type); if(p.type!=null) dp[len][off].push(p);
                }
              }
            }
          }
          dp[len][off].sort(fcmp);
        }
      }
    }
    var find = function(targ, off, len, callback) {
      targ.level = 6;
      var imax = dp[len][off].length;
      var imin = -1;
      while(imax-imin>1) {
        var ihalf = Math.floor((imax+imin)/2);
        if(fcmp(dp[len][off][ihalf], targ) >= 0) {
          imax = ihalf;
        } else {
          imin = ihalf;
        }
      }
      for(var i = imax; i<dp[len][off].length; i++) {
        if(fcmp(dp[len][off][i], targ) > 0) break;
        callback(dp[len][off][i]);
      }
      if(len <= dp_max) return;
      for(var mlen = 1; mlen < len; mlen++) {
        if(mlen < len-mlen) {
          // ex) 1+( ... ) == 10
          for(var i = 0; i < dp[mlen][off].length; i++) {
            var invs = [
                new Expr(targ, dp[mlen][off][i], 1),
                new Expr(dp[mlen][off][i], targ, 1),
                new Expr(targ, dp[mlen][off][i], 3),
                new Expr(dp[mlen][off][i], targ, 3),
              ];
            for(var j = 0; j < 4; j++) {
              if(invs[j].type != null) find(invs[j], off+mlen, len-mlen, function(val) {
                  var expr = new Expr(dp[mlen][off][i], val, j);
                  if(expr.type != null) callback(expr);
                });
            }
          }
        } else {
          // ex) ( ... )+4 == 10
          for(var i = 0; i < dp[len-mlen][off+mlen].length; i++) {
            var invs = [
                new Expr(targ, dp[len-mlen][off+mlen][i], 1),
                new Expr(targ, dp[len-mlen][off+mlen][i], 0),
                new Expr(targ, dp[len-mlen][off+mlen][i], 3),
                new Expr(targ, dp[len-mlen][off+mlen][i], 2),
              ];
            for(var j = 0; j < 4; j++) {
              if(invs[j].type != null) find(invs[j], off, mlen, function(val) {
                  var expr = new Expr(val, dp[len-mlen][off+mlen][i], j);
                  if(expr.type != null) callback(expr);
                });
            }
          }
        }
      }
    }
    $("#exprview").text("");
    var targ;
    var targ_str = $("#numinput").val();
    var targ_match;
    var use_brace = $("#use_brace").attr("checked");
    var use_decimal_cat = $("#use_decimal_cat").attr("checked");
    if(targ_match = /(-?\d+)\/(-?\d+)/.exec(targ_str)) {
      targ = {n: parseInt(RegExp.$1), d: parseInt(RegExp.$2)};
      targ.normalize = Expr.prototype.normalize;
      targ.normalize();
    } else {
      targ = {n: parseInt(targ_str), d: 1};
    }
    find(targ, 0, n, function(val) {
      var str = val.toString();
      if(!use_brace && str.match(/\(/))return;
      if(!use_decimal_cat && str.match(/[0-9]{2}/))return;
      $("#exprview").append(str + "<br/>");
    });
  });
});


