18
\$\begingroup\$

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

numpy answers gratefully received too.

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

26 Answers 26

10
\$\begingroup\$

Julia 1.0, 7 bytes

findmax

Try it online!

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

\$\endgroup\$
1
  • 1
    \$\begingroup\$ A genuine built-in answer! \$\endgroup\$
    – Simd
    Feb 6 at 21:26
9
\$\begingroup\$

Python + Numpy, 48 bytes

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

Attempt This Online!

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

Uiua SBCS, 9 bytes

⊢⊚⊃=∘/↥♭.

Try it!

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

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.

\$\endgroup\$
1
  • \$\begingroup\$ I don't think you need to reverse the list anymore, the challenge was reworded \$\endgroup\$
    – noodle man
    Feb 7 at 12:31
5
\$\begingroup\$

K (ngn/k), 12 bytes

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

Try it online!

        |//           max
           \    (mat,    )
(    )\|        (max,        )
   &=                 indices
 *+                   first
\$\endgroup\$
5
\$\begingroup\$

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

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 11 bytes \$\endgroup\$ Feb 7 at 16:55
  • \$\begingroup\$ @Mukundan314 thanks! \$\endgroup\$
    – Adám
    Feb 8 at 11:57
4
\$\begingroup\$

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!

\$\endgroup\$
3
  • \$\begingroup\$ Is [ 5, [ 3, 2 ] ] correct in your TIO? I think it should be [ 5, [ 2, 3 ] ] \$\endgroup\$
    – Simd
    Feb 6 at 12:32
  • 7
    \$\begingroup\$ @Simd Do you really need a strict output format? \$\endgroup\$
    – Arnauld
    Feb 6 at 12:39
  • \$\begingroup\$ 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. \$\endgroup\$
    – Simd
    Feb 6 at 12:42
4
\$\begingroup\$

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!

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

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
\$\endgroup\$
4
\$\begingroup\$

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.

\$\endgroup\$
6
  • \$\begingroup\$ I think you are supposed to return exactly one of the coordinates; this will return all of them. \$\endgroup\$
    – Giuseppe
    Feb 7 at 0:05
  • \$\begingroup\$ @Giuseppe I see; the behavior is different than which.max. \$\endgroup\$
    – qwr
    Feb 7 at 0:39
  • \$\begingroup\$ 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. \$\endgroup\$
    – quarague
    Feb 7 at 10:01
  • \$\begingroup\$ @quarague I think match will return 1-dimensional index, not 2. \$\endgroup\$
    – pajonk
    Feb 7 at 11:08
  • \$\begingroup\$ 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,]. \$\endgroup\$
    – Giuseppe
    Feb 7 at 15:03
4
\$\begingroup\$

Wolfram Language (Mathematica), 29 bytes

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

Try it online!

-1 byte from @att

\$\endgroup\$
1
  • \$\begingroup\$ FirstPosition -> #&@@ Position \$\endgroup\$
    – att
    Feb 7 at 19:23
4
\$\begingroup\$

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())}
\$\endgroup\$
4
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$
    – Fatalize
    Feb 8 at 9:21
  • \$\begingroup\$ Ah, thanks. Since doesn't work on nested lists, I assumed incorrectly that o wouldn't either. \$\endgroup\$
    – DLosc
    Feb 21 at 17:16
3
\$\begingroup\$

05AB1E, 9 bytes

˜Z=kIнg‰,

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

Try it online or verify all test cases.

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
\$\endgroup\$
3
\$\begingroup\$

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

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

Try it online!

Output format is

row
column
max
\$\endgroup\$
3
\$\begingroup\$

Haskell, 56 55 bytes

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).

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 55 bytes for the first one, 39 bytes for the second one \$\endgroup\$
    – DLosc
    Feb 6 at 21:45
  • 1
    \$\begingroup\$ @DLosc But... But the elegance of a one-liner! :P Thanks! \$\endgroup\$ Feb 7 at 3:39
2
\$\begingroup\$

Charcoal, 12 bytes

I⌈EA⟦⌈ικ⌕ι⌈ι

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:

   A            Input array
  E             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
I               Cast to string
                Implicitly print

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

I⌈EA⟦⌈ικ⌈⌕Aι⌈ι

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

I⌈EA⟦⌈ικ        As above
         ⌕A     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:

IE⌈Eθ⟦⌈ι±κ⌕ι⌈ι⟧⎇⊖κι±ι

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.

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

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
}
\$\endgroup\$
1
  • \$\begingroup\$ Go makes it hard! \$\endgroup\$
    – Simd
    Feb 7 at 18:51
2
\$\begingroup\$

Google Sheets, 63 59 bytes

=+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.

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

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!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Darn, 60 again: lambda m:(a:=max(r:=max(m,key=max)),(m.index(r),r.index(a))) \$\endgroup\$
    – no comment
    Mar 7 at 18:34
2
\$\begingroup\$

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.

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

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

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

Haskell + hgl, 22 bytes

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.
\$\endgroup\$
1
\$\begingroup\$

APL+WIN, 32 bytes

Prompts for matrix:

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

Try it online! Thanks to Dyalog Classic

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

Ruby, 55 bytes

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

Attempt This Online!

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

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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