在 Scheme 中增加一个字母字符串

Incrementing an alphabetic string in Scheme

我正在尝试在 Scheme 中以编程方式递增纯字母字符串。

像这样"MA",然后"MB",当它达到"MZ"时,它应该变成"MAA"等等,直到"MZZ"然后它应该变成 "MAAA" 所以 on.The "M" 需要添加为我正在做的那种工作的前缀。

我看了这个问题:Incrementing alphabets 这正是我想要的。

但是,我完全不知道从哪里开始。对于初学者,我什至不确定如何在方案中处理 ASCII。我并不期待完整的代码,但如果我能得到一些提示,我将不胜感激。

这是我的实现。注意需要加载SRFI 1,它提供了unfold-right:

(define letters "ABCDEFGHIJKLMNOPQRSTUVWXYZ")

(define (number->letters num)
  (unfold-right negative?
                (lambda (i) (string-ref letters (remainder i 26)))
                (lambda (i) (- (quotient i 26) 1))
                num))

(define (number->tag num)
  (list->string (cons #\M (number->letters num))))

示例:

> (number->tag 0)
"MA"
> (number->tag 18277)
"MZZZ"
> (number->tag 18278)
"MAAAA"

OP 要求解释代码的作用。因此,了解 OP 已经理解 算法 (因为他们已经链接到它),基本上剩下的就是展开操作。

折叠和展开的解释有点冗长,我不想通过解释它们来破坏这个 post,但是可以 "expand" 展开进入等效循环(使用与 unfold-right 的 SRFI 1 reference implementation 相同的变量名称)来表达正在发生的事情:

(define (number->letters num)
  (let lp ((seed num) (ans '()))
    (if (negative? seed)
        ans
        (lp (- (quotient seed 26) 1)
            (cons (string-ref letters (remainder seed 26)) ans)))))

基本上,它构建一个列表,从右到左,每次迭代使用 (string-ref letters (remainder seed 26))(其中 seed 在初始迭代中是 num)。 seed 的值然后在下一次迭代中更新为 (- (quotient seed 26) 1)。当 (negative? seed) 为真时,列表停止。

然后您可能会问为什么要使用展开而不是循环。基本上,在函数式编程中,当 "concept" 可以用更高级别的术语(例如,for-each、map、filter、fold 或 unfold)表示时,使用这些术语可以帮助其他程序员理解代码的作用。在函数式编程上下文中,它有点像 "design patterns"(在面向对象编程中常用)。 :-)