All SolutionsAll Solutions
↔️
Anagrams
Week 37, 2026
Prepare word list, Iterate and find anagrams | greenya | Odin Solutions
// https://program52.com/en/challenge/2026/571490F44
package main
import "core:fmt"
import "core:slice"
import "core:strings"
main :: proc () {
state: State
// state_init(&state, #load("words-example.txt", string))
state_init(&state, #load("words-strict.txt", string))
defer state_destroy(&state)
for w in state.known_words {
state_gen_anagrams_of(&state, w)
}
state_print(state)
}
State :: struct {
known_words : [] string,
sets : map [string] [dynamic] string,
seen : map [string] struct {},
}
state_init :: proc (this: ^State, known_words_text: string) {
projected_word_count := 1 + strings.count(known_words_text, "\n")
known_words := make([dynamic] string, 0, projected_word_count)
text := known_words_text
for s in strings.split_lines_iterator(&text) {
w := strings.trim_space(s)
append(&known_words, w)
}
shrink(&known_words)
slice.sort(known_words[:])
this.known_words = known_words[:]
}
state_destroy :: proc (this: ^State) {
delete(this.known_words)
for _, list in this.sets do delete(list)
delete(this.sets)
delete(this.seen)
}
state_gen_anagrams_of :: proc (this: ^State, word: string) {
if word in this.seen do return
for known_word in this.known_words {
if words_are_anagrams(known_word, word) {
if word not_in this.sets do this.sets[word] = {}
list := &this.sets[word]
append(list, known_word)
this.seen[known_word] = {}
}
}
}
state_print :: proc (this: State) {
order, _ := slice.map_keys(this.sets)
defer delete(order)
sets := this.sets
context.user_ptr = &sets
slice.sort_by(order[:], less=proc (a, b: string) -> bool {
sets := cast (^map [string] [dynamic] string) context.user_ptr
len_a := len(sets[a])
len_b := len(sets[b])
return len_a==len_b ? a<b : len_a>len_b
})
total, alone: int
for o in order {
list := this.sets[o]
slice.sort(list[:])
count := len(list)
total += count
if count==1 do alone += 1
fmt.printf("%i: ", count)
for w, i in list {
if i>0 do fmt.print(", ")
fmt.print(w)
}
fmt.println()
}
fmt.printfln("--- %i of %i words are anagrams of other words ---", total-alone, total)
}
words_are_anagrams :: proc (a, b: string) -> bool {
if len(a) != len(b) do return false
counts: [256] int
for c in a { counts[c] += 1 }
for c in b {
if counts[c] == 0 do return false
counts[c] -= 1
}
return true
}