Sequência de conjunto ex-crescente


11

fundo

Uma sequência de conjuntos ex-crescente da ordem é definida como uma sequência de conjuntos inteiros que satisfaz o seguinte:S 1 , S 2 , , S nNS1,S2,,Sn

  • Cada é um subconjunto não vazio de . { 1 , 2 , , N }Si{1,2,,N}
  • Para , , ou seja, quaisquer dois conjuntos consecutivos não têm elementos em comum.S iS i + 1 = 1i<nSiSi+1=
  • Para , a média (valor médio) de é estritamente menor que a de .S i S i + 11i<nSiSi+1

Desafio

Dado um número inteiro positivo N, produza o comprimento da sequência de ordem mais longa ex-crescente N.

Casos de teste

Estes são baseados nos resultados por usuário do 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

Regras

Aplicam-se as regras de padrão . O menor envio válido em bytes vence.

Recompensa

Esse problema foi discutido aqui no fórum do Project Euler há cerca de 4 anos, mas não conseguimos criar um algoritmo de tempo polinomial comprovável (em termos de N). Portanto, concederei +200 de recompensa à primeira submissão que conseguir isso ou provar sua impossibilidade.


Passei mais de uma semana tentando criar um algoritmo de tempo polinomial ou uma prova de dureza NP usando uma redução. Alguém aqui fez algum progresso nisso?
Enrico Borba

Respostas:


4

Braquilog , 28 bytes

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

Experimente online!

Isso é realmente muito lento. Demora cerca de 30 segundos por N = 3e não foi concluído após 12 minutos N = 4.

Explicação

⟦₁                             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.

Versão mais rápida, 39 bytes

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

Isso leva cerca de 50 segundos no meu computador para N = 4.

Este é o mesmo programa, exceto que classificamos o subconjunto de subconjuntos pela média em vez de fazer uma permutação aleatória. Então usamos em {⟨+/l⟩/₁/₁}ᵒvez de p.

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

Precisamos obter uma média flutuante porque acabei de descobrir um bug ridículo no qual flutuadores e números inteiros não se comparam por valor, mas por tipo com predicados de ordenação (é também por isso que eu uso <ᵈe não <₁para comparar as duas médias; o último exigiria que truque de dupla inversão para o trabalho).


Eu estava planejando trabalhar lentamente para resolver este problema (já que @ JonathanAllan mencionou isso no outro comentário), mas provavelmente estou com semanas de atraso para chegar a algo assim! Eu gosto de como (como a maioria das respostas do Brachylog), no final, parece uma clara reformulação da própria pergunta.
sundar - Restabelece Monica

@ Sundar, você sempre pode voltar mais tarde e tentar redescobrir uma solução!
Fatalize 26/07

3

CJam (81 bytes)

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

Demonstração online . Ele deve ser executado para entrada 4em um tempo razoável, mas eu não tentaria com entradas mais altas.

Dissecação

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

1

JavaScript (ES6), 175 bytes

Uma pesquisa recursiva ingênua e bastante lenta. Demora cerca de 15 segundos para calcular os 7 primeiros termos no 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

Experimente online!

ou teste esta versão modificada que gera a sequência de conjuntos mais longa e ex-crescente.

Quão?

{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()

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.