i hate everything
This commit is contained in:
@@ -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<String> letters;
|
||||
ArrayList<Integer> counts;
|
||||
|
||||
Huffman huff;
|
||||
|
||||
ArrayList<ITree> trees, treesSomeSorted, treesFirstTwoSorted, treesSame,
|
||||
treesSorted;
|
||||
|
||||
void init() {
|
||||
a = new Leaf(12, "a");
|
||||
@@ -31,17 +35,68 @@ class Examples {
|
||||
treesSorted = new ArrayList<ITree>(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<ITree>(Arrays.asList(c, e, d, f))
|
||||
treesSomeSorted, new ArrayList<ITree>(Arrays.asList(c, e, d, f))
|
||||
);
|
||||
Util.insertIntoSorted(a, treesSomeSorted);
|
||||
t.checkExpect(
|
||||
treesSomeSorted,
|
||||
new ArrayList<ITree>(Arrays.asList(c, e, a, d, f))
|
||||
treesSomeSorted, new ArrayList<ITree>(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<String>(Arrays.asList("h"))
|
||||
Util.enlist(s2), new ArrayList<String>(Arrays.asList("h"))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,7 +152,9 @@ class Examples {
|
||||
new ArrayList<Integer>(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<String>(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<Boolean>(Arrays.asList(
|
||||
false, false, false, false, false, true
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Huffman {
|
||||
|
||||
ArrayList<String> charset; // Character set.
|
||||
ArrayList<Integer> freqs; // Frequencies of characters in charset.
|
||||
ITree code; // The tree allowing for encoding and decoding.
|
||||
ArrayList<Integer> freqs; // Frequencies of characters in charset.
|
||||
ITree code; // The tree allowing for encoding and decoding.
|
||||
|
||||
Huffman(ArrayList<String> charset, ArrayList<Integer> 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<ITree> 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<Boolean> encode(String s) {
|
||||
ArrayList<String> msg = Util.enlist(s); // The given message, as a list of characters.
|
||||
ArrayList<Boolean> enc = new ArrayList<>(); // The returned encoded message.
|
||||
System.out.println("Encoding " + s);
|
||||
System.out.flush();
|
||||
|
||||
ArrayList<String> msg =
|
||||
Util.enlist(s); // The given message, as a list of characters.
|
||||
ArrayList<Boolean> 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<Boolean> 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<Boolean> encode(String ch);
|
||||
ArrayList<Boolean>
|
||||
encodeHelper(String ch, ArrayList<Boolean> 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<Boolean> 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<Boolean>
|
||||
encodeHelper(String ch, ArrayList<Boolean> 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<Boolean> encode(String ch) {
|
||||
System.out.println("I'm a leaf encoding " + ch);
|
||||
System.out.flush();
|
||||
throw new Error("Cannot encode a Leaf.");
|
||||
}
|
||||
|
||||
public ArrayList<Boolean>
|
||||
encodeHelper(String ch, ArrayList<Boolean> 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<ITree> 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<String> enlist(String s) {
|
||||
ArrayList<String> 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;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user