Skip to content

Instantly share code, notes, and snippets.

@msysyamamoto
Created February 12, 2014 22:50
Show Gist options
  • Select an option

  • Save msysyamamoto/8966169 to your computer and use it in GitHub Desktop.

Select an option

Save msysyamamoto/8966169 to your computer and use it in GitHub Desktop.
import Control.Applicative ((<$>))
import Data.List (nub, delete, subsequences, group, sort)
import System.Environment (getArgs)
import Test.HUnit
type Gem = Char
main :: IO ()
main = do
princessPath <- (!! 0) <$> getArgs
gemPath <- (!! 1) <$> getArgs
(princess, _) <- break (== '\r') <$> readFile princessPath
(gems, _) <- break (== '\r') <$> readFile gemPath
putStrLn . show $ solve princess gems
-- 宝石の一覧は、宝石の組合せを辞書順に並べたもの。
--
-- 探したい宝石パターンの先頭のGemを見て、それより小さくなる(先に現れる)
-- 宝石パターンの個数を求める。
-- それが終わったら次は二つ目のGemを見て、それよりも...
-- それが終わったら次は三つ目のGemを見て...
-- で、だんだん絞り込んで行く感じ
solve :: [Gem] -- 探したい宝石パターン
-> [Gem] -- 使用できる宝石の一覧
-> Int
solve _ [] = 0
solve [] _ = 0
solve (e0:es) gems = preNum + (solve es (delete e0 gems') + 1)
where
gems' = sort gems
preGems = takeWhile (e0 >) $ nub gems'
preNum = sum . map pernums $ map (flip delete gems') preGems
-- xs の重複を除いた部分列に対して順列の数を求め、その和を求める
pernums :: [Gem] -> Int
pernums xs = (1+) . sum $ map pernum subs
where
-- tail は "" を除外するため
subs = nub . map sort . tail $ subsequences xs
-- 同じものを含む順列の数を求める
pernum :: [Gem] -> Int
pernum xs = factorial (sum gnums) `div` product (map factorial gnums)
where
gnums = map length $ group xs
factorial :: Int -> Int
factorial n = product [1..n]
--
-- Test
--
runTests :: IO Counts
runTests = runTestTT $ TestList tests
tests :: [Test]
tests = map TestCase
[ assertEqual "1:a" 1 (solve "a" "aaabcc")
, assertEqual "2:aa" 2 (solve "aa" "aaabcc")
, assertEqual "3:aaa" 3 (solve "aaa" "aaabcc")
, assertEqual "4:aaab" 4 (solve "aaab" "aaabcc")
, assertEqual "5:aaabc" 5 (solve "aaabc" "aaabcc")
, assertEqual "6:aaabcc" 6 (solve "aaabcc" "aaabcc")
, assertEqual "7:aaac" 7 (solve "aaac" "aaabcc")
, assertEqual "8:aaacb" 8 (solve "aaacb" "aaabcc")
, assertEqual "9:aaacbc" 9 (solve "aaacbc" "aaabcc")
, assertEqual "10:aaacc" 10 (solve "aaacc" "aaabcc")
, assertEqual "11:aaaccb" 11 (solve "aaaccb" "aaabcc")
, assertEqual "12:aab" 12 (solve "aab" "aaabcc")
, assertEqual "13:aaba" 13 (solve "aaba" "aaabcc")
, assertEqual "14:aabac" 14 (solve "aabac" "aaabcc")
, assertEqual "15:aabacc" 15 (solve "aabacc" "aaabcc")
, assertEqual "16:aabc" 16 (solve "aabc" "aaabcc")
, assertEqual "17:aabca" 17 (solve "aabca" "aaabcc")
, assertEqual "18:aabcac" 18 (solve "aabcac" "aaabcc")
, assertEqual "19:aabcc" 19 (solve "aabcc" "aaabcc")
, assertEqual "20:aabcca" 20 (solve "aabcca" "aaabcc")
, assertEqual "21:aac" 21 (solve "aac" "aaabcc")
, assertEqual "22:aaca" 22 (solve "aaca" "aaabcc")
, assertEqual "23:aacab" 23 (solve "aacab" "aaabcc")
, assertEqual "24:aacabc" 24 (solve "aacabc" "aaabcc")
, assertEqual "25:aacac" 25 (solve "aacac" "aaabcc")
, assertEqual "26:aacacb" 26 (solve "aacacb" "aaabcc")
, assertEqual "27:aacb" 27 (solve "aacb" "aaabcc")
, assertEqual "28:aacba" 28 (solve "aacba" "aaabcc")
, assertEqual "29:aacbac" 29 (solve "aacbac" "aaabcc")
, assertEqual "30:aacbc" 30 (solve "aacbc" "aaabcc")
, assertEqual "31:aacbca" 31 (solve "aacbca" "aaabcc")
, assertEqual "32:aacc" 32 (solve "aacc" "aaabcc")
, assertEqual "33:aacca" 33 (solve "aacca" "aaabcc")
, assertEqual "34:aaccab" 34 (solve "aaccab" "aaabcc")
, assertEqual "35:aaccb" 35 (solve "aaccb" "aaabcc")
, assertEqual "36:aaccba" 36 (solve "aaccba" "aaabcc")
, assertEqual "37:ab" 37 (solve "ab" "aaabcc")
, assertEqual "38:aba" 38 (solve "aba" "aaabcc")
, assertEqual "39:abaa" 39 (solve "abaa" "aaabcc")
, assertEqual "40:abaac" 40 (solve "abaac" "aaabcc")
, assertEqual "41:abaacc" 41 (solve "abaacc" "aaabcc")
, assertEqual "42:abac" 42 (solve "abac" "aaabcc")
, assertEqual "43:abaca" 43 (solve "abaca" "aaabcc")
, assertEqual "44:abacac" 44 (solve "abacac" "aaabcc")
, assertEqual "45:abacc" 45 (solve "abacc" "aaabcc")
, assertEqual "46:abacca" 46 (solve "abacca" "aaabcc")
, assertEqual "47:abc" 47 (solve "abc" "aaabcc")
, assertEqual "48:abca" 48 (solve "abca" "aaabcc")
, assertEqual "49:abcaa" 49 (solve "abcaa" "aaabcc")
, assertEqual "50:abcaac" 50 (solve "abcaac" "aaabcc")
, assertEqual "51:abcac" 51 (solve "abcac" "aaabcc")
, assertEqual "52:abcaca" 52 (solve "abcaca" "aaabcc")
, assertEqual "53:abcc" 53 (solve "abcc" "aaabcc")
, assertEqual "54:abcca" 54 (solve "abcca" "aaabcc")
, assertEqual "55:abccaa" 55 (solve "abccaa" "aaabcc")
, assertEqual "56:ac" 56 (solve "ac" "aaabcc")
, assertEqual "57:aca" 57 (solve "aca" "aaabcc")
, assertEqual "58:acaa" 58 (solve "acaa" "aaabcc")
, assertEqual "59:acaab" 59 (solve "acaab" "aaabcc")
, assertEqual "60:acaabc" 60 (solve "acaabc" "aaabcc")
, assertEqual "61:acaac" 61 (solve "acaac" "aaabcc")
, assertEqual "62:acaacb" 62 (solve "acaacb" "aaabcc")
, assertEqual "63:acab" 63 (solve "acab" "aaabcc")
, assertEqual "64:acaba" 64 (solve "acaba" "aaabcc")
, assertEqual "65:acabac" 65 (solve "acabac" "aaabcc")
, assertEqual "66:acabc" 66 (solve "acabc" "aaabcc")
, assertEqual "67:acabca" 67 (solve "acabca" "aaabcc")
, assertEqual "68:acac" 68 (solve "acac" "aaabcc")
, assertEqual "69:acaca" 69 (solve "acaca" "aaabcc")
, assertEqual "70:acacab" 70 (solve "acacab" "aaabcc")
, assertEqual "71:acacb" 71 (solve "acacb" "aaabcc")
, assertEqual "72:acacba" 72 (solve "acacba" "aaabcc")
, assertEqual "73:acb" 73 (solve "acb" "aaabcc")
, assertEqual "74:acba" 74 (solve "acba" "aaabcc")
, assertEqual "75:acbaa" 75 (solve "acbaa" "aaabcc")
, assertEqual "76:acbaac" 76 (solve "acbaac" "aaabcc")
, assertEqual "77:acbac" 77 (solve "acbac" "aaabcc")
, assertEqual "78:acbaca" 78 (solve "acbaca" "aaabcc")
, assertEqual "79:acbc" 79 (solve "acbc" "aaabcc")
, assertEqual "80:acbca" 80 (solve "acbca" "aaabcc")
, assertEqual "81:acbcaa" 81 (solve "acbcaa" "aaabcc")
, assertEqual "82:acc" 82 (solve "acc" "aaabcc")
, assertEqual "83:acca" 83 (solve "acca" "aaabcc")
, assertEqual "84:accaa" 84 (solve "accaa" "aaabcc")
, assertEqual "85:accaab" 85 (solve "accaab" "aaabcc")
, assertEqual "86:accab" 86 (solve "accab" "aaabcc")
, assertEqual "87:accaba" 87 (solve "accaba" "aaabcc")
, assertEqual "88:accb" 88 (solve "accb" "aaabcc")
, assertEqual "89:accba" 89 (solve "accba" "aaabcc")
, assertEqual "90:accbaa" 90 (solve "accbaa" "aaabcc")
, assertEqual "91:b" 91 (solve "b" "aaabcc")
, assertEqual "92:ba" 92 (solve "ba" "aaabcc")
, assertEqual "93:baa" 93 (solve "baa" "aaabcc")
, assertEqual "94:baaa" 94 (solve "baaa" "aaabcc")
, assertEqual "95:baaac" 95 (solve "baaac" "aaabcc")
, assertEqual "96:baaacc" 96 (solve "baaacc" "aaabcc")
, assertEqual "97:baac" 97 (solve "baac" "aaabcc")
, assertEqual "98:baaca" 98 (solve "baaca" "aaabcc")
, assertEqual "99:baacac" 99 (solve "baacac" "aaabcc")
, assertEqual "100:baacc" 100 (solve "baacc" "aaabcc")
, assertEqual "101:baacca" 101 (solve "baacca" "aaabcc")
, assertEqual "102:bac" 102 (solve "bac" "aaabcc")
, assertEqual "103:baca" 103 (solve "baca" "aaabcc")
, assertEqual "104:bacaa" 104 (solve "bacaa" "aaabcc")
, assertEqual "105:bacaac" 105 (solve "bacaac" "aaabcc")
, assertEqual "106:bacac" 106 (solve "bacac" "aaabcc")
, assertEqual "107:bacaca" 107 (solve "bacaca" "aaabcc")
, assertEqual "108:bacc" 108 (solve "bacc" "aaabcc")
, assertEqual "109:bacca" 109 (solve "bacca" "aaabcc")
, assertEqual "110:baccaa" 110 (solve "baccaa" "aaabcc")
, assertEqual "111:bc" 111 (solve "bc" "aaabcc")
, assertEqual "112:bca" 112 (solve "bca" "aaabcc")
, assertEqual "113:bcaa" 113 (solve "bcaa" "aaabcc")
, assertEqual "114:bcaaa" 114 (solve "bcaaa" "aaabcc")
, assertEqual "115:bcaaac" 115 (solve "bcaaac" "aaabcc")
, assertEqual "116:bcaac" 116 (solve "bcaac" "aaabcc")
, assertEqual "117:bcaaca" 117 (solve "bcaaca" "aaabcc")
, assertEqual "118:bcac" 118 (solve "bcac" "aaabcc")
, assertEqual "119:bcaca" 119 (solve "bcaca" "aaabcc")
, assertEqual "120:bcacaa" 120 (solve "bcacaa" "aaabcc")
, assertEqual "121:bcc" 121 (solve "bcc" "aaabcc")
, assertEqual "122:bcca" 122 (solve "bcca" "aaabcc")
, assertEqual "123:bccaa" 123 (solve "bccaa" "aaabcc")
, assertEqual "124:bccaaa" 124 (solve "bccaaa" "aaabcc")
, assertEqual "125:c" 125 (solve "c" "aaabcc")
, assertEqual "126:ca" 126 (solve "ca" "aaabcc")
, assertEqual "127:caa" 127 (solve "caa" "aaabcc")
, assertEqual "128:caaa" 128 (solve "caaa" "aaabcc")
, assertEqual "129:caaab" 129 (solve "caaab" "aaabcc")
, assertEqual "130:caaabc" 130 (solve "caaabc" "aaabcc")
, assertEqual "131:caaac" 131 (solve "caaac" "aaabcc")
, assertEqual "132:caaacb" 132 (solve "caaacb" "aaabcc")
, assertEqual "133:caab" 133 (solve "caab" "aaabcc")
, assertEqual "134:caaba" 134 (solve "caaba" "aaabcc")
, assertEqual "135:caabac" 135 (solve "caabac" "aaabcc")
, assertEqual "136:caabc" 136 (solve "caabc" "aaabcc")
, assertEqual "137:caabca" 137 (solve "caabca" "aaabcc")
, assertEqual "138:caac" 138 (solve "caac" "aaabcc")
, assertEqual "139:caaca" 139 (solve "caaca" "aaabcc")
, assertEqual "140:caacab" 140 (solve "caacab" "aaabcc")
, assertEqual "141:caacb" 141 (solve "caacb" "aaabcc")
, assertEqual "142:caacba" 142 (solve "caacba" "aaabcc")
, assertEqual "143:cab" 143 (solve "cab" "aaabcc")
, assertEqual "144:caba" 144 (solve "caba" "aaabcc")
, assertEqual "145:cabaa" 145 (solve "cabaa" "aaabcc")
, assertEqual "146:cabaac" 146 (solve "cabaac" "aaabcc")
, assertEqual "147:cabac" 147 (solve "cabac" "aaabcc")
, assertEqual "148:cabaca" 148 (solve "cabaca" "aaabcc")
, assertEqual "149:cabc" 149 (solve "cabc" "aaabcc")
, assertEqual "150:cabca" 150 (solve "cabca" "aaabcc")
, assertEqual "151:cabcaa" 151 (solve "cabcaa" "aaabcc")
, assertEqual "152:cac" 152 (solve "cac" "aaabcc")
, assertEqual "153:caca" 153 (solve "caca" "aaabcc")
, assertEqual "154:cacaa" 154 (solve "cacaa" "aaabcc")
, assertEqual "155:cacaab" 155 (solve "cacaab" "aaabcc")
, assertEqual "156:cacab" 156 (solve "cacab" "aaabcc")
, assertEqual "157:cacaba" 157 (solve "cacaba" "aaabcc")
, assertEqual "158:cacb" 158 (solve "cacb" "aaabcc")
, assertEqual "159:cacba" 159 (solve "cacba" "aaabcc")
, assertEqual "160:cacbaa" 160 (solve "cacbaa" "aaabcc")
, assertEqual "161:cb" 161 (solve "cb" "aaabcc")
, assertEqual "162:cba" 162 (solve "cba" "aaabcc")
, assertEqual "163:cbaa" 163 (solve "cbaa" "aaabcc")
, assertEqual "164:cbaaa" 164 (solve "cbaaa" "aaabcc")
, assertEqual "165:cbaaac" 165 (solve "cbaaac" "aaabcc")
, assertEqual "166:cbaac" 166 (solve "cbaac" "aaabcc")
, assertEqual "167:cbaaca" 167 (solve "cbaaca" "aaabcc")
, assertEqual "168:cbac" 168 (solve "cbac" "aaabcc")
, assertEqual "169:cbaca" 169 (solve "cbaca" "aaabcc")
, assertEqual "170:cbacaa" 170 (solve "cbacaa" "aaabcc")
, assertEqual "171:cbc" 171 (solve "cbc" "aaabcc")
, assertEqual "172:cbca" 172 (solve "cbca" "aaabcc")
, assertEqual "173:cbcaa" 173 (solve "cbcaa" "aaabcc")
, assertEqual "174:cbcaaa" 174 (solve "cbcaaa" "aaabcc")
, assertEqual "175:cc" 175 (solve "cc" "aaabcc")
, assertEqual "176:cca" 176 (solve "cca" "aaabcc")
, assertEqual "177:ccaa" 177 (solve "ccaa" "aaabcc")
, assertEqual "178:ccaaa" 178 (solve "ccaaa" "aaabcc")
, assertEqual "179:ccaaab" 179 (solve "ccaaab" "aaabcc")
, assertEqual "180:ccaab" 180 (solve "ccaab" "aaabcc")
, assertEqual "181:ccaaba" 181 (solve "ccaaba" "aaabcc")
, assertEqual "182:ccab" 182 (solve "ccab" "aaabcc")
, assertEqual "183:ccaba" 183 (solve "ccaba" "aaabcc")
, assertEqual "184:ccabaa" 184 (solve "ccabaa" "aaabcc")
, assertEqual "185:ccb" 185 (solve "ccb" "aaabcc")
, assertEqual "186:ccba" 186 (solve "ccba" "aaabcc")
, assertEqual "187:ccbaa" 187 (solve "ccbaa" "aaabcc")
, assertEqual "188:ccbaaa" 188 (solve "ccbaaa" "aaabcc")
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment