El menor número de subsecuencias monotónicas contiguas

23

Descripción del desafío

Una subsecuencia monotónica es una secuencia de números [a1, a2, ..., an]tal que

a1 <= a2 <= ... <= ano a1 >= a2 >= ... >= an. [1, 3, 3, 7, 9, 13, 13, 100]es una subsecuencia monotónica (no decreciente), así como [9, 4, 4, 3, 0, -10, -12](esta no aumenta), pero [1, 3, 6, 9, 8]no lo es. Dada una lista de enteros (en cualquier formato razonable), genera el número más pequeño de Nmodo que la secuencia de estos enteros se pueda dividir en Nsecuencias monotónicas.

Ejemplos

[1, 3, 7, 5, 4, 2] -> [[1, 3, 7], [5, 4, 2]] -> 2
[1, 2, 3, 4, 5, 6] -> [1, 2, 3, 4, 5, 6]     -> 1
[3, 1, 5, 5, 6]    -> [[3, 1], [5, 5, 6]]    -> 2
[4, 6, 8, 9, 1, 6] -> [[4, 6, 8, 9], [1, 6]] -> 2
[3, 3, 3, 3]       -> [[3, 3, 3, 3]]         -> 1
[7]                -> [[7]]                  -> 1
[]                 -> []                     -> anything (you don't actually have to handle an empty list case)
[1, 3, 2, -1, 6, 9, 10, 2, 1, -12] -> [[1, 3], [2, -1], [6, 9, 10], [2, 1, -12]] -> 4
shooqie
fuente
Para aclarar, las subsecuencias deben ser contiguas, ¿verdad?
Zgarb
@ Zgarb Sí, lo hacen.
shooqie
3
Recomiendo agregar un caso de prueba donde las secuencias no siempre van en la dirección inversa: [4,4,8,8,1,4,5] -> 2
Nathan Merrill
@NathanMerrill: Buen punto, agregó uno.
shooqie
Cuando escribes eso para una cadena vacía, el resultado es 0 / undefinedque parece que debería ser 0 o la representación undefineden nuestro idioma, pero a partir de tu comentario sobre la respuesta de Jonathan Allan Jelly, parece que undefinedsignifica anything... ¿Cuál es? ? En el segundo caso, sugeriría escribir en anythinglugar deundefined
Dada

Respuestas:

6

Brachylog , 12 bytes

~c:{<=|>=}al

Pruébalo en línea!

Esto devuelve false.para la lista vacía [].

Explicación

(?)~c                 Take a list of sublists which when concatenated result in the Input
     :{<=|>=}a        Each sublist must be either increasing or decreasing
              l(.)    Output is the length of that list

Esto devolverá el más pequeño porque ~cgenerará puntos de elección desde el número más pequeño de sublistas hasta el más grande.

Fatalizar
fuente
¿Cuál es el argumento "Z" en el enlace TIO? (Parece ser parte del programa como lo haría un argumento de línea de comando).
Jonathan Allan el
@JonathanAllan Este argumento es el resultado. Idealmente, si pudiéramos personalizar la interfaz de TIO, habría Entrada y Salida y no habría argumentos. El argumento es Zporque Zes un nombre de variable; entonces estamos diciendo "llame a este programa con la Salida como variable". Puede cambiar Za cualquier otra letra mayúscula ; Es solo un nombre variable. La razón por la que existe este argumento es para permitir la posibilidad de establecer realmente la salida en algo, en lugar de una variable.
Fatalize
(Por ejemplo, si configura la Salida 4en ese ejemplo, le dirá si eso es correcto o no )
Fatalize
1
@JonathanAllan Cualquier lenguaje similar a Prolog es así: los predicados solo pueden tener éxito o fallar y no devuelven ningún valor. Entonces, para obtener una salida, uno debe tener un argumento variable para el predicado que se unificará con el resultado.
Fatalize
1
@JonathanAllan Eventualmente fallará 3porque no encontrará ninguna lista de sublistas donde todas sean monótonas y de longitud 3. Solo lleva mucho tiempo porque probará todas las listas posibles de sublistas, incluso aquellas que en realidad tienen más de 3 elementos porque la longitud se verifica después de encontrar la lista. Porque 5dice trueporque de hecho hay al menos una lista de longitud 5con sublistas monótonas que funciona. Entonces, este programa devuelve la longitud más pequeña cuando la salida es una variable y si hay alguna lista de esa longitud que funcione si la salida es un entero.
Fatalize
4

Perl, 65 bytes

62 bytes de código + 3 bytes para la -nbandera.

monot_seq.pl:

#!perl -n
s/\S+ /($_<=>$&)*($&<=>$')-$g>=0?$g=1:$.++;$g--;$_=$&/ge,$_=$.

Dé la entrada sin nueva línea final, con los números separados por espacios:

$ echo -n "1 3 2 -1 6 9 10 2 1 -12" | perl -M5.010 monot_seq.pl
4

-5 bytes gracias a @Gabriel Benamy.

Dada
fuente
Ahorre 5 bytes convirtiéndose ($&<=>$1)*($1<=>$2)||$1==$2en($&<=>$1)*($1<=>$2)>=0
Gabriel Benamy
@GabrielBenamy De hecho, gracias.
Dada
2

Mathematica, 111 bytes

d=#[[2]]-#[[1]]&;r=Rest;f@{n_}:=1;f@k__:=If[d@k==0,f@r@k,g[k Sign@d@k]];g@{n_}:=1;g@k__:=If[d@k>0,g@r@k,1+f@r@k]

Función con nombre que ftoma una lista no vacía de números (enteros o incluso reales). Funciona de adelante hacia atrás, descarta el primer elemento repetidamente y realiza un seguimiento de cuántas subsecuencias se necesitan. Más detallado:

d = #[[2]] - #[[1]] &;         function: difference of the first two elements
r = Rest;                      function: a list with its first element dropped
f@{n_} := 1;                   f of a length-1 list equals 1
f@k__ := If[d@k == 0, f@r@k,   if the first two elements are equal, drop one
                                 element and call f again ...
            g[k Sign@d@k]];  ... otherwise call the helper function g on the
                                 list, multiplying by -1 if necessary to ensure
                                 that the list starts with an increase
g@{n_} := 1;                   g of a length-1 list equals 1
g@k__ := If[d@k > 0, g@r@k,    if the list starts with an increase, drop one
                                 element and call g again ...
            1 + f@r@k];        ... otherwise drop one element, call f on the
                                 resulting list, and add 1
Greg Martin
fuente
d=#2-#&@@#&;Además, definir cualquiera fo gcomo operador unario ±probablemente ahorrará algunos bytes.
Martin Ender
2

Jalea , 19 bytes

IṠḟ0E
ŒṖÇ€€0e$Ðḟḅ1Ṃ

TryItOnline! o ejecutar todas las pruebas (la lista vacía da como resultado1)

¿Cómo?

IṠḟ0E - Link 1, test for monotonicity: a sublist
I     - incremental differences
 Ṡ    - sign {fall:-1; same:0; rise:1}
  ḟ0  - filter out the zeros
    E - all equal?

ŒṖÇ€€0e$Ðḟḅ1Ṃ - Main link
ŒṖ            - all partitions of the input list
  Ç€€         - call last link (1) as a monad for €ach for €ach
        Ðḟ    - filter out results:
       $      -    last two links as a monad
     0e       -        contains zero?
          ḅ1  - convert from unary (vectorises)
            Ṃ - minimum

(No estoy convencido de que este sea el método más adecuado para minimizar el recuento de bytes)

Jonathan Allan
fuente
@shooqie - ¿Podemos devolver algún valor para la lista vacía dado el comentario "indefinido"? Esto vuelve 1(lo que en realidad creo que tiene más sentido que 0).
Jonathan Allan
1
Quiero decir, eso es lo que undefinedsignifica: el resultado es irrelevante.
shooqie
2

Perl, 98 97 96 79 bytes

($a,$b)=($a<=>$b)*($b<=>$c)<0?($c,shift,$d++):($b,$c)while$c=shift;say$d+1 if$a

La entrada se proporciona como una lista de números, separados por espacios, proporcionados en tiempo de ejecución, p. Ej.

perl -M5.010 monotonic.pl 1 3 2 -1 6 9 10 2 1 -12
4

(el 4 es la salida)

Legible:

($a,$b)=($a<=>$b)*($b<=>$c)<0
    ?($c,shift,$d++)
    :($b,$c)
  while$c=shift;
say$d+1
  if$a

El 'operador de nave espacial' <=>devuelve -1 si LHS <RHS, 0 si LHS = RHS y +1 si LHS> RHS. Al comparar los tres elementos secuenciales $a,$b,$cpara determinar si son monótona, sólo es necesario determinar que no es exactamente el caso de que uno de $a<=>$b, $b<=>$ces 1 y el otro es -1 - que sólo sucede cuando su producto es -1. Si bien $a==$bo $b==$c, entonces la secuencia es monotónica, y el producto es 0. Si $a < $b < $c, entonces ambos resultan en -1, y -1 * -1 = 1. Si $a > $b > $c, entonces ambos resultan en 1, y 1 * 1 = 1. En cualquier caso, la secuencia es monotónica y deseamos continuar.

Si el producto es menor que 0, sabemos que la secuencia no es monotónica, y descartamos los valores $a,$bque actualmente tenemos, e incrementamos nuestro contador de subsecuencia. De lo contrario, avanzamos un número.

No devuelve nada si la entrada está vacía; de lo contrario, devuelve el menor número de subsecuencias monotónicas contiguas.

Gabriel Benamy
fuente
No necesita un espacio entre 1y if(o tal vez lo hace en perlas antiguas, pero en las recientes no las necesita ). También puede (probablemente) reemplazar shiftpor pop. Sin embargo, hay algunos casos de prueba en los que su código no funciona: 6 3 6 3(imprime 3 en lugar de 2), 4 3 2 1(imprime 2 en lugar de 1). Usando en poplugar de shiftresolverlos, pero creando otros nuevos ( 1 2 3 4imprime 3 en lugar de 1) ...
Dada
1

C # 6, 297 209 bytes

using System.Linq;int G(int[] a)=>a.Any()?a.SkipWhile((x,i)=>i<1||x>=a[i-1]).Count()<a.SkipWhile((x,i)=>i<1||x<=a[i-1]).Count()?G(a.Select(x=>-x).ToArray()):G(a.SkipWhile((x,i)=>i<1||x<=a[i-1]).ToArray())+1:0;

Sin golfing con explicaciones

int G(int[] a)=>
    a.Any()
        ?a.SkipWhile((x,i)=>i<1||x>=a[i-1]).Count()<a.SkipWhile((x,i)=>i<1||x<=a[i-1]).Count()   // If a begins by decreasing (including whole a decreasing)...
            ?G(a.Select(x=>-x).ToArray())   // ... Then flip sign to make a begins by increasing
            :G(a.SkipWhile((x,i)=>i<1||x<=a[i-1]).ToArray())+1   // ... Else skip the increasing part, recursively find the remaining part number, then add 1
        :0;   // Return 0 if a is empty
Enlace Ng
fuente
1

JavaScript (ES6), 69 bytes

f=(d,c,b,...a)=>1/b?(d>c)*(b>c)+(d<c)*(b<c)?1+f(b,...a):f(d,b,...a):1

Toma la entrada como múltiples parámetros. Funciona comparando recursivamente los primeros tres elementos para ver si son monótonos, de ser así, elimina el elemento del medio ya que es inútil, si no, elimina los dos primeros elementos y comienza una nueva secuencia.

Neil
fuente
0

Clojure, 97 bytes

#((reduce(fn[[C i]s](let[S(conj C s)](if(or(apply <= S)(apply >= S))[S i][[s](inc i)])))[[]1]%)1)

reducerealiza un seguimiento de la subsecuencia actual y calcula cuántas veces <=y >=condiciones fallan. El último 1toma el segundo elemento del resultado (siendo el contador i).

NikoNyrh
fuente