FINISHED HUFFMAN FINALLLLLLYLYLLY

This commit is contained in:
Jacob Signorovitch
2025-01-13 13:56:01 -05:00
parent d9d937c77e
commit b6ec810bb9
3 changed files with 384 additions and 371 deletions

View File

@@ -6,439 +6,492 @@ import tester.Tester;
class Examples { 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<String> letters; ArrayList<String> letters;
ArrayList<Integer> counts; ArrayList<Integer> counts;
Huffman huff; Huffman huff;
ArrayList<ITree> trees, treesSomeSorted, treesFirstTwoSorted, treesSame, ArrayList<ITree> trees, treesSomeSorted, treesFirstTwoSorted, treesSame,
treesSorted; treesSorted;
void init() { void init() {
a = new Leaf(12, "a"); a = new Leaf(12, "a");
b = new Leaf(45, "b"); b = new Leaf(45, "b");
c = new Leaf(5, "c"); c = new Leaf(5, "c");
d = new Leaf(13, "d"); d = new Leaf(13, "d");
e = new Leaf(9, "e"); e = new Leaf(9, "e");
f = new Leaf(16, "f"); f = new Leaf(16, "f");
g = new Leaf(928373743, "f"); g = new Leaf(928373743, "f");
h = new Leaf(1, "h"); h = new Leaf(1, "h");
i = new Leaf(1, "i"); i = new Leaf(1, "i");
j = new Leaf(1, "j"); j = new Leaf(1, "j");
trees = new ArrayList<ITree>(Arrays.asList(a, b, c, d, e, f)); trees = new ArrayList<ITree>(Arrays.asList(a, b, c, d, e, f));
treesSomeSorted = new ArrayList<ITree>(Arrays.asList(e, d, f)); treesSomeSorted = new ArrayList<ITree>(Arrays.asList(e, d, f));
treesFirstTwoSorted = new ArrayList<ITree>(Arrays.asList(c, e, b, f)); treesFirstTwoSorted = new ArrayList<ITree>(Arrays.asList(c, e, b, f));
treesSame = new ArrayList<ITree>(Arrays.asList(h, i)); treesSame = new ArrayList<ITree>(Arrays.asList(h, i));
treesSorted = new ArrayList<ITree>(Arrays.asList(c, e, a, d, f, b)); treesSorted = new ArrayList<ITree>(Arrays.asList(c, e, a, d, f, b));
} }
void init2() { void init2() {
// jacob itaru signorovitch // jacob itaru signorovitch
letters = new ArrayList<>(Arrays.asList( letters = new ArrayList<>(Arrays.asList("j", "a", "c", "o", "b", "i", "t",
"j", "a", "c", "o", "b", "i", "t", "r", "u", "s", "g", "n", "h", "v" "r", "u", "s", "g", "n", "h", "v"));
));
counts = new ArrayList<>( counts = new ArrayList<>(
Arrays.asList(1, 2, 2, 3, 1, 3, 2, 2, 1, 1, 1, 1, 1, 1) Arrays.asList(1, 2, 2, 3, 1, 3, 2, 2, 1, 1, 1, 1, 1, 1));
); }
}
void init3() { void init3() {
// hello world // hello world
letters = letters = new ArrayList<>(Arrays.asList("h", "e", "l", "o", "w", "r", "d"));
new ArrayList<>(Arrays.asList("h", "e", "l", "o", "w", "r", "d")); counts = new ArrayList<>(Arrays.asList(1, 1, 3, 2, 1, 1, 1));
counts = new ArrayList<>(Arrays.asList(1, 1, 3, 2, 1, 1, 1)); huff = new Huffman(letters, counts);
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 or
o e
) )
or
o
)
or
(
l
or or
( (
l d
or or
( (
d w
or or
( r
w
or
r
)
) )
) )
) )
)
*/ */
} }
void testUtilInsertIntoSorted(Tester t) { void testUtilInsertIntoSorted(Tester t) {
init(); init();
Util.insertIntoSorted(c, treesSomeSorted); Util.insertIntoSorted(c, treesSomeSorted);
t.checkExpect( t.checkExpect(treesSomeSorted,
treesSomeSorted, new ArrayList<ITree>(Arrays.asList(c, e, d, f)) new ArrayList<ITree>(Arrays.asList(c, e, d, f)));
); Util.insertIntoSorted(a, treesSomeSorted);
Util.insertIntoSorted(a, treesSomeSorted); t.checkExpect(treesSomeSorted,
t.checkExpect( 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(treesSomeSorted,
Util.insertIntoSorted(b, treesSomeSorted); new ArrayList<ITree>(Arrays.asList(c, e, a, d, f, b)));
t.checkExpect( Util.insertIntoSorted(j, treesSame);
treesSomeSorted, t.checkExpect(treesSame, new ArrayList<ITree>(Arrays.asList(h, i, j)));
new ArrayList<ITree>(Arrays.asList(c, e, a, d, f, b)) }
);
Util.insertIntoSorted(j, treesSame);
t.checkExpect(treesSame, new ArrayList<ITree>(Arrays.asList(h, i, j)));
}
void testUtilInsert(Tester t) { void testUtilInsert(Tester t) {
init(); init();
Util.insert(a, treesFirstTwoSorted, 2); Util.insert(a, treesFirstTwoSorted, 2);
t.checkExpect( t.checkExpect(treesFirstTwoSorted,
treesFirstTwoSorted, new ArrayList<ITree>(Arrays.asList(c, e, a, b, f)));
new ArrayList<ITree>(Arrays.asList(c, e, a, b, f)) Util.insert(g, treesFirstTwoSorted, 3);
); t.checkExpect(treesFirstTwoSorted,
Util.insert(g, treesFirstTwoSorted, 3); new ArrayList<ITree>(Arrays.asList(c, e, a, g, b, f)));
t.checkExpect( }
treesFirstTwoSorted,
new ArrayList<ITree>(Arrays.asList(c, e, a, g, b, f))
);
}
void testUtilSort(Tester t) { void testUtilSort(Tester t) {
init(); init();
ArrayList<ITree> treesSortedCp = treesSorted; ArrayList<ITree> treesSortedCp = treesSorted;
Util.sort(treesSortedCp); Util.sort(treesSortedCp);
t.checkExpect(treesSortedCp, treesSorted); t.checkExpect(treesSortedCp, treesSorted);
Util.sort(trees); Util.sort(trees);
t.checkExpect(trees, treesSorted); t.checkExpect(trees, treesSorted);
} }
void testUtilEnlist(Tester t) { void testUtilEnlist(Tester t) {
String s = "Hello"; String s = "Hello";
t.checkExpect( t.checkExpect(Util.enlist(s), new ArrayList<String>(
Util.enlist(s), Arrays.asList("H", "e", "l", "l", "o")));
new ArrayList<String>(Arrays.asList("H", "e", "l", "l", "o"))
);
String s2 = "h"; String s2 = "h";
t.checkExpect( t.checkExpect(Util.enlist(s2), new ArrayList<String>(Arrays.asList("h")));
Util.enlist(s2), new ArrayList<String>(Arrays.asList("h")) }
);
}
void testHuffmanMkcode(Tester t) { void testHuffmanMkcode(Tester t) {
init(); init();
Huffman h = new Huffman( Huffman h = new Huffman(new ArrayList<String>(Arrays.asList("a", "b")),
new ArrayList<String>(Arrays.asList("a", "b")), new ArrayList<Integer>(Arrays.asList(1, 1)));
new ArrayList<Integer>(Arrays.asList(1, 1))
);
t.checkExpect( t.checkExpect(h.code, new Node(2, new Leaf(1, "a"), new Leaf(1, "b")));
h.code, new Node(2, "b", new Leaf(1, "a"), new Leaf(1, "b"))
);
Huffman h2 = new Huffman( Huffman h2 = new Huffman(
new ArrayList<String>(Arrays.asList("a", "b", "c", "d", "e")), new ArrayList<String>(Arrays.asList("a", "b", "c", "d", "e")),
new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5)) new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5)));
);
// 1: a:1, b:2, c:3, d:4, e:5 // 1: a:1, b:2, c:3, d:4, e:5
// 2: (a:1|b:2):3, 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 // 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 // 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 // 5: (((a:1|b:2):3|:3):6|(d:4|e:5):9):15
t.checkExpect( t.checkExpect(
h2.code, h2.code,
new Node(15,
new Node(6, new Node(3, new Leaf(1, "a"), new Leaf(2, "b")),
new Leaf(3, "c")),
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( new Node(
15, "e", 4,
new Node( new Node(
6, "c", 2,
new Node(3, "b", new Leaf(1, "a"), new Leaf(2, "b")), new Leaf(1, "h"), // //
new Leaf(3, "c") new Leaf(1, "e")),
), new Leaf(2, "o")),
new Node(9, "e", new Leaf(4, "d"), new Leaf(5, "e"))
)
);
}
void testHuffmanEncode(Tester t) {
init3();
t.checkExpect(
huff.code,
new Node( new Node(
10, "lrwdoeh", 6,
new Node( new Node(
4, "oeh", 3,
new Node(2, "eh", new Leaf(1, "h"), new Leaf(1, "e")), new Leaf(1, "d"), // //
new Leaf(2, "o")
),
new Node(
6, "lrwd",
new Node( new Node(
3, "rwd", new Leaf(1, "d"), 2,
new Node(2, "rw", new Leaf(1, "w"), new Leaf(1, "r")) new Leaf(1, "w"), // //
), new Leaf(1, "r"))),
new Leaf(3, "l") new Leaf(3, "l"))));
)
)
);
t.checkExpect( ArrayList<Boolean> path =
huff.encode("he"), new ArrayList<Boolean>(Arrays.asList( new ArrayList<>(Arrays.asList(false, false, false));
false, false, false, false, false, true
)) ArrayList<Boolean> path2 =
); new ArrayList<>(Arrays.asList(false, false, false, false, false, true,
} true, true, true, true, false, true));
ArrayList<Boolean> path3 = new ArrayList<>(
Arrays.asList(false, false, false, false, false, true, true, true, true,
true, false, true, true, false, true, false, false, true,
true, false, true, true, true, true, true, false, false));
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("helloworld"), path3);
t.checkExpect(huff.decode(path3), "helloworld");
Huffman huff2 = new Huffman("foo bar baz");
ArrayList<Boolean> enc = huff2.encode("booz farz fazz");
t.checkExpect(huff2.decode(enc), "booz farz fazz");
}
} }
class Huffman { class Huffman {
ArrayList<String> charset; // Character set. ArrayList<String> charset; // Character set.
ArrayList<Integer> freqs; // Frequencies of characters in charset. ArrayList<Integer> freqs; // Frequencies of characters in charset.
ITree code; // The tree allowing for encoding and decoding. ITree code; // The tree allowing for encoding and decoding.
ArrayList<ArrayList<Boolean>> map; // Association between the charset and the
// path to reach that char in the code.
Huffman(ArrayList<String> charset, ArrayList<Integer> freqs) { Huffman(ArrayList<String> charset, ArrayList<Integer> freqs) {
if (charset.size() != freqs.size()) if (charset.size() != freqs.size())
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Character set must match frequencies." "Character set must match frequencies.");
);
if (charset.size() < 2) if (charset.size() < 2)
throw new IllegalArgumentException("Character set too small."); throw new IllegalArgumentException("Character set too small.");
this.charset = charset; this.charset = charset;
this.freqs = freqs; this.freqs = freqs;
this.mkcode(); this.map = new ArrayList<>();
// Generate the code.
this.mkcode();
// Generate map.
this.mkmap();
}
// Generates character freqs from string.
Huffman(String data) {
if (data.length() <= 1)
throw new Error("Can't create tree from that.");
ArrayList<String> charset = new ArrayList<>();
ArrayList<Integer> 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);
}
} }
// Creates the code tree. this.charset = charset;
void mkcode() { this.freqs = freqs;
ArrayList<ITree> nodes = new ArrayList<>(); this.map = new ArrayList<>();
// Copy all chars over as a tree leaves. // Generate the code.
for (int i = 0; i < this.charset.size(); i++) this.mkcode();
nodes.add(new Leaf(this.freqs.get(i), this.charset.get(i)));
// Combine until all under a single tree. // Generate map.
while (nodes.size() > 1) { this.mkmap();
// Sort the nodes. }
Util.sort(nodes);
// Move the 2 lowest into their own tree. // Creates the code tree.
ITree firstLowest = nodes.get(0); void mkcode() {
ITree secondLowest = nodes.get(1); ArrayList<ITree> nodes = new ArrayList<>();
nodes.remove(firstLowest);
nodes.remove(secondLowest);
ITree parent = new Node(
firstLowest.sumFreq(secondLowest), firstLowest.getQuestion(),
firstLowest, secondLowest
);
// Put new tree into list. // Copy all chars over as a tree leaves.
nodes.add(0, parent); for (int i = 0; i < this.charset.size(); i++)
} nodes.add(new Leaf(this.freqs.get(i), this.charset.get(i)));
// Set the code to the first (and hopefully only) tree. // Combine until all under a single tree.
this.code = nodes.getFirst(); while (nodes.size() > 1) {
// Sort the nodes.
Util.sort(nodes);
// 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.
nodes.add(0, parent);
} }
// Encode a message. // Set the code to the first (and hopefully only) tree.
ArrayList<Boolean> encode(String s) { this.code = nodes.getFirst();
System.out.println("Encoding " + s); }
System.out.flush();
ArrayList<String> msg = // Make the character path mapping.
Util.enlist(s); // The given message, as a list of characters. void mkmap() {
ArrayList<Boolean> enc = for (String ch : this.charset)
new ArrayList<>(); // The returned encoded message. this.map.addLast(this.code.encode(ch));
}
// Loop for each character in the message. // Encode a message.
for (String ch : msg) enc.addAll(this.encodeCh(ch)); ArrayList<Boolean> encode(String s) {
return enc; ArrayList<String> msg =
} Util.enlist(s); // The given message, as a list of characters.
ArrayList<Boolean> enc = new ArrayList<>(); // The returned encoded message.
// Encode a character. // Loop for each character in the message.
ArrayList<Boolean> encodeCh(String ch) { for (String ch : msg)
System.out.println("Encoding character " + ch); enc.addAll(this.encodeCh(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); return enc;
} }
// Encode a character.
ArrayList<Boolean> 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<Boolean> enc) { return this.code.follow(enc); }
} }
// Binary tree. // Binary tree.
interface ITree { interface ITree {
// Compare this and another tree, and return the lesser of the two. // Compare this and another tree, and return the lesser of the two.
boolean lessThan(ITree n); boolean lessThan(ITree n);
// Is this tree less than the given frequency? // Is this tree less than the given frequency?
boolean lessThan(int freq); boolean lessThan(int freq);
// Sum the frequency with another tree. // Sum the frequency with another tree.
int sumFreq(ITree t); int sumFreq(ITree t);
int sumFreq(int freq); int sumFreq(int freq);
// Return its question (the values on the right). // Encode a character.
String getQuestion(); ArrayList<Boolean> encode(String ch);
ArrayList<Boolean> encode(String ch, ArrayList<Boolean> encodingSoFar);
// Encode a character. // Follow (decode) a path.
ArrayList<Boolean> encode(String ch); String follow(ArrayList<Boolean> path);
ArrayList<Boolean> String followCh(ArrayList<Boolean> path);
encodeHelper(String ch, ArrayList<Boolean> encodingSoFar);
} }
abstract class ATree implements ITree { 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(ITree n) { return n.lessThan(this.freq); }
public boolean lessThan(int freq) { return this.freq < freq; } public boolean lessThan(int freq) { return this.freq < freq; }
public int sumFreq(ITree t) { return t.sumFreq(this.freq); } public int sumFreq(ITree t) { return t.sumFreq(this.freq); }
public int sumFreq(int freq) { return this.freq + freq; } public int sumFreq(int freq) { return this.freq + freq; }
} }
class Node extends ATree { class Node extends ATree {
// Left (false) and right (true) branches of tree. // Left (false) and right (true) branches of tree.
ITree l, r; ITree l, r;
// The 'question' the node asks to determine whether to go left or right. If Node(int freq, ITree l, ITree r) {
// the character is in the string, go right. super(freq);
String question; this.l = l;
this.r = r;
}
Node(int freq, String question, ITree l, ITree r) { public ArrayList<Boolean> encode(String ch) {
super(freq); ArrayList<Boolean> ret = new ArrayList<>();
this.question = question; ret.addAll(this.l.encode(ch, new ArrayList<>(Arrays.asList(false))));
this.l = l; ret.addAll(this.r.encode(ch, new ArrayList<>(Arrays.asList(true))));
this.r = r; return ret;
}
public ArrayList<Boolean> encode(String ch,
ArrayList<Boolean> encodingSoFar) {
ArrayList<Boolean> ret = new ArrayList<>(),
left = new ArrayList<Boolean>(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<Boolean> path) {
String ret = "";
// Each loop is 1 character.
while (path.size() > 0) {
Boolean b = path.getFirst();
path.removeFirst();
ret += b ? this.r.followCh(path) : this.l.followCh(path);
} }
public String getQuestion() { return this.question; } return ret;
}
public ArrayList<Boolean> encode(String ch) { public String followCh(ArrayList<Boolean> path) {
Boolean b = this.question.contains(ch); if (path.size() <= 0)
System.out.println( throw new Error("Invalid path.");
"I'm a node encoding " + ch + " and going " + (b ? "right" : "left") Boolean b = path.getFirst();
); path.removeFirst();
System.out.flush(); return b ? this.r.followCh(path) : this.l.followCh(path);
}
// 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)));
}
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);
}
} }
class Leaf extends ATree { class Leaf extends ATree {
String ch; // The character. String ch; // The character.
Leaf(int freq, String ch) { Leaf(int freq, String ch) {
super(freq); super(freq);
this.ch = ch; this.ch = ch;
} }
public String getQuestion() { return this.ch; } public ArrayList<Boolean> encode(String ch) {
throw new Error("Can't, fool.");
}
public ArrayList<Boolean> encode(String ch) { public ArrayList<Boolean> encode(String ch,
System.out.println("I'm a leaf encoding " + ch); ArrayList<Boolean> encodingSoFar) {
System.out.flush(); if (ch.equals(this.ch))
throw new Error("Cannot encode a Leaf."); return encodingSoFar;
} else
return new ArrayList<Boolean>();
}
public ArrayList<Boolean> public String follow(ArrayList<Boolean> path) {
encodeHelper(String ch, ArrayList<Boolean> encodingSoFar) { throw new Error("Shouldn't call follow() on leaf.");
System.out.println("I'm a leaf encode helping " + ch); }
System.out.flush(); public String followCh(ArrayList<Boolean> path) { return this.ch; }
return encodingSoFar; public String follow(ArrayList<Boolean> path, String soFar) {
} return soFar.concat(this.ch);
}
} }
class Util { class Util {
// Sort a list of trees from least to most frequent. // Sort a list of trees from least to most frequent.
static void sort(ArrayList<ITree> trees) { static void sort(ArrayList<ITree> trees) {
// Our work here is done. // Our work here is done.
if (trees.size() < 2) return; if (trees.size() < 2)
return;
for (int i = 1; i < trees.size(); i++) { for (int i = 1; i < trees.size(); i++) {
// Copy out the tree to insert. // Copy out the tree to insert.
ITree tree = trees.get(i); ITree tree = trees.get(i);
trees.remove(tree); trees.remove(tree);
// Insert it. // Insert it.
insert(tree, trees, i); insert(tree, trees, i);
}
} }
}
// Insert a Tree into an ArrayList of trees already sorted in [0, i), where // 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]. // 0 <= i <= trees.size(), such that it is sorted through [0, i].
static void insert(ITree tree, ArrayList<ITree> trees, int i) { static void insert(ITree tree, ArrayList<ITree> trees, int i) {
// Extract sorted. // Extract sorted.
ArrayList<ITree> sorted = new ArrayList<>(trees.subList(0, i)); ArrayList<ITree> sorted = new ArrayList<>(trees.subList(0, i));
// Insert tree. // Insert tree.
insertIntoSorted(tree, sorted); insertIntoSorted(tree, sorted);
// Overwrite original trees with sorted ones. // Overwrite original trees with sorted ones.
for (int j = 0; j < i; trees.set(j, sorted.get(j++))); for (int j = 0; j < i; trees.set(j, sorted.get(j++)))
// Insert the last tree back in. ;
trees.add(i, sorted.getLast()); // Insert the last tree back in.
} trees.add(i, sorted.getLast());
}
// Insert a Tree in an already fully sorted ArrayList of Trees. // Insert a Tree in an already fully sorted ArrayList of Trees.
static void insertIntoSorted(ITree tree, ArrayList<ITree> sortedTrees) { static void insertIntoSorted(ITree tree, ArrayList<ITree> sortedTrees) {
for (int i = 0; i < sortedTrees.size(); i++) for (int i = 0; i < sortedTrees.size(); i++)
if (sortedTrees.get(i).lessThan(tree)) { if (sortedTrees.get(i).lessThan(tree)) {
sortedTrees.add(i, tree); // sortedTrees.add(i, tree); //
return; return;
} }
sortedTrees.addLast(tree); // This tree is bigger than all the others. sortedTrees.addLast(tree); // This tree is bigger than all the others.
} }
// Convert a string to a list. // Convert a string to a list.
static ArrayList<String> enlist(String s) { static ArrayList<String> enlist(String s) {
ArrayList<String> ret = new ArrayList<>(); ArrayList<String> ret = new ArrayList<>();
for (int i = 0; i < s.length(); i++) for (int i = 0; i < s.length(); ret.add(String.valueOf(s.charAt(i++))))
ret.add(String.valueOf(s.charAt(i))); ;
return ret; return ret;
} }
} }

View File

@@ -386,6 +386,7 @@ class Game extends World {
} }
public Game onKeyEvent(String key) { public Game onKeyEvent(String key) {
if (this.guessesLeft <= 0) throw new Error("Done.");
if ("123456789".contains(key)) { // User has entered a number. if ("123456789".contains(key)) { // User has entered a number.
int choice = Integer.valueOf(key); int choice = Integer.valueOf(key);
if (choice <= this.conf.options.len()) return this.addDot( if (choice <= this.conf.options.len()) return this.addDot(

View File

@@ -1,41 +0,0 @@
// Zed settings
//
// For information on how to configure Zed, see the Zed
// documentation: https://zed.dev/docs/configuring-zed
//
// To see all of Zed's default settings without changing your
// custom settings, run `zed: open default settings` from the
// command palette (cmd-shift-p / ctrl-shift-p)
{
// GENERAL SETTINGS
"outline_panel": {
"dock": "right"
},
"vim_mode": true,
// UI SETTINGS
"ui_font_size": 16,
"ui_font_family": "Iosevka Sans Ligless",
// BUFFER SETTINGS
"buffer_font_size": 16,
"buffer_font_family": "Iosevka Mono Ligless",
// BEHAVIOR SETTINGS
"languages": {
"Java": {
"formatter": {
"external": {
"command": "clang-format",
"arguments": ["--style=file", "--assume-filename={buffer_path}"]
}
},
"format_on_save": "on"
}
},
"wrap_guides": [80],
// MISC OTHER
"theme": {
"mode": "system",
"light": "Gruvbox Light",
"dark": "Gruvbox Dark"
}
}