Skip to content

Instantly share code, notes, and snippets.

@ghoseb
Last active April 10, 2022 17:03
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ghoseb/1bb32eef113d90faaa21ab6693bf77c4 to your computer and use it in GitHub Desktop.
Save ghoseb/1bb32eef113d90faaa21ab6693bf77c4 to your computer and use it in GitHub Desktop.
Print the source-line length of a bunch of files as a histogram.
(ns file-cols.core
"Print the source-line length histogram of a bunch of files as a histogram.
Inspired by: https://gist.github.com/rsms/36bda3b5c8ab83d951e45ed788a184f4"
(:require [clojure.java.io :as io]))
(def uni-bar
"Unicode bars for histogram."
["" "▏" "▎" "▍" "▌" "▋" "▊" "▉" "█"])
(def quot-rem-8
"Quotient and remainder after dividing by 8."
(juxt #(quot % 8) #(rem % 8)))
(defn avg
"Average from a frequency map."
[freqs]
(float
(/ (reduce-kv (fn [ret x y] (+ ret (* x y))) 0 freqs)
(apply + (vals freqs)))))
(defn dir?
"Check if a File is a directory."
[^java.io.File f]
(.isDirectory f))
(defn col-freqs
"Calculate the column frequency for a seq of lines."
[ls]
(->> ls (map count) (filter pos?) frequencies))
(defn f-col-freqs
"Calculate the column frequency for a single file."
[f]
(with-open [r (io/reader f)]
(let [ls (line-seq r)]
(col-freqs ls))))
(defn bars
"Represent n using Unicode bars. Use blocks of 8 or smaller."
[n]
(let [[b8s r] (quot-rem-8 n)]
(loop [b8s b8s res []]
(if (zero? b8s)
(apply str (conj res (uni-bar r)))
(recur (dec b8s) (conj res (uni-bar 8)))))))
(defn scaled-histogram
"Create a scaled Unicode histogram from a frequency map."
([max-cols]
(partial scaled-histogram max-cols))
([max-cols freqs]
(let [max-val (apply max (vals freqs))
scale (fn [x] (-> x (/ max-val) (* max-cols 8.0) Math/round))]
(update-vals freqs scale))))
(defn fmt-str
"Construct the correct format string for the given frequency map."
[freqs]
(let [max-len (comp count str (partial apply max))
max-k-len (-> freqs keys max-len)
max-v-len (-> freqs vals max-len)]
(format "%%-%sd %%-%sd %%s" (max 4 max-k-len) (max 4 max-v-len))))
(defn do-print-histogram
"Print the Unicode histogram map."
[histf freqs]
(let [scaled-hist (histf freqs)]
(println (format "%-4s %s" "COLS" "COUNT"))
(doseq [[col bar-cnt] (into (sorted-map) scaled-hist)]
(println (format (fmt-str freqs) col (freqs col) (bars bar-cnt))))
(println (format "Average columns per line: %.2f" (avg freqs)))))
(defn -main
"Entry point for Babashka.
Expects a list of file-names.
$ find ~/Code/src -type f -name \"*.clj\" | bb -f file_cols.clj"
[& _]
(when-let [ls (line-seq (io/reader *in*))]
(->> ls
(remove (comp dir? io/as-file))
(map f-col-freqs)
(apply merge-with +)
(do-print-histogram (scaled-histogram 100)))))
(-main)
$❯ find ~/Code/src/babashka -type f -name "*.clj" | bb -f ~/Code/file_cols.clj
COLS COUNT
1 12 █
2 40 ███▍
3 30 ██▌
4 39 ███▎
5 178 ███████████████
6 61 █████▏
7 142 ████████████
8 165 █████████████▉
9 120 ██████████▏
10 187 ███████████████▊
11 225 ███████████████████
12 206 █████████████████▍
13 249 █████████████████████
14 296 █████████████████████████
15 330 ███████████████████████████▉
16 321 ███████████████████████████▏
17 361 ██████████████████████████████▌
18 385 ████████████████████████████████▌
19 408 ██████████████████████████████████▌
20 447 █████████████████████████████████████▊
21 550 ██████████████████████████████████████████████▌
22 485 █████████████████████████████████████████
23 456 ██████████████████████████████████████▌
24 439 █████████████████████████████████████▏
25 434 ████████████████████████████████████▋
26 442 █████████████████████████████████████▍
27 473 ████████████████████████████████████████
28 427 ████████████████████████████████████▏
29 433 ████████████████████████████████████▋
30 474 ████████████████████████████████████████
31 509 ███████████████████████████████████████████
32 521 ████████████████████████████████████████████
33 495 █████████████████████████████████████████▊
34 431 ████████████████████████████████████▍
35 457 ██████████████████████████████████████▋
36 516 ███████████████████████████████████████████▋
37 476 ████████████████████████████████████████▎
38 475 ████████████████████████████████████████▏
39 592 ██████████████████████████████████████████████████
40 391 █████████████████████████████████
41 429 ████████████████████████████████████▎
42 408 ██████████████████████████████████▌
43 402 ██████████████████████████████████
44 409 ██████████████████████████████████▌
45 356 ██████████████████████████████▏
46 380 ████████████████████████████████▏
47 345 █████████████████████████████▏
48 338 ████████████████████████████▌
49 381 ████████████████████████████████▏
50 358 ██████████████████████████████▎
51 362 ██████████████████████████████▋
52 319 ███████████████████████████
53 320 ███████████████████████████
54 319 ███████████████████████████
55 339 ████████████████████████████▋
56 283 ███████████████████████▉
57 272 ███████████████████████
58 260 ██████████████████████
59 268 ██████████████████████▋
60 211 █████████████████▉
61 226 ███████████████████▏
62 219 ██████████████████▌
63 221 ██████████████████▋
64 238 ████████████████████▏
65 192 ████████████████▎
66 206 █████████████████▍
67 189 ████████████████
68 193 ████████████████▎
69 192 ████████████████▎
70 180 ███████████████▎
71 129 ██████████▉
72 198 ████████████████▊
73 127 ██████████▊
74 153 ████████████▉
75 119 ██████████
76 114 █████████▋
77 99 ████████▍
78 139 ███████████▊
79 100 ████████▌
80 106 █████████
81 92 ███████▊
82 79 ██████▋
83 81 ██████▉
84 71 ██████
85 64 █████▍
86 72 ██████▏
87 75 ██████▍
88 60 █████▏
89 70 █████▉
90 53 ████▌
91 31 ██▋
92 46 ███▉
93 44 ███▊
94 31 ██▋
95 36 ███
96 38 ███▎
97 26 ██▎
98 24 ██
99 19 █▋
100 32 ██▊
101 23 ██
102 21 █▊
103 19 █▋
104 21 █▊
105 21 █▊
106 35 ███
107 26 ██▎
108 11 ▉
109 10 ▉
110 15 █▎
111 7 ▋
112 13 █▏
113 16 █▍
114 11 ▉
115 13 █▏
116 11 ▉
117 11 ▉
118 17 █▍
119 8 ▋
120 5 ▍
121 16 █▍
122 11 ▉
123 9 ▊
124 4 ▍
125 6 ▌
126 5 ▍
127 8 ▋
128 4 ▍
129 5 ▍
130 6 ▌
131 3 ▎
132 5 ▍
133 6 ▌
134 4 ▍
135 1 ▏
136 2 ▏
137 3 ▎
138 2 ▏
139 2 ▏
140 3 ▎
141 2 ▏
142 1 ▏
143 4 ▍
145 3 ▎
146 1 ▏
147 1 ▏
148 4 ▍
149 2 ▏
151 1 ▏
153 4 ▍
154 1 ▏
155 1 ▏
156 3 ▎
157 1 ▏
159 1 ▏
160 2 ▏
161 2 ▏
162 1 ▏
165 1 ▏
166 1 ▏
167 1 ▏
171 2 ▏
172 2 ▏
176 1 ▏
181 2 ▏
184 1 ▏
202 1 ▏
203 3 ▎
209 1 ▏
216 1 ▏
239 1 ▏
271 1 ▏
376 1 ▏
4014 1 ▏
Average columns per line: 42.20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment