lisp - 获取彩票号码

标签 lisp common-lisp

作为学习 Lisp 的一部分,我目前正在尝试编写一个函数来帮助我填写彩票。我希望该函数返回

  • 列表
  • 六个数字,
  • 其中每个数字都在 1 到 49 之间,
  • 没有重复的数字,
  • 并且列表按升序排列。

到目前为止,我已经完成了五个要求中的四个。这是我当前的代码:

(defun lottery ()
  (sort (loop repeat 6 collect (1+ (random 49))) #'<))

当我运行这个函数时,我得到如下信息:

(lottery)
;; => (3 10 23 29 41 43)

基本上,一切都很好 - 除了有时我在列表中两次出现相同的数字。这里开始变得令人费解。我的问题是我不太确定如何用 Lisp 方式解决这个问题。我能想到多种选择:

  • 对结果运行remove-duplicates,然后使用length检查列表是否少于六个元素,如果是,则运行lottery 第二次,将其附加到第一个结果,使用subseq仅获取前六个元素,然后重复。这可行,但不是很优雅,特别是当它涉及排序等时。多次。
  • 从一个空列表开始,使用 (1+ (random 49)) 创建一个随机数,然后调用 pushnew。现在使用列表递归调用lottery,直到length 返回六。我更喜欢这种方法,但我仍然不太相信,因为这样我需要两个函数:一个外部函数,lottery,和一个内部函数,递归调用并处理列表作为参数。
  • 从哈希表开始,使用 1 到 49 之间的数字作为键,并将键的值设置为 nil。然后,在循环内获取 1 到 49 之间的随机数,并将相应键的值更改为 t。一旦哈希表的六个元素具有 t 作为值,则返回。恕我直言,这是迄今为止最糟糕的方法,因为它浪费了大量内存并且不能很好地扩展。

您对这些选项有何看法?还有其他实现方法吗?高级 Lisp 开发人员将如何解决这个问题?

有什么提示吗?

最佳答案

创建一个包含 1 到 49 之间所有数字的列表,随机播放,取 6,排序。

=> (sort (take 6 (shuffle (range 1 50))))
; (8 14 16 23 34 39)

原发者添加:

为了展示最终的实现,我将其添加到此处:

(defun shuffle (list)
  (let ((len (length list)))
    (loop repeat len
      do
        (rotatef
          (nth (random len) list)
          (nth (random len) list))
      finally
        (return list))))

(defun lottery ()
  (sort (subseq (shuffle (loop for i from 1 to 49 collect i)) 0 6) #'<))

(lottery)
;; => (5 6 17 21 35 37)

关于lisp - 获取彩票号码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24109692/

相关文章:

parameters - LISP 参数绑定(bind)

lisp - 在 lisp 中更改数组值的最佳方法

debugging - 在 lisp 中调试 minimax game awele "oware"

common-lisp - 为什么在Common Lisp中的lambda之前使用#'?

java - 从 Java 执行 lisp 函数

emacs 扩展做系统调用, sleep ,然后重新加载缓冲区

c - 使用 Embeddable Common Lisp 编译文件的正确方法是什么?

tree - Scheme中n叉树的map函数

lisp - 整数lisp的最小值

common-lisp - 在 Common Lisp 中,打印到多个控制台的最佳方法是什么?