• 中文
    • English
  • 注册
  • 查看作者
  • 《算法第四版》课后练习题1.2.13答案

    习题1.2.13

    用我们对 Date 的实现(请见表1.1.12)作为模板,开发 Transaction 的实现。

    要点分析

    1.  Date实现

     Date 的API,请见表1.1.12,课本56页,这里也给出官方网站Date类具体实现[1] 

    public class Date implements Comparable<Date> {
        private static final int[] DAYS = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
        private final int month;   // month (between 1 and 12)
        private final int day;     // day   (between 1 and DAYS[month]
        private final int year;    // year
    
        /**
         * Initializes a new date from the month, day, and year.
         *
         * @param month the month (between 1 and 12)
         * @param day   the day (between 1 and 28-31, depending on the month)
         * @param year  the year
         * @throws IllegalArgumentException if this date is invalid
         */
        public Date(int month, int day, int year) {
            if (!isValid(month, day, year)) throw new IllegalArgumentException("Invalid date");
            this.month = month;
            this.day = day;
            this.year = year;
        }
    
        /**
         * Initializes new date specified as a string in form MM/DD/YYYY.
         *
         * @param date the string representation of this date
         * @throws IllegalArgumentException if this date is invalid
         */
        public Date(String date) {
            String[] fields = date.split("/");
            if (fields.length != 3) {
                throw new IllegalArgumentException("Invalid date");
            }
            month = Integer.parseInt(fields[0]);
            day = Integer.parseInt(fields[1]);
            year = Integer.parseInt(fields[2]);
            if (!isValid(month, day, year)) throw new IllegalArgumentException("Invalid date");
        }
    
        /**
         * Return the month.
         *
         * @return the month (an integer between 1 and 12)
         */
        public int month() {
            return month;
        }
    
        /**
         * Returns the day.
         *
         * @return the day (an integer between 1 and 31)
         */
        public int day() {
            return day;
        }
    
        /**
         * Returns the year.
         *
         * @return the year
         */
        public int year() {
            return year;
        }
    
    
        // is the given date valid?
        private static boolean isValid(int m, int d, int y) {
            if (m < 1 || m > 12) return false;
            if (d < 1 || d > DAYS[m]) return false;
            if (m == 2 && d == 29 && !isLeapYear(y)) return false;
            return true;
        }
    
        // is y a leap year?
        private static boolean isLeapYear(int y) {
            if (y % 400 == 0) return true;
            if (y % 100 == 0) return false;
            return y % 4 == 0;
        }
    
        /**
         * Returns the next date in the calendar.
         *
         * @return a date that represents the next day after this day
         */
        public Date next() {
            if (isValid(month, day + 1, year)) return new Date(month, day + 1, year);
            else if (isValid(month + 1, 1, year)) return new Date(month + 1, 1, year);
            else return new Date(1, 1, year + 1);
        }
    
        /**
         * Compares two dates chronologically.
         *
         * @param that the other date
         * @return {@code true} if this date is after that date; {@code false} otherwise
         */
        public boolean isAfter(Date that) {
            return compareTo(that) > 0;
        }
    
        /**
         * Compares two dates chronologically.
         *
         * @param that the other date
         * @return {@code true} if this date is before that date; {@code false} otherwise
         */
        public boolean isBefore(Date that) {
            return compareTo(that) < 0;
        }
    
        /**
         * Compares two dates chronologically.
         *
         * @return the value {@code 0} if the argument date is equal to this date;
         * a negative integer if this date is chronologically less than
         * the argument date; and a positive ineger if this date is chronologically
         * after the argument date
         */
        @Override
        public int compareTo(Date that) {
            if (this.year < that.year) return -1;
            if (this.year > that.year) return +1;
            if (this.month < that.month) return -1;
            if (this.month > that.month) return +1;
            if (this.day < that.day) return -1;
            if (this.day > that.day) return +1;
            return 0;
        }
    
        /**
         * Returns a string representation of this date.
         *
         * @return the string representation in the format MM/DD/YYYY
         */
        @Override
        public String toString() {
            return month + "/" + day + "/" + year;
        }
    
        /**
         * Compares this date to the specified date.
         *
         * @param other the other date
         * @return {@code true} if this date equals {@code other}; {@code false} otherwise
         */
        @Override
        public boolean equals(Object other) {
            if (other == this) return true;
            if (other == null) return false;
            if (other.getClass() != this.getClass()) return false;
            Date that = (Date) other;
            return (this.month == that.month) && (this.day == that.day) && (this.year == that.year);
        }
    
        /**
         * Returns an integer hash code for this date.
         *
         * @return an integer hash code for this date
         */
        @Override
        public int hashCode() {
            int hash = 17;
            hash = 31 * hash + month;
            hash = 31 * hash + day;
            hash = 31 * hash + year;
            return hash;
        }
    
        /**
         * Unit tests the {@code Date} data type.
         *
         * @param args the command-line arguments
         */
        public static void main(String[] args) {
            Date today = new Date(2, 25, 2004);
            StdOut.println(today);
            for (int i = 0; i < 10; i++) {
                today = today.next();
                StdOut.println(today);
            }
    
            StdOut.println(today.isAfter(today.next()));
            StdOut.println(today.isAfter(today));
            StdOut.println(today.next().isAfter(today));
    
    
            Date birthday = new Date(10, 16, 1971);
            StdOut.println(birthday);
            for (int i = 0; i < 10; i++) {
                birthday = birthday.next();
                StdOut.println(birthday);
            }
        }
    
    }

    2.  Transaction

    Transaction的API,请见课本48页,如下图:

    《算法第四版》课后练习题1.2.13答案

    我们参考Date模板的实现以及Transaction的API编写即可。

    官方答案

    Below is the syntax highlighted version of Transaction.java from §1.2 Data Abstraction.
    
    
    /******************************************************************************
     *  Compilation:  javac Transaction.java
     *  Execution:    java Transaction
     *  Dependencies: StdOut.java
     *  
     *  Data type for commercial transactions.
     *
     ******************************************************************************/
    
    import java.util.Arrays;
    import java.util.Comparator;
    
    /**
     *  The {@code Transaction} class is an immutable data type to encapsulate a
     *  commercial transaction with a customer name, date, and amount.
     *  <p>
     *  For additional documentation, 
     *  see <a href="https://algs4.cs.princeton.edu/12oop">Section 1.2</a> of 
     *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne. 
     *
     *  @author Robert Sedgewick
     *  @author Kevin Wayne
     */
    public class Transaction implements Comparable<Transaction> {
        private final String  who;      // customer
        private final Date    when;     // date
        private final double  amount;   // amount
    
    
        /**
         * Initializes a new transaction from the given arguments.
         *
         * @param  who the person involved in this transaction
         * @param  when the date of this transaction
         * @param  amount the amount of this transaction
         * @throws IllegalArgumentException if {@code amount} 
         *         is {@code Double.NaN}, {@code Double.POSITIVE_INFINITY},
         *         or {@code Double.NEGATIVE_INFINITY}
         */
        public Transaction(String who, Date when, double amount) {
            if (Double.isNaN(amount) || Double.isInfinite(amount))
                throw new IllegalArgumentException("Amount cannot be NaN or infinite");
            this.who    = who;
            this.when   = when;
            this.amount = amount;
        }
    
        /**
         * Initializes a new transaction by parsing a string of the form NAME DATE AMOUNT.
         *
         * @param  transaction the string to parse
         * @throws IllegalArgumentException if {@code amount} 
         *         is {@code Double.NaN}, {@code Double.POSITIVE_INFINITY},
         *         or {@code Double.NEGATIVE_INFINITY}
         */
        public Transaction(String transaction) {
            String[] a = transaction.split("\\s+");
            who    = a[0];
            when   = new Date(a[1]);
            amount = Double.parseDouble(a[2]);
            if (Double.isNaN(amount) || Double.isInfinite(amount))
                throw new IllegalArgumentException("Amount cannot be NaN or infinite");
        }
    
        /**
         * Returns the name of the customer involved in this transaction.
         *
         * @return the name of the customer involved in this transaction
         */
        public String who() {
            return who;
        }
     
        /**
         * Returns the date of this transaction.
         *
         * @return the date of this transaction
         */
        public Date when() {
            return when;
        }
     
        /**
         * Returns the amount of this transaction.
         *
         * @return the amount of this transaction
         */
        public double amount() {
            return amount;
        }
    
        /**
         * Returns a string representation of this transaction.
         *
         * @return a string representation of this transaction
         */
        @Override
        public String toString() {
            return String.format("%-10s %10s %8.2f", who, when, amount);
        }
    
        /**
         * Compares two transactions by amount.
         *
         * @param  that the other transaction
         * @return { a negative integer, zero, a positive integer}, depending
         *         on whether the amount of this transaction is { less than,
         *         equal to, or greater than } the amount of that transaction
         */
        public int compareTo(Transaction that) {
            return Double.compare(this.amount, that.amount);
        }    
    
        /**
         * Compares this transaction to the specified object.
         *
         * @param  other the other transaction
         * @return true if this transaction is equal to {@code other}; false otherwise
         */
        @Override
        public boolean equals(Object other) {
            if (other == this) return true;
            if (other == null) return false;
            if (other.getClass() != this.getClass()) return false;
            Transaction that = (Transaction) other;
            return (this.amount == that.amount) && (this.who.equals(that.who))
                                                && (this.when.equals(that.when));
        }
    
    
        /**
         * Returns a hash code for this transaction.
         *
         * @return a hash code for this transaction
         */
        public int hashCode() {
            int hash = 1;
            hash = 31*hash + who.hashCode();
            hash = 31*hash + when.hashCode();
            hash = 31*hash + ((Double) amount).hashCode();
            return hash;
            // return Objects.hash(who, when, amount);
        }
    
        /**
         * Compares two transactions by customer name.
         */
        public static class WhoOrder implements Comparator<Transaction> {
    
            @Override
            public int compare(Transaction v, Transaction w) {
                return v.who.compareTo(w.who);
            }
        }
    
        /**
         * Compares two transactions by date.
         */
        public static class WhenOrder implements Comparator<Transaction> {
    
            @Override
            public int compare(Transaction v, Transaction w) {
                return v.when.compareTo(w.when);
            }
        }
    
        /**
         * Compares two transactions by amount.
         */
        public static class HowMuchOrder implements Comparator<Transaction> {
    
            @Override
            public int compare(Transaction v, Transaction w) {
                return Double.compare(v.amount, w.amount);
            }
        }
    
    
        /**
         * Unit tests the {@code Transaction} data type.
         *
         * @param args the command-line arguments
         */
        public static void main(String[] args) {
            Transaction[] a = new Transaction[4];
            a[0] = new Transaction("Turing   6/17/1990  644.08");
            a[1] = new Transaction("Tarjan   3/26/2002 4121.85");
            a[2] = new Transaction("Knuth    6/14/1999  288.34");
            a[3] = new Transaction("Dijkstra 8/22/2007 2678.40");
    
            StdOut.println("Unsorted");
            for (int i = 0; i < a.length; i++)
                StdOut.println(a[i]);
            StdOut.println();
            
            StdOut.println("Sort by date");
            Arrays.sort(a, new Transaction.WhenOrder());
            for (int i = 0; i < a.length; i++)
                StdOut.println(a[i]);
            StdOut.println();
    
            StdOut.println("Sort by customer");
            Arrays.sort(a, new Transaction.WhoOrder());
            for (int i = 0; i < a.length; i++)
                StdOut.println(a[i]);
            StdOut.println();
    
            StdOut.println("Sort by amount");
            Arrays.sort(a, new Transaction.HowMuchOrder());
            for (int i = 0; i < a.length; i++)
                StdOut.println(a[i]);
            StdOut.println();
        }
    
    }

    参考资料

    [1] Algs4:Date.java

    [2] Algs4:Transaction.java

  • 0
  • 0
  • 0
  • 4.6k
  • 请登录之后再进行评论

    登录
    单栏布局 侧栏位置: