What and where is the max?

This small challenge derives from my annoyance at discovering that numpy doesn't have a built in function for it.

Input

An n by m matrix of integers.

Output

The maximum value in the matrix and the 2d coordinates of one of its occurrences. The coordinates should be in the order (row_idx, col_idx) if your code is no shorter than it would be with (col_idx, row_idx). Otherwise it can be (col_idx, row_idx) but if so, please explain it in your answer.

1-based indexing is allowed too

Examples

Input [[1, 2], [3, 4]]. Output (4, (1, 1))
Input [[-1]]. Output (-1, (0, 0))
Input [[6], [5], [4], [3], [2], [1]]. Output (6, (0, 0))
Input [[1, 2, 3, 4], [0, 2, 5, 3], [-5, -2, 3, 5]]. Output (5, (1, 2))


Note

• May we return the coordinates of all occurrences? Commented Feb 6 at 12:33
– Simd
Commented Feb 6 at 12:34
• I don't think "The coordinates should be in the order (row_idx, col_idx)" adds anything. Commented Feb 6 at 13:21
• Yes, but it adds nothing to the challenge, I suggest removing it (much like one would generally allow both zero and one indexing). Commented Feb 6 at 13:24
• @JonathanAllan I succumbed to peer pressure.
– Simd
Commented Feb 7 at 11:27

Julia 1.0, 7 bytes

findmax


Try it online!

Outputs (value, CartesianIndex(row_index, col_index)) (1-indexed)

– Simd
Commented Feb 6 at 21:26

Python + Numpy, 48 bytes

lambda x:(x.max(),divmod(x.argmax(),x.shape[1]))


Attempt This Online!

• This is a great answer.
– Simd
Commented Feb 7 at 7:11
• x.shape[1] is len(x.T)
– ovs
Commented Feb 7 at 11:55
• @ovs I knew there was a len trick but I didn't think of transpose
– qwr
Commented Feb 7 at 17:57

UiuaSBCS, 9 bytes

⊢⊚⊃=∘/↥♭.


Try it!

⊢⊚⊃=∘/↥♭.
.  # duplicate
♭   # deshape
/↥    # maximum
⊃=∘      # mask of where the max exists in input
⊚         # coordinates of the ones
⊢          # first


Vyxal, 3 bytes

Þė↑


Try it Online!

And they said maximum by tail was useless! Now who's laughing! (me... It's me who's laughing)

Outputs [[x, y], item].

Explained

Þė↑­⁡​‎‎⁪⁡⁪⁠⁪⁡⁪‏⁠‎⁪⁡⁪⁠⁪⁢⁪‏‏​⁡⁠⁡‌⁢​‎‎⁪⁡⁪⁠⁪⁣⁪‏‏​⁡⁠⁡‌­
Þė   # ‎⁡Multidimensional enumeration
↑  # ‎⁢Maximum by tail
💎


Created with the help of Luminespire.

• I don't think you need to reverse the list anymore, the challenge was reworded Commented Feb 7 at 12:31

K (ngn/k), 12 bytes

(*+&=)\||//\


Try it online!

        |//           max
\    (mat,    )
(    )\|        (max,        )
&=                 indices
*+                   first


APL (Dyalog Unicode), 12 11 bytes

−1 byte thanks to Mukundan314

Requires ⎕IO←0 which is default on many systems. Returns [max, row_idx, col_idx]

M,⍴⊤,⍳M←⌈/,


Try it online!

⌈/ the maximum (lit. maximum reduction) of the

, ravelled (flattened) argument

M← store that as M (for Maximum)

,⍳index of first location of that in the ravelled (flattened) argument

⍴⊤ the shape-radix representation of that

M, prepend the Maximum

• 11 bytes Commented Feb 7 at 16:55
• @Mukundan314 thanks!
Commented Feb 8 at 11:57

JavaScript (ES6), 52 bytes

Returns [max, y, x].

m=>m.map((r,y)=>r.map((v,x)=>m=v<m[0]?m:[v,y,x]))&&m


Try it online!

• Is [ 5, [ 3, 2 ] ] correct in your TIO? I think it should be [ 5, [ 2, 3 ] ]
– Simd
Commented Feb 6 at 12:32
• Commented Feb 6 at 12:39
• The output format isn't strict, but the order of the coordinates is. I hope that's ok. For example, the Vyxal output is fine.
– Simd
Commented Feb 6 at 12:42

Python + numpy, 61 bytes

lambda x:max(zip(x.flat,ndindex(x.shape)))
from numpy import*


Attempt This Online!

Returns the last index of the maximal value. Different 63 bytes, maybe key= can shorten this a bit?

lambda x:max((b,a)for a,b in ndenumerate(x))
from numpy import*


Attempt This Online!

• It's very likely the shortest numpy will avoid the import by only calling methods of the array argument
– ovs
Commented Feb 6 at 13:28
• If only I had known about ndenumerate! I like these solutions a lot.
– Simd
Commented Feb 6 at 13:35
• @Simd If you're looking for a proper solution, I'd probably do argmax + unravel_index.
– ovs
Commented Feb 6 at 13:37
• Yes, no imports!
– Stef
Commented Feb 6 at 22:36

Jelly, 5 bytes

ŒĖṚ€Ṁ


A monadic Link that accepts a (multidimensional) array and yields a pair, [maximum-value, [row, column, ...]] using 1-indexing. (Identifying the last location of the maximum-value.)

Try it online!

How?

While Jelly has both ŒM (get all multidimensional indices of maximal elements), œị (get element at multidimensional index y), and œi (get first multidimensional index of y), amongst some others I think this may be the tersest approach...

ŒĖṚ€Ṁ - Link: multidimensional array of comparables, A
ŒĖ    - multidimensional enumerate
Ṛ€  - reverse each (from [coordinates, value] to [value, coordinates])
Ṁ - maximum


R, 35 bytes

Almost built-in, but which.max flattens the input.

\(x,m=max(x))c(m,which(x==m,T)[1,])


Attempt This Online!

Fixed indexing and returned result, thanks to Giuseppe.

• I think you are supposed to return exactly one of the coordinates; this will return all of them. Commented Feb 7 at 0:05
• @Giuseppe I see; the behavior is different than which.max.
– qwr
Commented Feb 7 at 0:39
• You can shrink this by using match instead of which because that will automatically only return the first match. So (x,m=max(x))c(m,match(m,x)) should do the job. Commented Feb 7 at 10:01
• @quarague I think match will return 1-dimensional index, not 2. Commented Feb 7 at 11:08
• I think you can index and return the first row only -- in fact, as it stands now, this isn't correct since this'll return the first two entries, columnwise! so which(x==m,T)[1,]. Commented Feb 7 at 15:03

Wolfram Language (Mathematica), 29 bytes

{s=Max@#,#&@@#~Position~s-1}&


Try it online!

-1 byte from @att

• FirstPosition -> #&@@ Position
– att
Commented Feb 7 at 19:23

Rust + ndarray, 41 bytes

|a|a.indexed_iter().max_by_key(|(_,x)|*x)


A closure of type fn(&Array2<u8>)->Option<((usize, usize), &u8)>.

ndarray_stats has an argmax, but it's very verbose at 46 bytes:

{use ndarray_stats::*;|a|(a.max(),a.argmax())}


Brachylog, 12 8 bytes

-4 bytes thanks to Fatalize

{iiʰ}ᶠot


Outputs as [[max, col], row]. Try it online!

Explanation

{iiʰ}ᶠot
{   }ᶠ    Find all ways of satisfying this predicate:
i         Get some [element, index] pair (i.e. a row and its row index)
iʰ       Apply the same operation to that row, turning it into an element and
its column index
We now have a list of [[element, col], row] for each element in the array
o   Sort ascending
t  Take the last one


Nicer output format, 11 bytes

{iiʰ}ᶠotgᵗc


Outputs as [max, col, row]. Try it online!

Explanation

{iiʰ}ᶠotgᵗc
{iiʰ}ᶠot     Same as above, gives [[max, col], row]
gᵗ   Wrap the last element in a singleton list: [[max, col], [row]]
c  Concatenate: [max, col, row]


To output as [max, row, col] is 12 bytes; the only change is to transpose the matrix first with \:

\{iiʰ}ᶠotgᵗc


To output as [max, [row, col]] as originally requested is... longer. Brachylog doesn't handle mixed-type lists very well.

• I think {iiʰ}ᶠot works (8 bytes and same output format). Outside of golfing, your answer is better though because it can list all maximums, whereas this one only gives the last one. Commented Feb 8 at 9:21
• Ah, thanks. Since ⌉ doesn't work on nested lists, I assumed incorrectly that o wouldn't either. Commented Feb 21 at 17:16

05AB1E, 9 bytes

˜Z=kIнg‰,


0-based; outputs the maximum and coordinate on separated newlines.

Explanation:

Unfortunately, 05AB1E lacks multidimensional builtins, so things are done manually. Otherwise this could have been 4-5 bytes probably.

˜          # Flatten the (implicit) input-matrix
Z         # Push its maximum (without popping the list)
=        # Print this max with trailing newline (without popping again)
k       # Pop both now, and get the 0-based index of this max in the list
Iнg    # Push the width of the input-matrix (push input; first item; length)
‰   # Divmod the index by this width
,  # Pop and print it with trailing newline as well


Perl 5MList::Util=max -p 58 bytes

$\=max/-?\d+/g;/\[[^[]*$\\b/;say$=~y/[//-1;say$&=~y/,//}{


Try it online!

Output format is

row
column
max


Another one bytes the dust thanks to DLosc.

f m=maximum[(c,(y,x))|(y,r)<-e m,(x,c)<-e r]
e=zip[0..]


Try it online!

Heh, this is technically a built-in solution. Outputs as (max, (y, x)).

Weird output solution, 46 39 bytes

-7 bytes thanks to to DLosc.

maximum.e.map(maximum.e)
e=(zip[0..])


Try it online!

This effectively does the same thing but outputs as ((max, x), y).

• 55 bytes for the first one, 39 bytes for the second one Commented Feb 6 at 21:45
• @DLosc But... But the elegance of a one-liner! :P Thanks! Commented Feb 7 at 3:39

Python 3.8 (pre-release), 66 60 bytes

Vanilla Python approach, outgolfed by the numpy versions.

-6 bytes as lambda expression instead of a function

lambda m:(a:=max(l:=sum(m,[])),divmod(l.index(a),len(m[0])))


Try it online!

• Darn, 60 again: lambda m:(a:=max(r:=max(m,key=max)),(m.index(r),r.index(a))) Commented Mar 7 at 18:34

Charcoal, 12 bytes

Ｉ⌈ＥＡ⟦⌈ικ⌕ι⌈ι


Try it online! Link is to verbose version of code. Outputs the highest possible row with the maximum value but the lowest possible column in that row. Explanation:

   Ａ            Input array
Ｅ             Map over rows
ι         Current row
⌈          Maximum value
κ        Current index
⌕       First index of
ι    Current row
⌈     Maximum value
ι      In current row
⟦           Make into list
⌈              Take the maximum
Ｉ               Cast to string
Implicitly print


Getting the maximum column of the maximum row can be done for 14 bytes:

Ｉ⌈ＥＡ⟦⌈ικ⌈⌕Ａι⌈ι


Try it online! Link is to verbose version of code. Explanation:

Ｉ⌈ＥＡ⟦⌈ικ        As above
⌕Ａ     Find all indices of
ι  Current row
⌈   Maximum value
ι    In current row
⌈       Take the maximum


Getting the lowest possible row with the lowest possible column takes a massive 21 bytes:

ＩＥ⌈Ｅθ⟦⌈ι±κ⌕ι⌈ι⟧⎇⊖κι±ι


Try it online! Link is to verbose version of code. Explanation: Negates the row number, which gives you the highest possible negated row, but then has to negate it again for display.

Go, 147 bytes

import."slices"
func f(I[][]int)(m,x,y int){m=Max(I[0])
for _,r:=range I{m=max(m,Max(r))}
for a,r:=range I{x,y=a,Index(r,m)
if y>-1{break}}
return}


Attempt This Online!

Returns as max, x, y. Assumes that the matrix is non-empty.

Explanation

import."slices"
func f(I[][]int)(m,x,y int){
m=Max(I[0])                       // default value for max, to account for negatives
for _,r:=range I{m=max(m,Max(r))} // find the max of the whole matrix
for a,r:=range I{                 // find the location of the max
x,y=a,Index(r,m)                 // the current row index, and the index of the max
if y>-1{break}}                  // if the max is in this row, exit the loop
return
}

• Go makes it hard!
– Simd
Commented Feb 7 at 18:51

=+sort(tocol(A:N&","&row(A:N)&","&column(A:N)),tocol(A:N),)


Put the 2D array in cells A1:N1000 and the formula in cell P1.

Singularizes the data and coordinates and sorts in descending order. Uses unary plus + to extract just the first result. Gives 1-indexed coordinates.

Nekomata, 11 bytes

ᵉ#Ť#ᵒÐᶻᶻÐjṀ


Attempt this online!

This language is cool, though this isn't really using the cooler aspects of it. I also have a sneaking suspicion this can get better.

Alternate solution, 11 bytes

ᵐ{xᶻ,Ṁ}xᶻ,Ṁ


Attempt this online!

This is more elegant, but it flips the indices.

APL(NARS), 109 chars

r←f w;i;j;s;h;k;a;b
j←1⋄s←¯∞⋄h←k←⍬⋄(a b)←⍴w
i←1
→4×⍳∼w[i;j]>s⋄h←i⋄k←j⋄s←w[i;j]
→3×⍳a≥i+←1⋄→2×⍳b≥j+←1
r←s(h,k)


19+23+3+30+21+8+5=109

How to use&test:

      ⎕fmt f 2 3⍴ 1 4 3 2 ¯1 5
┌2───────┐
│  ┌2───┐│
│5 │ 2 3││
│~ └~───┘2
└∊───────┘
⎕fmt 2 3⍴ 1 4 3 2 ¯1 5
┌3──────┐
2 1  4 3│
│ 2 ¯1 5│
└~──────┘


it would return the max and the first coordinates it finds max

xB cr<Asx<<(mM eu<+eu)


Attempt This Online!

Outputs as ((x,y),v)

Strange order, 21 bytes

xB(cr<cr)<(mM eu<+eu)


Attempt This Online!

Outputs as (x,(y,v))

Different strange order, 21 bytes

mx<g<m(mx<g)

g=fzp nn


Attempt This Online!

Outputs as ((v,y),x)

Reflection

This answer is hampered by the fact I haven't yet implemented any array handling functions, so this has to work with lists.

That asside, I have a couple of thoughts:

• There should be a flipped version of eu. I approximate this with fzp nn in the final version.
• cr<cr is a useful enough function to have a short version.

APL+WIN, 32 bytes

Prompts for matrix:

(⌈/,m),(,(⍳↑⍴m)∘.,⍳1↓⍴m)[↑⍒,m←⎕]


Try it online! Thanks to Dyalog Classic

Ruby, 55 bytes

->a{b=a.flatten
[m=b.max,b.index(m).divmod(a[0].size)]}


Attempt This Online!

Racket, 114 112 bytes

Output in the format (value row_idx col_idx)

(λ(x[y(apply append x)][m(flatten y)][i(index-of y m)][l(length(car x))])(list m(quotient i l)(remainder i l)))


Try it online!

(λ(x
[y (flatten x)]                      ; flatten the matrix
[m (apply max y)]                    ; find the max value
[i (index-of y m)]                   ; index of the value
[l (length (car x))])                ; length of a row
(list m(quotient i l)(remainder i l))) ; format output


Arturo, 51 bytes

$->x->@[m:<=max a:<=flatten x(index a m)/%size x\0]  Try it It feels good to golf in Arturo again. Explained more or less in order of evaluation: $->x->       ; a function taking an argument x
@[...]       ; wrap ... in a list
flatten x    ; flatten input
a:<=         ; assign this to a as an expression
max          ; get max of a
m:<=         ; assign this to m as an expression
(index a m)  ; find index of max in flattened input
/%           ; divmod
size x\0     ; length of first row in input
`