g | x | w | all
Bytes Lang Time Link
8174Rust230515T160924Zmousetai
012Uiua SBCS240331T181952Zchunes
015Vyxal 3240207T131922Zpacman25
106Java JDK240502T172452ZGlory2Uk
011Pip xp240515T035509ZDLosc
055Perl 5240514T214453ZXcali
2420J230515T171624ZJonah
047JavaScript Node.js240401T025559Zl4m2
029Ruby230618T043038ZJordan
008Japt230515T143850ZShaggy
007Jelly230516T054124ZUnrelate
088SAS IML230515T194432ZBartosz
045Wolfram Language Mathematica230516T001910Zerfink
023Retina230516T211416ZFryAmThe
008Jelly230516T194020ZJonathan
020jq230516T062813Znoname
038Python 3230516T130014ZSuperSto
048Haskell230515T165856ZRoman Cz
034R230515T224447Zovs
018APL Dyalog Unicode230515T144047ZAdá
098Scala230516T052559Z138 Aspe
059julia230516T051537ZDamian P
048Python 2230516T042356Zloopy wa
775Vyxal230516T023819Zlyxal
018Charcoal230515T234016ZNeil
007Pyth230515T202440ZCursorCo
052R230515T181002Zpajonk
054JavaScript ES6230515T143253ZArnauld
077Excel230515T154709ZJos Wool

Rust, 81 74 bytes

|a,b,c|(0..).zip(a).filter(move|(d,_)|d%b%(b-1)*(d/b%(c-1))<1).map(|a|a.1)

Attempt This Online!

Takes input as a flattened matrix with size given as b and c

Uiua SBCS, 13 12 bytes

⊡⊚↥⇌≡⇌.≡∊0°⊡

Try it!

Port of Adám's APL answer.

-1 now that °⊡ is equivalent to ⇡△..

⊡⊚↥⇌≡⇌.≡∊0°⊡­⁡​‎‎⁡⁠⁤⁡‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁣‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏‏​⁡⁠⁡‌­
          °⊡   # ‎⁢coordinate matrix
       ≡∊0     # ‎⁣mask of coordinates that contain zero
   ⇌≡⇌.        # ‎⁤duplicate and reverse both axes
  ↥            # ‎⁢⁡max (logical or the masks together)
⊡⊚             # ‎⁢⁢select values from input according to mask

Vyxal 3, 15 bytes

∥Þhϩf₌[|⁰ḢṪᵛÞhJ

Try it Online!

accounting for depth-one lists takes 9 extra bytes for proper output

Java (JDK), 148 117 112 106 bytes

a->{for(int R=a.length,C=a[0].length,j=R*C;j-->0;)if(j<C|j/C>R-2|-~j%C<2)System.out.println(a[j/C][j%C]);}

Try it online!

I think this solution is pretty self-explanatory.

Pip -xp, 11 bytes

L4PDQ R:Z:a

Outputs (up to) four lists: down the left border, then right-to-left along the top border, then up the right border, and finally left-to-right along the bottom border.

Attempt This Online!

Explanation

L4PDQ R:Z:a
             ; a is command-line argument, eval'd as a Pip object (implicit, -x flag)
L4           ; Loop 4 times:
        Z:a  ;  Transpose a in place
      R:     ;  Reverse a in place
             ;  Together, these operations amount to a 90° counterclockwise rotation
   DQ        ;  Remove and return the last row of a
  P          ;  Print that value (formatted as a list, -p flag)

Perl 5, 55 bytes

sub{grep/./,@{shift@_},@{pop@_},map{(pop@$_),$$_[0]}@_}

Try it online!

J, 24 20 bytes

#~&,_>_(<,~<<0 _1)}]

Try it online!

alternative, 20 bytes

#~&,]+./&(#\e.1,#)|:

Try it online!

diagonal rotation, 24 bytes

#~&,_=[:+/,.~@1 _1|.!._]

Try it online!

Looks like this may be related to Adam's APL answer, but was discovered independently. See alternate below for a different approach.

  1. Diagonally rotate the matrix up-left using infinity as fill.
  2. Same thing down-right
  3. Add the two together (now the borders will all have the value infinity)
  4. Create a border-selecting 1-0 mask with 1 wherever infinity is
  5. Use that mask to filter the input, flattening both the mask and the input

original, 24 bytes

#~&,0=<:@$*/@:|"1$#:i.@$

Try it online!

JavaScript (Node.js), 47 bytes

m=>m.slice(1,-1).map(x=>x.splice(1,x.length-2))

Try it online!

Modify the input

Ruby, 31 29 bytes

Very similar to SuperStormer’s Python 3 answer. Outputs by modifying the given array.

->a{a[r=1..-2].map{_1[r]=[]}}

Attempt This Online!

Japt, 10 8 bytes

I/O as a 2D array of integers, with output sorted anti-clockwise starting in the bottom right corner.

4Æ=z)oÃf

Try it

4Æ=z)oÃf     :Implicit input of 2D array U
4Æ           :Map the range [0,4)
  =          :  Reassign to U
   z         :   Rotate U 90° clockwise
    )        :  End reassignment
     o       :  Pop last sub-array, mutating the array
      Ã      :End map
       f     :Filter, removing null elements

Jelly, 7 bytes

ŒDµżṪḢ)

Try it online!

No shot I could have thought of using diagonals if @Jonathan Allan hadn't first, so go upvote his solution! (Also, two bonus 8-byters: ŒDµṙ-ḣ2), ŒDµḊṖœ^))

ŒDµ   )    For each diagonal of the input:
    Ṫ      take and remove the last element,
   ż       zip with the remaining elements,
     Ḣ     and take the first of those pairs.

My original solutions, to laugh at:

Jelly, 9 bytes

ḊṖ$⁺€Fœ^F

Try it online!

ḊṖ           Remove the first and last rows
  $⁺€        and columns.
     F       Flatten the result,
        F    flatten the input,
      œ^     symmetric multiset difference.

Can't decide if this feels worse...:

Jelly, 9 bytes

ḊUZƊ3СZḢ

Try it online!

   Ɗ3С      Repeat [0, 1, 2, 3] times:
Ḋ            Remove the first row,
 U           reverse each row,
  Z          transpose.
       Z     Transpose the results
        Ḣ    and return the first row of that.

SAS IML, 88 70

Input is a rectangular matrix M e.g.,

M1={
 1  2  3  4  5  6,
 7  8  9 10 11 12,
13 14 15 16 17 18,
19 20 21 22 23 24,
25 26 27 28 29 30,
31 32 33 34 35 36,
37 38 39 40 41 42,
43 44 45 46 47 48,
49 50 51 52 53 54,
55 56 57 58 59 60
};

[EDIT:] According to comments below I updated the answer.

The code (an IML module):

start d(M);if 2<nrow(M)><ncol(M) then M[2:nrow(M)-1,2:ncol(M)-1]=.;M=M[loc(M>.)];finish;

Human readable:

start d(M);
  if 2 < nrow(M)><ncol(M) then 
    M[ 2:nrow(M)-1, 2:ncol(M)-1 ] = .; 
  M = M[ loc(M > .) ];
finish;

To execute the IML module d run the following:

call d(M);

The process:

  1. For a Matrix M with at least 3 rows and columns (2 < nrow(M)><ncol(M), where nrow(M) is number of rows, ncol(M) is number of columns, and >< is operator of minimum of two numbers) replace "everytnig inside" (2:nrow(M)-1, 2:ncol(M)-1) with missing data (.),
  2. select those elements of M where value is not missing.

To print out result, i.e. elements extracted from M, run the following line:

if type(M)="U" then print "M is Empty";
else print M;

Wolfram Language (Mathematica), 47 45 bytes

-2 bytes thanks to @alephalpha

Try it online!

If[Tr[1^#]>2,{#[[t={1,-1}]],#[[2;;-2,t]]},#]&

Explanation

Tr[1^#] returns the length of the shortest dimension by computing the Trace of a matrix of 1's with the same dimensions as the input, i.e., Min@Dimensions@#. If we have an edge case with a dimension of 0, 1, or 2, we return the input in its original form.

If Tr[1^#]>2 is true, then we use Mathematica's [[a;;b, c;;d]] syntax to access different parts of the matrix: #[[{1,-1}]] returns the first and last rows, #[[2;;-2,{1,-1}]] returns the first and last columns while excluding the "corners." We return a ragged array as the output: if the input is mxn with m,n>2, the output will be of the format {(2 x n array), ((m-2) x 2 array)}

Retina, 23 bytes

(?<=¶.+)\b\S+\b(?=.+¶)

Try it online!

Expects a matrix as having columns separated by spaces and rows separated by newlines. Works by removing numbers that have a newline more than immediately before and after them. The boundaries are required to avoid deleting digits/signs elsewhere in the boundary numbers since there isn't a way to make lookahead/behind non-greedy/backtrack (at least in fewer than 4 bytes).

Seems shorter than listing all boundary numbers, for the same reason. I've found a slightly crazy version that is a byte shorter, but is also far more abusive of the lax I/O.

L`^.+|.+$|\w+¶|\G[^,]+

Jelly, 8 bytes

With the lax output requirements I was expecting to find terser in Jelly!

ŒDị@Ḋ¡€.

A monadic Link that accepts the rectangular matrix and yields a list of lists of border values.

Try it online! Or see the test-suite.

How?

ŒDị@Ḋ¡€. - Link: list of lists, M
ŒD       - all NW-SE diagonals of M
       . - set the right argument to 0.5
      €  - for each diagonal:
     ¡   -   repeat...
    Ḋ    -   ...number of times: dequeue (i.e. once if diagonal length > 1)
   @     -   ...action: with swapped arguments - f(0.5, diagonal)
  ị      -                index into*
             
             * fractional indices give the two neighbours in the 
               case of 0.5 that's 0 (the last) and 1 (the first)

jq, 57 46 20 bytes

del(.[1:-1][][1:-1])

Online demo

Python 3, 38 bytes

def f(x):
 for c in x[1:-1]:c[1:-1]=[]

Outputs by modifying arguments. The code also works on Python 2.

Explanation: deletes the center part of each center row by modifying the original input.

Attempt This Online! (additional test cases taken from loopy walt's answer)

Haskell, 48 bytes

b=zipWith($)[head,map last,last,map head].repeat

Try it online!

Haskell, 74 bytes

import Data.List;(o:t)#(r:s)=r++t#(reverse$transpose$s);_#_=[];b=("1234"#)

Try it online!

At each of the four or less iterations, # peels the top row r from the matrix, and rotates it i-wise by transpose sending corner 2 to 3 and reverse sending corner 2 from 3 to 1 before reiterating for one side o less than before.

R, 44 34 bytes

\(m)m[rev(d<-row(m)<2|col(m)<2)|d]

Attempt This Online!

Footer stolen from pajonk's answer, and -10 thanks to them!

APL (Dyalog Unicode), 23 22 18 bytes

Thanks to ovs for −4 bytes.

Anonymous prefix lambda.

{⍵[⍸∨∘⌽∘⊖⍨1∊¨⍳⍴⍵]}

Try it online!

{} "dfn"; argument is :

⍵[] select from the argument:

   where indicated by

  ∨∘⌽∘⊖⍨ the following mask when ORed with its mirrored flipped version…

  1∊¨ true only where 1 is a member of

   the indices for an array that has the shape

  ⍴⍵ the shape of the argument

Scala, 98 bytes

Golfed version. Try it online!

(o,q)=>(o,q)match{case (Nil,_)|(_,Nil)=>Seq[Int]()case (_,r::s)=>r++f(o.tail,s.transpose.reverse)}

Ungolfed version. Try it online!

object Main extends App {
  def f(o: List[Int], rs: List[List[Int]]): List[Int] = (o, rs) match {
    case (Nil, _) | (_, Nil) => List[Int]()
    case (_, r :: s) => r ++ f(o.tail, s.transpose.reverse)
  }

  println(f((1 to 4).toList, List(List(1,2,3), List(4,5,6), List(7,8,9))))
  println(f((1 to 4).toList, List(List(9, 2,-5, 3), List(18, 3, 8, 0), List(2, 7,21,-3), List(9,-5,10,99))))
  println(f((1 to 4).toList, List(List(10, 20, 30, 40, 50, 60), List(70, 80, 90,-90,-80,-70), List(-60,-50,-40,-30,-20,-10))))
}

julia, 59 bytes

Expects a Matrix{Any} and returns a Vector{Any} of the border entries.

Each call of this function pops the top row of the matrix, rotates the resulting matrix to the right and recurses. Terminates after 4 iterations or when the resulting matrix is empty.

f(M,c=4)=length(M)c>0 ? [M[1,:];f(M[end:-1:2,:]',c-1)] : []

Attempt This Online!

Python 2, 48 bytes

f=lambda a:a[:1]+a[1:][-1:]+map(f,a[1:-(a>[f])])

Attempt This Online!

Takes a LOL and returns a ragged LOL. Output for non degenerate inputs is [top row,bottom row,[1st,last]of 2nd row,[1st,last]of 3rd row,...

Vyxal, 62 bitsv1, 7.75 bytes

4(∩ḣṘ)_W'

Try it Online!

Port of pyth messed up by the fact that and return 0 on an empty list instead of erroring (which has its use, but is annoying here)

Explained

4(∩ḣṘ)_W'
4(   )    # 4 times
  ∩       #   transpose top of stack
   ḣ      #   separate the head from the rest
    Ṙ     #   and reverse
      _W  # pop the remaining list and wrap the stack in a list
        ' # remove 0s and empty lists

Charcoal, 18 bytes

IΣEθΦι¬∧﹪κ⊖Lθ﹪μ⊖Lι

Attempt This Online! Link is to verbose version of code. Explanation: Uses a filter to keep elements in the first or last row or column i.e. those that are not both in an interior row and in an interior column.

   θ                Input array
  E                 Map over rows
     ι              Current row
    Φ               Filtered where
         κ          Current row
        ﹪           Modulo
            θ       Input array
           L        Length
          ⊖         Decremented
       ∧            Logical And
              μ     Current column
             ﹪      Modulo
                 ι  Current row
                L   Length
               ⊖    Decremented
      ¬             Logical Not
 Σ                  Flatten
I                   Cast to string
                    Implicitly print

Pyth, 7 bytes

V4.)=_C

Try it online!

Prints each side as lists separated by newlines. Goes clockwise starting with the left side.

Explanation

V4.)=_CQ    # implicitly add Q
            # implicitly assign Q = eval(input())
V4          # loop 4 times
    =  Q    #   assign Q to
      CQ    #   Q transposed
     _      #   and reversed
  .)        #   pop the last element of Q and print it

R, 52 bytes

\(m)m[row(m)%in%c(1,nrow(m))|col(m)%in%c(1,ncol(m))]

Attempt This Online!

JavaScript (ES6), 54 bytes

m=>m.map((r,y)=>r.filter((_,x)=>x*y/r[x+1]?!m[y+1]:1))

Try it online!

Or 58 bytes (ES10) if we want to flatten the output:

m=>m.flatMap((r,y)=>r.filter((_,x)=>x*y/r[x+1]?!m[y+1]:1))

Try it online!

Commented

m =>                 // m[] = input matrix
m.map((r, y) =>      // for each row r[] in m[] at index y:
  r.filter((_, x) => //   for each value in r[] at index x:
    x * y            //     if neither x nor y is equal to 0 and there's
    / r[x + 1] ?     //     at least one more column after this one:
      !m[y + 1]      //       keep the value only if this is the last row
    :                //     else:
      1              //       keep the value
  )                  //   end of filter()
)                    // end of map()

Excel, 77 bytes

=TOCOL(B2#/(MAP(B2#,LAMBDA(b,SUM(SUBTOTAL(2,OFFSET(b,{-1;1},{-1,1})))))<4),2)

Input is spilled range deliberately set to have its top-leftmost cell as B2, rather than the customary A1, such that the four cells above, below, to the right and to the left of that cell exist.