// File: SilentAssassinMa[P]Sudoku-Solver/SudokuSolver.cpp
// Function: SudokuSolver::SimulatedAnnealing(double, int)
void SudokuSolver::SimulatedAnnealing(double temp, int steps)
{
    if (!isSolvable)
    {
        cout << "Error : The Input Sudoku Is Not Solvable" << endl;
        return;
    }

    /* 
    Here we use 243 - (sum of unique elements) as the energy of the sudoku,
    and we initialize it so that each subsquare containes all integers once only
    */
    cout << "The Original Sudoku is " << endl;
    PrintSudoku(OriginalSudoku);
    cout << endl;

    // Initialization
    for (int i = 1; i <= 9; i++)
    {
        for (int j = 1; j <= 9; j++)
        {
            if ((i % 3) == 1 && (j % 3) == 1)
            {
                int subsquare[10] = {0};
                // Find the missing integers
                for (int m = 0; m < 3; m++)
                {
                    for (int n = 0; n < 3; n++)
                    {
                        if (FindElement(OriginalSudoku, i + m, j + n) != 0)
                        {
                            subsquare[FindElement(OriginalSudoku, i + m, j + n)] = 1;
                        }
                    }
                }

                // Fill the rest
                for (int m = 0; m < 3; m++)
                {
                    for (int n = 0; n < 3; n++)
                    {

                        if (isChangeable[9 * (i + m - 1) + j + n - 1])
                        {
                            for (int l = 1; l <= 9; l++)
                            {
                                if (subsquare[l] == 0)
                                {
                                    Current[9 * (i + m - 1) + j + n - 1] = l;
                                    subsquare[l] = 1;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    srand((unsigned)time(NULL));

    double Temperature = temp < 0 ? 0.25 : temp;
    int MaxSteps = steps <= 0 ? 1e6 : steps;

    int Ebefore = 243 - UniqueElements(Current);

    // start loop
    int step;
    for (step = 0; step < MaxSteps; step++)
    {
        // pick a random block and two random changeable elements

        int xblock = 3 * (rand() % 3) + 1;
        int yblock = 3 * (rand() % 3) + 1;
        int x1, x2, y1, y2;

        do
        {
            x1 = rand() % 3 + xblock;
            y1 = rand() % 3 + yblock;
            x2 = rand() % 3 + xblock;
            y2 = rand() % 3 + yblock;
        } while (!isChangeable[9 * (x1 - 1) + (y1 - 1)] || !isChangeable[9 * (x2 - 1) + (y2 - 1)] ||
                 (x1 == x2 && y1 == y2));

        // exchange the chosen elements
        int temp;
        temp = Current[9 * (x1 - 1) + (y1 - 1)];
        Current[9 * (x1 - 1) + (y1 - 1)] = Current[9 * (x2 - 1) + (y2 - 1)];
        Current[9 * (x2 - 1) + (y2 - 1)] = temp;

        int Eafter = 243 - UniqueElements(Current);

        if (Eafter < Ebefore)
        {
            // cout << step << " " << Eafter << endl;
        }

        if (Eafter == 0)
            break;

        if (exp((Ebefore - Eafter) / Temperature) > (rand() % 10000 / (double)10001))
        {
            Ebefore = Eafter;
        }
        else
        {
            temp = Current[9 * (x1 - 1) + (y1 - 1)];
            Current[9 * (x1 - 1) + (y1 - 1)] = Current[9 * (x2 - 1) + (y2 - 1)];
            Current[9 * (x2 - 1) + (y2 - 1)] = temp;
        }
    }

    if (CheckConsistency(Current))
    {
        cout << "The Filled Sudoku is " << endl;
        PrintSudoku(Current);
    }
    else
    {
        cout << "The Sudoku is not solved, try more steps or different temperature" << endl;
    }

    cout << endl;
    cout << "Total Steps : " << step << endl;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x8(%rbp)
movsd %xmm0, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xa8(%rbp)
testb $0x1, 0x2e1(%rax)
jne 0x2fc2
movq 0x7036(%rip), %rdi      # 0x9fd8
leaq 0x40fc(%rip), %rsi      # 0x70a5
callq 0x2120
movq %rax, %rdi
movq 0x7010(%rip), %rsi      # 0x9fc8
callq 0x2150
jmp 0x3639
movq 0x700f(%rip), %rdi      # 0x9fd8
leaq 0x40fe(%rip), %rsi      # 0x70ce
callq 0x2120
movq %rax, %rdi
movq 0x6fe9(%rip), %rsi      # 0x9fc8
callq 0x2150
movq -0xa8(%rbp), %rdi
movq %rdi, %rsi
addq $0x8, %rsi
movq (%rdi), %rax
callq *0x40(%rax)
movq 0x6fd9(%rip), %rdi      # 0x9fd8
movq 0x6fc2(%rip), %rsi      # 0x9fc8
callq 0x2150
movl $0x1, -0x18(%rbp)
cmpl $0x9, -0x18(%rbp)
jg 0x31cb
movl $0x1, -0x1c(%rbp)
cmpl $0x9, -0x1c(%rbp)
jg 0x31bb
movl -0x18(%rbp), %eax
movl $0x3, %ecx
cltd
idivl %ecx
cmpl $0x1, %edx
jne 0x31ab
movl -0x1c(%rbp), %eax
movl $0x3, %ecx
cltd
idivl %ecx
cmpl $0x1, %edx
jne 0x31ab
leaq -0x50(%rbp), %rdi
xorl %esi, %esi
movl $0x28, %edx
callq 0x20a0
movl $0x0, -0x54(%rbp)
cmpl $0x3, -0x54(%rbp)
jge 0x30e0
movl $0x0, -0x58(%rbp)
cmpl $0x3, -0x58(%rbp)
jge 0x30d3
movq -0xa8(%rbp), %rdi
addq $0x8, %rdi
movl -0x18(%rbp), %esi
addl -0x54(%rbp), %esi
movl -0x1c(%rbp), %edx
addl -0x58(%rbp), %edx
callq 0x40b0
cmpl $0x0, %eax
je 0x30c6
movq -0xa8(%rbp), %rdi
addq $0x8, %rdi
movl -0x18(%rbp), %esi
addl -0x54(%rbp), %esi
movl -0x1c(%rbp), %edx
addl -0x58(%rbp), %edx
callq 0x40b0
cltq
movl $0x1, -0x50(%rbp,%rax,4)
jmp 0x30c8
movl -0x58(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x58(%rbp)
jmp 0x3079
jmp 0x30d5
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x306c
movl $0x0, -0x5c(%rbp)
cmpl $0x3, -0x5c(%rbp)
jge 0x31a9
movl $0x0, -0x60(%rbp)
cmpl $0x3, -0x60(%rbp)
jge 0x3199
movq -0xa8(%rbp), %rax
movl -0x18(%rbp), %ecx
addl -0x5c(%rbp), %ecx
subl $0x1, %ecx
imull $0x9, %ecx, %ecx
addl -0x1c(%rbp), %ecx
addl -0x60(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
testb $0x1, 0x290(%rax,%rcx)
je 0x3189
movl $0x1, -0x64(%rbp)
cmpl $0x9, -0x64(%rbp)
jg 0x3187
movslq -0x64(%rbp), %rax
cmpl $0x0, -0x50(%rbp,%rax,4)
jne 0x317a
movq -0xa8(%rbp), %rax
movl -0x64(%rbp), %edx
movl -0x18(%rbp), %ecx
addl -0x5c(%rbp), %ecx
subl $0x1, %ecx
imull $0x9, %ecx, %ecx
addl -0x1c(%rbp), %ecx
addl -0x60(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl %edx, 0x14c(%rax,%rcx,4)
movslq -0x64(%rbp), %rax
movl $0x1, -0x50(%rbp,%rax,4)
jmp 0x3187
jmp 0x317c
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x3132
jmp 0x3189
jmp 0x318b
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x30f8
jmp 0x319b
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x30e7
jmp 0x31ab
jmp 0x31ad
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x3023
jmp 0x31bd
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x3012
xorl %eax, %eax
movl %eax, %edi
callq 0x2100
movl %eax, %edi
callq 0x2110
xorps %xmm0, %xmm0
ucomisd -0x10(%rbp), %xmm0
jbe 0x31f7
movsd 0x3e53(%rip), %xmm0     # 0x7040
movsd %xmm0, -0xb0(%rbp)
jmp 0x3204
movsd -0x10(%rbp), %xmm0
movsd %xmm0, -0xb0(%rbp)
movsd -0xb0(%rbp), %xmm0
movsd %xmm0, -0x70(%rbp)
cmpl $0x0, -0x14(%rbp)
jg 0x3229
movsd 0x3df1(%rip), %xmm0     # 0x7010
movsd %xmm0, -0xb8(%rbp)
jmp 0x3236
cvtsi2sdl -0x14(%rbp), %xmm0
movsd %xmm0, -0xb8(%rbp)
movq -0xa8(%rbp), %rdi
movsd -0xb8(%rbp), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x74(%rbp)
movq %rdi, %rsi
addq $0x14c, %rsi            # imm = 0x14C
movq (%rdi), %rax
callq *0x38(%rax)
movl %eax, %ecx
movl $0xf3, %eax
subl %ecx, %eax
movl %eax, -0x78(%rbp)
movl $0x0, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
cmpl -0x74(%rbp), %eax
jge 0x357f
callq 0x2050
movl $0x3, %ecx
cltd
idivl %ecx
imull $0x3, %edx, %eax
addl $0x1, %eax
movl %eax, -0x80(%rbp)
callq 0x2050
movl $0x3, %ecx
cltd
idivl %ecx
imull $0x3, %edx, %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
callq 0x2050
movl $0x3, %ecx
cltd
idivl %ecx
addl -0x80(%rbp), %edx
movl %edx, -0x88(%rbp)
callq 0x2050
movl $0x3, %ecx
cltd
idivl %ecx
addl -0x84(%rbp), %edx
movl %edx, -0x90(%rbp)
callq 0x2050
movl $0x3, %ecx
cltd
idivl %ecx
addl -0x80(%rbp), %edx
movl %edx, -0x8c(%rbp)
callq 0x2050
movl $0x3, %ecx
cltd
idivl %ecx
addl -0x84(%rbp), %edx
movl %edx, -0x94(%rbp)
movq -0xa8(%rbp), %rcx
movl -0x88(%rbp), %eax
subl $0x1, %eax
imull $0x9, %eax, %eax
movl -0x90(%rbp), %edx
subl $0x1, %edx
addl %edx, %eax
movslq %eax, %rdx
movb $0x1, %al
testb $0x1, 0x290(%rcx,%rdx)
movb %al, -0xb9(%rbp)
je 0x33a5
movq -0xa8(%rbp), %rcx
movl -0x8c(%rbp), %eax
subl $0x1, %eax
imull $0x9, %eax, %eax
movl -0x94(%rbp), %edx
subl $0x1, %edx
addl %edx, %eax
movslq %eax, %rdx
movb $0x1, %al
testb $0x1, 0x290(%rcx,%rdx)
movb %al, -0xb9(%rbp)
je 0x33a5
movl -0x88(%rbp), %ecx
xorl %eax, %eax
cmpl -0x8c(%rbp), %ecx
movb %al, -0xba(%rbp)
jne 0x3399
movl -0x90(%rbp), %eax
cmpl -0x94(%rbp), %eax
sete %al
movb %al, -0xba(%rbp)
movb -0xba(%rbp), %al
movb %al, -0xb9(%rbp)
movb -0xb9(%rbp), %al
testb $0x1, %al
jne 0x32aa
movq -0xa8(%rbp), %rdi
movl -0x88(%rbp), %eax
subl $0x1, %eax
imull $0x9, %eax, %eax
movl -0x90(%rbp), %ecx
subl $0x1, %ecx
addl %ecx, %eax
cltq
movl 0x14c(%rdi,%rax,4), %eax
movl %eax, -0x98(%rbp)
movl -0x8c(%rbp), %eax
subl $0x1, %eax
imull $0x9, %eax, %eax
movl -0x94(%rbp), %ecx
subl $0x1, %ecx
addl %ecx, %eax
cltq
movl 0x14c(%rdi,%rax,4), %ecx
movl -0x88(%rbp), %eax
subl $0x1, %eax
imull $0x9, %eax, %eax
movl -0x90(%rbp), %edx
subl $0x1, %edx
addl %edx, %eax
cltq
movl %ecx, 0x14c(%rdi,%rax,4)
movl -0x98(%rbp), %ecx
movl -0x8c(%rbp), %eax
subl $0x1, %eax
imull $0x9, %eax, %eax
movl -0x94(%rbp), %edx
subl $0x1, %edx
addl %edx, %eax
cltq
movl %ecx, 0x14c(%rdi,%rax,4)
movq %rdi, %rsi
addq $0x14c, %rsi            # imm = 0x14C
movq (%rdi), %rax
callq *0x38(%rax)
movl %eax, %ecx
movl $0xf3, %eax
subl %ecx, %eax
movl %eax, -0x9c(%rbp)
movl -0x9c(%rbp), %eax
cmpl -0x78(%rbp), %eax
jge 0x3472
jmp 0x3472
cmpl $0x0, -0x9c(%rbp)
jne 0x3480
jmp 0x357f
movl -0x78(%rbp), %eax
subl -0x9c(%rbp), %eax
cvtsi2sd %eax, %xmm0
divsd -0x70(%rbp), %xmm0
callq 0x21e0
movsd %xmm0, -0xc8(%rbp)
callq 0x2050
movsd -0xc8(%rbp), %xmm0
movl $0x2710, %ecx           # imm = 0x2710
cltd
idivl %ecx
cvtsi2sd %edx, %xmm1
movsd 0x3b88(%rip), %xmm2     # 0x7048
divsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x34d8
movl -0x9c(%rbp), %eax
movl %eax, -0x78(%rbp)
jmp 0x356f
movq -0xa8(%rbp), %rax
movl -0x88(%rbp), %ecx
subl $0x1, %ecx
imull $0x9, %ecx, %ecx
movl -0x90(%rbp), %edx
subl $0x1, %edx
addl %edx, %ecx
movslq %ecx, %rcx
movl 0x14c(%rax,%rcx,4), %ecx
movl %ecx, -0x98(%rbp)
movl -0x8c(%rbp), %ecx
subl $0x1, %ecx
imull $0x9, %ecx, %ecx
movl -0x94(%rbp), %edx
subl $0x1, %edx
addl %edx, %ecx
movslq %ecx, %rcx
movl 0x14c(%rax,%rcx,4), %edx
movl -0x88(%rbp), %ecx
subl $0x1, %ecx
imull $0x9, %ecx, %ecx
movl -0x90(%rbp), %esi
subl $0x1, %esi
addl %esi, %ecx
movslq %ecx, %rcx
movl %edx, 0x14c(%rax,%rcx,4)
movl -0x98(%rbp), %edx
movl -0x8c(%rbp), %ecx
subl $0x1, %ecx
imull $0x9, %ecx, %ecx
movl -0x94(%rbp), %esi
subl $0x1, %esi
addl %esi, %ecx
movslq %ecx, %rcx
movl %edx, 0x14c(%rax,%rcx,4)
jmp 0x3571
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
jmp 0x326f
movq -0xa8(%rbp), %rdi
movq %rdi, %rsi
addq $0x14c, %rsi            # imm = 0x14C
movq (%rdi), %rax
callq *0x20(%rax)
testb $0x1, %al
jne 0x359c
jmp 0x35d7
movq 0x6a35(%rip), %rdi      # 0x9fd8
leaq 0x3b3c(%rip), %rsi      # 0x70e6
callq 0x2120
movq %rax, %rdi
movq 0x6a0f(%rip), %rsi      # 0x9fc8
callq 0x2150
movq -0xa8(%rbp), %rdi
movq %rdi, %rsi
addq $0x14c, %rsi            # imm = 0x14C
movq (%rdi), %rax
callq *0x40(%rax)
jmp 0x35f9
movq 0x69fa(%rip), %rdi      # 0x9fd8
leaq 0x3b26(%rip), %rsi      # 0x710b
callq 0x2120
movq %rax, %rdi
movq 0x69d4(%rip), %rsi      # 0x9fc8
callq 0x2150
movq 0x69d8(%rip), %rdi      # 0x9fd8
movq 0x69c1(%rip), %rsi      # 0x9fc8
callq 0x2150
movq 0x69c5(%rip), %rdi      # 0x9fd8
leaq 0x3ae2(%rip), %rsi      # 0x70fc
callq 0x2120
movq %rax, %rdi
movl -0x7c(%rbp), %esi
callq 0x21c0
movq %rax, %rdi
movq 0x6994(%rip), %rsi      # 0x9fc8
callq 0x2150
addq $0xd0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)