diff --git a/ub08/code/AddSet.java b/ub08/code/AddSet.java new file mode 100755 index 0000000000000000000000000000000000000000..5462ce48026998b2cb0e8d8a9cf833b7d78c25c7 --- /dev/null +++ b/ub08/code/AddSet.java @@ -0,0 +1,43 @@ +/** + * @param <E> Element type. + * Simple functional set adding an element to another simple functional set. + */ +public class AddSet<E> extends SimpleFunctionalSet<E> { + + /** + * The element to add. + */ + private final E element; + + /** + * @param elem The element to add. + * @param s The remaining set. + */ + public AddSet(E elem, SimpleFunctionalSet<E> s) { + super(s); + this.element = elem; + } + + @Override + public boolean contains(Object o) { + if (this.element == null) { + if (o == null) { + return true; + } else { + return this.getRemainingSet().contains(o); + } + } else if (this.element.equals(o)) { + return true; + } else { + return this.getRemainingSet().contains(o); + } + } + + /** + * @return The element to add. + */ + public E getElement() { + return this.element; + } + +} diff --git a/ub08/code/EmptySet.java b/ub08/code/EmptySet.java new file mode 100755 index 0000000000000000000000000000000000000000..b9155b8e1555d09cf19dd93705c65c9efa04e92b --- /dev/null +++ b/ub08/code/EmptySet.java @@ -0,0 +1,19 @@ +/** + * @param <E> Element type. + * Simple functional set containing no element. + */ +public class EmptySet<E> extends SimpleFunctionalSet<E> { + + /** + * Creates an empty simple functional set. + */ + public EmptySet() { + super(null); + } + + @Override + public boolean contains(Object o) { + return false; + } + +} diff --git a/ub08/code/FunctionalSet.java b/ub08/code/FunctionalSet.java new file mode 100755 index 0000000000000000000000000000000000000000..c52bcaeb0531f16aed8b37fe9a122eef9289fe79 --- /dev/null +++ b/ub08/code/FunctionalSet.java @@ -0,0 +1,203 @@ +import java.util.*; + +/** + * Functional data structure for a set. + * @param <E> Element type. + */ +public class FunctionalSet<E> implements Set<E> { + + /** + * The head of the list of operations representing the set. + */ + private SimpleFunctionalSet<E> head; + + public String toString() { + String res = "{"; + Iterator<E> it = iterator(); + while (it.hasNext()) { + res = res + it.next(); + if (it.hasNext()) { + res = res + ", "; + } + } + return res + "}"; + } + + public E min(Comparator<E> comp) throws MinimumOfEmptySetException { + if (isEmpty()) { + throw new MinimumOfEmptySetException(); + } else { + E res = null; + for (E e: this) { + if (res == null || comp.compare(e, res) < 0) { + res = e; + } + } + return res; + } + } + + /** + * Creates an empty functional set. + */ + public FunctionalSet() { + this.head = new EmptySet<E>(); + } + + @Override + public boolean add(E e) { + if (this.contains(e)) { + return false; + } else { + this.head = new AddSet<E>(e, this.head); + return true; + } + } + + @Override + public boolean addAll(Collection<? extends E> c) { + boolean res = false; + for (E elem : c) { + res |= this.add(elem); + } + return res; + } + + @Override + public void clear() { + this.head = new EmptySet<E>(); + } + + @Override + public boolean contains(Object o) { + return this.head.contains(o); + } + + @Override + public boolean containsAll(Collection<?> c) { + for (Object o : c) { + if (!this.contains(o)) { + return false; + } + } + return true; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (o == null || o.getClass() != this.getClass()) { + return false; + } else { + FunctionalSet<?> set = (FunctionalSet<?>)o; + return this.containsAll(set) && set.containsAll(this); + } + } + + @Override + public int hashCode() { + int res = 5; + final int prime = 7; + for (E elem : this) { + res += prime * elem.hashCode(); + } + return res; + } + + @Override + public boolean isEmpty() { + return this.size() == 0; + } + + @Override + public Iterator<E> iterator() { + return new FunctionalSetIterator<E>(this, this.head); + } + + @Override + public boolean remove(Object o) { + if (this.contains(o)) { + this.head = new RemoveSet<E>(o, this.head); + return true; + } else { + return false; + } + } + + @Override + public boolean removeAll(Collection<?> c) { + boolean res = false; + for (Object o : c) { + res |= this.remove(o); + } + return res; + } + + @Override + public boolean retainAll(Collection<?> c) { + List<E> store = new ArrayList<E>(); + boolean change = false; + for (E elem : this) { + if (c.contains(elem)) { + store.add(elem); + } else { + change = true; + } + } + if (change) { + this.clear(); + for (E elem : store) { + this.add(elem); + } + return true; + } else { + return false; + } + } + + @Override + public int size() { + int res = 0; + for (Iterator<E> it = this.iterator(); it.hasNext(); it.next()) { + res++; + } + return res; + } + + @Override + public Object[] toArray() { + Object[] res = new Object[this.size()]; + int i = 0; + for (E elem : this) { + res[i] = elem; + i++; + } + return res; + } + + @SuppressWarnings("unchecked") + @Override + public <T>T[] toArray(T[] a) { + final int size = this.size(); + final T[] res; + if (a.length < size) { + res = Arrays.copyOf(a, size); + } else { + res = a; + } + int i = 0; + for (E elem : this) { + try { + res[i] = (T)elem; + } catch (ClassCastException e) { + throw new ArrayStoreException( + "Element " + elem + " cannot be cast to type of specified array!" + ); + } + i++; + } + return res; + } + +} diff --git a/ub08/code/FunctionalSetIterator.java b/ub08/code/FunctionalSetIterator.java new file mode 100755 index 0000000000000000000000000000000000000000..3ed6e0d1f6be3a3be1c4abb9b9c5b5c4cf89bd61 --- /dev/null +++ b/ub08/code/FunctionalSetIterator.java @@ -0,0 +1,80 @@ +import java.util.*; + +/** + * @param <E> Element type. + * Iterator through a functional set. + */ +public class FunctionalSetIterator<E> implements Iterator<E> { + + private SimpleFunctionalSet<E> current; + + private E recentElem; + + private boolean removable; + + private final FunctionalSet<E> set; + + private final Set<Object> used; + + public FunctionalSetIterator( + FunctionalSet<E> functionalSet, + SimpleFunctionalSet<E> head) + { + this.current = head; + this.recentElem = null; + this.removable = false; + this.set = functionalSet; + this.used = new FunctionalSet<Object>(); + this.forwardToNextUnusedSet(); + } + + @Override + public boolean hasNext() { + return !(this.current instanceof EmptySet); + } + + @Override + public E next() { + if (this.hasNext()) { + E elem = ((AddSet<E>) this.current).getElement(); + this.used.add(elem); + this.recentElem = elem; + this.removable = true; + this.current = this.current.getRemainingSet(); + this.forwardToNextUnusedSet(); + return elem; + } else { + throw new NoSuchElementException(); + } + } + + @Override + public void remove() { + if (this.removable) { + this.set.remove(this.recentElem); + this.removable = false; + } else { + throw new IllegalStateException( + "The next method has not been called before this remove operation!"); + } + } + + + private void forwardToNextUnusedSet() { + boolean loop = true; + while (loop) { + loop = false; + while (this.current instanceof RemoveSet) { + this.used.add(((RemoveSet<E>) this.current).getObject()); + this.current = this.current.getRemainingSet(); + } + if (this.current instanceof AddSet + && this.used.contains(((AddSet<E>) this.current).getElement())) + { + loop = true; + this.current = this.current.getRemainingSet(); + } + } + } + +} diff --git a/ub08/code/Main.java b/ub08/code/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..f1522e8011c0186d7a56d23d5efa90d299e76ff2 --- /dev/null +++ b/ub08/code/Main.java @@ -0,0 +1,34 @@ +import java.util.*; + +public class Main { + public static void main(String[] args) { + FunctionalSet<Integer> s = new FunctionalSet<>(); + String line; + do { + line = SimpleIO.getString("Enter 'add i', 'remove i', 'min', or 'exit'!"); + String[] words = line.split(" "); + try { + switch (words[0]) { + case "exit": break; + case "add": + s.add(Integer.parseInt(words[1])); + System.out.println(s); + break; + case "remove": + s.remove(Integer.parseInt(words[1])); + System.out.println(s); + break; + case "min": + System.out.println(s.min(Comparator.<Integer>naturalOrder())); + break; + default: + System.out.println("Unknown command."); + } + } catch (MinimumOfEmptySetException e) { + System.out.println("The minimum of the empty set is not defined!"); + } catch (NumberFormatException e) { + System.out.println("Failed to parse the number to add/remove."); + } + } while (!"exit".equals(line)); + } +} diff --git a/ub08/code/MinimumOfEmptySetException.java b/ub08/code/MinimumOfEmptySetException.java new file mode 100644 index 0000000000000000000000000000000000000000..6d1bce5c24ad943c6cc0b77de3177f9746157e12 --- /dev/null +++ b/ub08/code/MinimumOfEmptySetException.java @@ -0,0 +1 @@ +public class MinimumOfEmptySetException extends java.lang.RuntimeException{} diff --git a/ub08/code/RemoveSet.java b/ub08/code/RemoveSet.java new file mode 100755 index 0000000000000000000000000000000000000000..64f8fb414d81cd9eefc89ce411f4060cea3f7928 --- /dev/null +++ b/ub08/code/RemoveSet.java @@ -0,0 +1,43 @@ +/** + * @param <E> Element type. + * Simple set removing an object from another simple set. + */ +public class RemoveSet<E> extends SimpleFunctionalSet<E> { + + /** + * The object to remove. + */ + private final Object obj; + + /** + * @param o The object to remove. + * @param s The remaining set. + */ + public RemoveSet(Object o, SimpleFunctionalSet<E> s) { + super(s); + this.obj = o; + } + + @Override + public boolean contains(Object o) { + if (this.obj == null) { + if (o == null) { + return false; + } else { + return this.getRemainingSet().contains(o); + } + } else if (this.obj.equals(o)) { + return false; + } else { + return this.getRemainingSet().contains(o); + } + } + + /** + * @return The object to remove. + */ + public Object getObject() { + return this.obj; + } + +} diff --git a/ub08/code/SimpleFunctionalSet.java b/ub08/code/SimpleFunctionalSet.java new file mode 100755 index 0000000000000000000000000000000000000000..0a11a6d2c870398cc5713877b395b834ccf6f290 --- /dev/null +++ b/ub08/code/SimpleFunctionalSet.java @@ -0,0 +1,37 @@ +/** + * @param <E> Element type. + * Abstract class for simple functional sets just offering a characteristic function realized by the + * contains method. + */ +public abstract class SimpleFunctionalSet<E> { + + /** + * The remaining set. + */ + private final SimpleFunctionalSet<E> set; + + /** + * @param s The remaining set. + */ + public SimpleFunctionalSet(SimpleFunctionalSet<E> s) { + this.set = s; + } + + /** + * Returns <tt>true</tt> if this set contains the specified element. + * More formally, contains(o) returns <tt>true</tt> if and only if this set + * contains an element <tt>e</tt> such that + * <tt>(o==null ? e==null : e.equals(o))</tt>. + * @param o Element whose presence in this set is to be tested. + * @return <tt>true</tt> if this set contains the specified element. + */ + public abstract boolean contains(Object o); + + /** + * @return The remaining set. + */ + public SimpleFunctionalSet<E> getRemainingSet() { + return this.set; + } + +} diff --git a/ub08/code/SimpleIO.java b/ub08/code/SimpleIO.java new file mode 100644 index 0000000000000000000000000000000000000000..aab616cf7c226e750b8281ea0661105e7801820e --- /dev/null +++ b/ub08/code/SimpleIO.java @@ -0,0 +1,254 @@ + + +import java.awt.GraphicsEnvironment; +import java.util.Scanner; + +import javax.swing.JOptionPane; + +/** + * Class SimpleIO - class for input of simple input types + * via simple dialog box (or if headless System.in use) + * and output of strings (vie dialog box or System.out) + */ + +public class SimpleIO +{ + //Running without display support? + private static final boolean HEADLESS = GraphicsEnvironment.isHeadless(); + + /** + * Prompting the user for input (If Headless, will be prompted with System.in and System.out) + * @param title Title of the input + * @param messages Message that will be shown to the user + * @param options Optional: Give the user options + * @param initialOption Optional: The initial option + * @return The input string or the index of the selected option + */ + private static String getInputString(String title, Object messages[], + Object[] options, Object initialOption){ + return HEADLESS ? headlessImpl(title, messages, options, initialOption) : + displayImpl(title, messages, options, initialOption); + } + + /** + * Prompting the user for input (If Headless, will be prompted with System.in and System.out) + * @param title Title of the input + * @param messages Message that will shown + * @return The inputstring + */ + private static String getInputString(String title, Object messages[]){ + return getInputString(title, messages, null, null); + } + + private static String headlessImpl(String title, Object messages[], + Object[] options, Object initialOption){ + @SuppressWarnings("resource")//System.in should not be closed + Scanner scanner = new Scanner(System.in); + + System.out.println(title); + + for(Object o : messages) + System.out.println(o.toString()); + + if(options != null){ + System.out.print("Choose one: |"); + + for(Object option : options){ + if(option == initialOption){ + System.out.print(" " + option.toString() + " (INITIAL) |"); + } + else{ + System.out.print(" " + option.toString() + " |"); + } + } + + System.out.println(""); + } + + String result = scanner.nextLine(); + + if(options != null){ + for(int i = 0; i < options.length; i++){ + if(options[i].toString().equals(result)) + return i + ""; + } + + return null; + } + + + return result; + } + + /** + * Prompting the user with a gui + * @param title The title from the frame + * @param messages The message the user will be shown + * @param options Optional: Give the user options + * @param initialOption Optional: The initial option + * @return The inputstring or the index of the option if given + */ + private static String displayImpl(String title, Object messages[], + Object[] options, Object initialOption){ + if(options == null){ + return JOptionPane.showInputDialog(null, messages, title, JOptionPane.QUESTION_MESSAGE); + } + else{ + return "" + JOptionPane.showOptionDialog(null, messages, title, + JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, + null, options, initialOption); + } + } + + /** + * Getting information from the user and returning it + * @param type The type of information + * @param prompt The question prompted to the user + * @return the information as Object (It can safely casted to the given type) + */ + private static Object getInputLine(Type type, String prompt){ + Object result = null; + Object[] commentArray = {prompt, "", ""}; + + while(result == null){ + String response; + + if(type == Type.Boolean){ + response = getInputString(type.getDescription() + " eingeben", commentArray, + new String[]{"True", "False"}, "True"); + } + else{ + response = getInputString(type.getDescription() + " eingeben", commentArray); + } + + + if(response != null){ + try{ + switch (type) { + case String:{ + result = response; + break; + } + case Boolean:{ + result = response.equals("0"); + break; + } + case Int:{ + result = Integer.parseInt(response); + break; + } + case Char:{ + if(response.length() == 1){ + result = response.charAt(0); + } + + break; + } + case Float:{ + result = Float.parseFloat(response); + break; + } + case Double:{ + result = Double.parseDouble(response); + break; + } + default: + throw new IllegalStateException("Type incorrect"); + } + } + catch(NumberFormatException exception){ + result = null; + } + } + + if(result == null){ + commentArray[1] = "Invalid input: " + response; + commentArray[2] = "Enter a valid " + type.getDescription(); + } + } + + return result; + } + + /** + ** String input from the user via a simple dialog. + ** @param prompt the message string to be displayed inside dialog + ** @return String input from the user. + **/ + public static String getString(String prompt){ + return (String) getInputLine(Type.String, prompt); + } + + /** + ** char input from the user via a simple dialog. + ** @param prompt the message string to be displayed inside dialog + ** @return char input from the user. + **/ + public static char getChar(String prompt){ + return (char) getInputLine(Type.Char, prompt); + } + + /** + ** boolean selection from the user via a simple dialog. + ** @param prompt message to appear in dialog + ** @return boolean selection from the user + **/ + public static boolean getBoolean(String prompt){ + return (boolean) getInputLine(Type.Boolean, prompt); + } + + + /** + ** returns integer input from the user via a simple dialog. + ** @param prompt the message string to be displayed inside dialog + ** @return the input integer + **/ + public static int getInt(String prompt){ + return (int) getInputLine(Type.Int, prompt); + } + + + /** + ** returns a float input from the user via a simple dialog. + ** @param prompt the message string to be displayed inside dialog + ** @return the input float + **/ + public static float getFloat(String prompt){ + return (float) getInputLine(Type.Float, prompt); + } + + /** + ** returns a double input from the user via a simple dialog. + ** @param prompt the message string to be displayed inside dialog + ** @return the input double + **/ + public static double getDouble(String prompt){ + return (double) getInputLine(Type.Double, prompt); + } + + /** + * Defines the type from the user-question + */ + private enum Type{ + String("String"), Char("Char"), Int("int"), + Boolean("Boolean"), Float("Float"), Double("Double"); + + private String description; + + private Type(String input){ + this.description = input; + } + + public String getDescription(){ + return description; + } + } + + /** prints the string "content" in a window with the title "title" + ** @param content the string to be displayed + ** @param title the title of the display window + **/ + public static void output (String content, String title) { + JOptionPane.showMessageDialog (null,content,title,JOptionPane.PLAIN_MESSAGE); + } +}