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.
-
1\$\begingroup\$ May we return the coordinates of all occurrences? \$\endgroup\$chunes– chunes2024年02月06日 12:33:55 +00:00Commented Feb 6, 2024 at 12:33
-
1\$\begingroup\$ @chunes Just one please. \$\endgroup\$Simd– Simd2024年02月06日 12:34:05 +00:00Commented Feb 6, 2024 at 12:34
-
11\$\begingroup\$ I don't think "The coordinates should be in the order (row_idx, col_idx)" adds anything. \$\endgroup\$Jonathan Allan– Jonathan Allan2024年02月06日 13:21:31 +00:00Commented Feb 6, 2024 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\$Jonathan Allan– Jonathan Allan2024年02月06日 13:24:23 +00:00Commented Feb 6, 2024 at 13:24
-
2\$\begingroup\$ @JonathanAllan I succumbed to peer pressure. \$\endgroup\$Simd– Simd2024年02月07日 11:27:56 +00:00Commented Feb 7, 2024 at 11:27
27 Answers 27
-
2\$\begingroup\$ This is a great answer. \$\endgroup\$Simd– Simd2024年02月07日 07:11:55 +00:00Commented Feb 7, 2024 at 7:11
-
2\$\begingroup\$
x.shape[1]islen(x.T)\$\endgroup\$ovs– ovs2024年02月07日 11:55:10 +00:00Commented Feb 7, 2024 at 11:55 -
1\$\begingroup\$ @ovs I knew there was a
lentrick but I didn't think of transpose \$\endgroup\$qwr– qwr2024年02月07日 17:57:04 +00:00Commented Feb 7, 2024 at 17:57
Vyxal, 3 bytes
Þė↑
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.
-
\$\begingroup\$ I don't think you need to reverse the list anymore, the challenge was reworded \$\endgroup\$noodle person– noodle person2024年02月07日 12:31:48 +00:00Commented Feb 7, 2024 at 12:31
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←⌈/,
⌈/ 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
-
1\$\begingroup\$ 11 bytes \$\endgroup\$Mukundan314– Mukundan3142024年02月07日 16:55:38 +00:00Commented Feb 7, 2024 at 16:55
-
\$\begingroup\$ @Mukundan314 thanks! \$\endgroup\$Adám– Adám2024年02月08日 11:57:16 +00:00Commented Feb 8, 2024 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
-
\$\begingroup\$ Is
[ 5, [ 3, 2 ] ]correct in your TIO? I think it should be[ 5, [ 2, 3 ] ]\$\endgroup\$Simd– Simd2024年02月06日 12:32:26 +00:00Commented Feb 6, 2024 at 12:32 -
7\$\begingroup\$ @Simd Do you really need a strict output format? \$\endgroup\$Arnauld– Arnauld2024年02月06日 12:39:26 +00:00Commented Feb 6, 2024 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– Simd2024年02月06日 12:42:04 +00:00Commented Feb 6, 2024 at 12:42
Python + numpy, 61 bytes
lambda x:max(zip(x.flat,ndindex(x.shape)))
from numpy import*
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*
-
\$\begingroup\$ It's very likely the shortest numpy will avoid the import by only calling methods of the array argument \$\endgroup\$ovs– ovs2024年02月06日 13:28:02 +00:00Commented Feb 6, 2024 at 13:28
-
\$\begingroup\$ If only I had known about ndenumerate! I like these solutions a lot. \$\endgroup\$Simd– Simd2024年02月06日 13:35:47 +00:00Commented Feb 6, 2024 at 13:35
-
2\$\begingroup\$ @Simd If you're looking for a proper solution, I'd probably do
argmax+unravel_index. \$\endgroup\$ovs– ovs2024年02月06日 13:37:20 +00:00Commented Feb 6, 2024 at 13:37 -
\$\begingroup\$ Yes, no imports! \$\endgroup\$Stef– Stef2024年02月06日 22:36:32 +00:00Commented Feb 6, 2024 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.)
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,])
Fixed indexing and returned result, thanks to Giuseppe.
-
1\$\begingroup\$ I think you are supposed to return exactly one of the coordinates; this will return all of them. \$\endgroup\$Giuseppe– Giuseppe2024年02月07日 00:05:57 +00:00Commented Feb 7, 2024 at 0:05
-
\$\begingroup\$ @Giuseppe I see; the behavior is different than
which.max. \$\endgroup\$qwr– qwr2024年02月07日 00:39:25 +00:00Commented Feb 7, 2024 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– quarague2024年02月07日 10:01:12 +00:00Commented Feb 7, 2024 at 10:01
-
\$\begingroup\$ @quarague I think
matchwill return 1-dimensional index, not 2. \$\endgroup\$pajonk– pajonk2024年02月07日 11:08:10 +00:00Commented Feb 7, 2024 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– Giuseppe2024年02月07日 15:03:15 +00:00Commented Feb 7, 2024 at 15:03
-
\$\begingroup\$
FirstPosition->#&@@ Position\$\endgroup\$att– att2024年02月07日 19:23:02 +00:00Commented Feb 7, 2024 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
{iih}fot
Outputs as [[max, col], row]. Try it online!
Explanation
{iih}fot
{ }f Find all ways of satisfying this predicate:
i Get some [element, index] pair (i.e. a row and its row index)
ih 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
{iih}fotgtc
Outputs as [max, col, row]. Try it online!
Explanation
{iih}fotgtc
{iih}fot Same as above, gives [[max, col], row]
gt 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 \:
\{iih}fotgtc
To output as [max, [row, col]] as originally requested is... longer. Brachylog doesn't handle mixed-type lists very well.
-
-
\$\begingroup\$ Ah, thanks. Since
⌉doesn't work on nested lists, I assumed incorrectly thatowouldn't either. \$\endgroup\$DLosc– DLosc2024年02月21日 17:16:54 +00:00Commented Feb 21, 2024 at 17:16
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
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..]
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..])
This effectively does the same thing but outputs as ((max, x), y).
-
1
-
1\$\begingroup\$ @DLosc But... But the elegance of a one-liner! :P Thanks! \$\endgroup\$totallyhuman– totallyhuman2024年02月07日 03:39:41 +00:00Commented Feb 7, 2024 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])))
-
1\$\begingroup\$ Darn, 60 again:
lambda m:(a:=max(r:=max(m,key=max)),(m.index(r),r.index(a)))\$\endgroup\$no comment– no comment2024年03月07日 18:34:34 +00:00Commented Mar 7, 2024 at 18:34
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.
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}
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
}
-
\$\begingroup\$ Go makes it hard! \$\endgroup\$Simd– Simd2024年02月07日 18:51:16 +00:00Commented Feb 7, 2024 at 18:51
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.
Nekomata, 11 bytes
e#Ť#oÐzzÐjṀ
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
m{xz,Ṁ}xz,Ṁ
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×ばつ⍳∼w[i;j]>s⋄h←i⋄k←j⋄s←w[i×ばつ⍳a≥i×ばつ⍳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
Haskell + hgl, 22 bytes
xB cr<Asx<<(mM eu<+eu)
Outputs as ((x,y),v)
Strange order, 21 bytes
xB(cr<cr)<(mM eu<+eu)
Outputs as (x,(y,v))
Different strange order, 21 bytes
mx<g<m(mx<g)
g=fzp nn
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 withfzp nnin the final version. cr<cris a useful enough function to have a short version.
APL+WIN, 32 bytes
Prompts for matrix:
(⌈/,m),(,(⍳↑⍴m)∘.,⍳1↓⍴m)[↑⍒,m←⎕]
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)))
(λ(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 x0円]
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 x0円 ; length of first row in input