tags:

views:

623

answers:

3

so it's ugly, but it work, so here it is

squareExp2 can be 9 or 16

Square can be 3 or 4

length of the gridbox and gridbox1 array can be 0 to 80 or 0 to 255

(you see the pattern now)

this code is ran only one time, at runtime

 For j = 0 To squareExp2 - 1
     For i = 0 To squareExp2 - 1
         box = (j * squareExp2) + i

         gridbox(box) = ((j \ Square) * squareExp2 * Square) + ((j Mod Square) * Square) + (i \ Square) * squareExp2 + (i Mod Square)
         gridbox1(gridbox(box)) = ((j \ Square) * squareExp2 * Square) + (((j Mod Square) * Square) * Square)
     Next
 Next

goal of the code above is to move the code from

    k = (gridRow(pos) \ iSquare) * iSquare
    l = (gridCol(pos) \ iSquare) * iSquare

    For i = l To l + iSquare - 1
        For j = k To k + iSquare - 1
            box = (j * squareExp2) + i
            foundNumber(grid(box)) = grid(box)
        Next
    Next

to

   j = myGridbox1(i)
   For x = j To j + squareExp2 - 1
       foundNumber(grid(myGridbox(x))) = grid(myGridbox(x))
   Next

* edit *

in the end

            Dim Square2 As Integer = iSquare * iSquare
            Dim Square3 As Integer = Square2 * iSquare
            Dim Square4 As Integer = Square2 * Square2

            Dim j2_offset As Integer = 0
            For j2 As Integer = 0 To iSquare - 1
                Dim j1_offset As Integer = 0
                Dim j1_interleaved_offset As Integer = 0
                For j1 As Integer = 0 To iSquare - 1
                    Dim i2_offset As Integer = 0
                    Dim i2_interleaved_offset As Integer = 0
                    Dim j_offset_value As Integer = j2_offset + j1_offset
                    For i2 As Integer = 0 To iSquare - 1
                        Dim offset_value As Integer = j_offset_value + i2_offset
                        Dim interleaved_value As Integer = j2_offset + i2_interleaved_offset + j1_interleaved_offset
                        For i1 As Integer = 0 To iSquare - 1
                            box = offset_value + i1
                            gridbox(box) = interleaved_value + i1
                            gridbox1(gridbox(box)) = j_offset_value
                        Next
                        i2_offset += iSquare
                        i2_interleaved_offset += Square2
                    Next
                    j1_offset += Square2
                    j1_interleaved_offset += iSquare
                Next
                j2_offset += Square3
            Next

Update little followup, a few months later.

It was for a sudoku program and you can find where it being used here

+2  A: 

If I only got it right, this should do the same:

For j1 = 0 To square - 1
  For j2 = 0 To square - 1
    j = j1 * square + j2
    For i1 = 0 To square - 1
      For i2 = 0 To square - 1
        box = (j * squareExp2) + i1 * square + i2
        gridbox(box) = (((j1 * square + i1) * square + j2) * square) + i2
        gridbox1(gridbox(box)) = j * squareExp2
      Next
    Next
  Next
Next
Guffa
this one is working, I will wait 1-2 hours before marking the answer
Fredou
in a loop for 10sec, I can run that code 8.3 millions time
Fredou
+2  A: 

It looks like this is for generating a remap table from linear address to offset in same data in morton order. gridbox(y*squareExp2+x) is the offset in the swizzled data, and gridbox1(x) is the offset of the block.

This sort of thing is usually expressed as a sequence of bitwise operations, but this doesn't generalise to blocks of any dimension (e.g., 3x3).

I'm not aware of any neater way of doing it for arbitrary block sizes. The coordinate of the block must be known (it's (i\square,j\square)), the coordinate within the block must be known (it's (i mod square,j mod square)), each part of the block's coordinate has to be scaled by the block size in that dimension (squareExp2*square, j-wards, and squareExp2, i-wards), and the coordinate within the block has to be scaled in the j direction by the block's stride (square). So if there is no more than these calculations involved (and it looks like there isn't, though I might have got it wrong!) then I'm not sure there's anything else that can be squeezed out.

brone
you just gave me a few thing to read on, morton order and swizzled data. I didn't knew these definition. thanks!
Fredou
result of my question can be found here http://www.codeproject.com/KB/vb/CodeBehindSudoku.aspx , thanks!
Fredou
+2  A: 

Edit: final answer for real ultimate power!

So for gridbox, you are basically taking i and j and interleaving their digits in base(square). E.g., given i and j in base(scale), you are computing:

i(2)j(2)i(1)j(1)

Where (n) signifies the digit base(scale).

So that's easy enough to speed up: just keep a running tally of each digit's contribution to the final value of gridbox(...).

Speeding up gridbox1(...) is even easier. Basically, you are computing:

Square * Square *(j\Square * Square + (j Mod Square))

Now, (j Mod Square) expands to (j - j\Square*Square) which reduces the above to:

Square * Square *(j\Square * Square + (j - j\Square*Square))

Which simplifies to:

Square * Square *(j\Square * Square + j - j\Square*Square)

Which simplifies to:

Square * Square * (j)

Here's the final loop:

Dim Square2 = Square * Square
Dim Square3 = Square2 * Square
Dim Square4 = Square2 * Square2

Dim j2_offset = 0
Dim j2_interleaved_offset = 0
Dim j2_value_offset= 0
For j2 = 0 To Square - 1
    Dim j1_offset = 0
    Dim j1_interleaved_offset = 0
    For j1 = 0 To Square - 1
        Dim i2_offset = 0
        Dim i1_interleaved_offset = 0
        For i2 = 0 To Square - 1
            For i1 = 0 To Square - 1
                Dim box = j2_offset + j1_offset + i2_offset + i1
                gridbox(box) = j2_interleaved_offset + i2_interleaved_offset + j1_interleaved_offset + i1
                gridbox1(gridbox(box)) = j2_offset + j1_offset
            Next
            i2_offset += Square
            i2_interleaved_offset += Square2
        Next
        j1_offset += Square2
        j1_interleaved_offset += Square
    Next
    j2_offset += Square3
    j2_interleaved_offset += Square3
Next
MSN
don't worry about the syntax, when it's done I will try it and fix it if needed and I will tell you if it work, like I did with the other one
Fredou
question, is i2_interleaved_offset a typo of j2_interleaved_offset ?
Fredou
Nope. Basically, it's there to take i2i1 and j2j1 and merge them to form j2 i2 j1 i1.
MSN
ok, I asked because the variable was declared
Fredou
Oh right, missing that!
MSN
work perfectly and in a loop of 10sec I can run the code 10.8 millions time (my original code can run about 5 millions time)
Fredou
It's certainly not as fast as precomputing it though :( And you could probably make it faster by caching more intermediate results. But whatever.
MSN
I don't want an array of constant in my code, I want it calculated but your code is still 2x faster than mine which is good :-)
Fredou
i'm taking your answer, easy to read and fast(11.9 millions), I made a few change, look at my original post to see it (will be done in a few seconds)
Fredou
result of my question can be found here http://www.codeproject.com/KB/vb/CodeBehindSudoku.aspx , thanks!
Fredou