我正在尝试以编程方式在Scheme中增加一个纯字母字符串。
像这样" MA"然后" MB"当它到达" MZ"时,它应该成为" MAA"直到" MZZ"然后它应该成为" MAAA"等等。" M"需要添加为我正在做的工作的前缀。
我看了这个问题:Incrementing alphabets这正是我想要的。
但是,我完全不知道从哪里开始。对于初学者,我甚至不确定如何处理方案中的ASCII。我并不期待整个代码,但如果我得到一些提示,我将不胜感激。
答案 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))
(在初始迭代中seed
为num
)。然后,seed
的值会更新为(- (quotient seed 26) 1)
以进行下一次迭代。 (negative? seed)
为真时,列表会停止。
然后你可能会问为什么会使用展开而不是循环。基本上,在函数式编程中,当“概念”可以用更高级的术语表达时(例如,for-each,map,filter,fold或unfold),使用这些术语有助于其他程序员理解代码的作用。在函数式编程上下文中,它有点像“设计模式”(在面向对象编程中常用)。 : - )