diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..07403e6 --- /dev/null +++ b/.clang-format @@ -0,0 +1,13 @@ +--- +AlignConsecutiveShortCaseStatements: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true +IndentCaseLabels: true +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: true +AllowShortIfStatementsOnASingleLine: AllIfsAndElse +AllowShortLoopsOnASingleLine: true +IndentWidth: 4 +PointerAlignment: Left +AlignAfterOpenBracket: BlockIndent diff --git a/huffman_coding/src/huffman_coding/Main.java b/huffman_coding/src/huffman_coding/Main.java index 9adbc88..d48b617 100644 --- a/huffman_coding/src/huffman_coding/Main.java +++ b/huffman_coding/src/huffman_coding/Main.java @@ -6,504 +6,537 @@ import tester.Tester; class Examples { - ITree a, b, c, d, e, f, g, h, i, j, o, t, r, u, s, n, v; + ITree a, b, c, d, e, f, g, h, i, j, o, t, r, u, s, n, v; - ArrayList letters; - ArrayList counts; + ArrayList letters; + ArrayList counts; - Huffman huff; + Huffman huff; - ArrayList trees, treesSomeSorted, treesFirstTwoSorted, treesSame, - treesSorted; + ArrayList trees, treesSomeSorted, treesFirstTwoSorted, treesSame, + treesSorted; - void init() { - a = new Leaf(12, "a"); - b = new Leaf(45, "b"); - c = new Leaf(5, "c"); - d = new Leaf(13, "d"); - e = new Leaf(9, "e"); - f = new Leaf(16, "f"); - g = new Leaf(928373743, "f"); - h = new Leaf(1, "h"); - i = new Leaf(1, "i"); - j = new Leaf(1, "j"); + void init() { + a = new Leaf(12, "a"); + b = new Leaf(45, "b"); + c = new Leaf(5, "c"); + d = new Leaf(13, "d"); + e = new Leaf(9, "e"); + f = new Leaf(16, "f"); + g = new Leaf(928373743, "f"); + h = new Leaf(1, "h"); + i = new Leaf(1, "i"); + j = new Leaf(1, "j"); - trees = new ArrayList(Arrays.asList(a, b, c, d, e, f)); - treesSomeSorted = new ArrayList(Arrays.asList(e, d, f)); - treesFirstTwoSorted = new ArrayList(Arrays.asList(c, e, b, f)); - treesSame = new ArrayList(Arrays.asList(h, i)); - treesSorted = new ArrayList(Arrays.asList(c, e, a, d, f, b)); - } + trees = new ArrayList(Arrays.asList(a, b, c, d, e, f)); + treesSomeSorted = new ArrayList(Arrays.asList(e, d, f)); + treesFirstTwoSorted = new ArrayList(Arrays.asList(c, e, b, f)); + treesSame = new ArrayList(Arrays.asList(h, i)); + treesSorted = new ArrayList(Arrays.asList(c, e, a, d, f, b)); + } - void init2() { - // jacob itaru signorovitch + void init2() { + // jacob itaru signorovitch - letters = new ArrayList<>(Arrays.asList("j", "a", "c", "o", "b", "i", "t", - "r", "u", "s", "g", "n", "h", "v")); + letters = new ArrayList<>(Arrays.asList( + "j", "a", "c", "o", "b", "i", "t", "r", "u", "s", "g", "n", "h", "v" + )); - counts = new ArrayList<>( - Arrays.asList(1, 2, 2, 3, 1, 3, 2, 2, 1, 1, 1, 1, 1, 1)); - } + counts = new ArrayList<>( + Arrays.asList(1, 2, 2, 3, 1, 3, 2, 2, 1, 1, 1, 1, 1, 1) + ); + } - void init3() { - // hello world - letters = new ArrayList<>(Arrays.asList("h", "e", "l", "o", "w", "r", "d")); - counts = new ArrayList<>(Arrays.asList(1, 1, 3, 2, 1, 1, 1)); - huff = new Huffman(letters, counts); + void init3() { + // hello world + letters = + new ArrayList<>(Arrays.asList("h", "e", "l", "o", "w", "r", "d")); + counts = new ArrayList<>(Arrays.asList(1, 1, 3, 2, 1, 1, 1)); + huff = new Huffman(letters, counts); - /* - ( ( ( h or e ) or o ) or ( l or ( d or ( w or r ) ) ) ) + /* + ( ( ( h or e ) or o ) or ( l or ( d or ( w or r ) ) ) ) - if you space it out and read it sideways it's like the tree + if you space it out and read it sideways it's like the tree - ( ( ( - h + ( + h + or + e + ) or - e + o ) - or - o - ) - or - ( - l or ( - d + l or ( - w + d or - r + ( + w + or + r + ) ) ) ) - ) - */ - } + */ + } - void testUtilInsertIntoSorted(Tester t) { - init(); - Util.insertIntoSorted(c, treesSomeSorted); - t.checkExpect(treesSomeSorted, - new ArrayList(Arrays.asList(c, e, d, f))); - Util.insertIntoSorted(a, treesSomeSorted); - t.checkExpect(treesSomeSorted, - new ArrayList(Arrays.asList(c, e, a, d, f))); - Util.insertIntoSorted(b, treesSomeSorted); - t.checkExpect(treesSomeSorted, - new ArrayList(Arrays.asList(c, e, a, d, f, b))); - Util.insertIntoSorted(j, treesSame); - t.checkExpect(treesSame, new ArrayList(Arrays.asList(h, i, j))); - } + void testUtilInsertIntoSorted(Tester t) { + init(); + Util.insertIntoSorted(c, treesSomeSorted); + t.checkExpect( + treesSomeSorted, new ArrayList(Arrays.asList(c, e, d, f)) + ); + Util.insertIntoSorted(a, treesSomeSorted); + t.checkExpect( + treesSomeSorted, new ArrayList(Arrays.asList(c, e, a, d, f)) + ); + Util.insertIntoSorted(b, treesSomeSorted); + t.checkExpect( + treesSomeSorted, + new ArrayList(Arrays.asList(c, e, a, d, f, b)) + ); + Util.insertIntoSorted(j, treesSame); + t.checkExpect(treesSame, new ArrayList(Arrays.asList(h, i, j))); + } - void testUtilInsert(Tester t) { - init(); - Util.insert(a, treesFirstTwoSorted, 2); - t.checkExpect(treesFirstTwoSorted, - new ArrayList(Arrays.asList(c, e, a, b, f))); - Util.insert(g, treesFirstTwoSorted, 3); - t.checkExpect(treesFirstTwoSorted, - new ArrayList(Arrays.asList(c, e, a, g, b, f))); - } + void testUtilInsert(Tester t) { + init(); + Util.insert(a, treesFirstTwoSorted, 2); + t.checkExpect( + treesFirstTwoSorted, + new ArrayList(Arrays.asList(c, e, a, b, f)) + ); + Util.insert(g, treesFirstTwoSorted, 3); + t.checkExpect( + treesFirstTwoSorted, + new ArrayList(Arrays.asList(c, e, a, g, b, f)) + ); + } - void testUtilSort(Tester t) { - init(); - ArrayList treesSortedCp = treesSorted; + void testUtilSort(Tester t) { + init(); + ArrayList treesSortedCp = treesSorted; - Util.sort(treesSortedCp); - t.checkExpect(treesSortedCp, treesSorted); + Util.sort(treesSortedCp); + t.checkExpect(treesSortedCp, treesSorted); - Util.sort(trees); - t.checkExpect(trees, treesSorted); - } + Util.sort(trees); + t.checkExpect(trees, treesSorted); + } - void testUtilEnlist(Tester t) { - String s = "Hello"; - t.checkExpect(Util.enlist(s), new ArrayList( - Arrays.asList("H", "e", "l", "l", "o"))); + void testUtilEnlist(Tester t) { + String s = "Hello"; + t.checkExpect( + Util.enlist(s), + new ArrayList(Arrays.asList("H", "e", "l", "l", "o")) + ); - String s2 = "h"; - t.checkExpect(Util.enlist(s2), new ArrayList(Arrays.asList("h"))); - } + String s2 = "h"; + t.checkExpect( + Util.enlist(s2), new ArrayList(Arrays.asList("h")) + ); + } - void testHuffmanMkcode(Tester t) { - init(); - Huffman h = new Huffman(new ArrayList(Arrays.asList("a", "b")), - new ArrayList(Arrays.asList(1, 1))); + void testHuffmanMkcode(Tester t) { + init(); + Huffman h = new Huffman( + new ArrayList(Arrays.asList("a", "b")), + new ArrayList(Arrays.asList(1, 1)) + ); - t.checkExpect(h.code, new Node(2, new Leaf(1, "a"), new Leaf(1, "b"))); + t.checkExpect(h.code, new Node(2, new Leaf(1, "a"), new Leaf(1, "b"))); - Huffman h2 = new Huffman( - new ArrayList(Arrays.asList("a", "b", "c", "d", "e")), - new ArrayList(Arrays.asList(1, 2, 3, 4, 5))); + Huffman h2 = new Huffman( + new ArrayList(Arrays.asList("a", "b", "c", "d", "e")), + new ArrayList(Arrays.asList(1, 2, 3, 4, 5)) + ); - // 1: a:1, b:2, c:3, d:4, e:5 - // 2: (a:1|b:2):3, c:3, d:4, e:5 - // 3: d:4, e:5, ((a:1|b:2):3|c:3):6 - // 4: ((a:1|b:2):3|c:3):6, (d:4|e:5):9 - // 5: (((a:1|b:2):3|:3):6|(d:4|e:5):9):15 + // 1: a:1, b:2, c:3, d:4, e:5 + // 2: (a:1|b:2):3, c:3, d:4, e:5 + // 3: d:4, e:5, ((a:1|b:2):3|c:3):6 + // 4: ((a:1|b:2):3|c:3):6, (d:4|e:5):9 + // 5: (((a:1|b:2):3|:3):6|(d:4|e:5):9):15 - t.checkExpect( - h2.code, - new Node(15, - new Node(6, new Leaf(3, "c"), - new Node(3, new Leaf(1, "a"), new Leaf(2, "b"))), - new Node(9, new Leaf(4, "d"), new Leaf(5, "e")))); - } + t.checkExpect( + h2.code, new Node( + 15, + new Node( + 6, new Leaf(3, "c"), + new Node(3, new Leaf(1, "a"), new Leaf(2, "b")) + ), + new Node(9, new Leaf(4, "d"), new Leaf(5, "e")) + ) + ); + } - void testHuffmanEncodeAndAlsoDecodeAndAlsoEverythingElse(Tester t) { - init3(); - t.checkExpect( - huff.code, - new Node( - 10, - new Node( - 4, - new Node( - 2, - new Leaf(1, "h"), // // - new Leaf(1, "e")), - new Node( - 2, - new Leaf(1, "w"), // // - new Leaf(1, "r"))), - new Node( - 6, - new Leaf(3, "l"), // // - new Node( - 3, - new Leaf(1, "d"), // // - new Leaf(2, "o"))))); + void testHuffmanEncodeAndAlsoDecodeAndAlsoEverythingElse(Tester t) { + init3(); + t.checkExpect( + huff.code, new Node( + 10, + new Node( + 4, + new Node( + 2, + new Leaf( + 1, "h" + ), // // + new Leaf(1, "e") + ), + new Node( + 2, + new Leaf( + 1, "w" + ), // // + new Leaf(1, "r") + ) + ), + new Node( + 6, + new Leaf( + 3, "l" + ), // // + new Node( + 3, + new Leaf( + 1, "d" + ), // // + new Leaf(2, "o") + ) + ) + ) + ); - ArrayList path = - new ArrayList<>(Arrays.asList(false, false, false)); + ArrayList path = + new ArrayList<>(Arrays.asList(false, false, false)); - ArrayList path2 = - new ArrayList<>(Arrays.asList(false, false, false, // h - false, false, true, // e - true, false, // l - true, false, // l - true, true, true // o - )); + ArrayList path2 = new ArrayList<>(Arrays.asList( + false, false, false, // h + false, false, true, // e + true, false, // l + true, false, // l + true, true, true // o + )); - ArrayList path3 = - new ArrayList<>(Arrays.asList(false, false, false, // h - false, false, true, // e - true, false, // l - true, false, // l - true, true, true, // o - false, true, false, // w - true, true, true, // o - false, true, true, // r - true, false, // l - true, true, false // d - )); + ArrayList path3 = new ArrayList<>(Arrays.asList( + false, false, false, // h + false, false, true, // e + true, false, // l + true, false, // l + true, true, true, // o + false, true, false, // w + true, true, true, // o + false, true, true, // r + true, false, // l + true, true, false // d + )); - t.checkExpect(huff.encode("h"), path); - t.checkExpect(huff.decode(path), "h"); + t.checkExpect(huff.encode("h"), path); + t.checkExpect(huff.decode(path), "h"); - t.checkExpect(huff.encode("hello"), path2); - t.checkExpect(huff.decode(path2), "hello"); + t.checkExpect(huff.encode("hello"), path2); + t.checkExpect(huff.decode(path2), "hello"); - t.checkExpect(huff.encode("helloworld"), path3); - t.checkExpect(huff.decode(path3), "helloworld"); + t.checkExpect(huff.encode("helloworld"), path3); + t.checkExpect(huff.decode(path3), "helloworld"); - Huffman huff2 = new Huffman("foo bar baz"); - ArrayList enc = huff2.encode("booz farz fazz"); - t.checkExpect(huff2.decode(enc), "booz farz fazz"); - } + Huffman huff2 = new Huffman("foo bar baz"); + ArrayList enc = huff2.encode("booz farz fazz"); + t.checkExpect(huff2.decode(enc), "booz farz fazz"); + } } class Huffman { - ArrayList charset; // Character set. - ArrayList freqs; // Frequencies of characters in charset. - ITree code; // The tree allowing for encoding and decoding. - ArrayList> map; // Association between the charset and the - // path to reach that char in the code. + ArrayList charset; // Character set. + ArrayList freqs; // Frequencies of characters in charset. + ITree code; // The tree allowing for encoding and decoding. + ArrayList> + map; // Association between the charset and the + // path to reach that char in the code. - Huffman(ArrayList charset, ArrayList freqs) { - if (charset.size() != freqs.size()) - throw new IllegalArgumentException( - "Character set must match frequencies."); + Huffman(ArrayList charset, ArrayList freqs) { + if (charset.size() != freqs.size()) + throw new IllegalArgumentException( + "Character set must match frequencies." + ); - if (charset.size() < 2) - throw new IllegalArgumentException("Character set too small."); + if (charset.size() < 2) + throw new IllegalArgumentException("Character set too small."); - this.charset = charset; - this.freqs = freqs; + this.charset = charset; + this.freqs = freqs; - this.map = new ArrayList<>(); + this.map = new ArrayList<>(); - // Generate the code. - this.makeCode(); + // Generate the code. + this.makeCode(); - // Generate map. - this.makeMap(); - } - - // Generates character freqs from string. - Huffman(String data) { - if (data.length() <= 1) - throw new Error("Can't create tree from that."); - ArrayList charset = new ArrayList<>(); - ArrayList freqs = new ArrayList<>(); - - for (int i = 0; i < data.length(); i++) { - // The current character. - String ch = data.substring(i, i + 1); - - if (charset.contains(ch)) { - int j = charset.indexOf(ch); - freqs.set(j, freqs.get(j) + 1); - } else { - charset.add(ch); - freqs.add(1); - } + // Generate map. + this.makeMap(); } - this.charset = charset; - this.freqs = freqs; - this.map = new ArrayList<>(); + // Generates character freqs from string. + Huffman(String data) { + if (data.length() <= 1) throw new Error("Can't create tree from that."); + ArrayList charset = new ArrayList<>(); + ArrayList freqs = new ArrayList<>(); - // Generate the code. - this.makeCode(); + for (int i = 0; i < data.length(); i++) { + // The current character. + String ch = data.substring(i, i + 1); - // Generate map. - this.makeMap(); - } + if (charset.contains(ch)) { + int j = charset.indexOf(ch); + freqs.set(j, freqs.get(j) + 1); + } else { + charset.add(ch); + freqs.add(1); + } + } - // Creates the code tree. - void makeCode() { - ArrayList nodes = new ArrayList<>(); + this.charset = charset; + this.freqs = freqs; + this.map = new ArrayList<>(); - // Copy all chars over as a tree leaves. - for (int i = 0; i < this.charset.size(); i++) - nodes.add(new Leaf(this.freqs.get(i), this.charset.get(i))); + // Generate the code. + this.makeCode(); - Util.sort(nodes); - - // Combine until all under a single tree. - while (nodes.size() > 1) { - // Move the 2 lowest into their own tree. - ITree firstLowest = nodes.get(0); - ITree secondLowest = nodes.get(1); - nodes.remove(firstLowest); - nodes.remove(secondLowest); - ITree parent = new Node(firstLowest.sumFreq(secondLowest), firstLowest, - secondLowest); - - // Put new tree into list. - Util.insertIntoSorted(parent, nodes); + // Generate map. + this.makeMap(); } - // Set the code to the first (and hopefully only) tree. - this.code = nodes.getFirst(); - } + // Creates the code tree. + void makeCode() { + ArrayList nodes = new ArrayList<>(); - // Make the character path mapping. - void makeMap() { - for (String ch : this.charset) - this.map.addLast(this.code.encode(ch)); - } + // Copy all chars over as a tree leaves. + for (int i = 0; i < this.charset.size(); i++) + nodes.add(new Leaf(this.freqs.get(i), this.charset.get(i))); - // Encode a message. - ArrayList encode(String s) { + Util.sort(nodes); - ArrayList msg = - Util.enlist(s); // The given message, as a list of characters. - ArrayList enc = new ArrayList<>(); // The returned encoded message. + // Combine until all under a single tree. + while (nodes.size() > 1) { + // Move the 2 lowest into their own tree. + ITree firstLowest = nodes.get(0); + ITree secondLowest = nodes.get(1); + nodes.remove(firstLowest); + nodes.remove(secondLowest); + ITree parent = new Node( + firstLowest.sumFreq(secondLowest), firstLowest, secondLowest + ); - // Loop for each character in the message. - for (String ch : msg) - enc.addAll(this.encodeCh(ch)); + // Put new tree into list. + Util.insertIntoSorted(parent, nodes); + } - return enc; - } + // Set the code to the first (and hopefully only) tree. + this.code = nodes.getFirst(); + } - // Encode a character. - ArrayList encodeCh(String ch) { - // Throw error if character is not in charset. - if (!this.charset.contains(ch)) - throw new IllegalArgumentException("Cannot encode unknown character \"" + - ch + "\"."); + // Make the character path mapping. + void makeMap() { + for (String ch : this.charset) this.map.addLast(this.code.encode(ch)); + } - int i = this.charset.indexOf(ch); - return this.map.get(i); - } + // Encode a message. + ArrayList encode(String s) { - // Decode a message. - String decode(ArrayList enc) { return this.code.follow(enc); } + ArrayList msg = + Util.enlist(s); // The given message, as a list of characters. + ArrayList enc = + new ArrayList<>(); // The returned encoded message. + + // Loop for each character in the message. + for (String ch : msg) enc.addAll(this.encodeCh(ch)); + + return enc; + } + + // Encode a character. + ArrayList encodeCh(String ch) { + // Throw error if character is not in charset. + if (!this.charset.contains(ch)) + throw new IllegalArgumentException( + "Cannot encode unknown character \"" + ch + "\"." + ); + + int i = this.charset.indexOf(ch); + return this.map.get(i); + } + + // Decode a message. + String decode(ArrayList enc) { return this.code.follow(enc); } } // Binary tree. interface ITree { - // Compare this and another tree, and return the lesser of the two. - boolean lessThan(ITree n); + // Compare this and another tree, and return the lesser of the two. + boolean lessThan(ITree n); - // Is this tree less than the given frequency? - boolean lessThan(int freq); + // Is this tree less than the given frequency? + boolean lessThan(int freq); - // Sum the frequency with another tree. - int sumFreq(ITree t); - int sumFreq(int freq); + // Sum the frequency with another tree. + int sumFreq(ITree t); + int sumFreq(int freq); - // Encode a character. - ArrayList encode(String ch); - ArrayList encode(String ch, ArrayList encodingSoFar); + // Encode a character. + ArrayList encode(String ch); + ArrayList encode(String ch, ArrayList encodingSoFar); - // Follow (decode) a path. - String follow(ArrayList path); - String followCh(ArrayList path); + // Follow (decode) a path. + String follow(ArrayList path); + String followCh(ArrayList path); } abstract class ATree implements ITree { - int freq; // The frequency of the tree. + int freq; // The frequency of the tree. - ATree(int freq) { this.freq = freq; } + ATree(int freq) { this.freq = freq; } - public boolean lessThan(ITree n) { return n.lessThan(this.freq); } - public boolean lessThan(int freq) { return this.freq < freq; } - public int sumFreq(ITree t) { return t.sumFreq(this.freq); } - public int sumFreq(int freq) { return this.freq + freq; } + public boolean lessThan(ITree n) { return n.lessThan(this.freq); } + public boolean lessThan(int freq) { return this.freq < freq; } + public int sumFreq(ITree t) { return t.sumFreq(this.freq); } + public int sumFreq(int freq) { return this.freq + freq; } } class Node extends ATree { - // Left (false) and right (true) branches of tree. - ITree l, r; + // Left (false) and right (true) branches of tree. + ITree l, r; - Node(int freq, ITree l, ITree r) { - super(freq); - this.l = l; - this.r = r; - } - - public ArrayList encode(String ch) { - ArrayList ret = new ArrayList<>(); - ret.addAll(this.l.encode(ch, new ArrayList<>(Arrays.asList(false)))); - ret.addAll(this.r.encode(ch, new ArrayList<>(Arrays.asList(true)))); - return ret; - } - - public ArrayList encode(String ch, - ArrayList encodingSoFar) { - ArrayList ret = new ArrayList<>(), - left = new ArrayList(Arrays.asList(false)), - right = new ArrayList<>(Arrays.asList(true)); - - left.addAll(0, encodingSoFar); - right.addAll(0, encodingSoFar); - - ret.addAll(this.l.encode(ch, left)); - ret.addAll(this.r.encode(ch, right)); - return ret; - } - - public String follow(ArrayList path) { - ArrayList pathcpy = path; - String ret = ""; - - // Each loop is 1 character. - while (pathcpy.size() > 0) { - Boolean b = pathcpy.getFirst(); - pathcpy.removeFirst(); - ret += b ? this.r.followCh(pathcpy) : this.l.followCh(pathcpy); + Node(int freq, ITree l, ITree r) { + super(freq); + this.l = l; + this.r = r; } - return ret; - } + public ArrayList encode(String ch) { + ArrayList ret = new ArrayList<>(); + ret.addAll(this.l.encode(ch, new ArrayList<>(Arrays.asList(false)))); + ret.addAll(this.r.encode(ch, new ArrayList<>(Arrays.asList(true)))); + return ret; + } - public String followCh(ArrayList path) { - if (path.size() <= 0) - throw new Error("Invalid path."); - Boolean b = path.getFirst(); - path.removeFirst(); - return b ? this.r.followCh(path) : this.l.followCh(path); - } + public ArrayList + encode(String ch, ArrayList encodingSoFar) { + ArrayList ret = new ArrayList<>(), + left = new ArrayList(Arrays.asList(false)), + right = new ArrayList<>(Arrays.asList(true)); + + left.addAll(0, encodingSoFar); + right.addAll(0, encodingSoFar); + + ret.addAll(this.l.encode(ch, left)); + ret.addAll(this.r.encode(ch, right)); + return ret; + } + + public String follow(ArrayList path) { + ArrayList pathcpy = new ArrayList<>(); + for (Boolean b : path) pathcpy.add(b); + String ret = ""; + + // Each loop is 1 character. + while (pathcpy.size() > 0) { + Boolean b = pathcpy.getFirst(); + pathcpy.removeFirst(); + ret += b ? this.r.followCh(pathcpy) : this.l.followCh(pathcpy); + } + + return ret; + } + + public String followCh(ArrayList path) { + if (path.size() <= 0) throw new Error("Invalid path."); + Boolean b = path.getFirst(); + path.removeFirst(); + return b ? this.r.followCh(path) : this.l.followCh(path); + } } class Leaf extends ATree { - String ch; // The character. + String ch; // The character. - Leaf(int freq, String ch) { - super(freq); - this.ch = ch; - } + Leaf(int freq, String ch) { + super(freq); + this.ch = ch; + } - public ArrayList encode(String ch) { - throw new Error("Can't, fool."); - } + public ArrayList encode(String ch) { + throw new Error("Can't, fool."); + } - public ArrayList encode(String ch, - ArrayList encodingSoFar) { - if (ch.equals(this.ch)) - return encodingSoFar; - else - return new ArrayList(); - } + public ArrayList + encode(String ch, ArrayList encodingSoFar) { + if (ch.equals(this.ch)) return encodingSoFar; + else return new ArrayList(); + } - public String follow(ArrayList path) { - throw new Error("Shouldn't call follow() on leaf."); - } - public String followCh(ArrayList path) { return this.ch; } - public String follow(ArrayList path, String soFar) { - return soFar.concat(this.ch); - } + public String follow(ArrayList path) { + throw new Error("Shouldn't call follow() on leaf."); + } + public String followCh(ArrayList path) { return this.ch; } + public String follow(ArrayList path, String soFar) { + return soFar.concat(this.ch); + } } class Util { - // Sort a list of trees from least to most frequent. - static void sort(ArrayList trees) { - // Our work here is done. - if (trees.size() < 2) - return; + // Sort a list of trees from least to most frequent. + static void sort(ArrayList trees) { + // Our work here is done. + if (trees.size() < 2) return; - for (int i = 1; i < trees.size(); i++) { - // Copy out the tree to insert. - ITree tree = trees.get(i); - trees.remove(tree); - // Insert it. - insert(tree, trees, i); + for (int i = 1; i < trees.size(); i++) { + // Copy out the tree to insert. + ITree tree = trees.get(i); + trees.remove(tree); + // Insert it. + insert(tree, trees, i); + } } - } - // Insert a Tree into an ArrayList of trees already sorted in [0, i), where - // 0 <= i <= trees.size(), such that it is sorted through [0, i]. - static void insert(ITree tree, ArrayList trees, int i) { - // Extract sorted. - ArrayList sorted = new ArrayList<>(trees.subList(0, i)); - // Insert tree. - insertIntoSorted(tree, sorted); - // Overwrite original trees with sorted ones. - for (int j = 0; j < i; trees.set(j, sorted.get(j++))) - ; - // Insert the last tree back in. - trees.add(i, sorted.getLast()); - } + // Insert a Tree into an ArrayList of trees already sorted in [0, i), where + // 0 <= i <= trees.size(), such that it is sorted through [0, i]. + static void insert(ITree tree, ArrayList trees, int i) { + // Extract sorted. + ArrayList sorted = new ArrayList<>(trees.subList(0, i)); + // Insert tree. + insertIntoSorted(tree, sorted); + // Overwrite original trees with sorted ones. + for (int j = 0; j < i; trees.set(j, sorted.get(j++))); + // Insert the last tree back in. + trees.add(i, sorted.getLast()); + } - // Insert a Tree in an already fully sorted ArrayList of Trees. - static void insertIntoSorted(ITree tree, ArrayList sortedTrees) { - for (int i = 0; i < sortedTrees.size(); i++) - if (sortedTrees.get(i).lessThan(tree)) { - sortedTrees.add(i, tree); // - return; - } - sortedTrees.addLast(tree); // This tree is bigger than all the others. - } + // Insert a Tree in an already fully sorted ArrayList of Trees. + static void insertIntoSorted(ITree tree, ArrayList sortedTrees) { + for (int i = 0; i < sortedTrees.size(); i++) + if (sortedTrees.get(i).lessThan(tree)) { + sortedTrees.add(i, tree); // + return; + } + sortedTrees.addLast(tree); // This tree is bigger than all the others. + } - // Convert a string to a list. - static ArrayList enlist(String s) { - ArrayList ret = new ArrayList<>(); - for (int i = 0; i < s.length(); ret.add(String.valueOf(s.charAt(i++)))) - ; - return ret; - } + // Convert a string to a list. + static ArrayList enlist(String s) { + ArrayList ret = new ArrayList<>(); + for (int i = 0; i < s.length(); ret.add(String.valueOf(s.charAt(i++)))); + return ret; + } } diff --git a/traversal/.project b/traversal/.project new file mode 100644 index 0000000..05a3787 --- /dev/null +++ b/traversal/.project @@ -0,0 +1,28 @@ + + + traversal + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + + + 1736900497 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/traversal/.settings/org.eclipse.core.resources.prefs b/traversal/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/traversal/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/traversal/.settings/org.eclipse.jdt.core.prefs b/traversal/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..9a7984b --- /dev/null +++ b/traversal/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=21 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=21 diff --git a/traversal/src/traversal/Main.java b/traversal/src/traversal/Main.java new file mode 100644 index 0000000..725c987 --- /dev/null +++ b/traversal/src/traversal/Main.java @@ -0,0 +1,123 @@ +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.NoSuchElementException; +import java.util.Queue; + +// a non-empty binary tree +abstract class BT { + X value; + + BT(X value) { this.value = value; } + + // produce an iterator for the left child, or an empty iterator if one does + // not exist + abstract Iterator leftIterator(DFTIterator f); + + // produce an iterator for the right child, or an empty iterator if one does + // not exist + abstract Iterator rightIterator(DFTIterator f); + + // add this node's children, if they exist, to the queue (left then right) + abstract void addChildrenToQueue(Queue> queue); +} + +class Leaf extends BT { + Iterator leftIterator(DFTIterator f) { + throw new NoSuchElementException(); + } + + Iterator rigtIterator(DFTIterator f) { + throw new NoSuchElementException(); + } + + void addChildrenToQueue(Queue> queue) { queue.add(this); } + + Leaf(X value) { super(value); } +} + +class Node extends BT { + BT left; + BT right; + + Node(X value, BT left, BT right) { + super(value); + this.left = left; + this.right = right; + } + + Iterator leftIterator(DFTIterator f) { + return this.left.leftIterator(f); + } + + Iterator rightIterator(DFTIterator f) { + return this.right.rightIterator(f); + } + + void addChildrenToQueue(Queue> queue) { + this.left.addChildrenToQueue(queue); + this.right.addChildrenToQueue(queue); + } +} + +// a depth first iterator for a BT +interface DFTIterator extends Iterator { + // produce a depth first traversal iterator for the given BT + DFTIterator iterate(BT x); +} + +abstract class DFT implements DFTIterator { + BT bt; + Iterator left; + Iterator right; + // has the top-level value of bt been iterated over yet + boolean nodeGiven; + + DFT(BT bt) { + this.bt = bt; + this.left = bt.leftIterator(this); + this.right = bt.rightIterator(this); + } + + public boolean hasNext() { + return left.hasNext() || !nodeGiven || right.hasNext(); + } + + // check that there is a next element, wraps the getNext method + public X next() { + if (!this.hasNext()) { throw new NoSuchElementException(); } + return this.getNext(); + } + + // actually get the next + abstract X getNext(); +} + +class InOrder extends DFT { + + InOrder(BT bt) { super(bt); } + + public DFTIterator iterate(BT x) { return new InOrder(x); } +} + +class PreOrder extends DFT { + + PreOrder(BT bt) { super(bt); } + + public DFTIterator iterate(BT x) { return new PreOrder(x); } +} + +class PostOrder extends DFT { + + PostOrder(BT bt) { super(bt); } + + public DFTIterator iterate(BT x) { return new PostOrder(x); } +} + +// a breadth first iterator for a BT +class BFT implements Iterator { + + Queue> queue = new LinkedList>(); + + BFT(BT bt) { queue.add(bt); } +}