检查球拍功能的括号

时间:2015-04-12 05:38:29

标签: scheme racket

  

我试图创建一个函数,该函数采用表示Racket函数的非空字符串和该字符串的索引。如果索引引用右括号,则返回匹配的左括号的索引。其他错误。

> (find-paren "(if (zero? x) (* 2 x) x)" 11)
false
> (find-paren "(if (zero? x) (* 2 x) x)" 12)
4
> (find-paren "(+ (* 2 (- 5 3)) (/ (+ 4 2) 3))" 14)
8
> (find-paren "(+ (* 2 (- 5 3)) (/ (+ 4 2) 3))" 15)
3
> (find-paren "(+ (* 2 (- 5 3)) (/ (+ 4 2) 3))" 30)
0

我试图以最快的方式做到这一点,所以没有爆炸,子串,字符串 - >列表,字符串 - ith。我已经被困在这个问题上差不多一个小时了。如果字符串是syme​​tric,那么我的函数将起作用:

(define (find-paren expr i)
  (cond [(not (equal? #\) (string-ref expr i))) false]
        [else (- (string-length expr) i)]))

但它不对称。我还创建了一个函数来计算字符在字符串中出现的次数,但是我不确定它是否会有那么多的帮助:

(define (char-count c s)
  (local [(define (loop i count)
            (cond
              [(negative? i) count]
              [(char=? c (string-ref s i))
               (loop (sub1 i) (add1 count))]
              [else
               (loop (sub1 i) count)]))]
    (loop (sub1 (string-length s)) 0)))

在ISL +中,任何帮助都会很棒

1 个答案:

答案 0 :(得分:2)

如果您要使用实际的Racket表达式,您将很快而不是以后需要使用词法分析器将字符串表示形式转换为标记列表。

下面的程序显示了如何找到匹配的左右括号对。 给定该列表,很容易找到与给定右括号匹配的左括号。

如果您的解决方案直接适用于字符串表示,则需要在pair-parens-loop中模仿算法。

; a TOKEN consists of a lexeme (a 'left, 'right or a char)
; and the position from which the lexeme was read.
(define-struct token (lexeme pos))

; left? and right? checks whether the token was a left or right parenthesis respectively.
(define (left? t)  (eq? (token-char t) 'left))
(define (right? t) (eq? (token-char t) 'right))

; lex : string -> list-of-tokens
;   lex the whole string
(define (lex s)
  (lex-loop s 0))

; lex-loop : string natural -> list-of-tokens
;   lex-loop the part of the string that begins with position p
(define (lex-loop s p)
  (cond
    [(= p (string-length s))        '()]
    [(char=? (string-ref s p) #\()  (cons (make-token 'left p)  (lex-loop s (+ p 1)))]
    [(char=? (string-ref s p) #\))  (cons (make-token 'right p) (lex-loop s (+ p 1)))]
    [else                           (lex-loop s (+ p 1))]))

; pair-parens : list-of-tokens -> list-of-list-of-tokens
;   return a list of mathcing left/right tokens
(define (pair-parens ts)
  (pair-parens-loop ts '() '()))

(define (pair-parens-loop ts pending found)
  (cond
    [(empty? ts) found]
    [(left?  (first ts))
     (pair-parens-loop (rest ts) (cons (first ts) pending) found)]
    [(right? (first ts))
     (pair-parens-loop (rest ts) (rest pending) (cons (list (first pending) (first ts)) found))]
    [else (error)]))


;;;
;;; EXAMPLE
;;;

> (lex "(if (zero? x) (* 2 x) x)")
(list
 (make-token 'left 0)
 (make-token 'left 4)
 (make-token 'right 12)
 (make-token 'left 14)
 (make-token 'right 20)
 (make-token 'right 23))


> (pair-parens (lex "(if (zero? x) (* 2 x) x)"))
(list
 (list (make-token 'left 0) (make-token 'right 23))
 (list (make-token 'left 14) (make-token 'right 20))
 (list (make-token 'left 4) (make-token 'right 12)))