Secuencia de set ex-creciente

11

Antecedentes

Una secuencia de conjunto ex-creciente de orden se define como una secuencia de conjuntos enteros que satisface lo siguiente:NS1,S2,,Sn

  • Cada es un subconjunto no vacío de . { 1 , 2 , , N }Si{1,2,,N}
  • Para , , es decir, dos conjuntos consecutivos no tienen elementos en común.S iS i + 1 = 1i<nSiSi+1=
  • Para , la media (valor promedio) de es estrictamente menor que la de .S i S i + 11i<nSiSi+1

Desafío

Dado un número entero positivo N, genera la longitud de la secuencia de orden de conjunto ex-creciente más larga N.

Casos de prueba

Estos se basan en los resultados del usuario de Project Euler thundre .

1 => 1 // {1}
2 => 2 // {1} {2}
3 => 3 // {1} {2} {3}
4 => 5 // {1} {2} {1,4} {3} {4}
5 => 7 // {1} {2} {1,4} {3} {2,5} {4} {5}
6 => 10 // {1} {2} {1,4} {3} {1,4,5} {2,3,6} {4} {3,6} {5} {6}
7 => 15 // {1} {2} {1,4} {3} {1,2,7} {3,4} {1,2,5,7} {4} {1,3,6,7} {4,5} {1,6,7} {5} {4,7} {6} {7}
8 => 21
9 => 29
10 => 39
11 => 49
12 => 63
13 => 79
14 => 99
15 => 121
16 => 145
17 => 171
18 => 203
19 => 237
20 => 277
21 => 321
22 => 369
23 => 419
24 => 477
25 => 537

Reglas

Se aplican reglas estándar de . El envío válido más corto en bytes gana.

Generosidad

Este problema se discutió aquí en el foro del Proyecto Euler hace aproximadamente 4 años, pero no se nos ocurrió un algoritmo de tiempo polinómico demostrable (en términos de N). Por lo tanto, otorgaré una recompensa de +200 a la primera presentación que logre esto, o probaré su imposibilidad.

Bubbler
fuente
He pasado más de una semana tratando de encontrar un algoritmo de tiempo polinómico o una prueba de dureza NP usando una reducción. ¿Alguien aquí ha progresado en esto?
Enrico Borba

Respuestas:

4

Brachylog , 28 bytes

⟦₁⊇ᶠk⊇pSs₂ᶠ{c≠&⟨+/l⟩ᵐ<ᵈ}ᵐ∧Sl

Pruébalo en línea!

Esto es realmente muy lento. Toma alrededor de 30 segundos N = 3y no se completó después de 12 minutos N = 4.

Explicación

⟦₁                             Take the range [1, …, Input]
  ⊇ᶠk                          Find all ordered subsets of that range, minus the empty set
     ⊇                         Take an ordered subset of these subsets
      pS                       Take a permutation of that subset and call it S
       Ss₂ᶠ                    Find all substrings of 2 consecutive elements in S
           {           }ᵐ      Map for each of these substrings:
            c≠                   All elements from both sets must be different
              &⟨+/l⟩ᵐ            And the average of both sets (⟨xyz⟩ is a fork like in APL)
                     <ᵈ          Must be in strictly increasing order
                         ∧Sl   If all of this succeeds, the output is the length of L.

Versión más rápida, 39 bytes.

⟦₁⊇ᶠk⊇{⟨+/l⟩/₁/₁}ᵒSs₂ᶠ{c≠&⟨+/l⟩ᵐ<₁}ᵐ∧Sl

Esto toma alrededor de 50 segundos en mi computadora N = 4.

Este es el mismo programa, excepto que clasificamos el subconjunto de subconjuntos por promedio en lugar de tomar una permutación aleatoria. Entonces usamos en {⟨+/l⟩/₁/₁}ᵒlugar de p.

{         }ᵒ     Order by:
 ⟨+/l⟩             Average (fork of sum-divide-length)
      /₁/₁         Invert the average twice; this is used to get a float average

Necesitamos obtener un promedio flotante porque acabo de descubrir un error ridículo en el que los flotantes y los enteros no se comparan por valor sino por tipo con predicados de orden (por eso también uso <ᵈy no <₁comparo ambos promedios; esto último requeriría que truco de doble inversión para trabajar).

Fatalizar
fuente
Estaba planeando trabajar lentamente para abordar este (ya que @JonathanAllan lo mencionó en el otro comentario), ¡pero probablemente me falten semanas para pensar en algo como esto! Me gusta cómo (al igual que la mayoría de las respuestas de Brachylog) al final, solo parece una clara reformulación de la pregunta en sí.
sundar - Restablecer Monica
@sundar, siempre puede volver más tarde e intentar redescubrir una solución.
Fatalize
3

CJam (81 bytes)

{YY@#(#{{2bW%ee{)*~}%}:Z~{)Z__1b\,d/\a+}%$}%{_,1>{2ew{z~~&!\~=>}%0&!}{,}?},:,:e>}

Demo en línea . Debería ejecutarse para la entrada 4en un tiempo razonable, pero no lo intentaría con entradas más altas.

Disección

{                 e# Declare a block (anonymous function)
  YY@#(#          e# There are 2^N subsets of [0, N), but the empty subset is problematic
                  e# so we calculate 2^(2^N - 1) subsets of the non-empty subsets
  {               e# Map integer to subset of non-empty subsets:
    {             e#   Define a block to map an bitset to its set indices; e.g. 9 => [0 3]
      2bW%ee      e#     Convert to base 2, reverse, and index
      {)*~}%      e#     If the bit was set, keep the index
    }:Z           e#   Assign the block to variable Z
    ~             e#   Evaluate it
    {             e#   Map those indices to non-empty subsets of [0, N):
      )Z          e#     Increment (to skip the empty set) and apply Z
      __1b\,d/    e#     Sum one copy, take length of another, divide for average
      \a+         e#     Wrap the subset and prepend its average value
    }%
    $             e#   Sort (lexicographically, so by average value)
  }%
  {               e# Filter out subsets of subsets with conflicts:
    _,1>{         e#   If the length is greater than 1
      2ew         e#     Take each consecutive pair of subsets
      {           e#     Map:
        z~        e#       Zip and expand to get [score1 score2] [subset1 subset2]
        ~&!\      e#       No element in common => 1
        ~=        e#       Different scores => 0
        >         e#       1 iff both constraints are met
      }%
      0&!         e#     1 iff no consecutive pair failed the test
    }{
      ,           e#   Otherwise filter to those of length 1
    }?
  },
  :,:e>           e# Map to size of subset and take the greatest
}
Peter Taylor
fuente
1

JavaScript (ES6), 175 bytes

Una búsqueda recursiva ingenua y bastante lenta. Toma aproximadamente 15 segundos calcular los 7 primeros términos en TIO.

n=>(a=[...Array(n)].reduce(a=>[...a,...a.map(y=>[x,...y],x=n--)],[[]]),g=(p,b=a,n)=>a.map(a=>(m=a.map(n=>s+=++k*b.includes(n)?g:n,s=k=0)&&s/k)>p&&g(m,a,-~n),r=r>n?r:n))(r=0)|r

Pruébalo en línea!

o pruebe esta versión modificada que genera la secuencia de conjuntos ex-creciente más larga.

¿Cómo?

Primero calculamos la powerset de y la almacenamos en :a{1,2,,n}a

a = [...Array(n)].reduce(a =>
  [...a, ...a.map(y => [x, ...y], x = n--)],
  [[]]
)

Parte recursiva:

g = (                         // g = recursive function taking:
  p,                          //   p = previous mean average
  b = a,                      //   b = previous set
  n                           //   n = sequence length
) =>                          //
  a.map(a =>                  // for each set a[] in a[]:
    (m = a.map(n =>           //   for each value n in a[]:
      s +=                    //     update s:
        ++k * b.includes(n) ? //       increment k; if n exists in b[]:
          g                   //         invalidate the result (string / integer --> NaN)
        :                     //       else:
          n,                  //         add n to s
      s = k = 0)              //     start with s = k = 0; end of inner map()
      && s / k                //   m = s / k = new mean average
    ) > p                     //   if it's greater than the previous one,
    && g(m, a, -~n),          //   do a recursive call with (m, a, n + 1)
    r = r > n ? r : n         //   keep track of the greatest length in r = max(r, n)
  )                           // end of outer map()
Arnauld
fuente
1

Python 3 , 205 197 184 182 bytes

f=lambda N,c=[[1]]:max([len(c)]+[f(N,c+[n])for k in range(N)for n in combinations(range(1,N+1),k+1)if not{*c[-1]}&{*n}and sum(c[-1])/len(c[-1])<sum(n)/len(n)]);from itertools import*

Pruébalo en línea!

Jonathan Frech
fuente
197 bytes usando en sumlugar de chain.from_iterable.
ovs
@ceilingcat Gracias.
Jonathan Frech