001package algs13;
002
003import stdlib.StdOut;
004import stdlib.Trace;
005
006/**
007 * MyListAccessor (debugging).
008 * <p>
009 * This homework is intended to give you hands-on experience debugging and testing code. The intent is to give
010 * you more practice with linked lists and develop your intuition about how linked lists work.
011 * <p>
012 * Instructions:
013 * <p>
014 * 1. Make sure you have watched last week's lecture. Read over the main method and the test methods to develop an understanding
015 * of what they are doing.
016 * <p>
017 * 2. Look for the TODO in the code below.
018 * <p>
019 * 3. Utilize the techniques presented (your choice of Inspection, print statements, trace on paper, Trace utility,
020 * or IntelliJ Interactive debugger) to find and fix the bugs.
021 * <p>
022 * This is a "written homework" assignment. You do NOT need to submit this file with solutions as part of this homework.
023 * You DO need to submit your answers to the questions posed below.
024 */
025public class MyListAccessor {
026
027    private Node first;
028    private int N;
029
030    private static class Node {
031        final double item;
032        Node next;
033
034        Node(double item, Node next) {
035            this.item = item;
036            this.next = next;
037        }
038    }
039
040    public int numFives1() {
041        int result = 0;
042        for (Node x = first; x != null; x = x.next)
043            if (x.item == 5.0)
044                result = result + 1;
045        return result;
046    }
047
048    public int numFives2() {
049        Node x = first;
050        int result = 0;
051        while (x != null) {
052            if (x.item == 5.0)
053                result = result + 1;
054            x = x.next;
055        }
056        return result;
057    }
058
059    public int numFives3() {
060        Node x = first;
061        int result = 0;
062        while (x != null) {
063            if (x.item == 5.0)
064                result = result + 1;
065            x = x.next.next;
066        }
067        return result;
068    }
069
070    public int numFives4() {
071        if (first == null) return 0;
072        int result = 0;
073        if (first.item == 5.0)
074            result = result + 1;
075        Node x = first;
076        while (x.next != null) {
077            if (x.next.item == 5.0)
078                result = result + 1;
079            x.next = x.next.next;
080        }
081        return result;
082    }
083
084    public int numFives5() {
085        int result = 0;
086        for (Node x = first; x.next != null && x.next.item == 5.0; x = x.next) {
087            result += 1;
088        }
089        return result;
090    }
091
092    public int numFives6() {
093        if (first == null) return 0;
094        int result = 0;
095        if (first.item == 5.0)
096            result = result + 1;
097        Node x = first;
098        while (x.next != null) {
099            if (x.item == 5.0)
100                result = result + 1;
101            x = x.next;
102        }
103        return result;
104    }
105
106    public int numFives7() {
107        if (first.next == null) return 0;
108        Node x = first;
109        int result = 0;
110        while (x.next != null) {
111            if (x.item != 5.0) x = x.next;
112            if (x.item == 5.0) {
113                result = result + 1;
114                x = x.next;
115            }
116        }
117        if (x.next == null && x.item == 5.0) {
118            result = result + 1;
119        }
120        return result;
121    }
122
123    public int numFives8() {
124        if (first == null) return 0;
125        Node x = first;
126        Node y = first.next;
127        int result = 0;
128        while (x != null) {
129            if (x.item == 5.0) result = result + 1;
130            x = y;
131        }
132        return result;
133    }
134
135    public int numFives9() {
136        int result = 0;
137        if (first.item == 5.0)
138            result = result + 1;
139        Node x = first;
140        while (x.next != null) {
141            if (x.next.item == 5.0)
142                result = result + 1;
143            x = x.next;
144        }
145        return result;
146    }
147
148    public int numFives10() {
149        int result = 0;
150        for (Node x = first; x != null; x = x.next) {
151            if (x.item == 5.0)
152                result = result + 1;
153            x = x.next;
154        }
155        return result;
156    }
157
158    /**
159     * TODO: Change this to invoke each method, numFives1, numFives2, ... numFives10,
160     * in turn. You can comment out the first line and uncomment the second line.
161     * <p>
162     * For each version of the method, tell me:
163     * <p>
164     * a. Whether there is a bug or not. (Note: There are no compiler errors in this file).
165     * b. What's wrong with the method and how to fix it.
166     * <p>
167     * Fix the code for each method to make it work. Some of the implementations may end up
168     * looking the same, or very similar.
169     * <p>
170     * Write your answers the the questions about each implementation of numFives on paper,
171     * or put them in a Word document. Upload a scan of your handwritten answers or your
172     * Word document to D2L. Do not submit image files directly, although you can paste
173     * photographs of your handwritten answers into the Word document. A better alternative
174     * would be to use a scanning app on your phone, and submit a PDF of your handwritten answers.
175     * <p>
176     * You do not need to hand in this file.
177     */
178
179    public static int numFives(MyListAccessor list) {
180        return list.numFives1();
181        // return list.numFives2();
182        // return list.numFives3();
183        // return list.numFives4();
184        // return list.numFives5();
185        // return list.numFives6();
186        // return list.numFives7();
187        // return list.numFives8();
188        // return list.numFives9();
189        // return list.numFives10();
190    }
191
192    /* A main function for testing */
193    public static void main(String[] args) {
194
195        // TODO: If you want, you can uncomment this line of code and use Trace for visualizing
196        //       the execution of the program.
197        // Trace.run();
198        Trace.drawStepsOfMethod("numFives1");
199        Trace.drawStepsOfMethod("numFives2");
200        Trace.drawStepsOfMethod("numFives3");
201        Trace.drawStepsOfMethod("numFives4");
202        Trace.drawStepsOfMethod("numFives5");
203        Trace.drawStepsOfMethod("numFives6");
204        Trace.drawStepsOfMethod("numFives7");
205        Trace.drawStepsOfMethod("numFives8");
206        Trace.drawStepsOfMethod("numFives9");
207        Trace.drawStepsOfMethod("numFives10");
208
209        testNumFives(3, listOf(11, 21, 5, 31, 5, 41, 5, 51));
210        testNumFives(4, listOf(11, 21, 5, 31, 5, 5, 41, 5, 51));
211        testNumFives(4, listOf(11, 21, 5, 5, 5, 31, 41, 5, 51));
212        testNumFives(0, listOf(11, 21, 31, 41));
213        testNumFives(1, listOf(11, 21, 5, 31, 41));
214        testNumFives(1, listOf(11, 21, 31, 41, 5));
215        testNumFives(1, listOf(5, 11, 21, 31, 41));
216        testNumFives(0, listOf(11));
217        testNumFives(1, listOf(5));
218        testNumFives(3, listOf(5, 5, 5));
219        testNumFives(0, listOf());
220        StdOut.println("Finished tests");
221    }
222
223    @Override
224    public String toString() {
225        StringBuilder b = new StringBuilder();
226        Node x = first;
227        b.append("[ ");
228        while (x != null) {
229            if (x != first) b.append(", ");
230            b.append(x.item);
231            x = x.next;
232        }
233        b.append(" ]");
234        return b.toString();
235    }
236
237    private static MyListAccessor listOf(double... items) {
238        Node next = null;
239        for (int i = items.length - 1; i >= 0; i--) {
240            next = new Node(items[i], next);
241        }
242        MyListAccessor list = new MyListAccessor();
243        list.first = next;
244        list.N = items.length;
245        return list;
246    }
247
248    /* This is a test function */
249    private static void testNumFives(int expected, MyListAccessor list) {
250        int actual = numFives(list);
251        if (expected != actual) {
252            StdOut.format("Failed: Expecting [%d] Actual [%d] with argument %s\n", expected, actual, list.toString());
253        }
254        checkInvariants(list);
255    }
256
257    private static void showError(String message) {
258        Trace.draw();
259        StdOut.println(message);
260        throw new Error(); // stops execution
261    }
262
263    private static void checkInvariants(MyListAccessor that) {
264        int N = that.N;
265        Node first = that.first;
266        if (N < 0) throw new Error();
267        if (N == 0) {
268            if (first != null) {
269                showError("N==0, Expected first == null.");
270            }
271        } else {
272            if (first == null) {
273                showError("N!=0, Expected first != null.");
274            }
275        }
276        if (N > 0) {
277            Node current = first;
278            for (int i = 0; i < N; i++) {
279                if (current == null) {
280                    showError(String.format("N==%d, Expected %d next nodes, but got fewer.", N, N));
281                    return;
282                }
283                current = current.next;
284            }
285            if (current != null) {
286                showError(String.format("N==%d, Expected %d next nodes, but got more.", N, N));
287            }
288        }
289    }
290}