word_freq.odin in Odin
A word-frequency table from a split iterator, a map, a sort, and a bar chart.
// Count word frequencies in a passage and chart the leaders.
package main
import "core:fmt"
import "core:slice"
import "core:strings"
PASSAGE :: "the rain in maine falls mainly on the plain and " +
"the rain stays on the plain"
Entry :: struct {
word: string,
count: int,
}
more_first :: proc(a, b: Entry) -> bool {
return a.count > b.count
}
main :: proc() {
// Tally every word into a map keyed by its slice of the passage.
counts := make(map[string]int)
defer delete(counts)
rest := PASSAGE
for word in strings.split_iterator(&rest, " ") {
counts[word] += 1
}
// Pull the entries out and sort by count, biggest first.
ranked: [dynamic]Entry
defer delete(ranked)
for word, n in counts {
append(&ranked, Entry{word, n})
}
slice.sort_by(ranked[:], more_first)
fmt.println(len(ranked), "distinct words")
fmt.println("word ct bar")
bars := "####################"
for e in ranked {
fmt.printfln("%-7s %2d %s", e.word, e.count, bars[:e.count])
}
}
How it works
split_iteratorwalks the passage;counts[word] += 1tallies into the map.- The entries move to a
[dynamic]Entryandslice.sort_byranks them. - Slicing a bar of hashes to
e.countdraws each word's line.
Keywords and builtins used here
EntryPASSAGEappendbooldeferdeletedynamicforimportinintlenmakemappackageprocreturnstringstruct
The run, in numbers
- Lines
- 43
- Characters to type
- 955
- Tokens
- 207
- Three-star pace
- 65 tpm
At the three-star pace of 65 tokens a minute, this run takes about 191 seconds.
Step 1 of 3 in Encore, step 25 of 27 in Language basics.