小さい頃はエラ呼吸

いつのまにやら肺で呼吸をしています。


4つの数字を四則演算して10をつくる(JavaScript版)

はじめに

同僚に「1、1、9、9」の4つの数字を四則演算して10をつくれるかという問題を出されて、30分くらい考えたけど、結局解けませんでした。
Googleで調べればすぐに答えは分かるのですが、それではおもしろくないのでJavaScriptで力技で計算するプログラムを作ってみました。

作成する際のポイント

アルゴリズムが分からなくて非常に苦労しましたが、以下のサイトに非常に詳しく書いてあります。perlのサンプルコードもあります。

4つの数字を a,b,c,d とし、四則演算子を op1,op2,op3 と表したとき、
それらを組み合わせて出来る計算式は次の通りである。

*1 op3 d
a op1 *2
あとは、重複しない1〜9までの4つの数字の順列に

  1. ,-,*,/ の複数使用可能な4つの演算子の中から3つの順列を当てはめて、

それぞれ a〜d,op1〜op3 とし、上の5つの式を計算して 10 になることを確かめればよい。
めも日記(2004-08-28) はてなブックマーク - めも日記(2004-08-28)

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>4つの数字で10にする</title>
<script src="calc.js"></script>
</head>
<body>
<form>
  <input type="text" id="value1" value="4">
  <input type="text" id="value2" value="6">
  <input type="text" id="value3" value="3">
  <input type="text" id="value4" value="7">
  <input type="button" id="calc" value="計算する">
  <div id="result">
  </div>
</form>
</body>
</html>
Javascript
var calc = {
  n1:"",
  n2:"",
  n3:"",
  n4:"",
  calculate: function() {
    var number = Array(this.n1, this.n2, this.n3, this.n4);
    var usedNumber;
    var tmp = "";
    var n1, n2, n3, n4;
    var countN1 = getCount(number, this.n1);
    var countN2 = getCount(number, this.n2);
    var countN3 = getCount(number, this.n3);
    var countN4 = getCount(number, this.n4);
    
    for (var i = 0, len = number.length; i < len; i++) {
      n1 = number[i];
      usedNumber = new Array(4);
      usedNumber[0] = n1;
      for (var j = 0; j < len; j++) {
        n2 = number[j];
        usedNumber[1] = n2;
        for (var k = 0; k < len; k++) {
          n3 = number[k];
          usedNumber[2] = n3;
          for (var l = 0; l < len; l++) {
            n4 = number[l];
            usedNumber[3] = n4;
            // 数字の個数を数えて全部そろったら演算する
            if (getCount(usedNumber, this.n1) === countN1) {
              if (getCount(usedNumber, this.n2) === countN2) {
                if (getCount(usedNumber, this.n3) === countN3) {
                  if (getCount(usedNumber, this.n4) === countN4) {
                    tmp += calculateEx(n1, n2, n3, n4);
                  }
                }
              }  
            }
          }
        }
      }
    }
    return tmp;
    
    function getCount(array, x) {
      var count = 0;
      for (var i = 0, len = array.length; i < len; i++) {
        if (array[i] === x) {
          count++;
        }
      }
      return count;
    }
    
    function calculateEx(n1, n2, n3, n4) {
      var enzanshi = Array("+", "-", "*", "/");
      var opt1, opt2, opt3, shiki, answer;
      var tmp = "";
      
      for (var i = 0, len = enzanshi.length; i < len; i++) {
        opt1 = enzanshi[i];
        for (var j = 0; j < len; j++) {
          opt2 = enzanshi[j];
          for (var k = 0; k < len; k++) {
            opt3 = enzanshi[k];
            
            // ((a op1 b) op2 c) op3 d
            shiki = "((" + n1 + opt1 + n2 + ")" + opt2 + n3 + ")" + opt3 + n4;
            if (answer === 10) {
              tmp += answer + " = " + shiki + "<br>";
            }
            
            // (a op1 b) op2 (c op3 d)
            shiki = "(" + n1 + opt1 + n2 + ")" + opt2 + "(" + n3 +opt3 + n4 + ")";
            answer = eval(shiki);
            if (answer === 10) {
              tmp += answer + " = " + shiki + "<br>";
            }
            
            // (a op1 (b op2 c)) op3 d
            shiki = "(" + n1 + opt1 + "(" + n2 + opt2 + n3 +"))" + opt3 + n4;
            answer = eval(shiki);
            if (answer === 10) {
              tmp += answer + " = " + shiki + "<br>";
            }
            
            // a op1 ((b op2 c) op3 d)
            shiki = n1 + opt1 + "((" + n2 + opt2 + n3 +")" + opt3 + n4 + ")";
            answer = eval(shiki);
            if (answer === 10) {
              tmp += answer + " = " + shiki + "<br>";
            }
  
            // a op1 (b op2 (c op3 d))
            shiki = n1 + opt1 + "(" + n2 + opt2 + "(" + n3 + opt3 + n4 + "))";
            answer = eval(shiki);
            if (answer === 10) {
              tmp += answer + " = " + shiki + "<br>";
            }
          }
        }
      }
      return tmp;
    }
  }
};

window.onload = function() {
  document.getElementById("calc").onclick = function() {
  calc.n1 = document.getElementById("value1").value;
  calc.n2 = document.getElementById("value2").value;
  calc.n3 = document.getElementById("value3").value;
  calc.n4 = document.getElementById("value4").value;
  document.getElementById("result").innerHTML = calc.calculate();
  alert("end");
  }
}

*1:a op1 b) op2 c) op3 d (a op1 b) op2 (c op3 d) (a op1 (b op2 c

*2:b op2 c) op3 d) a op1 (b op2 (c op3 d