0

I was thinking a way to create a function that detects a palindrome without using reverse... I thought I would be clever and do a condition where substring 0 to middle equals substring end to middle. I;ve found out that it only works on words with 3 letters "wow" because "w" = "w". But if the letters are like "wooow", wo doesn't equal ow. What is a way to detect palindrome without using a reverse function?

Hint or solutions might be very helpful

(define (palindrome? str)
(cond
((equal? (substring str 0 (- (/ (string-length str) 2) 0.5))
         (substring str (+ (/ (string-length str) 2) 0.5) (string-length str))) str)
 (else false)))

Oh and I'm using beginner language so I can't use stuff like map or filter

yes I know this is a very useless function haha

Óscar López
  • 232,561
  • 37
  • 312
  • 386
user2113651
  • 153
  • 2
  • 10
  • I don't know your language or anything about it functions. But if you have something that can index the letters or the words with a variable and loop it. So for each letter in the first half of the string if string.index(letter) - string.index(-letter). So the first letter = first letter from the end, second letter = second from the end and so on until you reach mid. Although you will have to add something to handle even and odd length words. – user2140261 Apr 02 '13 at 22:58

3 Answers3

1

It's possible to solve this problem by messing around with the string's characters in a given index. The trick is to use string-ref wisely. Here, let me give you some hints pointing to a solution that will work with the beginner's language :

; this is the main procedure
(define (palindrome? s)
  ; it uses `loop` as a helper
  (loop <???> <???> <???>))

; loop receives as parameters:
; `s` : the string
; `i` : the current index, starting at 0
; `n` : the string's length
(define (loop s i n)
  (cond (<???>  ; if `i` equals `n`
         <???>) ; then `s` is a palindrome
        (<???>  ; if the char at the current index != its opposite (*)
         <???>) ; then `s` is NOT a palindrome
        (else   ; otherwise
         (loop <???> <???> <???>)))) ; advance the recursion over `i`

Of course, the interesting part is the one marked with (*). Think of it, a string is a palindrome if the char at the 0 index equals the char at the n-1 index (n being the string's length) and the char at the 1 index equals the char at the n-2 index, and so on. In general, if it's true that the char at the i index equals the char at the n-i-1 index (its "opposite") for all i, then we can conclude that the string is a palindrome - but if a single pair of opposite chars is not equal to each other, then it's not a palindrome.

As a further optimization, notice that you don't need to traverse the whole string, it's enough to test the characters up to the half of the string's length (this is explained in Chris' answer) - intuitively, you can see that if the char at i equals the char at n-i-1, then it follows that the char at n-i-1 equals the char at i, so there's no need to perform the same test two times.

Try to write the procedures on your own, and don't forget to test them:

(palindrome? "")
=> #t
(palindrome? "x")
=> #t
(palindrome? "axa")
=> #t
(palindrome? "axxa")
=> #t

(palindrome? "axc")
=> #f
(palindrome? "axca")
=> #f
(palindrome? "acxa")
=> #f
(palindrome? "axcta")
=> #f
Óscar López
  • 232,561
  • 37
  • 312
  • 386
1

Here is a creative answer

(define (palindrome list)
  (let halving ((last list) (fast list) (half '()))
    (cond ((null? fast)       (equal? half last))
          ((null? (cdr fast)) (equal? half (cdr last)))
          (else (halving (cdr last) (cddr fast)
                         (cons (car last) half))))))

It travels halfway down the list (using fast to find the end), builds up a list of the first half and then simply uses equal? on half with the remainder of list.

GoZoner
  • 67,920
  • 20
  • 95
  • 145
0

Simple.

  1. For each i, from 0 to floor(length / 2), compare the character at index i and at index length - i - 1.
  2. If mismatch, return false.
  3. Otherwise, if the loop runs out, return true.

Skeletal code:

(define (palindrome? str)
  (define len (string-length str))
  (define halfway <???>)
  (let loop ((i 0))
    (cond ((>= i halfway) #t)
          ((char=? <???> <???>)
           (loop (+ i 1)))
          (else #f))))
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • 1
    This was what I commented about. I can't verify the code but the logic is solid. – user2140261 Apr 02 '13 at 23:10
  • uh it says loop nor let is defined? is it because I'm using drracket?? – user2113651 Apr 02 '13 at 23:26
  • 1
    @user2113651 Chris' solution uses a "named let", which is not available in the beginner's language. See my answer for hints on how to solve the problem with the procedures available for your language. – Óscar López Apr 02 '13 at 23:32