2011-11-05 38 views
0

例如字符頻率,如果我輸入字符的序列發現在共同口齒不清

「世界你好」 H = 1個E = 1 L = 3 O - 2 R = 1 W = 1 d = 1

能有人幫我

我發現這個code在線,但我不明白我想要一個簡單的一個

(defun letter-freq (file) 
(with-open-file (stream file) 
    (let ((str (make-string (file-length stream))) 
     (arr (make-array 256 :element-type 'integer :initial-element 0))) 
    (read-sequence str stream) 
    (loop for c across str do (incf (aref arr (char-code c)))) 
    (loop for c from 32 to 126 for i from 1 do 
     (format t "~c: ~d~a" 
     (code-char c) (aref arr c) 
     (if (zerop (rem i 8)) #\newline #\tab)))))) 

(letter-freq "test.lisp") 

回答

1

此代碼是不是很難理解。它打開文件將其讀入一個字符串。與此同時,它也使數組保持結果(大小256,因爲理論上你可能有128以上的非打印字符,我猜)。然後它遍歷數組,並增加數組中相應的元素。例如,'a'是32,因此當它找到'a'時,它將增加數組元素32.

最後,它遍歷可打印字符結果並將其打印出來。

1

我傾向於同意drysdam。我已經在一段時間內沒有觸及過任何Common Lisp代碼,並且能夠按照他所描述的一般理解閱讀這個例子。

我不知道你用的是什麼樣的Lisp的環境,但即使是在裸CL REPL(讀的eval打印循環)你可以要求系統(describe 'some-unknown-symbol)。如果你碰巧是「被迫」使用Emacs它有SLIME y gobful功能。

我看到這是你今天的第二個lisp相關問題。也許最好打一些book

+1

是的,我強烈推薦這本書。事實上,我幾乎沒有做過任何真正的CL編程,因爲我讀了那本書,所以我仍然可以理解引用的代碼。 – drysdam

4

上述代碼對於ASCII字符非常具體。如果你想爲任何可能的字符做同樣的事情,你可以使用散列表。

(defun letter-freq (file) 
    (with-open-file (stream file) 
    (let ((str (make-string (file-length stream))) 
      (ht (make-hash-table))) 
     (read-sequence str stream) 
     (loop :for char :across str :do 
     (incf (gethash char ht 0))) 
     (maphash (lambda (k v) 
       (format t "[email protected]: ~D~%" k v)) 
       ht)))) 

[email protected]格式指令打印charaсter彷彿prin1

+0

您的閱讀文件的方法不好,特別是如果您的文件可能有非ascii字符。文件長度以字節爲單位返回長度,但字符可以是一個或多個字節。 [編輯出的格式不正確的示例代碼] 更好的是循環讀取線。 – angus

+0

我同意,但我剛剛使用原始代碼中的方法,不要將其更改太多。更好的可以在這裏找到:http://stackoverflow.com/questions/8015766/read-in-seqence-from-a-text-file-in-common-lisp/8016277#8016277 –

+0

@angus:至少字符串永遠不會太短,我相信這是一個錯誤的上限。將它與一個fill- =指針結合起來(我認爲這些指針是由READ-SEQUENCE自動設置的),你所做的「全部」可能會浪費RAM。 – Vatine

2

我將任務分成2級較小的任務:從文件

1閱讀並返回一個字符串 2數字符的字母頻率串

對於1中,你可以使用文件字符串函數(https://github.com/kugelblitz/young/blob/master/external-helpers.lisp

對於2,你可以使用一個 '包' 的數據結構,以及FSET封裝庫(http://common-lisp.net/project/fset/):

(defun letter-freq (str) 
    (let ((bg (fset:convert 'fset:bag str))) 
    (fset:do-bag-pairs (value mult bg) 
         (format t "~a: ~a~%" value mult))))