Given a list of dominoes, dominoes[i] = [a, b] is equivalent to dominoes[j] = [c, d] if and only if either (a==c and b==d), or (a==d and b==c) - that is, one domino can be rotated to be equal to another domino.
Return the number of pairs (i, j) for which 0 <= i < j < dominoes.length, and dominoes[i] is equivalent to dominoes[j].
 
Example 1:
Input: dominoes = [[1,2],[2,1],[3,4],[5,6]]
Output: 1

 
Constraints:

1 <= dominoes.length <= 40000
1 <= dominoes[i][j] <= 9

Difficulty: introductory

Starter code:

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        

Solutions:
class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        set1={}
        
        sum1=0
        for i in dominoes:

            ri=list(reversed(i))
            i=tuple(i)
            ri=tuple(ri)
            if i in set1.keys():
                sum1+=set1[i]
                set1[i]+=1
            elif ri in set1.keys():
                sum1+=set1[ri]
                set1[ri]+=1
            else:
                set1[i]=1
        return sum1

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        lst = [tuple(sorted(d)) for d in dominoes]
        dct = dict((x,lst.count(x)) for x in set(lst))

        y = sum(list([(x*(x-1)/2) for x in list(dct.values())]))
        return int(y)


class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        lst = [tuple(sorted(d)) for d in dominoes]
        counts = [lst.count(x) for x in set(lst)]
        # return int(sum(map(lambda x: (x*(x-1)/2), counts)))
        return int(sum([x*(x-1)/2 for x in counts]))
        
        
        
        
        x = [1,2,3]
        y = map(lambda a: a+2, x)
        print(list(y))

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        c = collections.Counter()
        for i in dominoes:
            c[tuple(sorted(i))] += 1
            
        return sum(math.comb(i, 2) for i in c.values()) 

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        count = 0
#         for i in range(len(dominoes)-1):
#             for j in range(i+1,len(dominoes)):
#                 if (dominoes[i][0]==dominoes[j][0] and dominoes[i][1]==dominoes[j][1] ) or (dominoes[i][0]==dominoes[j][1] and dominoes[i][1]==dominoes[j][0] ):
#                     count+=1
                    
#         return count
    
        mydict = {}
        for dom in dominoes:
            if ''.join(str(dom)) in mydict:
                mydict[''.join(str(dom))] += 1
            elif  ''.join(str(dom[::-1])) in mydict:
                mydict[''.join(str(dom[::-1]))] += 1
            else:
                mydict[''.join(str(dom))] = 1
        for val in list(mydict.values()):
            if val > 1:
                count += val*(val-1)//2

        return count



class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        for i in range(len(dominoes)):
            dominoes[i] = tuple(sorted(dominoes[i]))
            
        ans = 0
        
        for i in set(dominoes):
            d = dominoes.count(i)
            if d > 1:
                ans += d*(d-1) // 2
        return ans

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        
        for i in range(len(dominoes)):
            dominoes[i] = tuple(sorted(dominoes[i]))
        ans = 0
        for i in set(dominoes):
            t = dominoes.count(i)
            ans += t*(t-1)//2
        return ans

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        # d=dict()
        # res=0
        # for i,j in dominoes:
        #     if(str([i,j]) in d):
        #         d[str([i,j])]+=1
        #         res+=d[str([i,j])]
        #     elif(str([j,i]) in d):
        #         d[str([j,i])]+=1
        #         res+=d[str([j,i])]
        #     else:
        #         d[str([i,j])]=0
        # return res
        d={}
        res=0
        for i in dominoes:
            i=sorted(i)
            if(str(i) not in d):
                d[str(i)]=0
            d[str(i)]+=1
            if(d[str(i)]>1):
                res+=d[str(i)]-1
        print(d)
        return res

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        return sum(d * (d - 1) // 2 for d in Counter(tuple(sorted(domino)) for domino in dominoes).values())

from collections import defaultdict

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        # ans = 0
        # dominoes = sorted([sorted(i) for i in dominoes])
        # # print(dominoes)
        # prev = dominoes.pop()
        # cnt = 0
        # tot = 0
        # while dominoes:
        #     curr = dominoes.pop()
        #     # print('curr ', curr)
        #     if curr == prev:
        #         cnt += 1
        #         tot += cnt
        #     else:
        #         ans += tot
        #         tot, cnt = 0, 0
        #     prev = curr
        # return ans + tot
                
        
        # step 1: count the dominoes
        d = {}
        for domi in dominoes:
            p = tuple(sorted(domi))
            if p in d:
                d[p] += 1
            else:
                d[p] = 1
        # step 2: caculate the pairs. for each pair, number of pairs = n*(n-1)//2
        c = 0
        for n in list(d.values()):
            s = n*(n-1)//2
            c += s
        return c


class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        s=[]
        for i in range(len(dominoes)):
            
            dominoes[i]=sorted(dominoes[i])
            if dominoes[i] not in s:
                s.append(dominoes[i])
        re=0
        def fac(n):
            if n==0:
                return 1
            if n<3:
                return n
            return n*fac(n-1)
        for r in s:
            c=dominoes.count(r)
            re+=int(fac(c)/(fac(c-2)*2))
            
        print(dominoes,s,re)
        return re

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        dominoes_dict = {}
        for i in [frozenset(domino) for domino in dominoes]:
                if i not in dominoes_dict:
                    dominoes_dict[i] = 1
                else:
                    dominoes_dict[i] += 1 
        
        return sum([int((n*(n-1))/2) for n in list(dominoes_dict.values()) if n > 1])


class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        dominoes_dict = {}
        for i in dominoes:
            j = frozenset(i)
            if j not in dominoes_dict:
                dominoes_dict[j] = 1
            else:
                dominoes_dict[j] += 1 
        
        return sum([int((n*(n-1))/2) for n in list(dominoes_dict.values()) if n > 1])


class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        
        dicts = defaultdict(int)
        ans = 0

        for domi in dominoes:
            dicts[tuple(sorted(domi))] += 1
            
        for n in dicts.values():
            ans += n * (n - 1) // 2
        
        return ans

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        collection = defaultdict(int)
        count = 0
        for i in dominoes:
            pair = frozenset(i)
            count+=collection[pair]
            collection[pair]+=1
                
        
        return count

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        from collections import defaultdict
        counter = defaultdict(int)
        for domino in dominoes:
            counter[tuple(sorted(domino))] +=1
        return sum([v*(v-1)//2 for v in counter.values()])

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        # step 1: count the dominoes
        d = {}
        for dom in dominoes:
            p = tuple(sorted(dom))
            if p in d:
                d[p] += 1
            else:
                d[p] = 1
        # step calculate it 
        c = 0
        for n in d.values():
            s = n*(n-1)//2
            c += s
        return c            

from math import comb
class Solution:
    #def convert(self,list) -> int: 
    #    res = int(\"\".join(map(str, list))) 
    #    return res     
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        hashtable = {}
        for d in dominoes:
            new = tuple(sorted(d))
            if(new not in list(hashtable.keys())):
                hashtable[new] = 1
            else:
                hashtable[new] += 1
        counter = 0
        print(hashtable)
        for k,v in list(hashtable.items()):
            if v >= 2:
                counter += (comb(v,2))
                
                
        return counter
            


class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        d = {}
        for domi in dominoes:
            p = tuple(sorted(domi))
            if p in d:
                d[p] += 1
            else:
                d[p] = 1
        c = 0
        for n in d.values():
            s = n*(n-1)//2
            c += s
        return c

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
#         # Ot(n^2) where n = len(dominoes)
#         # Os(1)
#         count, n = 0, len(dominoes)
#         for i in range(n - 1):
#             for k in range(i + 1, n):
#                 count += dominoes[i] == dominoes[k] or dominoes[i] == list(reversed(dominoes[k]))
                    
#         return count
        
#         # Ot(n) where n = len(dominoes)
#         # Os(n)
        
#         count_dict = {}
#         total_count = 0
#         for d1, d2 in dominoes:
#             if (d1, d2) in count_dict:
#                 count_dict[(d1, d2)] += 1
#                 total_count += count_dict[(d1, d2)] - 1
#             elif (d2, d1) in count_dict:
#                 count_dict[(d2, d1)] += 1
#                 total_count += count_dict[(d2, d1)] - 1
#             else:
#                 count_dict[(d1, d2)] = 1
                
#         return total_count


        # Ot(n) where n = len(dominoes)
        # Os(n)
        
        count_dict = {}
        total_count = 0
        for d in dominoes:
            d = tuple(sorted(d))
            if d in count_dict:
                total_count += count_dict[tuple(d)]
                count_dict[d] += 1
            else:
                count_dict[d] = 1

        return total_count