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\$
12
  • 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, 2017 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, 2017 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, 2017 at 10:01
  • 7
    \$\begingroup\$ Does the order matter? \$\endgroup\$
    – Mr. Xcoder
    Aug 24, 2017 at 10:19
  • 9
    \$\begingroup\$ FWIW I think having the order be irrelevant might make for more interesting golfs... \$\endgroup\$ Aug 24, 2017 at 11:17

22 Answers 22

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\$
1
  • 2
    \$\begingroup\$ So simple... :) \$\endgroup\$ Aug 24, 2017 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\$
5
  • \$\begingroup\$ Nice workaround, using the signs as separators. Could you use bitwsie & to save a byte? \$\endgroup\$
    – Shaggy
    Aug 24, 2017 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, 2017 at 13:58
  • \$\begingroup\$ Yup, just tested it with n=5 and spotted that it wouldn't work. \$\endgroup\$
    – Shaggy
    Aug 24, 2017 at 14:08
  • \$\begingroup\$ k%~-n&&k%-~n should work. nice trick with the separator! \$\endgroup\$
    – Titus
    Aug 24, 2017 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, 2017 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\$
6
  • 1
    \$\begingroup\$ -1 byte d=diag(n<-scan());which(d|d[n:1,]) \$\endgroup\$
    – Rift
    Aug 24, 2017 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, 2017 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\$ Aug 25, 2017 at 12:30
  • \$\begingroup\$ Though I'm not planning on going back and editing all my old answers to fix this! \$\endgroup\$ Aug 25, 2017 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, 2017 at 12:41
6
\$\begingroup\$

Jelly, 8 bytes

⁼þ`+Ṛ$ẎT

Try it online!

Uses Luis Mendo's algorithm on his MATL answer.

\$\endgroup\$
2
  • \$\begingroup\$ Mhm, I am quite surprised you didn't use ŒD. \$\endgroup\$
    – Mr. Xcoder
    Aug 24, 2017 at 11:06
  • \$\begingroup\$ @Mr.Xcoder ŒD does something completely different from X of a specific size. \$\endgroup\$ Aug 24, 2017 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\$
4
  • \$\begingroup\$ What is "transpose" supposed to mean? \$\endgroup\$ Aug 24, 2017 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, 2017 at 19:37
  • \$\begingroup\$ Amazing! It would take me two loops if I want to accomplish this. \$\endgroup\$
    – mr5
    Aug 25, 2017 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\$ Aug 25, 2017 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\$
0
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\$
2
  • \$\begingroup\$ ##&@@@Table[{i-#,1-i}+i#,{i,#}]⋃{}& is 5 bytes shorter \$\endgroup\$ Aug 24, 2017 at 14:54
  • \$\begingroup\$ Union@@Range[{1,#},#^2,{#+1,#-1}]& \$\endgroup\$
    – alephalpha
    Aug 25, 2017 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\$
3
  • \$\begingroup\$ 6 bytes \$\endgroup\$
    – Luis Mendo
    Aug 24, 2017 at 14:36
  • \$\begingroup\$ Wow! Please post it, I'll eventually delete mine \$\endgroup\$
    – Cinaski
    Aug 24, 2017 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, 2017 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
  • 1
    \$\begingroup\$ i%-~n&&i%~-n||printf("%d ",i+1) (-7 bytes) \$\endgroup\$
    – Titus
    Aug 24, 2017 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\$
5
  • \$\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\$ Aug 25, 2017 at 13:01
  • \$\begingroup\$ in fact you can have 92 bytes by using Linq Try it online! \$\endgroup\$ Aug 25, 2017 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, 2017 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\$ Aug 26, 2017 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, 2017 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\$
5
  • \$\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, 2017 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\$ Aug 24, 2017 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, 2017 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, 2017 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\$ Aug 27, 2017 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\$
2
  • \$\begingroup\$ Shouldn't ` -n` be +3? \$\endgroup\$
    – sergiol
    Aug 24, 2017 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, 2017 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\$
0
\$\begingroup\$

Husk, 12 bytes

ṁo►L∂Se↔C¹ḣ□

Try it online!

indices are unordered.

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