/* 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 aVector
may have taken great care to make theVector
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)); } }