// Arup Guha
// 10/20/2013
// Solution to 2008 MCPC Problem B: Lampyridae Teleportae

import java.util.*;

public class c {

	public static char[][] grid;
	public static int rows;
	public static int cols;
	public static int size;

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);
		rows = stdin.nextInt();

		// Go through each case.
		while (rows != 0) {

			cols = stdin.nextInt();
			size = rows*cols + rows/2;
			grid = new char[rows][cols+1];

			// Read in the grid.
			for (int i=0; i<rows; i++)
				for (int j=0; j<cols+i%2; j++)
					grid[i][j] = stdin.next().charAt(0);

			// Solve and go to next case.
			System.out.println(solve());
			rows = stdin.nextInt();
		}
	}

	// Wrapper function for recursive solve.
	public static String solve() {

		// Try starting our equation at each spot and return if any work.
		for (int x=0; x<rows; x++) {
			for (int y=0; y<cols+x%2; y++) {
				
				// Set up our used array for starting from (x,y).
				boolean[][] used = new boolean[rows][cols+1];
				used[x][y] = true;
				
				// Run this search.
				String ans = solve(used, ""+grid[x][y], 1, x, y);
				
				// Un-use this slot.
				used[x][y] = false;
				
				// We found our answer!
				if (ans != null) return ans;
			}
		}
		
		// Indicates that no equation exists.
		return "";
	}

	// Recursive function to solve the problem. expr is what we've built so far, used is
	// what is already used, (x,y) is where we're at, and k is the size of our expression.
	public static String solve(boolean[][] used, String expr, int k, int x, int y) {

		// We've finished the permutation, see if it works.
		if (k == size) {
			if (isTrue(expr))
				return expr;
			else
				return null;
		}

		int[][] d = getDelta(x);

		// Go through each possible next step.
		for (int i=0; i<d.length; i++) {

			// Next location.
			int nx = x + d[i][0];
			int ny = y + d[i][1];

			// Screen out what's not allowed.
			if (!inbounds(nx,ny)) continue;
			if (used[nx][ny]) continue;
			
			// Use this square and add to the expression.
			used[nx][ny] = true;
			String temp = solve(used, expr+grid[nx][ny], k+1, nx, ny);
			
			// Undo used.
			used[nx][ny] = false;
			
			// If this worked, return immediately.
			if (temp != null) return temp;
		}

		// Indicate nothing worked.
		used[x][y] = false;
		return null;
	}

	// Returns the possible movement array from a given row on the grid.
	public static int[][] getDelta(int row) {
		if (row%2 == 0) {
			int[][] array = {{-1,0},{-1,1},{0,-1},{0,1},{1,0}, {1,1}};
			return array;
		}
		else {
			int[][] array = {{-1,-1},{-1,0},{0,-1},{0,1},{1,-1},{1,0}};
			return array;
		}
	}

	// Returns true iff (x,y) is in the grid.
	public static boolean inbounds(int x, int y) {
		if (x < 0 || x >= rows) return false;
		if (y < 0 || y >= cols + x%2) return false;
		return true;
	}

	public static boolean isTrue(String expr) {

		// Parse out equal sign.
		StringTokenizer tok = new StringTokenizer(expr, "=");
		String left = "";
		String right = "";
		left = tok.nextToken();
		if (tok.hasMoreTokens())
			right = tok.nextToken();

		// This can't work.
		if (left.length() == 0 || right.length() == 0) return false;

		// Get values.
		Integer leftVal = getVal(left);
		Integer rightVal = getVal(right);

		// Something illegal happened in evaluation.
		if (leftVal == null || rightVal == null) return false;

		// See if they are equal or not.
		return leftVal == rightVal;
	}

	// s is an expression with no =.
	public static Integer getVal(String s) {

		// no unary
		// division must be perfect
		// two digits only per number or one
		// no leading zeroes, one zero okay

		// Can't start or end with an operator.
		if (!Character.isDigit(s.charAt(0))) return null;
		if (!Character.isDigit(s.charAt(s.length()-1))) return null;

		// Get positions of operators.
		ArrayList<Integer> opPos = new ArrayList<Integer>();
		for (int i=0; i<s.length(); i++)
			if (!Character.isDigit(s.charAt(i)))
				opPos.add(i);

		// Get initial value.
		Integer val = 0;
		if (opPos.size() > 0)
			val = getInt(s.substring(0, opPos.get(0)));
		else
			val = getInt(s);

		if (val == null) return null;

		// Run through the expression in order.
		for (int i=0; i<opPos.size(); i++) {

			char op = s.charAt(opPos.get(i));

			// Set start and end of next number.
			int start = opPos.get(i)+1;
			int end = s.length();
			if (i < opPos.size()-1)
				end = opPos.get(i+1);

			// Not allowed.
			if (end <= start) return null;

			// Screen out invalid numbers for the next token.
			Integer nextVal = getInt(s.substring(start, end));
			if (nextVal == null) return null;

			// Execute the current operation.
			if (op  == '+')
				val += nextVal;
			else if (op == '-')
				val -= nextVal;
			else if (op == '*')
				val *= nextVal;
				
			// Watch out for divide by 0!!!
			else {
				if (nextVal == 0 || val%nextVal != 0) return null;
				val /= nextVal;
			}
		}

		return val;
	}

	// Easy since we only want 1 or 2 digit numbers.
	public static Integer getInt(String s) {
		if (s.length() < 1 || s.length() > 2) return null;
		if (s.length() == 2 && s.charAt(0) == '0') return null;
		return Integer.parseInt(s);
	}
}