Länge des längsten Abstiegs

8

Ihre Aufgabe ist es, die Länge des längsten Abstiegs auf einem "Berg" zu bestimmen, der als Gitter aus ganzzahligen Höhen dargestellt wird. Ein "Abstieg" ist ein beliebiger Weg von einer Startzelle zu orthogonal benachbarten Zellen mit streng abnehmenden Höhen (dh nicht diagonal und nicht auf dieselbe Höhe). Sie können beispielsweise von 5-4-3-1, aber nicht von 5-5-4-3-3-2-1 wechseln. Die Länge dieses Pfades gibt an, wie viele Zellbewegungen von der Startzelle zur Endzelle vorhanden sind. 5-4-3-1 ist also Länge 3.

Sie erhalten ein rechteckiges Gitter als Eingabe und sollten eine Ganzzahl ausgeben, die den längsten Abstieg angibt.

Beispiele

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

Die Länge des längsten Abstiegs auf diesem Berg beträgt 5. Der längste Weg beginnt bei der 7 und bewegt sich nach links, oben, links, oben und dann nach links (7-6-5-4-2-1). Da dieser Pfad 5 Bewegungen enthält, beträgt die Pfadlänge 5.

Sie könnten alle die gleiche Nummer sein.

1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

Da diese Höhenkarte flach ist, ist der längste Abstieg 0. (nicht 19, da die Pfadsequenz streng absteigend sein muss)

Höhenkarten können aus größeren Zahlen als einstelligen Zahlen bestehen.

10 12 13 14 15 15
17 14 15 15 15 16
18 20 21 15 15 15
21 14 10 11 11 15
15 15 15 15 15 15

Der längste Weg hat hier die Länge 6. (21, 20, 18, 17, 14, 12, 10)

... und noch größere Zahlen sind auch in Ordnung.

949858 789874  57848  43758 387348
  5848 454115   4548 448545 216464
188452 484126 484216 786654 145451
189465 474566 156665 132645 456651
985464  94849 151654 151648 484364

Der längste Abstieg ist hier von Länge 7. (786654, 484216, 484126, 474566, 156665, 151654, 151648, 132645)

Regeln und Hinweise

  • Raster können in jedem geeigneten Format erstellt werden. Geben Sie Ihr Format in Ihrer Antwort an.
  • Sie können davon ausgehen, dass die Höhenzuordnung perfekt rechteckig ist, nicht leer ist und nur positive Ganzzahlen im vorzeichenbehafteten 32-Bit-Ganzzahlbereich enthält.
  • Der längste Abstiegsweg kann an einer beliebigen Stelle im Raster beginnen und enden.
  • Sie müssen den längsten Abstiegsweg in keiner Weise beschreiben. Nur seine Länge ist erforderlich.
  • Der kürzeste Code gewinnt
Beefster
quelle
Wie ist das letzte Beispiel zu interpretieren?
Peter Taylor
@ PeterTaylor Ich bin nicht sicher, was du meinst.
Beefster
Ich denke, das letzte Beispiel ist nur eine Matrix aus mehrstelligen Zahlen
Verkörperung der Ignoranz
@EmbodimentofIgnorance, ah, ja, ich verstehe. Es wäre viel einfacher, den Pfad mit zweistelligen Zahlen anstatt mit 4 bis 6 zu erkennen.
Peter Taylor
1
@ Οurous: nur rechteckig. Nicht gezackt.
Beefster

Antworten:

8

JavaScript (ES7),  106 103 102  98 Byte

f=(m,n=b=-1,x,y,p)=>m.map((r,Y)=>r.map((v,X)=>(x-X)**2+(y-Y)**2-1|v/p?b=n<b?b:n:f(m,n+1,X,Y,v)))|b

Probieren Sie es online aus!

Kommentiert

f = (                        // f = recursive function taking:
  m,                         //   m[]  = input matrix
  n = b = -1,                //   n    = length of the current path; b = best length so far
  x, y,                      //   x, y = coordinates of the previous cell
  p                          //   p    = value of the previous cell
) =>                         //
  m.map((r, Y) =>            // for each row r[] at position Y in m[]:
    r.map((v, X) =>          //   for each value v at position X in r[]:
      (x - X) ** 2 +         //     compute the squared Euclidean distance
      (y - Y) ** 2           //     between (x, y) and (X, Y)
      - 1                    //     if A) the above result is not equal to 1
      | v / p ?              //     or B) v is greater than or equal to p:
        b = n < b ? b : n    //       end of path: update b to n if n >= b
      :                      //     else:
        f(m, n + 1, X, Y, v) //       do a recursive call
    )                        //   end of inner map()
  ) | b                      // end of outer map(); return b

Wie?

xyp NaN , was den rekursiven Aufruf auslöst. Daher werden alle Zellen als möglicher Ausgangspunkt des Pfades betrachtet.

Arnauld
quelle
6

Gelee ,  23 21  20 Bytes

-2 danke an Erik den Outgolfer

ŒỤŒPạƝ§ỊẠƲƇœị⁸QƑƇṪL’

Probieren Sie es online aus! (viel zu ineffizient für die Beispiele - Pfad hier ist95 94 93 83 77 40 10so6ergibt sich)

Wie?

ŒỤŒPạƝ§ỊẠƲƇœị⁸QƑƇṪL’ - Link: list of lists of integers, M
ŒỤ                   - multi-dimensional indices sorted by values
  ŒP                 - power-set
          Ƈ          - filter, keep those for which:
         Ʋ           -   last four links as a monad:
     Ɲ               -     for each pair of neighbours:
    ạ                -       absolute difference
      §              -     sum each
       Ị             -     insignificant?
        Ạ            -     all?
           œị        - multi-dimensional index into:
             ⁸       -   chain's left argument, M
                Ƈ    - filter, keep only those:
               Ƒ     -   unaffected by?:
              Q      -     de-duplicate
                 Ṫ   - tail
                  L  - length
                   ’ - decrement
Jonathan Allan
quelle
3

Python 2, 150 147 140 136 134 132 125 123 120 Bytes

l=lambda g,i,j:max(0<g.get(t)<g[i,j]and-~l(g,*t)for d in(-1,1)for t in((i+d,j),(i,j+d)))
lambda g:max(l(g,*t)for t in g)

Probieren Sie es online aus!

Nimmt Eingaben in Form eines Wörterbuchs vor (x, y): value.

-7 Bytes dank wizzwizz4, -2 Bytes dank Jonathan Allen, -2 Bytes dank BMO

Alternative 123 121 Bytes

l=lambda i,j:max(0<g.get(t)<g[i,j]and-~l(*t)for d in(-1,1)for t in((i+d,j),(i,j+d)))
g=input();print max(l(*t)for t in g)

Probieren Sie es online aus!

Im Wesentlichen die gleiche Lösung, nur dass das endgültige Lambda durch ein tatsächliches Programm ersetzt wird. Ich persönlich mag den ersten besser, aber dieser kommt der Anzahl der Bytes sehr nahe g, da er als globale Variable verwendet werden kann.

ArBo
quelle
2

Sauber , 211 207 Bytes

import StdEnv,Data.List
z=zipWith
$l=maximum[length k-1\\p<-permutations[(v,[x,y])\\y<-[0..]&u<-l,x<-[0..]&v<-u],(k,[m:n])<-map unzip(subsequences p)|and[all((>)2o sum o map abs)(z(z(-))n[m:n]):z(>)k(tl k)]]

Probieren Sie es online aus!

Eine Brute-Force-Lösung, die eine Liste von Listen mit ganzen Zahlen ( [[Int]]) verwendet.
Der TIO-Treiber hat das gleiche Format wie die Beispiele über STDIN.

Es ist zu langsam, eines der Beispiele auf TIO und wahrscheinlich auch lokal auszuführen, funktioniert aber theoretisch.

Dieser macht das gleiche schneller, kann 3x3 oder 2x4 auf TIO und 4x4 und 3x5 lokal machen.

Eingerückt:

$ l
    = maximum
        [ length k-1
        \\p <- permutations
            [ (v, [x, y])
            \\y <- [0..] & u <- l
            , x <- [0..] & v <- u
            ]
        , (k, [m: n]) <- map unzip
            (subsequences p)
        | and
            [ all
                ((>) 2 o sum o map abs)
                (zipWith (zipWith (-)) n [m:n])
                :
                zipWith (>) k (tl k)
            ]
        ]
Οurous
quelle
2

Python 3 , 219 Bytes

e,m=len,enumerate
b=lambda g,x,y:[b(g,i,j)for o in[-1,1]for i,j in[(x+o,y),(x,y+o)]if e(g)>i>=0<=j<e(g[x])and g[x][y]<g[i][j]]
l=lambda t:e(t)and 1+max(map(l,t))
d=lambda g:max(l(b(g,x,y))for x,r in m(g)for y,_ in m(r))

Probieren Sie es online aus!

Das Raster wird als Liste von Listen dargestellt:

[
    [1, 2, 3, 2, 2],
    [3, 4, 5, 5, 5],
    [3, 4, 6, 7, 4],
    [3, 3, 5, 6, 2],
    [1, 1, 2, 3, 1],
]

Ursprünglicher ungolfed Code:

def potential_neighbours(x, y):
    return [(x-1, y), (x+1, y), (x, y-1), (x, y+1)]

def neighbours(grid, x, y):
    result = []
    for i, j in potential_neighbours(x, y):
        if 0 <= i < len(grid) and 0 <= j < len(grid[x]) and grid[x][y] < grid[i][j]:
            result += [(i, j)]
    return result

def build_tree(grid, x, y):
    return [build_tree(grid, i, j) for i, j in neighbours(grid, x, y)]

def longest_path_in_tree(tree):
    if len(tree) == 0:
        return 0
    return 1 + max(map(longest_path_in_tree, tree))

def longest_descent(grid):
    trees = [build_tree(grid, x, y) for x, row in enumerate(grid) for y, _ in enumerate(row)]
    return max(map(longest_path_in_tree, trees))
Nishioka
quelle
2

Haskell , 188 186 Bytes

-XNoMonomorphismRestriction

f m|c<-[0..length(m!!0)-1],r<-[0..length m-1]=h[g[(x,y)]|x<-r,y<-c,let g((x,y):p)=h[1+g(k:p)|i<-[-1,1],k@(u,v)<-[(x+i,y),(x,y+i)],u#r,v#c,m!!u!!v<m!!x!!y,not$k#p]]
(#)=elem
h=foldl max 0

Probieren Sie es online aus!

notElem(not.).(#)+4

Probieren Sie es online aus!

Erklärung & Ungolfed

Strategie: Probieren Sie rekursiv alle möglichen Pfade aus, verfolgen Sie die besuchten Einträge und maximieren Sie deren Länge.

elemnotElem(#)elemmaximize0

safeMaximum = foldl max 0

Jetzt können wir unsere rekursive Funktion definieren fun :: [[Integer]] -> Integer:

fun xs
  | c <- [0..length(m!!0)-1]             -- all possible indices of xs' columns
  , r <- [0..length m-1]                 -- all possible indices of xs' rows
  = safeMaximum                          -- maximize ..
      [ g [(x,y)]                        -- .. initially we haven't visited any others
      | x <- c, y<-r                     -- .. all possible entries
-- For the purpose of golfing we define g in the list-comprehension, it takes all visited entries (p) where (x,y) is the most recent
      , let g((x,y):p) = safeMaximum     -- maximize ..
          [ 1 + g(k:p)                   -- .. recurse, adding (x,y) to the visited nodes & increment (the next path will be 1 longer)
          | i <- [-1,1]                  -- offsets [left/up,right/down]
          , k@(u,v) <-[(x+i,y),(x,y+i)]  -- next entry-candidate
          , u#c, v#r                     -- make sure indices are in bound ..
          , m!!u!!v < m!!x!!y            -- .. , the the path is decreasing
          , not$(u,v)#p                  -- .. and we haven't already visited that element
          ]
      ]
ბიმო
quelle
Wie nimmt das Gitter? Liste der Listen?
Beefster
@Beefster: Ja, es heißt [[Integer]]Liste der Listen. Obwohl Sie in der verknüpften TIO einen Wrapper haben parse :: String -> [[Integer]], st. Sie können Zeichenfolgen verwenden, die auf Leerzeichen und neue Zeilen aufgeteilt sind.
4.
1

Python 3, 263 227 Bytes

def f(m):
 p={(x,y):[c for i in[-1,1]for c in[(x,y+i),(x+i,y)]]for x,y in m};d={c:0 for c in p if not p[c]}
 while len(p)-len(d):
  for c in p:
   for b in p[c]:
    if b in d:d[c]=max(d[b]+1,d.get(c,0))
 return max(d.values())

Probieren Sie es online aus!

-2 Bytes dank BMO

Nimmt Gitter im Format auf {(0, 0): 1, (1, 0): 2, ...}. Dieses Format kann aus dem Beispielformat mit der folgenden Dienstprogrammfunktion generiert werden:

lambda s,e=enumerate:{(x,y):int(n)for y,l in e(s.split('\n'))for x,n in e(l.split())}
wizzwizz4
quelle