18
\$\begingroup\$

Given a number n, Output an ordered list of 1-based indices falling on either of the diagonals of an n*n square matrix.

Example:

For an input of 3:

The square shall be:

1 2 3
4 5 6
7 8 9

Now we select all the indices represented by \, / or X (# or non-diagonal positions are rejected)

\ # /
# X #
/ # \

The output shall be:

[1,3,5,7,9]

Test cases:

1=>[1]
2=>[1,2,3,4]
3=>[1,3,5,7,9]
4=>[1,4,6,7,10,11,13,16]
5=>[1,5,7,9,13,17,19,21,25]

There will be no accepted answer. I want to know the shortest code for each language.

\$\endgroup\$
  • 1
    \$\begingroup\$ The question is asking for the (1-indexed) indices of the \, / and X characters in the images. Not a bad question per se, but lacks explanation. \$\endgroup\$ – Arfie Aug 24 '17 at 9:24
  • \$\begingroup\$ If you are willing to provide a brief and clear explanation of what you want, We will probably reopen this, as it is not a bad challenge. As of now, it is just very unclear \$\endgroup\$ – Mr. Xcoder Aug 24 '17 at 9:36
  • \$\begingroup\$ I've voted to reopen, though you might also want to move the ascii images out of the examples area to avoid confusion. At first I wasn't sure if I had to produce those as well (but I understand the wanted output is only the list of indices) \$\endgroup\$ – Arfie Aug 24 '17 at 10:01
  • 7
    \$\begingroup\$ Does the order matter? \$\endgroup\$ – Mr. Xcoder Aug 24 '17 at 10:19
  • 9
    \$\begingroup\$ FWIW I think having the order be irrelevant might make for more interesting golfs... \$\endgroup\$ – Jonathan Allan Aug 24 '17 at 11:17

21 Answers 21

10
\$\begingroup\$

Octave, 28 bytes

@(n)find((I=eye(n))+flip(I))

Anonymous function that inputs a number and outputs a column vector of numbers.

Try it online!

\$\endgroup\$
  • 2
    \$\begingroup\$ So simple... :) \$\endgroup\$ – Stewie Griffin Aug 24 '17 at 16:24
7
\$\begingroup\$

JavaScript (ES6), 48 bytes

Outputs a dash-separated list of integers as a string.

f=(n,k=n*n)=>--k?f(n,k)+(k%~-n&&k%-~n?'':~k):'1'

Formatted and commented

f = (n, k = n * n) => // given n and starting with k = n²
  --k ?               // decrement k; if it does not equal zero:
    f(n, k) + (       //   return the result of a recursive call followed by:
      k % ~-n &&      //     if both k % (n - 1) and
      k % -~n ?       //             k % (n + 1) are non-zero:
        ''            //       an empty string
      :               //     else:
        ~k            //       -(k + 1) (instantly coerced to a string)
    )                 //   end of iteration
  :                   // else:
    '1'               //   return '1' and stop recursion

Test cases

f=(n,k=n*n)=>--k?f(n,k)+(k%~-n&&k%-~n?'':~k):'1'

;[1,2,3,4,5].forEach(n => console.log(n, '->', f(n)))

\$\endgroup\$
  • \$\begingroup\$ Nice workaround, using the signs as separators. Could you use bitwsie & to save a byte? \$\endgroup\$ – Shaggy Aug 24 '17 at 13:47
  • \$\begingroup\$ @Shaggy No, that wouldn't work. For instance: 4%3 and 4%5 have no 1-bit in common, but both are non-zero. \$\endgroup\$ – Arnauld Aug 24 '17 at 13:58
  • \$\begingroup\$ Yup, just tested it with n=5 and spotted that it wouldn't work. \$\endgroup\$ – Shaggy Aug 24 '17 at 14:08
  • \$\begingroup\$ k%~-n&&k%-~n should work. nice trick with the separator! \$\endgroup\$ – Titus Aug 24 '17 at 17:12
  • \$\begingroup\$ @Titus Not that it really matters when it comes to golfing but ... yeah, that might be slightly more readable. :-) (updated) \$\endgroup\$ – Arnauld Aug 24 '17 at 20:00
7
\$\begingroup\$

R, 38 35 34 38 bytes

3 bytes saved when I remembered about the existence of the which function... , 1 byte saved thanks to @Rift

d=diag(n<-scan());which(d|d[n:1,])

+4 bytes for the argument ec=T when called as a full program by source()

Try it online!

Explanation:

n<-scan()            # take input
d=diag(n);           # create an identity matrix (ones on diagonal, zeros elsewhere)
d|d[n:1,]            # coerce d to logical and combine (OR) with a flipped version
which([d|d[n:1,]])   # Find indices for T values in the logical expression above
\$\endgroup\$
  • 1
    \$\begingroup\$ -1 byte d=diag(n<-scan());which(d|d[n:1,]) \$\endgroup\$ – Rift Aug 24 '17 at 15:50
  • \$\begingroup\$ When running this as a full program (source) this doesn't print anything. You have to call cat. See this post on meta. \$\endgroup\$ – JAD Aug 25 '17 at 12:06
  • \$\begingroup\$ @JarkoDubbeldam Fair enough! I had always worked on the basis that it gives valid output on TIO, never really considered the requirements of being a "full program". \$\endgroup\$ – user2390246 Aug 25 '17 at 12:30
  • \$\begingroup\$ Though I'm not planning on going back and editing all my old answers to fix this! \$\endgroup\$ – user2390246 Aug 25 '17 at 12:32
  • \$\begingroup\$ It is a bit vague, because of the console environment of R and code snippets being the main way of using it. Feel free to share insights on that meta thread I linked. It hasn't received all that much input. \$\endgroup\$ – JAD Aug 25 '17 at 12:41
6
\$\begingroup\$

Jelly, 8 bytes

⁼þ`+Ṛ$ẎT

Try it online!

Uses Luis Mendo's algorithm on his MATL answer.

\$\endgroup\$
  • \$\begingroup\$ Mhm, I am quite surprised you didn't use ŒD. \$\endgroup\$ – Mr. Xcoder Aug 24 '17 at 11:06
  • \$\begingroup\$ @Mr.Xcoder ŒD does something completely different from X of a specific size. \$\endgroup\$ – Erik the Outgolfer Aug 24 '17 at 11:14
5
\$\begingroup\$

Octave, 41 37 bytes

This works in MATLAB too by the way. No sneaky Octave specific functionality :)

@(x)unique([x:x-1:x^2-1;1:x+1:x*x+1])

Try it online!

Explanation:

Instead of creating a square matrix, and find the two diagonals, I figured I rather calculate the diagonals directly instead. This was 17 bytes shorter! =)

@(x)                                   % Anonymous function that takes 'x' as input
    unique(...                   ...)  % unique gives the unique elements, sorted
           [x:x-1:x^2-1                % The anti-diagonal (is that the correct word?)
                       ;               % New row
                        1:x+1:x*x+1])  % The regular diagonal

This is what it looks like, without unique:

ans =    
    6   11   16   21   26   31
    1    8   15   22   29   36

Yes, I should probably have flipped the order of the diagonals to make it more human-friendly.

\$\endgroup\$
5
\$\begingroup\$

MATL, 6 bytes

XytP+f

Try it online!

Explanation

Same approach as my Octave answer.

Consider input 3 as an example.

Xy   % Implicit input. Identity matrix of that size
     % STACK: [1 0 0;
               0 1 0;
               0 0 1]
t    % Duplicate
     % STACK: [1 0 0
               0 1 0
               0 0 1],
              [1 0 0
               0 1 0
               0 0 1]
P    % Flip vertically
     % STACK: [1 0 0
               0 1 0
               0 0 1],
              [0 0 1
               0 1 0
               1 0 0]
+    % Add
     % STACK: [1 0 1
               0 2 0
               1 0 1]
f    % Linear indices of nonzero entries. Implicit display  
     % STACK:[1; 3; 5; 7; 9]

Linear indexing is column-major, 1-based. For more information see length-12 snippet here.

\$\endgroup\$
  • \$\begingroup\$ What is "transpose" supposed to mean? \$\endgroup\$ – Erik the Outgolfer Aug 24 '17 at 18:27
  • \$\begingroup\$ @EriktheOutgolfer Sorry, my bad. t is duplicate, not transpose. Also, I've added a worked out example \$\endgroup\$ – Luis Mendo Aug 24 '17 at 19:37
  • \$\begingroup\$ Amazing! It would take me two loops if I want to accomplish this. \$\endgroup\$ – mr5 Aug 25 '17 at 2:51
  • \$\begingroup\$ @LuisMendo I suspected so, because transposing an identity matrix makes no sense...hmm, I managed to save a byte with your algorithm. \$\endgroup\$ – Erik the Outgolfer Aug 25 '17 at 8:52
4
\$\begingroup\$

Python 2, 54 53 bytes

lambda n:[i+1for i in range(n*n)if i%-~n<1or i%~-n<1]

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Octave, 68 54 bytes

Thanks to @Stewie Griffin for saving 14 bytes!

@(x)unique([diag(m=reshape(1:x^2,x,x)),diag(flip(m))])

Try it online!

MATLAB, 68 bytes

x=input('');m=reshape([1:x*x],x,x);unique([diag(m) diag(flipud(m))])

Explanation:

@(x)                               % Anonymous function
m=reshape([1:x*x],x,x);            % Create a vector from 1 to x^2 and
                                   % reshape it into an x*x matrix.
diag(m)                            % Find the values on the diagonal.
diag(flip(m))                      % Flip the matrix upside down and
                                   % find the values on the diagonal.
unique([])                         % Place the values from both diagonals
                                   % into a vector and remove duplicates.
\$\endgroup\$
  • \$\begingroup\$ @LuisMendo Thanks, Jimi's my favourite. \$\endgroup\$ – Steadybox Aug 24 '17 at 14:59
4
\$\begingroup\$

Mathematica, 42 bytes

Union@Flatten@Table[{i,#+1-i}+i#-#,{i,#}]&

Try it online!

@KellyLowder golfed it down to..

Mathematica, 37 bytes

##&@@@Table[{i-#,1-i}+i#,{i,#}]⋃{}&

and @alephalpha threw away the table!

Mathematica, 34 bytes

Union@@Range[{1,#},#^2,{#+1,#-1}]&
\$\endgroup\$
  • \$\begingroup\$ ##&@@@Table[{i-#,1-i}+i#,{i,#}]⋃{}& is 5 bytes shorter \$\endgroup\$ – Kelly Lowder Aug 24 '17 at 14:54
  • \$\begingroup\$ Union@@Range[{1,#},#^2,{#+1,#-1}]& \$\endgroup\$ – alephalpha Aug 25 '17 at 11:55
2
\$\begingroup\$

Proton, 41 bytes

n=>[i+1for i:0..n*n if!(i%-~n)or!(i%~-n)]

Try it online!

\$\endgroup\$
2
\$\begingroup\$

MATL, 14 bytes

U:GeGXytPY|*Xz

Try it online!

\$\endgroup\$
  • \$\begingroup\$ 6 bytes \$\endgroup\$ – Luis Mendo Aug 24 '17 at 14:36
  • \$\begingroup\$ Wow! Please post it, I'll eventually delete mine \$\endgroup\$ – Cinaski Aug 24 '17 at 14:42
  • 1
    \$\begingroup\$ I will post it if you are not going to incorporate it into your answer; but no need to delete yours \$\endgroup\$ – Luis Mendo Aug 24 '17 at 14:43
2
\$\begingroup\$

C (gcc), 65 58 bytes

-7 bytes thanks to Titus!

f(n,i){for(i=0;i<n*n;i++)i%-~n&&i%~-n||printf("%d ",i+1);}

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ i%-~n&&i%~-n||printf("%d ",i+1) (-7 bytes) \$\endgroup\$ – Titus Aug 24 '17 at 16:54
2
\$\begingroup\$

C# (.NET Core), 97 83 bytes

f=>{var s="[";for(int i=0;i<n*n-1;)s+=i%-~n<1|i++%~-n<1?i+",":"";return s+n*n+"]";}

Try it online!

The change here is based on the shift between numbers to find. The two shifts starting at 0 are n-1 and n+1, so if n=5, the numbers for n-1 would be 0,4,8,12,16,20 and for n+1 would be 0,6,12,18,24. Combining these and giving 1-indexing (instead of 0-indexing) gives 1,5,7,9,13,17,19,21,25. The offset from n is achieved using bitwise negation (bitwise complement operation), where ~-n==n-1 and -~n==n+1.

Old Version

f=>{var s="[";for(int i=0;i<n*n-1;i++)s+=(i/n!=i%n&&n-1-i/n!=i%n?"":i+1+",");return s+$"{n*n}]";}

Try it online!

This approach uses the column and row indices for determining if the numbers are on the diagonals. i/n gives the row index, and i%n gives the column index.

Returning Only The Number Array

If constructing only the number array is deemed to count towards the byte cost, then the following could be done, based on Dennis.Verweij's suggestion (using System.Linq; adds an extra 18 bytes):

C# (.NET Core), 66+18=84 bytes

x=>Enumerable.Range(1,x*x).Where(v=>~-v%~-x<1|~-v%-~x<1).ToArray()

Try it online!

\$\endgroup\$
  • \$\begingroup\$ you can reduce the code by getting rid of the extra &. The extra & is there only to break the comparison if the first input is false MSDN \$\endgroup\$ – Dennis.Verweij Aug 25 '17 at 13:01
  • \$\begingroup\$ in fact you can have 92 bytes by using Linq Try it online! \$\endgroup\$ – Dennis.Verweij Aug 25 '17 at 13:47
  • \$\begingroup\$ @Dennis.Verweij Neat, I wasn't sure how much I could shift to the header or footer in TIO. I'll have a play around with mine. \$\endgroup\$ – Ayb4btu Aug 25 '17 at 20:07
  • \$\begingroup\$ you have to remember to include 18 bytes for the reference to linq (using System.Linq;) which is unfortunate, but how it works :S \$\endgroup\$ – Dennis.Verweij Aug 26 '17 at 18:56
  • \$\begingroup\$ Ah, ok. But that isn't necessary for using System;? (I assume wrapping it in a namespace System.Linq isn't valid?) \$\endgroup\$ – Ayb4btu Aug 26 '17 at 21:14
2
\$\begingroup\$

Javascript, 73 63 bytes

old version

n=>[...Array(y=n*n).keys(),y].filter(x=>(--x/n|0)==x%n||(x/n|0)==n-x%n-1)

Saved 10 bytes thanks to @Shaggy

n=>[...Array(n*n)].map((_,y)=>y+1).filter(x=>!(--x%-~n&&x%~-n))

First time golfing! here's hoping I didn't mess up too badly.

let f=n=>[...Array(n*n)].map((_,y)=>y+1).filter(x=>!(--x%-~n&&x%~-n));
[1,2,3,4,5].forEach(n=>console.log(f(n)))

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG :) A similar solution to the one I was working on (only mine is 0-indexed). You might be able to save some bytes by using the following in your filter function: !(--x%(n+1)&&x%(n-1)) and by creating your array like so: [...Array(n*n+1).keys()] \$\endgroup\$ – Shaggy Aug 24 '17 at 14:02
  • \$\begingroup\$ @Shaggy Thank you! I'll try to improve the answer with your suggestion as soon as I get home from work! \$\endgroup\$ – Marco Lepore Aug 24 '17 at 14:07
  • \$\begingroup\$ You're welcome. By the way: "it's a bit shorter than creating a [1...n*n] range with Array(n*n).fill().map((x,i)=>i+1)" - [...Array(n*n)].map((_,y)=>y+1) is a shorter way of doing that, for future reference. \$\endgroup\$ – Shaggy Aug 24 '17 at 14:26
  • \$\begingroup\$ Did a bit more with it and ended up with this for 56 bytes: n=>[...Array(n*n+1).keys()].filter(x=>!(--x%-~n&&x%~-n)) \$\endgroup\$ – Shaggy Aug 24 '17 at 14:49
  • \$\begingroup\$ @Shaggy I tried your last version but it would output an extra zero for f(1) and f(2), it works with a [1...n*n] range though so I used the way you showed me in the previous comment. Or maybe I messed up someway? \$\endgroup\$ – Marco Lepore Aug 27 '17 at 13:41
1
\$\begingroup\$

Pyth, 20 18 bytes

(Here is the initial version.)

hMf|<%ThQ1<%TtQ1U*

Test Suite.

Pyth, 18 bytes

hMf>1*%ThQ%T|tQ1U*

Test Suite.

\$\endgroup\$
1
\$\begingroup\$

Perl 5, 56 + 1 (-n) = 57 bytes

!(($_+1+$_/$,)%$,&&$_%($,+1))&&say++$_ for 0..($,=$_)**2

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Shouldn't ` -n` be +3? \$\endgroup\$ – sergiol Aug 24 '17 at 15:27
  • 1
    \$\begingroup\$ No. The assumed command line is perl -e. The command line for this example would be perl -ne. That's a difference of +1. \$\endgroup\$ – Xcali Aug 24 '17 at 15:32
1
\$\begingroup\$

Java (OpenJDK 8), 71 bytes

n->{for(int i=0;i<n*n;i++)if(i%-~n<1||i%~-n<1)System.out.println(i+1);}

Try it online!

Port of scottinet's answer.

\$\endgroup\$
1
\$\begingroup\$

Japt, 16 bytes

Can't seem to do better than this but I'm sure it's possible. Had to sacrifice 2 bytes for the unnecessary requirement that we use 1-indexing.

²õ f@´XvUÉ ªXvUÄ

Test it

\$\endgroup\$
1
\$\begingroup\$

Octave, 32 bytes

@(n)find((m=abs(--n:-2:-n))==m')

Try it online!

\$\endgroup\$
0
\$\begingroup\$

PHP, 56 54+1 bytes

+1 byte for -R flag

for(;$z**.5<$n=$argn;$z++)$z%-~$n&&$z%~-$n||print~+$z;

prints numbers prepended by dashes. Run as pipe with -nR or try it online.

requires PHP 5.6 or later for ** operator.
Add one byte for older PHP: Replace ;$z**.5<$n=$argn with $z=$argn;$z<$n*$n.

\$\endgroup\$
0
\$\begingroup\$

Ruby, 45 bytes

->n{(n*n).times{|i|i%-~n>0&&i%~-n>0||p(i+1)}}

Works internally as zero indexed. checks if i modulo n+1 or n-1 is 0, if so prints i+1.

\$\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.