// Unique.java -- Filtruje słowa przy użyciu wielu metod
// Metoda (list, vector, stack, hashtable) argument to argument programu.

import java.io.*;
import java.util.*;

// Abstrakcyjna klasa bazowa
interface Filter {
  public void put(String word);  // Wyświetlenie pierwszego wystąpienia słowa
}

// Implementacja Filter przy użyciu powiązanej listy do przechowywania powtarzających się słów
class ListFilter implements Filter {
  private ListNode list=null;  // Początek powiązanej listy

  public void put(String word) {
    // Odnalezienie słowa na liście
    ListNode p;
    for (p=list; p!=null; p=p.next)
      if (p.word.equals(word))
        break;

    // Jeśli nie odnaleziono słowa, należy je wyświetlić i dodać do listy
    if (p==null) {
      System.out.println(word);
      p=new ListNode(word);
      p.next=list;
      list=p;
    }
  }
}
 
// Węzeł powiązanej listy używany w in ListFilter
class ListNode {
  String word;
  ListNode next;  // Odwołanie do kolejnego węzła
  ListNode(String word) {  // Konstruktor
    this.word=word;
  }
}

// VectorFilter wykorzystuje Vector do przechowywania powtarzających się słów
class VectorFilter implements Filter {
  private Vector v=new Vector();
  public void put(String word) {
    int i;
    for (i=0; i<v.size(); ++i)
      if (v.elementAt(i).equals(word))
        break;
    if (i==v.size()) { // Nie odnaleziono
      System.out.println(word);
      v.addElement(word);
    }
  }
}

// StackFilter przechowuje słowa na stosie
class StackFilter implements Filter {
  private Stack s=new Stack();
  public void put(String word) {
    if (!s.contains(word)) {
      System.out.println(word);
      s.push(word);
    }
  }
}
 
// HashtableFilter przechowuje słowa w tablicy w postaci mapy: słowo -> liczba
class HashtableFilter implements Filter {
  private Dictionary h=new Hashtable();
  public void put(String word) {
    Object value=h.get(word);
    if (value==null) {
      System.out.println(word);
      h.put(word, new Integer(1));
    }
    else
      h.put(word, new Integer(1+((Integer)value).intValue()));
  }

  // Lista wystąpień poszczególnych słów
  public void listWords() {
    Enumeration e=h.keys();
    while (e.hasMoreElements()) {
      Object key=e.nextElement();
      System.out.println(key+" "+h.get(key));
    }
  }
}
 
public class Unique {
  public static void main(String[] argv) throws IOException {

    // Utworzenie odpowiedniego filtra
    Filter filter=null;  // Interfejs bazowy
    if (argv[0].equals("list"))
      filter=new ListFilter();  // Implementacja filtra
    else if (argv[0].equals("vector"))
      filter=new VectorFilter();
    else if (argv[0].equals("stack"))
      filter=new StackFilter();
    else if (argv[0].equals("hashtable"))
      filter=new HashtableFilter();

    // Analiza i filtrowanie słów
    String word="";
    while (true) {
      int c=System.in.read();
      if (c<0)
        break;
      if (Character.isLetter((char)c))
        word=word+(char)c;
      else if (!word.equals("")) {
        filter.put(word);
        word="";
      }
    }
  }
}

