// File: /workspace/github_cpp_makefile_star2_O3/Manca[P]algorithms2/./assignment2.hpp
// Function: assignment2::four_clustering::four_clustering(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
int four_clustering(const std::string& inputFile)
        {
            const int K = 4;    // four clusters
            typedef std::tuple<int, int, int> Edge;
            std::vector<Edge> edges;

            std::fstream file(inputFile, std::ios::in);
            if (file.is_open())
            {
                PROFILE("Four Clustering")
                int n;
                int x, y, c;
                file >> n;
                // we'll use UnionFind for computing 4 clusters
                DataStructures::UnionFind uf(n);
                while (file >> x >> y >> c)
                {
                    edges.push_back(std::make_tuple(x, y, c));
                }

                // first step, sort edges in decreasing order of distances (because can't pop from front on std::vector)
                std::sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b)
                {
                    return (std::get<2>(a) > std::get<2>(b));
                });

                std::vector<Edge> test1 = { std::make_tuple(1, 3, 2), std::make_tuple(1, 4, 3), std::make_tuple(1, 2, 1), std::make_tuple(2,4,1) };

                while (uf.count() > K)
                {
                    Edge connect = edges.back();                                  // take the min cost edge
                    edges.pop_back();                                            // remove it from the set
                    uf.Union(std::get<0>(connect) - 1, std::get<1>(connect) - 1);   // and connect the points
                }
                file.close();

                // let's loop through the remaining edges and find the first cluster not connected to one of our 4 clusters
                Edge remaining = edges.back();
                while (uf.connected(std::get<0>(remaining) - 1, std::get<1>(remaining) - 1))
                {
                    edges.pop_back();
                    remaining = edges.back();
                }
                PROFILE_STOP();

                return std::get<2>(remaining);  // just get the edge weight, corresponding to max-spacing
            }
            return -1;
        }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2a8, %rsp            # imm = 0x2A8
movq %rdi, %rsi
xorps %xmm0, %xmm0
movaps %xmm0, 0x20(%rsp)
movq $0x0, 0x30(%rsp)
leaq 0x98(%rsp), %rdi
movl $0x8, %edx
callq 0x2330
leaq 0x118(%rsp), %rdi
callq 0x20b0
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
testb %al, %al
je 0x3aea
callq 0x88f8
movq %rax, %rbx
leaq 0x60(%rsp), %r14
movq %r14, -0x10(%r14)
leaq 0xab30(%rip), %rsi      # 0xe3de
leaq 0xab38(%rip), %rdx      # 0xe3ed
leaq 0x50(%rsp), %rdi
callq 0xbb78
leaq 0x50(%rsp), %rsi
movq %rbx, %rdi
callq 0x8942
movq 0x50(%rsp), %rdi
cmpq %r14, %rdi
je 0x38db
callq 0x21f0
leaq 0x98(%rsp), %rdi
leaq 0x1c(%rsp), %rsi
callq 0x2160
movl 0x1c(%rsp), %esi
leaq 0x38(%rsp), %rdi
callq 0x8ab6
leaq 0x98(%rsp), %rbx
leaq 0x18(%rsp), %r14
leaq 0x14(%rsp), %r15
leaq 0x10(%rsp), %r12
leaq 0x20(%rsp), %r13
leaq 0x50(%rsp), %rbp
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2160
movq %rax, %rdi
movq %r15, %rsi
callq 0x2160
movq %rax, %rdi
movq %r12, %rsi
callq 0x2160
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x3970
movl 0x10(%rsp), %eax
movl %eax, 0x50(%rsp)
movl 0x14(%rsp), %eax
movl %eax, 0x54(%rsp)
movl 0x18(%rsp), %eax
movl %eax, 0x58(%rsp)
movq %r13, %rdi
movq %rbp, %rsi
callq 0xbc0e
jmp 0x391c
movq 0x20(%rsp), %r14
movq 0x28(%rsp), %rbx
cmpq %rbx, %r14
je 0x39eb
movq %rbx, %r15
subq %r14, %r15
movq %r15, %rax
sarq $0x2, %rax
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rax, %rcx
bsrq %rcx, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x83a4
cmpq $0xc1, %r15
jl 0x39e0
leaq 0xc0(%r14), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0x86b8
cmpq %rbx, %r15
je 0x39eb
movq %r15, %rdi
callq 0x8771
addq $0xc, %r15
jmp 0x39cd
movq %r14, %rdi
movq %rbx, %rsi
callq 0x86b8
movaps 0xa6ae(%rip), %xmm0     # 0xe0a0
leaq 0x50(%rsp), %rsi
movaps %xmm0, (%rsi)
movaps 0xa6af(%rip), %xmm0     # 0xe0b0
movaps %xmm0, 0x10(%rsi)
movaps 0xa6b4(%rip), %xmm0     # 0xe0c0
movaps %xmm0, 0x20(%rsi)
leaq 0x80(%rsp), %rdi
leaq 0xf(%rsp), %rcx
movl $0x4, %edx
callq 0x8850
cmpl $0x5, 0x48(%rsp)
jl 0x3a5a
leaq 0x38(%rsp), %rbx
movq 0x28(%rsp), %rax
leaq -0xc(%rax), %rcx
movl -0x8(%rax), %edx
movl -0x4(%rax), %esi
movq %rcx, 0x28(%rsp)
decl %esi
decl %edx
movq %rbx, %rdi
callq 0x8bb0
cmpl $0x4, 0x48(%rsp)
jg 0x3a33
leaq 0x98(%rsp), %rdi
callq 0x2050
movq 0x28(%rsp), %rax
leaq -0xc(%rax), %rdx
leaq -0x8(%rax), %rdi
leaq -0x4(%rax), %rsi
movq 0x38(%rsp), %rcx
movl (%rdx), %ebx
movl (%rdi), %edx
movl (%rsi), %edi
decl %edi
movl %edi, %esi
movslq %edi, %r8
movl (%rcx,%r8,4), %edi
cmpl %r8d, %edi
jne 0x3a85
decl %edx
movl %edx, %edi
movslq %edx, %r8
movl (%rcx,%r8,4), %edx
cmpl %r8d, %edx
jne 0x3a95
cmpl %edi, %esi
jne 0x3ac1
leaq -0x18(%rax), %rdx
leaq -0x10(%rax), %rsi
movq %rax, %rdi
addq $-0xc, %rax
movq %rax, 0x28(%rsp)
addq $-0x14, %rdi
jmp 0x3a7d
callq 0x88f8
movq %rax, %rdi
callq 0x898c
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x3ae0
callq 0x21f0
leaq 0x38(%rsp), %rdi
callq 0x8bf8
leaq 0x98(%rsp), %rdi
callq 0x20a0
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x3b06
callq 0x21f0
movl %ebx, %eax
addq $0x2a8, %rsp            # imm = 0x2A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3b3d
jmp 0x3b56
jmp 0x3b38
jmp 0x3b38
movq %rax, %rbx
movq 0x50(%rsp), %rdi
cmpq %r14, %rdi
je 0x3b63
callq 0x21f0
jmp 0x3b63
jmp 0x3b38
movq %rax, %rbx
jmp 0x3b63
movq %rax, %rbx
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x3b59
callq 0x21f0
jmp 0x3b59
jmp 0x3b56
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x8bf8
leaq 0x98(%rsp), %rdi
callq 0x20a0
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x3b7f
callq 0x21f0
movq %rbx, %rdi
callq 0x2350