// Arup Guha
// 2/18/2015
// Solution to 2009 MCPC Problem G: A to Z Numerals

import java.util.*;

public class g {

	final public static int MAX = 18;
	public static long[] value;

	public static void main(String[] args) {

		// Easy way to store numeral values.
		value = new long[2*MAX];
		value[0] = 1;
		value[1] = 5;
		for (int i=2; i<value.length; i++)
			value[i] = 10*value[i-2];

		Scanner stdin = new Scanner(System.in);
		long n = stdin.nextLong();

		while (n != 0) {

			// Set up recursion - convert and output result.
			int[] res = solve(n);
			System.out.println(convert(res));

			// Get next case.
			n = stdin.nextLong();
		}

	}

	// Wrapper function
	public static int[] solve(long n) {
		return solveRec(new int[2*MAX], n, 2*MAX-1);
	}

	public static int[] solveRec(int[] number, long n, int pos) {

		// Done filling it in.
		if (n == 0) return Arrays.copyOf(number, 2*MAX);
		if (pos == 0) {

			// Not allowed in 1 spot.
			if (Math.abs(n) > 3) return null;

			// Otherwise, fill this in and return.
			number[pos] = (int)n;
			int[] sol = Arrays.copyOf(number, 2*MAX);
			number[pos] = 0;
			return sol;
		}

		// Use this to shorten code later.
		int sign = n > 0 ? 1 : -1;

		// Find how many of this numeral are just too many.
		int next = 0;
		while (Math.abs(n) - next*value[pos] > 0) next++;

		// These aren't viable.
		if (next == 5) return null;

		// Placement is too small, must put a zero here - ratios are strange, correspond to limit of infinite
		// sequence of future terms all added or subtracted.
		if ( (next == 1) && ((n > 0 && n <= value[pos]/3*2) || (n < 0 && Math.abs(n) <= value[pos]/3)) )
			return solveRec(number, n, pos-1);

		// Can't have more than one copy of an "odd" term.
		if (next == 2 && pos%2 == 1) {
			number[pos] = 1*sign;
			int[] sol = solveRec(number, n-sign*value[pos], pos-1);
			number[pos] = 0;
			return sol;
		}

		// We never try 4 of a numeral so only one choice here also.
		if (next == 4) {
			number[pos] = 3*sign;

			// This branch never becomes optimal.
			long left = n-sign*3*value[pos];
			if (left > value[pos]/3) {
				number[pos] = 0;
				return null;
			}

			// Run this option.
			int[] sol = solveRec(number, n-sign*3*value[pos], pos-1);
			number[pos] = 0;
			return sol;
		}

		// Try this option first, shooting under.
		long left = n-sign*(next-1)*value[pos];

		number[pos] = sign*(next-1);
		int[] sol1 = solveRec(number, n-sign*(next-1)*value[pos], pos-1);
		number[pos] = 0;

		// In this situation, this is the only option we need to try.
		if ( (left > 0 && left <= value[pos]/3*2) || (left < 0 && Math.abs(left) <= value[pos]/3) ) return sol1;

		// Otherwise try both options.
		number[pos] = sign*next;
		int[] sol2 = solveRec(number, n-sign*next*value[pos], pos-1);
		number[pos] = 0;

		// Pick the better one.
		return best(sol1, sol2);
	}

	public static String convert(int[] sol) {

		ArrayList<Character> str = new ArrayList<Character>();

		// Builds all positive values.
		for (int i=sol.length-1; i>=0; i--) {

			// Current character to place.
			char ch = i%2 == 0 ? (char)('a'+(i/2)) : (char)('A'+(i/2));

			// Positive, just add at end.
			if (sol[i] > 0) {
				for (int j=0; j<sol[i]; j++)
					str.add(ch);
			}

			// Negative, we have to search back. (Will never have more than 2 of a single character.)
			else if (sol[i] < 0) {

				int index = str.size()-1;

				// Find spot for first negative character.
				while (index-1>=0 && value(str.get(index)) > value(str.get(index-1))) index--;
				str.add(index, ch);

				// Done with this character.
				if (sol[i] == -1) continue;

				// Place the second one.
				if (index > 0) index--;
				while (index-1>=0 && value(str.get(index)) > value(str.get(index-1))) index--;
				str.add(index, ch);
			}
		}

		// Build this and return.
		String ans = "";
		for (int i=0; i<str.size(); i++)
			ans = ans + str.get(i);
		return ans;
	}

	// Returns the better answer based on their rules.
	public static int[] best(int[] sol1, int[] sol2) {

		// Try not to return null.
		if (sol1 == null) return sol2;
		if (sol2 == null) return sol1;

		// If neither are viable, the best of these two is null.
		if (!viable(sol1) && !viable(sol2)) return null;

		// Only one viable, so return it.
		if (!viable(sol1)) return sol2;
		if (!viable(sol2)) return sol1;

		// Break ties based on length.
		int len1 = total(sol1);
		int len2 = total(sol2);
		if (len1 < len2) return sol1;
		if (len2 < len1) return sol2;

		// Final tie-breaker: number of subtracted characters.
		int sub1 = totalMinus(sol1);
		int sub2 = totalMinus(sol2);
		if (sub1 < sub2) return sol1;
		return sol2;
	}

	// Returns true iff this solution is valid according to the rules.
	public static boolean viable(int[] sol) {

		// Never allowed to subtract more of a single character than there are positive
		// characters that are larger.
		int curPos = 0;
		for (int i=sol.length-1; i>=0; i--) {
			if (sol[i] > 0)curPos += sol[i];
			else if (sol[i] < 0 && Math.abs(sol[i]) > curPos) return false;
		}
		return true;
	}

	// Just returns the number of characters represented by sol.
	public static int total(int[] sol) {
		int sum = 0;
		for (int i=0; i<sol.length; i++)
			sum += Math.abs(sol[i]);
		return sum;
	}

	// Returns the total number of subtracted characters in sol.
	public static int totalMinus(int[] sol) {
		int sum = 0;
		for (int i=0; i<sol.length; i++)
			if (sol[i] < 0)
				sum += Math.abs(sol[i]);
		return sum;
	}

	// Just gets us the place value of the character ch to help us index our array.
	public static int value(char ch) {
		if (ch >= 'a' && ch <= 'z') return 2*(ch - 'a');
		else return 2*(ch - 'A') + 1;
	}
}