diff --git a/huffman_coding/src/huffman_coding/Main.java b/huffman_coding/src/huffman_coding/Main.java index 67d441c..b7b5dfa 100644 --- a/huffman_coding/src/huffman_coding/Main.java +++ b/huffman_coding/src/huffman_coding/Main.java @@ -6,439 +6,492 @@ 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 - or - e - ) + h or - o + e ) + or + o + ) + or + ( + l or ( - l + d or ( - d + w or - ( - w - or - r - ) + 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, "b", 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, + t.checkExpect( + 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( - 15, "e", + 4, new Node( - 6, "c", - new Node(3, "b", new Leaf(1, "a"), new Leaf(2, "b")), - new Leaf(3, "c") - ), - new Node(9, "e", new Leaf(4, "d"), new Leaf(5, "e")) - ) - ); - } - - void testHuffmanEncode(Tester t) { - init3(); - t.checkExpect( - huff.code, + 2, + new Leaf(1, "h"), // // + new Leaf(1, "e")), + new Leaf(2, "o")), new Node( - 10, "lrwdoeh", + 6, new Node( - 4, "oeh", - new Node(2, "eh", new Leaf(1, "h"), new Leaf(1, "e")), - new Leaf(2, "o") - ), - new Node( - 6, "lrwd", + 3, + new Leaf(1, "d"), // // new Node( - 3, "rwd", new Leaf(1, "d"), - new Node(2, "rw", new Leaf(1, "w"), new Leaf(1, "r")) - ), - new Leaf(3, "l") - ) - ) - ); + 2, + 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 - )) - ); - } + ArrayList path = + new ArrayList<>(Arrays.asList(false, false, false)); + + ArrayList path2 = + new ArrayList<>(Arrays.asList(false, false, false, false, false, true, + true, true, true, true, false, true)); + + ArrayList 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 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 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.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 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); + } } - // Creates the code tree. - void mkcode() { - 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.mkcode(); - // Combine until all under a single tree. - while (nodes.size() > 1) { - // Sort the nodes. - Util.sort(nodes); + // Generate map. + this.mkmap(); + } - // 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.getQuestion(), - firstLowest, secondLowest - ); + // Creates the code tree. + void mkcode() { + ArrayList nodes = new ArrayList<>(); - // Put new tree into list. - nodes.add(0, parent); - } + // 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))); - // Set the code to the first (and hopefully only) tree. - this.code = nodes.getFirst(); + // Combine until all under a single tree. + 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. - ArrayList encode(String s) { - System.out.println("Encoding " + s); - System.out.flush(); + // Set the code to the first (and hopefully only) tree. + this.code = nodes.getFirst(); + } - ArrayList msg = - Util.enlist(s); // The given message, as a list of characters. - ArrayList enc = - new ArrayList<>(); // The returned encoded message. + // Make the character path mapping. + void mkmap() { + for (String ch : this.charset) + this.map.addLast(this.code.encode(ch)); + } - // Loop for each character in the message. - for (String ch : msg) enc.addAll(this.encodeCh(ch)); + // Encode a message. + ArrayList encode(String s) { - return enc; - } + ArrayList msg = + Util.enlist(s); // The given message, as a list of characters. + ArrayList enc = new ArrayList<>(); // The returned encoded message. - // 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 + "\"." - ); + // Loop for each character in the message. + for (String ch : msg) + enc.addAll(this.encodeCh(ch)); - return this.code.encode(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); - // Return its question (the values on the right). - String getQuestion(); + // Encode a character. + ArrayList encode(String ch); + ArrayList encode(String ch, ArrayList encodingSoFar); - // Encode a character. - ArrayList encode(String ch); - ArrayList - encodeHelper(String ch, ArrayList encodingSoFar); + // 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; - // The 'question' the node asks to determine whether to go left or right. If - // the character is in the string, go right. - String question; + Node(int freq, ITree l, ITree r) { + super(freq); + this.l = l; + this.r = r; + } - Node(int freq, String question, ITree l, ITree r) { - super(freq); - this.question = question; - 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) { + 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 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))); - } - - 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); - } + 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 String getQuestion() { return this.ch; } + public ArrayList encode(String ch) { + throw new Error("Can't, fool."); + } - 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 encode(String ch, + ArrayList encodingSoFar) { + if (ch.equals(this.ch)) + return encodingSoFar; + else + return new ArrayList(); + } - public ArrayList - encodeHelper(String ch, ArrayList encodingSoFar) { - System.out.println("I'm a leaf encode helping " + ch); - System.out.flush(); - return encodingSoFar; - } + 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(); i++) - 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/mastermind/src/mastermind/Main.java b/mastermind/src/mastermind/Main.java index c00d051..45479ae 100644 --- a/mastermind/src/mastermind/Main.java +++ b/mastermind/src/mastermind/Main.java @@ -386,6 +386,7 @@ class Game extends World { } public Game onKeyEvent(String key) { + if (this.guessesLeft <= 0) throw new Error("Done."); if ("123456789".contains(key)) { // User has entered a number. int choice = Integer.valueOf(key); if (choice <= this.conf.options.len()) return this.addDot( diff --git a/settings.json b/settings.json deleted file mode 100644 index d3f0f13..0000000 --- a/settings.json +++ /dev/null @@ -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" - } -} -