# Theory slides

The following are links to slideshows that summarise the covered topics.

# Enumerations

Create a class with a `main` method. For all of the exercises below, put code in `main` that tests the new content.

1. Create a `MyDate` class
1. In it, create `enum`s `Month` and `Weekday`
2. Create methods
1. Names
1. `Month::getEnglishName`
1. `Month::getHunName`,
2. `Month::getXName` (where `X` is your favourite language),
3. replace the above methods using an `enum Language`
4. make similar methods for `Weekday`s
2. `MyDate::getWeekDay`
3. `Weekday::isThisDay(Month month, int day)`
3. Write Javadoc documentation for the methods

# Anonymous functions (Lambda functions)

In the following exercises, it is your job to decide which (built-in) lambda to use. The most common choices are listed here, and you can also have a look at the documentation of the `java.util.function` package.

• `Runnable`: Ø → Ø
• `Consumer`: T → Ø
• `IntConsumer`: int → Ø
• `Supplier`: Ø → T
• `Function`: T1T2
• `IntFunction`: int → T
• `IntUnaryOperator`: int → int
• `BiFunction`: (T1, T2) → T3
• `IntBinaryOperator`: (int, int) → int
• `Predicate`: T → boolean
1. Have some fun with the previously created enums.
• Make a lambda that takes a day of the week and a number `n`, and returns the weekday that is `n` days after the other one. Keep in mind that `n` can be a big number, or a negative one.
• Make a lambda that takes two weekdays, and returns whether the first one is earlier in the week than the second one.
• Make a lambda that, when called, returns a day of the week; when called again and again, it produces the days of the week in order. If called even more times, it starts at the first day again.
• Make a lambda that returns a lambda like the previous one. The “outer” lambda gets a day of the week as a parameter; the returned lambda starts from that day.
2. Sort the command line arguments based on the number of `'a'` characters in them.
3. Sort the command line arguments so that those arguments that contains names of weekdays come first.
4. Create the method `createArray` that fills in an array. It takes the length of the array as an argument, and an `int→int` function `f`. Use the `f` function on each index of the array, and it will produce the value for the index.
• Make an array of arrays in a similar way. Here, the function has to take two arguments for the two indices.
• Can you make `createArray` generate an array of arbitrary depth?
5. Create the method `compose` that takes two functions and returns their composition, which is another function.
6. Create the method `iterate` that takes a function `f` and a (non-negative) integer `n` and returns a function that iterates `f` `n` times.
7. Create the method `geneticAlgorithm` that runs a genetic algorithm.
• The goal of the algorithm is to find an approximate solution to a problem by making “educated guesses”.
• The algorithm will work on an `Entity` class.
• The algorithm takes a number of arguments. Most of these are lambdas.
1. First, `populationCount` entities are created using `createRandomEntity()`.
2. Then, `doCrossover(Entity e1, Entity e2)` is invoked on two random entities. This is repeated `crossoverCount` times.
3. Then, `mutateEntity(Entity e)` is invoked on a randomly selected entity. The method, with `mutationProbability` probability will change the entity in some way.
• Usually, `mutationProbability` is quite low, perhaps 0.1%.
4. Then, `calculateFitness(Entity e)` calculates the fitness of each entity. We only keep the best `pruneCount` entities; we fill up the remaining places with `createRandomEntity()`.
5. So far, we have generated a new generation out of the previous one. We repeat these steps `generationCount` times, then return with the entity with the highest finess value of the last generation.
• Let us see how well the genetic algorithm can crack a code. Call the algorithm the following way.
• Write some text into a `String`, this will be the `code` to crack.
• You may limit your strings to lowercase English characters in this exercise.
• The `Entity` class will contain a `String` now.
• The fitness value of an `Entity` shows how far its `String` is from the `code`.
• Compute the fitness of an `Entity` like this: add the difference of the lengths of the strings, plus the number of differing character positions.
• With this formula, the best fitness value is `0`, which is reached when we have reached the `code`.
• A crossover between two `Entity`s splits both strings at random positions, and joins their first and second parts.
• A mutation changes a random character in the string of the `Entity`.
• Run the genetic algorithm a couple of times, and see whether it can crack the code.
• Experiment with different values for the parameters.

# Streams

1. Print the lengths of the command line arguments in reverse order.
2. Print the sum of even numbers that are greater than `8` from the command line arguments.
• Variant: ignore all texts that are not numbers.
• Variant: using a lambda, take the condition as an argument. So, instead of testing for “greater than `8`”, test whatever the caller specifies.
3. Make a method that generates a stream of the first `n` prime numbers.
4. Given some filenames in the command line arguments, print the names on one line, separated with commas, in descending order in the number of lines in the file. If two files have the same number of lines, then the one with more words on its first line should come first.

# Unit testing

In the following exercises, test the described functions. Try everything covered in the lecture: descriptions, parameters etc. For each exercise, make several small test cases.

1. Make a function `summer` that sums the numbers between its two arguments by adding them together one by one.
2. Make a function `shortSummer` that sums the numbers between its two arguments with a formula.
3. Make a function that takes an English–Hungarian dictionary represented as a `Map` and a text in English. The function will translate the text word by word, and inserts “?” for all words not in the dictionary.
• You may use different languages if you wish.
4. Test the lambda that produces the first `n` primes.
• If `n` is negative, the lambda should throw an `IllegalArgumentException`. Find out how that can be done, then test for the exception.
5. Test the lambda that gets a weekday, and returns the weekday `n` days after that. Use parameters from a `@CsvSource` or any other source.
6. Create the class `Battleship` that represents a state of the Battleship game.
• In it, create the methods `shoot`, `hitCount` and `safeCount`.
• Also add any constructors, methods etc. you feel necessary.
• Test them using nested tests.
7. Make a method that takes a file name and an arbitrary number of arguments, and prints the sum of the numbers into the file.
• Test whether the file is present, and if it is, test the contents of the file.
• Make sure you delete the file at the end of each test case.
8. Change `geneticAlgorithm` so that it also takes an individual as a parameter.
• This individual should always be a member of the population. That is, it should not be thrown out even if its fitness is too low.
9. Check with JUnit that the return value of `geneticAlgorithm` contains at least one individual whose fitness value is not less than that of this individual.
1. Extract the body of the loop in `geneticAlgorithm` into a separate function. Make a JUnit test that checks that the size of the population at the beginning of every loop iteration equals `populationCount` (the first parameter of `geneticAlgorithm`).

# Serialization

Make a serializable class `Book` that contains the following information:

• `title`
• `author`
• `year`
• `pages`

The class `BookStore` stores books in a `Map`, identifying them by their names. The class implements the following methods.

``````// Puts some predefined books into the map, to serve as initial data.

// Writes the books into the given file using serialization.
// Returns whether the save operation was successful.
boolean saveBooks(String fileName);

// Loads the books from the given file.
// Returns whether the load operation was successful.

Make a simple application that tests the above operations.

# Sockets

1. Make a simple client-server application whose parts communicate using serialization. Use the `Book` and `BookStore` classes from the previous exercise.
• When the client connects, the server does the following.
1. Takes the name of a book from the client.
2. Creates a `BookStore`.
3. Tries to load the books from a file.
• If unsuccessful, the store is initialised using `addSomeBooks`.
4. Looks up the requested book by name in the store.
1. If found, sends `true` to the client, then the book itself.
2. Otherwise, sends `false` to the client.
5. Saves the books to the file.
• The client connects to the server, and takes the appropriate steps, mirroring the server.
2. Make the previous server should accept clients one after the other.
• At the same time, only one client is connected.
• When the client disconnects, the server starts waiting for another client.
3. Create a server that receives numbers (as text) from the client. When the client is done sending numbers, the server sends the client their sum, then they disconnect.
4. Create a server that uses text messages to communicate with the client. The client sends the name of a file; if it exists, the server sends back its contents.
1. Let the client send many file names. The server sends back the contents of all existing files.
5. Create a server that remembers how many clients have connected to it so far, and sends this number in a text message to the client. The client receives this number and prints it, but it doesn’t send any messages to the server.

1. Make two threads that each use `System.out.println` to print a given text `10000` times. (Give different texts to the threads.)
• Notice how the printouts are interleaved.
2. Now, instead of `println`, print each text character by character (and an ending newline).
• What happens to the printout?
• Use synchronization to fix the issue.
3. Two goats are trying to cross a narrow bridge from opposite sides. They meet in the middle, and they start pushing each other. Independently of each other, the goats take some time, and then push the other goat one step. Whenever one of the goats is pushed off of the bridge, the game ends. Take the speed of the goats (how much they wait between pushes) and the length of the bridge as parameters; make the program log important actions.
4. Compute the `n`th Fibonacci number so that the non-basic cases compute the two halves of the addition on two separate threads.

1. Make a TCP/IP server that can handle several clients: after `accept`ing them, each connection is handled by a separate thread.
• Make sure to use an inefficient Fibonacci implementation so that it takes long, or add a delay (`Thread.sleep`).