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.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.Stack;

public class Main {
	InputStream is;

	boolean __FILE_DEBUG_FLAG__ = false;
	String __DEBUG_FILE_NAME__ = "src/T2";

	FastScanner in;
	PrintWriter out;
	
	boolean ans = true;
	
	class Elem {
		boolean[] can = new boolean[256];

		Elem() { }
		
		Elem(int lower, int upper) {
			for (int i = lower; i <= upper; i++) {
				can[i%256] = true;
			}
		}
		
		void set(int x) {
			can[x%256] = true;
		}

		Elem add(Elem e) {
			Elem res = new Elem();
			for (int i = 0; i < 256; i++) {
				if (!can[i]) continue;
				for (int j = 0; j < 256; j++) {
					if (!e.can[j]) continue;
					res.set(i+j);
				}
			}
			return res;
		}
		
		Elem sub(Elem e) {
			Elem res = new Elem();
			for (int i = 0; i < 256; i++) {
				if (!can[i]) continue;
				for (int j = 0; j < 256; j++) {
					if (!e.can[j]) continue;
					res.set(i-j+256);
				}
			}
			return res;
		}

		Elem mult(Elem e) {
			Elem res = new Elem();
			for (int i = 0; i < 256; i++) {
				if (!can[i]) continue;
				for (int j = 0; j < 256; j++) {
					if (!e.can[j]) continue;
					can[(i*j) % 256] = true;
					res.set(i*j);
				}
			}
			return res;
		}

		Elem div(Elem e) {
			Elem res = new Elem();
			for (int i = 0; i < 256; i++) {
				if (!can[i]) continue;
				for (int j = 0; j < 256; j++) {
					if (!e.can[j]) continue;
					if (j == 0) {
						ans = false; 
					} else {
						res.set(i/j);
					}
				}
			}
			return res;
		}
	}
	
	public void solve() {	
		int n = in.nextInt();
		HashMap<String, Elem> map = new HashMap<String, Elem>();
		for (int i = 0; i < n; i++) {
			String name = in.next();
			int lower = in.nextInt(), upper = in.nextInt();
			map.put(name, new Elem(lower, upper));
		}
		
		int m = in.nextInt();
		Stack<Elem> stack = new Stack<Elem>();
		for (int i = 0; i < m; i++) {
			String next = in.next();
			char c = next.charAt(0);
			if (c == '+') {
				Elem e1 = stack.pop();
				Elem e2 = stack.pop();
				stack.push(e2.add(e1));
			} else if (c == '-') {
				Elem e1 = stack.pop();
				Elem e2 = stack.pop();
				stack.push(e2.sub(e1));				
			} else if (c == '*') {
				Elem e1 = stack.pop();
				Elem e2 = stack.pop();
				stack.push(e2.mult(e1));				
			} else if (c == '/') {
				Elem e1 = stack.pop();
				Elem e2 = stack.pop();
				stack.push(e2.div(e1));
				if (!ans) break;
			} else if (Character.isDigit(c)) {
				int val = Integer.valueOf(next);
				stack.push(new Elem(val, val));
			} else if (Character.isLetter(c)) {
				stack.push(map.get(next));
			}
		}
		
		System.out.println(ans ? "correct" : "error");
	}

	
	public void run() {
		if (__FILE_DEBUG_FLAG__) {
			try {
				is = new FileInputStream(__DEBUG_FILE_NAME__);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			System.out.println("FILE_INPUT!!");
		} else {
			is = System.in;
		}
		in = new FastScanner(is);
		out = new PrintWriter(System.out);

		solve();
	}

	public static void main(String[] args) {
		new Main().run();
	}

	public void mapDebug(int[][] a) {
		System.out.println("--------map display---------");

		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[i].length; j++) {
				System.out.printf("%3d ", a[i][j]);
			}
			System.out.println();
		}

		System.out.println("----------------------------");
		System.out.println();
	}

	public void debug(Object... obj) {
		System.out.println(Arrays.deepToString(obj));
	}

	class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
			//stream = new FileInputStream(new File("dec.in"));

		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		int nextInt() {
			return Integer.parseInt(next());
		}

		int[] nextIntArray(int n) {
			int[] array = new int[n];
			for (int i = 0; i < n; i++)
				array[i] = nextInt();

			return array;
		}

		int[][] nextIntMap(int n, int m) {
			int[][] map = new int[n][m];
			for (int i = 0; i < n; i++) {
				map[i] = in.nextIntArray(m);
			}
			return map;
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		long[] nextLongArray(int n) {
			long[] array = new long[n];
			for (int i = 0; i < n; i++)
				array[i] = nextLong();

			return array;
		}

		long[][] nextLongMap(int n, int m) {
			long[][] map = new long[n][m];
			for (int i = 0; i < n; i++) {
				map[i] = in.nextLongArray(m);
			}
			return map;
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}

		double[] nextDoubleArray(int n) {
			double[] array = new double[n];
			for (int i = 0; i < n; i++)
				array[i] = nextDouble();

			return array;
		}

		double[][] nextDoubleMap(int n, int m) {
			double[][] map = new double[n][m];
			for (int i = 0; i < n; i++) {
				map[i] = in.nextDoubleArray(m);
			}
			return map;
		}

		String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		String[] nextStringArray(int n) {
			String[] array = new String[n];
			for (int i = 0; i < n; i++)
				array[i] = next();

			return array;
		}

		String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}
	}
}