18
\$\begingroup\$

Challenge

Given a matrix of positive integers, determine if there are any "rings" of mountains. The formal definition for this challenge is: given a matrix of positive integers, is there any positive integer n for which there is a closed ring of cells in the matrix that are strictly greater than n such that all cells enclosed in the ring are less than or equal to n.

Let's take a truthy example:

3 4 5 3
3 1 2 3
4 2 1 3
4 3 6 5

If we set n to 2:

1 1 1 1
1 0 0 1
1 0 0 1
1 1 1 1

As we can clearly see, the 1s along the edge form a ring.

We define a ring as an ordered collection of cells where adjacent cells in the collection are also adjacent (edge or corner) on the grid. Additionally, the ring must contain at least 1 cell inside of it; that is, attempting to edge-only BFS-floodfill the entire matrix excluding the cells in the collection and never traversing a cell in the collection must miss at least one cell.

Truthy Test Cases

4 7 6 5 8 -> 1 1 1 1 1
6 2 3 1 5 -> 1 0 0 0 1 (n = 3)
6 3 2 1 5 -> 1 0 0 0 1
7 5 7 8 6 -> 1 1 1 1 1

1 3 2 3 2
1 6 5 7 2
1 7 3 7 4
1 6 8 4 6

1 3 1
3 1 3
1 3 1

7 5 8 7 5 7 8 -> if you have n = 4, you get an interesting ridge shape around the top and right of the grid
8 4 4 2 4 2 7
6 1 8 8 7 2 7
5 4 7 2 5 3 5
5 6 5 1 6 4 5
3 2 3 2 7 4 8
4 4 6 7 7 2 5
3 2 8 2 2 2 8
2 4 8 8 6 8 8

5 7 6 8 6 8 7 -> there is an island in the outer ring (n = 4), but the island is a ring
5 3 2 4 2 4 7
6 3 7 8 5 1 5
8 2 5 2 8 2 7
8 3 8 8 8 4 7
6 1 4 1 1 2 8
5 5 5 5 7 8 7

150 170 150
170 160 170
150 170 150

Falsy Test Cases

1 2 3 2 1 -> this is just a single mountain if you picture it graphcially
2 3 4 3 2
3 4 5 4 3
2 3 4 3 2
1 2 3 2 1

4 5 4 3 2 -> this is an off-centered mountain
5 6 5 4 3
4 5 4 3 2
3 4 3 2 1

1 1 1 1 1 -> this is four mountains, but they don't join together to form a ring
1 2 1 2 1
1 1 1 1 1
1 2 1 2 1
1 1 1 1 1

3 3 3 3 3 -> there is a ring formed by the `3`s, but the `4` in the middle is taller so it doesn't qualify as a mountain ring
3 1 1 1 3
3 1 4 1 3
3 1 1 1 3
3 3 3 3 3

3 4 4 4 3
4 4 3 4 4
3 3 3 3 4
4 4 3 4 4
3 4 4 4 3

1  2  3  4  5
6  7  8  9  10
11 12 13 14 15
16 17 18 19 20
22 23 24 25 26

Rules

  • Standard Loopholes Apply
  • This is , so the shortest answer in bytes in each language is declared the winner of its language. No answers will be accepted.
  • The input may be taken as any reasonable form for a matrix of positive integers
  • The output may be given as any two reasonable, consistent, distinct values indicating [true] or [false].
\$\endgroup\$
2
  • \$\begingroup\$ For what n is the third "truthy" test case actually truthy? [1,2]? \$\endgroup\$ Commented May 17, 2018 at 15:14
  • \$\begingroup\$ @EriktheOutgolfer The ring of 3s are adjacent by corner. So, yes. \$\endgroup\$
    – user202729
    Commented May 17, 2018 at 15:22

4 Answers 4

3
\$\begingroup\$

Jelly, 38 bytes

Ẇ€Z$⁺Ẏµ,ZẈ>2ẠµƇµḊṖZƊ⁺FṀ<,Z.ịḊṖ$€Ɗ€ƊȦ)Ṁ

Try it online!

Outputs 1 if the matrix contains mountain ranges, 0 otherwise.

How it works (slightly outdated)

I may be able to shorten the code a bit, so this section will probably undergo heavy editing.

The helper link

,Z.ịḊṖ$€Ɗ€ – Helper link. Let S be the input matrix.
,Z         – Pair S with its transpose.
        Ɗ€ – For each matrix (S and Sᵀ), Apply the previous 3 links as a monad.
  .ị       – Element at index 0.5; In Jelly, the ị atom returns the elements at
             indices floor(x) and ceil(x) for non-integer x, and therefore this
             returns the 0th and 1st elements. As Jelly is 1-indexed, this is the
             same as retrieving the first and last elements in a list.
    ḊṖ$€   – And for each list, remove the first and last elements.

For example, given a matrix in the form:

A(1,1) A(1,2) A(1,3) ... A(1,n)
A(2,1) A(2,2) A(2,3) ... A(2,n)
A(3,1) A(3,2) A(3,3) ... A(3,n)
...
A(m,1) A(m,2) A(m,3) ... A(m,n)

This returns the arrays (the order doesn't matter):

A(1,2), A(1,3), ..., A(1,n-1)
A(m,2), A(m,3), ..., A(m,n-1)
A(2,1), A(3,1), ..., A(m-1,1)
A(2,n), A(3,n), ..., A(m-1,n)

Long story short, this generates the outermost rows and columns, with the corners removed.

The main link

Ẇ€Z$⁺Ẏµ,ZẈ>2ẠµƇµḊṖZƊ⁺FṀ<ÇȦ)Ṁ – Main link. Let M be the input matrix.
Ẇ€                           – For each row of M, get all its sublists.
  Z$                         – Transpose and group into a single link with the above.
    ⁺                        – Do twice. So far, we have all contiguous sub-matrices.
     Ẏ                       – Flatten by 1 level.
      µ      µƇ              – Filter-keep those that are at least 3 by 3:
       ,Z                      – Pair each sub-matrix S with Sᵀ.
         Ẉ                     – Get the length of each (no. rows, no. columns).
          >2                   – Element-wise, check if it's greater than 2.
            Ạ                  – All.
               µ          )  – Map over each sub-matrix S that's at least 3 by 3
                ḊṖ           – Remove the first and last elements.
                  ZƊ         – Zip and group the last 3 atoms as a single monad.
                    ⁺        – Do twice (generates the inner cells).
                     FṀ      – Flatten, and get the maximum.
                       <Ç    – Element-wise, check if the results of the helper
                               link are greater than those in this list.
                         Ȧ   – Any and all. 0 if it is empty, or contains a falsey
                               value when flattened, else 1.
                           Ṁ – Maximum.
\$\endgroup\$
2
\$\begingroup\$

Clean, 224 ... 161 bytes

import StdEnv,StdLib
p=prod
~ =map
^ =reverse o$
@ =transpose o~(^o^)
$l=:[h:t]|h>1=l=[1: $t]
$e=e
?m=p[p(~p(limit(iterate(@o@)(~(~(\a|a>b=2=0))m))))\\n<-m,b<-n]

Try it online!

Defines the function ? :: [[Int]] -> Int, returning 0 if there is an ring, and 1 otherwise.

Works by turning the matrix into 2s for mountains and 0s for valleys, then floods in with 1s until the result stops changing. If any 0s still exist for any mountain height, the product will be 0.

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

JavaScript (Node.js), 302 bytes

a=>a.some((b,i)=>b.some((n,j)=>(Q=(W=(i,j,f)=>[a.map((b,I)=>b.map((t,J)=>I==i&J==j)),...a+0].reduce(A=>A.map((b,I)=>b.map((t,J)=>f(I)(J)&&(A[I-1]||b)[J]|(A[I+1]||b)[J]|b[J-1]|b[J+1]|t))))(i,j,I=>J=>a[I][J]<=n)).some((b,i)=>b.some((d,j)=>d&&!i|!j|!Q[i+1]|b[j+1]==b.b))<!/0/.test(W(0,0,I=>J=>!Q[I][J]))))

Try it online!

Checks if flowing from a point can't reach the border, while border can walk to every point

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

Python3, 568 bytes

E=enumerate
M=[(0,1),(0,-1),(1,0),(-1,0)]
def G(n,d):
 q=[i for i in d if d[i]==n]
 while q:
  v=q.pop(0)
  Q,S=[v],[v]
  for x,y in Q:
   for X,Y in M:
    if d.get(t:=(x+X,y+Y))and d[t]<=n and t not in S:Q+=[t];S+=[t];q=[*{*q}-{t}]
  yield S
def f(b):
 d={(x,y):v for x,r in E(b)for y,v in E(r)}
 for i in{*d.values()}:
  for g in G(i,d):
   e={(x+X,y+Y)for x,y in g for X,Y in M}-{*g}
   if all(d.get(t,0)>i for t in e):
    s,*e=e;q=[s];e={*e}
    for x,y in q:t=[u for X,Y in M+[(-1,-1),(1,1),(1,-1),(-1,1)]if(u:=(x+X,y+Y))in e];q+=t;e-={*t}
    if not e:return 1

Try it online!

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