{"id":"text-ui-remembering","slug":"remembering","title":"Remembering between commands","text":"The info desk answers every command the same way, whatever came before it. Most programs have to remember something from one command to the next: a count, a total, the names typed so far. Variables do that, with one rule: a variable that must last from command to command is created **before** the loop. A variable created inside the loop's braces is made new in every round and forgotten at the end of it.\n\nA musician logs practice sessions. `log` is followed by a line with the minutes practiced, `total` adds up all the sessions, and `longest` finds the longest one:\n\n```java\nimport java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        ArrayList<Integer> sessions = new ArrayList<>();\n        while (true) {\n            System.out.print(\"> \");\n            String command = scanner.nextLine();\n            if (command.equals(\"quit\")) {\n                System.out.println(\"Keep practicing!\");\n                break;\n            }\n            if (command.equals(\"log\")) {\n                int minutes = Integer.valueOf(scanner.nextLine());\n                sessions.add(minutes);\n                System.out.println(\"Logged \" + minutes + \" minutes\");\n            } else if (command.equals(\"total\")) {\n                int total = 0;\n                for (int minutes : sessions) {\n                    total = total + minutes;\n                }\n                System.out.println(\"Total: \" + total + \" minutes\");\n            } else if (command.equals(\"longest\")) {\n                int longest = 0;\n                for (int minutes : sessions) {\n                    if (minutes > longest) {\n                        longest = minutes;\n                    }\n                }\n                System.out.println(\"Longest: \" + longest + \" minutes\");\n            } else {\n                System.out.println(\"Unknown command: \" + command);\n            }\n        }\n    }\n}\n```\n\n```input\nlog\n25\nlog\n40\ntotal\nlog\n15\nlongest\nquit\n```\n\n```output\n> Logged 25 minutes\n> Logged 40 minutes\n> Total: 65 minutes\n> Logged 15 minutes\n> Longest: 40 minutes\n> Keep practicing!\n```\n\n- `sessions` is created before the loop, so every round adds to the same list, and `total` sees every session logged so far. Created inside the loop, it would start empty in every round, and `total` would always say 0 minutes.\n- `log` reads the minutes from the line after the command, as the previous step described: `Integer.valueOf(scanner.nextLine())`.\n- `total` and `longest` are created inside their own branches. They're only needed while that one answer is worked out, so they're worked out again from the list each time.\n\n### Small solutions, put together\n\nThe program looks long, but each part of it is something you've written before:\n\n1. Read commands until `quit`, and answer unknown ones: the loop of the previous step.\n2. Remember each session: add it to a list.\n3. Add up the values of a list.\n4. Find the largest value of a list.\n\nThat's a good way into any bigger program: list the small problems it's made of, solve them one at a time, and try each one before going on. Here you could first write the loop with only `quit` and the unknown-command answer, then `log` and `total`, and `longest` last. Each piece stays small enough to check at a glance.\n\n### What to remember\n\nRemember what later commands need. A list of sessions is one way to do it. But `total` and `longest` could also be answered with two `int` variables, updated at every `log`, without keeping the sessions at all. A list is needed when a command needs every value again, for example to print all the sessions. Step 5 comes back to this choice.\n","task":"A small campsite has 3 tent spots. The program remembers how many spots are taken, starting from 0. Create that variable before the loop, and add the commands:\n\n- `arrive`: a group arrives. Print `Welcome! Free spots: ` and the number of spots still free, or `Sorry, the campsite is full` when all 3 spots are taken.\n- `depart`: a group leaves. Print `Safe travels! Free spots: ` and the number of free spots, or `Nobody is camping` when no spot is taken.\n- `spots`: print `Free spots: ` and the number of free spots.\n- Anything else: print `Unknown command: ` and the command.\n\n`quit` is ready. For the input shown, the program prints:\n\n```\n> Welcome! Free spots: 2\n> Welcome! Free spots: 1\n> Free spots: 1\n> Welcome! Free spots: 0\n> Sorry, the campsite is full\n> Safe travels! Free spots: 1\n> Lights out\n```\n","kind":"code","seed":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        // Create the variable for the taken spots here.\n        while (true) {\n            System.out.print(\"> \");\n            String command = scanner.nextLine();\n            if (command.equals(\"quit\")) {\n                System.out.println(\"Lights out\");\n                break;\n            }\n            // Handle arrive, depart, spots and unknown commands here.\n        }\n    }\n}\n","solution":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        // Create the variable for the taken spots here.\n        int taken = 0;\n        while (true) {\n            System.out.print(\"> \");\n            String command = scanner.nextLine();\n            if (command.equals(\"quit\")) {\n                System.out.println(\"Lights out\");\n                break;\n            }\n            // Handle arrive, depart, spots and unknown commands here.\n            if (command.equals(\"arrive\")) {\n                if (taken < 3) {\n                    taken++;\n                    System.out.println(\"Welcome! Free spots: \" + (3 - taken));\n                } else {\n                    System.out.println(\"Sorry, the campsite is full\");\n                }\n            } else if (command.equals(\"depart\")) {\n                if (taken > 0) {\n                    taken--;\n                    System.out.println(\"Safe travels! Free spots: \" + (3 - taken));\n                } else {\n                    System.out.println(\"Nobody is camping\");\n                }\n            } else if (command.equals(\"spots\")) {\n                System.out.println(\"Free spots: \" + (3 - taken));\n            } else {\n                System.out.println(\"Unknown command: \" + command);\n            }\n        }\n    }\n}\n","hints":["`int taken = 0;` goes before the loop, so the count lasts from one command to the next. Inside the loop, it would be 0 again in every round.","In the `arrive` branch, check `taken < 3` before adding one. In the `depart` branch, check `taken > 0` before taking one away. The free spots are `3 - taken`, in parentheses when it's part of a longer `+`."],"tests":[{"name":"Test 1","stdin":"arrive\narrive\nspots\narrive\narrive\ndepart\nquit\n","expect":"> Welcome! Free spots: 2\n> Welcome! Free spots: 1\n> Free spots: 1\n> Welcome! Free spots: 0\n> Sorry, the campsite is full\n> Safe travels! Free spots: 1\n> Lights out","hidden":false},{"name":"Test 2","stdin":"depart\nspots\nquit\n","expect":"> Nobody is camping\n> Free spots: 3\n> Lights out","hidden":true},{"name":"Test 3","stdin":"arrive\ndepart\ndepart\narrive\narrive\narrive\narrive\nspots\ncamp\nquit\n","expect":"> Welcome! Free spots: 2\n> Safe travels! Free spots: 3\n> Nobody is camping\n> Welcome! Free spots: 2\n> Welcome! Free spots: 1\n> Welcome! Free spots: 0\n> Sorry, the campsite is full\n> Free spots: 0\n> Unknown command: camp\n> Lights out","hidden":true}],"require":[],"forbid":[],"more":[{"task":"A birdwatcher notes each bird seen. Write the program. Keep the sightings in a list of Strings, one entry for each bird seen, and create the list before the loop. The commands:\n\n- `saw`: the next line is a species. Add it to the list and print `Noted: ` and the species.\n- `count`: the next line is a species. Print the species, `: ` and how many times it was seen, spelled exactly the same, capitals included, like `robin: 2`.\n- `total`: print `Birds seen: ` and the number of sightings.\n- `quit`: print `Happy birding!` and end the program.\n- Anything else: print `Unknown command: ` and the command.\n\nPrint the prompt `> ` before each command. For the input shown, the program prints:\n\n```\n> Noted: robin\n> Noted: heron\n> Noted: robin\n> robin: 2\n> owl: 0\n> Birds seen: 3\n> Happy birding!\n```\n","kind":"code","seed":"import java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        // Write the program here.\n    }\n}\n","solution":"import java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        // Write the program here.\n        ArrayList<String> sightings = new ArrayList<>();\n        while (true) {\n            System.out.print(\"> \");\n            String command = scanner.nextLine();\n            if (command.equals(\"quit\")) {\n                System.out.println(\"Happy birding!\");\n                break;\n            }\n            if (command.equals(\"saw\")) {\n                String species = scanner.nextLine();\n                sightings.add(species);\n                System.out.println(\"Noted: \" + species);\n            } else if (command.equals(\"count\")) {\n                String species = scanner.nextLine();\n                int count = 0;\n                for (String bird : sightings) {\n                    if (bird.equals(species)) {\n                        count++;\n                    }\n                }\n                System.out.println(species + \": \" + count);\n            } else if (command.equals(\"total\")) {\n                System.out.println(\"Birds seen: \" + sightings.size());\n            } else {\n                System.out.println(\"Unknown command: \" + command);\n            }\n        }\n    }\n}\n","hints":["Three small problems: the command loop, adding to a list, and counting the entries of a list that equal a given String. `total` is the list's `size()`.","For `count`, read the species with another `scanner.nextLine()`, then go through the list with a for-each loop and add one to a counter for each entry that `equals` the species."],"tests":[{"name":"Test 1","stdin":"saw\nrobin\nsaw\nheron\nsaw\nrobin\ncount\nrobin\ncount\nowl\ntotal\nquit\n","expect":"> Noted: robin\n> Noted: heron\n> Noted: robin\n> robin: 2\n> owl: 0\n> Birds seen: 3\n> Happy birding!","hidden":false},{"name":"Test 2","stdin":"total\ncount\nrobin\nquit\n","expect":"> Birds seen: 0\n> robin: 0\n> Happy birding!","hidden":true},{"name":"Test 3","stdin":"saw\ngreat tit\nsaw\nGreat tit\nsaw\ngreat tit\ncount\ngreat tit\nwatch\ntotal\nquit\n","expect":"> Noted: great tit\n> Noted: Great tit\n> Noted: great tit\n> great tit: 2\n> Unknown command: watch\n> Birds seen: 3\n> Happy birding!","hidden":true}],"require":[{"pattern":"ArrayList\\s*<\\s*String\\s*>","message":"Keep the sightings in an `ArrayList<String>`."}],"forbid":[]},{"task":"At a deli counter, customers take their place in line and are served in the order they came. Write the program. Keep the names of the waiting customers in a list, first in line first. The commands:\n\n- `take`: the next line is a name. Add it to the end of the line, and print the name, `, you're number ` and their place in line, like `Ana, you're number 1`.\n- `next`: print `Now serving ` and the first name in line, and take it off the line. If nobody is waiting, print `Nobody is waiting`.\n- `queue`: print `In line: ` and the list, like `In line: [Ben, Cleo]`.\n- `close`: print `Closed for today` and end the program.\n- Anything else: print `Unknown command: ` and the command.\n\nPrint the prompt `> ` before each command. For the input shown, the program prints:\n\n```\n> Ana, you're number 1\n> Ben, you're number 2\n> Now serving Ana\n> Cleo, you're number 2\n> In line: [Ben, Cleo]\n> Now serving Ben\n> Now serving Cleo\n> Nobody is waiting\n> Closed for today\n```\n","kind":"code","seed":"import java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        // Write the program here.\n    }\n}\n","solution":"import java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        // Write the program here.\n        ArrayList<String> names = new ArrayList<>();\n        while (true) {\n            System.out.print(\"> \");\n            String command = scanner.nextLine();\n            if (command.equals(\"close\")) {\n                System.out.println(\"Closed for today\");\n                break;\n            }\n            if (command.equals(\"take\")) {\n                String name = scanner.nextLine();\n                names.add(name);\n                System.out.println(name + \", you're number \" + names.size());\n            } else if (command.equals(\"next\")) {\n                if (names.isEmpty()) {\n                    System.out.println(\"Nobody is waiting\");\n                } else {\n                    System.out.println(\"Now serving \" + names.get(0));\n                    names.remove(0);\n                }\n            } else if (command.equals(\"queue\")) {\n                System.out.println(\"In line: \" + names);\n            } else {\n                System.out.println(\"Unknown command: \" + command);\n            }\n        }\n    }\n}\n","hints":["Right after `names.add(name)`, the new customer is last in line, so their place is `names.size()`.","The first in line is at index 0: print `names.get(0)`, then `names.remove(0)`. Check `names.isEmpty()` first. Printing the list itself gives the `[Ben, Cleo]` form."],"tests":[{"name":"Test 1","stdin":"take\nAna\ntake\nBen\nnext\ntake\nCleo\nqueue\nnext\nnext\nnext\nclose\n","expect":"> Ana, you're number 1\n> Ben, you're number 2\n> Now serving Ana\n> Cleo, you're number 2\n> In line: [Ben, Cleo]\n> Now serving Ben\n> Now serving Cleo\n> Nobody is waiting\n> Closed for today","hidden":false},{"name":"Test 2","stdin":"next\nqueue\nclose\n","expect":"> Nobody is waiting\n> In line: []\n> Closed for today","hidden":true},{"name":"Test 3","stdin":"take\nMia\ntake\nLeo\ntake\nMia\nqueue\nnext\nqueue\nserve\nclose\n","expect":"> Mia, you're number 1\n> Leo, you're number 2\n> Mia, you're number 3\n> In line: [Mia, Leo, Mia]\n> Now serving Mia\n> In line: [Leo, Mia]\n> Unknown command: serve\n> Closed for today","hidden":true}],"require":[],"forbid":[]}]}