問題を解決するためのより簡単な方法がありますが、言語に関する追加の知識が必要です。たとえば、スペースで文字列を分割し、各単語を処理するために正規表現を使用します。map
filter
(define line "xbox 360")
(define (process line)
(map (lambda (word)
(cond ((string->number word) "number")
(else "word")))
(filter (lambda (str)
(not (equal? str "")))
(regexp-split #px"\\s+" line))))
受け取った入力は、入力ファイル内の行を含む文字列であることに注意してください(プロシージャによって返されますfile->lines
)。一般的な考え方は、ファイルを 1 行ずつ読み取り、上記のコード スニペットを使用してそれぞれを順番に処理することです。
コードでもう少し高度な機能を使用しても問題ない場合は、上記の方法でうまくいきます。
編集 :
リストの繰り返しとread-char
(peek-char
最初の文字のみを読み取り、次の文字に進まない not ) のみを使用してバージョンを作成しましたが、これは上記の手順よりもはるかに複雑であることがわかります。
(define (process line)
(let ((port (open-input-string line)))
(let loop ((char (read-char port))
(acc '()))
(cond ((eof-object? char)
(cond ((null? acc) '())
((string->number (list->string acc)) (list "number"))
(else (list "word"))))
((char-whitespace? char)
(cond ((null? acc)
(loop (read-char port) '()))
((string->number (list->string acc))
(cons "number" (loop (read-char port) '())))
(else
(cons "word" (loop (read-char port) '())))))
(else
(loop (read-char port) (cons char acc)))))))
両方のソリューションは、次のテストで期待どおりに機能します。
(process "xbox 360")
> '("word" "number")
(process "1")
> '("number")
(process "a")
> '("word")
(process " ")
> '()
(process "")
> '()
(process " a b 1 a ")
> '("word" "word" "number" "word")