A ragged matrix, is a matrix that has a different number of elements in each row. Your challenge is to write a program in any favorable language to find the indices of all occurrences of target in the ragged matrix.
Input:
A list of ragged lists (can be empty) of positive integers and a target range e.g. 26-56. The target range, given 2 positive integers. For languages that do not support this type of list, you can input it as a string representation
You may assume that a<=b
Output:
If a number in the ragged list is within the range or equal to a or equal to b, output the index of the ragged list then the index of the number in that ragged list e.g. 0 4 - The 0 is the first ragged list in the input and the 4 is the index of the number in the first ragged list
Test cases:
[[[1,3,2,32,19],[19,2,48,19],[],[9,35,4],[3,19]],19-53]
->
[[0,3],[0,4],[1,0],[1,2],[1,3],[3,1],[4,1]]
[[[1,2,3,2],[],[7,9,2,1,4]],2-2]
->
[[0,1],[0,3],[2,2]]
You can choose to follow the output format above or output it in the following as well:
[[[1,3,2,32,19],[19,2,48,19],[],[9,35,4],[3,19]],19-53]
->
0 3 0 4 1 0 1 2 1 3 3 1 4 1
0-based and 1-based indexing is allowed
You can output your answers in any way as long as it is distinguishable what the indexes of the number and matrix are
You may assume the integers in the list are always positive and non-zero
This is code-golf, so shortest code wins!
14 Answers 14
Wolfram Language (Mathematica), 23 bytes
Position[a_/;#<=a<=#2]&
Input [a, b][list]. Returns 1-indexed.
Jelly, (削除) 8 (削除ここまで) 7 bytes
r/iⱮⱮŒṪ
Walkthrough
/ Reduce input range list by
r range
ⱮⱮ Foreach at depth 2
(on the right argument)
i Find first index of RHS in LHS
(Or, in this case, checks whether
current item (RHS) is within range (LHS)? )
ŒṪ All truthy multidimensional indices
-
1\$\begingroup\$ Nice job. A great Jelly tip is that when you find yourself using
@to look for dyads that can do what you need of the one you're using but with swapped arguments. In this case, to save a byte I would dor/ċⱮⱮŒṪ. \$\endgroup\$Jonathan Allan– Jonathan Allan2022年01月27日 19:43:37 +00:00Commented Jan 27, 2022 at 19:43 -
1\$\begingroup\$ You can also use
iinstead ofe@if you only need truthy/falsey values instead of 1/0: Relevant tip \$\endgroup\$2022年01月27日 19:44:59 +00:00Commented Jan 27, 2022 at 19:44
APL (Dyalog Extended), 8 bytes
Full program. Prompts for range, then array.
⍸↑⎕∊ ̈.../⎕
Explained from the right:
⎕ prompt (for range)
.../ reduce using the range function (gives enclosed list of all number in the range)
∊ ̈ check if the elements of each of the following lists are in the entire (because it is enclosed) range:
⎕ prompt for array
↑ mix list of Boolean lists into a matrix, padding with Falses
⍸ indices of Trues
R, 87 bytes
Or R>=4.1, 80 bytes by replacing the word function with a \.
function(l,a,b,`[`=lapply)cbind(rep(seq(l),lengths(w<-l[`%in%`,a:b][which])),unlist(w))
Solution shorter in R>=4.1:
R, 92 bytes
Or R>=4.1, 78 bytes by replacing two function occurrences with \s.
function(l,a,b)cbind(rep(seq(l),lengths(w<-lapply(l,function(x)which(x%in%a:b)))),unlist(w))
Outgolfed by @Giuseppe. See that answer for a detailed explanation and comparison of our approaches.
-
2
-
2\$\begingroup\$ @Giuseppe - Wow, you're an R magician! Do you remember all these seemingly-wierd functions, or do you have a secret way to search for them? \$\endgroup\$Dominic van Essen– Dominic van Essen2022年01月27日 20:04:45 +00:00Commented Jan 27, 2022 at 20:04
-
\$\begingroup\$ @Giuseppe, I think you should post it as a separate answer. \$\endgroup\$pajonk– pajonk2022年01月27日 20:05:19 +00:00Commented Jan 27, 2022 at 20:05
-
2\$\begingroup\$ @DominicvanEssen
sequencecomes up every now and again and I've been tyring to find a use forlengthswith all the ragged-list questions of late (looks like pajonk beat me there though). I'll admit after a couple years of golfing in R I had a slow year at work so I tried to read through the docs for mostbasefunctions and every now and again some weird ones come up :-) \$\endgroup\$Giuseppe– Giuseppe2022年01月27日 20:25:22 +00:00Commented Jan 27, 2022 at 20:25 -
\$\begingroup\$ @pajonk I'll post it separately with an explanation in a bit. \$\endgroup\$Giuseppe– Giuseppe2022年01月27日 20:25:44 +00:00Commented Jan 27, 2022 at 20:25
Python 3, 69 bytes
lambda l,r,e=enumerate:[[X,Y]for X,x in e(l)for Y,y in e(x)if y in r]
-3 thanks to @tsh
-
3\$\begingroup\$ 69 if accept input as a range object:
lambda l,r,e=enumerate:[[X,Y]for X,x in e(l)for Y,y in e(x)if y in r]\$\endgroup\$tsh– tsh2022年01月27日 08:11:22 +00:00Commented Jan 27, 2022 at 8:11 -
\$\begingroup\$ @tsh thanks a lot!! \$\endgroup\$avarice– avarice2022年01月27日 16:23:01 +00:00Commented Jan 27, 2022 at 16:23
K (ngn/k), 13 bytes
{+&~(y+!2)'x}
Takes the ragged matrix as x (first arg, a list of lists) and the range as y (second arg, a pair of integers).
(y+!2)convert the range from e.g.19 53to19 54(to do a[lb;ub]comparison rather than[lb;ub))(...)'xdo a binary lookup ofxin the list generated by(...). if a value inxis between the (adjusted) indices,0is returned~not the above; values within the range become1and all others0&use "deep-where" to return indices of 1's+transpose the result
It's likely that the final + (transpose) can be elided depending on what constitutes acceptable output.
R, 78 bytes
function(l,a,b)cbind(rep(seq(l),L<-lengths(l)),sequence(L))[unlist(l)%in%a:b,]
Originally posted as a comment on pajonk's answer, so uses that test harness. That answer is a very natural way to approach the problem in R, so if I hadn't peeked first, I probably wouldn't have found this gem.
Using R-style indexing, a single value in l is l[[i]][j], i.e., the jth (vector) element of the ith element of the list l. pajonk's answer generates a list of all the indices j for each i such that l[[i]][j] %in% a:b and then joins them with an appropriately-sized list of i, as below:
function(l,a,b){
in_ab <- sapply(l,`%in%`,a:b) # for each element of l, return TRUE/FALSE where elements are in a..b
j_idx_list <- sapply(in_ab,which) # now return the 1-based indices of the TRUE values
j_idx <- unlist(j_idx_list) # and collapse into a single vector
i_lengths <- lengths(j_idx_list) # take the # of valid j-indices in each sublist
i_idx <- rep(seq(l),i_lengths) # and generate i-indices to match
cbind(i_idx,j_idx) # and combine
}
This answer instead uses some functions rarely used in golfing, sequence and lengths to generate all the valid pairs i,j and then filters them directly. In fact, sequence is such an odd function in R that the docs used to say1 that "it mainly exists in reverence to the very early history of R", as I have mentioned before.
Ungolfed a bit:
function(l,a,b){
L <- lengths(l) # find the lengths of each element of l
j_idx <- sequence(L) # for each Length h, generate 1..h and append them together in order
i_idx <- rep(seq(l),L) # replicate each of 1..length(l) times equal to the length of l[[i]]
filter_idx <- unlist(l)%in%a:b # index for filtering
cbind(i_idx,j_idx)[filter_idx,] # combine i,j indices as columns of a matrix, and filter the rows
}
1 Starting in version 4.0.0, sequence was updated to accept a from and by argument, much like seq, and this line was removed.
05AB1E, 13 (or 7?) bytes
εNUεIŸsåiXN‚?
First input is the matrix; second the range as pair of integers.
Outputs pairs of 0-based indices without delimiter to STDOUT.
Try it online or verify all test cases.
Not sure if this is a valid output-format:
ŸIåεƶ0K
First input is the range as pair of integers; second the matrix.
Outputs the 1-based truthy indices of each row.
Try it online or verify all test cases.
Explanation:
ε # Map over each row of the (implicit) first input-matrix:
NU # Store the row-index in variable `X`
ε # Map over each integer in the row:
I # Push the second (implicit) input-pair
Ÿ # Convert it to an inclusive ranged list
såi # If the current integer is in this list:
XN‚ # Pair `X` with the inner map-index
? # Pop and output it
Ÿ # Convert the (implicit) first input-pair to an inclusive ranged list
I # Push the second input-matrix
å # Check for each inner-most value if it's within this range
ε # Map over these integers:
ƶ # Multiply each value by its 1-based index
0K # Remove all 0s
# (after which the list of lists is output implicitly)
Charcoal, 34 bytes
≔⮌I⪪η-η≔...·⊟η⊟ηηFLθF⌕AE§θιNoηκ1I⟦⟦ικ
Try it online! Link is to verbose version of code. Explanation:
≔⮌I⪪η-η≔...·⊟η⊟ηη
Convert the second input into a range.
FLθ
Loop over the sublists.
F⌕AE§θιNoηκ1
Loop over the indices where the element lies within the range.
I⟦⟦ικ
Output the outer and inner indices on separate lines double-spaced between each pair of indices.
Factor, 71 bytes
[ '[ [ _ _ between? ] arg-where ] map <enumerated> expand-values-push ]
Explanation
'[ [ _ _ between? ] arg-where ] mapMap the indices inside the range to each row of the ragged matrix.<enumerated>Zip a list with its indices.expand-values-pushCombine each key with each of the elements in its value, collecting the results in a single list of pairs.
! { { 1 3 2 32 19 } { 19 2 48 19 } { } { 9 34 4 } { 3 19 } } 19 53
'[ [ _ _ between? ] arg-where ] map ! { V{ 3 4 } V{ 0 2 3 } V{ } V{ 1 } V{ 1 } }
<enumerated> ! { { 0 V{ 3 4 } } { 1 V{ 0 2 3 } } { 2 V{ } } { 3 V{ 1 } } { 4 V{ 1 } } }
expand-values-push ! V{ { 0 3 } { 0 4 } { 1 0 } { 1 2 } { 1 3 } { 3 1 } { 4 1 } }
JavaScript (V8), (削除) 58 (削除ここまで) 56 bytes
(a,l,r)=>a.map((x,i)=>x.map((y,j)=>l>y|y>r||print(i,j)))
Saved 2 bytes thanks to Arnauld.
-
1\$\begingroup\$
l<=y&y<=r&&can be turned intol>y|y>r||\$\endgroup\$Arnauld– Arnauld2022年01月27日 21:12:50 +00:00Commented Jan 27, 2022 at 21:12
Vyxal, 12 bytes
ṫ÷r£hƛ\vc;ÞT
Needs input in form: [<main_arr>, [a, b]]
ṫ # Get [a, b]
÷r # Get range a..b
£ # Set to register
h # Main array
ƛ # Begin map
\ # Push register
vc # Is item inside range (vectorized)
;ÞT # Close map and print truthy indices
Python3, 80 bytes
lambda l,a,b:[ [X,Y] for X,x in enumerate(l) for Y,y in enumerate(x) if a<=y<=b]
Scala, 112 bytes
for a 2d matrix, find all indices where element is between the Range.
Golfed version. Try it online!
def f(l:Seq[Seq[Int]],r:Range)={for{(x,i)<-l.zipWithIndex;(y,j)<-x.zipWithIndex if r.contains(y)}yield Seq(i,j)}
Ungolfed version. Try it online!
object PythonToScala {
def main(args: Array[String]): Unit = {
val l: List[List[Int]] = List(List(1, 3, 2, 32, 19), List(19, 2, 48, 19), List(), List(9, 35, 4), List(3, 19))
val a: Int = 19
val b: Int = 53
def f(l: List[List[Int]], r: Range): List[List[Int]] = {
for {
(x, i) <- l.zipWithIndex
(y, j) <- x.zipWithIndex if r.contains(y)
} yield List(i, j)
}
println(f(l, a until b))
}
}
a<=b. Then why example is56-26? \$\endgroup\$rangeobject in python? (e.g.range(26,57)for26-56) \$\endgroup\$ŒṪseems to be made for this challenge \$\endgroup\$