Problem:
Problem C: K Poker

Description

時は200X年、K大学で活動する謎のサークルKはその大学の文化祭の最中にK東4Fで彼らが作成した新たなゲーム、Kポーカーを発表した。

このゲームは一見すると普通のポーカーであるが、カードに基本点という要素をつけてポーカーをより奥の深いゲームにしたものである。

カードの基本点はそれぞれのカードに書かれている絵柄によって決まり、手札の点数は手札にある5枚の基本点の合計に手札の役の倍率を掛けたものになる。

この基本点を導入した事により、例えばフルハウスなどの強い役を作ったとしても基本点が0であればブタと同様に扱われてしまい、ワンペアに負けることさえある。

それ以外のルールは通常のポーカーと同じである。

このKポーカーをPCに移植しようと思ったあなたは手札の点数を計算するプログラムを書く事にした。

なおこのゲームは18歳未満の人はプレイ出来ない。

Input

入力は複数のテストケースからなる。

各テストケースの最初の行にはチェックする手札の数Nが書かれている。

次の4行には13個の整数が並びカードの基本点が1-13の順に並んで書かれている。4行のスーツは上から順にスペード、クローバー、ハート、ダイヤの順に並んでいる。

次の行には9個の整数が並び、順にワンペア、ツーペア、スリーカード、ストレート、フラッシュ、フルハウス、フォーカード、ストレートフラッシュ、ロイヤルストレートフラッシュの倍率を表している。役の倍率は必ず昇順となっている。ブタ(役無し、ノーペア)の倍率は常に0である。

次のN行には手札を表す5個の長さ2の異なる文字列が並んでいる。1文字目はカードの数値を表し,A,2,3,4,5,6,7,8,9,T,J,Q,Kのいずれかである。2文字目はカードのスーツを表し、S,C,H,Dのいずれかである。各アルファベットはAはエース、Tは10、Jはジャック、Qはクイーン、Kはキング、Sはスペード、Cはクローバー、Hはハート、Dはダイヤを表す。

入力の数値は全て[0,10000]の範囲に収まっている。

入力はEOFで終わる。

Output

各手札の点数を1行ずつ出力せよ。

連続する2つのテストケースの間には空行を1つ入れること。

役についてはwikipediaのポーカーのページを参照のこと。
なお、ストレートはエースとキングをまたぐ場合があるが、手札が10,ジャック、クイーン、キング、エースの場合にのみストレートとみなされる。

Sample Input

3
0 1 0 1 0 0 0 0 0 1 0 0 0
1 0 0 0 0 0 1 0 0 1 0 0 2
0 1 1 0 1 1 1 0 0 0 0 5 5
3 1 1 1 0 1 0 0 1 0 3 0 2
1 1 2 4 5 10 20 50 100
7H 6H 2H 5H 3H
9S 9C 9H 8H 8D
KS KH QH JD TS
10
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9
AS 3D 2C 5D 6H
6S 6C 7D 8H 9C
TS TD QC JD JC
KD KH KC AD 2C
3D 4H 6D 5H 7C
2S KS QS AS JS
TS TD JD JC TH
8H 8D TC 8C 8S
4S 5S 3S 7S 6S
KD QD JD TD AD

Output for Sample Input

25
0
14

0
5
10
15
20
25
30
35
40
45

Solution in JAVA (judge verdict: Wrong Answer)

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		int[][] basePoints = new int[4][13];
		int[] rates = new int[9];

		Map<Character, Integer> cardMap = new HashMap<Character, Integer>() {
			{
				put('A', 0);
				put('2', 1);
				put('3', 2);
				put('4', 3);
				put('5', 4);
				put('6', 5);
				put('7', 6);
				put('8', 7);
				put('9', 8);
				put('T', 9);
				put('J', 10);
				put('Q', 11);
				put('K', 12);
			}
		};
		Map<Character, Integer> markMap = new HashMap<Character, Integer>() {
			{
				put('S', 0);
				put('C', 1);
				put('H', 2);
				put('D', 3);
			}
		};

		while (true) {
			int n = 0;
			try {
				n = sc.nextInt();
				if (n == 0) {
					break;
				}

				for (int i = 0; i < 4; i++) {
					for (int j = 0; j < 13; j++) {
						basePoints[i][j] = sc.nextInt();
					}
				}
				for (int i = 0; i < 9; i++) {
					rates[i] = sc.nextInt();
				}
			} catch (Exception e) {
				return;
			}

			for (int i = 0; i < n; i++) {
				Card[] cards = new Card[5];
				int minNumber = 13;
				int maxNumber = 0;
				int basePoint = 0;
				Set<Integer> marks = new HashSet<Integer>();
				Set<Integer> numbers = new HashSet<Integer>();
				for (int j = 0; j < 5; j++) {
					String cardString = sc.next();
					cards[j] = new Card(cardMap.get(cardString.charAt(0)),
							markMap.get(cardString.charAt(1)));
					marks.add(cards[j].type);
					numbers.add(cards[j].number);
					// if (cards[j].number < minNumber)
					// minNumber = cards[j].number;
					// if (maxNumber < cards[j].number)
					// maxNumber = cards[j].number;
					basePoint += basePoints[cards[j].type][cards[j].number];
				}

				Yaku yaku = resolveRate(cards, marks, numbers);
				int rate = yaku == null ? 0 : rates[yaku.ordinal()];
				System.out.println(basePoint * rate);

			}
			System.out.println();
		}

	}

	static Yaku resolveRate(Card[] cards, Set<Integer> marks,
			Set<Integer> numbers) {
		Arrays.sort(cards);

		// tbV
		boolean isFlash = marks.size() == 1;

		// straight
		boolean isStraight = true;
		for (int i = 1; i < 5; i++) {
			if (cards[i - 1].number + 1 != cards[i].number
					&& (i != 4 || cards[i].number != 0)) {
				isStraight = false;
				break;
			}
		}

		if (isFlash && isStraight) {
			if (cards[4].number == 0) {
				return Yaku.ROYAL;
			}
			else {
				return Yaku.STRAIGHT_FLASH;
			}
		}
		if (isStraight) {
			return Yaku.STRAIGHT;
		}
		if (isFlash) {
			return Yaku.FLASH;
		}
		if (numbers.size() == 2) {
			int numEqualToFirst = 0;
			for (int j = 1; j < 5; j++) {
				if (cards[0].number == cards[j].number) {
					numEqualToFirst++;
				}
			}
			if (numEqualToFirst == 0 || numEqualToFirst == 3) {
				return Yaku.FOUR_PAIR;
			}
			else {
				return Yaku.FULLHAUSE;
			}
		}
		if (numbers.size() == 3) {
			for (int j = 0; j < 5; j++) {
				int numCount = 0;
				for (int k = 0; k < 5; k++) {
					if (cards[j].number == cards[k].number)
						numCount++;

				}
				if (numCount == 3) {
					return Yaku.THREE_PAIR;
				}
			}
			return Yaku.TWO_PAIR;
		}
		if (numbers.size() == 4) {
			return Yaku.ONE_PAIR;
		}

		return null;

	}

	static class Card implements Comparable<Card> {
		final int number;
		final int type;

		public Card(int number, int type) {
			super();
			this.number = number;
			this.type = type;
		}

		@Override
		public int compareTo(Card o) {
			if (number != o.number)
				return number - o.number;
			return type - o.type;
		}

	}

}

enum Yaku {
	ONE_PAIR, TWO_PAIR, THREE_PAIR, STRAIGHT, FLASH, FULLHAUSE, FOUR_PAIR, STRAIGHT_FLASH, ROYAL;
}