From eb79eae777f5118d02d0fe1992b84cc6f203a424 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 7 Jan 2025 22:41:11 -0500 Subject: [PATCH] i hate everything --- huffman_coding/src/huffman_coding/Main.java | 266 ++++++++++++++------ 1 file changed, 193 insertions(+), 73 deletions(-) diff --git a/huffman_coding/src/huffman_coding/Main.java b/huffman_coding/src/huffman_coding/Main.java index 9c507cf..67d441c 100644 --- a/huffman_coding/src/huffman_coding/Main.java +++ b/huffman_coding/src/huffman_coding/Main.java @@ -6,11 +6,15 @@ import tester.Tester; class Examples { - ITree a, b, c, d, e, f, g, h, i, j; + ITree a, b, c, d, e, f, g, h, i, j, o, t, r, u, s, n, v; - ArrayList< - ITree - > trees, treesSomeSorted, treesFirstTwoSorted, treesSame, treesSorted; + ArrayList letters; + ArrayList counts; + + Huffman huff; + + ArrayList trees, treesSomeSorted, treesFirstTwoSorted, treesSame, + treesSorted; void init() { a = new Leaf(12, "a"); @@ -31,17 +35,68 @@ class Examples { treesSorted = new ArrayList(Arrays.asList(c, e, a, d, f, b)); } + void init2() { + // jacob itaru signorovitch + + 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) + ); + } + + 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 ) ) ) ) + + if you space it out and read it sideways it's like the tree + + ( + ( + ( + h + or + e + ) + or + o + ) + or + ( + l + or + ( + d + or + ( + w + or + r + ) + ) + ) + ) + + */ + } + void testUtilInsertIntoSorted(Tester t) { init(); Util.insertIntoSorted(c, treesSomeSorted); t.checkExpect( - treesSomeSorted, - new ArrayList(Arrays.asList(c, e, d, f)) + 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)) + treesSomeSorted, new ArrayList(Arrays.asList(c, e, a, d, f)) ); Util.insertIntoSorted(b, treesSomeSorted); t.checkExpect( @@ -86,8 +141,7 @@ class Examples { String s2 = "h"; t.checkExpect( - Util.enlist(s2), - new ArrayList(Arrays.asList("h")) + Util.enlist(s2), new ArrayList(Arrays.asList("h")) ); } @@ -98,7 +152,9 @@ class Examples { 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, "b", new Leaf(1, "a"), new Leaf(1, "b")) + ); Huffman h2 = new Huffman( new ArrayList(Arrays.asList("a", "b", "c", "d", "e")), @@ -114,32 +170,61 @@ class Examples { t.checkExpect( h2.code, new Node( - 15, + 15, "e", new Node( - 6, - new Node(3, new Leaf(1, "a"), new Leaf(2, "b")), + 6, "c", + new Node(3, "b", new Leaf(1, "a"), new Leaf(2, "b")), new Leaf(3, "c") ), - new Node(9, new Leaf(4, "d"), new Leaf(5, "e")) + new Node(9, "e", new Leaf(4, "d"), new Leaf(5, "e")) ) ); } + + void testHuffmanEncode(Tester t) { + init3(); + t.checkExpect( + huff.code, + new Node( + 10, "lrwdoeh", + new Node( + 4, "oeh", + new Node(2, "eh", new Leaf(1, "h"), new Leaf(1, "e")), + new Leaf(2, "o") + ), + new Node( + 6, "lrwd", + new Node( + 3, "rwd", new Leaf(1, "d"), + new Node(2, "rw", new Leaf(1, "w"), new Leaf(1, "r")) + ), + new Leaf(3, "l") + ) + ) + ); + + t.checkExpect( + huff.encode("he"), new ArrayList(Arrays.asList( + false, false, false, false, false, true + )) + ); + } } class Huffman { ArrayList charset; // Character set. - ArrayList freqs; // Frequencies of characters in charset. - ITree code; // The tree allowing for encoding and decoding. + ArrayList freqs; // Frequencies of characters in charset. + ITree code; // The tree allowing for encoding and decoding. Huffman(ArrayList charset, ArrayList freqs) { - if (charset.size() != freqs.size()) throw new IllegalArgumentException( - "Character set must match frequencies." - ); + 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; @@ -152,9 +237,8 @@ class Huffman { ArrayList nodes = 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)) - ); + for (int i = 0; i < this.charset.size(); i++) + nodes.add(new Leaf(this.freqs.get(i), this.charset.get(i))); // Combine until all under a single tree. while (nodes.size() > 1) { @@ -167,9 +251,8 @@ class Huffman { nodes.remove(firstLowest); nodes.remove(secondLowest); ITree parent = new Node( - firstLowest.sumFreq(secondLowest), - firstLowest, - secondLowest + firstLowest.sumFreq(secondLowest), firstLowest.getQuestion(), + firstLowest, secondLowest ); // Put new tree into list. @@ -182,20 +265,32 @@ class Huffman { // Encode a message. ArrayList encode(String s) { - ArrayList msg = Util.enlist(s); // The given message, as a list of characters. - ArrayList enc = new ArrayList<>(); // The returned encoded message. + System.out.println("Encoding " + s); + System.out.flush(); + + 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) { - // Throw error if character is not in charset. - if (!this.charset.contains(ch)) throw new IllegalArgumentException( - "Cannot encode unknown character \"" + ch + "\"." - ); - // Go through the - } + for (String ch : msg) enc.addAll(this.encodeCh(ch)); return enc; } + + // Encode a character. + ArrayList encodeCh(String ch) { + System.out.println("Encoding character " + ch); + System.out.flush(); + // Throw error if character is not in charset. + if (!this.charset.contains(ch)) + throw new IllegalArgumentException( + "Cannot encode unknown character \"" + ch + "\"." + ); + + return this.code.encode(ch); + } } // Binary tree. @@ -210,33 +305,25 @@ interface ITree { int sumFreq(ITree t); int sumFreq(int freq); - // Given the character, choose whether to go left (0) or right (1) or stop (-1). - Int getNext(String ch); + // Return its question (the values on the right). + String getQuestion(); + + // Encode a character. + ArrayList encode(String ch); + ArrayList + encodeHelper(String ch, ArrayList encodingSoFar); } abstract class ATree implements ITree { 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 { @@ -248,19 +335,38 @@ class Node extends ATree { // the character is in the string, go right. String question; - Node(int freq, ITree l, ITree r) { + Node(int freq, String question, ITree l, ITree r) { super(freq); + this.question = question; this.l = l; this.r = r; } - // Ask its question on a character. - Boolean ask(String ch) { - return this.question.contains(ch); + public String getQuestion() { return this.question; } + + public ArrayList encode(String ch) { + Boolean b = this.question.contains(ch); + System.out.println( + "I'm a node encoding " + ch + " and going " + (b ? "right" : "left") + ); + System.out.flush(); + + // If the character's in the question, go right; otherwise, go left. + return this.question.contains(ch) + ? this.r.encodeHelper(ch, new ArrayList<>(Arrays.asList(true))) + : this.l.encodeHelper(ch, new ArrayList<>(Arrays.asList(false))); } - Integer getNext(String ch) { - return this.ask(ch) ? + public ArrayList + encodeHelper(String ch, ArrayList encodingSoFar) { + System.out.println("I'm a node encode helping " + ch); + System.out.flush(); + Boolean contains = this.question.contains(ch); + + ITree choice = contains ? this.r : this.l; + encodingSoFar.add(contains); + + return choice.encodeHelper(ch, encodingSoFar); } } @@ -272,6 +378,21 @@ class Leaf extends ATree { super(freq); this.ch = ch; } + + public String getQuestion() { return this.ch; } + + public ArrayList encode(String ch) { + System.out.println("I'm a leaf encoding " + ch); + System.out.flush(); + throw new Error("Cannot encode a Leaf."); + } + + public ArrayList + encodeHelper(String ch, ArrayList encodingSoFar) { + System.out.println("I'm a leaf encode helping " + ch); + System.out.flush(); + return encodingSoFar; + } } class Util { @@ -299,26 +420,25 @@ class Util { 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; - } + 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(); i++) ret.add( - String.valueOf(s.charAt(i)) // Why why why can't we just use a list of chars ;_; - ); + for (int i = 0; i < s.length(); i++) + ret.add(String.valueOf(s.charAt(i))); return ret; } }