Menor número de subsequências monotônicas contíguas

23

Descrição do Desafio

Uma subsequência monotônica é uma sequência de números [a1, a2, ..., an]tal que

a1 <= a2 <= ... <= anou a1 >= a2 >= ... >= an. [1, 3, 3, 7, 9, 13, 13, 100]é uma subsequência monotônica (não decrescente), bem como [9, 4, 4, 3, 0, -10, -12](esta não é crescente), mas [1, 3, 6, 9, 8]não é. Dada uma lista de números inteiros (em qualquer formato razoável), imprima o menor número, de Nmodo que a sequência desses números inteiros possa ser dividida em Nsequências monotônicas.

Exemplos

[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
fonte
Para esclarecer, as subsequências devem ser contíguas, certo?
Zgarb
@ Zgarb Sim, eles fazem.
shooqie
3
Eu recomendo adicionar um caso de teste em que as seqüências nem sempre sigam na direção inversa: # [4,4,8,8,1,4,5] -> 2
Nathan Merrill
@ NathanMerrill: Bom ponto, acrescentou um.
shooqie
Quando você escreve isso para uma sequência vazia, o resultado é 0 / undefinedque parece que deve ser 0 ou a representação de undefinednossa língua, mas, a partir do seu comentário na resposta de Jonathan Allan Jelly, parece que undefinedsignifica anything... Qual é essa? ? No segundo caso, eu sugeriria escrever em anythingvez deundefined
Dada

Respostas:

6

Braquilog , 12 bytes

~c:{<=|>=}al

Experimente online!

Isso retorna false.para a lista vazia [].

Explicação

(?)~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

Isso retornará o menor porque ~cgerará pontos de escolha do menor número de sublistas para o maior.

Fatalizar
fonte
Qual é o argumento "Z" no link do TIO? (Parece fazer parte do programa como faria um argumento da linha de comando).
Jonathan Allan
@ JonathanAllan Este argumento é a saída. Idealmente, se pudéssemos personalizar a interface do TIO, haveria a Entrada e a Saída e nenhum argumento. O argumento é Zporque Zé um nome de variável; então estamos dizendo "chame esse programa com a saída como uma variável". Você pode mudar Zpara qualquer outra letra maiúscula ; é apenas um nome de variável. A razão pela qual esse argumento existe é permitir a possibilidade de realmente definir a saída para algo, em vez de uma variável.
Fatalize
(Por exemplo, se você definir a Saída como 4nesse exemplo, ele informará se isso está correto ou não ) #
Fatalize
1
@ JonathanAllan Qualquer linguagem semelhante ao Prolog é assim: os predicados só podem ter sucesso ou falhar e não retornam nenhum valor. Portanto, para obter uma saída, é necessário ter um argumento variável para o predicado que será unificado ao resultado.
Fatalize
1
@ JonathanAllan Acabará por falhar 3porque não encontrará nenhuma lista de sublistas onde todas são monotônicas e de comprimento 3. Leva apenas um longo tempo, porque tentará todas as listas possíveis de sublistas, mesmo aquelas com mais de três elementos, porque o comprimento é verificado depois de encontrar a lista. Pois 5diz trueporque de fato há pelo menos uma lista de comprimento 5com sublistas monotônicas que funciona. Portanto, este programa retorna o menor comprimento quando a saída é uma variável e se existe alguma lista desse comprimento que funcione se a saída for um número inteiro.
Fatalize
4

Perl, 65 bytes

62 bytes de código + 3 bytes para -nsinalizador.

monot_seq.pl:

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

Forneça a entrada sem nova linha final, com os números separados por espaços:

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

-5 bytes graças a @Gabriel Benamy.

dada
fonte
Economize 5 bytes se transformando ($&<=>$1)*($1<=>$2)||$1==$2em($&<=>$1)*($1<=>$2)>=0
Gabriel Benamy 15/11
@GabrielBenamy De fato, obrigado.
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]

Função nomeada fque obtém uma lista não vazia de números (números inteiros ou mesmo reais). Funciona de frente para trás, descartando o primeiro elemento repetidamente e acompanhando quantas subseqüências são necessárias. Mais detalhado:

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
fonte
d=#2-#&@@#&;Além disso, definir um fou gcomo operador unário ±provavelmente salvará alguns bytes.
Martin Ender
2

Geléia , 19 bytes

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

TryItOnline! ou executar todos os testes (a lista vazia resulta em1)

Quão?

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 entanto, não estou convencido de que este seja o método mais adequado para minimizar a contagem de bytes.

Jonathan Allan
fonte
@shooqie - Podemos retornar algum valor para a lista vazia, dado o comentário "indefinido"? Isso retorna 1(o que realmente acho que faz mais sentido do que 0).
Jonathan Allan
1
Quero dizer, é isso que undefinedsignifica - o resultado é 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

A entrada é fornecida como uma lista de números, separados por espaços, fornecidos em tempo de execução, por exemplo

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

(o 4 é a saída)

Legível:

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

O 'operador de nave espacial' <=>retorna -1 se LHS <RHS, 0 se LHS = RHS e +1 se LHS> RHS. Ao comparar três elementos sequenciais $a,$b,$cpara determinar se são monotônicos, é necessário apenas determinar que esse não é exatamente um de $a<=>$b, $b<=>$cé 1 e o outro é -1 - o que só acontece quando o produto é -1. Se um $a==$bou $b==$c, então, a sequência é monotônica e o produto é 0. Se $a < $b < $c, então ambos resultam em -1 e -1 * -1 = 1. Se $a > $b > $c, então ambos resultam em 1 e 1 * 1 = 1. Nos dois casos, a sequência é monotônica e queremos continuar.

Se o produto for menor que 0, sabemos que a sequência não é monotônica, descartamos os valores $a,$bque estamos mantendo no momento e aumentamos nosso contador de subsequências. Caso contrário, avançamos um número.

Não retorna nada se a entrada estiver vazia; caso contrário, retorna o menor número de subsequências monotônicas contíguas

Gabriel Benamy
fonte
Você não precisa de um espaço entre 1e if(ou talvez precise de perls antigos, mas nos mais recentes não precisa ). Além disso, você pode (provavelmente) substituir shiftpor pop. No entanto, existem alguns casos de teste nos quais seu código não funciona: 6 3 6 3(você imprime 3 em vez de 2), 4 3 2 1(você imprime 2 em vez de 1). Usando popvez de shiftresolver aqueles, mas criar novas ( 1 2 3 4imprime 3 em vez 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;

Ungolfed com explicações

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
Ng do link
fonte
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

Recebe entrada como vários parâmetros. Funciona comparando recursivamente os três primeiros elementos para verificar se são monotônicos; nesse caso, remove o elemento do meio, pois é inútil; caso contrário, remove os dois primeiros elementos e inicia uma nova sequência.

Neil
fonte
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)

reducecontrola a subsequência atual e calcula quantas vezes <=e as >=condições falham. Last 1pega o segundo elemento do resultado (sendo o contador i).

NikoNyrh
fonte