Как мне сопоставить каждое значение из одного списка в другой?(Haskell) - PullRequest
0 голосов
/ 30 ноября 2018

Это код, который у меня есть:

data Suit = Diamond | Club | Heart | Spade
  deriving (Read, Enum, Eq, Bounded)

data Rank = Two | Three | Four
     | Five | Six | Seven | Eight | Nine | Ten 
     | Jack | Queen | King | Ace
  deriving (Read, Enum, Eq, Ord, Bounded)

, и я пытаюсь сопоставить каждое значение, ранг или костюм, с уникальным простым числом.

primeMapper :: Either Rank Suit -> Int

быть последней функцией, и я хочу перебрать каждый костюм и установить для него первые четыре простых числа:

primeMapper [Diamond .. Spade] = [2,3,5,7]

и каждый ранг, равный остальным простым числам вплоть до 17-го числа:

primeMapper [Two .. Ace] = drop 4 . take 17 $ primes

при условии, что у меня есть генерирующая функция, называемая простыми числами.

Этот код, однако, выдает ошибки, очевидно, потому что он генерирует список из списка.Как мне достичь того, что я пытаюсь сделать?Дайте мне знать, если я смогу объяснить это лучше.

Конечная цель - создать хеш-таблицу, которая дает уникальные идентификаторы каждой карточке на основе простых факторов, а затем сгенерировать простую факторизацию и использовать модуль для быстрого сравнения покерных комбинаций.

Ответы [ 4 ]

0 голосов
/ 30 ноября 2018

Надеюсь, что-то из этого можно адаптировать.

no2s3s5s = \n -> take n $ scanl (\b a -> a+b) 11 $ cycle [2,4,2,4,6,2,6,4]
rnk = filter (/=49) $ no2s3s5s 14  
stv = [2,3,5,7]
_deck = [ b*v | b <- stv, v <- rnk]
_Dia = take 13.drop (0*13) $ _deck
_Clb = take 13.drop (1*13) $ _deck
_Hrt = take 13.drop (2*13) $ _deck
_Spd = take 13.drop (3*13) $ _deck

_Dia

[22,26,34,38,46,58,62,74,82,86, 94,106,118]

_Clb

[33,39,51,57,69,87,93,111,123,129,141,159,177]

_Hrt

[55, 65,85,95,115,145,155,185,205,215,235,265,295]

_Spd

[77,91,119,133,161,203,217,259,287,301,329,371,413]

_deck

[22,26,34,38, 46,58,62,74,82,86,94,106,118,33,39,51,57,69,87,93,111,123,129,141,159,177,55,65,85,95,115,145,155,185,205,215,235,265,295,77,91,119,133,161,203,117,259 * 87,128,129 10 * * 10 10] 1029 * 10]]

52

Ваши кратные (_deck) все уникальны.Обычно я использую no2s3s5s с вычисленным (ограниченным) списком факторов и функцией мода для генерации длинного списка простых чисел.

0 голосов
/ 30 ноября 2018

Лучше использовать ваше решение с использованием сопоставления с образцом, хотя я бы предпочел

primeMapper :: Either Suit Rank -> Int
primeMapper (Left Diamond) = 2
primeMapper (Left Club)    = 3
...

вместо вашего длинного выражения case.

Однако вы также можете использовать lookup :: Eq a => a -> [(a, b)] -> Maybe b

import Data.Maybe (fromJust)

primeMapper :: Either Suit Rank -> Int
primeMapper = fromJust . flip lookup zippedPrimes
  where
  zippedPrimes = zip suitranks primes
  suitranks    = fmap Left suits ++ fmap Right ranks :: [Either Suit Rank]
  suits        = fromEnum minBound
  ranks        = fromEnum minBound
0 голосов
/ 30 ноября 2018

В зависимости от того, для чего вы планируете использовать это, вам может не потребоваться использование простых чисел или простых факторизаций вообще;Вы можете получить быстрое преобразование в и из простых чисел, просто выбрав один или другой иск или ранг для базового преобразования.Здесь я выберу костюм - есть четыре масти, поэтому возьмите первую цифру в базе 4 в качестве масти и оставшиеся цифры в качестве ранга.

encode :: (Suit, Rank) -> Int
encode (s, r) = fromEnum s + 4 * fromEnum r

decode :: Int -> (Suit, Rank)
decode n = (toEnum s, toEnum r) where (r, s) = n `quotRem` 4

Вы можете проверить в ghci, что это даетУникальный номер каждой карты:

> [encode (s, r) | r <- [minBound .. maxBound], s <- [minBound .. maxBound]]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51]

И что они декодируют соответствующим образом:

> map decode [0..51] == [(s, r) | r <- [minBound .. maxBound], s <- [minBound .. maxBound]]
True
0 голосов
/ 30 ноября 2018

В конечном итоге я решил, что я пытаюсь сделать вручную, так:

primeMapper :: Either Suit Rank -> Int
primeMapper x = case x of
        Left Diamond -> 2
        Left Club -> 3
        Left Heart -> 5
        Left Spade -> 7
        Right Two -> 11
        Right Three -> 13
        Right Four -> 17
        Right Five -> 19
        Right Six -> 23
        Right Seven -> 29
        Right Eight -> 31
        Right Nine -> 37
        Right Ten -> 41
        Right Jack -> 43
        Right Queen -> 47
        Right King -> 53
        Right Ace -> 59

... был ли более краткий способ сделать это, чем записывать каждый случай вручную?

...