【问题标题】:Simulating binary addition - DrRacket Intermediate Student with Lambda模拟二进制加法 - DrRacket 中级学生与 Lambda
【发布时间】:2019-11-06 11:53:37
【问题描述】:

正如标题所说,我是一名大学生,使用 DrRacket 和 Intermediate Student With Lambda 语言。我的任务是一种算法,给定一个包含二进制数的字符串,将下一个数字显示为输出,仅对二进制表示进行操作(因此,不转换为十进制,添加 +1 并重新转换为二进制)。自从我在国外以来,我已经跳过了前三周的课程,现在我正在努力追赶,据我所知,教授现在的主要目标是让我们练习递归(此外,我们是不允许使用像 do 那样的列表或循环,只能使用通过 lambda 表达式定义的函数。
我在作业中尝试了几次,现在我的代码如下所示:

; function called by the user

(define bin-succ
  (lambda (bin)    ; not-empty string of "0"s and "1"s
    (let ( (k (- (string-length bin) 1)) (post (make-string 0)) )
      (position bin k post)
      )
    )
  )

; actual recursive function of the code: it searches from the least significant
; bit to the most significant bit if there is any "0" in the string

(define position
  (lambda (bin k post)
    (cond ( (= k -1)
            (string-append "1" post) )
          ( (char=? (string-ref bin k) #\0)
            (string-append (substring bin 0 k) "1" post) )
          ( (char=? (string-ref bin k) #\1)
            ((position bin (- k 1) post)
            (string-append "0" post)) )
          )
    )
  )

目前,该算法适用于最后一位为 0 的数字,例如 0、10、11010 等...,但是当我声明一个以 1 结尾的数字作为输入时,程序会突出显示的最后一部分尤其是代码

((position bin (- k 1) post)
            (string-append "0" post))

并返回错误:

function call: expected a function after the open parenthesis, but received "11"

我尝试使用 begin 在由第三个 cond 的情况调用的不同函数中创建表达式列表,这将重新调用该函数position,从而使算法再次递归,但没有运气,因为它说 begin 不是定义的函数。
我可能忽略了一些非常简单的事情(主要是由于我跳过了入门课程)或者我可能以不正确的心态解决了这个问题,但无论哪种方式我都被困住了,我感谢任何有用的输入。
最后一个问题:在最后一个 cond 案例中使用 else 也不被接受,谁能解释我为什么? DrRacket 使用多种语言的事实让我非常困惑,因为许多在线文档不适用于我当前的设置。

【问题讨论】:

  • (position bin (- k 1) post) 显然返回“11”,所以它就像调用("11" (string-append "0" post))。预期的结果是什么?
  • 也许你应该把你的标题改成“使用字符串运算符模拟二进制加法”或模拟二进制加法。
  • @Sylwester 现在我已经理解了我的错误,但是在询问的那一刻我无意中尝试设计这个程序,因为它更像是一个“while”循环(类似于 直到你找到数字中的0,只需继续添加0即可发布并向左跳过)。阅读您的评论帮助我更好地理解了我应该如何重新安排我的心态来学习这门语言,谢谢。
  • @DenisD'Ambrosi Scheme 没有循环结构作为原语。例如。 do 只是成为 letrec 的语法,它会立即被调用,而递归是让它做更多转的原因。如果您被允许执行(begin expr1 expr2) expr1 只会生效,而只有expr2 的结果才是结果。学生语言可能会避免副作用,所以 begin 没有意义。

标签: recursion scheme conditional-statements racket


【解决方案1】:

到目前为止,也许您一直在查看 Racket 文档而不是 ISL+(使用 Lambda 的中级学生)文档?有关 ISL+ 文档,请参阅 https://docs.racket-lang.org/htdp-langs/intermediate-lam.html。在 DrRacket 中的一个术语上按 f1 会将您带到您正在使用的语言上下文中的文档。

((position bin (- k 1) post)
            (string-append "0" post))

这是功能应用程序。您正在尝试应用(作为参数):(string-append "0" post)函数 (position bin (- k 1) post)。然而,position 返回一个 String

您可以简单地将新帖子传递给递归调用。你也可以在最后一个子句中使用else。这是工作代码:

; String -> String
(define (bin-succ bin)
  (position bin (- (string-length bin) 1) ""))

; String Number String -> String
(define (position bin k post)
  (cond  [(= k -1)
          (string-append "1" post)]
         [(char=? (string-ref bin k) #\0)
          (string-append (substring bin 0 k) "1" post)]
         [else
          (position bin (- k 1) (string-append "0" post))]))

一个更干净的解决方案是有一个计数器:

(define (bin-succ bin)
  (cond [(string=? bin "1") "10"]
        [(string=? (last bin) "0") (string-append (all-but-last bin) "1")]
        [else (string-append (bin-succ (all-but-last bin)) "0")]))

(define (last str)
  (substring str (sub1 (string-length str)) (string-length str)))

(define (all-but-last str)
  (substring str 0 (sub1 (string-length str))))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-12
    • 1970-01-01
    • 2023-02-21
    • 2015-08-05
    • 2018-11-01
    • 2020-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多