Loops Lisp-Flag(bandera)don';功能
我试图写一个函数来确定一个单词是否是回文。我这样做,但它总是返回“不是回文”。我不知道发生了什么事Loops Lisp-Flag(bandera)don';功能,loops,common-lisp,conditional-statements,palindrome,clisp,Loops,Common Lisp,Conditional Statements,Palindrome,Clisp,我试图写一个函数来确定一个单词是否是回文。我这样做,但它总是返回“不是回文”。我不知道发生了什么事 (defun palindromo (X) (setq i 0) (setq j (- (length X) 1)) (setq bandera 0) (loop while (< j i) do (when (char= (char X i) (char X j)) (+ i 1)
(defun palindromo (X)
(setq i 0)
(setq j (- (length X) 1))
(setq bandera 0)
(loop while (< j i)
do
(when (char= (char X i) (char X j))
(+ i 1)
(- j 1)
(setq bandera 1))
(unless (char/= (char X i) (char X j))
(setq bandera 0)
)
)
(cond
((equal 0 bandera) (write "Is not a palindrome"))
((equal 1 bandera) (write "Is a palindrome"))
)
)
(德芬回文(X)
(setq i 0)
(设定值j(-(长度X)1))
(setq波段0)
(循环时(
如何解决此问题?循环问题
循环终止测试是
while(
,但您之前将i
和j
分别设置为第一个和最后一个字符的索引。这意味着(实际上,不需要外部定义的循环来确定字符串是否为回文。[备注:我一开始就这么认为。但正如@coredump和@jkiiski所指出的,reverse
函数会减慢过程,因为它会复制整个字符串一次。]
使用:
[此函数将比您的代码更高效
如果s是回文的,则返回T
,否则返回NIL
(不正确,它只会节省您的编写工作量,但效率低于使用循环的过程)
详细版本应为:
(defun palindromep (s)
(let ((result (string= s (reverse s))))
(write (if result
"Is a palindrome"
"Is not a palindrome"))
result))
写入您希望的答案,但返回T
或NIL
返回T
或NIL
的测试函数的命名约定是将“谓词”的名称以p
结尾
反向功能的性能不如@coredump建议的while循环
这是我的初学者尝试测试速度[不推荐]:
;; Improved loop version by @coredump:
(defun palindromep-loop (string)
(loop with max = (1- (length string))
for i from 0
for j downfrom max
while (< i j)
always (char= (char string i)
(char string j))))
;; the solution with reverse
(defun palindromep (s)
(string= s (reverse s)))
;; the test functions test over and over the same string "abcdefggfedcba"
;; 10000 times over and over again
;; I did the repeats so that the measuring comes at least to the milliseconds
;; range ... (but it was too few repeats still. See below.)
(defun test-palindrome-loop ()
(loop repeat 10000
do (palindromep-loop "abcdefggfedcba")))
(time (test-palindrome-loop))
(defun test-palindrome-p ()
(loop repeat 10000
do (palindromep "abcdefggfedcba")))
(time (test-palindrome-p))
;; run on SBCL
[55]> (time (test-palindrome-loop))
Real time: 0.152438 sec.
Run time: 0.152 sec.
Space: 0 Bytes
NIL
[56]> (time (test-palindrome-p))
Real time: 0.019284 sec.
Run time: 0.02 sec.
Space: 240000 Bytes
NIL
;; note: this is the worst case that the string is a palindrome
;; for `palindrome-p` it would break much earlier when a string is
;; not a palindrome!
;;通过@coredump改进了循环版本:
(defun回文循环(字符串)
(循环最大值=(1-(长度字符串))
我从0开始
对于从max向下的j
而((时间(测试回文循环))
实时:0.152438秒。
运行时间:0.152秒。
空间:0字节
无
[56]>(时间(test-palindrome-p))
实时:0.019284秒。
运行时间:0.02秒。
空间:240000字节
无
;注意:这是最坏的情况,字符串是回文
;对于回文-p,当一个字符串被删除时,它会更早断开
不是回文!
这是@coredump测试函数速度的尝试:
(lisp-implementation-type)
"SBCL"
(lisp-implementation-version)
"1.4.0.75.release.1710-6a36da1"
(machine-type)
"X86-64"
(defun palindromep-loop (string)
(loop with max = (1- (length string))
for i from 0
for j downfrom max
while (< i j)
always (char= (char string i)
(char string j))))
(defun palindromep (s)
(string= s (reverse s)))
(defun test-palindrome-loop (s)
(sb-ext:gc :full t)
(time
(loop repeat 10000000
do (palindromep-loop s))))
(defun test-palindrome-p (s)
(sb-ext:gc :full t)
(time
(loop repeat 10000000
do (palindromep s))))
(defun rand-char ()
(code-char
(+ #.(char-code #\a)
(random #.(- (char-code #\z) (char-code #\a))))))
(defun generate-palindrome (n &optional oddp)
(let ((left (coerce (loop repeat n collect (rand-char)) 'string)))
(concatenate 'string
left
(and oddp (list (rand-char)))
(reverse left))))
(let ((s (generate-palindrome 20)))
(test-palindrome-p s)
(test-palindrome-loop s))
Evaluation took:
4.093 seconds of real time
4.100000 seconds of total run time (4.068000 user, 0.032000 system)
[ Run times consist of 0.124 seconds GC time, and 3.976 seconds non-GC time. ]
100.17% CPU
9,800,692,770 processor cycles
1,919,983,328 bytes consed
Evaluation took:
2.353 seconds of real time
2.352000 seconds of total run time (2.352000 user, 0.000000 system)
99.96% CPU
5,633,385,408 processor cycles
0 bytes consed
(lisp实现类型)
“SBCL”
(lisp实现版本)
“1.4.0.75.版本1710-6a36da1”
(机器类型)
“X86-64”
(defun回文循环(字符串)
(循环最大值=(1-(长度字符串))
我从0开始
对于从max向下的j
而(
我从中学到的是:
-更严格地测试,必要时重复(秒范围)
-进行随机生成,然后并行测试
非常感谢您提供了一个很好的例子@coredump!以及@jkiiski!@Gwang JinKimREVERSE
复制整个字符串,这比仅使用两个索引循环并在第一次不匹配时退出效率要低得多。@Gwang JinKim循环版本需要较少的测试。string=
在最坏的情况下,将测试e当两个索引交叉时,循环版本可以停止(因此它只测试字符串的一半与另一半)@Gwang JinKim如果我在我的机器上计时,循环版本只需要反转版本的一半时间和一半周期。你可能会得到不同的结果,因为重复次数太少,结果几乎是随机的。试着将重复次数从10000
更改为100000000
,并且不同的e应该变得更清晰了。只有10000次迭代,我得到了大约1ms,这不够精确。我尝试了更长的回文(非常量回文),更多的重复,并在测试前调用gc:@Gwang JinKim No
(defun palindromep (s)
(string= s (reverse s)))
(defun palindromep (s)
(let ((result (string= s (reverse s))))
(write (if result
"Is a palindrome"
"Is not a palindrome"))
result))
;; Improved loop version by @coredump:
(defun palindromep-loop (string)
(loop with max = (1- (length string))
for i from 0
for j downfrom max
while (< i j)
always (char= (char string i)
(char string j))))
;; the solution with reverse
(defun palindromep (s)
(string= s (reverse s)))
;; the test functions test over and over the same string "abcdefggfedcba"
;; 10000 times over and over again
;; I did the repeats so that the measuring comes at least to the milliseconds
;; range ... (but it was too few repeats still. See below.)
(defun test-palindrome-loop ()
(loop repeat 10000
do (palindromep-loop "abcdefggfedcba")))
(time (test-palindrome-loop))
(defun test-palindrome-p ()
(loop repeat 10000
do (palindromep "abcdefggfedcba")))
(time (test-palindrome-p))
;; run on SBCL
[55]> (time (test-palindrome-loop))
Real time: 0.152438 sec.
Run time: 0.152 sec.
Space: 0 Bytes
NIL
[56]> (time (test-palindrome-p))
Real time: 0.019284 sec.
Run time: 0.02 sec.
Space: 240000 Bytes
NIL
;; note: this is the worst case that the string is a palindrome
;; for `palindrome-p` it would break much earlier when a string is
;; not a palindrome!
(lisp-implementation-type)
"SBCL"
(lisp-implementation-version)
"1.4.0.75.release.1710-6a36da1"
(machine-type)
"X86-64"
(defun palindromep-loop (string)
(loop with max = (1- (length string))
for i from 0
for j downfrom max
while (< i j)
always (char= (char string i)
(char string j))))
(defun palindromep (s)
(string= s (reverse s)))
(defun test-palindrome-loop (s)
(sb-ext:gc :full t)
(time
(loop repeat 10000000
do (palindromep-loop s))))
(defun test-palindrome-p (s)
(sb-ext:gc :full t)
(time
(loop repeat 10000000
do (palindromep s))))
(defun rand-char ()
(code-char
(+ #.(char-code #\a)
(random #.(- (char-code #\z) (char-code #\a))))))
(defun generate-palindrome (n &optional oddp)
(let ((left (coerce (loop repeat n collect (rand-char)) 'string)))
(concatenate 'string
left
(and oddp (list (rand-char)))
(reverse left))))
(let ((s (generate-palindrome 20)))
(test-palindrome-p s)
(test-palindrome-loop s))
Evaluation took:
4.093 seconds of real time
4.100000 seconds of total run time (4.068000 user, 0.032000 system)
[ Run times consist of 0.124 seconds GC time, and 3.976 seconds non-GC time. ]
100.17% CPU
9,800,692,770 processor cycles
1,919,983,328 bytes consed
Evaluation took:
2.353 seconds of real time
2.352000 seconds of total run time (2.352000 user, 0.000000 system)
99.96% CPU
5,633,385,408 processor cycles
0 bytes consed