3 ms·
I stopped when I scrolled as far as where he mentioned having trouble and thought I'd try it out myself. Here's my initial solution: new [] {"pool", "loco",
by rikkus 12y ago
I stopped when I scrolled as far as where he mentioned having trouble and thought I'd try it out myself. Here's my initial solution:
new [] {"pool", "loco", "cool", "stain", "satin", "pretty", "nice", "loop"}
.Aggregate (
new { Index = 0, Found = new Dictionary<string, List<WordAndIndex>>() },
(acc, word) =>
{
acc.Found
.FindOrCreate(word.Sort())
.Add(new WordAndIndex(word, acc.Index));
return new { Index = acc.Index + 1, Found = acc.Found };
}
)
.Found
.Where(f => f.Value.Count() > 1)
.SelectMany(f => f.Value)
.OrderBy(wordAndIndex => wordAndIndex.Index)
.Select(wordAndIndex => wordAndIndex.Text)
(some helper methods omitted for brevity)
I was fairly happy with this, but curious to see what he'd come up with in the end. I like it - especially the way it uses indices and zip. Here's my translation to C# (no helpers added here!):
IEnumerable<string> Anagrams(IEnumerable<string> words)
{
Func<string, string> sortLetters =
(s) => new string(s.ToCharArray().OrderBy(c => c).ToArray());
var sortedWords = words.Select(sortLetters);
var sortedWordsLookup = sortedWords.ToLookup(s => s);
return words.Zip(
sortedWords,
(word, normal) => new { word, normal }
)
.Where(
(wordAndSortedWord) =>
sortedWordsLookup[wordAndSortedWord.normal].Count() > 1
)
.Select(wordAndSortedWord => wordAndSortedWord.word);
}