Four Four's(awk)
[問題] Four Four's 数字 4 を 4 つと+, -, ×, ÷, (, ) を使って、答えが 1 から 10 になる式を作りなさい。 数字は 4 だけです。
なかなか難問です。
perlにはevalがありますが、awkにはevalのようなものはありませんので、逆ポーランド記法を実装して解きます。
この逆ポーランド記法も馴染みがないですが、以下ソースです。
#!/usr/bin/gawk -f BEGIN{ # 真偽値の定義 TRUE = 1; FALSE = 0; Num = 0; # スタックに保持している個数 solve4(); } function solve4(){ operator[0] = "+"; operator[1] = "-"; operator[2] = "*"; operator[3] = "/"; for (x = 0; x <= 3; x++){ for (y = 0; y <= 3; y++){ for(z = 0; z <= 3; z++){ expr[0] = 4 4 operator[y] 4 4 operator[z] operator[x]; expr[1] = 4 4 4 4 operator[z] operator[y] operator[x]; expr[2] = 4 4 operator[z] 4 operator[y] 4 operator[x]; expr[3] = 4 4 4 operator[z] 4 operator[y] operator[x]; expr[4] = 4 4 4 operator[z] operator[y] 4 operator[x]; for(e in expr){ result = eval(expr[e]); if(result == int(result) && result >= 1 && result <= 10){ printf "%d%s",result,":"; if(e == 0){ print "(" 4 operator[y] 4 ")" operator[x] "(" 4 operator[z] 4 ")"; }else if(e == 1){ print 4 operator[x] "(" 4 operator[y] "(" 4 operator[z] 4 "))"; }else if(e == 2){ print "((" 4 operator[z] 4 ")" operator[y] 4 ")" operator[x] 4; }else if(e == 3){ print 4 operator[x] "((" 4 operator[z] 4 ")" operator[y] 4 ")"; }else{ print "(" 4 operator[y] "(" 4 operator[z] 4 "))" operator[x] 4; } } } } } } } function eval(cal){ max = split(cal,a,""); for(i = 1; i <= max; i++){ if(a[i] ~ /[0-9]+/){ push(stack,a[i]); } if(a[i] ~ /[+-/*]/){ calc(get_ope(a[i]),stack); } } return stack[Num-1]; } function push(stack,input){ stack[Num] = input; Num++; } function pop(stack){ Num--; return stack[Num]; } function get_ope(char){ if(match(char,/+/)){ return -1; } if(match(char,/-/)){ return -2; } if(match(char,/*/)){ return -3; } if(match(char,/\//)){ return -4; } } function calc(ope,stack){ n1 = pop(stack); n2 = pop(stack); switch(ope){ case -1: push(stack,n2+n1); break; case -2: push(stack,n2-n1); break; case -3: push(stack,n2*n1); break; case -4: if(n1 == 0){ break; } push(stack,n2/n1); break; default: print "ERR!"; exit; } }
重複チェックは未実装です。
興味ある方は一度作ってみて下さい。