コード中の文字の頻度分析
出題者です。 こちらで用意していた回答は awk を使ったものでした。一応解説すると、組み込み変数FSを空にし、1行単位の文字毎に連想配列に格納しています。
1 2 3 4 5 6 7 8 9 | # 1文字版
BEGIN { FS="" }
{ for (i=1; i<=NF; i++) ht[$i]++}
END { for (c in ht) print ht[c],c }
# 3文字版
BEGIN { FS="" }
{ for (i=1; i<=NF-2; i++) { ht[$i$(i+1)$(i+2)]++}}
END { for (c in ht) print ht[c],c }
|
Posted feedbacks - Scheme
Gauche (Scheme) で書きました。
Gauche 付属の srfi-42.scm を分析してみました。
#\space = 11142 / 38818 : 28.70 %
#\e = 2396 / 38818 : 6.17 %
#\( = 1640 / 38818 : 4.22 %
#\) = 1634 / 38818 : 4.20 %
#\r = 1492 / 38818 : 3.84 %
#\t = 1419 / 38818 : 3.65 %
#\= = 1391 / 38818 : 3.58 %
#\a = 1284 / 38818 : 3.30 %
#\s = 1280 / 38818 : 3.29 %
#\i = 1194 / 38818 : 3.07 %
...
やっぱり括弧がちょっと多めかな。
Gauche 付属の srfi-42.scm を分析してみました。
#\space = 11142 / 38818 : 28.70 %
#\e = 2396 / 38818 : 6.17 %
#\( = 1640 / 38818 : 4.22 %
#\) = 1634 / 38818 : 4.20 %
#\r = 1492 / 38818 : 3.84 %
#\t = 1419 / 38818 : 3.65 %
#\= = 1391 / 38818 : 3.58 %
#\a = 1284 / 38818 : 3.30 %
#\s = 1280 / 38818 : 3.29 %
#\i = 1194 / 38818 : 3.07 %
...
やっぱり括弧がちょっと多めかな。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | (define make-char-counter (lambda ()
(let ((ls '()))
(lambda (c)
(if (char? c)
(set! ls
(let loop ((li ls) (flag #f) (ret '()))
(if (pair? li)
(if (char=? c (caar li))
(loop (cdr li) #t (cons (cons c (+ 1 (cdar li))) ret))
(loop (cdr li) flag (cons (car li) ret)))
(if flag ret (cons (cons c 1) ret)))))
ls)))))
(define count-char (lambda (file)
(call-with-input-file file
(lambda (in)
(let ((counter (make-char-counter)))
(let loop ((c (read-char in)))
(if (eof-object? c)
(counter #f)
(begin (counter c) (loop (read-char in))))))))))
(define main (lambda (args)
(let* ((count (sort (count-char (cadr args)) (lambda (x y) (> (cdr x) (cdr y)))))
(total (fold (lambda (p total) (+ (cdr p) total)) 0 count)))
(for-each
(lambda (p)
(format #t "~s = ~d / ~d : ~d.~2,'0d %" (car p) (cdr p) total
(inexact->exact (truncate (* (/ (cdr p) total) 100)))
(remainder (inexact->exact (truncate (* (/ (cdr p) total) 10000))) 100))
(newline))
count))
0))
|
Gauche で書きました。 Gauche に添付されている srfi-*.scm で調べてみると:
#\space: 9865(20.78%) #\e: 3536(7.449%) #\t: 3154(6.644%) #\a: 2160(4.550%) #\i: 2159(4.548%) #\-: 2057(4.333%) #\(: 1872(3.943%) #\): 1872(3.943%) #\n: 1834(3.863%)
括弧が目立って多いかと思いきや、頻度の高いアルファベットやハイフンよりも少ないという結果になっていました(それでも C 言語の 1.5~2.0 % 程度というのに比べると十分多いのかもしれませんが)。
結局、一番多いのは字下げのための空白でした。よく訓練された Lisper には括弧は見えない云々。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | (use srfi-1)
(use gauche.collection)
(define (main args)
(call-with-input-file (second args)
(lambda (port)
(let* ((ts (port->list read-char port))
(lt (length ts))
(tss (group-collection ts))
(hist (sort (map (lambda (ts)
(let ((l (length ts)))
(list (car ts) l (/. (* l 100) lt))))
tss)
(lambda (x y) (> (second x) (second y))))))
(for-each (cut apply format #t "~S:\t~A(~,,,,5A%)~%" <>) hist)))))
|





crane
#6382()
Rating0/0=0.00
プログラムコード中の文字の頻度は言語によって相当にばらつきがあると思います。ある言語はピリオドが頻出するとか、別の言語はカッコの頻出頻度が高い、とか。そこで、
(その言語で書かれた「典型的な」プログラムコード、といえるようなものがあると良いのですが・・)
簡単すぎるという方は、複数文字にしてみたり単語の頻度にしてみてください。
参考;Wikipedia 頻度分析
http://ja.wikipedia.org/wiki/%E9%A0%BB%E5%BA%A6%E5%88%86%E6%9E%90
1 reply [ reply ]