11
\$\begingroup\$

Is there a way in Golfscript to bring all of the diagonals of an array into a single array?

For example, for the array

[[1 2 3][4 5 6][7 8 9]]

return

[[7][4 8][1 5 9][2 6][3]]

(not necessarily in that order) and for

["ABCD""EFGH""IJKL"]

return

["I""EJ""AFK""BGL""CH""D"]

(not necessarily in that order). Assume the lengths of the arrays are the same.

I am struggling with figuring it out. I tried doing something with = and iterating through the (length+1)th character of the strings, but that didn't work. Can someone help me?

I'd like the shortest way to do this, if possible.

\$\endgroup\$
  • \$\begingroup\$ This isn't your regular Q&A site; you need to have a winning criterion. I suggest a popularity content for starters. \$\endgroup\$ – Timtech Sep 18 '14 at 23:40
  • \$\begingroup\$ @Timtech I understand. I'll try regular stackexchange. \$\endgroup\$ – Josiah Winslow Sep 18 '14 at 23:50
  • 7
    \$\begingroup\$ Language-specific golf advice questions are officially on-topic: meta.codegolf.stackexchange.com/a/1725/20260 \$\endgroup\$ – xnor Sep 19 '14 at 0:02
  • 5
    \$\begingroup\$ @xnor You linked to wrong answer there. That one is about those tips lists we have. But asking for specific advice is also on topic so it would be nice if people could stop downvoting and close voting this. \$\endgroup\$ – Martin Ender Sep 19 '14 at 7:22
  • 7
    \$\begingroup\$ @steveverrill I don't agree that these should be made CW. That only applies to the list questions (in fact, I don't even agree that those should be CW), but there's really no reason for specific advice question to be CW - they are basically micro-optimisation golfing contests, and the people answering them do deserve the rep for it (as does the asker, if the question is interesting). \$\endgroup\$ – Martin Ender Sep 19 '14 at 16:21
8
\$\begingroup\$

Consider

[
    "ABCD"
    "EFGH"
    "IJKL"
]

To obtain the main diagonal and the diagonals above it, we can shift out the first char of the second row and the first two of the third:

[
    "ABCD"
    "FGH"
    "KL"
]

Note that all columns correspond to a diagonal, so "zipping" the array (i.e., transposing rows and columns) will yield an array containing the aforementioned four diagonals:

[
    "AFK"
    "BGL"
    "CH"
    "D"
]

We're still missing the diagonals below the main diagonal.

If we zip A itself and repeat the above process, we'll obtain an array containing the main diagonal and all diagonals below it. All that's left it to compute the set union of both arrays.

Putting it all together:

[.zip]{:A,,{.A=>}%zip}/|


[.zip]{              }/  # For the original array and it's transpose, do the following:
       :A                # Store the array in A.
         ,,{    }%       # For each I in [ 0 1 ... len(A) ], do the following:
            .A=>         # Push A[I] and shift out its first I characters.
                  zip    # Transpose the resulting array.
                       | # Perform set union.

Try it online.

Finally, if we only need the diagonals because we're searching for a string inside them (like in the Word Search Puzzle, which I assume inspired this question), a "less clean" approach might also be suitable.

You can use

..,n**\.0=,\,+)/zip

to obtain all diagonals, plus some unnecessary linefeed characters.

I've explained the process in detail in this answer.

Try it online.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.