Problem:
 Score : 300 points    Problem Statement We will call a string obtained by arranging the characters contained in a string a in some order, an anagram of a .  For example, greenbin is an anagram of beginner . As seen here, when the same character occurs multiple times, that character must be used that number of times.  Given are N strings s_1, s_2, \ldots, s_N . Each of these strings has a length of 10 and consists of lowercase English characters. Additionally, all of these strings are distinct. Find the number of pairs of integers i, j  (1 \leq i < j \leq N) such that s_i is an anagram of s_j .      Constraints  2 \leq N \leq 10^5  s_i is a string of length 10 .  Each character in s_i is a lowercase English letter.  s_1, s_2, \ldots, s_N are all distinct.         Input Input is given from Standard Input in the following format:  N  s_1  s_2  :  s_N       Output Print the number of pairs of integers i, j  (1 \leq i < j \leq N) such that s_i is an anagram of s_j .        Sample Input 1 3
acornistnt
peanutbomb
constraint      Sample Output 1 1  s_1 =  acornistnt is an anagram of s_3 =  constraint . There are no other pairs i, j such that s_i is an anagram of s_j , so the answer is 1 .       Sample Input 2 2
oneplustwo
ninemodsix      Sample Output 2 0  If there is no pair i, j such that s_i is an anagram of s_j , print 0 .       Sample Input 3 5
abaaaaaaaa
oneplustwo
aaaaaaaaba
twoplusone
aaaabaaaaa      Sample Output 3 4  Note that the answer may not fit into a 32 -bit integer type, though we cannot put such a case here.

Solution (Python):


import sys

debug = False

def log(text):
    if debug:
        print(text)

def parse_input(lines_as_string = None):

    global debug
    lines = []
    if lines_as_string is None:
        debug = False
        lines.append(input())
        n = int(lines[0])
        for i in range(n):
            lines.append(input())
    else:
        debug = True
        lines = [e for e in lines_as_string.split("\n")][1:-1]
        n = int(lines[0])

    s = lines[1:]

    return (n, s)


def cnt_dict_to_tuple(cnt_dict):
    t = (
        cnt_dict.get("a", 0),
        cnt_dict.get("b", 0),
        cnt_dict.get("c", 0),
        cnt_dict.get("d", 0),
        cnt_dict.get("e", 0),
        cnt_dict.get("f", 0),
        cnt_dict.get("g", 0),
        cnt_dict.get("h", 0),
        cnt_dict.get("i", 0),
        cnt_dict.get("j", 0),
        cnt_dict.get("k", 0),
        cnt_dict.get("l", 0),
        cnt_dict.get("m", 0),
        cnt_dict.get("n", 0),
        cnt_dict.get("o", 0),
        cnt_dict.get("p", 0),
        cnt_dict.get("q", 0),
        cnt_dict.get("r", 0),
        cnt_dict.get("s", 0),
        cnt_dict.get("t", 0),
        cnt_dict.get("u", 0),
        cnt_dict.get("v", 0),
        cnt_dict.get("w", 0),
        cnt_dict.get("x", 0),
        cnt_dict.get("y", 0),
        cnt_dict.get("z", 0),
    )
    return t



def solve(n, s):

    cnt_tuple_dict = dict()
    for i in range(n):
        cnt_dict = dict()    
        for c in s[i]:
            cnt = cnt_dict.get(c, 0)
            cnt = cnt + 1
            cnt_dict[c] = cnt
    
        t = cnt_dict_to_tuple(cnt_dict)
        if debug:
            log("t=%s" % str(t))

        same_cnt_index_list = cnt_tuple_dict.get(t, [])
        same_cnt_index_list.append(i)
        cnt_tuple_dict[t] = same_cnt_index_list


    result = 0
    for t, same_cnt_index_list in cnt_tuple_dict.items():
        n = len(same_cnt_index_list)

        result = result + int(n*(n-1)/2)

    return result


def main():
    

    print("%s" % solve(*parse_input()))

if __name__ == '__main__':

    main()

Solution (Python):
N = int(input())
s = [0]*(N+1)
for i in range(N):
    tmp = sorted(list(input()))
    s[i] = ''.join(tmp)
s[-1] = 'zzzzzzzzzzz'
s.sort()

ans = 0
i = 0
while i < N:
    k = 1
    while s[i] == s[i+k]:
        k += 1
    ans += (k-1)*k/2
    i += k
        
print(int(ans))

Solution (Python):
import math
N = int(input())
sorted_map = {}

def combinations_count(n, r):
    return math.factorial(n) // (math.factorial(n - r) * math.factorial(r))

for i in range(N):
    inserted_flag = True
    input_sorted = ''.join(sorted(input()))
    if input_sorted in sorted_map.keys():
        sorted_map[input_sorted] += 1
        inserted_flag = False
    if inserted_flag:
        sorted_map[input_sorted] = 1

count = 0
for count_num in sorted_map.values():
    if count_num == 1:
        continue
    count += combinations_count(count_num, 2)
print(count)

Solution (Python):

def combain(X, Y):
    return int(( X * (X - 1)) / Y)

N = int(input())
S = []

ans = 0

for i in range(N):
    S.append(sorted(input()))

S.sort()

ans = 0

X = 1
for i in range(N-1):
    if S[i] == S[i+1]:
        X += 1
    elif X > 1:
        C = combain(X, 2)
        X = 1
        ans += C

if X > 1:
    C = combain(X, 2)
    X = 1
    ans += C
    
print(ans)

Solution (Python):
n=int(input())
s=sorted([''.join(sorted(input())) for i in range(n)])

c=[]
i=0
while i<n-1:
  cnt=0
  while i<n-1 and s[i]==s[i+1]:
    cnt+=1
    i+=1
  c+=[cnt+1]
  i+=1
ans=0
for i in c:
  if i>1:
    ans+=i*(i-1)//2
print(ans)

Solution (Python):
dic = {}
N = int(input())

for n in range( N ):
    s = input()
    s1 = list( s )     
    s1.sort()
    s2 = ''.join(s1)

    if s2 in dic:
        dic[ s2 ] += 1
    else:
        dic[ s2 ] = 1

total = 0
for n in dic.values():
    if n >= 2:
        num = n * ( n - 1 ) // 2
        total += num

print( total )

Solution (Python):
n = int(input())
r = dict()
find = False
for i in range(n):
    l = str(sorted([c for c in input()]))
    if l not in  r:
        r[l] = 1
    else:
        r[l] = r[l] + 1
        find=True

sum = 0    
def comb(n, k):
    bo = 1
    for kk in range(1, k+1):
        bo = bo * kk
    si = 1
    for kk in range(n-k+1 ,n+1):
        si = si * kk
    return int(si / bo)

for k, v in r.items():
    sum = sum + comb(v, 2)
print(sum)

Solution (Python):
n=int(input())
s=["".join(sorted(list(input()))) for i in range(n)]
s.sort()
dp=[1]
for i in range(n-1):
  if s[i]==s[i+1]:
    dp[len(dp)-1]+=1
  else:
    dp.append(1)
ans=0
for i in dp:
  ans+=i*(i-1)//2
print(ans)

Solution (Python):
n = int(input())
m = {}
 
for i in range(n):
  s = "".join(sorted(list(input())))
  if s in m.keys():
    m[s] = m[s] + 1
  else:
    m[s] = 1
 
ans = 0
for s in m.keys():
  ans += m[s] * (m[s] - 1) // 2
 
print(ans)

Solution (Python):

import collections
import math

l = int(input())
st = []
for i in range(l):
    x = ''.join(sorted(input()))
    st.append(x)
c = collections.Counter(st)
cv = c.values()
sum = 0
for i in cv:
    if int(i) > 1:
        tm = 0
        for j in range(int(i)-1):
            tm = tm + int(i)-1-j
        sum = sum + tm

print(math.floor(sum))

Solution (Python):
import math

N = int(input())
S = []
for i in range(N):
    S_tmp = str(input())
    S_tmp = list(S_tmp)
    S_tmp.sort()
    S.append("".join(S_tmp))
S.sort()

count=0
x = 0
tmp = S[0]
count_all = []
for i in S[1:]:
    if tmp==i:
        count+=1
    else:
        if count>0:
            x += math.factorial(count+1)//(math.factorial(count+1-2) * math.factorial(2))
        count = 0
    tmp = i
if count>0:
    x += math.factorial(count+1)//(math.factorial(count+1-2) * math.factorial(2))
        
    tmp = i
print(x)

Solution (Python):


import re
from collections import deque
from functools import reduce
from itertools import permutations
from math import pi
from operator import itemgetter
from operator import mul
from operator import xor
from os import linesep
from queue import PriorityQueue
from sys import stdin


def rline() -> str:
    return stdin.readline().strip()


def rlines(hint: int = 1):
    ret = ['' for i in range(hint)]
    for i in range(hint):
        ret[i] = rline()
    return ret


def htokens(hint: int = 1):
    lns = rlines(hint)
    ret = list(map(lambda ln: ln.split(), lns))
    
    if hint == 1:
        
        ret.append([])
    return ret


def vtokens(hint: int = 1):
    m, _ = htokens()
    wint = len(m)
    ret = [[None] * hint for i in range(wint)]
    for y in range(hint):
        if y != 0:
            m, _ = htokens()
        
        x = 0
        for v in m:
            ret[x][y] = v
            x += 1
    
    if wint == 1:
        
        ret.append([])
    return ret


def rint(radix: int = 10) -> int:
    return int(rline(), radix)


def hints(hint: int = 1, radix: int = 10):
    ret = htokens(hint)
    for i in range(len(ret)):
        ret[i] = list(map(lambda v: int(v, radix), ret[i]))
    return ret


def vints(hint: int = 1, radix: int = 10):
    ret = vtokens(hint)
    for i in range(len(ret)):
        ret[i] = list(map(lambda v: int(v, radix), ret[i]))
    return ret


def mat(hint: int, wint: int):
    return [[None]*wint for i in range(hint)]


def filllist(lst, value: int) -> None:
    
    for i in range(len(lst)):
        lst[i] = value


def isprime(n: int) -> bool:
    if n <= 1:
        return False
    if n in (2, 3, 5):
        return True
    if n % 2 == 0:
        return False
    if n % 3 == 0:
        return False
    lst = int(n**0.5)
    f = 5
    while f <= lst:
        if n % f == 0:
            return False
        if n % (f + 2) == 0:
            return False
        f += 6
    return True


def strmat(matrix, lnsep: str = linesep, fieldsep: str = ' ') -> str:
    return lnsep.join(map(lambda row: fieldsep.join(map(str, row)), matrix))


def strbool(boolval: int) -> str:
    return ['No', 'Yes'][boolval]


def solve() -> None:
    
    n = rint()
    ss = rlines(n)

    
    dict = {}
    for s in ss:
        cnt = [0] * 26
        for c in s:
            cnt[ord(c) - ord('a')] += 1
        tup = tuple(i for i in cnt)
        if not tup in dict.keys():
            dict[tup] = 0
        dict[tup] += 1

    
    ans = sum(map(lambda x: 0 if x == 1 else x*(x-1)//2, dict.values()))

    
    print(ans)


if __name__ == '__main__':
    solve()

Solution (Python):
from collections import Counter

N = int(input())

s = []
s_ap = s.append

for i in range(N):
    s_ap("".join(sorted(input())))

result = 0

for i in Counter(s).values():
    if not i == 1:
        result += int(i * (i - 1) / 2)
        
print(result)

Solution (Python):
from collections import defaultdict

N = int(input())
S = [input() for i in range(N)]
ans = defaultdict(list)
for s in S:
    count = [0] * 26
    for c in s:
        count[ord(c)-ord('a')] += 1
    ans[tuple(count)].append(s)

ret = 0
l = 0
for a in ans.keys():
    l = len(ans[a])
    ret += l*(l-1)//2

print(ret)

Solution (Python):
N = int(input())
S = [[c for c in input()] for i in range(N)]
dic={}
for i in range(len(S)):
    S[i].sort()
    S[i] = str(S[i])
    if S[i] in dic:
        dic[S[i]] +=1
    else:
        dic[S[i]] = 1

comb=0
for i in dic.keys():
    if dic[i] !=0:
        comb = comb + dic[i]*(dic[i]-1)/2
print(int(comb))

Solution (Python):
import sys
sys.setrecursionlimit(10000000)
nCr = {}
def cmb(n, r):
    if r == 0 or r == n: return 1
    if r == 1: return n
    if (n,r) in nCr: return nCr[(n,r)]
    nCr[(n,r)] = cmb(n-1,r) + cmb(n-1,r-1)
    return nCr[(n,r)]

n = int(input())
s=[]
m={}
sum=0
for i in range(0,n):
    
    tmp = "".join(sorted(input()))
    if tmp in m:
        m[tmp]+=1
    else:
        m[tmp] = 1
for k in m:
    if m[k]>1:
        
        
        sum+=cmb(m[k],2)
print(sum)