/**
* ACSL RUMMY
* AMERICAN COMPUTER SCIENCE LEAGUE - CONTEST 4
*
* ROBERT BADEA
* APRIL 15, 2013
*
*/
import
java.util.*;
public class
RummyPlayer {
LinkedList<LinkedList<Card>>
runsCopy;
LinkedList<TreeSet<Card>>
setsCopy;
LinkedList<LinkedList<Card>>
runs;
LinkedList<TreeSet<Card>> sets;
// create a new rummy player
@SuppressWarnings("unchecked")
public RummyPlayer(Card[] cards) {
runs = new
LinkedList<LinkedList<Card>>();
sets = new
LinkedList<TreeSet<Card>>();
for (Card card : cards) {
//for (int i = 0; i < cards.length;
++i) {
boolean addedInRuns = false;
for (LinkedList<Card> run :
runs) {
if (card.linksForRunBefore(run.getFirst())){
run.addFirst(card);
addedInRuns = true;
}
else if
(card.linksForRunAfter(run.getLast())) {
run.addLast(card);
addedInRuns = true;
}
}
if (!addedInRuns) {
LinkedList<Card> newRun =
new LinkedList<Card>();
newRun.addLast(card);
runs.add(newRun);
}
boolean addedInSets = false;
for (TreeSet<Card> set :
sets) {
if
(card.linksForSet(set.first())) {
set.add(card);
addedInSets = true;
}
}
if (!addedInSets) {
TreeSet<Card> newSet =
new TreeSet<Card>();
newSet.add(card);
sets.add(newSet);
}
}
runsCopy = new
LinkedList<LinkedList<Card>>();
setsCopy = new LinkedList<TreeSet<Card>>();
for (LinkedList<Card> run : runs)
{
runsCopy.addLast((LinkedList)run.clone());
}
for (TreeSet<Card> set : sets) {
setsCopy.addLast((TreeSet)set.clone());
}
}
@SuppressWarnings("unchecked")
public void reset() {
runs.clear();
sets.clear();
for (LinkedList<Card> run :
runsCopy) {
Object clone = run.clone();
if (clone instanceof LinkedList)
runs.addLast((LinkedList)clone);
}
for (TreeSet<Card> set :
setsCopy) {
sets.addLast((TreeSet)set.clone());
}
}
// class for a playing card
public static class Card implements
Comparable<Card> {
private int rank;
private int suit;
public Card(String c) {
c = c.replaceAll("(,)?",
"");
if (c == null) throw new NullPointerException();
if (c.length() != 2) throw new IllegalArgumentException();
char rank = c.charAt(0);
char suit = c.charAt(1);
// Yes, switching this is ugly, but
it is also straightforward
switch (rank) {
case 'A': this.rank = 1;
break;
case '2': this.rank = 2;
break;
case '3': this.rank = 3;
break;
case '4': this.rank = 4;
break;
case '5':
this.rank = 5;
break;
case '6': this.rank = 6;
break;
case '7': this.rank = 7;
break;
case '8': this.rank = 8;
break;
case '9': this.rank = 9;
break;
case 'T': this.rank = 10;
break;
case 'J': this.rank = 12;
break;
case 'Q': this.rank = 13;
break;
case 'K': this.rank = 14;
break;
default: throw new IllegalArgumentException();
}
switch (suit) {
case 'S':
this.suit = 4;
break;
case 'H': this.suit = 3;
break;
case 'C': this.suit = 2;
break;
case 'D': this.suit = 1;
break;
default: throw
new IllegalArgumentException();
}
}
public String toString() {
String result = "";
// Yes, switching this is ugly too,
I know
switch (rank) {
case 1: result = result + "A";
break;
case 2: result = result + "2";
break;
case 3: result = result + "3";
break;
case 4: result = result + "4";
break;
case 5: result = result + "5";
break;
case 6: result = result + "6";
break;
case 7: result = result + "7";
break;
case 8: result = result + "8";
break;
case 9: result = result + "9";
break;
case 10: result = result + "T";
break;
case 12: result = result + "J";
break;
case 13: result = result + "Q";
break;
case 14: result = result + "K";
break;
default: throw new IllegalStateException();
}
switch (suit) {
case 4: result = result + "S";
break;
case 3: result = result + "H";
break;
case 2: result = result + "C";
break;
case 1: result = result + "D";
break;
default: throw
new IllegalStateException();
}
return result;
}
// test if that card could be before or
after this card in a set/run
public boolean linksForRunBefore(Card
that) {
return (this.rank - that.rank ==
-1) && (this.suit == that.suit);
}
public boolean linksForRunAfter(Card
that) {
return (this.rank - that.rank ==
+1) && (this.suit == that.suit);
}
public boolean linksForSet(Card that) {
return (this.rank == that.rank)
&& (this.suit != that.suit);
}
public int compareTo(Card that) {
if (that == null) return -1;
int rankDiff = this.rank -
that.rank;
if (rankDiff != 0) return rankDiff;
return (this.suit - that.suit);
}
}
// deletes the most useless card in the
hand
private void deleteMostUseless() {
Card min = null;
LinkedList<Card>
runFromWhichMinIs = null;
for (LinkedList<Card> run : runs)
{
if (run.size() < 3) {
Card first = run.getFirst();
if (first.compareTo(min) <
0) {
min = first;
runFromWhichMinIs = run;
}
}
}
if (runFromWhichMinIs == null)
throw new IllegalStateException();
runFromWhichMinIs.remove(min);
if (runFromWhichMinIs.isEmpty())
runs.remove(runFromWhichMinIs);
for (TreeSet<Card> set : sets) {
if (set.remove(min))
if (set.isEmpty()) {
sets.remove(set);
break;
}
}
}
public void addCard(Card card) {
for (LinkedList<Card> run : runs)
{
int runSize = run.size();
if (runSize > 1 &&
runSize < 4) {
if
(card.linksForRunBefore(run.getFirst())){
run.addFirst(card);
deleteMostUseless();
break;
}
else if
(card.linksForRunAfter(run.getLast())) {
run.addLast(card);
deleteMostUseless();
break;
}
}
}
for (TreeSet<Card> set : sets) {
int setSize = set.size();
if (setSize > 1 &&
setSize < 4) {
if
(card.linksForSet(set.first())) {
set.add(card);
deleteMostUseless();
break;
}
}
}
}
public String toString() {
boolean[][] used = new boolean[4][14];
StringBuilder sb = new StringBuilder();
int appended = 0;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 14; ++j)
used[i][j] = false;
for (LinkedList<Card> run : runs)
{
if (run.size() > 2)
for (Card card : run) {
if (!used[card.suit -
1][card.rank]) {
sb.append(card.toString());
appended++;
if (appended < 7)
sb.append("
");
used[card.suit -
1][card.rank] = true;
}
}
}
for (TreeSet<Card> set : sets) {
if (set.size() > 2)
for (Iterator<Card> it =
set.descendingIterator(); it.hasNext();) {
Card card = it.next();
if (!used[card.suit -
1][card.rank]) {
sb.append(card.toString());
appended++;
if (appended < 7)
sb.append("
");
used[card.suit -
1][card.rank] = true;
}
}
}
TreeSet<Card> rest = new
TreeSet<Card>();
for (LinkedList<Card> run : runs)
{
for (Card card : run) {
if (!used[card.suit -
1][card.rank]) {
rest.add(card);
}
}
}
for (Iterator<Card> it =
rest.descendingIterator(); it.hasNext();) {
Card card = it.next();
sb.append(card.toString());
appended++;
if (appended < 7)
sb.append(" ");
}
return sb.toString();
}
public static void main(String[] args) {
Card[] cards = new Card[7];
Scanner scanner = new
Scanner(System.in);
System.out.println("Please enter
the 7 two-character strings representing\nthe cards in a player's hand,
separated by single spaces:");
for (int i = 0; i < 7; ++i) {
cards[i] = new
Card(scanner.next());
}
RummyPlayer player = new
RummyPlayer(cards);
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
player.addCard(new
Card(scanner.next()));
}
System.out.println(player.toString());
player.reset();
}
}
}