检查球拍功能的括号
Checking parenthesis of racket function
I'm trying to make a function that takes a non-empty string representing a Racket function and an index of that string. If the index refers to a right parenthesis, then the index of the matching left parentheses is returned. Else false.
> (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
我正在尝试以尽可能最快的方式完成此操作,因此不会出现爆炸、子字符串、字符串-> 列表、字符串。` 我已经在这个问题上停留了将近一个小时。如果字符串是对称的,那么我的函数将起作用:
(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+
中的任何帮助都会很棒
如果您要使用实际的 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)))
I'm trying to make a function that takes a non-empty string representing a Racket function and an index of that string. If the index refers to a right parenthesis, then the index of the matching left parentheses is returned. Else false.
> (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
我正在尝试以尽可能最快的方式完成此操作,因此不会出现爆炸、子字符串、字符串-> 列表、字符串。` 我已经在这个问题上停留了将近一个小时。如果字符串是对称的,那么我的函数将起作用:
(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+
中的任何帮助都会很棒如果您要使用实际的 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)))