【问题标题】:FizzBuzz Lambda Only Returning Last IntegerFizzBu​​zz Lambda 仅返回最后一个整数
【发布时间】:2015-08-29 05:36:43
【问题描述】:

我是 Scheme 的新手,正在尝试编写一个示例 FizzBu​​zz 函数。以下是规则:

  • 如果一个数字可以被 3 和 5 整除,请改为“fizzbuzz”
  • 如果一个数字可以被 3 整除,则改为“fizz”
  • 如果一个数字可以被 5 整除,则改为“buzz”
  • 否则请说出号码。

这是我的代码:

(define (fizzbuzz n)
  (print (fizzbuzz1 1 n)))

;; Helper function for fizzbuzz
(define (fizzbuzz1 i n)
  (cond [(and (= 0 (modulo i 3)) (= 0 (modulo i 5)))
         " fizzbuzz "]
        [(= 0 (modulo i 3))
         " fizz "]
        [(= 0 (modulo i 5))
         " buzz "]
        (i))

  (cond [(< i n) (fizzbuzz1 (+ 1 i) n)]))

(fizzbuzz 21)

但它显示的只是“21”(来自测试用例)。有人可以帮帮我吗?

编辑:稍微修正了我的代码并更新了它,但现在我得到的是#&lt;void&gt; 打印出来。

【问题讨论】:

    标签: scheme racket fizzbuzz


    【解决方案1】:

    您的函数实际上计算了从 1 到 21 的所有数字的正确结果,只是您不做任何事情将它们显示在输出中,或者以某种方式收集它们,以便它们在内部计算后“丢失” fizzbuzz1(初始的print只打印fizzbuzz1的结果,即#&lt;void&gt;)。如果你想显示它们(通过使用display 而不是print,以获得更美观的结果),你可以在cond 的每个分支中放置一个display,例如像这样(并注意如果你想学习这些语言,你绝对应该开始以一种干净的方式缩进你的函数!):

    (define (fizzbuzz n)
      (fizzbuzz1 1 n))
    
    (define (fizzbuzz1 i n)
      (cond [(and (= 0 (modulo i 3) ) (= 0 (modulo i 5) ))
             (display " fizzbuzz ")]
            [(= 0 (modulo i 3))
             (display " fizz ")]
            [(= 0 (modulo i 5))
             (display " buzz ")]
            [else (display i) (display " ")]
            )
      (cond [(< i n) (fizzbuzz1 (+ 1 i) n)])
      )
    

    还要注意最后的#void 是由于fizzbuzz 的初始定义中的打印函数的值,如果你删除它,它会消失。

    另一种,更优雅, 的可能性是在计算字符串时收集所有字符串,例如使用string-append,就像在这个函数中一样:

    (define (fizzbuzz n)
       (fizzbuzz1 1 n))
    
    (define (fizzbuzz1 i n)
      (if (> i n)
          ""
          (string-append
           (cond [(and (= 0 (modulo i 3) ) (= 0 (modulo i 5) ))
                  " fizzbuzz "]
                 [(= 0 (modulo i 3))
                  " fizz "]
                 [(= 0 (modulo i 5))
                  " buzz "]
                 [else (~a " " i " ")]
                 )
           (fizzbuzz1 (+ 1 i) n))))
    

    请注意,在这种情况下,如果您的程序在交互式环境(如 DrRacket)中使用,则无需“打印”结果。

    编辑

    此解决方案的效率不如第一个解决方案,但如果您需要将所有结果收集到某个结构中以将它们用于其他任务,则应该让您了解程序应该具有哪种结构。作为另一个示例,您可以使用cons 收集它们,例如,生成字符串列表而不是单个字符串(只需将'() 替换为"",将cons 替换为string-append)。

    【讨论】:

    • 你说string-append 方法更优雅,但当我看到它时我会畏缩。这就像在循环中看到字符串+=(而不是使用StringBuilder),这是画家施莱米尔的问题。
    • 我编辑了答案,但我认为学习递归的人应该首先学习如何编程,然后如何高效地编程。当然,您的经历可能与我的不同。
    • 您可以使用cons 进行递归。使用append(或与之相关的任何东西)进行递归只是要求画家施莱米尔。 :-) 例如,您可以组合一个字符串列表,然后对结果执行一个string-append(使用apply)。
    • 这个答案基本正确,但我发现缩进建议很糟糕(一般来说,一行不应该有唯一的括号!请参阅canonical Scheme style guide)。此外,构建这样的字符串并不适合手头的任务。您确实应该在cond 中显示它。
    • 我正在 DrRacket 中编写这个程序。我不明白的是什么时候需要打印声明,什么时候不需要。因为几天前我写了一个不同的函数,它返回列表中的最大数。在那种情况下,我不需要告诉它显示到控制台,它只是自己做的。
    【解决方案2】:

    此外,如果您使用的是球拍(因为您使用了球拍标签),您可能会发现球拍的for 结构在这里很有用。

    使用for(如Renzo所说,使用display)你可以这样写fizzbuzz:

    #lang racket
    
    (define (fizzbuzz n)
      (for ([i (in-range n)])
        (cond [(and (= 0 (modulo i 3)) (= 0 (modulo i 5)))
               (displayln "fizzbuzz")]
              [(= 0 (modulo i 3))
               (displayln "fizz")]
              [(= 0 (modulo i 5))
               (displayln "buzz")]
              [else (displayln i)])))
    
    (fizzbuzz 21)
    

    另一种选择是使用for/list,类似于for,但将结果累加到一个列表中:

    #lang racket
    
    (define (fizzbuzz n)
      (for/list ([i (in-range n)])
        (cond [(and (= 0 (modulo i 3)) (= 0 (modulo i 5)))
               "fizzbuzz"]
              [(= 0 (modulo i 3))
               "fizz"]
              [(= 0 (modulo i 5))
               "buzz"]
              [else i])))
    
    (fizzbuzz 21)
    (apply string-append (fizzbuzz 21))
    

    【讨论】:

    • 感谢您的回答。我将研究 Racket 的 for 循环。我们还没有在课堂上讲过它,所以我不确定我是否可以在这个作业中使用它。
    猜你喜欢
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-06
    • 2012-02-21
    • 2018-07-18
    相关资源
    最近更新 更多