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 JinKim
REVERSE
复制整个字符串,这比仅使用两个索引循环并在第一次不匹配时退出效率要低得多。@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