Problem:
問題名 Zero division checker

森下さんは困っていました... 姉原さんにプログラムを書いてもらったのですが、そのプログラムがクラッシュするのです。

姉原さんに書いてもらったのは、逆ポーランド記法の式を読んで、その計算結果を出力するプログラムで、クラッシュログによると、 0 で割り算をしてしまったのが原因のようです。これは、森下さんが間違った式を入力してしまったからかもしれませんし、もしかしたら、もしかしたら、姉原さんの書いたプログラムにバグがあるのかもしれません。

姉原さんの書いたプログラムを読んでみようと思いましたが、姉原さんのプログラムはアセンブリというよくわからないことばで書かれているようで、見ているだけで頭がガンガンしてきます。

そこで、森下さんはあなたに、式が間違っていないかどうか調べるプログラムを書いてもらうことにしました。式が間違っている、とは、その式に従って計算すると、 0 での割り算をしてしまう可能性のあることをいいます。

なお、姉原さんの書いたコードはとてもふるいコンピューターで動くもので、加減乗除は整数で行い、結果は 8 bit の符号なし整数として保存されます。
例えば、255+1 は 0 になってしまうし、3/2 は 1 になります。

あ、姉原さんにはないしょですよ。

(参考)逆ポーランド記法で表された式を計算する、擬似コード

s = 空のスタック
n = 式の要素数
for i in 1..n:
if 式のi番目の要素が整数:
sにその整数をプッシュする
if 式のi番目の要素が変数:
sにその変数の値をプッシュする
if 式のi番目の要素が演算子:
sから値をポップし、bとする
sから値をポップし、aとする
if 演算子が'+':
r = (a + b) % 256 とする
if 演算子が'-':
r = (a - b + 256) % 256 とする
if 演算子が'*':
r = (a * b) % 256 とする
if 演算子が'/':
r = (a / b) % 256 とする
sにrをプッシュする
sから値をポップし、式の計算結果とする

Input

m

name1 lb1 ub1

...

namem lbm ubm

n

e1 e2 ... en

0 ≤ m ≤ 100

0 ≤ lbi ≤ ubi ≤ 255

1 ≤ namei (1 ≤ i ≤ m) の長さ ≤ 20

1 ≤ n ≤ 100

m は変数の数、namei, lbi, ubi はそれぞれ変数iの名前、下限、上限を表します。

n は式に含まれる要素の数を表し、ei は式の i 番目の要素を表します。

各変数は式の中に高々1回しか現れません。

Output

式が間違っているときにはerror、間違っていないときにはcorrectと一行で出力してください。

Sample Input 1

1
a 1 10
3
10 a /

Output for the Sample Input 1

correct

Sample Input 2

2
a 1 10
b 1 10
5
1 a b - /

Output for the Sample Input 2

error

Sample Input 3

1
a 0 255
7
1 a 2 * 1 + /

Output for the Sample Input 3

correct

Solution in JAVA (judge verdict: Accepted)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.lang.ArithmeticException;

import static java.lang.Integer.parseInt;

/**
 * Zero Division Checker
 */
public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String line;
		String[] words;

		Main main = new Main();

		Map<String, Mono> vars = new HashMap<>();

		//
		int m = parseInt(br.readLine());
		for (int i = 0; i < m; i++) {
			words = br.readLine().split(" ");
			vars.put(
					words[0],
					main.new Mono(
							parseInt(words[1]),
							parseInt(words[2])
					)
			);
		}

		//parse
		int n = parseInt(br.readLine());
		StringTokenizer st = new StringTokenizer(br.readLine());
		Deque<Exp> stack = new ArrayDeque<>();

		for (int i = 0; i < n; i++) {
			String e = st.nextToken();
			if ("+-*/".contains(e)) {
				Exp a, b;
				b = stack.pop();
				a = stack.pop();
				switch (e) {
					case "+":
						stack.push(main.new Bino(a, b, main.new Add()));
						break;
					case "-":
						stack.push(main.new Bino(a, b, main.new Subtract()));
						break;
					case "*":
						stack.push(main.new Bino(a, b, main.new Multiply()));
						break;
					case "/":
						stack.push(main.new Bino(a, b, main.new Divide()));
						break;
				}
			} else {
				if (vars.containsKey(e)) {
					stack.push(vars.get(e));
				} else {
					stack.push(main.new Mono(parseInt(e)));
				}
			}
		}

		//solve
		Exp exp = stack.pop();
		try {
			exp.eval();
			System.out.println("correct");
		} catch (ArithmeticException ex) {
			System.out.println("error");
		}
	}

	//Element
	interface Elm {
	}

	//Operator
	interface Op extends Elm {
		int eval(int a, int b);
	}

	class Add implements Op {
		@Override
		public int eval(int a, int b) {
			return (a + b) % 256;
		}
	}

	class Subtract implements Op {
		@Override
		public int eval(int a, int b) {
			return (a - b + 256) % 256;
		}
	}

	class Multiply implements Op {
		@Override
		public int eval(int a, int b) {
			return (a * b) % 256;
		}
	}

	class Divide implements Op {
		@Override
		public int eval(int a, int b) {
			return (a / b) % 256;
		}
	}

	//
	interface Exp extends Elm {
		Exp eval();

		int lb();

		int ub();
	}

	class Mono implements Exp {
		int lb, ub;

		Mono(int lb) {
			this(lb, lb);
		}

		Mono(int lb, int ub) {
			this.lb = lb;
			this.ub = ub;
		}

		public Mono eval() {
			return this;
		}

		public int lb() {
			return lb;
		}

		public int ub() {
			return ub;
		}
	}

	class Bino implements Exp {
		int lb = 256, ub = -1;
		Exp a, b;
		Op op;

		Bino(Exp a, Exp b, Op op) {
			this.a = a;
			this.b = b;
			this.op = op;
		}

		public Exp eval() {

			if (a instanceof Bino) a.eval();
			if (b instanceof Bino) b.eval();

			int alb, aub;
			int blb, bub;
			alb = a.lb();
			aub = a.ub();
			blb = b.lb();
			bub = b.ub();

			for (int i = alb; i <= aub; i++) {
				for (int j = blb; j <= bub; j++) {
					int r = op.eval(i, j);
					lb = Math.min(lb, r);
					ub = Math.max(ub, r);
				}
			}
			return new Mono(lb, ub);
		}

		public int lb() {
			return lb;
		}

		public int ub() {
			return ub;
		}
	}
}