import java.util.*; public class StringProduct implements Enumeration { private String s; // smaller of two strings private String b; // bigger of two strings private StringList todo; // strings to be enumerated, sorted from small to big private StringList prev; // most recently calculated "round" of strings, // sorted from small to big private String next; // smallest string of next "round" // Introduce the abbreviation "SL." for "StringList." private static StringList SL; // Creates an enumerationg of the strings in the product of s1 and s2 public StringProduct (String s1, String s2) { if (stringCompare(s1,s2) < 0) { s = s1; b = s2; } else { s = s2; b = s1; } todo = SL.prepend("", SL.empty()); prev = todo; next = s; } public boolean hasMoreElements () { return true; } // Returns the next string in the string product public Object nextElement () { if (SL.isEmpty(todo) || (stringCompare(SL.head(todo),next) >= 0)) { prev = merge(mapConcat(s, prev), mapConcat(b, prev)); next = s + SL.head(prev); todo = merge(todo, prev); } String hd = SL.head(todo); todo = SL.tail(todo); return hd; } // Returns a new list that has the same length as xs and in which // every element is the result of concatenating s with the corresponding // element of xs. private StringList mapConcat (String s, StringList xs) { if (SL.isEmpty(xs)) { return xs; } else { return SL.prepend(s + SL.head(xs), mapConcat(s, SL.tail(xs))); } } // Return a new list that merges the elements of two sorted lists of strings, // removing any duplicates. private StringList merge (StringList xs, StringList ys) { if (SL.isEmpty(xs)) return ys; else if (SL.isEmpty(ys)) return xs; else { String x = SL.head(xs); String y = SL.head(ys); int comp = stringCompare(x,y); if (comp == 0) { return SL.prepend(x, merge(SL.tail(xs), SL.tail(ys))); } else if (comp < 0) { return SL.prepend(x, merge(SL.tail(xs), ys)); } else { // if (comp > 0) return SL.prepend(y, merge(xs, SL.tail(ys))); } } } // In this string comparison, strings with fewer characters are considered // smaller than strings with more characters. Strings with the same number // of characters are compared lexicographically. For example, // // stringCompare("b", "aa") < 0 // stringCompare("ab", "aa") > 0 // stringCompare("ab", "ab") = 0 private static int stringCompare (String s1, String s2) { if (s1 == s2) { return 0; // cheap pointer equality test } else { int len1 = s1.length(); int len2 = s2.length(); if (len1 == len2) { return s1.compareTo(s2); // compares strings lexicographically } else { return len1 - len2; } } } // Given two string arguments, prints (one per line) the strings in the // product of the two strings. public static void main (String[] args) { if (args.length == 2) { Enumeration strings = new StringProduct(args[0], args[1]); while (true) { System.out.println("\"" + strings.nextElement() + "\""); } } else { System.out.println("expect 2 strings as arguments"); } } }