Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 44 additions & 105 deletions tasks/medium/strings/anagram_finder.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,52 @@ tags = ["strings", "hashing", "sorting"]
time_to_solve_sec = 360

description_en = """
Given an array of lowercase words $w$, group words that are anagrams.
Return an array of groups (each a string array) where each group has size $\\ge 2$.
Inside each group, words are sorted lexicographically (duplicates allowed).
Groups are sorted by their first element, then by group size.
Given an array `words` of lowercase words, group words that are anagrams.

Return an array of groups (each is a string array) where each group has size $\\ge 2$.
Inside each group, words should be ordered alphabetically, duplicates are not allowed. Groups should be ordered alphabetically by their first word.
If there are no anagrams, return `[["anagrams not found!"]]`.
"""

description_ru = """
Дан массив слов в нижнем регистре $w$. Сгруппируйте слова-анаграммы.
Верните массив групп (каждая — массив строк) только с группами размера $\\ge 2$.
Внутри группы слова отсортированы лексикографически (дубликаты допускаются).
Группы отсортированы по первому слову, затем по размеру группы.
Дан массив `words` слов в нижнем регистре. Сгруппируйте слова-анаграммы.

Верните массив групп (каждая — массив строк) с группами размера $\\ge 2$.
Внутри групп слова должны быть упорядочены по алфавиту, дубликаты не допускаются. Группы должны быть упорядочены по алфавиту по первому слову.
Если анаграмм нет, верните `[["anagrams not found!"]]`.
"""

limits = """
- $0 \\leq \\text{len}(w) \\leq 5\\cdot 42$
- $1 \\leq \\text{len}(w_i) \\leq 30$
- $w_i \\in [a\\!\\dots\\!z]^*$
- $0 \\leq \\text{len}(words) \\leq 5\\cdot 42$
- $1 \\leq \\text{len}(words_i) \\leq 30$
- $words_i \\in [a\\!\\dots\\!z]^*$
"""

solution = """
def solution(w):
def solution(words):
from collections import defaultdict
groups = defaultdict(list)
for s in w:
key = ''.join(sorted(s))
groups[key].append(s)
# keep only groups with >=2

groups = defaultdict(set)
for w in words:
key = "".join(sorted(w))
groups[key].add(w)
kept = []
for key, arr in groups.items():
for arr in groups.values():
if len(arr) >= 2:
arr.sort()
kept.append(arr)
kept.append(sorted(arr))
if not kept:
return [["anagrams not found!"]]
kept.sort(key=lambda g: (g[0], len(g)))
return kept
return sorted(kept)
"""

examples = """
solution(["a","b","c"]) == [["anagrams not found!"]]
solution(["ab","ba","cd","dc"]) == [["ab","ba"],["cd","dc"]]
solution(["eat","tea","tan","ate","nat","bat"]) == [["ate","eat","tea"],["nat","tan"]]
solution(["a", "b", "c"]) == [["anagrams not found!"]]
solution(["ab", "ba", "cd", "dc"]) == [["ab", "ba"], ["cd", "dc"]]
solution(["eat", "tea", "tan", "ate", "nat", "bat"]) == [["ate", "eat", "tea"], ["nat", "tan"]]
"""

[[input_signature]]
argument_name = "w"
argument_name = "words"
[input_signature.type]
name = "array"
[input_signature.type.nested]
Expand All @@ -72,7 +70,7 @@ expected = [["ever", "veer"], ["item", "mite"], ["kale", "lake"]]
[[asserts]]
arguments = [["meat", "mat", "team", "mate", "eat", "mate"]]
comment = "Only the meat/mate/team group qualifies; words sorted"
expected = [["mate", "mate", "meat", "team"]]
expected = [["mate", "meat", "team"]]

[[asserts]]
arguments = [["there", "is", "no", "anagrams", "foo", "bar"]]
Expand All @@ -94,47 +92,26 @@ arguments = [
"gelugaan",
"nuaegalg",
"osls",
"osls",
],
"osls"
]
]
comment = "Multiple groups with duplicates"
expected = [
[
"cough",
"guohc",
"guohc",
],
[
"distribution",
"oriintdusbti",
],
[
"gelugaan",
"nuaegalg",
],
[
"nitwer",
"trnwie",
],
[
"osls",
"osls",
],
[
"water",
"water",
],
["cough", "guohc"],
["distribution", "oriintdusbti"],
["gelugaan", "nuaegalg"],
["nitwer", "trnwie"]
]

[[asserts]]
arguments = [["ab", "ba", "ab", "bca", "cab", "abc", "zzz"]]
comment = "Two groups; sorted groups and words"
expected = [["ab", "ab", "ba"], ["abc", "bca", "cab"]]
expected = [["ab", "ba"], ["abc", "bca", "cab"]]

[[asserts]]
arguments = [["a", "a"]]
comment = "Single-letter duplicates"
expected = [["a", "a"]]
expected = [["anagrams not found!"]]

[[asserts]]
arguments = [["a", "b", "c"]]
Expand All @@ -147,31 +124,9 @@ comment = "All are one large group"
expected = [["abc", "acb", "bac", "bca", "cab", "cba"]]

[[asserts]]
arguments = [
[
"listen",
"silent",
"enlist",
"inlets",
"google",
"gogole",
"elints",
],
]
arguments = [["listen", "silent", "enlist", "inlets", "google", "gogole", "elints"]]
comment = "Classic anagram set"
expected = [
[
"elints",
"enlist",
"inlets",
"listen",
"silent",
],
[
"gogole",
"google",
],
]
expected = [["elints", "enlist", "inlets", "listen", "silent"], ["gogole", "google"]]

[[asserts]]
arguments = [["dusty", "stud", "study", "rust", "tsur", "udsty"]]
Expand All @@ -191,7 +146,7 @@ expected = [["anagrams not found!"]]
[[asserts]]
arguments = [["aaaa", "aaaa", "aaaa"]]
comment = "All identical"
expected = [["aaaa", "aaaa", "aaaa"]]
expected = [["anagrams not found!"]]

[[asserts]]
arguments = [["loop", "polo", "pool", "loco", "cool"]]
Expand All @@ -210,33 +165,17 @@ expected = [["xyz", "xzy", "yxz", "yzx", "zxy", "zyx"]]

[[asserts]]
arguments = [["abc", "bca", "cab", "abcd", "bcad", "dacb", "dbca", "zz", "zz"]]
comment = "One 3-group, one 4-group, one 2-group; sorted by first word"
expected = [
[
"abc",
"bca",
"cab",
],
[
"abcd",
"bcad",
"dacb",
"dbca",
],
[
"zz",
"zz",
],
]
comment = "One 3-group, one 4-group; sorted by first word"
expected = [["abc", "bca", "cab"], ["abcd", "bcad", "dacb", "dbca"]]

[[asserts]]
arguments = [["abc", "bac", "ccc", "ccc", "bcc", "cbc"]]
comment = "Two groups with duplicates"
expected = [["abc", "bac"], ["bcc", "cbc"], ["ccc", "ccc"]]
comment = "Two groups and two duplicates"
expected = [["abc", "bac"], ["bcc", "cbc"]]

[[asserts]]
arguments = [["note", "tone", "stone", "tones", "onset", "seton"]]
comment = "One group of note/tone and one large group of onset/seton/stone/tones"
comment = "One small group and one big group"
expected = [["note", "tone"], ["onset", "seton", "stone", "tones"]]

[[asserts]]
Expand All @@ -246,10 +185,10 @@ expected = [["lair", "liar", "rail"]]

[[asserts]]
arguments = [["abc", "cba", "bca", "abcd", "abdc", "abcd", "dcab", "cadb"]]
comment = "Group sizes 3 and 5 (abcd group has duplicate)"
expected = [["abc", "bca", "cba"], ["abcd", "abcd", "abdc", "cadb", "dcab"]]
comment = "Group sizes 3 and 4 (abcd group has duplicate)"
expected = [["abc", "bca", "cba"], ["abcd", "abdc", "cadb", "dcab"]]

[[asserts]]
arguments = [["zzz", "zzz", "zzz", "zzzz", "zzzz"]]
comment = "Two groups of repeated letters"
expected = [["zzz", "zzz", "zzz"], ["zzzz", "zzzz"]]
expected = [["anagrams not found!"]]
Loading