简体   繁体   English

如何在Clojure中使用频率来组合相同的频率并显示一次?

[英]How to use frequencies in clojure to combine same frequency and display them once?

I making a poker hands game in clojure. 我在Clojure中制作扑克手游戏。 I have to define a function such that such that it returns the ranks in the descending order. 我必须定义一个函数,以便它以降序返回等级。 For example: order ["2H" "3S" "6C" "5D" "4D"] should return (6 5 4 3 2). 例如:订单[“ 2H”“ 3S”“ 6C”“ 5D”“ 4D”]应该返回(6 5 4 3 2)。 But if there is a two-pair like this: ["5H" "AD" "5C" "7D" "AS"] then it should return (14 5 7), but mine returns [14 14 7 5 5], how can I correct this? 但是,如果有这样的两对子:[“ 5H”“ AD”“ 5C”“ 7D”“ AS”]那么它应该返回(14 5 7),但是我的返回[14 14 7 5 5],我可以更正吗? It should work in the same way for other cases of poker hands as well like for a full house it should give the rank of the three of a kind and the rank of the two of a kind. 在其他情况下,它应该以相同的方式工作,就像在满屋子游戏中一样,它应该给出三种类型的排名和两种类型的排名。 So, for this I have written: 因此,为此,我写了:

(defn order
                [hand]
                "Return a list of the ranks, sorted highest first"
                (let [ranks (reverse (sort (map #(.indexOf "--23456789TJQKA" %)
                                                (map #(str (first %)) hand))))]
                  (if (= ranks [14 5 4 3 2])
                    [5 4 3 2 1]
                    (into [] ranks))))

I have also written all the other poker hand functions like flush?, straight? 我还编写了所有其他扑克手功能,例如同花顺? etc. 等等

Also, I have to define another function such that it takes two orders like '(8 5 9) '(8 7 3) and returns true if the first has the larger value of the first difference, else false. 另外,我必须定义另一个函数,使其采用两个顺序,例如'(8 5 9)'(8 7 3),如果第一个具有较大的第一个差值,则返回true,否则返回false。 Could someone please give me an idea how to do this? 有人可以给我一个想法怎么做吗?

Updated to show sorting by count, then rank: 更新以显示按计数排序,然后排名:

(defn ->r [hand]
  (let [ranks (zipmap "23456789TJKQA" (range 2 15)) ; creates a map like {\2 2, .... \A 14}
        count-then-rank
          (fn [x y] (compare 
                      [(second y) (first y)] 
                      [(second x) (first x)]))]
    (->> hand
         (map (comp ranks first)) ; returns the rank for each card eg: '(5 14 5 7 14)
         frequencies              ; returns a map of rank vs count eg: {5 2, 14 2, 7 1}
         (sort count-then-rank)   ; becomes a sorted list of tuples eg: '([14 2] [5 2] [7 1])
         (map first))))           ; extract the first value each time eg: '(14 5 7)

For a more complete solution, you can use the frequencies to determine if you have 4 of a kind, 3 of a kind, full house etc. 对于更完整的解决方案,您可以使用频率来确定您是否有4种,3种,满屋等。

Updated with more info on straight and straight flush: 更新了有关直冲和直冲的更多信息:

For a straight, one approach is: 对于直接而言,一种方法是:

  1. Extract the ranks so you would have a list like '(14 3 2 4 5) 提取等级,这样您将获得类似“(14 3 2 4 5)的列表
  2. Sort this list to get '(2 3 4 5 14) 排序此列表可获得'(2 3 4 5 14)
  3. Get the first element: 2, and the last element 14 获取第一个元素:2,最后一个元素14
  4. Construct a range from 2 (inclusive) to 15 (exclusive) to get '(2 3 4 5 6 7 8 9 10 11 12 13 14) 构造一个从2(含)到15(不含)的范围以得到'(2 3 4 5 6 7 8 9 10 11 12 13 14)
  5. Compare against the sorted sequence. 与排序的序列进行比较。 In this case the result is false. 在这种情况下,结果为假。
  6. Retry, but first replace 14 with 1. 重试,但首先将14替换为1。
    • replace => '(1 3 2 4 5) 替换=>'(1 3 2 4 5)
    • sort => '(1 2 3 4 5) 排序=>'(1 2 3 4 5)
    • (range 1 6) => '(1 2 3 4 5) (范围1 6)=>'(1 2 3 4 5)
    • This time, the range and the sorted list match, so this is a straight. 这次,范围和排序的列表匹配,所以这是直的。

(defn straight? [cards]                             ; eg: ["AH" "3H" "2H" "4H" "5H"] 
  (let [ranks (zipmap "23456789TJKQA" (range 2 15))
        ranks-only (map (comp ranks first) cards)   ; eg: '(14 3 2 4 5)
        ace-high (sort ranks-only)                  ; eg: '(2 3 4 5 14)
        ace-low (sort (replace {14 1} ranks-only))  ; eg: '(1 2 3 4 5)
        consecutive #(= (range (first %) (inc (last %))) %)] ; eg: (= (range 1 6) '(1 2 3 4 5))
    (or (consecutive ace-high)
        (consecutive ace-low))))

For a flush, simply extract all the suits, and then ensure they are all equal: 抽奖时,只需抽出所有西服,然后确保它们相等即可:

(defn flush? [cards] 
    (apply = (map second cards)))  ; this is when suit is the second character

Now, simply combine these two boolean conditions to determine if this is a straight flush 现在,只需将这两个布尔条件组合起来即可确定这是否是同花顺

(defn straight-flush? [cards]
     (and (straight? cards) (flush? cards)))

See if you can solve 4clojure best hand puzzle , to open up a large number of different ways to tackle this. 看看您是否可以解决4clojure最佳手动拼图 ,以打开多种不同的方式来解决此问题。 When I solved this, I used similar, but not identical functions. 解决此问题时,我使用了相似但不相同的功能。

Spoiler a more complete solution (using suit first "D7" instead of rank first "7D") is below 下面是一个更完整的解决方案(使用西服优先的“ D7”代替排名第一的“ 7D”)

https://github.com/toolkit/4clojure-solutions/blob/master/src/puzzle_solutions/best_hand.clj https://github.com/toolkit/4clojure-solutions/blob/master/src/puzzle_solutions/best_hand.clj

I think frequencies will get you closer to what you're looking for. 我认为frequencies将使您更接近所需的内容。

user=> (frequencies [14 14 7 5 5])
{14 2, 7 1, 5 2}

You could use this for sorting : 您可以使用它进行排序

user=> (sort-by (frequencies [14 14 7 5 5]) [14 14 7 5 5])
(7 14 14 5 5)

And then you could use distinct : 然后您可以使用different

user=> (distinct [14 14 7 5 5])
(14 7 5)

Putting all of these together should get you exactly what you want. 将所有这些放在一起应该可以让您得到真正想要的东西。 I'll leave that as an exercise for the reader. 我将其留给读者练习。 When I'm stuck wondering if there's an easy way to do something, I often turn to Clojure's cheatsheet . 当我想知道是否有一种简单的方法来做某事时,我经常转向Clojure的备忘单

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM