// File: /workspace/github_cpp_makefile_star2_O2/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, 0x10(%rsp)
andq $0x0, 0x20(%rsp)
leaq 0x98(%rsp), %rdi
pushq $0x8
popq %rdx
callq 0x2360
leaq 0x118(%rsp), %rdi
callq 0x20c0
testb %al, %al
je 0x3517
callq 0x725c
movq %rax, %rbx
leaq 0x9f32(%rip), %rsi      # 0xd38e
leaq 0x50(%rsp), %rdi
leaq 0x38(%rsp), %rdx
callq 0x2120
leaq 0x50(%rsp), %rsi
movq %rbx, %rdi
callq 0x72a6
leaq 0x50(%rsp), %rdi
callq 0x2150
leaq 0x98(%rsp), %rdi
leaq 0x34(%rsp), %rsi
callq 0x21a0
movl 0x34(%rsp), %esi
leaq 0x38(%rsp), %rdi
callq 0x73a0
leaq 0x98(%rsp), %rbx
leaq 0x30(%rsp), %r14
leaq 0x2c(%rsp), %r15
leaq 0x28(%rsp), %r12
leaq 0x10(%rsp), %r13
leaq 0x50(%rsp), %rbp
movq %rbx, %rdi
movq %r14, %rsi
callq 0x21a0
movq %rax, %rdi
movq %r15, %rsi
callq 0x21a0
movq %rax, %rdi
movq %r12, %rsi
callq 0x21a0
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x351f
movl 0x28(%rsp), %eax
movl %eax, 0x50(%rsp)
movl 0x2c(%rsp), %eax
movl %eax, 0x54(%rsp)
movl 0x30(%rsp), %eax
movl %eax, 0x58(%rsp)
movq %r13, %rdi
movq %rbp, %rsi
callq 0xa436
jmp 0x34c3
pushq $-0x1
popq %rbx
jmp 0x3671
movq 0x10(%rsp), %r14
movq 0x18(%rsp), %rbx
cmpq %rbx, %r14
je 0x3590
movq %rbx, %r15
subq %r14, %r15
pushq $0xc
popq %rcx
movq %r15, %rax
cqto
idivq %rcx
bsrq %rax, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x6dc6
cmpq $0xc1, %r15
jl 0x3585
leaq 0xc0(%r14), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0x705f
cmpq %rbx, %r15
je 0x3590
movq %r15, %rdi
callq 0x70b6
addq $0xc, %r15
jmp 0x3572
movq %r14, %rdi
movq %rbx, %rsi
callq 0x705f
movaps 0x9ad9(%rip), %xmm0     # 0xd070
leaq 0x50(%rsp), %rsi
movaps %xmm0, (%rsi)
movaps 0x9ada(%rip), %xmm0     # 0xd080
movaps %xmm0, 0x10(%rsi)
movaps 0x9adf(%rip), %xmm0     # 0xd090
movaps %xmm0, 0x20(%rsi)
leaq 0x80(%rsp), %rdi
pushq $0x4
popq %rdx
leaq 0xf(%rsp), %rcx
callq 0x71d4
leaq 0x38(%rsp), %rbx
cmpl $0x5, 0x48(%rsp)
jl 0x35f8
movq 0x18(%rsp), %rax
leaq -0xc(%rax), %rcx
movl -0x8(%rax), %edx
movl -0x4(%rax), %esi
movq %rcx, 0x18(%rsp)
decl %esi
decl %edx
movq %rbx, %rdi
callq 0x741e
jmp 0x35cf
leaq 0x98(%rsp), %rdi
callq 0x2040
movq 0x18(%rsp), %rcx
leaq -0xc(%rcx), %rdx
leaq -0x8(%rcx), %rax
addq $-0x4, %rcx
leaq 0x38(%rsp), %r14
movl (%rdx), %ebx
movl (%rax), %edx
movl (%rcx), %esi
decl %esi
decl %edx
movq %r14, %rdi
callq 0x748e
testb %al, %al
je 0x364d
movq 0x18(%rsp), %rax
leaq -0xc(%rax), %rcx
movq %rcx, 0x18(%rsp)
leaq -0x18(%rax), %rdx
leaq -0x10(%rax), %rcx
addq $-0x14, %rax
jmp 0x361b
callq 0x725c
movq %rax, %rdi
callq 0x72c8
leaq 0x80(%rsp), %rdi
callq 0x9d3e
leaq 0x38(%rsp), %rdi
callq 0x746c
leaq 0x98(%rsp), %rdi
callq 0x20b0
leaq 0x10(%rsp), %rdi
callq 0x9d3e
movl %ebx, %eax
addq $0x2a8, %rsp            # imm = 0x2A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x36d5
jmp 0x36bc
jmp 0x36d5
jmp 0x36b7
jmp 0x36b7
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x2150
jmp 0x36e2
jmp 0x36b7
movq %rax, %rbx
jmp 0x36e2
movq %rax, %rbx
leaq 0x80(%rsp), %rdi
callq 0x9d3e
jmp 0x36d8
movq %rax, %rbx
jmp 0x36ef
jmp 0x36d5
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x746c
leaq 0x98(%rsp), %rdi
callq 0x20b0
leaq 0x10(%rsp), %rdi
callq 0x9d3e
movq %rbx, %rdi
callq 0x2380