Create a class with a main method. For all of the exercises below, put code in main that tests the new content.
Create a MyDate class
In it, create enums Month and Weekday
Create methods
Names
Month::getEnglishName
Month::getHunName,
Month::getXName (where X is your favourite language),
replace the above methods using an enum Language
make similar methods for Weekdays
MyDate::getWeekDay
Weekday::isThisDay(Month month, int day)
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: T1 → T2
IntFunction: int → T
IntUnaryOperator: int → int
BiFunction: (T1, T2) → T3
IntBinaryOperator: (int, int) → int
Predicate: T → boolean
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.
Sort the command line arguments based on the number of 'a' characters in them.
Sort the command line arguments so that those arguments that contains names of weekdays come first.
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?
Create the method compose that takes two functions and returns their composition, which is another function.
Create the method iterate that takes a function f and a (non-negative) integer n and returns a function that iteratesfn times.
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.
First, populationCount entities are created using createRandomEntity().
Then, doCrossover(Entity e1, Entity e2) is invoked on two random entities. This is repeated crossoverCount times.
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%.
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().
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 Entitys 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
Print the lengths of the command line arguments in reverse order.
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.
Make a method that generates a stream of the first n prime numbers.
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.
Make a function summer that sums the numbers between its two arguments by adding them together one by one.
Make a function shortSummer that sums the numbers between its two arguments with a formula.
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.
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.
Test the lambda that gets a weekday, and returns the weekday n days after that. Use parameters from a @CsvSource or any other source.
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.
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.
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.
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.
Make a simple application that tests the above operations.
Sockets
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.
Takes the name of a book from the client.
Creates a BookStore.
Tries to load the books from a file.
If unsuccessful, the store is initialised using addSomeBooks.
Looks up the requested book by name in the store.
If found, sends true to the client, then the book itself.
Otherwise, sends false to the client.
Saves the books to the file.
The client connects to the server, and takes the appropriate steps, mirroring the server.
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.
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.
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.
Let the client send many file names. The server sends back the contents of all existing files.
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.
Threading
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.
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.
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.
Compute the nth Fibonacci number so that the non-basic cases compute the two halves of the addition on two separate threads.
Sockets with threading
In each of the following exercises, communication can be text based or binary based, it’s your choice.
Make a TCP/IP server that can handle several clients: after accepting them, each connection is handled by a separate thread.
The program works like this: the client sends a number, and the server replies with the corresponding Fibonacci number.
Make sure to use an inefficient Fibonacci implementation so that it takes long, or add a delay (Thread.sleep).
Make a server to which any number of clients can connect. Whenever a client sends a text message, it is immediately sent to all other (currently connected) clients.
Make a program that simulates a stock market. It has two ports: regular clients connect to the first port, admins to the second one.
Admins can set the value of stocks. Stocks are identified by their names.
Regulars can query stock prices, and buy and sell stocks.
For added difficulty, you can let the clients also trade stocks with each other (for money or for other stocks).
It is up to you to decide the details of the protocol.