Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Her ligger løsningsforslaget til eksamen kontinuasjonseksamen 2021. Vi vil senere legge til ofte forekommende feil og misforståelser i kombinasjon med kildekoden .

...

Expand
titleDel 4 - Objektstrukturer og delegering (20 %)

Oppgave a) Objektstrukturer (12 %)

Fyll inn vedlagte Temperature. Temperature har oversikt over en temperatur som enten er i Fahrenheit eller i Celsius.

Temperature har følgende metoder

  • Temperature(double degrees, char scale) - Initialiserer et Temperature-objekt med en skala (Fahrenheit/Celsius) og et antall grader
  • getScale() - Returnerer om temperaturen er i Fahrenheit eller Celsius.
  • getDegrees() - Returnerer temperaturen i antall grader.
  • toOther() - Gjør om dette temperatur-objektet til den andre skalaen og returnerer det.
  • inOther() - Lager et nytt temperatur-objekt i den den andre skalaen og returnerer det.
  • lower(double amount) - Senker temperaturen med et antall grader.
Expand
titleKodeskjelett 4a


Code Block
languagejava
package del4;

public class Temperature {

	// Add any needed fields
	/**
	 * 
	 * @param degrees an arbitrary number
	 * @param scale   a character declaring the scale
	 * 
	 * @throws IllegalArgumentException if scale is not 'C' or 'F'
	 */
	public Temperature(double degrees, char scale) {
		// TODO

	}

	/**
	 * 
	 * @return The current scale
	 */
	public char getScale() {
		// TODO
		return '0';
	}

	/**
	 * 
	 * @return the current degree of this object
	 */
	public double getDegrees() {
		// TODO
		return 0;
	}

	/**
	 * Converts this temperature object to be the opposite scale of what it
	 * currently is
	 * 
	 * @return this temperature object, converted with value in Celsius if the scale
	 *         of this temperature object is Fahrenheit, and value in Fahrenheit if
	 *         this the scale of this temperature object is Celsius
	 */
	public Temperature toOther() {
		// TODO
		return null;
	}

	/**
	 * Creates a new temperature object with values in the other scale of this
	 * temperature object
	 * 
	 * @return a new Temperature object, with value in Celsius if the scale of this
	 *         temperature object is Fahrenheit, and value in Fahrenheit if the
	 *         scale of this temperature object is Celsius
	 */
	public Temperature inOther() {
		// TODO
		return null;
	}

	/**
	 * Lowers the temperature
	 * 
	 * @param amount the amount to lower by
	 */
	public void lower(double amount) {
		// TODO
	}

	/**
	 * 
	 * @param celsius
	 * @return the temperature in Fahrenheit
	 */
	public static double convertCelsisusToFahrenheit(double celsius) {
		return (celsius * 1.8 + 32.0);
	}

	/**
	 * 
	 * @param fahrenheit
	 * @return the temperature in Celsius
	 */
	public static double convertFahrenheitToCelsius(double fahrenheit) {
		return (fahrenheit - 32.0) / 1.8;
	}

	public static void main(String[] args) {
		Temperature t = new Temperature(20, 'C');
		// Should print 20
		System.out.println(t.getDegrees());
		t.lower(10);
		// Should now print 10
		System.out.println(t.getDegrees());
		t.toOther();
		// Should now print 50
		System.out.println(t.getDegrees());
		t.toOther();

		Temperature t2 = t.inOther();
		// Should be 50;
		System.out.println(t2.getDegrees());

		// Should be 10
		System.out.println(t.getDegrees());
	}

}




Expand
titleLF


Code Block
languagejava
package del4;

public class Temperature {
	
	private char scale; // Only valid values are C or F
	private double degree;
	
	/**
	 * 
	 * @param degrees an arbitrary number
	 * @param scale a character declaring the scale
	 * 
	 * @throws IllegalArgumentException if scale is not 'C' or 'F'
	 */
	public Temperature(double degrees, char scale) {
		this.degree = degrees;
		if (scale != 'C' && scale != 'F') {
			throw new IllegalArgumentException();
		}
		this.scale = scale;
	}

	/**
	 * 
	 * @return The current scale
	 */
	public char getScale() {
		return scale;
	}

	
	/**
	 * 
	 * @return the current degree of this object
	 */
	public double getDegrees() {
		return degree;
	}

	/**
	 * Converts this temperature object to be the opposite scale of what it
	 * currently is
	 * 
	 * @return this temperature object, converted with value in Celsius if the value
	 *         of this temperature object is Fahrenheit, and value in Fahrenheit if
	 *         this temperature object is Celsius
	 */
	public Temperature toOther() {
		if (this.scale == 'C') {
			this.scale = 'F';
			this.degree = convertCelsisusToFahrenheit(this.degree);
		}
		else {
			this.scale = 'C';
			this.degree = convertFahrenheitToCelsius(this.degree);
		}
		return this;
	}

	/**
	 * Creates a new temperature object with values in the other scale of this
	 * temperature object.
	 * 
	 * @return a new Temperature object, with value in Celsius if the value of this
	 *         temperature object is Fahrenheit, and value in Fahrenheit if this
	 *         temperature object is Celsius
	 */
	public Temperature inOther() {
		if (this.scale == 'C') {
			return new Temperature(convertCelsisusToFahrenheit(this.degree), 'F');
	
		}
		else {
			return new Temperature(convertFahrenheitToCelsius(this.degree), 'C');

		}
	}


	
	/**
	 * Lowers the temperature
	 * @param amount the amount to lower by
	 */
	public void lower(double amount) {
		this.degree -= amount;
	}
	
	/**
	 * 
	 * @param celsius
	 * @return the temperature in Fahrenheit
	 */
	public static double convertCelsisusToFahrenheit(double celsius) {
		return (celsius * 1.8 + 32.0);
	}
	
	/**
	 * 
	 * @param fahrenheit
	 * @return the temperature in Celsius
	 */
	public static double convertFahrenheitToCelsius(double fahrenheit) {
		return (fahrenheit - 32.0) / 1.8;
	}
	
	public static void main(String[] args) {
		Temperature t = new Temperature(20, 'C');
		// Should print 20
		System.out.println(t.getDegrees());
		t.lower(10);
		// Should now print 10
		System.out.println(t.getDegrees());
		t.toOther();
		// Should now print 50
		System.out.println(t.getDegrees());
		t.toOther();

		Temperature t2 = t.inOther();
		// Should be 50;
		System.out.println(t2.getDegrees());

		// Should be 10
		System.out.println(t.getDegrees());
	}


	
	
}



Oppgave b) Delegering (8%)

Fyll inn DelegatingTemperature. DelegatingTemperature skal delegere til et underliggende Temperature-objekt og ha metodene beskrevet under. Du kan gå ut ifra at alle metodene til delegaten fungerer slik de skal.

  • DelegatingTemperature(Temperature delegate, char scale) - Oppretter et DelegatingTemperature-objekt med en skala (Fahrenheit/Celsisus) og et antall grader som er representert i delegaten.
  • getScale() - Returnerer om temperaturen er i Fahrenheit eller Celsius.
  • getDegrees() - Returnerer temperaturen i antall grader.
  • toOther() - Gjør om dette temperatur-objektet til den andre skalaen og returnerer det.
  • inOther() - Lager et nytt temperatur-objekt i den den andre skalaen og returnerer det.
Expand
titleKodeskjelett 4b


Code Block
languagejava
package del4;

public class DelegatingTemperature {

	// Add any needed fields
	/**
	 * 
	 * @param delegate - the Temperature to get degree from
	 * @param scale    a character declaring the scale of this temperature object
	 * 
	 * @throws IllegalArgumentException if scale is not 'C' or 'F'
	 */
	public DelegatingTemperature(Temperature delegate, char scale) {
		// TODO
	}

	/**
	 * 
	 * @return The current scale
	 */
	public char getScale() {
		// TODO
		return '0';
	}

	/**
	 * 
	 * @return the current degree from the delegate, converted to the correct scale
	 */
	public double getDegrees() {
		// TODO
		return 0;
	}

	/**
	 * 
	 * @return this temperature object, with scale converted to Celsius if the
	 *         current scale of this delegatingTemperature object is in Fahrenheit,
	 *         and value in Fahrenheit if this delegatingTemperature object is in
	 *         Celsius
	 */
	public DelegatingTemperature toOther() {
		// TODO
		return null;
	}

	/**
	 * 
	 * @return a new DelegatingTemperature object, with the same delegate, with
	 *         scale converted to Celsius if the current scale of this
	 *         delegatingTemperature object is Fahrenheit, and value in Fahrenheit
	 *         if this delegatingTemperature object is Celsius
	 */
	public DelegatingTemperature inOther() {
		// TODO
		return null;

	}

	public static void main(String[] args) {
		Temperature t = new Temperature(10, 'C');
		DelegatingTemperature dt = new DelegatingTemperature(t, 'F');
		// Should now print 10
		System.out.println(t.getDegrees());
		// Should now print 50
		System.out.println(dt.getDegrees());
		dt.toOther();
		// Should now print 10
		System.out.println(dt.getDegrees());
		// Should now print 10
		System.out.println(t.getDegrees());
	}
}



Expand
titleLF


Code Block
languagejava
package del4;

public class DelegatingTemperature {

	// Add any needed fields
	private Temperature delegate;
	private char scale;
	/**
	 * 
	 * @param delegate - the Temperature to get degree from
	 * @param scale    a character declaring the scale of this temperature object
	 * 
	 * @throws IllegalArgumentException if scale is not 'C' or 'F'
	 */
	public DelegatingTemperature(Temperature delegate, char scale) {
		this.delegate = delegate;
		this.setScale(scale);
	}

	/**
	 * 
	 * @return The current scale
	 */
	public char getScale() {
		return this.scale;
	}
	
	private void setScale(char scale) {
		if (scale != 'F' && scale != 'C') {
			throw new IllegalArgumentException() ;
		}
		this.scale = scale;
	}

	/**
	 * 
	 * @return the current degree from the delegate, converted to the correct scale
	 */
	public double getDegrees() {
		if (this.scale == this.delegate.getScale()) {
			return this.delegate.getDegrees();
		}
		return this.delegate.inOther().getDegrees();
	}

	/**
	 * 
	 * @return this temperature object, with scale converted to Celsius if the
	 *         current scale of this delegatingTemperature object is in Fahrenheit, and
	 *         value in Fahrenheit if this delegatingTemperature object is in Celsius
	 */
	public DelegatingTemperature toOther() {
		this.scale = this.scale == 'C' ? 'F' : 'C';
		return this;
	}

	/**
	 * 
	 * @return a new DelegatingTemperature object, with the same delegate, with
	 *         scale converted to Celsius if the current scale of this
	 *         delegatingTemperature object is Fahrenheit, and value in Fahrenheit
	 *         if this delegatingTemperature object is Celsius
	 */
	public DelegatingTemperature inOther() {
		return new DelegatingTemperature(this.delegate, this.scale == 'C' ? 'F' : 'C');

	}

	public static void main(String[] args) {
		Temperature t = new Temperature(10, 'C');
		DelegatingTemperature dt = new DelegatingTemperature(t, 'F');
		// Should now print 10
		System.out.println(t.getDegrees());
		// Should now print 50
		System.out.println(dt.getDegrees());
		dt.toOther();
		// Should now print 10
		System.out.println(dt.getDegrees());
		// Should now print 10
		System.out.println(t.getDegrees());
	}
}



...

Expand
titleDel 7 - Objektstrukturer og java-teknikker (10 %)

Implementer metodene i Realtor

  • Realtor(double comission) oppretter et Realtor objekt med en gitt provisjon
  • setCommission(double comission) Oppdaterer provisjonen til megleren
  • addProperty(Property property) Legger til en eiendom i porteføljen til megleren
  • calculateTotalCommission() - Regner ut total provisjonslønn basert på alle solgte boliger megleren har
  • iterator() - Returnerer en iterator for å iterere gjennom alle eiendommene til megleren
Expand
titleKodeskjelett del 7


Code Block
languagejava
package del5_8;

import java.util.Iterator;

public class Realtor implements Iterable<Property> {

	/**
	 * Creates a Realtor object
	 * 
	 * @param name       the name of the realtor
	 * @param commission the commission the realtor takes for a sale
	 */
	public Realtor(String name, double commission) {
		// TODO
	}

	/**
	 * 
	 * @return the name of the realtor
	 */
	public String getName() {
		// TODO
		return null;
	}

	/**
	 * 
	 * @param commission the new commission of the realtor
	 * 
	 * @throws IllegalArgumentException if the commission not between (excluding) 0
	 *                                  and (including) 100.
	 */
	public void setCommission(double commission) {
		// TODO
	}

	/**
	 * Adds a property to the realtor's sale collection
	 * 
	 * @param property a property
	 */
	public void addProperty(Property property) {
		// TODO
	}

	/**
	 * The total commission is calculated as the sum of the highest bid of each sold
	 * property times the commission rate. The commission rate is calculated based
	 * on the realtor's current commission rate and does not need to consider
	 * historical commission rates
	 * 
	 * A realtor with commission of 10 %, and two sold properties sold at 1000 each,
	 * would have a total commission value of 200
	 * 
	 * @return the calculated commission of the realtor
	 */
	public double calculateTotalCommission() {
		// TODO
		return 0;
	}

	@Override
	public Iterator<Property> iterator() {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * 
	 * @return an iterator to be able to iterate through all the properties of this
	 *         realtor
	 */
	public Iterator<Property> iterable() {
		return null;
	}

	public static void main(String[] args) {
		Realtor realtor = new Realtor("test", 10);
		// The following will only work if BusinessProperty and Property has the correct
		// implementation
		Property p = new Property("name", 1500);
		p.bidReceived("BIDDER", 2000);
		p.setIsSold();
		realtor.addProperty(p);
		// Should be 200
		System.out.println(realtor.calculateTotalCommission());
	}

}



Expand
titleLF


Code Block
languagejava
package del5_8;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Realtor implements Iterable<Property>{

	private List<Property> properties = new ArrayList<>();
	private double commission;
	private String name;
	/**
	 * Creates a Realtor object
	 * 
	 * @param name      the name of the realtor
	 * @param comission the commission the realtor takes for a sale
	 */
	public Realtor(String name, double commission) {
		this.setCommission(commission);
		this.name = name;
	}
	
	public String getName() {
		return this.name;
	}

	/**
	 * 
	 * @param comission the new comission of the realtor
	 * 
	 * @throws IllegalArgumentException if the commission not between (excluding) 0
	 *                                  and (including) 100.
	 */
	public void setCommission(double commission) {
		if (commission <= 0 || commission > 100) {
			throw new IllegalArgumentException("Comission must be between 0 and 100");
		}
		this.commission = commission;
	}

	/**
	 * Adds a property to the realtor's sale collection
	 * 
	 * @param property a property
	 */
	public void addProperty(Property property) {
		this.properties.add(property);
	}

	/**
	 * The total comission is calculated as the sum of the highest bid of each sold
	 * property times the commission rate The comission rate is calculated based on
	 * the realtor's current commission rate and does not need to consider
	 * historical commission rates
	 * 
	 * @return the calculated commission of the realtor
	 */
	public double calculateTotalCommission() {
		return this.properties.stream().filter(p -> p.isSold()).mapToDouble(Property::getHighestBid)
				.map(price -> price * (commission) / 100.0).sum();
	}

	@Override
	public Iterator<Property> iterator() {
		return this.properties.iterator();
	}
	
	public String toString() {
		return this.name;
	}	
	public static void main(String[] args) {
		Realtor realtor = new Realtor("test", 10);
		// Will only work if BusinessProperty and Property has the correct
		// implementation
		Property p = new Property("name", 1500);
		p.bidReceived("BIDDER", 2000);
		p.setIsSold();
		realtor.addProperty(p);
		// Should be 200
		System.out.println(realtor.calculateTotalCommission());
	}

}



...

Expand
titleDel 8 - Interfaces og Comparator (5 %)

Implementer metoden i RealtorComparator

  • sortRealtorsByHighestBidReceived - Returnerer en Comparator som sorterer en liste med Realtor-objekter. Disse skal sorteres etter hvilken megler som har oppnådd det høyeste budet basert på alle eiendommene fra høyest til lavest

    Expand
    titleKodeskjelett del 8


    Code Block
    languagejava
    package del5_8;
    
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    
    public class RealtorComparator {
    
    	/**
    	 * 
    	 * @return a comparator that sorts Realtor objects based on the highest bid they
    	 *         have received on any of their properties from highest to lowest
    	 * 
    	 *         Example output with a list of one "realtor1" with two properties,
    	 *         property1 with highest bid 1000, and property2 with highest bid 2000,
    	 *         and a second "realtor2" with one property with the highest bid of
    	 *         500, and a third "realtor3" with one property with the highest bid of
    	 *         3000 would yield the following result
    	 * 
    	 *         realtor3
    	 *         realtor1 
    	 *         realtor2
    	 * 
    	 *         I.e: This sorts by the highest, single sale, and not the total of
    	 *         sales for each realtor.
    	 * 
    	 * 
    	 */
    	public static Comparator<Realtor> sortRealtorsByHighestBidReceived() {
    		return null;
    	}
    
    	public static void main(String[] args) {
    		// This may not yield the correct results if Property/BusinessProperty/Realtor
    		// has not been correctly implemented
    		Realtor realtor = new Realtor("test1", 10);
    		Realtor realtor2 = new Realtor("test2", 10);
    		Property p = new BusinessProperty("name", 1500);
    		p.bidReceived("BIDDER", 2000);
    		Property p2 = new BusinessProperty("name2", 1000);
    		p2.bidReceived("BIDDER", 1500);
    		realtor.addProperty(p);
    		realtor2.addProperty(p2);
    		List<Realtor> realtors = Arrays.asList(realtor2, realtor);
    		System.out.println(realtors);
    		Collections.sort(realtors, sortRealtorsByHighestBidReceived());
    		// A more useful to string method or using the debugger might be helpful here
    		// Should be in the opposite direction with realtor, and then realtor2
    		System.out.println(realtors);
    
    	}
    
    }
    



    Expand
    titleLF


    Code Block
    languagejava
    package del5_8;
    
    
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    
    public class RealtorComparator {
    
    	/**
    	 * 
    	 * @return a comparator that sort Realtor objects based on the highest bid they
    	 *         have received on any of their properties from highest to lowest
    	 * 
    	 *         Example output with a list of one "realtor1" with two properties,
    	 *         property1 with highest bid 1000, and property2 with highest bid 2000,
    	 *         and a second "realtor2" with one property with the highest bid of
    	 *         500, and a third "realtor3" with one property with the highest bid of
    	 *         3000 would yield the following result
    	 * 
    	 *         realtor3 
    	 *         realtor1 
    	 *         realtor2
    	 * 
    	 * 
    	 */
    	public static Comparator<Realtor> sortRealtorsByHighestBidReceived() {
    		return (Realtor r1, Realtor r2) -> {
    			int highestBidR1 = 0;
    			for (Property property: r1) {
    				highestBidR1 = Math.max(highestBidR1, property.getHighestBid());
    			}
    			int highestBidR2 = 0;
    			for (Property property: r2) {
    				highestBidR1 = Math.max(highestBidR2, property.getHighestBid());
    			}
    			return highestBidR2-highestBidR1;
    		};
    	}
    	
    	public static void main(String[] args) {
    		// This may not yield the correct results if Property/BusinessProperty/Realtor has not been correctly implemented
    		Realtor realtor = new Realtor("test1", 10);
    		Realtor realtor2 = new Realtor("test2", 10);
    		Property p = new BusinessProperty("name", 1500);
    		p.bidReceived("BIDDER", 2000);
    		Property p2 = new BusinessProperty("name2", 1000);
    		p2.bidReceived("BIDDER", 1500);
    		realtor.addProperty(p);
    		realtor2.addProperty(p2);
    		List<Realtor> realtors=  Arrays.asList(realtor2, realtor);
    		System.out.println(realtors);
    		Collections.sort(realtors, sortRealtorsByHighestBidReceived());
    		// A more useful to string method or using the debugger might be helpful here
    		System.out.println(realtors);
    		
    	}
    
    }
    



...

Expand
titleDel 9 - Funksjonelle grensesnitt og lister (10 %)

Fyll ut UniversityHandbookUtils sine metoder for operasjoner på en liste med Course-objekter.

    • getCourseNames(List courses) - Returnerer en liste med navnene til alle emnene
    • getCourseProperties(List courses, Function<Course, String> function) - Returnerer alle emner transformerte ved hjelp av funksjonen
    • calculateGradesSummary(List courses, BinaryOperator operator) - Returnerer resultatet av å kjøre operatoren på alle karaktersnittene til emnene
    • getCoursesYouCanTake(List courses, List takenCourses) - Returnerer alle emnene hvor du tilfredstiller alle forkunnskapskravene (takenCourses representerer her emnene du tidligere har tatt)

Expand
titleKodeskjelett del 9


Code Block
languagejava
package del9;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class Course {
	private String courseName;
	private List<Course> prerequisites = new ArrayList<>();
	private double averageGrade;

	public Course(String courseName, double averageGrade) {
		this(courseName);
		this.averageGrade = averageGrade;
	}

	public Course(String courseName) {
		this.courseName = courseName;
	}
	
	public String getCourseName() {
		return courseName;
	}

	public void setAverageGrade(double averageGrade) {
		this.averageGrade = averageGrade;
	}
	
	public double getAverageGrade() {
		return averageGrade;
	}

	public void addPrequisite(Course course) {
		this.prerequisites.add(course);
	}
	
	public Collection<Course> getPrerequisites() {
		return new ArrayList<>(prerequisites);
	}
	
	public String toString() {
		return this.courseName;
	}

}

package del9;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.BinaryOperator;
import java.util.function.Function;

public class UniversityHandbookUtils {

	/**
	 * 
	 * @param courses List of course objects
	 * @return a list of course names
	 */
	public static Collection<String> getCourseNames(Collection<Course> courses) {
		// TODO
		return Arrays.asList();
	}

	/**
	 * 
	 * @param courses List of course objects
	 * @return a list of a course objects transformed by the function
	 */
	public static Collection<String> getCourseProperties(Collection<Course> courses,
			Function<Course, String> function) {
		// TODO
		return Arrays.asList();
	}

	/**
	 * 
	 * @param courses  a list of course objects
	 * @param operator a binary operator
	 * @return the result of applying the operator across all average grades
	 */
	public static double calculateGradesSummary(Collection<Course> courses, BinaryOperator<Double> operator) {
		// TODO
		return 0;
	}

	/**
	 * 
	 * @param courses      List of course objects
	 * @param takenCourses List of course objects
	 * @return a list of courses where takenCourses contains all prerequisites
	 *         needed to enroll in the course
	 */
	public static Collection<Course> getCoursesYouCanTake(Collection<Course> courses, Collection<Course> takenCourses) {
		// TODO
		return Arrays.asList();
	}

	public static void main(String[] args) {
		Course tdt4109 = new Course("TDT4109", 3.23);
		Course tdt4100 = new Course("TDT4100", 3.23);
		Course tdt4120 = new Course("TDT4120", 3.23);
		Course tdt1337 = new Course("TDT1337", 3.23);
		Course tdt3713 = new Course("TDT3713", 3.23);

		tdt4100.addPrequisite(tdt4109);
		tdt4120.addPrequisite(tdt4109);
		tdt4120.addPrequisite(tdt4100);
		tdt1337.addPrequisite(tdt3713);
		tdt3713.addPrequisite(tdt1337);
		List<Course> courses = Arrays.asList(tdt4109, tdt4100, tdt4120, tdt1337, tdt3713);

		// These two lines should print the same list of course names
		System.out.println(getCourseNames(courses));
		System.out.println(getCourseProperties(courses, c -> c.getCourseName()));

		// Should print 16.15
		System.out.println(calculateGradesSummary(courses, (prevGrade, currentGrade) -> prevGrade + currentGrade));

		// Should print tdt4109, tdt4100 (order does not matter)
		System.out.println(getCoursesYouCanTake(courses, Arrays.asList(tdt4109)));

	}

}



Expand
titleLF


Code Block
languagejava
package del9;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;

public class UniversityHandbookUtils {

	/**
	 * 
	 * @param courses List of course objects
	 * @return a list of course names
	 */
	public static List<String> getCourseNames(Collection<Course> courses) {
		return courses.stream().map(Course::getCourseName).collect(Collectors.toList());
	}

	/**
	 * 
	 * @param courses List of course objects
	 * @return a list of a course objects transformed by the function
	 */
	public static Collection<String> getCourseProperties(Collection<Course> courses,
			Function<Course, String> function) {
		return courses.stream().map(function).collect(Collectors.toList());
	}

	/**
	 * 
	 * @param courses  a list of course objects
	 * @param operator a binary operator
	 * @return a summary of all the grades of the courses by applying the binary
	 *         operator
	 */
	public static double calculateGradesSummary(Collection<Course> courses, BinaryOperator<Double> operator) {
		return courses.stream().map(Course::getAverageGrade).reduce(operator).get();

	}

	/**
	 * 
	 * @param courses      List of course objects
	 * @param takenCourses List of course objects
	 * @return a list of courses where takenCourses contains all prerequisites
	 *         needed to enroll in the course
	 */
	public static Collection<Course> getCoursesYouCanTake(Collection<Course> courses, Collection<Course> takenCourses) {
		return courses.stream().filter(course -> takenCourses.containsAll(course.getPrerequisites()))
				.collect(Collectors.toList());
	}
	
	public static void main(String[] args) {
		Course tdt4109 = new Course("TDT4109", 3.23);
		Course tdt4100 = new Course("TDT4100", 3.23);
		Course tdt4120 = new Course("TDT4120", 3.23);
		Course tdt1337 = new Course("TDT1337", 3.23);
		Course tdt3713 = new Course("TDT3713", 3.23);

		tdt4100.addPrequisite(tdt4109);
		tdt4120.addPrequisite(tdt4109);
		tdt4120.addPrequisite(tdt4100);
		tdt1337.addPrequisite(tdt3713);
		tdt3713.addPrequisite(tdt1337);
		List<Course> courses = Arrays.asList(tdt4109, tdt4100, tdt4120, tdt1337, tdt3713);
		
		// These two lines should print the same list of course names
		System.out.println(getCourseNames(courses));
		System.out.println(getCourseProperties(courses, c -> c.getCourseName()));
		
		// Should print 16.15 
		System.out.println(calculateGradesSummary(courses, (prevGrade, currentGrade) -> prevGrade + currentGrade));
		
		// Should print tdt4109, tdt4100 (order does not matter) 
		System.out.println(getCoursesYouCanTake(courses, Arrays.asList(tdt4109)));
		
	}


}



...