// File: 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:
subq $0x3e8, %rsp            # imm = 0x3E8
movq %rdi, 0x3d8(%rsp)
movl $0x4, 0x3d4(%rsp)
leaq 0x3b8(%rsp), %rdi
callq 0x10290
movq 0x3d8(%rsp), %rsi
leaq 0x1a8(%rsp), %rdi
movl $0x8, %edx
callq 0x3410
jmp 0x5413
leaq 0x1a8(%rsp), %rdi
callq 0x3430
movb %al, 0x77(%rsp)
jmp 0x5426
movb 0x77(%rsp), %al
testb $0x1, %al
jne 0x5433
jmp 0x59ad
callq 0x10a60
movq %rax, 0x68(%rsp)
jmp 0x543f
leaq 0x177(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x3470
movq 0x60(%rsp), %rdx
leaq 0x2aede(%rip), %rsi     # 0x3033b
leaq 0x178(%rsp), %rdi
callq 0x3360
jmp 0x546c
movq 0x68(%rsp), %rdi
leaq 0x178(%rsp), %rsi
callq 0x10ad0
jmp 0x5480
leaq 0x178(%rsp), %rdi
callq 0x31f0
leaq 0x177(%rsp), %rdi
callq 0x3300
leaq 0x1a8(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0x31e0
jmp 0x54b1
movl 0x170(%rsp), %esi
leaq 0x148(%rsp), %rdi
callq 0x10ca0
jmp 0x54c7
jmp 0x54c9
leaq 0x1a8(%rsp), %rdi
leaq 0x16c(%rsp), %rsi
callq 0x31e0
movq %rax, 0x58(%rsp)
jmp 0x54e5
movq 0x58(%rsp), %rdi
leaq 0x168(%rsp), %rsi
callq 0x31e0
movq %rax, 0x50(%rsp)
jmp 0x54fe
movq 0x50(%rsp), %rdi
leaq 0x164(%rsp), %rsi
callq 0x31e0
movq %rax, 0x48(%rsp)
jmp 0x5517
movq 0x48(%rsp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x3310
movb %al, 0x47(%rsp)
jmp 0x5531
movb 0x47(%rsp), %al
testb $0x1, %al
jne 0x553e
jmp 0x5615
leaq 0x13c(%rsp), %rdi
leaq 0x16c(%rsp), %rsi
leaq 0x168(%rsp), %rdx
leaq 0x164(%rsp), %rcx
callq 0x10b20
jmp 0x5565
leaq 0x3b8(%rsp), %rdi
leaq 0x13c(%rsp), %rsi
callq 0x10b60
jmp 0x557c
jmp 0x54c9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
jmp 0x59f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
jmp 0x59e9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
jmp 0x55ea
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
leaq 0x178(%rsp), %rdi
callq 0x31f0
leaq 0x177(%rsp), %rdi
callq 0x3300
jmp 0x59e9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
jmp 0x599e
leaq 0x3b8(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x10490
movq 0x38(%rsp), %rdi
movq %rax, 0x130(%rsp)
callq 0x104c0
movq %rax, 0x128(%rsp)
movq 0x130(%rsp), %rdi
movq 0x128(%rsp), %rsi
callq 0x5a10
jmp 0x5658
movl $0x1, 0xc4(%rsp)
movl $0x3, 0xc0(%rsp)
movl $0x2, 0xbc(%rsp)
leaq 0xc8(%rsp), %rdi
leaq 0xc4(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
leaq 0xbc(%rsp), %rcx
callq 0x10830
jmp 0x56a0
leaq 0xd4(%rsp), %rdi
movl $0x1, 0xb8(%rsp)
movl $0x4, 0xb4(%rsp)
movl $0x3, 0xb0(%rsp)
leaq 0xb8(%rsp), %rsi
leaq 0xb4(%rsp), %rdx
leaq 0xb0(%rsp), %rcx
callq 0x10830
jmp 0x56e8
leaq 0xe0(%rsp), %rdi
movl $0x1, 0xac(%rsp)
movl $0x2, 0xa8(%rsp)
movl $0x1, 0xa4(%rsp)
leaq 0xac(%rsp), %rsi
leaq 0xa8(%rsp), %rdx
leaq 0xa4(%rsp), %rcx
callq 0x10830
jmp 0x5730
leaq 0xec(%rsp), %rdi
movl $0x2, 0xa0(%rsp)
movl $0x4, 0x9c(%rsp)
movl $0x1, 0x98(%rsp)
leaq 0xa0(%rsp), %rsi
leaq 0x9c(%rsp), %rdx
leaq 0x98(%rsp), %rcx
callq 0x10830
jmp 0x5778
leaq 0xc8(%rsp), %rax
movq %rax, 0xf8(%rsp)
movq $0x4, 0x100(%rsp)
leaq 0x97(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x10870
movq 0x30(%rsp), %rcx
movq 0xf8(%rsp), %rsi
movq 0x100(%rsp), %rdx
leaq 0x108(%rsp), %rdi
callq 0x10880
jmp 0x57ca
leaq 0x97(%rsp), %rdi
callq 0x10a40
leaq 0x148(%rsp), %rdi
callq 0x10eb0
movl %eax, 0x2c(%rsp)
jmp 0x57ea
movl 0x2c(%rsp), %eax
cmpl $0x4, %eax
jle 0x58b4
leaq 0x3b8(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x10f10
movq 0x18(%rsp), %rdi
movl 0x8(%rax), %ecx
movl %ecx, 0x90(%rsp)
movq (%rax), %rax
movq %rax, 0x88(%rsp)
callq 0x10f50
leaq 0x88(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x10f70
movq 0x20(%rsp), %rdi
movl (%rax), %eax
decl %eax
movl %eax, 0x28(%rsp)
callq 0x105e0
movl 0x28(%rsp), %esi
movl (%rax), %edx
decl %edx
leaq 0x148(%rsp), %rdi
callq 0x10dc0
jmp 0x5863
jmp 0x57d7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
leaq 0x97(%rsp), %rdi
callq 0x10a40
jmp 0x599e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
leaq 0x108(%rsp), %rdi
callq 0x10760
jmp 0x599e
leaq 0x1a8(%rsp), %rdi
callq 0x3040
jmp 0x58c3
leaq 0x3b8(%rsp), %rdi
callq 0x10f10
movq (%rax), %rcx
movq %rcx, 0x7c(%rsp)
movl 0x8(%rax), %eax
movl %eax, 0x84(%rsp)
leaq 0x7c(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x10f70
movq 0x8(%rsp), %rdi
movl (%rax), %eax
decl %eax
movl %eax, 0x10(%rsp)
callq 0x105e0
movl 0x10(%rsp), %esi
movl (%rax), %edx
decl %edx
leaq 0x148(%rsp), %rdi
callq 0x10f80
movb %al, 0x17(%rsp)
jmp 0x591e
movb 0x17(%rsp), %al
testb $0x1, %al
jne 0x5928
jmp 0x5951
leaq 0x3b8(%rsp), %rdi
callq 0x10f50
leaq 0x3b8(%rsp), %rdi
callq 0x10f10
movq %rax, %rsi
leaq 0x7c(%rsp), %rdi
callq 0x10600
jmp 0x58e2
callq 0x10a60
movq %rax, (%rsp)
jmp 0x595c
movq (%rsp), %rdi
callq 0x10b90
jmp 0x5967
leaq 0x7c(%rsp), %rdi
callq 0x105f0
movl (%rax), %eax
movl %eax, 0x3e4(%rsp)
movl $0x1, 0x78(%rsp)
leaq 0x108(%rsp), %rdi
callq 0x10760
leaq 0x148(%rsp), %rdi
callq 0x10ec0
jmp 0x59c0
leaq 0x148(%rsp), %rdi
callq 0x10ec0
jmp 0x59e9
movl $0xffffffff, 0x3e4(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x78(%rsp)
leaq 0x1a8(%rsp), %rdi
callq 0x30c0
leaq 0x3b8(%rsp), %rdi
callq 0x10760
movl 0x3e4(%rsp), %eax
addq $0x3e8, %rsp            # imm = 0x3E8
retq
leaq 0x1a8(%rsp), %rdi
callq 0x30c0
leaq 0x3b8(%rsp), %rdi
callq 0x10760
movq 0x1a0(%rsp), %rdi
callq 0x3460