Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -----------------------------------------------------------------
- public class HandSort {
- private static final int RANDOM_HAND_SIZE = 13;
- public static void main(String[] args) {
- new Hand(RANDOM_HAND_SIZE).sort();
- }
- }
- -----------------------------------------------------------------
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- public class Hand implements Iterable<Card> {
- private List<ArrayList<Card>> cards;
- private int numSuits;
- private List<Hand> pastMoves = new ArrayList<>();
- private int printFrom;
- private int printLength;
- private int printTo;
- public Hand(int numCards) {
- List<Card> deck = new ArrayList<>();
- for (Suit suit : Suit.values()) {
- for (int rank = Card.MAX_RANK; rank >= Card.MIN_RANK; rank--) {
- deck.add(new Card(rank, suit));
- }
- }
- Collections.shuffle(deck);
- buildFromDeck(deck, numCards);
- }
- public Hand(List<Card> deck, int numCards) {
- buildFromDeck(deck, numCards);
- }
- private Hand(List<ArrayList<Card>> cards) {
- this.cards = cards;
- }
- public void buildFromDeck(List<Card> deck, int numCards) {
- cards = new ArrayList<>();
- List<Card> sortCards = new ArrayList<>(numCards);
- Set<Integer> suitsSeen = new HashSet<>();
- for (int i = 0; i < numCards; i++) {
- Card card = deck.get(i);
- ArrayList<Card> cardContainer = new ArrayList<>(4);
- cardContainer.add(card);
- cards.add(cardContainer);
- sortCards.add(card);
- suitsSeen.add(card.getSuitRank());
- }
- numSuits = suitsSeen.size();
- Collections.sort(sortCards);
- for (int i = 0; i < numCards - 1; i++) {
- Card currentCard = sortCards.get(i);
- Card nextCard = sortCards.get(i + 1);
- if (nextCard.hasSameSuit(currentCard)) {
- currentCard.setRightAdj(nextCard);
- }
- }
- mergeGroups();
- }
- public int getNumContainers() {
- return cards.size();
- }
- public int getNumPastMoves() {
- return pastMoves.size();
- }
- public int getNumSuits() {
- return numSuits;
- }
- public boolean isSorted() {
- int numSuitsSeen = 1;
- Card previousCard = null;
- boolean sameColorTouching = false;
- boolean[] suitsSeen = new boolean[Card.NUM_SUITS];
- suitsSeen[getFirstCardAt(0).getSuitRank()] = true;
- for (Card card : this) {
- int currentSuitRank = card.getSuitRank();
- if (previousCard != null) {
- if (!card.hasSameSuit(previousCard)) {
- numSuitsSeen++;
- if (suitsSeen[currentSuitRank]) {
- return false;
- }
- if (!card.hasDifferentColor(previousCard)) {
- sameColorTouching = true;
- }
- // if there are more than 2 suits, they must alternate colors
- if (sameColorTouching && numSuitsSeen > 2) {
- return false;
- }
- suitsSeen[currentSuitRank] = true;
- previousCard = null;
- } else {
- if (card.getRank() > previousCard.getRank()) {
- return false;
- }
- }
- }
- previousCard = card;
- }
- return true;
- }
- public Iterator<Card> iterator() {
- return new HandIterator();
- }
- public Hand moveCardContainers(int from, int length, int to) {
- List<ArrayList<Card>> cardCopy = copyCards();
- List<ArrayList<Card>> removed = new ArrayList<>(length);
- for (int i = 0; i < length; i++) {
- removed.add(cardCopy.remove(from));
- }
- cardCopy.addAll(to, removed);
- return new Hand(cardCopy);
- }
- public List<Hand> nextMoves(int minContainers) {
- if (cards.size() > minContainers) {
- return new ArrayList<>();
- }
- List<Hand> nextMoves = new ArrayList<>();
- boolean[] sameSuitMoves = new boolean[Card.NUM_SUITS];
- for (int from = 0; from < cards.size() - 1; from++) {
- int currentSuit = getFirstCardAt(from).getSuitRank();
- for (int length = 1; length + from < cards.size(); length++) {
- if (getFirstCardAt(from + length - 1).getSuitRank() != currentSuit) {
- currentSuit = -1;
- }
- boolean unsortingViolation = false;
- for (int to = from + 1; to + length - 1 < cards.size(); to++) {
- Card firstTo = getFirstCardAt(to + length - 1);
- for (int i = from; i < from + length; i++) {
- Card firstFrom = getFirstCardAt(i);
- if (firstFrom.getSuitRank() == firstTo.getSuitRank()
- && firstFrom.getRank() > firstTo.getRank()) {
- unsortingViolation = true;
- break;
- }
- }
- if (unsortingViolation) {
- break;
- }
- Hand hand = createNextHand(from, length, to);
- if (minContainers > hand.cards.size()) {
- nextMoves = new ArrayList<>();
- sameSuitMoves = new boolean[Card.NUM_SUITS];
- minContainers = hand.cards.size();
- }
- if (currentSuit != -1 && (from == 0 || getFirstCardAt(from - 1).getSuitRank() == currentSuit)
- && (to + length == cards.size() || getFirstCardAt(to + length).getSuitRank() == currentSuit)) {
- // same suit move
- if (sameSuitMoves[currentSuit]) {
- break;
- } else {
- sameSuitMoves[currentSuit] = true;
- }
- }
- if (minContainers == hand.cards.size()) {
- nextMoves.add(hand);
- }
- }
- }
- }
- return nextMoves;
- }
- public void pastMovePrint() {
- for (Hand hand : pastMoves) {
- if (hand.printLength == 1) {
- System.out.println("move group " + (hand.printFrom + 1) + " after group "
- + (hand.printLength + hand.printTo));
- } else {
- System.out.println("move groups " + (hand.printFrom + 1) + " to "
- + (hand.printFrom + hand.printLength) + " after group "
- + (hand.printLength + hand.printTo));
- }
- System.out.println(hand);
- };
- }
- public void sort() {
- List<Hand> bfsList = new ArrayList<>();
- bfsList.add(this);
- int previousLevel = -1;
- int minContainers = Integer.MAX_VALUE;
- while (!bfsList.isEmpty()) {
- Hand currentHand = bfsList.remove(0);
- if (currentHand.getNumPastMoves() != previousLevel) {
- previousLevel = currentHand.getNumPastMoves();
- System.out.println("level " + previousLevel + ", bfs queue size " + bfsList.size());
- System.out.println(currentHand);
- }
- if (currentHand.isSorted()) {
- System.out.println("\noriginal hand");
- System.out.println(this);
- currentHand.pastMovePrint();
- System.out.println("sorted in " + currentHand.getNumPastMoves() + " moves");
- System.out.println("level " + previousLevel + ", bfs queue size " + bfsList.size());
- break;
- }
- if (currentHand.getNumContainers() < minContainers) {
- minContainers = currentHand.getNumContainers();
- }
- bfsList.addAll(currentHand.nextMoves(minContainers));
- }
- }
- public String toString() {
- StringBuilder sb = new StringBuilder();
- for (List<Card> cardGroup : cards) {
- for (Card card : cardGroup) {
- sb.append(card.suitToShortString());
- }
- sb.append(' ');
- }
- sb.append('\n');
- for (List<Card> cardGroup : cards) {
- for (Card card : cardGroup) {
- sb.append(card.rankToShortString());
- }
- sb.append(' ');
- }
- return sb.toString();
- }
- private Hand createNextHand(int from, int length, int to) {
- Hand hand = moveCardContainers(from, length, to);
- hand.mergeGroups();
- hand.pastMoves.addAll(this.pastMoves);
- hand.pastMoves.add(hand);
- hand.printFrom = from;
- hand.printLength = length;
- hand.printTo = to;
- return hand;
- }
- @SuppressWarnings("unchecked")
- private List<ArrayList<Card>> copyCards() {
- List<ArrayList<Card>> copy = new ArrayList<>(cards.size());
- for (ArrayList<Card> cardContainer : cards) {
- copy.add((ArrayList<Card>) cardContainer.clone());
- }
- return copy;
- }
- private Card getFirstCard(List<Card> cardContainer) {
- return cardContainer.get(0);
- }
- private Card getFirstCardAt(int index) {
- return cards.get(index).get(0);
- }
- private Card getLastCard(List<Card> cardContainer) {
- return cardContainer.get(cardContainer.size() - 1);
- }
- private void mergeGroups() {
- for (int i = 0; i < cards.size() - 1; i++) {
- List<Card> cardGroup = cards.get(i);
- List<Card> nextCardGroup = cards.get(i + 1);
- if (getLastCard(cardGroup).getRightAdj() == getFirstCard(nextCardGroup)) {
- cardGroup.addAll(nextCardGroup);
- cards.remove(i + 1);
- i--;
- }
- }
- }
- private class HandIterator implements Iterator<Card> {
- private Iterator<Card> inner;
- private Iterator<ArrayList<Card>> outer = cards.iterator();
- private HandIterator() {
- inner = outer.next().iterator();
- }
- @Override
- public boolean hasNext() {
- return inner.hasNext();
- }
- @Override
- public Card next() {
- Card next = inner.next();
- if (!inner.hasNext() && outer.hasNext()) {
- inner = outer.next().iterator();
- }
- return next;
- }
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
- }
- -----------------------------------------------------------------
- public class Card implements Comparable<Card> {
- public static final int MIN_RANK = 2;
- public static final int MAX_RANK = 14;
- public static final int NUM_SUITS = 4;
- private int rank; // 2 through 14
- private Card rightAdj;
- private Suit suit;
- public Card(int rank, Suit suit) {
- if (rank < MIN_RANK || MAX_RANK > 14) {
- throw new IllegalArgumentException("rank must be in [" + MIN_RANK + ", " + MAX_RANK + "]");
- }
- this.rank = rank;
- this.suit = suit;
- }
- public int compareTo(Card other) {
- if (!hasSameSuit(other)) {
- return other.getSuitRank() - getSuitRank();
- }
- return other.rank - rank;
- }
- public int getRank() {
- return rank;
- }
- public Card getRightAdj() {
- return rightAdj;
- }
- public Suit getSuit() {
- return suit;
- }
- public int getSuitRank() {
- return suit.getSuitRank();
- }
- public boolean hasDifferentColor(Card other) {
- return suit.hasDifferentColor(other.suit);
- }
- public boolean hasSameSuit(Card other) {
- return suit == other.suit;
- }
- public String rankToShortString() {
- switch (this.rank) {
- case 14:
- return "A";
- case 13:
- return "K";
- case 12:
- return "Q";
- case 11:
- return "J";
- case 10:
- return "T";
- default:
- return String.valueOf(rank);
- }
- }
- public void setRightAdj(Card rightAdj) {
- this.rightAdj = rightAdj;
- }
- public String suitToShortString() {
- return suit.toShortString();
- }
- public String toString() {
- return suitToShortString() + rankToShortString();
- }
- }
- -----------------------------------------------------------------
- public enum Suit {
- SPADES(3),
- HEARTS(2),
- DIAMONDS(1),
- CLUBS(0),
- ;
- private int suitRank;
- private Suit(int suitRank) {
- this.suitRank = suitRank;
- }
- public int getSuitRank() {
- return suitRank;
- }
- public boolean hasDifferentColor(Suit other) {
- return this.suitRank + other.suitRank != 3;
- }
- public String toShortString() {
- return name().substring(0, 1);
- }
- }
- -----------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement