Subseqüência aritmética mais longa

11

Dada uma seqüência finita não vazia de números inteiros, retorne uma subsequência aritmética de comprimento máximo.

Se houver vários do mesmo comprimento máximo, qualquer um deles poderá ser retornado.

Definições:

Uma sequência aritmética é uma sequência a(1),a(2),a(3),a(4),...tal que existe uma constante ctal que a(m+1)-a(m) = cpara todos m. Em outras palavras: a diferença entre dois termos subsequentes é constante.

Dada uma sequência, b(1),b(2),b(3),b(4),...uma subsequência é uma sequência b(s(1)),b(s(2)),b(s(3)),b(s(4)),...onde 1 <= s(1)e s(m) < s(m+1)para todos m. Em outras palavras: Pegue a sequência original e remova quantas entradas desejar.

Exemplos

Input                     Output
[4,1,2,3,6,5]             [1,3,5] or [1,2,3]
[5,4,2,-1,-2,-4,-4]       [5,2,-1,-4]
[1,2,1,3,1,4,1,5,1]       [1,1,1,1,1] or [1,2,3,4,5]
[1]                       [1]

Alguns casos de teste mais longos:

Length: 25
Input: [-9,0,5,15,-1,4,17,-3,20,13,15,9,0,-6,11,17,17,9,26,11,5,11,3,16,25]
Output: [15,13,11,9] or [17,13,9,5]

Length: 50
Input: [35,7,37,6,6,33,17,33,38,30,38,12,37,49,44,5,19,19,35,30,40,19,11,5,39,11,20,28,12,33,25,8,40,6,15,12,27,5,21,6,6,40,15,31,49,22,35,38,22,33]
Output: [6,6,6,6,6] or [39,33,27,21,15]

Length: 100
Input: [6,69,5,8,53,10,82,82,73,15,66,52,98,65,81,46,44,83,9,14,18,40,84,81,7,40,53,42,66,63,30,44,2,99,17,11,38,20,49,34,96,93,6,74,27,43,55,95,42,99,31,71,67,54,70,67,18,13,100,18,4,57,89,67,20,37,47,99,16,86,65,38,20,43,49,13,59,23,39,59,26,30,62,27,83,99,74,35,59,11,91,88,82,27,60,3,43,32,17,18]
Output: [6,18,30,42,54] or [8,14,20,26,32] or [46,42,38,34,30] or [83,63,43,23,3] or [14,17,20,23,26] or [7,17,27,37,47] or [71,54,37,20,3]

fundo

Tive essa idéia quando me lembrei do Teorema do Tao Verde de 2004, que afirma que a sequência de primos contém sequências aritméticas finitas de comprimento arbitrário.

flawr
fonte

Respostas:

5

Geléia , 8 bytes

ŒPIE$ÐfṪ

Experimente online! ou verifique todos os casos de teste .

Como funciona

ŒPIE$ÐfṪ  Main link. Argument: A (list of integers)

ŒP        Powerset; generate all sublists of A, sorted by length.
     Ðf   Filter the powerset by the link to the left:
    $       Combine the two atoms to the left into a monadic link.
  I           Compute all increments.
   E          Test whether they're all equal.
          This returns all arithmetic subsequences, sorted by length.
       Ṫ  Tail; extract the last sequence.
Dennis
fonte
2

Pitão, 12 11 bytes

ef!P{-VTtTy

Suíte de teste.

          y  powerset of implicit input, generate all subsequences
ef       T   find the last subsequence (sorted increasing in length) where...
       Tt      bifurcate over tail, giving [1,2,3,4,5] [2,3,4,5]
     -V        vectorize over -, giving differences of each consecutive pair
    {          dedup (remove duplicate elements)
   P           pop, resulting in [] if all differences were equal
  !            boolean not, resulting in True if all differences were equal

Obrigado a @LeakyNun por um byte!

Maçaneta da porta
fonte
2

MATL, 19 18 17 16 18 bytes

1 byte salvo (e 2 bytes adicionados de volta) graças a Luis!

"GX@XN!"@dun2<?vx@

Uma abordagem bastante ingênua, que a força bruta verifica todas as permutações ordenadas da entrada. Obviamente, isso pode demorar um pouco para seqüências mais longas. Para salvar um byte, comecei com as menores sub-sequências (comprimento = 1) e trabalhei até as seqüências maiores (comprimento = N).

Experimente Online!

Explicação

                % Impilicitly grab input array (N)
"               % For each value in this array
    G           % Explicitly grab the input
    X@          % Loop index, will be [1, 2, ... length(N)] as we iterate
    XN          % Determine all permutations of k elements (nchoosek). The output is 
                % each k-length permutation of the input as a different row. Order doesn't 
                % matter so the result is always ordered the same as the input
    !           % Take the transpose so each k-length permutation is a column
    "           % For each column
        d       % Compute the difference between successive elements
        un      % Determine the number of unique differences
        2<?     % If there are fewer than 2 unique values
            vx  % Vertically concatenate everything on the stack so far and delete it
            @   % Push the current permuatation to the stack
                % Implicit end of if statement
                % Implicit end of for loop
                % Implicit end of for loop
                % Implicitly display the stack
Suever
fonte
@LuisMendo Thanks! Eu sempre quis saber como obter a iteração do loop #.
Suever 29/05
@LuisMendo Oh boa captura, você está certo. Esse duplo difffornece uma matriz vazia que não pode ser negada.
Suever 29/05
1

Python 2, 124 115 98 97 bytes

p=[[]]
for n in input():p+=[x+[n][:2>len(x)or n-x[-1]==x[1]-x[0]]for x in p]
print max(p,key=len)

Muito lento e com muita memória. Teste em Ideone .

Versão alternativa, 98 bytes

p={()}
for n in input():p|={x+(n,)[:2>len(x)or n-x[-1]==x[1]-x[0]]for x in p}
print max(p,key=len)

Isso conclui todos os casos de teste instantaneamente. Teste em Ideone .

Dennis
fonte
1
byte ou velocidade, que é a questão
downrep_nation
0

Pyth verificação geral 8593c76, 24 de março , 10 bytes

efq-VTtT)y

Isso é exatamente o mesmo que a resposta da maçaneta da porta, exceto que em março, havia uma função de 2 bytes ( q ... )) que verificava se todos os elementos de uma lista eram iguais, o mesmo !P{que e o melhor que você pode fazer atualmente.

isaacg
fonte
0

JavaScript (ES6), 157 bytes

a=>{for(m=i=0,l=a.length;i<l;i++)for(j=i;++j<l;)for(t=n=a[k=i],c=0;k<l;k++)a[k]==t&&(t+=a[j]-n,++c>m)?q=a[m=c,p=n,j]-n:q;return a.slice(-m).map(_=>(p+=q)-q)}

Quase 20 vezes mais que a resposta da geléia ... Ungolfed:

function subsequence(a) {
    var max = 0;
    for (var i = 0; i < a.length; i++) {
        for (var j = i + 1; j < a.length; j++) {
            var target = a[i];
            var count = 0;
            for (var k = i; k < a.length; k++) {
                if (a[k] == target) {
                    count++;
                    target += a[j] - a[i];
                    if (count > max) {
                        max = count;
                        start = a[i];
                        step = a[j] - a[i];
                    }
                }
            }
        }
    }
    var result = new Array(max);
    for (var i = 0; i < max; i++) {
        result[i] = start + step * i;
    }
    return result;
}
Neil
fonte