I have this code where I create a list of valid sequences of 9 digits. Each sequence must only contain the digits 1-9, no zeroes.
Each digit must only occur once per sequence. There are 362880 valid sequences.
Example:
-------------
123456789 ; first valid sequence
123456798
123456879
...
...
987654321 ; last valid sequence
------------
This example writes the sequence as lines of ascii text. I did this to aid in visually inspecting the results. This algo works, but is painfully slow.
I am looking for ways to make this much faster. The result does not have to be ascii text. It could be binary data instead, or even dwords.
include \masm32\include\masm32rt.inc
.data
number dd 123456789 ; start with the first valid 'number'
numstring db 16 dup (0)
hOutput dd 0
outfile db "output.txt", 0
crlf db 0Dh, 0Ah, 0
bw dd 0
num1 db 0
num2 db 0
num3 db 0
num4 db 0
num5 db 0
num6 db 0
num7 db 0
num8 db 0
num9 db 0
.code
start:
invoke CreateFile, addr outfile, GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0
mov hOutput, eax
top:
invoke dwtoa, number, addr numstring ; generate decimal string from 'number'
lea ecx, numstring ; test if "0" is present, skip writing string
cmp byte ptr [ecx], "0"
jz skipit
cmp byte ptr [ecx+1], "0"
jz skipit
cmp byte ptr [ecx+2], "0"
jz skipit
cmp byte ptr [ecx+3], "0"
jz skipit
cmp byte ptr [ecx+4], "0"
jz skipit
cmp byte ptr [ecx+5], "0"
jz skipit
cmp byte ptr [ecx+6], "0"
jz skipit
cmp byte ptr [ecx+7], "0"
jz skipit
cmp byte ptr [ecx+8], "0"
jz skipit
mov num1, 0 ; zero out individual digit counters
mov num2, 0
mov num3, 0
mov num4, 0
mov num5, 0
mov num6, 0
mov num7, 0
mov num8, 0
mov num9, 0
mov edx, 0 ; clear counter
loop1:
.if byte ptr [ecx+edx] == "1" ; increment for occurence of each 'digit'
inc num1
.elseif byte ptr [ecx+edx] == "2"
inc num2
.elseif byte ptr [ecx+edx] == "3"
inc num3
.elseif byte ptr [ecx+edx] == "4"
inc num4
.elseif byte ptr [ecx+edx] == "5"
inc num5
.elseif byte ptr [ecx+edx] == "6"
inc num6
.elseif byte ptr [ecx+edx] == "7"
inc num7
.elseif byte ptr [ecx+edx] == "8"
inc num8
.elseif byte ptr [ecx+edx] == "9"
inc num9
.endif
inc edx ; increment counter
cmp edx, 9
jnz loop1
cmp num1, 1 ; check if any digit appears more than once
jnz skipit ; if so, skip writing string
cmp num2, 1
jnz skipit
cmp num3, 1
jnz skipit
cmp num4, 1
jnz skipit
cmp num5, 1
jnz skipit
cmp num6, 1
jnz skipit
cmp num7, 1
jnz skipit
cmp num8, 1
jnz skipit
cmp num9, 1
jnz skipit
invoke WriteFile, hOutput, addr numstring, 9, addr bw, 0 ; write string
invoke WriteFile, hOutput, addr crlf, 2, addr bw, 0 ; write CR/LF
skipit:
inc number
cmp number, 987654321 ; end after last valid 'number'
jle top
invoke CloseHandle, hOutput ; close handle :P
invoke ExitProcess, 0 : exit :)
end start
I am experimenting with ways of testing for valid sudoku grids. This will be a lookup table of sorts...
So, does anyone have any tips to make this much faster? I plan on using this code at runtime and not have to store a ~4MB listing in data.
Attachment removed, source code is above.