// File: mitchblank[P]qiksolve/qiksolve.cpp
// Function: Dictionary::recursiveSolve(AbstractSolutionAcceptor*, std::vector<unsigned int, std::allocator<unsigned int>> const&, AnswerSequence*) const
void Dictionary::recursiveSolve(AbstractSolutionAcceptor * const acceptor, Words const& active_words, AnswerSequence * const runningAnswersp) const
{
	assert(!active_words.empty());
	if (active_words.size() == 1) {	// We found an end node
		acceptor->acceptSolution(*runningAnswersp, active_words.front());
	} else {
		DividedWordList dl(wordLength());
		double best_entropy = -1.0;
		Word best_word = 0;
		// Of all of the words in active_words, find the one that
		// will gives us the most even split (and thus the highest entropy)
		{
			auto it = keys_.cbegin();
			do {
				dl.build(*this, active_words, *it);
				double const entropy = dl.entropy();
				if (entropy > best_entropy) {
					best_entropy = entropy;
					best_word = *it;
				}
			} while (++it != keys_.cend());
		}
		assert(popcount32(best_word) == wordLength());
		// Now that we have found our best word, recompute the split
		dl.build(*this, active_words, best_word);
		assert(dl.entropy() == best_entropy);
		acceptor->acceptBranch(*runningAnswersp, best_word, best_entropy, dl);
		// Now recursively descend
		for (unsigned i = 0; i < wordLength() + 1; i++) {
			const WordsWithTotalChoices& wwtc = dl[i];
			if (wwtc.count() > 0) {
				runningAnswersp->push_back(i);
				recursiveSolve(acceptor, wwtc.choices(), runningAnswersp);
				runningAnswersp->pop_back();
			}
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x18(%rbp), %rdi
callq 0x4550
xorb $-0x1, %al
testb $0x1, %al
jne 0x2db7
jmp 0x2db9
jmp 0x2dd8
leaq 0xa373(%rip), %rdi      # 0xd133
leaq 0xa292(%rip), %rsi      # 0xd059
movl $0x18b, %edx            # imm = 0x18B
leaq 0xa376(%rip), %rcx      # 0xd149
callq 0x20e0
movq -0x18(%rbp), %rdi
callq 0x4df0
cmpq $0x1, %rax
jne 0x2e21
movq -0x10(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x18(%rbp), %rdi
callq 0x4e40
movq -0x98(%rbp), %rdi
movq -0x90(%rbp), %rsi
movl (%rax), %edx
movq (%rdi), %rax
callq *0x18(%rax)
jmp 0x3104
movq -0x88(%rbp), %rdi
callq 0x4bb0
movl %eax, %esi
leaq -0x38(%rbp), %rdi
callq 0x4e70
movq -0x88(%rbp), %rdi
movsd 0xa201(%rip), %xmm0     # 0xd048
movsd %xmm0, -0x40(%rbp)
movl $0x0, -0x44(%rbp)
addq $0x30, %rdi
callq 0x4590
movq %rax, -0x50(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0xa0(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x45c0
movq -0x88(%rbp), %rsi
movq -0xa0(%rbp), %rdx
movl (%rax), %ecx
leaq -0x38(%rbp), %rdi
callq 0x2990
jmp 0x2e8f
leaq -0x38(%rbp), %rdi
callq 0x2b90
movsd %xmm0, -0xa8(%rbp)
jmp 0x2ea2
movsd -0xa8(%rbp), %xmm0
movsd %xmm0, -0x68(%rbp)
movsd -0x68(%rbp), %xmm0
ucomisd -0x40(%rbp), %xmm0
jbe 0x2eef
movsd -0x68(%rbp), %xmm0
movsd %xmm0, -0x40(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x45c0
movl (%rax), %eax
movl %eax, -0x44(%rbp)
jmp 0x2eef
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x4f00
jmp 0x310d
jmp 0x2ef1
leaq -0x50(%rbp), %rdi
callq 0x4620
movq -0x88(%rbp), %rdi
movq %rax, -0xb0(%rbp)
addq $0x30, %rdi
callq 0x4640
movq -0xb0(%rbp), %rdi
movq %rax, -0x70(%rbp)
leaq -0x70(%rbp), %rsi
callq 0x45e0
testb $0x1, %al
jne 0x2e60
movq -0x88(%rbp), %rdi
movl -0x44(%rbp), %ecx
movl %ecx, %eax
shrl %eax
andl $0x55555555, %eax       # imm = 0x55555555
subl %eax, %ecx
movl %ecx, %eax
andl $0x33333333, %eax       # imm = 0x33333333
shrl $0x2, %ecx
andl $0x33333333, %ecx       # imm = 0x33333333
addl %ecx, %eax
movl %eax, %ecx
shrl $0x4, %ecx
addl %ecx, %eax
andl $0xf0f0f0f, %eax        # imm = 0xF0F0F0F
imull $0x1010101, %eax, %eax  # imm = 0x1010101
shrl $0x18, %eax
movl %eax, -0xb8(%rbp)
callq 0x4bb0
movl %eax, -0xb4(%rbp)
jmp 0x2f7c
movl -0xb8(%rbp), %eax
movl -0xb4(%rbp), %ecx
cmpl %ecx, %eax
jne 0x2f8e
jmp 0x2fad
leaq 0xa221(%rip), %rdi      # 0xd1b6
leaq 0xa0bd(%rip), %rsi      # 0xd059
movl $0x19f, %edx            # imm = 0x19F
leaq 0xa1a1(%rip), %rcx      # 0xd149
callq 0x20e0
movq -0x88(%rbp), %rsi
movq -0x18(%rbp), %rdx
movl -0x44(%rbp), %ecx
leaq -0x38(%rbp), %rdi
callq 0x2990
jmp 0x2fc6
leaq -0x38(%rbp), %rdi
callq 0x2b90
movsd %xmm0, -0xc0(%rbp)
jmp 0x2fd9
movsd -0xc0(%rbp), %xmm0
ucomisd -0x40(%rbp), %xmm0
jne 0x2fec
jp 0x2fec
jmp 0x300b
leaq 0xa1e9(%rip), %rdi      # 0xd1dc
leaq 0xa05f(%rip), %rsi      # 0xd059
movl $0x1a2, %edx            # imm = 0x1A2
leaq 0xa143(%rip), %rcx      # 0xd149
callq 0x20e0
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl -0x44(%rbp), %edx
movsd -0x40(%rbp), %xmm0
movq (%rdi), %rax
movq 0x10(%rax), %rax
leaq -0x38(%rbp), %rcx
callq *%rax
jmp 0x302a
movl $0x0, -0x74(%rbp)
movq -0x88(%rbp), %rdi
movl -0x74(%rbp), %eax
movl %eax, -0xc8(%rbp)
callq 0x4bb0
movl %eax, -0xc4(%rbp)
jmp 0x304e
movl -0xc8(%rbp), %eax
movl -0xc4(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jae 0x30fb
movl -0x74(%rbp), %eax
movl %eax, %esi
leaq -0x38(%rbp), %rdi
callq 0x4ce0
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rdi
callq 0x4dc0
movq %rax, -0xd0(%rbp)
jmp 0x3089
movq -0xd0(%rbp), %rax
cmpq $0x0, %rax
jbe 0x30eb
movq -0x20(%rbp), %rdi
leaq -0x74(%rbp), %rsi
callq 0x49f0
jmp 0x30a5
movq -0x10(%rbp), %rax
movq %rax, -0xe0(%rbp)
movq -0x80(%rbp), %rdi
callq 0x4de0
movq %rax, -0xd8(%rbp)
jmp 0x30c2
movq -0xd8(%rbp), %rdx
movq -0xe0(%rbp), %rsi
movq -0x88(%rbp), %rdi
movq -0x20(%rbp), %rcx
callq 0x2d80
jmp 0x30e2
movq -0x20(%rbp), %rdi
callq 0x4ed0
jmp 0x30ed
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x3031
leaq -0x38(%rbp), %rdi
callq 0x4f00
addq $0xe0, %rsp
popq %rbp
retq
movq -0x58(%rbp), %rdi
callq 0x2290
nopw %cs:(%rax,%rax)