{"id":"strings-part-summary","slug":"putting-it-together","title":"Putting it together","text":"Lists, arrays and strings often work together. The program below reads quiz results as `name,score` lines until an empty line, and then prints everyone who scored above the average. The average is known only after the last line, so the program has to remember every name and score until then: that's what the two lists are for.\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<String> names = new ArrayList<>();\n        ArrayList<Integer> scores = new ArrayList<>();\n        while (true) {\n            String line = scanner.nextLine();\n            if (line.isEmpty()) {\n                break;\n            }\n            String[] parts = line.split(\",\");\n            names.add(parts[0]);\n            scores.add(Integer.valueOf(parts[1].trim()));\n        }\n\n        int sum = 0;\n        for (int score : scores) {\n            sum += score;\n        }\n        double average = (double) sum / scores.size();\n        System.out.println(\"Average: \" + average);\n\n        System.out.println(\"Above the average:\");\n        for (int i = 0; i < names.size(); i++) {\n            if (scores.get(i) > average) {\n                System.out.println(names.get(i) + \" (\" + scores.get(i) + \")\");\n            }\n        }\n    }\n}\n```\n\n```input\nAino,72\nKai, 55\nLumi,90\nNoor,61\n\n```\n\n```output\nAverage: 69.5\nAbove the average:\nAino (72)\nLumi (90)\n```\n\n- Each line is split into an array of two parts. The name goes into one list and the score into the other, so the same index points to the same person in both lists.\n- `trim()` lets the program accept `Kai, 55` as well as `Kai,55`.\n- The last loop goes through the indexes, so it can look up the name and the score of the same person.\n\n### The end of part 3\n\nThis step ends the material of the MOOC's third part. Part 3 was about handling more data than a few variables can hold. It started with finding bugs, and then brought lists, which grow as values are added, and arrays, whose size is fixed when they're made. A loop goes through either of them one element at a time. This module added the tools for taking text apart: its characters, its pieces and `split`. Together they let a program read any amount of input and make sense of it. The MOOC closes the part with [a summary page](https://java-programming.mooc.fi/part-3/5-increasing-amounts-of-data) on its own site, for reading only.\n","task":"Read one line of whole numbers separated by spaces, such as `4 8 15 16`, and print their sum and the largest of them. The numbers can be negative too. For the input `4 8 15 16` the program prints:\n\n```\nSum: 43\nLargest: 16\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        String line = scanner.nextLine();\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        String line = scanner.nextLine();\n        String[] parts = line.split(\" \");\n        int sum = 0;\n        int largest = Integer.valueOf(parts[0]);\n        for (String part : parts) {\n            int number = Integer.valueOf(part);\n            sum += number;\n            if (number > largest) {\n                largest = number;\n            }\n        }\n        System.out.println(\"Sum: \" + sum);\n        System.out.println(\"Largest: \" + largest);\n    }\n}\n","hints":["Split the line at the spaces and loop over the parts. Each part is text: turn it into a number with `Integer.valueOf(part)`.","All the numbers can be negative, so start `largest` from the first number, `Integer.valueOf(parts[0])`, not from 0."],"tests":[{"name":"Test 1","stdin":"4 8 15 16\n","expect":"Sum: 43\nLargest: 16","hidden":false},{"name":"Test 2","stdin":"-5 -2 -9\n","expect":"Sum: -16\nLargest: -2","hidden":true},{"name":"Test 3","stdin":"7\n","expect":"Sum: 7\nLargest: 7","hidden":true},{"name":"Test 4","stdin":"10 -3 10 2\n","expect":"Sum: 19\nLargest: 10","hidden":true}],"require":[{"pattern":"\\.split\\s*\\(","message":"Cut the line into numbers with `split`."}],"forbid":[],"more":[{"task":"Write a method `countWord(String text, String word)` that returns how many of the words in `text` are `word`, whatever the capitals. The words in `text` are separated by single spaces. The check runs `System.out.println(countWord(\"The cat saw the other cat\", \"the\"));` and expects:\n\n```\n2\n```\n","kind":"code","seed":"public class Main {\n    public static void main(String[] args) {\n        System.out.println(countWord(\"The cat saw the other cat\", \"the\"));\n    }\n\n    // Write the countWord method here.\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        System.out.println(countWord(\"The cat saw the other cat\", \"the\"));\n    }\n\n    public static int countWord(String text, String word) {\n        int count = 0;\n        for (String part : text.split(\" \")) {\n            if (part.equalsIgnoreCase(word)) {\n                count++;\n            }\n        }\n        return count;\n    }\n}\n","hints":["Split `text` at the spaces, and compare each part with `word` using `equalsIgnoreCase`.","Compare whole words: `contains` would also count the `the` inside `other`."],"tests":[{"name":"System.out.println(countWord(\"The cat saw the other cat\", \"the\"));","stdin":"","call":"System.out.println(countWord(\"The cat saw the other cat\", \"the\"));\n","expect":"2","hidden":false},{"name":"System.out.println(countWord(\"to be or not to be\", \"BE\"));","stdin":"","call":"System.out.println(countWord(\"to be or not to be\", \"BE\"));\n","expect":"2","hidden":true},{"name":"System.out.println(countWord(\"Nothing here\", \"cat\"));","stdin":"","call":"System.out.println(countWord(\"Nothing here\", \"cat\"));\n","expect":"0","hidden":true},{"name":"System.out.println(countWord(\"go\", \"go\"));","stdin":"","call":"System.out.println(countWord(\"go\", \"go\"));\n","expect":"1","hidden":true}],"require":[{"pattern":"\\.split\\s*\\(","message":"Cut the text into words with `split`."}],"forbid":[{"pattern":"(==|!=)\\s*\"\"|\"\"\\s*(==|!=)","message":"Compare text with `equals` or `equalsIgnoreCase`, not `==`."}]},{"task":"Read lines in the form `name,city` until an empty line. Then read one more line, a city, and print the names of everyone from that city, in the order they were read. If nobody is from there, print `Nobody from ` and the city. For the input `Aino,Oulu`, `Ben,Turku`, `Carla,Oulu`, an empty line and `Oulu` the program prints:\n\n```\nAino\nCarla\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        ArrayList<String> names = new ArrayList<>();\n        ArrayList<String> cities = new ArrayList<>();\n\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        ArrayList<String> names = new ArrayList<>();\n        ArrayList<String> cities = new ArrayList<>();\n        while (true) {\n            String line = scanner.nextLine();\n            if (line.isEmpty()) {\n                break;\n            }\n            String[] parts = line.split(\",\");\n            names.add(parts[0]);\n            cities.add(parts[1]);\n        }\n        String wanted = scanner.nextLine();\n        int found = 0;\n        for (int i = 0; i < names.size(); i++) {\n            if (cities.get(i).equals(wanted)) {\n                System.out.println(names.get(i));\n                found++;\n            }\n        }\n        if (found == 0) {\n            System.out.println(\"Nobody from \" + wanted);\n        }\n    }\n}\n","hints":["The first loop is like the ones in the last step: stop at an empty line, split, and add `parts[0]` to `names` and `parts[1]` to `cities`.","Then read the city to look for, and loop over the indexes: when `cities.get(i).equals(wanted)`, print `names.get(i)`. Count the matches, so that at the end you know whether there were none."],"tests":[{"name":"Test 1","stdin":"Aino,Oulu\nBen,Turku\nCarla,Oulu\n\nOulu\n","expect":"Aino\nCarla","hidden":false},{"name":"Test 2","stdin":"Aino,Oulu\nBen,Turku\n\nTampere\n","expect":"Nobody from Tampere","hidden":true},{"name":"Test 3","stdin":"Dev,Espoo\nEli,Espoo\nFin,Espoo\n\nEspoo\n","expect":"Dev\nEli\nFin","hidden":true},{"name":"Test 4","stdin":"Gus,Turku\nHal,Vaasa\n\nVaasa\n","expect":"Hal","hidden":true}],"require":[{"pattern":"\\.split\\s*\\(","message":"Cut each line into its parts with `split`."},{"pattern":"\\.equals(IgnoreCase)?\\s*\\(","message":"Compare the cities with `equals`."}],"forbid":[{"pattern":"(==|!=)\\s*\"\"|\"\"\\s*(==|!=)","message":"Check for the empty line with `isEmpty()` or `equals(\"\")`, not `==`."},{"pattern":"\\bwanted\\s*(==|!=)|(==|!=)\\s*wanted\\b","message":"Compare the cities with `equals`, not `==`."}]}]}