index to coordinates in diagonal (zigzag) traverse












2















So I have a 4x4 matrix like so



 |0 1 2 3
-+-------
0|0 1 3 6
1|2 4 7 a
2|5 8 b d
3|9 c e f


and I am traversing it in the order specified by the hexadecimal characters in it. so start at (0, 0), then (1, 0), (0, 1), (2, 0), (1, 1), (0, 2)...



So here is the code:



def diagonal(n):
for a in range(n):
for b in range(a + 1):
yield a - b, b
for a in range(n - 1):
for b in range(n - a - 1):
yield n - b - 1, b + 1 + a


iterating through this gives



for x, y in diagonal(4):
print((x, y))

# (0, 0)
# (1, 0)
# (0, 1)
# (2, 0)
# (1, 1)
# (0, 2)
# (3, 0)
# (2, 1)
# (1, 2)
# (0, 3)
# (3, 1)
# (2, 2)
# (1, 3)
# (3, 2)
# (2, 3)
# (3, 3)


which is exactly as I intended. The part I am stuck on is trying to make a function where I give it the index, and it gives me the coordinates. So for my 4x4 matrix,(this is still in hexadecimal)



0 -> (0, 0)
1 -> (1, 0)
2 -> (0, 1)
3 -> (2, 0)
4 -> (1, 1)
5 -> (0, 2)
6 -> (3, 0)
7 -> (2, 1)
8 -> (1, 2)
9 -> (0, 3)
a -> (3, 1)
b -> (2, 2)
c -> (1, 3)
d -> (3, 2)
e -> (2, 3)
f -> (3, 3)


I have intentions to move on to variable sized square matrices so I cannot just hard code these values into a dict.



I have been tinkering for hours trying to get this to work but I cannot for the life of me get it to work.



This is not homework, just something I'm working on in my spare time, and it's slowly driving me up the wall.



If anything is not clear please don't hesitate to ask.



Thanks in advance.



Edit:
I presume someone will comment about this post Traverse Matrix in Diagonal strips which is similar but as with my first function this only iterates over the coordinates, and I cannot work out the coordinates from an index.










share|improve this question





























    2















    So I have a 4x4 matrix like so



     |0 1 2 3
    -+-------
    0|0 1 3 6
    1|2 4 7 a
    2|5 8 b d
    3|9 c e f


    and I am traversing it in the order specified by the hexadecimal characters in it. so start at (0, 0), then (1, 0), (0, 1), (2, 0), (1, 1), (0, 2)...



    So here is the code:



    def diagonal(n):
    for a in range(n):
    for b in range(a + 1):
    yield a - b, b
    for a in range(n - 1):
    for b in range(n - a - 1):
    yield n - b - 1, b + 1 + a


    iterating through this gives



    for x, y in diagonal(4):
    print((x, y))

    # (0, 0)
    # (1, 0)
    # (0, 1)
    # (2, 0)
    # (1, 1)
    # (0, 2)
    # (3, 0)
    # (2, 1)
    # (1, 2)
    # (0, 3)
    # (3, 1)
    # (2, 2)
    # (1, 3)
    # (3, 2)
    # (2, 3)
    # (3, 3)


    which is exactly as I intended. The part I am stuck on is trying to make a function where I give it the index, and it gives me the coordinates. So for my 4x4 matrix,(this is still in hexadecimal)



    0 -> (0, 0)
    1 -> (1, 0)
    2 -> (0, 1)
    3 -> (2, 0)
    4 -> (1, 1)
    5 -> (0, 2)
    6 -> (3, 0)
    7 -> (2, 1)
    8 -> (1, 2)
    9 -> (0, 3)
    a -> (3, 1)
    b -> (2, 2)
    c -> (1, 3)
    d -> (3, 2)
    e -> (2, 3)
    f -> (3, 3)


    I have intentions to move on to variable sized square matrices so I cannot just hard code these values into a dict.



    I have been tinkering for hours trying to get this to work but I cannot for the life of me get it to work.



    This is not homework, just something I'm working on in my spare time, and it's slowly driving me up the wall.



    If anything is not clear please don't hesitate to ask.



    Thanks in advance.



    Edit:
    I presume someone will comment about this post Traverse Matrix in Diagonal strips which is similar but as with my first function this only iterates over the coordinates, and I cannot work out the coordinates from an index.










    share|improve this question



























      2












      2








      2








      So I have a 4x4 matrix like so



       |0 1 2 3
      -+-------
      0|0 1 3 6
      1|2 4 7 a
      2|5 8 b d
      3|9 c e f


      and I am traversing it in the order specified by the hexadecimal characters in it. so start at (0, 0), then (1, 0), (0, 1), (2, 0), (1, 1), (0, 2)...



      So here is the code:



      def diagonal(n):
      for a in range(n):
      for b in range(a + 1):
      yield a - b, b
      for a in range(n - 1):
      for b in range(n - a - 1):
      yield n - b - 1, b + 1 + a


      iterating through this gives



      for x, y in diagonal(4):
      print((x, y))

      # (0, 0)
      # (1, 0)
      # (0, 1)
      # (2, 0)
      # (1, 1)
      # (0, 2)
      # (3, 0)
      # (2, 1)
      # (1, 2)
      # (0, 3)
      # (3, 1)
      # (2, 2)
      # (1, 3)
      # (3, 2)
      # (2, 3)
      # (3, 3)


      which is exactly as I intended. The part I am stuck on is trying to make a function where I give it the index, and it gives me the coordinates. So for my 4x4 matrix,(this is still in hexadecimal)



      0 -> (0, 0)
      1 -> (1, 0)
      2 -> (0, 1)
      3 -> (2, 0)
      4 -> (1, 1)
      5 -> (0, 2)
      6 -> (3, 0)
      7 -> (2, 1)
      8 -> (1, 2)
      9 -> (0, 3)
      a -> (3, 1)
      b -> (2, 2)
      c -> (1, 3)
      d -> (3, 2)
      e -> (2, 3)
      f -> (3, 3)


      I have intentions to move on to variable sized square matrices so I cannot just hard code these values into a dict.



      I have been tinkering for hours trying to get this to work but I cannot for the life of me get it to work.



      This is not homework, just something I'm working on in my spare time, and it's slowly driving me up the wall.



      If anything is not clear please don't hesitate to ask.



      Thanks in advance.



      Edit:
      I presume someone will comment about this post Traverse Matrix in Diagonal strips which is similar but as with my first function this only iterates over the coordinates, and I cannot work out the coordinates from an index.










      share|improve this question
















      So I have a 4x4 matrix like so



       |0 1 2 3
      -+-------
      0|0 1 3 6
      1|2 4 7 a
      2|5 8 b d
      3|9 c e f


      and I am traversing it in the order specified by the hexadecimal characters in it. so start at (0, 0), then (1, 0), (0, 1), (2, 0), (1, 1), (0, 2)...



      So here is the code:



      def diagonal(n):
      for a in range(n):
      for b in range(a + 1):
      yield a - b, b
      for a in range(n - 1):
      for b in range(n - a - 1):
      yield n - b - 1, b + 1 + a


      iterating through this gives



      for x, y in diagonal(4):
      print((x, y))

      # (0, 0)
      # (1, 0)
      # (0, 1)
      # (2, 0)
      # (1, 1)
      # (0, 2)
      # (3, 0)
      # (2, 1)
      # (1, 2)
      # (0, 3)
      # (3, 1)
      # (2, 2)
      # (1, 3)
      # (3, 2)
      # (2, 3)
      # (3, 3)


      which is exactly as I intended. The part I am stuck on is trying to make a function where I give it the index, and it gives me the coordinates. So for my 4x4 matrix,(this is still in hexadecimal)



      0 -> (0, 0)
      1 -> (1, 0)
      2 -> (0, 1)
      3 -> (2, 0)
      4 -> (1, 1)
      5 -> (0, 2)
      6 -> (3, 0)
      7 -> (2, 1)
      8 -> (1, 2)
      9 -> (0, 3)
      a -> (3, 1)
      b -> (2, 2)
      c -> (1, 3)
      d -> (3, 2)
      e -> (2, 3)
      f -> (3, 3)


      I have intentions to move on to variable sized square matrices so I cannot just hard code these values into a dict.



      I have been tinkering for hours trying to get this to work but I cannot for the life of me get it to work.



      This is not homework, just something I'm working on in my spare time, and it's slowly driving me up the wall.



      If anything is not clear please don't hesitate to ask.



      Thanks in advance.



      Edit:
      I presume someone will comment about this post Traverse Matrix in Diagonal strips which is similar but as with my first function this only iterates over the coordinates, and I cannot work out the coordinates from an index.







      python matrix






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 23 '18 at 3:35









      Gal Avineri

      16210




      16210










      asked Nov 22 '18 at 23:54









      dangee1705dangee1705

      2,0241722




      2,0241722
























          2 Answers
          2






          active

          oldest

          votes


















          4














          Here is a function that seems to do what you want. An explanation comes after the code.



          from math import sqrt

          def triangular(n):
          return n * (n + 1) // 2

          def coords_from_index(ndx, n=4):
          if ndx < triangular(n):
          basecol = (int(sqrt(8 * ndx + 1)) - 1) // 2
          row = ndx - triangular(basecol)
          col = basecol - row
          else:
          oldcol, oldrow = coords_from_index(n**2 - 1 - ndx, n)
          row = n - 1 - oldrow
          col = n - 1 - oldcol
          return col, row

          # Test code
          n = 4
          for ndx in range(n**2):
          print(hex(ndx)[2:], '->', coords_from_index(ndx, n))


          The printout from that test code is:



          0 -> (0, 0)
          1 -> (1, 0)
          2 -> (0, 1)
          3 -> (2, 0)
          4 -> (1, 1)
          5 -> (0, 2)
          6 -> (3, 0)
          7 -> (2, 1)
          8 -> (1, 2)
          9 -> (0, 3)
          a -> (3, 1)
          b -> (2, 2)
          c -> (1, 3)
          d -> (3, 2)
          e -> (2, 3)
          f -> (3, 3)




          Here is a brief explanation of my code.



          Like your code to generate the coordinates in order, I treat the upper-left triangle of the square differently from the lower-right triangle. Let's look first at the upper-left triangle, which for the square of size 4 includes the indices 0 through 9.



          If you look at the top number in each column, you see that those are the "triangular numbers", which are the sum of consecutive integers starting from 0. So the top row is 0, 0+1, 0+1+2, and 0+1+2+3. The well-known formula for those numbers is



          triangular(n) = n * (n + 1) // 2


          So I wrote a small routine for that. If you know the triangular number (call it ndx) and want to find n, you can use algebra to solve the quadratic equation and you get



          n = (sqrt(8 * ndx + 1) - 1) // 2


          If you replace the sqrt with int(sqrt( you get that same result for a triangular number, and you also get the "base" number for any ndx that falls between two triangular numbers. You can then use your index and the "base number" to find the corresponding column and row for the index.



          Now, if you look at the lower-right triangle, which includes the indices a through f, you see that there is symmetry with the upper-left triangle. I chose to use that symmetry to calculate the row and column for any of these indices. I could have calculated them more directly, but the approach I used works well.



          Note that if you use really large values of n and ndx that the int(sqrt( does not always give the correct answer, due to the vagaries of floating-point arithmetic. But ndx needs to be really large, on the order of 2**50, before that happens. Let me know if you need a more reliable routine to calculate the integer square root.






          share|improve this answer

































            3














            This is basically an algorithmic question :)



            I'd suggest the following algorithm:




            1. Find in what diagonal the requested index relies

            2. Find the position of the index on that diagonal

            3. Infer the coordinate


            The implementation i'd suggest is the following:



            As a initial step, prepare an array of the first linear index in each diagonal.

            for example in a 4x4 matrix the array would look like this: [0, 1, 3, 6, 10, 30, 15].
            Notice These are basically bins. This means that all the linear indices that maintain a[i] <= index < a[i+1] are found in the i'th diagonal.



            Than, when receiving an index:




            1. Find in which diagonal the requested index is found.

              You can do this by finding d which fulfills bin[d] <= index < bin[d]


            2. Find the position on that diagonal.

              This is distance between bin[d] and index. This means that if index - bin[d] = k, than the index is in the k'th position on that diagonal.



            3. Infer the coordinate.

              Up until now you've found that the index is in the k'th position on the d'th diagonal.



              Let us denote the size of the matrix is MxM.

              if x <= M-1 than we are on the diagonal (k, d - k)

              if x > M-1 than we are on the diagonal (d - (m-1) + k, (m-1) - k)

              When we will insert k that we've found earlier we will find the requested coordinate.




            Implementation



            def ind2cor(index):
            d = bisect_left(a, index)
            if index != a[d]:
            d -= 1

            k = index - a[d]

            if d <= m-1:
            return k, d - k
            else:
            return d - (m - 1) + k, (m - 1) - k


            Example:



            m = 4
            a = [0, 3, 6, 10, 13, 15]
            for i in range(16):
            print('{}: {}'.format(i, ind2cor(i)))


            Yields:



            0: (0, 0)
            1: (0, 1)
            2: (1, 0)
            3: (0, 2)
            4: (1, 1)
            5: (2, 0)
            6: (0, 3)
            7: (1, 2)
            8: (2, 1)
            9: (3, 0)
            10: (1, 3)
            11: (2, 2)
            12: (3, 1)
            13: (2, 3)
            14: (3, 2)
            15: (3, 3)


            I can also provide a method to generate the indices of the diagonals:



            def genereate_diagonal_indices(m):
            a = [0]
            for i in range(1, m):
            a.append(a[-1] + i)
            for i in range(m, 1, -1):
            a.append(a[-1] + i)
            return a


            So you could use a = genereate_diagonal_indices(m) in the code above instead.






            share|improve this answer


























            • Out of interest i compared the complexities of the algorithms Rory and I provided. It seems that in time complexity both Rory's algorithm and mine are O(log(m)), where m is the length of one axis of the matrix. In memory complexity Rory's algorithm is O(1) and mine is Theta(m).

              – Gal Avineri
              Nov 23 '18 at 10:30











            • I believe you have misunderstood my algorithm. There is one if statement and one resulting recursive call, but those happen at most once and do not increase the algorithmic complexity. The sqrt operator is done in O(1) in modern CPUs, I believe, though I could be wrong for some CPUs. As a result, my algorithm does straight calculations and thus is O(1) in both time and memory. Unless you mean that m is the number of bits of the length of one side of the square?

              – Rory Daulton
              Nov 23 '18 at 12:12













            • I might have misunderstood, i'd love to discuss it! I claimed your algorithm has a time complexity of O(log(m)) due to the calculation of the sqrt. I searched the internet for the complexity of calculation of sqrt and found this stackoverflow.com/questions/23103847/… which claims it is O(log(m)). However it might be wrong. Could you support the claim that sqrt time complexity is O(1)? :)

              – Gal Avineri
              Nov 23 '18 at 16:20











            • This point is debatable. I could claim that I noted that my code is meant for ndx < 2**50, so the limitation makes the code O(1). Instead, I'll give the timing results on my computer. Using %timeit on int(sqrt(n)) gives 295 ns for n=1, 299 ns for n=2, 313 ns for n=2**25-1, and 371 ns for n=2**50-1. This is worse than my claimed O(1) and better than your claimed O(log(n)). I'm not sure what that is--it looks a little better than O(log(log(n))).

              – Rory Daulton
              Nov 23 '18 at 16:41













            • If we assume ndx < c than i could also infer that m < c2 and that would make my algorithm O(1) as well. So for the sake of the argument should we continue without this assumption? Thank you for trying to collect timing results! The results are interesting, but i'm not sure we can reliably try to infer the complexity by them due to many other factors which my act. Therefore i'd like to find the theoretical compelxity. I've searched some more and found this cstheory.stackexchange.com/questions/9706/…

              – Gal Avineri
              Nov 23 '18 at 17:00













            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53439212%2findex-to-coordinates-in-diagonal-zigzag-traverse%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            4














            Here is a function that seems to do what you want. An explanation comes after the code.



            from math import sqrt

            def triangular(n):
            return n * (n + 1) // 2

            def coords_from_index(ndx, n=4):
            if ndx < triangular(n):
            basecol = (int(sqrt(8 * ndx + 1)) - 1) // 2
            row = ndx - triangular(basecol)
            col = basecol - row
            else:
            oldcol, oldrow = coords_from_index(n**2 - 1 - ndx, n)
            row = n - 1 - oldrow
            col = n - 1 - oldcol
            return col, row

            # Test code
            n = 4
            for ndx in range(n**2):
            print(hex(ndx)[2:], '->', coords_from_index(ndx, n))


            The printout from that test code is:



            0 -> (0, 0)
            1 -> (1, 0)
            2 -> (0, 1)
            3 -> (2, 0)
            4 -> (1, 1)
            5 -> (0, 2)
            6 -> (3, 0)
            7 -> (2, 1)
            8 -> (1, 2)
            9 -> (0, 3)
            a -> (3, 1)
            b -> (2, 2)
            c -> (1, 3)
            d -> (3, 2)
            e -> (2, 3)
            f -> (3, 3)




            Here is a brief explanation of my code.



            Like your code to generate the coordinates in order, I treat the upper-left triangle of the square differently from the lower-right triangle. Let's look first at the upper-left triangle, which for the square of size 4 includes the indices 0 through 9.



            If you look at the top number in each column, you see that those are the "triangular numbers", which are the sum of consecutive integers starting from 0. So the top row is 0, 0+1, 0+1+2, and 0+1+2+3. The well-known formula for those numbers is



            triangular(n) = n * (n + 1) // 2


            So I wrote a small routine for that. If you know the triangular number (call it ndx) and want to find n, you can use algebra to solve the quadratic equation and you get



            n = (sqrt(8 * ndx + 1) - 1) // 2


            If you replace the sqrt with int(sqrt( you get that same result for a triangular number, and you also get the "base" number for any ndx that falls between two triangular numbers. You can then use your index and the "base number" to find the corresponding column and row for the index.



            Now, if you look at the lower-right triangle, which includes the indices a through f, you see that there is symmetry with the upper-left triangle. I chose to use that symmetry to calculate the row and column for any of these indices. I could have calculated them more directly, but the approach I used works well.



            Note that if you use really large values of n and ndx that the int(sqrt( does not always give the correct answer, due to the vagaries of floating-point arithmetic. But ndx needs to be really large, on the order of 2**50, before that happens. Let me know if you need a more reliable routine to calculate the integer square root.






            share|improve this answer






























              4














              Here is a function that seems to do what you want. An explanation comes after the code.



              from math import sqrt

              def triangular(n):
              return n * (n + 1) // 2

              def coords_from_index(ndx, n=4):
              if ndx < triangular(n):
              basecol = (int(sqrt(8 * ndx + 1)) - 1) // 2
              row = ndx - triangular(basecol)
              col = basecol - row
              else:
              oldcol, oldrow = coords_from_index(n**2 - 1 - ndx, n)
              row = n - 1 - oldrow
              col = n - 1 - oldcol
              return col, row

              # Test code
              n = 4
              for ndx in range(n**2):
              print(hex(ndx)[2:], '->', coords_from_index(ndx, n))


              The printout from that test code is:



              0 -> (0, 0)
              1 -> (1, 0)
              2 -> (0, 1)
              3 -> (2, 0)
              4 -> (1, 1)
              5 -> (0, 2)
              6 -> (3, 0)
              7 -> (2, 1)
              8 -> (1, 2)
              9 -> (0, 3)
              a -> (3, 1)
              b -> (2, 2)
              c -> (1, 3)
              d -> (3, 2)
              e -> (2, 3)
              f -> (3, 3)




              Here is a brief explanation of my code.



              Like your code to generate the coordinates in order, I treat the upper-left triangle of the square differently from the lower-right triangle. Let's look first at the upper-left triangle, which for the square of size 4 includes the indices 0 through 9.



              If you look at the top number in each column, you see that those are the "triangular numbers", which are the sum of consecutive integers starting from 0. So the top row is 0, 0+1, 0+1+2, and 0+1+2+3. The well-known formula for those numbers is



              triangular(n) = n * (n + 1) // 2


              So I wrote a small routine for that. If you know the triangular number (call it ndx) and want to find n, you can use algebra to solve the quadratic equation and you get



              n = (sqrt(8 * ndx + 1) - 1) // 2


              If you replace the sqrt with int(sqrt( you get that same result for a triangular number, and you also get the "base" number for any ndx that falls between two triangular numbers. You can then use your index and the "base number" to find the corresponding column and row for the index.



              Now, if you look at the lower-right triangle, which includes the indices a through f, you see that there is symmetry with the upper-left triangle. I chose to use that symmetry to calculate the row and column for any of these indices. I could have calculated them more directly, but the approach I used works well.



              Note that if you use really large values of n and ndx that the int(sqrt( does not always give the correct answer, due to the vagaries of floating-point arithmetic. But ndx needs to be really large, on the order of 2**50, before that happens. Let me know if you need a more reliable routine to calculate the integer square root.






              share|improve this answer




























                4












                4








                4







                Here is a function that seems to do what you want. An explanation comes after the code.



                from math import sqrt

                def triangular(n):
                return n * (n + 1) // 2

                def coords_from_index(ndx, n=4):
                if ndx < triangular(n):
                basecol = (int(sqrt(8 * ndx + 1)) - 1) // 2
                row = ndx - triangular(basecol)
                col = basecol - row
                else:
                oldcol, oldrow = coords_from_index(n**2 - 1 - ndx, n)
                row = n - 1 - oldrow
                col = n - 1 - oldcol
                return col, row

                # Test code
                n = 4
                for ndx in range(n**2):
                print(hex(ndx)[2:], '->', coords_from_index(ndx, n))


                The printout from that test code is:



                0 -> (0, 0)
                1 -> (1, 0)
                2 -> (0, 1)
                3 -> (2, 0)
                4 -> (1, 1)
                5 -> (0, 2)
                6 -> (3, 0)
                7 -> (2, 1)
                8 -> (1, 2)
                9 -> (0, 3)
                a -> (3, 1)
                b -> (2, 2)
                c -> (1, 3)
                d -> (3, 2)
                e -> (2, 3)
                f -> (3, 3)




                Here is a brief explanation of my code.



                Like your code to generate the coordinates in order, I treat the upper-left triangle of the square differently from the lower-right triangle. Let's look first at the upper-left triangle, which for the square of size 4 includes the indices 0 through 9.



                If you look at the top number in each column, you see that those are the "triangular numbers", which are the sum of consecutive integers starting from 0. So the top row is 0, 0+1, 0+1+2, and 0+1+2+3. The well-known formula for those numbers is



                triangular(n) = n * (n + 1) // 2


                So I wrote a small routine for that. If you know the triangular number (call it ndx) and want to find n, you can use algebra to solve the quadratic equation and you get



                n = (sqrt(8 * ndx + 1) - 1) // 2


                If you replace the sqrt with int(sqrt( you get that same result for a triangular number, and you also get the "base" number for any ndx that falls between two triangular numbers. You can then use your index and the "base number" to find the corresponding column and row for the index.



                Now, if you look at the lower-right triangle, which includes the indices a through f, you see that there is symmetry with the upper-left triangle. I chose to use that symmetry to calculate the row and column for any of these indices. I could have calculated them more directly, but the approach I used works well.



                Note that if you use really large values of n and ndx that the int(sqrt( does not always give the correct answer, due to the vagaries of floating-point arithmetic. But ndx needs to be really large, on the order of 2**50, before that happens. Let me know if you need a more reliable routine to calculate the integer square root.






                share|improve this answer















                Here is a function that seems to do what you want. An explanation comes after the code.



                from math import sqrt

                def triangular(n):
                return n * (n + 1) // 2

                def coords_from_index(ndx, n=4):
                if ndx < triangular(n):
                basecol = (int(sqrt(8 * ndx + 1)) - 1) // 2
                row = ndx - triangular(basecol)
                col = basecol - row
                else:
                oldcol, oldrow = coords_from_index(n**2 - 1 - ndx, n)
                row = n - 1 - oldrow
                col = n - 1 - oldcol
                return col, row

                # Test code
                n = 4
                for ndx in range(n**2):
                print(hex(ndx)[2:], '->', coords_from_index(ndx, n))


                The printout from that test code is:



                0 -> (0, 0)
                1 -> (1, 0)
                2 -> (0, 1)
                3 -> (2, 0)
                4 -> (1, 1)
                5 -> (0, 2)
                6 -> (3, 0)
                7 -> (2, 1)
                8 -> (1, 2)
                9 -> (0, 3)
                a -> (3, 1)
                b -> (2, 2)
                c -> (1, 3)
                d -> (3, 2)
                e -> (2, 3)
                f -> (3, 3)




                Here is a brief explanation of my code.



                Like your code to generate the coordinates in order, I treat the upper-left triangle of the square differently from the lower-right triangle. Let's look first at the upper-left triangle, which for the square of size 4 includes the indices 0 through 9.



                If you look at the top number in each column, you see that those are the "triangular numbers", which are the sum of consecutive integers starting from 0. So the top row is 0, 0+1, 0+1+2, and 0+1+2+3. The well-known formula for those numbers is



                triangular(n) = n * (n + 1) // 2


                So I wrote a small routine for that. If you know the triangular number (call it ndx) and want to find n, you can use algebra to solve the quadratic equation and you get



                n = (sqrt(8 * ndx + 1) - 1) // 2


                If you replace the sqrt with int(sqrt( you get that same result for a triangular number, and you also get the "base" number for any ndx that falls between two triangular numbers. You can then use your index and the "base number" to find the corresponding column and row for the index.



                Now, if you look at the lower-right triangle, which includes the indices a through f, you see that there is symmetry with the upper-left triangle. I chose to use that symmetry to calculate the row and column for any of these indices. I could have calculated them more directly, but the approach I used works well.



                Note that if you use really large values of n and ndx that the int(sqrt( does not always give the correct answer, due to the vagaries of floating-point arithmetic. But ndx needs to be really large, on the order of 2**50, before that happens. Let me know if you need a more reliable routine to calculate the integer square root.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 23 '18 at 0:56

























                answered Nov 23 '18 at 0:26









                Rory DaultonRory Daulton

                13.2k41930




                13.2k41930

























                    3














                    This is basically an algorithmic question :)



                    I'd suggest the following algorithm:




                    1. Find in what diagonal the requested index relies

                    2. Find the position of the index on that diagonal

                    3. Infer the coordinate


                    The implementation i'd suggest is the following:



                    As a initial step, prepare an array of the first linear index in each diagonal.

                    for example in a 4x4 matrix the array would look like this: [0, 1, 3, 6, 10, 30, 15].
                    Notice These are basically bins. This means that all the linear indices that maintain a[i] <= index < a[i+1] are found in the i'th diagonal.



                    Than, when receiving an index:




                    1. Find in which diagonal the requested index is found.

                      You can do this by finding d which fulfills bin[d] <= index < bin[d]


                    2. Find the position on that diagonal.

                      This is distance between bin[d] and index. This means that if index - bin[d] = k, than the index is in the k'th position on that diagonal.



                    3. Infer the coordinate.

                      Up until now you've found that the index is in the k'th position on the d'th diagonal.



                      Let us denote the size of the matrix is MxM.

                      if x <= M-1 than we are on the diagonal (k, d - k)

                      if x > M-1 than we are on the diagonal (d - (m-1) + k, (m-1) - k)

                      When we will insert k that we've found earlier we will find the requested coordinate.




                    Implementation



                    def ind2cor(index):
                    d = bisect_left(a, index)
                    if index != a[d]:
                    d -= 1

                    k = index - a[d]

                    if d <= m-1:
                    return k, d - k
                    else:
                    return d - (m - 1) + k, (m - 1) - k


                    Example:



                    m = 4
                    a = [0, 3, 6, 10, 13, 15]
                    for i in range(16):
                    print('{}: {}'.format(i, ind2cor(i)))


                    Yields:



                    0: (0, 0)
                    1: (0, 1)
                    2: (1, 0)
                    3: (0, 2)
                    4: (1, 1)
                    5: (2, 0)
                    6: (0, 3)
                    7: (1, 2)
                    8: (2, 1)
                    9: (3, 0)
                    10: (1, 3)
                    11: (2, 2)
                    12: (3, 1)
                    13: (2, 3)
                    14: (3, 2)
                    15: (3, 3)


                    I can also provide a method to generate the indices of the diagonals:



                    def genereate_diagonal_indices(m):
                    a = [0]
                    for i in range(1, m):
                    a.append(a[-1] + i)
                    for i in range(m, 1, -1):
                    a.append(a[-1] + i)
                    return a


                    So you could use a = genereate_diagonal_indices(m) in the code above instead.






                    share|improve this answer


























                    • Out of interest i compared the complexities of the algorithms Rory and I provided. It seems that in time complexity both Rory's algorithm and mine are O(log(m)), where m is the length of one axis of the matrix. In memory complexity Rory's algorithm is O(1) and mine is Theta(m).

                      – Gal Avineri
                      Nov 23 '18 at 10:30











                    • I believe you have misunderstood my algorithm. There is one if statement and one resulting recursive call, but those happen at most once and do not increase the algorithmic complexity. The sqrt operator is done in O(1) in modern CPUs, I believe, though I could be wrong for some CPUs. As a result, my algorithm does straight calculations and thus is O(1) in both time and memory. Unless you mean that m is the number of bits of the length of one side of the square?

                      – Rory Daulton
                      Nov 23 '18 at 12:12













                    • I might have misunderstood, i'd love to discuss it! I claimed your algorithm has a time complexity of O(log(m)) due to the calculation of the sqrt. I searched the internet for the complexity of calculation of sqrt and found this stackoverflow.com/questions/23103847/… which claims it is O(log(m)). However it might be wrong. Could you support the claim that sqrt time complexity is O(1)? :)

                      – Gal Avineri
                      Nov 23 '18 at 16:20











                    • This point is debatable. I could claim that I noted that my code is meant for ndx < 2**50, so the limitation makes the code O(1). Instead, I'll give the timing results on my computer. Using %timeit on int(sqrt(n)) gives 295 ns for n=1, 299 ns for n=2, 313 ns for n=2**25-1, and 371 ns for n=2**50-1. This is worse than my claimed O(1) and better than your claimed O(log(n)). I'm not sure what that is--it looks a little better than O(log(log(n))).

                      – Rory Daulton
                      Nov 23 '18 at 16:41













                    • If we assume ndx < c than i could also infer that m < c2 and that would make my algorithm O(1) as well. So for the sake of the argument should we continue without this assumption? Thank you for trying to collect timing results! The results are interesting, but i'm not sure we can reliably try to infer the complexity by them due to many other factors which my act. Therefore i'd like to find the theoretical compelxity. I've searched some more and found this cstheory.stackexchange.com/questions/9706/…

                      – Gal Avineri
                      Nov 23 '18 at 17:00


















                    3














                    This is basically an algorithmic question :)



                    I'd suggest the following algorithm:




                    1. Find in what diagonal the requested index relies

                    2. Find the position of the index on that diagonal

                    3. Infer the coordinate


                    The implementation i'd suggest is the following:



                    As a initial step, prepare an array of the first linear index in each diagonal.

                    for example in a 4x4 matrix the array would look like this: [0, 1, 3, 6, 10, 30, 15].
                    Notice These are basically bins. This means that all the linear indices that maintain a[i] <= index < a[i+1] are found in the i'th diagonal.



                    Than, when receiving an index:




                    1. Find in which diagonal the requested index is found.

                      You can do this by finding d which fulfills bin[d] <= index < bin[d]


                    2. Find the position on that diagonal.

                      This is distance between bin[d] and index. This means that if index - bin[d] = k, than the index is in the k'th position on that diagonal.



                    3. Infer the coordinate.

                      Up until now you've found that the index is in the k'th position on the d'th diagonal.



                      Let us denote the size of the matrix is MxM.

                      if x <= M-1 than we are on the diagonal (k, d - k)

                      if x > M-1 than we are on the diagonal (d - (m-1) + k, (m-1) - k)

                      When we will insert k that we've found earlier we will find the requested coordinate.




                    Implementation



                    def ind2cor(index):
                    d = bisect_left(a, index)
                    if index != a[d]:
                    d -= 1

                    k = index - a[d]

                    if d <= m-1:
                    return k, d - k
                    else:
                    return d - (m - 1) + k, (m - 1) - k


                    Example:



                    m = 4
                    a = [0, 3, 6, 10, 13, 15]
                    for i in range(16):
                    print('{}: {}'.format(i, ind2cor(i)))


                    Yields:



                    0: (0, 0)
                    1: (0, 1)
                    2: (1, 0)
                    3: (0, 2)
                    4: (1, 1)
                    5: (2, 0)
                    6: (0, 3)
                    7: (1, 2)
                    8: (2, 1)
                    9: (3, 0)
                    10: (1, 3)
                    11: (2, 2)
                    12: (3, 1)
                    13: (2, 3)
                    14: (3, 2)
                    15: (3, 3)


                    I can also provide a method to generate the indices of the diagonals:



                    def genereate_diagonal_indices(m):
                    a = [0]
                    for i in range(1, m):
                    a.append(a[-1] + i)
                    for i in range(m, 1, -1):
                    a.append(a[-1] + i)
                    return a


                    So you could use a = genereate_diagonal_indices(m) in the code above instead.






                    share|improve this answer


























                    • Out of interest i compared the complexities of the algorithms Rory and I provided. It seems that in time complexity both Rory's algorithm and mine are O(log(m)), where m is the length of one axis of the matrix. In memory complexity Rory's algorithm is O(1) and mine is Theta(m).

                      – Gal Avineri
                      Nov 23 '18 at 10:30











                    • I believe you have misunderstood my algorithm. There is one if statement and one resulting recursive call, but those happen at most once and do not increase the algorithmic complexity. The sqrt operator is done in O(1) in modern CPUs, I believe, though I could be wrong for some CPUs. As a result, my algorithm does straight calculations and thus is O(1) in both time and memory. Unless you mean that m is the number of bits of the length of one side of the square?

                      – Rory Daulton
                      Nov 23 '18 at 12:12













                    • I might have misunderstood, i'd love to discuss it! I claimed your algorithm has a time complexity of O(log(m)) due to the calculation of the sqrt. I searched the internet for the complexity of calculation of sqrt and found this stackoverflow.com/questions/23103847/… which claims it is O(log(m)). However it might be wrong. Could you support the claim that sqrt time complexity is O(1)? :)

                      – Gal Avineri
                      Nov 23 '18 at 16:20











                    • This point is debatable. I could claim that I noted that my code is meant for ndx < 2**50, so the limitation makes the code O(1). Instead, I'll give the timing results on my computer. Using %timeit on int(sqrt(n)) gives 295 ns for n=1, 299 ns for n=2, 313 ns for n=2**25-1, and 371 ns for n=2**50-1. This is worse than my claimed O(1) and better than your claimed O(log(n)). I'm not sure what that is--it looks a little better than O(log(log(n))).

                      – Rory Daulton
                      Nov 23 '18 at 16:41













                    • If we assume ndx < c than i could also infer that m < c2 and that would make my algorithm O(1) as well. So for the sake of the argument should we continue without this assumption? Thank you for trying to collect timing results! The results are interesting, but i'm not sure we can reliably try to infer the complexity by them due to many other factors which my act. Therefore i'd like to find the theoretical compelxity. I've searched some more and found this cstheory.stackexchange.com/questions/9706/…

                      – Gal Avineri
                      Nov 23 '18 at 17:00
















                    3












                    3








                    3







                    This is basically an algorithmic question :)



                    I'd suggest the following algorithm:




                    1. Find in what diagonal the requested index relies

                    2. Find the position of the index on that diagonal

                    3. Infer the coordinate


                    The implementation i'd suggest is the following:



                    As a initial step, prepare an array of the first linear index in each diagonal.

                    for example in a 4x4 matrix the array would look like this: [0, 1, 3, 6, 10, 30, 15].
                    Notice These are basically bins. This means that all the linear indices that maintain a[i] <= index < a[i+1] are found in the i'th diagonal.



                    Than, when receiving an index:




                    1. Find in which diagonal the requested index is found.

                      You can do this by finding d which fulfills bin[d] <= index < bin[d]


                    2. Find the position on that diagonal.

                      This is distance between bin[d] and index. This means that if index - bin[d] = k, than the index is in the k'th position on that diagonal.



                    3. Infer the coordinate.

                      Up until now you've found that the index is in the k'th position on the d'th diagonal.



                      Let us denote the size of the matrix is MxM.

                      if x <= M-1 than we are on the diagonal (k, d - k)

                      if x > M-1 than we are on the diagonal (d - (m-1) + k, (m-1) - k)

                      When we will insert k that we've found earlier we will find the requested coordinate.




                    Implementation



                    def ind2cor(index):
                    d = bisect_left(a, index)
                    if index != a[d]:
                    d -= 1

                    k = index - a[d]

                    if d <= m-1:
                    return k, d - k
                    else:
                    return d - (m - 1) + k, (m - 1) - k


                    Example:



                    m = 4
                    a = [0, 3, 6, 10, 13, 15]
                    for i in range(16):
                    print('{}: {}'.format(i, ind2cor(i)))


                    Yields:



                    0: (0, 0)
                    1: (0, 1)
                    2: (1, 0)
                    3: (0, 2)
                    4: (1, 1)
                    5: (2, 0)
                    6: (0, 3)
                    7: (1, 2)
                    8: (2, 1)
                    9: (3, 0)
                    10: (1, 3)
                    11: (2, 2)
                    12: (3, 1)
                    13: (2, 3)
                    14: (3, 2)
                    15: (3, 3)


                    I can also provide a method to generate the indices of the diagonals:



                    def genereate_diagonal_indices(m):
                    a = [0]
                    for i in range(1, m):
                    a.append(a[-1] + i)
                    for i in range(m, 1, -1):
                    a.append(a[-1] + i)
                    return a


                    So you could use a = genereate_diagonal_indices(m) in the code above instead.






                    share|improve this answer















                    This is basically an algorithmic question :)



                    I'd suggest the following algorithm:




                    1. Find in what diagonal the requested index relies

                    2. Find the position of the index on that diagonal

                    3. Infer the coordinate


                    The implementation i'd suggest is the following:



                    As a initial step, prepare an array of the first linear index in each diagonal.

                    for example in a 4x4 matrix the array would look like this: [0, 1, 3, 6, 10, 30, 15].
                    Notice These are basically bins. This means that all the linear indices that maintain a[i] <= index < a[i+1] are found in the i'th diagonal.



                    Than, when receiving an index:




                    1. Find in which diagonal the requested index is found.

                      You can do this by finding d which fulfills bin[d] <= index < bin[d]


                    2. Find the position on that diagonal.

                      This is distance between bin[d] and index. This means that if index - bin[d] = k, than the index is in the k'th position on that diagonal.



                    3. Infer the coordinate.

                      Up until now you've found that the index is in the k'th position on the d'th diagonal.



                      Let us denote the size of the matrix is MxM.

                      if x <= M-1 than we are on the diagonal (k, d - k)

                      if x > M-1 than we are on the diagonal (d - (m-1) + k, (m-1) - k)

                      When we will insert k that we've found earlier we will find the requested coordinate.




                    Implementation



                    def ind2cor(index):
                    d = bisect_left(a, index)
                    if index != a[d]:
                    d -= 1

                    k = index - a[d]

                    if d <= m-1:
                    return k, d - k
                    else:
                    return d - (m - 1) + k, (m - 1) - k


                    Example:



                    m = 4
                    a = [0, 3, 6, 10, 13, 15]
                    for i in range(16):
                    print('{}: {}'.format(i, ind2cor(i)))


                    Yields:



                    0: (0, 0)
                    1: (0, 1)
                    2: (1, 0)
                    3: (0, 2)
                    4: (1, 1)
                    5: (2, 0)
                    6: (0, 3)
                    7: (1, 2)
                    8: (2, 1)
                    9: (3, 0)
                    10: (1, 3)
                    11: (2, 2)
                    12: (3, 1)
                    13: (2, 3)
                    14: (3, 2)
                    15: (3, 3)


                    I can also provide a method to generate the indices of the diagonals:



                    def genereate_diagonal_indices(m):
                    a = [0]
                    for i in range(1, m):
                    a.append(a[-1] + i)
                    for i in range(m, 1, -1):
                    a.append(a[-1] + i)
                    return a


                    So you could use a = genereate_diagonal_indices(m) in the code above instead.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 23 '18 at 16:53

























                    answered Nov 23 '18 at 1:07









                    Gal AvineriGal Avineri

                    16210




                    16210













                    • Out of interest i compared the complexities of the algorithms Rory and I provided. It seems that in time complexity both Rory's algorithm and mine are O(log(m)), where m is the length of one axis of the matrix. In memory complexity Rory's algorithm is O(1) and mine is Theta(m).

                      – Gal Avineri
                      Nov 23 '18 at 10:30











                    • I believe you have misunderstood my algorithm. There is one if statement and one resulting recursive call, but those happen at most once and do not increase the algorithmic complexity. The sqrt operator is done in O(1) in modern CPUs, I believe, though I could be wrong for some CPUs. As a result, my algorithm does straight calculations and thus is O(1) in both time and memory. Unless you mean that m is the number of bits of the length of one side of the square?

                      – Rory Daulton
                      Nov 23 '18 at 12:12













                    • I might have misunderstood, i'd love to discuss it! I claimed your algorithm has a time complexity of O(log(m)) due to the calculation of the sqrt. I searched the internet for the complexity of calculation of sqrt and found this stackoverflow.com/questions/23103847/… which claims it is O(log(m)). However it might be wrong. Could you support the claim that sqrt time complexity is O(1)? :)

                      – Gal Avineri
                      Nov 23 '18 at 16:20











                    • This point is debatable. I could claim that I noted that my code is meant for ndx < 2**50, so the limitation makes the code O(1). Instead, I'll give the timing results on my computer. Using %timeit on int(sqrt(n)) gives 295 ns for n=1, 299 ns for n=2, 313 ns for n=2**25-1, and 371 ns for n=2**50-1. This is worse than my claimed O(1) and better than your claimed O(log(n)). I'm not sure what that is--it looks a little better than O(log(log(n))).

                      – Rory Daulton
                      Nov 23 '18 at 16:41













                    • If we assume ndx < c than i could also infer that m < c2 and that would make my algorithm O(1) as well. So for the sake of the argument should we continue without this assumption? Thank you for trying to collect timing results! The results are interesting, but i'm not sure we can reliably try to infer the complexity by them due to many other factors which my act. Therefore i'd like to find the theoretical compelxity. I've searched some more and found this cstheory.stackexchange.com/questions/9706/…

                      – Gal Avineri
                      Nov 23 '18 at 17:00





















                    • Out of interest i compared the complexities of the algorithms Rory and I provided. It seems that in time complexity both Rory's algorithm and mine are O(log(m)), where m is the length of one axis of the matrix. In memory complexity Rory's algorithm is O(1) and mine is Theta(m).

                      – Gal Avineri
                      Nov 23 '18 at 10:30











                    • I believe you have misunderstood my algorithm. There is one if statement and one resulting recursive call, but those happen at most once and do not increase the algorithmic complexity. The sqrt operator is done in O(1) in modern CPUs, I believe, though I could be wrong for some CPUs. As a result, my algorithm does straight calculations and thus is O(1) in both time and memory. Unless you mean that m is the number of bits of the length of one side of the square?

                      – Rory Daulton
                      Nov 23 '18 at 12:12













                    • I might have misunderstood, i'd love to discuss it! I claimed your algorithm has a time complexity of O(log(m)) due to the calculation of the sqrt. I searched the internet for the complexity of calculation of sqrt and found this stackoverflow.com/questions/23103847/… which claims it is O(log(m)). However it might be wrong. Could you support the claim that sqrt time complexity is O(1)? :)

                      – Gal Avineri
                      Nov 23 '18 at 16:20











                    • This point is debatable. I could claim that I noted that my code is meant for ndx < 2**50, so the limitation makes the code O(1). Instead, I'll give the timing results on my computer. Using %timeit on int(sqrt(n)) gives 295 ns for n=1, 299 ns for n=2, 313 ns for n=2**25-1, and 371 ns for n=2**50-1. This is worse than my claimed O(1) and better than your claimed O(log(n)). I'm not sure what that is--it looks a little better than O(log(log(n))).

                      – Rory Daulton
                      Nov 23 '18 at 16:41













                    • If we assume ndx < c than i could also infer that m < c2 and that would make my algorithm O(1) as well. So for the sake of the argument should we continue without this assumption? Thank you for trying to collect timing results! The results are interesting, but i'm not sure we can reliably try to infer the complexity by them due to many other factors which my act. Therefore i'd like to find the theoretical compelxity. I've searched some more and found this cstheory.stackexchange.com/questions/9706/…

                      – Gal Avineri
                      Nov 23 '18 at 17:00



















                    Out of interest i compared the complexities of the algorithms Rory and I provided. It seems that in time complexity both Rory's algorithm and mine are O(log(m)), where m is the length of one axis of the matrix. In memory complexity Rory's algorithm is O(1) and mine is Theta(m).

                    – Gal Avineri
                    Nov 23 '18 at 10:30





                    Out of interest i compared the complexities of the algorithms Rory and I provided. It seems that in time complexity both Rory's algorithm and mine are O(log(m)), where m is the length of one axis of the matrix. In memory complexity Rory's algorithm is O(1) and mine is Theta(m).

                    – Gal Avineri
                    Nov 23 '18 at 10:30













                    I believe you have misunderstood my algorithm. There is one if statement and one resulting recursive call, but those happen at most once and do not increase the algorithmic complexity. The sqrt operator is done in O(1) in modern CPUs, I believe, though I could be wrong for some CPUs. As a result, my algorithm does straight calculations and thus is O(1) in both time and memory. Unless you mean that m is the number of bits of the length of one side of the square?

                    – Rory Daulton
                    Nov 23 '18 at 12:12







                    I believe you have misunderstood my algorithm. There is one if statement and one resulting recursive call, but those happen at most once and do not increase the algorithmic complexity. The sqrt operator is done in O(1) in modern CPUs, I believe, though I could be wrong for some CPUs. As a result, my algorithm does straight calculations and thus is O(1) in both time and memory. Unless you mean that m is the number of bits of the length of one side of the square?

                    – Rory Daulton
                    Nov 23 '18 at 12:12















                    I might have misunderstood, i'd love to discuss it! I claimed your algorithm has a time complexity of O(log(m)) due to the calculation of the sqrt. I searched the internet for the complexity of calculation of sqrt and found this stackoverflow.com/questions/23103847/… which claims it is O(log(m)). However it might be wrong. Could you support the claim that sqrt time complexity is O(1)? :)

                    – Gal Avineri
                    Nov 23 '18 at 16:20





                    I might have misunderstood, i'd love to discuss it! I claimed your algorithm has a time complexity of O(log(m)) due to the calculation of the sqrt. I searched the internet for the complexity of calculation of sqrt and found this stackoverflow.com/questions/23103847/… which claims it is O(log(m)). However it might be wrong. Could you support the claim that sqrt time complexity is O(1)? :)

                    – Gal Avineri
                    Nov 23 '18 at 16:20













                    This point is debatable. I could claim that I noted that my code is meant for ndx < 2**50, so the limitation makes the code O(1). Instead, I'll give the timing results on my computer. Using %timeit on int(sqrt(n)) gives 295 ns for n=1, 299 ns for n=2, 313 ns for n=2**25-1, and 371 ns for n=2**50-1. This is worse than my claimed O(1) and better than your claimed O(log(n)). I'm not sure what that is--it looks a little better than O(log(log(n))).

                    – Rory Daulton
                    Nov 23 '18 at 16:41







                    This point is debatable. I could claim that I noted that my code is meant for ndx < 2**50, so the limitation makes the code O(1). Instead, I'll give the timing results on my computer. Using %timeit on int(sqrt(n)) gives 295 ns for n=1, 299 ns for n=2, 313 ns for n=2**25-1, and 371 ns for n=2**50-1. This is worse than my claimed O(1) and better than your claimed O(log(n)). I'm not sure what that is--it looks a little better than O(log(log(n))).

                    – Rory Daulton
                    Nov 23 '18 at 16:41















                    If we assume ndx < c than i could also infer that m < c2 and that would make my algorithm O(1) as well. So for the sake of the argument should we continue without this assumption? Thank you for trying to collect timing results! The results are interesting, but i'm not sure we can reliably try to infer the complexity by them due to many other factors which my act. Therefore i'd like to find the theoretical compelxity. I've searched some more and found this cstheory.stackexchange.com/questions/9706/…

                    – Gal Avineri
                    Nov 23 '18 at 17:00







                    If we assume ndx < c than i could also infer that m < c2 and that would make my algorithm O(1) as well. So for the sake of the argument should we continue without this assumption? Thank you for trying to collect timing results! The results are interesting, but i'm not sure we can reliably try to infer the complexity by them due to many other factors which my act. Therefore i'd like to find the theoretical compelxity. I've searched some more and found this cstheory.stackexchange.com/questions/9706/…

                    – Gal Avineri
                    Nov 23 '18 at 17:00




















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53439212%2findex-to-coordinates-in-diagonal-zigzag-traverse%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Futebolista

                    Feedback on college project

                    Albești (Vaslui)