This commit is contained in:
2025-02-01 17:02:24 -05:00
parent 8a264d7dfc
commit 677f82fc8a
6 changed files with 599 additions and 389 deletions

13
.clang-format Normal file
View File

@@ -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

View File

@@ -38,16 +38,19 @@ class Examples {
void init2() { void init2() {
// jacob itaru signorovitch // jacob itaru signorovitch
letters = new ArrayList<>(Arrays.asList("j", "a", "c", "o", "b", "i", "t", letters = new ArrayList<>(Arrays.asList(
"r", "u", "s", "g", "n", "h", "v")); "j", "a", "c", "o", "b", "i", "t", "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 = new ArrayList<>(Arrays.asList("h", "e", "l", "o", "w", "r", "d")); letters =
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);
@@ -88,14 +91,18 @@ class Examples {
void testUtilInsertIntoSorted(Tester t) { void testUtilInsertIntoSorted(Tester t) {
init(); init();
Util.insertIntoSorted(c, treesSomeSorted); Util.insertIntoSorted(c, treesSomeSorted);
t.checkExpect(treesSomeSorted, t.checkExpect(
new ArrayList<ITree>(Arrays.asList(c, e, d, f))); treesSomeSorted, 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); Util.insertIntoSorted(b, treesSomeSorted);
t.checkExpect(treesSomeSorted, t.checkExpect(
new ArrayList<ITree>(Arrays.asList(c, e, a, d, f, b))); treesSomeSorted,
new ArrayList<ITree>(Arrays.asList(c, e, a, d, f, b))
);
Util.insertIntoSorted(j, treesSame); Util.insertIntoSorted(j, treesSame);
t.checkExpect(treesSame, new ArrayList<ITree>(Arrays.asList(h, i, j))); t.checkExpect(treesSame, new ArrayList<ITree>(Arrays.asList(h, i, j)));
} }
@@ -103,11 +110,15 @@ class Examples {
void testUtilInsert(Tester t) { void testUtilInsert(Tester t) {
init(); init();
Util.insert(a, treesFirstTwoSorted, 2); Util.insert(a, treesFirstTwoSorted, 2);
t.checkExpect(treesFirstTwoSorted, t.checkExpect(
new ArrayList<ITree>(Arrays.asList(c, e, a, b, f))); treesFirstTwoSorted,
new ArrayList<ITree>(Arrays.asList(c, e, a, b, f))
);
Util.insert(g, treesFirstTwoSorted, 3); Util.insert(g, treesFirstTwoSorted, 3);
t.checkExpect(treesFirstTwoSorted, t.checkExpect(
new ArrayList<ITree>(Arrays.asList(c, e, a, g, b, f))); treesFirstTwoSorted,
new ArrayList<ITree>(Arrays.asList(c, e, a, g, b, f))
);
} }
void testUtilSort(Tester t) { void testUtilSort(Tester t) {
@@ -123,23 +134,30 @@ class Examples {
void testUtilEnlist(Tester t) { void testUtilEnlist(Tester t) {
String s = "Hello"; String s = "Hello";
t.checkExpect(Util.enlist(s), new ArrayList<String>( t.checkExpect(
Arrays.asList("H", "e", "l", "l", "o"))); Util.enlist(s),
new ArrayList<String>(Arrays.asList("H", "e", "l", "l", "o"))
);
String s2 = "h"; String s2 = "h";
t.checkExpect(Util.enlist(s2), new ArrayList<String>(Arrays.asList("h"))); t.checkExpect(
Util.enlist(s2), new ArrayList<String>(Arrays.asList("h"))
);
} }
void testHuffmanMkcode(Tester t) { void testHuffmanMkcode(Tester t) {
init(); init();
Huffman h = new Huffman(new ArrayList<String>(Arrays.asList("a", "b")), Huffman h = new Huffman(
new ArrayList<Integer>(Arrays.asList(1, 1))); new ArrayList<String>(Arrays.asList("a", "b")),
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, 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
@@ -148,50 +166,68 @@ class Examples {
// 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(
new Node(15, 15,
new Node(6, new Leaf(3, "c"), new Node(
new Node(3, new Leaf(1, "a"), new Leaf(2, "b"))), 6, new Leaf(3, "c"),
new Node(9, new Leaf(4, "d"), new Leaf(5, "e")))); 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) { void testHuffmanEncodeAndAlsoDecodeAndAlsoEverythingElse(Tester t) {
init3(); init3();
t.checkExpect( t.checkExpect(
huff.code, huff.code, new Node(
new Node(
10, 10,
new Node( new Node(
4, 4,
new Node( new Node(
2, 2,
new Leaf(1, "h"), // // new Leaf(
new Leaf(1, "e")), 1, "h"
), // //
new Leaf(1, "e")
),
new Node( new Node(
2, 2,
new Leaf(1, "w"), // // new Leaf(
new Leaf(1, "r"))), 1, "w"
), // //
new Leaf(1, "r")
)
),
new Node( new Node(
6, 6,
new Leaf(3, "l"), // // new Leaf(
3, "l"
), // //
new Node( new Node(
3, 3,
new Leaf(1, "d"), // // new Leaf(
new Leaf(2, "o"))))); 1, "d"
), // //
new Leaf(2, "o")
)
)
)
);
ArrayList<Boolean> path = ArrayList<Boolean> path =
new ArrayList<>(Arrays.asList(false, false, false)); new ArrayList<>(Arrays.asList(false, false, false));
ArrayList<Boolean> path2 = ArrayList<Boolean> path2 = new ArrayList<>(Arrays.asList(
new ArrayList<>(Arrays.asList(false, false, false, // h false, false, false, // h
false, false, true, // e false, false, true, // e
true, false, // l true, false, // l
true, false, // l true, false, // l
true, true, true // o true, true, true // o
)); ));
ArrayList<Boolean> path3 = ArrayList<Boolean> path3 = new ArrayList<>(Arrays.asList(
new ArrayList<>(Arrays.asList(false, false, false, // h false, false, false, // h
false, false, true, // e false, false, true, // e
true, false, // l true, false, // l
true, false, // l true, false, // l
@@ -223,13 +259,15 @@ 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 ArrayList<ArrayList<Boolean>>
map; // Association between the charset and the
// path to reach that char in the code. // 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.");
@@ -248,8 +286,7 @@ class Huffman {
// Generates character freqs from string. // Generates character freqs from string.
Huffman(String data) { Huffman(String data) {
if (data.length() <= 1) if (data.length() <= 1) throw new Error("Can't create tree from that.");
throw new Error("Can't create tree from that.");
ArrayList<String> charset = new ArrayList<>(); ArrayList<String> charset = new ArrayList<>();
ArrayList<Integer> freqs = new ArrayList<>(); ArrayList<Integer> freqs = new ArrayList<>();
@@ -294,8 +331,9 @@ class Huffman {
ITree secondLowest = nodes.get(1); ITree secondLowest = nodes.get(1);
nodes.remove(firstLowest); nodes.remove(firstLowest);
nodes.remove(secondLowest); nodes.remove(secondLowest);
ITree parent = new Node(firstLowest.sumFreq(secondLowest), firstLowest, ITree parent = new Node(
secondLowest); firstLowest.sumFreq(secondLowest), firstLowest, secondLowest
);
// Put new tree into list. // Put new tree into list.
Util.insertIntoSorted(parent, nodes); Util.insertIntoSorted(parent, nodes);
@@ -307,8 +345,7 @@ class Huffman {
// Make the character path mapping. // Make the character path mapping.
void makeMap() { void makeMap() {
for (String ch : this.charset) for (String ch : this.charset) this.map.addLast(this.code.encode(ch));
this.map.addLast(this.code.encode(ch));
} }
// Encode a message. // Encode a message.
@@ -316,11 +353,11 @@ class Huffman {
ArrayList<String> msg = ArrayList<String> msg =
Util.enlist(s); // The given message, as a list of characters. Util.enlist(s); // The given message, as a list of characters.
ArrayList<Boolean> enc = new ArrayList<>(); // The returned encoded message. ArrayList<Boolean> enc =
new ArrayList<>(); // The returned encoded message.
// Loop for each character in the message. // Loop for each character in the message.
for (String ch : msg) for (String ch : msg) enc.addAll(this.encodeCh(ch));
enc.addAll(this.encodeCh(ch));
return enc; return enc;
} }
@@ -329,8 +366,9 @@ class Huffman {
ArrayList<Boolean> encodeCh(String ch) { ArrayList<Boolean> encodeCh(String ch) {
// Throw error if character is not in charset. // Throw error if character is not in charset.
if (!this.charset.contains(ch)) if (!this.charset.contains(ch))
throw new IllegalArgumentException("Cannot encode unknown character \"" + throw new IllegalArgumentException(
ch + "\"."); "Cannot encode unknown character \"" + ch + "\"."
);
int i = this.charset.indexOf(ch); int i = this.charset.indexOf(ch);
return this.map.get(i); return this.map.get(i);
@@ -391,8 +429,8 @@ class Node extends ATree {
return ret; return ret;
} }
public ArrayList<Boolean> encode(String ch, public ArrayList<Boolean>
ArrayList<Boolean> encodingSoFar) { encode(String ch, ArrayList<Boolean> encodingSoFar) {
ArrayList<Boolean> ret = new ArrayList<>(), ArrayList<Boolean> ret = new ArrayList<>(),
left = new ArrayList<Boolean>(Arrays.asList(false)), left = new ArrayList<Boolean>(Arrays.asList(false)),
right = new ArrayList<>(Arrays.asList(true)); right = new ArrayList<>(Arrays.asList(true));
@@ -406,7 +444,8 @@ class Node extends ATree {
} }
public String follow(ArrayList<Boolean> path) { public String follow(ArrayList<Boolean> path) {
ArrayList<Boolean> pathcpy = path; ArrayList<Boolean> pathcpy = new ArrayList<>();
for (Boolean b : path) pathcpy.add(b);
String ret = ""; String ret = "";
// Each loop is 1 character. // Each loop is 1 character.
@@ -420,8 +459,7 @@ class Node extends ATree {
} }
public String followCh(ArrayList<Boolean> path) { public String followCh(ArrayList<Boolean> path) {
if (path.size() <= 0) if (path.size() <= 0) throw new Error("Invalid path.");
throw new Error("Invalid path.");
Boolean b = path.getFirst(); Boolean b = path.getFirst();
path.removeFirst(); path.removeFirst();
return b ? this.r.followCh(path) : this.l.followCh(path); return b ? this.r.followCh(path) : this.l.followCh(path);
@@ -441,12 +479,10 @@ class Leaf extends ATree {
throw new Error("Can't, fool."); throw new Error("Can't, fool.");
} }
public ArrayList<Boolean> encode(String ch, public ArrayList<Boolean>
ArrayList<Boolean> encodingSoFar) { encode(String ch, ArrayList<Boolean> encodingSoFar) {
if (ch.equals(this.ch)) if (ch.equals(this.ch)) return encodingSoFar;
return encodingSoFar; else return new ArrayList<Boolean>();
else
return new ArrayList<Boolean>();
} }
public String follow(ArrayList<Boolean> path) { public String follow(ArrayList<Boolean> path) {
@@ -463,8 +499,7 @@ 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) if (trees.size() < 2) return;
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.
@@ -483,8 +518,7 @@ class Util {
// 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. // Insert the last tree back in.
trees.add(i, sorted.getLast()); trees.add(i, sorted.getLast());
} }
@@ -502,8 +536,7 @@ class Util {
// 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(); ret.add(String.valueOf(s.charAt(i++)))) for (int i = 0; i < s.length(); ret.add(String.valueOf(s.charAt(i++))));
;
return ret; return ret;
} }
} }

28
traversal/.project Normal file
View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>traversal</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<filteredResources>
<filter>
<id>1736900497</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View File

@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@@ -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

View File

@@ -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> {
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<X> leftIterator(DFTIterator<X> f);
// produce an iterator for the right child, or an empty iterator if one does
// not exist
abstract Iterator<X> rightIterator(DFTIterator<X> f);
// add this node's children, if they exist, to the queue (left then right)
abstract void addChildrenToQueue(Queue<BT<X>> queue);
}
class Leaf<X> extends BT<X> {
Iterator<X> leftIterator(DFTIterator<X> f) {
throw new NoSuchElementException();
}
Iterator<X> rigtIterator(DFTIterator<X> f) {
throw new NoSuchElementException();
}
void addChildrenToQueue(Queue<BT<X>> queue) { queue.add(this); }
Leaf(X value) { super(value); }
}
class Node<X> extends BT<X> {
BT<X> left;
BT<X> right;
Node(X value, BT<X> left, BT<X> right) {
super(value);
this.left = left;
this.right = right;
}
Iterator<X> leftIterator(DFTIterator<X> f) {
return this.left.leftIterator(f);
}
Iterator<X> rightIterator(DFTIterator<X> f) {
return this.right.rightIterator(f);
}
void addChildrenToQueue(Queue<BT<X>> queue) {
this.left.addChildrenToQueue(queue);
this.right.addChildrenToQueue(queue);
}
}
// a depth first iterator for a BT
interface DFTIterator<X> extends Iterator<X> {
// produce a depth first traversal iterator for the given BT
DFTIterator<X> iterate(BT<X> x);
}
abstract class DFT<X> implements DFTIterator<X> {
BT<X> bt;
Iterator<X> left;
Iterator<X> right;
// has the top-level value of bt been iterated over yet
boolean nodeGiven;
DFT(BT<X> 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<X> extends DFT<X> {
InOrder(BT<X> bt) { super(bt); }
public DFTIterator<X> iterate(BT<X> x) { return new InOrder<X>(x); }
}
class PreOrder<X> extends DFT<X> {
PreOrder(BT<X> bt) { super(bt); }
public DFTIterator<X> iterate(BT<X> x) { return new PreOrder<X>(x); }
}
class PostOrder<X> extends DFT<X> {
PostOrder(BT<X> bt) { super(bt); }
public DFTIterator<X> iterate(BT<X> x) { return new PostOrder<X>(x); }
}
// a breadth first iterator for a BT
class BFT<X> implements Iterator<X> {
Queue<BT<X>> queue = new LinkedList<BT<X>>();
BFT(BT<X> bt) { queue.add(bt); }
}