使用Clojure向量对7张扑克牌手牌进行建模

3
我有一个表示七张扑克牌的向量,想要使用以下方法找到下一手牌:
  • 值的范围从0到12,并已排序(例如:[0 0 7 11 11 12 12])
  • 有效向量最多只能有4个相同的值
  • 第一个有效向量是[0 0 0 0 1 1 1]
  • 如果index和index + 1处的值不同,则将index处的值加1,并将0到index-1处的所有值设置为0
  • 重复上一步直到向量有效
例如,(next-hand [0 0 0 0 1 1 1])将直接返回[0 0 0 1 1 1 1]。但是,(next-hand [0 0 0 1 1 1 1])会循环执行。
[0 0 1 1 1 1 1] (invalid)
[0 1 1 1 1 1 1] (invalid)
[1 1 1 1 1 1 1] (invalid)
[0 0 0 0 0 0 2] (invalid)
[0 0 0 0 0 1 2] (invalid)

并返回这张有效的牌:
[0 0 0 0 1 1 2]

这是我拥有的sudo代码,但需要将其转换为clojure。请注意,我在手末尾添加了一个非常大的整数以使最后一次比较始终为true。因此,在[1 1 1 1 1 1 1 99]的情况下,第一个循环将在i=6处结束,且1 < 99 == true

let hand = [hand 99]
while hand is invalid
  for i in range(0,6)
    if hand[i] < hand[i+1]
      increment hand[i]
      break
  for j in range(0,i-1)
    hand[j] = 0

编辑时间:2013年3月29日星期五: 为了使选择方案与扑克牌手模型配合使用,我添加了一个is-valid函数,代码如下:

(defn is-valid [v]
  (let [distinct-ranks (partition-by identity v)
        count-distinct (map count distinct-ranks)
        max-count (apply max count-distinct)]
    (<= max-count 4)))

并且更新为(filter #(is-valid %)next-hand中。


听起来像是 core.logic 的工作。 - Alex Taggart
@AlexTaggart:我不这么认为,这听起来不像是关系/约束问题。 - Ankur
1个回答

0

一个可能的解决方案:

(defn next [v]
  (let [i (->> (map <  v (rest v))
               (map-indexed vector)
               (filter #(% 1))
               first)
        index (if i (i 0) 6)]
    (for [[i x] (map-indexed vector v)]
      (cond (= i index) (inc x)
            (< i index) 0
            :else x))))

(defn next-hand [v]
  (->> (iterate next (next v))
       (filter #(= 4 (apply + %)))
       first
       vec))

(next-hand [0 0 0 1 1 1 1])

这很接近了。next函数是完美的。然而,next-hand并没有评估为有效的下一手。我认为,需要一个valid-hand函数来停止,并且我会尝试明天发布它。你能解释一下iterate如何与其他部分配合工作吗?什么会停止迭代? - Brett Pontarelli
next-hand 中的 filter 用于查找有效的手牌。在这种情况下,有效的手牌是指向量总和为4的手牌,也许您认为有效的手牌有其他含义。iterate 将生成一个无限序列的手牌,其中下一手基于上一手。 - Ankur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接