La subsecuencia aritmética más larga


11

Dada una secuencia finita no vacía de enteros, devuelve una subsecuencia aritmética de longitud máxima.

Si hay múltiples de la misma longitud máxima, cualquiera de ellos puede ser devuelto.

Definiciones:

Una secuencia aritmética es una secuencia a(1),a(2),a(3),a(4),...tal que hay una constante ctal que a(m+1)-a(m) = cpara todos m. En otras palabras: la diferencia entre dos términos posteriores es constante.

Dada una secuencia, b(1),b(2),b(3),b(4),...una subsecuencia es una secuencia b(s(1)),b(s(2)),b(s(3)),b(s(4)),...donde 1 <= s(1)y s(m) < s(m+1)para todos m. En otras palabras: tome la secuencia original y elimine tantas entradas como desee.

Ejemplos

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]

Algunos casos de prueba más largos:

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]

Antecedentes

Se me ocurrió esta idea cuando recordé el Teorema del Tao Verde de 2004, que establece que la secuencia de números primos contiene secuencias aritméticas finitas de longitud arbitraria.

Respuestas:


5

Jalea , 8 bytes

ŒPIE$ÐfṪ

Pruébalo en línea! o verificar todos los casos de prueba .

Cómo 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.

2

Pyth, 12 11 bytes

ef!P{-VTtTy

Banco de pruebas.

          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

¡Gracias a @LeakyNun por un byte!


2

MATL, 19 18 17 16 18 bytes

¡1 byte guardado (y 2 bytes agregados nuevamente) gracias a Luis!

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

Un enfoque bastante ingenuo en el que la fuerza bruta verifica todas las permutaciones ordenadas de la entrada. Obviamente, esto puede tomar un tiempo para secuencias más largas. Para guardar un byte, comencé con las subsecuencias más pequeñas (longitud = 1) y trabajé hasta las secuencias más grandes (longitud = N).

Pruébalo en línea!

Explicación

                % 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

@LuisMendo ¡Gracias! Siempre me pregunté cómo obtener la iteración del bucle #.
Suever

@LuisMendo Oh, buena captura, tienes razón. Ese doble diffda una matriz vacía que no se puede negar.
Suever

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)

Muy lento e intensivo en memoria. Pruébelo en Ideone .

Versión 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)

Esto completa todos los casos de prueba al instante. Pruébelo en Ideone .


1
byte o velocidad, esa es la pregunta
downrep_nation

0

Pyth checkout 8593c76, 24 de marzo , 10 bytes

efq-VTtT)y

Esto es exactamente lo mismo que la respuesta de Doorknob, excepto que en marzo, había una función de 2 bytes ( q ... )) que verificaba si todos los elementos de una lista eran iguales, lo !P{que es lo mejor que puedes hacer actualmente.


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)}

Casi 20 veces más que la respuesta de Jelly ... 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;
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.