Phase10/src/com/github/s7uxn37/phase10/Optimizer.java
/**
     * @param cards partitioned cards
     * @param target assigned target
     * @return the minimum number of missing cards to achieve the target
     */
@param cards partitioned cards
@param target assigned target
@return the minimum number of missing cards to achieve the target
@param cards partitioned cards @param target assigned target @return the minimum number of missing cards to achieve the target
public static int distanceToTarget(ArrayList<Card> cards, Target target) {
        switch(target.type) {
            case RUN:
                HashSet<Integer> numbers = new HashSet<>();
                for (Card c : cards) {
                    if (!numbers.contains(c.number))
                        numbers.add(c.number);
                }
                int minDist = target.cardCount; 
                for (int i = 0; i < cards.size() && minDist > 0; i++) { 
                    int dist = 0;
                    int runStart = cards.get(i).number;
                    for (int value = runStart + 1; value < runStart + target.cardCount; value++) {
                        if (!numbers.contains(value))
                            dist++;
                    }
                    if (dist < minDist)
                        minDist = dist;
                }
                return minDist;
            case SAME_COLOR: {
                HashMap<Integer, Integer> colorCounts = countValues(cards, card -> card.colorIndex);
                int maxCount = 0;
                for (Map.Entry<Integer, Integer> e : colorCounts.entrySet()) {
                    int count = e.getValue();
                    if (count > maxCount)
                        maxCount = count;
                }
                return Math.max(0, target.cardCount - maxCount);
            }
            case SAME_NUMBER:
                HashMap<Integer, Integer> numberCounts = new HashMap<>();
                for (Card c : cards) {
                    int prev = numberCounts.getOrDefault(c.number, 0);
                    numberCounts.put(c.number, prev + 1);
                }
                int maxCount = 0;
                for (Map.Entry<Integer, Integer> e : numberCounts.entrySet()) {
                    int count = e.getValue();
                    if (count > maxCount)
                        maxCount = count;
                }
                return Math.max(0, target.cardCount - maxCount);
        }
        return target.cardCount;
    }
public static int distanceToTarget ( ArrayList < Card > cards , Target target ) { switch ( target . type ) { case RUN : HashSet < Integer > numbers = new HashSet < > ( ) ; for ( Card c : cards ) { if ( ! numbers . contains ( c . number ) ) numbers . add ( c . number ) ; } int minDist = target . cardCount ; for ( int i = 0 ; i < cards . size ( ) && minDist > 0 ; i ++ ) { int dist = 0 ; int runStart = cards . get ( i ) . number ; for ( int value = runStart + 1 ; value < runStart + target . cardCount ; value ++ ) { if ( ! numbers . contains ( value ) ) dist ++ ; } if ( dist < minDist ) minDist = dist ; } return minDist ; case SAME_COLOR : { HashMap < Integer , Integer > colorCounts = countValues ( cards , card -> card . colorIndex ) ; int maxCount = 0 ; for ( Map . Entry < Integer , Integer > e : colorCounts . entrySet ( ) ) { int count = e . getValue ( ) ; if ( count > maxCount ) maxCount = count ; } return Math . max ( 0 , target . cardCount - maxCount ) ; } case SAME_NUMBER : HashMap < Integer , Integer > numberCounts = new HashMap < > ( ) ; for ( Card c : cards ) { int prev = numberCounts . getOrDefault ( c . number , 0 ) ; numberCounts . put ( c . number , prev + 1 ) ; } int maxCount = 0 ; for ( Map . Entry < Integer , Integer > e : numberCounts . entrySet ( ) ) { int count = e . getValue ( ) ; if ( count > maxCount ) maxCount = count ; } return Math . max ( 0 , target . cardCount - maxCount ) ; } return target . cardCount ; }
@param cards partitioned cards
 @param target assigned target
 @return the minimum number of missing cards to achieve the target
@param cards partitioned cards @param target assigned target @return the minimum number of missing cards to achieve the target
// worst case: draw all cards // card[i] is start of run