Besides @SolitudeSF's important suggestion, an algorithmic improvement you can
use is to replace `algorithm.sorted(lower, system.cmp)` with a hand-written
"counting sort". For ASCII (i.e. 1 byte textual characters) this is (very?)
easy and should be quite a bit faster than `algorithm.sorted`. Something like
this:
proc sortByLetter(word: string): string =
var cnt: array[26, int8]
for ch in word: #simple counting sort
cnt[ord(ch) - ord('A')].inc
for i, c in cnt:
for n in 0 ..< c:
result.add chr(ord('A') + i)
Run
You probably need some `toUpper` in there if your dictionary is stored in
lowercase (although that could also be done prior to entry to the above `proc`
or you could also just change `A` to `a`). That `int8` type covers words up to
255 characters long, but I think the longest real word in any spoken language
with dictionaries is less than that. You could always count and print a warning
or switch that to `int16` or `int32` which could help if chemical elements or
really crazy stuff is possibly in play.
The same idea could be adapted to unicode but then you would probably want a
`Table`, not an `array` which would slow it down more than the above minor
modifications.
I actually think this is a good problem context in which to introduce the oft
neglected counting sort which can also be used with (unlike here) non-empty
satellite data (at some slightly increased code baggage).