Commit 9ca48b27 authored by Jostein Hjortland Tysse's avatar Jostein Hjortland Tysse
Browse files

Add øving 5 LF

parent 40c85dc8
package oving5;
import java.util.Iterator;
import java.util.function.BinaryOperator;
public class BinaryComputingIterator implements Iterator<Double> {
private final Iterator<Double> iterator1, iterator2;
private final Double default1, default2;
private final BinaryOperator<Double> operator;
public BinaryComputingIterator(Iterator<Double> iterator1, Iterator<Double> iterator2, Double default1,
Double default2, BinaryOperator<Double> operator) {
this.iterator1 = iterator1;
this.iterator2 = iterator2;
this.default1 = default1;
this.default2 = default2;
this.operator = operator;
}
public BinaryComputingIterator(Iterator<Double> iterator1, Iterator<Double> iterator2,
final BinaryOperator<Double> operator) {
this(iterator1, iterator2, null, null, operator);
}
@Override
public boolean hasNext() {
return this.hasNext1() && this.hasNext2();
}
@Override
public Double next() {
return operator.apply(this.next1(), this.next2());
}
@Override
public void remove() {
throw new UnsupportedOperationException("Remove is not supported");
}
// Hjelpemetoder
private boolean hasNext1() {
return this.iterator1.hasNext() || this.default1 != null;
}
private boolean hasNext2() {
return this.iterator2.hasNext() || this.default2 != null;
}
private double next1() {
if (!this.hasNext1()) {
throw new IllegalStateException("Iterator 1 has no next element!");
}
return this.iterator1.hasNext() ? this.iterator1.next() : this.default1;
}
private double next2() {
if (!this.hasNext2()) {
throw new IllegalStateException("Iterator 2 has no next element!");
}
return this.iterator2.hasNext() ? this.iterator2.next() : this.default2;
}
}
package oving5;
public class Card implements Comparable<Card> {
// the suit (farge), one of the values 'S' (spades), 'H' (hearts), 'D'
// (diamonds) and 'C' (clubs)
private char suit;
// the value, 1 for the ace, 2 - 10, 11 (knight), 12 (queen) and 13 (king). -1
// is invalid
private int face = -1;
// the set of suits in decreasing order
public final static String SUITS = "SHDC";
public Card(char suit, int face) {
if (SUITS.indexOf(suit) < 0) {
throw new IllegalArgumentException("Illegal suit: " + suit);
}
if (face < 1 || face > 13) {
throw new IllegalArgumentException("Illegal face: " + face);
}
this.suit = suit;
this.face = face;
}
/*
* Returns suit and face as a string
* E.g. Ace of spades is S1 and king of clubs is C13
*/
public String toString() {
return String.valueOf(suit) + face;
}
public char getSuit() {
return this.suit;
}
public int getFace() {
return this.face;
}
// from Comparable<Card>
@Override
public int compareTo(Card card) {
// Index of other card's suit will be higher than this card's suit if the other
// card should come before this one
int diff = SUITS.indexOf(card.suit) - SUITS.indexOf(suit);
if (diff == 0) {
// If this card should come first, the other will have a higher value
diff = face - card.face;
}
return diff;
}
}
package oving5;
import java.util.Comparator;
public class CardComparator implements Comparator<Card> {
private final String suitOrder;
private final boolean aceIsHighest;
public CardComparator(boolean aceIsHighest, char trumph) {
this(aceIsHighest, trumph, "CDHS");
}
public CardComparator(boolean aceIsHighest, String suitOrder) {
this(aceIsHighest, ' ', suitOrder);
}
// suitOrder is part of the voluntary extra task
public CardComparator(boolean aceIsHighest, char trumph, String suitOrder) {
this.aceIsHighest = aceIsHighest;
if (trumph != ' ') {
// Make sure the trumph is last, so that it is considered "best". This means
// we don't need to store the trumph anywhere
this.suitOrder = suitOrder.replace(String.valueOf(trumph), "") + trumph;
} else {
this.suitOrder = suitOrder;
}
}
private int getFace(Card card) {
if (card.getFace() == 1 && this.aceIsHighest) {
return 14;
}
return 1;
}
@Override
public int compare(Card card1, Card card2) {
int suit1 = this.suitOrder.indexOf(card1.getSuit());
int suit2 = this.suitOrder.indexOf(card2.getSuit());
int diff = suit1 - suit2;
// The suits are the same
if (diff == 0) {
int face1 = this.getFace(card1);
int face2 = this.getFace(card2);
diff = face1 - face2;
}
return diff;
}
}
package oving5;
import java.util.Iterator;
public interface CardContainer extends Iterable<Card> {
/*
* @returns the number of cards within this CardContainer
*/
public int getCardCount();
/*
* Get a card at the given index
*
* @param i The index
*
* @throws IllegalArgumentException when the index i is out of bounds
*
* @returns the card at the provided index, starting at 0
*/
public Card getCard(int i) throws IllegalArgumentException;
// Not part of the assignment to add this. This allows us to iterate over
// any card container without explicitly calling new CardContainerIterator.
@Override
default Iterator<Card> iterator() {
return new CardContainerIterator(this);
}
}
package oving5;
import java.util.Iterator;
public class CardContainerIterator implements Iterator<Card> {
private CardContainer container;
private int pos;
public CardContainerIterator(CardContainer container) {
this.container = container;
this.pos = 0;
}
@Override
public boolean hasNext() {
return this.pos < this.container.getCardCount();
}
@Override
public Card next() {
// Longer version:
Card card = this.container.getCard(this.pos);
this.pos += 1;
return card;
// Short version, using that "this.pos++" returns the value before incrementing by
// 1. "++this.pos" will return the value after incrementing.
// return container.getCard(this.pos++);
}
@Override
public void remove() {
throw new UnsupportedOperationException("CardContainerIterator does not not support remove");
}
}
package oving5;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class CardDeck implements CardContainer {
// array to hold Card objects, filled in the constructor
private ArrayList<Card> cards;
public CardDeck(int suitSize) {
cards = new ArrayList<Card>();
for (int i = 0; i < Card.SUITS.length(); i++) {
for (int face = 1; face <= suitSize; face++) {
Card card = new Card(Card.SUITS.charAt(i), face);
cards.add(card);
}
}
}
@Override
public String toString() {
return "[Deck " + cards.toString().substring(1);
}
public void deal(CardHand hand, int handSize) {
for (int i = 0; i < handSize; i++) {
hand.addCard(cards.remove(cards.size() - 1));
}
}
public int getCardCount() {
return cards.size();
}
public Card getCard(int i) {
if (i < 0 || i >= getCardCount()) {
throw new IllegalArgumentException(
String.format("%s is an illegal card index, when the size of the deck is %s", i, getCardCount()));
}
return cards.get(i);
}
public void shufflePerfectly() {
int halfSize = cards.size() / 2;
for (int i = 0; i < halfSize; i++) {
Card card = cards.remove(halfSize + i);
cards.add(i * 2 + 1, card);
}
}
// methods using Predicate<Card>
public boolean hasCard(Predicate<Card> predicate) {
// Streams solution:
// return this.cards.stream().anyMatch(predicate);
// Manual solution
for (Card card : cards) {
if (predicate.test(card)) {
// Avoid looping through the rest if we have found a match
return true;
}
}
return false;
}
public int getCardCount(Predicate<Card> predicate) {
// Streams solution:
// return (int) this.cards.stream().filter(predicate).count();
// Manual solution
int count = 0;
for (Card card : cards) {
if (predicate.test(card)) {
count++;
}
}
return count;
}
public List<Card> getCards(Predicate<Card> predicate) {
// Streams solution:
// return this.cards.stream().filter(predicate).collect(Collectors.toList());
// Manual solution
List<Card> matchingCards = new ArrayList<Card>();
for (Card card : cards) {
if (predicate.test(card)) {
matchingCards.add(card);
}
}
return matchingCards;
}
}
package oving5;
import java.util.ArrayList;
import java.util.Iterator;
public class CardHand implements CardContainer {
// array to hold Card objects, filled in the constructor
private ArrayList<Card> cards;
public CardHand() {
cards = new ArrayList<Card>();
}
@Override
public String toString() {
return "[Hand " + cards.toString().substring(1);
}
public void addCard(Card card) {
this.cards.add(card);
}
public int getCardCount() {
return cards.size();
}
public Card getCard(int i) {
if (i < 0 || i >= getCardCount()) {
throw new IllegalArgumentException(
String.format("%s is an illegal card index, when the size of the hand is %s", i, getCardCount()));
}
return cards.get(i);
}
public Card play(int i) {
return cards.remove(i);
}
// Iterable<Card> in CardContainer<Card>
@Override
public Iterator<Card> iterator() {
return cards.iterator();
}
}
package oving5;
public interface Named {
public String getGivenName();
public void setGivenName(String name);
public String getFamilyName();
public void setFamilyName(String name);
public String getFullName();
public void setFullName(String name);
}
package oving5;
import java.util.Comparator;
public class NamedComparator implements Comparator<Named> {
@Override
public int compare(Named named1, Named named2) {
int diff = named1.getFamilyName().compareTo(named2.getFamilyName());
if (diff == 0) {
diff = named1.getGivenName().compareTo(named2.getGivenName());
}
return diff;
}
}
package oving5;
public class Person1 implements Named {
private String givenName;
private String familyName;
public Person1(String givenName, String familyName) {
this.givenName = givenName;
this.familyName = familyName;
}
public String getGivenName() {
return this.givenName;
}
public void setGivenName(String givenName) {
this.givenName = givenName;
}
public String getFamilyName() {
return this.familyName;
}
public void setFamilyName(String familyName) {
this.familyName = familyName;
}
public String getFullName() {
return this.givenName + " " + this.familyName;
}
public void setFullName(String fullName) {
int pos = fullName.indexOf(' ');
this.givenName = fullName.substring(0, pos);
this.familyName = fullName.substring(pos + 1);
}
}
package oving5;
public class Person2 implements Named {
private String fullName;
public Person2(String fullName) {
this.fullName = fullName;
}
public String getFullName() {
return this.fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getGivenName() {
// Alternativt:
// return this.fullName.split(" ")[0]
return this.fullName.substring(0, this.fullName.indexOf(' '));
}
public void setGivenName(String givenName) {
this.fullName = givenName + " " + getFamilyName();
}
public String getFamilyName() {
// Alternativt:
// return this.fullName.split(" ")[1]
return this.fullName.substring(this.fullName.indexOf(' ') + 1);
}
public void setFamilyName(String familyName) {
this.fullName = getGivenName() + " " + familyName;
}
}
package oving5;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.function.BinaryOperator;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
public class RPNCalc {
private Stack<Double> operandStack;
private Map<Character, BinaryOperator<Double>> operators;
// Extra task fields
private Map<Character, BinaryOperator<Double>> binaryOperators;
private Map<Character, UnaryOperator<Double>> unaryOperators;
private Map<Character, Supplier<Double>> suppliers;
public RPNCalc() {
operandStack = new Stack<Double>();
operators = new HashMap<>();
binaryOperators = new HashMap<>();
unaryOperators = new HashMap<>();
suppliers = new HashMap<>();
}
@Override
public String toString() {
return operandStack.toString();
}
public void push(double value) {
operandStack.push(value);
}
public int getSize() {
return operandStack.size();
}
public double peek(int n) {
return peek(n, Double.NaN);
}
public double peek(int n, double def) {
if (n < 0 || operandStack.size() <= n) {
return def;
}
return operandStack.get(operandStack.size() - n - 1);
}
// Method used in earlier versions. Currently not a part of the assignment.
public double pop(double def) {
if (operandStack.isEmpty()) {
return def;
}
return operandStack.pop();
}
public double pop() {
return pop(Double.NaN);
}
// perform the operation denoted by op
// each operation pops and pushes values off and onto the operand stack,
public void performOperation(char op) {
if (operators.containsKey(op)) {
double d2 = pop();
double d1 = pop();
push(operators.get(op).apply(d1, d2));
} else {
throw new UnsupportedOperationException("The given operation has not been added.");
}
}
public boolean addOperator(char op, BinaryOperator<Double> operator) {
if (operators.containsKey(op))
return false;
operators.put(op, operator);
return true;
}
public void removeOperator(char op) {
operators.remove(op);
}
/*
* EXTRA TASK
*
* Below, two implementations of the extra tasks are shown. To separate the
* methods with equal names, Version 1 has a suffix of 1 to method names, and
* version 2 has a 2.
*
* VERSION 1
* This version only allows an operator to be added as one of binary, unary or