在Scheme中增加字母字符串

时间:2015-02-21 04:18:27

标签: scheme

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

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

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

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

1 个答案:

答案 0 :(得分:2)

这是我的实施。请注意,您需要加载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已经理解算法(因为它们已经链接到它),基本上剩下的就是展开操作。

折叠和展开有点冗长要解释,我不想通过解释它们来破坏这篇文章,但是可以将展开“扩展”到等效循环中(使用与SRFI 1相同的变量名称{ {3}} unfold-right}来表达正在发生的事情:

(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))(在初始迭代中seednum)。然后,seed的值会更新为(- (quotient seed 26) 1)以进行下一次迭代。 (negative? seed)为真时,列表会停止。

然后你可能会问为什么会使用展开而不是循环。基本上,在函数式编程中,当“概念”可以用更高级的术语表达时(例如,for-each,map,filter,fold或unfold),使用这些术语有助于其他程序员理解代码的作用。在函数式编程上下文中,它有点像“设计模式”(在面向对象编程中常用)。 : - )