// File: /workspace/github_cpp_makefile_star2_O2/Manca[P]algorithms2/./assignment2.hpp
// Function: assignment2::clustering_big::run_algorithm(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
void run_algorithm(const std::string& inputFile)
        {
            std::fstream file(inputFile, std::ios::in);
            if (file.is_open())
            {
                PROFILE("Read input Clustering Big (slower algo)")
                int n, bpn;
                file >> n >> bpn;

                std::string node;
                std::getline(file, node);
                HashMap mapa;

                const int MAX_NODES = (int)std::pow(2, bpn);
                DataStructures::UnionFind uf(MAX_NODES); // total number of elements (2^24)

                while (std::getline(file, node))
                {
                    node.erase(std::remove_if(node.begin(), node.end(), [](char x) {return std::isspace(x); }), end(node));
                    std::bitset<24> bit_node(node);
                    int nodeNumber = bit_node.to_ulong();

                    mapa[nodeNumber] = false;
                }
                file.close();
                PROFILE_STOP();

                // generate distances
                std::vector<int> distances_one = generateHammingDistances(bpn, 1);
                std::vector<int> distances_two = generateHammingDistances(bpn, 2);
                int num_edg_cost_one = 0;
                int num_edg_cost_two = 0;

                PROFILE("Clustering big (slower algo)")
                // iterate through the map and find the neighbors
                for (auto& el : mapa)
                {
                    el.second = true;           // we won't bother to add already seen edge to UnionFind

                    for (auto d : distances_one)
                    {
                        int res = el.first ^ d;
                        auto exists = mapa.find(res);
                        if (exists != mapa.end() && !exists->second) // if it's found but not yet seen!
                        {
                            // add to UF (there is an edge from current element to the one 1 Hamming distance away)
                            num_edg_cost_one++;
                            uf.Union(exists->first, el.first);
                        }
                    }
                    for (auto d : distances_two)
                    {
                        int res = el.first ^ d;
                        auto exists = mapa.find(res);
                        if (exists != mapa.end() && !exists->second)
                        {
                            // add node connected to current one 2 Hamming distances away
                            num_edg_cost_two++;
                            uf.Union(exists->first, el.first);
                        }
                    }
                }
                PROFILE_STOP();
                // from total number of nodes (all clusters)
                // subtract leaders (clusters with nodes that are at most 2 Hamming distances away from each other)
                // and duplicated nodes to get number of clusters that are at least 3 Hamming distances away from others
                size_t totalNumberClusters = n - (MAX_NODES - uf.count()) - (n - mapa.size());
                std::cout << "Edges 1 Hamming distance away: " << num_edg_cost_one << std::endl;
                std::cout << "Edges 2 Hamming distances away: " << num_edg_cost_two << std::endl;
                std::cout << "Number of clusters: " << totalNumberClusters << std::endl;
                assert(totalNumberClusters == 6118);
            }
        }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2e8, %rsp            # imm = 0x2E8
movq %rdi, %rsi
leaq 0xd8(%rsp), %rdi
pushq $0x8
popq %rdx
callq 0x2360
leaq 0x158(%rsp), %rdi
callq 0x20c0
testb %al, %al
je 0x3c80
callq 0x725c
movq %rax, %rbx
leaq 0x9b8e(%rip), %rsi      # 0xd39e
leaq 0xa0(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x2120
leaq 0xa0(%rsp), %rsi
movq %rbx, %rdi
callq 0x72a6
leaq 0xa0(%rsp), %rdi
callq 0x2150
leaq 0xd8(%rsp), %rdi
leaq 0x34(%rsp), %rsi
callq 0x21a0
movq %rsp, %rsi
movq %rax, %rdi
callq 0x21a0
leaq 0x20(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0xd8(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x2080
leaq 0xd0(%rsp), %rax
movq %rax, -0x30(%rax)
movq $0x1, -0x28(%rax)
xorps %xmm0, %xmm0
movups %xmm0, -0x20(%rax)
movl $0x3f800000, -0x10(%rax) # imm = 0x3F800000
movups %xmm0, -0x8(%rax)
movl (%rsp), %edi
movsd 0x9820(%rip), %xmm0     # 0xd0d0
callq 0x22f0
cvttsd2si %xmm0, %esi
leaq 0x70(%rsp), %rdi
movl %esi, 0x30(%rsp)
callq 0x73a0
leaq 0x10(%rsp), %rbx
leaq 0xd8(%rsp), %rdi
movq %rbx, %rsi
callq 0x2080
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x3a59
movq 0x10(%rsp), %r13
movq 0x18(%rsp), %r14
leaq (%r14,%r13), %rbp
movq %r14, %r15
sarq $0x2, %r15
movq %r14, %rbx
movq %r13, 0x8(%rsp)
testq %r15, %r15
jle 0x3959
movq %r13, %rdi
callq 0x70e0
testb %al, %al
jne 0x3994
leaq 0x1(%r13), %r12
movq %r12, %rdi
callq 0x70e0
testb %al, %al
jne 0x3997
leaq 0x2(%r13), %r12
movq %r12, %rdi
callq 0x70e0
testb %al, %al
jne 0x3997
leaq 0x3(%r13), %r12
movq %r12, %rdi
callq 0x70e0
testb %al, %al
jne 0x3997
addq $0x4, %r13
decq %r15
addq $-0x4, %rbx
jmp 0x390b
cmpq $0x1, %rbx
je 0x3a31
cmpq $0x2, %rbx
je 0x3a1b
cmpq $0x3, %rbx
jne 0x3a4c
movq %r13, %rdi
callq 0x70e0
testb %al, %al
leaq 0x10(%rsp), %rbx
jne 0x3a44
incq %r13
jmp 0x3a20
movq %r13, %r12
leaq 0x10(%rsp), %rbx
cmpq %rbp, %r12
je 0x39d1
movq %r12, %r13
incq %r12
cmpq %rbp, %r12
je 0x39c5
movq %r12, %rdi
callq 0x70e0
testb %al, %al
jne 0x39a4
movb (%r12), %al
movb %al, (%r13)
incq %r13
jmp 0x39a4
movq 0x10(%rsp), %rax
movq 0x18(%rsp), %r14
jmp 0x39d9
movq %rbp, %r13
movq 0x8(%rsp), %rax
addq %rax, %r14
movq %rbx, %rdi
movq %r13, %rsi
movq %r14, %rdx
callq 0x20a0
leaq 0x50(%rsp), %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x74b2
movl 0x50(%rsp), %eax
movl %eax, 0x38(%rsp)
leaq 0xa0(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0xa62a
movb $0x0, (%rax)
jmp 0x38cc
leaq 0x10(%rsp), %rbx
movq %r13, %rdi
callq 0x70e0
testb %al, %al
jne 0x3a44
incq %r13
jmp 0x3a36
leaq 0x10(%rsp), %rbx
movq %r13, %rdi
callq 0x70e0
testb %al, %al
cmoveq %rbp, %r13
movq %r13, %r12
jmp 0x399c
movq %rbp, %r13
leaq 0x10(%rsp), %rbx
jmp 0x39d4
leaq 0xd8(%rsp), %rdi
callq 0x2040
callq 0x725c
movq %rax, %rdi
callq 0x72c8
movl (%rsp), %esi
leaq 0x38(%rsp), %rdi
pushq $0x1
popq %rdx
callq 0x3701
movl (%rsp), %esi
leaq 0x88(%rsp), %rdi
pushq $0x2
popq %rdx
callq 0x3701
callq 0x725c
movq %rax, %rbx
leaq 0x9921(%rip), %rsi      # 0xd3c6
leaq 0x50(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0x2120
leaq 0x50(%rsp), %rsi
movq %rbx, %rdi
callq 0x72a6
leaq 0x50(%rsp), %rbx
movq %rbx, %rdi
callq 0x2150
movl $0x0, 0x8(%rsp)
leaq 0xa0(%rsp), %r15
movq 0x10(%r15), %r13
xorl %r14d, %r14d
testq %r13, %r13
je 0x3b99
movb $0x1, 0xc(%r13)
movq 0x38(%rsp), %r12
movq 0x40(%rsp), %rbp
cmpq %rbp, %r12
je 0x3b3e
movl (%r12), %eax
xorl 0x8(%r13), %eax
movl %eax, 0x50(%rsp)
movq %r15, %rdi
movq %rbx, %rsi
callq 0xa98e
testq %rax, %rax
je 0x3b38
cmpb $0x0, 0xc(%rax)
jne 0x3b38
incl %r14d
movl 0x8(%rax), %esi
movl 0x8(%r13), %edx
leaq 0x70(%rsp), %rdi
callq 0x741e
addq $0x4, %r12
jmp 0x3afd
movq 0x88(%rsp), %r12
movq 0x90(%rsp), %rbp
cmpq %rbp, %r12
je 0x3b90
movl (%r12), %eax
xorl 0x8(%r13), %eax
movl %eax, 0x50(%rsp)
movq %r15, %rdi
movq %rbx, %rsi
callq 0xa98e
testq %rax, %rax
je 0x3b8a
cmpb $0x0, 0xc(%rax)
jne 0x3b8a
incl 0x8(%rsp)
movl 0x8(%rax), %esi
movl 0x8(%r13), %edx
leaq 0x70(%rsp), %rdi
callq 0x741e
addq $0x4, %r12
jmp 0x3b4e
movq (%r13), %r13
jmp 0x3ae5
callq 0x725c
movq %rax, %rdi
callq 0x72c8
movslq 0x34(%rsp), %r15
movl %r15d, %r12d
subl 0x30(%rsp), %r12d
addl 0x80(%rsp), %r12d
movq 0xb8(%rsp), %rbx
movq 0x1240e(%rip), %rdi     # 0x15fd8
leaq 0x9812(%rip), %rsi      # 0xd3e3
callq 0x2230
movq %rax, %rdi
movl %r14d, %esi
callq 0x2370
movq %rax, %rdi
callq 0x2160
movq 0x123e8(%rip), %rdi     # 0x15fd8
leaq 0x980c(%rip), %rsi      # 0xd403
callq 0x2230
movq %rax, %rdi
movl 0x8(%rsp), %esi
callq 0x2370
movq %rax, %rdi
callq 0x2160
movq 0x123c1(%rip), %rdi     # 0x15fd8
leaq 0x9806(%rip), %rsi      # 0xd424
callq 0x2230
movslq %r12d, %rcx
subq %r15, %rbx
addq %rcx, %rbx
movq %rax, %rdi
movq %rbx, %rsi
callq 0x21c0
movq %rax, %rdi
callq 0x2160
cmpq $0x17e6, %rbx           # imm = 0x17E6
jne 0x3c9f
leaq 0x88(%rsp), %rdi
callq 0x9cda
leaq 0x38(%rsp), %rdi
callq 0x9cda
leaq 0x70(%rsp), %rdi
callq 0x746c
leaq 0xa0(%rsp), %rdi
callq 0x8b30
leaq 0x10(%rsp), %rdi
callq 0x2150
leaq 0xd8(%rsp), %rdi
callq 0x20b0
addq $0x2e8, %rsp            # imm = 0x2E8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x9793(%rip), %rdi      # 0xd439
leaq 0x97a8(%rip), %rsi      # 0xd455
leaq 0x97b3(%rip), %rcx      # 0xd467
movl $0xec, %edx
callq 0x21b0
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x2150
jmp 0x3d0c
jmp 0x3d09
movq %rax, %rbx
jmp 0x3d19
jmp 0x3d02
movq %rax, %rbx
jmp 0x3d2d
movq %rax, %rbx
jmp 0x3d3a
movq %rax, %rbx
leaq 0xa0(%rsp), %rdi
jmp 0x3d3f
jmp 0x3cf1
jmp 0x3cf1
movq %rax, %rbx
jmp 0x3d44
jmp 0x3d09
jmp 0x3d02
jmp 0x3d09
jmp 0x3d02
jmp 0x3d02
jmp 0x3d02
movq %rax, %rbx
jmp 0x3d23
jmp 0x3d09
movq %rax, %rbx
leaq 0x88(%rsp), %rdi
callq 0x9cda
leaq 0x38(%rsp), %rdi
callq 0x9cda
leaq 0x70(%rsp), %rdi
callq 0x746c
leaq 0xa0(%rsp), %rdi
callq 0x8b30
leaq 0x10(%rsp), %rdi
callq 0x2150
leaq 0xd8(%rsp), %rdi
callq 0x20b0
movq %rbx, %rdi
callq 0x2380