// File: /workspace/github_cpp_makefile_star2_O2/ksabry[P]bfbrute/src/ProgramIterator.h
// Function: ProgramIterator<400ul, 32ul, 12ul, 32ul>::StringDistanceOutputRecursive[abi:cxx11](char const*, unsigned long, unsigned long, unsigned char*, unsigned long)
std::string StringDistanceOutputRecursive(const char* target, uint_fast32_t targetSize, uint_fast32_t shortCircuit, uint8_t* currentData, uint_fast32_t currentDataIdx)
	{
		if (targetSize == 0)
		{
			return std::string();
		}

		uint_fast32_t bestScore = 100000;
		std::string bestProgram = std::string(shortCircuit + 1, ' ');
		char c = target[0];

		// Compute best scores for reaching each specific data index
		uint_fast32_t dataDeltaScores[data_size];
		std::string dataDeltaPrograms[data_size];

		for (uint_fast32_t idx = 0; idx < data_size; idx++)
		{
			dataDeltaScores[idx] = abs(static_cast<int_fast32_t>(currentDataIdx - idx));
			dataDeltaPrograms[idx] = "";
			if (idx > currentDataIdx)
			{
				for (uint_fast32_t i = 0; i < idx - currentDataIdx; i++) dataDeltaPrograms[idx] += '>';
			}
			else
			{
				for (uint_fast32_t i = 0; i < currentDataIdx - idx; i++) dataDeltaPrograms[idx] += '<';
			}
		}
		for (int_fast32_t startDelta = -8; startDelta <= 8; startDelta++)
		{
			int_fast32_t startIdx = static_cast<int_fast32_t>(currentDataIdx) + startDelta;
			if (startIdx < 0 || startIdx >= data_size)
			{
				continue;
			}
			for (int_fast32_t innerDelta = -8; innerDelta <= 8; innerDelta++)
			{
				if (innerDelta == 0)
				{
					continue;
				}
				int_fast32_t innerIdx = startIdx;
				while (currentData[innerIdx])
				{
					innerIdx += innerDelta;
					if (innerIdx < 0 || innerIdx >= data_size)
					{
						goto loop_fail;
					}
				}
				for (int_fast32_t endDelta = -8; endDelta <= 8; endDelta++)
				{
					int_fast32_t endIdx = innerIdx + endDelta;
					if (endIdx < 0 || endIdx >= data_size)
					{
						continue;
					}
					uint_fast32_t dataDeltaScore = 2 + abs(startDelta) + abs(innerDelta) + abs(endDelta);
					if (dataDeltaScore < dataDeltaScores[endIdx])
					{
						dataDeltaScores[endIdx] = dataDeltaScore;
						dataDeltaPrograms[endIdx] = std::string();
						if (startDelta > 0)
						{
							for (uint_fast32_t i = 0; i < startDelta; i++) dataDeltaPrograms[endIdx] += '>';
						}
						else
						{
							for (uint_fast32_t i = 0; i < -startDelta; i++) dataDeltaPrograms[endIdx] += '<';
						}
						dataDeltaPrograms[endIdx] += '[';
						if (innerDelta > 0)
						{
							for (uint_fast32_t i = 0; i < innerDelta; i++) dataDeltaPrograms[endIdx] += '>';
						}
						else
						{
							for (uint_fast32_t i = 0; i < -innerDelta; i++) dataDeltaPrograms[endIdx] += '<';
						}
						dataDeltaPrograms[endIdx] += ']';
						if (endDelta > 0)
						{
							for (uint_fast32_t i = 0; i < endDelta; i++) dataDeltaPrograms[endIdx] += '>';
						}
						else
						{
							for (uint_fast32_t i = 0; i < -endDelta; i++) dataDeltaPrograms[endIdx] += '<';
						}
					}
				}
			loop_fail:;
			}
		}

		// Search through reaching each specific data index and directly modifying the data to match the next character
		for (uint_fast32_t newDataIdx = 0; newDataIdx < data_size; newDataIdx++)
		{
			uint_fast32_t charScore = 1 + dataDeltaScores[newDataIdx] + abs(static_cast<int8_t>(c - currentData[newDataIdx]));
			std::string charProgram = dataDeltaPrograms[newDataIdx];
			int8_t diff = static_cast<int8_t>(c - currentData[newDataIdx]);
			if (diff > 0)
			{
				for (uint_fast32_t i = 0; i < diff; i++) charProgram += '+';
			}
			else
			{
				for (uint_fast32_t i = 0; i < -diff; i++) charProgram += '-';
			}
			charProgram += '.';

			if (charScore > shortCircuit)
			{
				continue;
			}

			char oldData = currentData[newDataIdx];
			currentData[newDataIdx] = c;
			std::string restProgram = StringDistanceOutputRecursive(target + 1, targetSize - 1, shortCircuit - charScore, currentData, newDataIdx);
			uint_fast32_t restScore = restProgram.size();
			currentData[newDataIdx] = oldData;

			if (charScore + restScore < bestScore)
			{
				bestScore = charScore + restScore;
				bestProgram = charProgram + restProgram;
			}

#ifdef CASE_INSENSITIVE
			if ('a' <= c && c <= 'z')
			{
				char upperC = toupper(c);
				uint_fast32_t upperCharScore = 1 + dataDeltaScores[newDataIdx] + abs(static_cast<int8_t>(upperC - currentData[newDataIdx]));
				std::string upperCharProgram = dataDeltaPrograms[newDataIdx];
				int8_t diff = static_cast<int8_t>(upperC - currentData[newDataIdx]);
				if (diff > 0)
				{
					for (uint_fast32_t i = 0; i < diff; i++) upperCharProgram += '+';
				}
				else
				{
					for (uint_fast32_t i = 0; i < -diff; i++) upperCharProgram += '-';
				}
				upperCharProgram += '.';

				if (upperCharScore > shortCircuit)
				{
					continue;
				}

				char oldData = currentData[newDataIdx];
				currentData[newDataIdx] = upperC;
				std::string restProgram = StringDistanceOutputRecursive(target + 1, targetSize - 1, shortCircuit - upperCharScore, currentData, newDataIdx);
				uint_fast32_t restScore = restProgram.size();
				currentData[newDataIdx] = oldData;

				if (upperCharScore + restScore < bestScore)
				{
					bestScore = upperCharScore + restScore;
					bestProgram = upperCharProgram + restProgram;
				}
			}
#endif
		}
		return bestProgram;
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x3f68, %rsp           # imm = 0x3F68
movq %rsi, 0x58(%rsp)
movq %rcx, 0x38(%rsp)
testq %rcx, %rcx
je 0x7564
movq %rdx, %rbx
movq %r9, 0x28(%rsp)
movq %r8, 0x60(%rsp)
leaq 0x1(%r8), %rsi
leaq 0x10(%rdi), %rax
movq %rax, (%rdi)
pushq $0x20
popq %rdx
movq %rdi, 0x20(%rsp)
callq 0x2260
movq %rbx, 0x30(%rsp)
movb (%rbx), %al
movb %al, 0xf(%rsp)
pushq $0x10
popq %rax
leaq (%rsp,%rax), %rcx
addq $0xd60, %rcx            # imm = 0xD60
movq %rcx, -0x10(%rcx)
andq $0x0, -0x8(%rcx)
movb $0x0, (%rcx)
addq $0x20, %rax
cmpq $0x3210, %rax           # imm = 0x3210
jne 0x7103
xorl %r14d, %r14d
pushq $0x3e
popq %rbp
pushq $0x3c
popq %r15
movq 0x3fa0(%rsp), %rbx
cmpq $0x190, %r14            # imm = 0x190
je 0x71c5
movq 0x3fa0(%rsp), %rax
subq %r14, %rax
movq %rax, %rcx
negq %rcx
cmovsq %rax, %rcx
movq %rcx, 0xe0(%rsp,%r14,8)
movq %r14, %rax
shlq $0x5, %rax
leaq (%rsp,%rax), %r12
addq $0xd60, %r12            # imm = 0xD60
movq %r12, %rdi
leaq 0x15d7(%rip), %rsi      # 0x8755
callq 0x23c0
movq %rbx, %r13
cmpq %r14, 0x3fa0(%rsp)
jae 0x71a7
xorl %r13d, %r13d
cmpq %r13, %rbx
je 0x71ba
movq %r12, %rdi
movl %ebp, %esi
callq 0x21a0
decq %r13
jmp 0x7193
subq $0x1, %r13
jb 0x71ba
movq %r12, %rdi
movl %r15d, %esi
callq 0x21a0
jmp 0x71a7
incq %r14
decq %rbx
jmp 0x7138
pushq $-0x8
popq %rax
pushq $0x8
popq %rcx
pushq $0x3e
popq %rbp
pushq $0x3c
popq %r15
movq %rcx, 0x40(%rsp)
movq %rax, %rcx
cmpq $0x9, %rcx
movq 0x3fa0(%rsp), %rax
je 0x73da
movq %rcx, 0x18(%rsp)
addq %rcx, %rax
movq %rax, 0x70(%rsp)
cmpq $0x18f, %rax            # imm = 0x18F
jbe 0x7210
movq 0x18(%rsp), %rcx
incq %rcx
decq 0x40(%rsp)
jmp 0x71da
movq 0x18(%rsp), %rax
movq %rax, %rcx
negq %rcx
cmovsq %rax, %rcx
addq $0x2, %rcx
movq %rcx, 0x68(%rsp)
pushq $0x8
popq %rax
movq %rax, 0x48(%rsp)
pushq $-0x8
popq %rax
movq %rax, 0x10(%rsp)
testq %rax, %rax
je 0x7264
cmpq $0x9, 0x10(%rsp)
je 0x7201
movq 0x70(%rsp), %r14
movq 0x28(%rsp), %rax
cmpb $0x0, (%rax,%r14)
je 0x7273
addq 0x10(%rsp), %r14
cmpq $0x18f, %r14            # imm = 0x18F
jbe 0x724a
movq 0x10(%rsp), %rax
incq %rax
decq 0x48(%rsp)
jmp 0x7233
movq 0x10(%rsp), %rax
movq %rax, %rcx
negq %rcx
cmovsq %rax, %rcx
addq 0x68(%rsp), %rcx
movq %rcx, 0x78(%rsp)
pushq $0x8
popq %rax
movq %rax, 0x50(%rsp)
pushq $-0x8
popq %rbx
cmpq $0x9, %rbx
je 0x7264
leaq (%rbx,%r14), %rax
cmpq $0x18f, %rax            # imm = 0x18F
ja 0x73cd
movq %rbx, %rcx
negq %rcx
cmovsq %rbx, %rcx
addq 0x78(%rsp), %rcx
cmpq 0xe0(%rsp,%rax,8), %rcx
jae 0x73cd
leaq 0x90(%rsp), %rdx
movq %rdx, 0x80(%rsp)
andq $0x0, 0x88(%rsp)
movq %rcx, 0xe0(%rsp,%rax,8)
movb $0x0, 0x90(%rsp)
shlq $0x5, %rax
leaq (%rsp,%rax), %r13
addq $0xd60, %r13            # imm = 0xD60
movq %r13, %rdi
leaq 0x80(%rsp), %r12
movq %r12, %rsi
callq 0x2270
movq %r12, %rdi
callq 0x20b0
movq 0x40(%rsp), %r12
cmpq $0x0, 0x18(%rsp)
jle 0x734c
movq 0x18(%rsp), %r12
subq $0x1, %r12
jb 0x7352
movq %r13, %rdi
movl %ebp, %esi
callq 0x21a0
jmp 0x732f
movq %r13, %rdi
movl %r15d, %esi
callq 0x21a0
subq $0x1, %r12
jae 0x7341
movq %r13, %rdi
pushq $0x5b
popq %rsi
callq 0x21a0
movq 0x48(%rsp), %r12
cmpq $0x0, 0x10(%rsp)
jle 0x738c
movq 0x10(%rsp), %r12
subq $0x1, %r12
jb 0x7392
movq %r13, %rdi
movl %ebp, %esi
callq 0x21a0
jmp 0x736f
movq %r13, %rdi
movl %r15d, %esi
callq 0x21a0
subq $0x1, %r12
jae 0x7381
movq %r13, %rdi
pushq $0x5d
popq %rsi
callq 0x21a0
movq 0x50(%rsp), %r12
testq %rbx, %rbx
jle 0x73c7
movq %rbx, %r12
subq $0x1, %r12
jb 0x73cd
movq %r13, %rdi
movl %ebp, %esi
callq 0x21a0
jmp 0x73aa
movq %r13, %rdi
movl %r15d, %esi
callq 0x21a0
subq $0x1, %r12
jae 0x73bc
incq %rbx
decq 0x50(%rsp)
jmp 0x7297
incq 0x30(%rsp)
decq 0x38(%rsp)
movl $0x186a0, %eax          # imm = 0x186A0
movq %rax, 0x10(%rsp)
xorl %r14d, %r14d
leaq 0x80(%rsp), %rbx
pushq $0x2b
popq %rbp
cmpq $0x190, %r14            # imm = 0x190
je 0x753e
movq 0xe0(%rsp,%r14,8), %r12
movq 0x28(%rsp), %r13
movb (%r13,%r14), %r15b
movq %r14, %rax
shlq $0x5, %rax
leaq (%rsp,%rax), %rsi
addq $0xd60, %rsi            # imm = 0xD60
movq %rbx, %rdi
callq 0x22a0
movb 0xf(%rsp), %al
subb (%r13,%r14), %al
testb %al, %al
jle 0x7458
movzbl %al, %r13d
subq $0x1, %r13
jb 0x7471
movq %rbx, %rdi
movl %ebp, %esi
callq 0x21a0
jmp 0x7446
movsbq %al, %r13
testq %r13, %r13
je 0x7471
movq %rbx, %rdi
pushq $0x2d
popq %rsi
callq 0x21a0
incq %r13
jmp 0x745c
movq %rbx, %rdi
pushq $0x2e
popq %rsi
callq 0x21a0
movb 0xf(%rsp), %dl
movl %edx, %eax
subb %r15b, %al
movl %eax, %ecx
sarb $0x7, %cl
xorb %cl, %al
subb %cl, %al
movzbl %al, %eax
leaq (%r12,%rax), %r15
incq %r15
movq 0x60(%rsp), %r8
subq %r15, %r8
jb 0x752e
movq 0x28(%rsp), %r13
movb (%r13,%r14), %r12b
movb %dl, (%r13,%r14)
movq %r14, (%rsp)
leaq 0xa0(%rsp), %rdi
movq 0x58(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq 0x38(%rsp), %rcx
movq %r13, %r9
callq 0x70ac
addq 0xa8(%rsp), %r15
movb %r12b, (%r13,%r14)
cmpq 0x10(%rsp), %r15
leaq 0xc0(%rsp), %r12
jae 0x7521
movq %r12, %rdi
movq %rbx, %rsi
leaq 0xa0(%rsp), %rdx
callq 0x75fc
movq 0x20(%rsp), %rdi
movq %r12, %rsi
callq 0x2270
movq %r12, %rdi
callq 0x20b0
movq %r15, 0x10(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0x20b0
movq %rbx, %rdi
callq 0x20b0
incq %r14
jmp 0x73fc
movl $0x31e0, %ebx           # imm = 0x31E0
leaq (%rsp,%rbx), %rdi
addq $0xd60, %rdi            # imm = 0xD60
callq 0x20b0
addq $-0x20, %rbx
cmpq $-0x20, %rbx
jne 0x7543
movq 0x20(%rsp), %rdi
jmp 0x7574
leaq 0x10(%rdi), %rax
movq %rax, (%rdi)
andq $0x0, 0x8(%rdi)
movb $0x0, 0x10(%rdi)
movq %rdi, %rax
addq $0x3f68, %rsp           # imm = 0x3F68
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0xa0(%rsp), %rdi
callq 0x20b0
jmp 0x75ac
jmp 0x75a9
jmp 0x75a9
jmp 0x75c7
jmp 0x75c7
jmp 0x75a9
jmp 0x75c7
jmp 0x75c7
movq %rax, %rbx
leaq 0x80(%rsp), %rdi
callq 0x20b0
jmp 0x75ca
jmp 0x75c7
jmp 0x75c7
jmp 0x75c7
jmp 0x75c7
jmp 0x75c7
jmp 0x75c7
movq %rax, %rbx
movl $0x31e0, %r14d          # imm = 0x31E0
leaq (%rsp,%r14), %rdi
addq $0xd60, %rdi            # imm = 0xD60
callq 0x20b0
addq $-0x20, %r14
cmpq $-0x20, %r14
jne 0x75d0
movq 0x20(%rsp), %rdi
callq 0x20b0
movq %rbx, %rdi
callq 0x2390