An anagram is a word, a phrase, or a sentence formed from another by rearranging its letters. An example of this is "angel", which is an anagram of "glean".

Write a function that receives an array of words, and returns the total number of distinct pairs of anagramic words inside it.

Some examples:

- There are 2 anagrams in the array `["dell", "ledl", "abc", "cba"]`
- There are 7 anagrams in the array `["dell", "ledl", "abc", "cba", "bca", "bac"]`

Difficulty: introductory

Starter code:

def anagram_counter(words):
	

Solutions:
from collections import Counter

def anagram_counter(words):
    return sum(n*(n-1)// 2 for n in Counter(''.join(sorted(x)) for x in words).values())

def anagram_counter(words):
    def is_anagrams(s1, s2): return sorted(s1) == sorted(s2)
    return 0 if not words else sum([1 for x in range(len(words)-1) for y in range(x+1, len(words)) if is_anagrams(words[x], words[y])])

from collections import Counter

def anagram_counter(words):
    return sum(n*(n-1)>>1 for n in Counter(''.join(sorted(word)) for word in words).values())

from collections import Counter

def anagram_counter(words):
    return sum(n * (n - 1) / 2 for n in Counter(frozenset(word) for word in words).values())

from collections import Counter
from itertools import combinations
def anagram_counter(words):
    return sum(1 for a, b in combinations((frozenset(Counter(w)) for w in words), 2) if a == b)

from collections import Counter

def anagram_counter(words):
    anag = Counter( tuple(sorted(Counter(w).items())) for w in words )
    return sum(n*(n-1)//2 for n in anag.values())

def anagram_counter(words):
    anagrams = 0
    for i, word in enumerate(words):
        for wrd in [w for w in words if w != word and set(word) == set(w)]:
            anagrams += 1
    return anagrams / 2

from collections import Counter

def anagram_counter(words):
    return sum(n * (n - 1) // 2 for n in Counter(''.join(sorted(w)) for w in words).values())

from collections import Counter

def anagram_counter(a):
    return sum(n * (n - 1) / 2 for n in Counter("".join(sorted(x)) for x in a).values())

# METHOD ONE ~ list comprehension
"100 seconds per 1000 runs of Lorem Ipsum"
# def anagram_counter(s):
#     return sum([1for i,c in enumerate(s)for w in s[i+1:]if sorted(c)==sorted(w)])

# METHOD TWO ~ standard iteration
"50 seconds per 1000 runs of Lorem Ipsum"
#def anagram_counter(words):
#    anagram_count = 0
#    for i, current in enumerate(words):#                    FUN FACT:
#        cenrrtu = sorted(current)
#        for word in words[i+1:]:
#            if cenrrtu == sorted(word):#     Lorum Ipsum contains 6,862 anagram matches
#                anagram_count += 1
#    return anagram_count

# METHOD THREE ~ comparing sets to counts
"0.5 seconds per 1000 runs of Lorem Ipsum"
def run_down(number):
    count = 0
    while number:
        count += number - 1
        number -= 1
    return count

def anagram_counter(words):
    sorts = list(''.join(sorted(word)) for word in words)
    unique = set(sorts)
    return sum(run_down(sorts.count(word)) for word in unique)
    
"""
iterations     _comp_    _iter_    _sets_
1              0.0990    0.0541    0.0008
10             1.0113    0.4954    0.0054
100            9.9280    4.8606    0.0535
1000         101.2153   50.2576    0.5660
"""