LISP 递归三角形
LISP Recursive Triangle
我的递归调用似乎不起作用,我正在尝试给定一个整数来制作一个三角形,在你们的帮助下,我终于能够在同一行打印出正确数量的字符串1 行的次数。在打印该行的最后,我有一个递归调用,它调用 triangle 来生成另一行,一个字符更短。由于某种原因,此电话似乎永远无法接通。请在下面找到代码,在此先感谢大家的帮助,非常感谢!
注意:附带说明一下,有什么方法可以停止 Lisp 中类似于 return 语句的函数吗?我希望递归在 k = 1 时停止,而不是继续到 k = 0。
(defun newTriangle (k)
(cond ((<= k 0) (princ '(Nope)))
((or (= k 1) (= k -1)) (princ 'a))
((> k 0) (make-string k :initial-element #\a))
(newTriangle (- k 1))))
(print (newTriangle 3))
示例输出三角形(3)
aaa
aa
a
示例输出三角形(-3)
aaa
aa
a
首先,您需要确定 newTriangle
正在做什么。调用 (print (newTriangle 3))
建议 newTriangle
应该 return 一个 字符串 ,然后通过调用 print
打印出来。但是,newTriangle
的 OP 定义既是打印输出,又是 return 将三角形的单行作为字符串。
从未达到对 newTriangle
的递归调用,因为在达到此行之前已经用尽了 k
值的所有可能情况。由于 k
只能小于零、等于零或大于零,并且由于在到达递归调用之前测试了所有这些情况,因此永远不会到达。另请注意,OP 代码的 cond
语句的最后部分语法错误。 cond
分支中的第一个表达式是一个测试,惯例是在此处使用 t
作为一个分支,如果到达则将始终对其进行评估。但是,这里不需要这么多案例。
假设 newTriangle
函数不应该 return 一个字符串,而是应该打印一个三角形作为 side-effect,它应该做什么?如果输入的数字大于0,它应该打印一行字符数等于输入数字的行,然后在输入减一的情况下调用自己;否则它什么都不做:
(defun print-triangle (k)
(when (> k 0)
(princ (make-string k :initial-element #\a))
(terpri)
(print-triangle (- k 1))))
这个定义被命名为 print-triangle
以强调它将三角形打印为 side-effect,并且因为 kebab-case 在 Lisps 中是惯用的,而 camelCase 不是。请注意,每次使用大于零的输入调用 print-triangle
时,都会 打印一个正确长度的字符串 ,然后打印一个换行符(使用 obscurely-named terpri
,它只是将换行符写入当前输出流),然后再次调用 print-triangle
,k
减 1。
示例 REPL 交互:
CL-USER> (print-triangle 3)
aaa
aa
a
NIL
如果目标是 return 一个字符串,一种方法是调用一个将结果保存在参数中的辅助函数:
(defun new-triangle (k)
(build-triangle k ""))
(defun build-triangle (k result)
(if (> k 0)
(build-triangle (- k 1)
(concatenate 'string
result
(make-string k :initial-element #\a)
(string #\newline)))
result))
这里,new-triangle
接受一个整数参数,并调用 build-triangle
,在 result
位置传递整数参数和一个空字符串。 build-triangle
函数的操作与之前的 print-triangle
非常相似,但不是打印行,而是将它们与 result
连接起来,连同包含换行符的字符串。 build-triangle
完成后,result
字符串被 return 编辑为 new-triangle
。请注意,只需从 REPL 调用 new-triangle
就会将结果字符串 打印为数据 (即,带引号);在 new-triangle
的结果上调用 print
会将字符串打印为数据,return 会打印字符串。要查看不带引号打印的字符串,可以使用format
;或者您可以使用 princ
打印不带引号的字符串,而 return 打印字符串本身:
CL-USER> (new-triangle 3)
"aaa
aa
a
"
CL-USER> (print (new-triangle 3))
"aaa
aa
a
"
"aaa
aa
a
"
CL-USER> (format t "~A" (new-triangle 3))
aaa
aa
a
NIL
CL-USER> (princ (new-triangle 3))
aaa
aa
a
"aaa
aa
a
"
我的递归调用似乎不起作用,我正在尝试给定一个整数来制作一个三角形,在你们的帮助下,我终于能够在同一行打印出正确数量的字符串1 行的次数。在打印该行的最后,我有一个递归调用,它调用 triangle 来生成另一行,一个字符更短。由于某种原因,此电话似乎永远无法接通。请在下面找到代码,在此先感谢大家的帮助,非常感谢!
注意:附带说明一下,有什么方法可以停止 Lisp 中类似于 return 语句的函数吗?我希望递归在 k = 1 时停止,而不是继续到 k = 0。
(defun newTriangle (k)
(cond ((<= k 0) (princ '(Nope)))
((or (= k 1) (= k -1)) (princ 'a))
((> k 0) (make-string k :initial-element #\a))
(newTriangle (- k 1))))
(print (newTriangle 3))
示例输出三角形(3)
aaa
aa
a
示例输出三角形(-3)
aaa
aa
a
首先,您需要确定 newTriangle
正在做什么。调用 (print (newTriangle 3))
建议 newTriangle
应该 return 一个 字符串 ,然后通过调用 print
打印出来。但是,newTriangle
的 OP 定义既是打印输出,又是 return 将三角形的单行作为字符串。
从未达到对 newTriangle
的递归调用,因为在达到此行之前已经用尽了 k
值的所有可能情况。由于 k
只能小于零、等于零或大于零,并且由于在到达递归调用之前测试了所有这些情况,因此永远不会到达。另请注意,OP 代码的 cond
语句的最后部分语法错误。 cond
分支中的第一个表达式是一个测试,惯例是在此处使用 t
作为一个分支,如果到达则将始终对其进行评估。但是,这里不需要这么多案例。
假设 newTriangle
函数不应该 return 一个字符串,而是应该打印一个三角形作为 side-effect,它应该做什么?如果输入的数字大于0,它应该打印一行字符数等于输入数字的行,然后在输入减一的情况下调用自己;否则它什么都不做:
(defun print-triangle (k)
(when (> k 0)
(princ (make-string k :initial-element #\a))
(terpri)
(print-triangle (- k 1))))
这个定义被命名为 print-triangle
以强调它将三角形打印为 side-effect,并且因为 kebab-case 在 Lisps 中是惯用的,而 camelCase 不是。请注意,每次使用大于零的输入调用 print-triangle
时,都会 打印一个正确长度的字符串 ,然后打印一个换行符(使用 obscurely-named terpri
,它只是将换行符写入当前输出流),然后再次调用 print-triangle
,k
减 1。
示例 REPL 交互:
CL-USER> (print-triangle 3)
aaa
aa
a
NIL
如果目标是 return 一个字符串,一种方法是调用一个将结果保存在参数中的辅助函数:
(defun new-triangle (k)
(build-triangle k ""))
(defun build-triangle (k result)
(if (> k 0)
(build-triangle (- k 1)
(concatenate 'string
result
(make-string k :initial-element #\a)
(string #\newline)))
result))
这里,new-triangle
接受一个整数参数,并调用 build-triangle
,在 result
位置传递整数参数和一个空字符串。 build-triangle
函数的操作与之前的 print-triangle
非常相似,但不是打印行,而是将它们与 result
连接起来,连同包含换行符的字符串。 build-triangle
完成后,result
字符串被 return 编辑为 new-triangle
。请注意,只需从 REPL 调用 new-triangle
就会将结果字符串 打印为数据 (即,带引号);在 new-triangle
的结果上调用 print
会将字符串打印为数据,return 会打印字符串。要查看不带引号打印的字符串,可以使用format
;或者您可以使用 princ
打印不带引号的字符串,而 return 打印字符串本身:
CL-USER> (new-triangle 3)
"aaa
aa
a
"
CL-USER> (print (new-triangle 3))
"aaa
aa
a
"
"aaa
aa
a
"
CL-USER> (format t "~A" (new-triangle 3))
aaa
aa
a
NIL
CL-USER> (princ (new-triangle 3))
aaa
aa
a
"aaa
aa
a
"