/* http://scribbledecobble.blogspot.com/2018/03/angle.html
* by John P. Spurgeon
*
*
*
* CONTENTS
*
* 0. Make Angle great again!
* 1. Interfaces
* 2. BigNum: Avoids Floats & Doubles
* 3. Pseudo-continuous Measure
* 4. Angle Multi-tool
* 5. The Angle Superclass
* 6. Some Angle Subclasses
* 7. Smoke Test Algorithm
* 8. Pseudo-random Data
* 9. Songs
*
*
*
* The use of subclassing is controversial... In this book, we avoid subclassing... [T]he
* designer of a class such as a Vector may have taken great care to make the Vector immutable,
* but a subclass, with full access to those instance variables, can recklessly change them.
*
* — ROBERT SEDGEWICK and KEVIN WAYNE, Computer Science: An Interdisciplinary Approach (2017)
*
*
* You’ll shoot your eye out, kid.
*
* — SANTA CLAUS in “A Christmas Story” (1983)
*/
/*
* Well, here’s your box. Nearly everything I have is in it, and
* it is not full. Pain and excitement are in it, and feeling good or
* bad and evil thoughts and good thoughts — the pleasure of design
* and some despair and the indescribable joy of creation.
*
* — JOHN STEINBECK, dedication of East of Eden (1952)
*
*
* All of the major problems associated with computer programming—issues of
* reliability, portability learnability, maintainability, and efficiency—are
* ameliorated when programs and their dialogs with users become more literate.
*
* — DONALD E. KNUTH, Literate Programming (1992)
*
*
* I believe that the time is ripe for significantly better documentation of
* programs, and that we can best achieve this by considering programs to be works
* of LITERATURE. Hence, my title: “Literate Programming.” ... By coining the phrase
* “literate programming,” I am imposing a moral commitment on everyone who hears
* the term; surely nobody wants to admit writing an ILLITERATE program.
*
* — DONALD E. KNUTH, Literate Programming (1992)
*
*
* [A]n unforeseen problem has, however, arisen: I suddenly have a collection
* of programs that seem quite beautiful in my own eyes, and I have a compelling
* urge to publish all of them so that everyone can admire these works of art.
* ... if I keep accumulating such gems, I'll soon run out of storage space,
* and my office will be encrusted with webs of my own making. There is no
* telling what will happen if lots of other people catch WEB fever
* and start foisting their creations on each other.
*
* — DONALD E. KNUTH, Literate Programming (1992)
*
*
* I’m glad that the idea of STYLE in programming is now coming to the forefront
* at last, and I hope that most of you have seen the excellent little book on
* ELEMENTS OF PROGRAMMING STYLE by Kernighan and Plauger. In this connection it
* is most important for us all to remember that there is no one “best” style;
* everybody has their own preferences, and it is a mistake to try to
* force people into an unnatural mold.
*
* — DONALD E. KNUTH, Literate Programming (1992)
*
*
* Omit needless words.
*
* — STRUNK and WHITE, The Elements of Style (1979)
*
*/
/* 0. Make Angle great again!
*
* It is generally very difficult to keep up with a field that is economically profitable, and
* so it is only natural to expect that today’s standardized systems of measurement will eventually
* be superseded by better ones. The good news is, nobody owns standardization. Systems of
* measurement are in competition with similar systems all over the world. Standards aren’t owed a
* career. They are employed at will. As Michael Corleone said, “The new overthrows the old. It’s
* natural.” Ergo, your software must be Agile to survive.
* Software developers are, first and foremost, businessmen and women. We want no conflict with
* any one. (Get it?) All kidding aside, when someone says they are sure you will find it very
* instructive to actually take all of the data from a given problem and convert it into, say,
* portrzebie units, work the problem in the new system, and then transfer the answer back into the
* original units again, the software developer queries, “How many times?”
* Rounding error and overflow notwithstanding, Angle is the solution to all that ails your app.
* (Who here cares about rounding error and overflow? Raise your hands. That’s what I thought.)
* Suppose you’ve patented new algorithms for division and addition that obviate the angst of all
* the rounding error and overflow worry warts out there. They’re sure to make you billions, give or
* take a few. But it’s not about the money anymore. It’s about world domination. You need everyone
* to pay and pay attention to you. You need fame and immortality. Angle supports units for that!
* Moreover, when the well runs dry — and it will — all you have to do is toss out the old standards
* and invent new ones. Drain the swamp, as they say. If you’ve got Angle, all you gotta do is
* change a few lines of code and you’re good to go to the bank again. But you'll need a great
* campaign slogan. Something really great.
*/
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Comparator;
import java.util.List;
import java.util.Stack;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.SortedSet;
import java.util.TreeSet;
/* 1. Interfaces
*
* “Can you do Addition?” the White Queen asked. “What’s one and one and one and
* one and one and one and one and one and one and one?”
* “I don’t know,” said Alice. “I lost count.”
* “She ca’n’t do Addition,” the Red Queen interupted. “Can you do Subtraction?
* Take nine from eight.”
* “Nine from eight I ca’n’t, you know,” Alice replied very readily: “but——”
* “She ca’n’t do Subtraction,” said the White Queen. “Can you do Division?
*
* — LEWIS CARROLL, Through The Looking Glass (1946)
*/
interface Measure<N extends Comparable<N>> {
N value(); // A possibly negative decimal or integral number.
N size(); // The magnitude (absolute value) of value().
String units(); // The units of size() and value().
}
interface StdMeasure<N extends Comparable<N>> {
N stdValue(); // A standard equivalent of value().
N stdSize(); // The size of stdValue().
String stdUnits(); // The units of stdValue() and stdSize().
}
interface Num extends Comparable<Num> {
/* You can make TINY_PIECE_OF_PI as large as you want, but it will still be very tiny. */
static final String TINY_PIECE_OF_PI = "3.14159265358979323846264338327950288419716939937510";
static final int PRECISION = 16; // Should be limited by length of TINY_PIECE_OF_PI.
static final int ROUND = 14; // Should be limited by PRECISION
static final int DISPLAY = 4; // Should be limited by ROUND
static final Num ZERO = new BigNum("0");
static final Num ONE = new BigNum("1");
static final Num TWO = new BigNum("2");
static final Num PI = new BigNum(TINY_PIECE_OF_PI);
static final Num TAO = TWO.multiply(PI);
Num negate();
Num abs();
Num add(Num augend);
Num subtract(Num subtrahend);
Num multiply(Num multiplicand);
Num divide(Num divisor);
Num remainder(Num divisor);
boolean isEqualTo(Num other);
boolean isLessThan(Num other);
boolean isMoreThan(Num other);
double roundedValue();
BigDecimal bigDecimalValue();
}
interface StdConMeas extends Measure<Num>, StdMeasure<Num> {
// A type that is a mixture of types.
}
/* 2. BigNum: Avoids Floats & Doubles (a precise approach to approximation)
*
* Item 48: Avoid float and double if exact answers are required
*
* — JOSHUA BLOCH, Effective Java (2008)
*/
final class BigNum implements Num {
static final MathContext MC = new MathContext(Num.PRECISION);
static final MathContext ROUND_MC = new MathContext(Num.ROUND);
private final BigDecimal val; // The "wrapped" or "boxed" BigDecimal value.
public BigNum(BigDecimal bigDecimal) { val = bigDecimal; }
public BigNum(Num n) { val = n.bigDecimalValue(); }
public BigNum(String strVal) { val = new BigDecimal(strVal, BigNum.MC); }
public BigNum(Integer n) { this(n.toString()); }
public BigDecimal bigDecimalValue() { return val; }
public final Num abs() { return new BigNum(val.abs(BigNum.MC)); }
public final Num negate() { return new BigNum(val.negate(BigNum.MC)); }
public final Num add(Num n) { return new BigNum(val.add(n.bigDecimalValue(), BigNum.MC)); }
public final Num subtract(Num n) { return new BigNum(val.subtract(n.bigDecimalValue(), BigNum.MC)); }
public final Num multiply(Num n) { return new BigNum(val.multiply(n.bigDecimalValue(), BigNum.MC)); }
public final Num divide(Num n) { return new BigNum(val.divide(n.bigDecimalValue(), BigNum.MC)); }
public final Num remainder(Num n) { return new BigNum(val.remainder(n.bigDecimalValue(), BigNum.MC)); }
public final boolean isEqualTo(Num n) { return subtract(n).roundedValue() == 0; }
public final boolean isLessThan(Num n) { return subtract(n).roundedValue() < 0; }
public final boolean isMoreThan(Num n) { return subtract(n).roundedValue() > 0; }
public final double roundedValue() { return val.round(BigNum.ROUND_MC).doubleValue(); }
public final int compareTo(Num n) { return val.compareTo(n.bigDecimalValue()); }
public boolean equals(Object x) {
if (x == null || !BigNum.class.isAssignableFrom(x.getClass())) return false;
BigNum that = (BigNum) x;
return this.val.equals(that.val);
}
}
/* Eats, Shoots & Leaves: the zero tolerance approach to punctuation
*
* — The title of a book by Lynne Truss (2004)
*/
/* 3. Pseudo-continuous Measure
*
* It is downright sinful to teach the abstract before the concrete.
*
* — Z. A. MELZAK, quoted in Concrete Mathematics (1992)
*/
abstract class PseudoContinuousMeasure implements StdConMeas {
// At the very beginning, let’s decide to pronounce the name right: zee-val, like potter-zee-bee.
protected final Num zVal; // A standardized pidgin or bridge value.
protected PseudoContinuousMeasure(Num convertedVal) { zVal = convertedVal; }
protected PseudoContinuousMeasure(String strVal) { zVal = convertToZVal(strVal); }
protected PseudoContinuousMeasure(StdConMeas other) { zVal = other.stdValue(); }
protected abstract Num toZFactor(); // Implementations should be responsible.
protected abstract Num fromZFactor(); // Implementations should do the right thing.
protected final Num convertFromZVal() { return fromZFactor().multiply(zVal); }
protected final Num convertToZVal(String strVal) { return toZFactor().multiply(new BigNum(strVal)); }
public final Num value() { return convertFromZVal(); }
public final Num size() { return convertFromZVal().abs(); }
public String units() { return stdUnits(); /* Implementations will vary. */ }
public final Num stdValue() { return zVal; }
public final Num stdSize() { return zVal.abs(); }
public abstract String stdUnits(); // The buck should stop somewhere.
public String toString() { return toString(Num.DISPLAY); }
public String toString(int n) {
return valueToString(n) + " (" + stdValueToString(n) + ")";
}
protected String valueToString(int n) {
return PseudoContinuousMeasure.toString(value().roundedValue(), n, units());
}
protected String stdValueToString(int n) {
return PseudoContinuousMeasure.toString(stdValue().roundedValue(), n, stdUnits());
}
protected static String toString(Double value, int decimalPlaces, String units) {
return String.format("%." + decimalPlaces + "f " + units, value);
}
public boolean equals(Object x) {
if (x == null || !PseudoContinuousMeasure.class.isAssignableFrom(x.getClass())) return false;
PseudoContinuousMeasure that = (PseudoContinuousMeasure) x;
return this.zVal.equals(that.zVal) && this.stdUnits().equals(that.stdUnits());
}
}
/* That was Will all over. He scorned the vague, the tame, the colorless, the
* irresolute. He felt it was worse to be irresolute than to be wrong. I remember
* a day in class when he leaned far forward, in his characteristic pose—the pose
* of a man about to impart a secret—and croaked, “If you don’t know how to pronounce
* a word, say it loud! If you don’t know how to pronounce a word, say it loud!”
* This comical piece of advice struck me as sound at the time, and I still
* respect it. Why compound ignorance with inaudibility? Why run and hide?
*
* — E. B. WHITE, The Elements of Style, 3rd ed. (1979)
*/
/* 4. Angle Multi-tool
*
* In recent years, a number of urban and outdoor multi-tools have sprouted offering
* non-traditional tools one would not expect to find in a single unit. Substituting
* a toolbox, these multi-tools functions include a hammer, spirit level, camera
* tripod, LED light, lighter, tape measure and an assortment of screwdriver bits.
*
* — https://en.wikipedia.org/wiki/Multi-tool (accessed 2 April 2018)
*/
final class AngleMultiTool {
private final Num full, half, quarter;
public AngleMultiTool(Num unitsPerCycle) {
full = unitsPerCycle;
half = full.divide(Num.TWO);
quarter = half.divide(Num.TWO);
}
public final boolean isNegative(Num a) { return a.isLessThan(Num.ZERO); }
public final boolean isPositive(Num a) { return a.isMoreThan(Num.ZERO); }
public final boolean isZero(Num a) { return a.isEqualTo(Num.ZERO); }
public final boolean isAcute(Num a) { return isPositive(a) && a.isLessThan(quarter); }
public final boolean isRight(Num a) { return a.isEqualTo(quarter); }
public final boolean isObtuse(Num a) { return a.isMoreThan(quarter) && a.isLessThan(half); }
public final boolean isStraight(Num a) { return a.isEqualTo(half); }
public final boolean isConcave(Num a) { return a.isLessThan(half); }
public final boolean isConvex(Num a) { return a.isMoreThan(half); }
public final boolean areCongruent(Num a, Num b) { return a.isEqualTo(b); }
public final boolean areComplementary(Num a, Num b) { return a.add(b).isEqualTo(quarter); }
public final boolean areSupplementary(Num a, Num b) { return a.add(b).isEqualTo(half); }
public final boolean areExplementary(Num a, Num b) { return a.add(b).isEqualTo(full); }
public final boolean areCoterminal(Num a, Num b) {
return toMinPosCoterminal(a).isEqualTo(toMinPosCoterminal(b));
}
public final Num toComplement(Num a) { return quarter.subtract(a); }
public final Num toSupplement(Num a) { return half.subtract(a); }
public final Num toConjugate(Num a) { return full.subtract(a); }
public final Num toReduced(Num a) { return a.remainder(full); }
public final Num toReference(Num a) {
final Num r = a.remainder(full); // assert: -full < r < full
if (r.isMoreThan(half)) return full.subtract(r); // return: 0 < value < half
if (r.isLessThan(half.negate())) return full.add(r); // return: 0 < value < half
if (r.isLessThan(Num.ZERO)) return r.negate(); // return: 0 < value < half
return r; // return: 0 <= r < half
}
public final Num toMinPosCoterminal(Num a) {
final Num r = a.remainder(full); // assert: -full < r < full
return (r.isLessThan(Num.ZERO)) ? r.add(full) : r; // return: 0 <= r < full
}
}
/* 5. The Angle Superclass */
class Angle extends PseudoContinuousMeasure implements Comparable<Angle> {
private static final class ValueComparator implements Comparator<Angle> {
public final int compare(Angle a, Angle b) { return a.stdValue().compareTo(b.stdValue()); }
}
private static final class SizeComparator implements Comparator<Angle> {
public final int compare(Angle a, Angle b) { return a.stdSize().compareTo(b.stdSize()); }
}
public static final String UNITS = "turns";
public static final Num UNITS_PER_CYCLE = new BigNum("1");
public static final Comparator<Angle> VALUE_COMPARATOR = new ValueComparator();
public static final Comparator<Angle> SIZE_COMPARATOR = new SizeComparator();
public static final Comparator<Angle> NATURAL_COMPARATOR = SIZE_COMPARATOR;
private static final AngleMultiTool MULTI_TOOL =
new AngleMultiTool(Angle.UNITS_PER_CYCLE); // Initialize after UNITS_PER_CYCLE has been initialized.
private final AngleMultiTool tool() { return Angle.MULTI_TOOL; }
protected final Num toZFactor() { return Angle.UNITS_PER_CYCLE.divide(unitsPerCycle()); }
protected final Num fromZFactor() { return unitsPerCycle().divide(Angle.UNITS_PER_CYCLE); }
protected Num unitsPerCycle() { return Angle.UNITS_PER_CYCLE; }
protected Angle newAngle(Num zVal) { return new Angle(zVal); }
protected Angle(Num zVal) { super(zVal); }
protected Angle(String strVal) { super(strVal); }
public Angle(Angle a) { super(a); }
public final String stdUnits() { return Angle.UNITS; }
public final boolean isNegative() { return tool().isNegative(zVal); }
public final boolean isZero() { return tool().isZero(zVal); }
public final boolean isAcute() { return tool().isAcute(zVal); }
public final boolean isRight() { return tool().isRight(zVal); }
public final boolean isObtuse() { return tool().isObtuse(zVal); }
public final boolean isStraight() { return tool().isStraight(zVal); }
public final boolean isConcave() { return tool().isConcave(zVal); }
public final boolean isConvex() { return tool().isConvex(zVal); }
public final boolean isCongruentTo(Angle a) { return tool().areCongruent(zVal, a.zVal); }
public final boolean isComplementOf(Angle a) { return tool().areComplementary(zVal, a.zVal); }
public final boolean isSupplementOf(Angle a) { return tool().areSupplementary(zVal, a.zVal); }
public final boolean isConjugatOf(Angle a) { return tool().areExplementary(zVal, a.zVal); }
public final boolean isCoterminalWith(Angle a) { return tool().areCoterminal(zVal, a.zVal); }
public final Angle toComplement() { return newAngle(tool().toComplement(zVal)); }
public final Angle toSupplement() { return newAngle(tool().toSupplement(zVal)); }
public final Angle toConjugate() { return newAngle(tool().toConjugate(zVal)); }
public final Angle toReduced() { return newAngle(tool().toReduced(zVal)); }
public final Angle toReference() { return newAngle(tool().toReference(zVal)); }
public final Angle toMinPosCoterminal() { return newAngle(tool().toMinPosCoterminal(zVal)); }
public final Angle negate() { return newAngle(zVal.negate()); }
public final Angle abs() { return newAngle(zVal.abs()); }
public final Angle add(Angle a) { return newAngle(zVal.add(a.zVal)); }
public final Angle subtract(Angle a) { return newAngle(zVal.subtract(a.zVal)); }
public final int compareTo(Angle a) { return NATURAL_COMPARATOR.compare(this, a); }
}
/* 6. Some Angle Subclasses */
final class Radians extends Angle {
public static final String UNITS = "radians";
public static final Num UNITS_PER_CYCLE = Num.TAO;
protected final Num unitsPerCycle() { return Radians.UNITS_PER_CYCLE; }
protected Angle newAngle(Num zVal) { return new Radians(zVal); }
protected Radians(Num zVal) { super(zVal); }
public Radians(Angle angle) { super(angle); }
public Radians(String strVal) { super(strVal); }
public final String units() { return Radians.UNITS; }
}
class Degrees extends Angle {
public static final String UNITS = "degrees";
public static final Num UNITS_PER_CYCLE = new BigNum("360");
protected final Num unitsPerCycle() { return Degrees.UNITS_PER_CYCLE; }
protected Angle newAngle(Num zVal) { return new Degrees(zVal); }
protected Degrees(Num zVal) { super(zVal); }
public Degrees(Angle angle) { super(angle); }
public Degrees(String strVal) { super(strVal); }
public String units() { return Degrees.UNITS; }
}
final class DegMinSec extends Degrees {
private static final Num NUM60 = new BigNum("60"), NUM3600 = new BigNum("3600");
public static String toString(String d, String m, String s) {
Num numD = new BigNum(d), numM = new BigNum(m), numS = new BigNum(s);
return numD.add(numM.divide(NUM60)).add(numS.divide(NUM3600)).bigDecimalValue().toString();
}
public static final String UNITS = "deg-min-sec";
protected Angle newAngle(Num zVal) { return new DegMinSec(zVal); }
protected DegMinSec(Num zVal) { super(zVal); }
public DegMinSec(Angle angle) { super(angle); }
public DegMinSec(String d, String m, String s) { super(DegMinSec.toString(d, m, s)); }
public final String units() { return DegMinSec.UNITS; }
protected final String valueToString(int n) {
Num d = value(), m = NUM60.multiply(d.remainder(Num.ONE)), s = NUM60.multiply(m.remainder(Num.ONE));
return PseudoContinuousMeasure.toString(d.roundedValue(), 0, "deg") + " " +
PseudoContinuousMeasure.toString(m.roundedValue(), 0, "min") + " " +
PseudoContinuousMeasure.toString(s.roundedValue(), Num.DISPLAY, "sec");
}
}
class Zygo extends Angle { // A so-called revolutionary unit of measure.
public static final String UNITS = "zygo";
public static final Num UNITS_PER_CYCLE = new BigNum("100");
protected final Num unitsPerCycle() { return Zygo.UNITS_PER_CYCLE; }
protected Angle newAngle(Num zVal) { return new Zygo(zVal); }
protected Zygo(Num zVal) { super(zVal); }
public Zygo(Angle angle) { super(angle); }
public Zygo(String strVal) { super(strVal); }
public String units() { return Zygo.UNITS; }
}
/* Many of the basic potrzebie units have been acceptable for some time to the Google
* Calculator as well as to Wolfram|Alpha™, so it is natural to wonder how many other
* software systems will adopt them in the future.
*
* — DONALD E. KNUTH, Selected Papers on Fun & Games (2011)
*/
/* 7. Smoke Test Algorithm */
public class AngleTester {
private static final SortedSet<Angle> orderedSet = new TreeSet<Angle>(Angle.SIZE_COMPARATOR);
private static final SortedSet<Angle> relatedSet = new TreeSet<Angle>(Angle.VALUE_COMPARATOR);
private static void debug(String s) { /* System.out.print(s); */ }
private static String angleToString(Angle a, String label) {
return label + ": " + a.toString() + " " + (a.isZero() ? "zero" : a.isAcute() ? "acute" :
a.isRight() ? "right" : a.isObtuse() ? "obtuse" : a.isStraight() ? "straight" :
a.isConvex() ? "convex" : a.isNegative() ? "negative" : "snap!") + "\n";
}
private static void process(Angle a) { orderedSet.add(a); debug(angleToString(a, "angle"));
Angle com = a.toComplement(); relatedSet.add(com); debug(angleToString(com, "complement"));
Angle sup = a.toSupplement(); relatedSet.add(sup); debug(angleToString(sup, "supplement"));
Angle con = a.toConjugate(); relatedSet.add(con); debug(angleToString(con, "conjugate"));
Angle ref = a.toReference(); relatedSet.add(ref); debug(angleToString(ref, "reference"));
}
private static List<Angle> parseAngles(String[] args) {
final List<Angle> multiset = new LinkedList<Angle>();
final Stack<String> values = new Stack<String>();
for (String arg : args) {
switch (arg) {
case Angle.UNITS: if (!values.empty()) multiset.add(new Angle(values.pop())); break;
case Radians.UNITS: if (!values.empty()) multiset.add(new Radians(values.pop())); break;
case Degrees.UNITS: if (!values.empty()) multiset.add(new Degrees(values.pop())); break;
case Zygo.UNITS: if (!values.empty()) multiset.add(new Zygo(values.pop())); break;
case DegMinSec.UNITS: String deg, min, sec;
if (!values.empty()) sec = values.pop(); else break;
if (!values.empty()) min = values.pop(); else break;
if (!values.empty()) deg = values.pop(); else break;
multiset.add(new DegMinSec(deg, min, sec)); break;
default: values.push(arg);
}
}
while (!values.empty()) multiset.add(new Zygo(values.pop())); // Use the default units du jour.
return multiset;
}
public static void smokeTest(String[] input, String expected, String id) { // ALGORITHM S (Smoke Test).
orderedSet.clear(); relatedSet.clear(); // 0. Clear data structures.
final List<Angle> multiset = parseAngles(input); // 1. Parse input.
for (Angle a : multiset) process(a); // 2. Process input.
StringBuilder results = new StringBuilder("\nTEST ID: " + id + "\n"); // 3. Begin with main heading.
results.append("\nUNORDERED MULTISET\n"); // 4. Append first subheading.
for (Angle a : multiset) results.append(angleToString(a, "angle")); // 5. Append first result set.
results.append("\nSET WITHOUT DUPLICATES ORDERED BY SIZE\n"); // 6. Append second subheading.
for (Angle a : orderedSet) results.append(angleToString(a, "angle")); // 7. Append second result set.
results.append("\nRELATED SET WITHOUT DUPLICATES ORDERED BY VALUE\n"); // 8. Append third subheading.
for (Angle a : relatedSet) results.append(angleToString(a, "angle")); // 9. Append third result set.
System.out.println(results); // 10. Print results.
if (expected == null) return; // 11. If not verifiable: done.
String actual = Data.compress(results.toString()); // 12. Compress results.
// Data.printAsCode(actual, 90); // 13. (Print new expectations.)
System.out.println(actual.equals(expected) ? "Passed!" : "FAILED"); // 14. Compare and report. (Done.)
}
public static void main(String[] args) { // ALGORITHM M (Main Program).
System.out.println(new Song("Turn! Turn! Turn!")); // 0. Print theme song.
smokeTest(Dataset1.input, Dataset1.expected, "SMOKE TEST 1"); // 1. Execute first smoke test.
smokeTest(args, null, "AD HOC"); // 2. Execute ad hoc test.
}
}
/* 8. Pseudo-random Data
*
* [Don] observed that a program running on a table of “real data,” ... is a lot more
* interesting than the same program running on “random data.”
*
* — PAUL ROBERTS, in Literate Programming by Donald E. Knuth (1992)
*
* Table 1 illustrates the typical behavior of comparison counting, by applying it to 16 numbers
* that were chosen at random by the author on March 19, 1963. The same 16 numbers will be used to
* illustrate almost all of the other methods that we shall discuss later.
*
* — DONALD E. KNUTH, vol. 3 (2nd ed.) of The Art of Computer Programming (1998)
*/
final class Data {
public static String compress(String s) { return s.toString().replaceAll("\\s+",""); } // Remove white space.
public static void printAsCode(String s, int size) {
int start = 0, firstSize = 56;
String data = s.substring(start, Math.min(s.length(), start + firstSize));
System.out.print("\"" + data + "\"");
for (start += firstSize; start < s.length(); start += size) {
data = s.substring(start, Math.min(s.length(), start + size));
System.out.print(" +\n \"" + data + "\"");
}
System.out.println(";");
}
}
final class Dataset1 {
public static final String[] input = { "503.087", "radians", "512.061", "degrees", "908", "170", "897",
"deg-min-sec", "275", "zygo", "653.426", "154", "509", "deg-min-sec", "612", "677", "765.703"
};
public static final String expected = "TESTID:SMOKETEST1UNORDEREDMULTISETangle:503.0870radians(" +
"80.0688turns)convexangle:512.0610degrees(1.4224turns)convexangle:911deg5min57.0000sec(2.53" +
"08turns)convexangle:275.0000zygo(2.7500turns)convexangle:656deg8min2.6000sec(1.8226turns)c" +
"onvexangle:765.7030zygo(7.6570turns)convexangle:677.0000zygo(6.7700turns)convexangle:612.0" +
"000zygo(6.1200turns)convexSETWITHOUTDUPLICATESORDEREDBYSIZEangle:512.0610degrees(1.4224tur" +
"ns)convexangle:656deg8min2.6000sec(1.8226turns)convexangle:911deg5min57.0000sec(2.5308turn" +
"s)convexangle:275.0000zygo(2.7500turns)convexangle:612.0000zygo(6.1200turns)convexangle:67" +
"7.0000zygo(6.7700turns)convexangle:765.7030zygo(7.6570turns)convexangle:503.0870radians(80" +
".0688turns)convexRELATEDSETWITHOUTDUPLICATESORDEREDBYVALUEangle:-501.5162radians(-79.8188t" +
"urns)negativeangle:-499.9454radians(-79.5688turns)negativeangle:-496.8038radians(-79.0688t" +
"urns)negativeangle:-740.7030zygo(-7.4070turns)negativeangle:-715.7030zygo(-7.1570turns)neg" +
"ativeangle:-665.7030zygo(-6.6570turns)negativeangle:-652.0000zygo(-6.5200turns)negativeang" +
"le:-627.0000zygo(-6.2700turns)negativeangle:-587.0000zygo(-5.8700turns)negativeangle:-577." +
"0000zygo(-5.7700turns)negativeangle:-562.0000zygo(-5.6200turns)negativeangle:-512.0000zygo" +
"(-5.1200turns)negativeangle:-250.0000zygo(-2.5000turns)negativeangle:-821deg-5min-57.0000s" +
"ec(-2.2808turns)negativeangle:-225.0000zygo(-2.2500turns)negativeangle:-731deg-5min-57.000" +
"0sec(-2.0308turns)negativeangle:-175.0000zygo(-1.7500turns)negativeangle:-566deg-8min-2.60" +
"00sec(-1.5726turns)negativeangle:-551deg-5min-57.0000sec(-1.5308turns)negativeangle:-476de" +
"g-8min-2.6000sec(-1.3226turns)negativeangle:-422.0610degrees(-1.1724turns)negativeangle:-3" +
"32.0610degrees(-0.9224turns)negativeangle:-296deg-8min-2.6000sec(-0.8226turns)negativeangl" +
"e:-152.0610degrees(-0.4224turns)negativeangle:0.4322radians(0.0688turns)acuteangle:12.0000" +
"zygo(0.1200turns)acuteangle:64deg52min57.4000sec(0.1774turns)acuteangle:23.0000zygo(0.2300" +
"turns)acuteangle:25.0000zygo(0.2500turns)rightangle:34.2970zygo(0.3430turns)obtuseangle:15" +
"2.0610degrees(0.4224turns)obtuseangle:169deg55min3.0000sec(0.4692turns)obtuse";
}
/* 9. Songs
*
* In music, segue is a direction to the performer. It means continue (the next section) without a
* pause. In live performance, a segue can occur during a jam session, where the improvisation of
* the end of one song progresses into a new song. Segues can even occur between groups of musicians
* during live performance. For example, as one band finishes its set, members of the following act
* replace members of the first band one by one, until a complete band swap occurs.
*
* — https://en.wikipedia.org/wiki/Segue (accessed 31 March 2018)
*/
final class Songs {
public static List<String> getVerses(String songTitle) { return new LinkedList<String>(); } // to do
public static Num getVerseCount(String songTitle) { return new BigNum(getVerses(songTitle).size()); }
public static Num getAvgVerseLength(String songTitle) { return null; } // to do
public static String getRefrain(String songTitle) {
StringBuilder sb = new StringBuilder("\n[Bridge]\n");
switch(songTitle) {
case ("Turn! Turn! Turn!"): // Written by Pete Seeger in the late 1950s; see also Ecclesiastes 3:1-8.
sb.append("\nTo Everything (Turn, Turn, Turn)");
sb.append("\nThere is a season (Turn, Turn, Turn)");
sb.append("\nAnd a time to every purpose, under Heaven");
break;
case ("One"): // By Harry Nilsson; made famous by Three Dog Night.
for (int i=3; i-- > 0; sb.append("\nOne is the loneliest number"));
sb.append(" that you'll ever do");
break;
case ("Who Knows One?"): // Also known as “Ehad Mi Yode’a”; author unknown.
default:
throw new UnsupportedOperationException("Sorry, I don't know the lyrics for " + songTitle + ".");
}
return sb.toString();
}
}
class Song {
private final String title;
public Song(String title) { this.title = title; }
public final String title() { return this.title; }
public final String refrain() { return Songs.getRefrain(title); }
public final List<String> verses() { return Songs.getVerses(this.title); }
public final Num verseCount() { return Songs.getVerseCount(this.title); }
public final Num avgVerseLength() { return Songs.getAvgVerseLength(this.title); }
public final Num refrainLength() { return new BigNum(this.refrain().length()); }
public String toString() { return title + "\n" + lyrics(); }
public final String lyrics() {
String r = refrain(); StringBuilder sb = new StringBuilder(r);
for (String verse : Songs.getVerses(title)) sb.append("\n\n" + verse + "\n\n" + r);
return sb.toString();
}
/** @see Donald E. Knuth, “The Complexity of Songs,” <i>Communications of the ACM</i> <b>27</b>
* (April 1984) 344-346; errata (June 1984), 593.
*/
public final Num sizeComplexity() {
final Num m = this.verseCount(), V = this.avgVerseLength(), R = this.refrainLength();
return R.add(V.multiply(m));
}
}