Sequenza set crescente


11

sfondo

Una sequenza di insiemi di ordine crescente è definita come una sequenza di insiemi interi che soddisfa quanto segue:S 1 , S 2 , , S nNS1,S2,,Sn

  • Ogni è un sottoinsieme non vuoto di . { 1 , 2 , , N }Si{1,2,,N}
  • Per , , ovvero due insiemi consecutivi non hanno elementi in comune.S iS i + 1 = 1i<nSiSi+1=
  • Per , la media (valore medio) di è strettamente inferiore a quella di .S i S i + 11i<nSiSi+1

Sfida

Dato un numero intero positivo N, emette la lunghezza della sequenza d'ordine impostata crescente crescente più lunga N.

Casi test

Questi sono basati sui risultati dell'utente thundre di Project Euler .

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

Regole

Si applicano le regole standard del . Vince l'invio valido più breve in byte.

generosità

Questo problema è stato discusso qui sul forum di Project Euler circa 4 anni fa, ma non siamo riusciti a trovare un algoritmo di tempo polinomiale dimostrabile (in termini di N). Pertanto, assegnerò +200 ricompensa alla prima presentazione che raggiunge questo obiettivo, o dimostrerò la sua impossibilità.


Ho trascorso più di una settimana cercando di elaborare un algoritmo a tempo polinomiale o una prova di durezza NP usando una riduzione. Qualcuno qui ha fatto progressi su questo?
Enrico Borba,

Risposte:


4

Brachylog , 28 byte

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

Provalo online!

Questo è davvero dannatamente lento. Dura circa 30 secondi N = 3e non è stato completato dopo 12 minuti N = 4.

Spiegazione

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

Versione più veloce, 39 byte

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

Questo richiede circa 50 secondi sul mio computer per N = 4.

Questo è lo stesso programma, tranne per il fatto che ordiniamo il sottoinsieme di sottoinsiemi in media invece di prendere una permutazione casuale. Quindi usiamo {⟨+/l⟩/₁/₁}ᵒinvece di p.

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

Dobbiamo ottenere una media float perché ho appena scoperto un bug ridicolo in cui float e numeri interi non si confrontano per valore ma per tipo con i predicati di ordinazione (questo è anche il motivo per cui utilizzo <ᵈe non <₁confrontare entrambe le medie; quest'ultima richiederebbe che doppio trucco di inversione per funzionare).


Stavo pianificando di andare lentamente avanti per affrontare questo (dal momento che @JonathanAllan lo ha menzionato nell'altro commento), ma sono probabilmente settimane indietro a trovare qualcosa del genere! Mi piace come (come la maggior parte delle risposte di Brachylog) alla fine sembra solo una rielaborazione ordinata della domanda stessa.
Sundar - Ripristina Monica il

@sundar puoi sempre tornarci più tardi e provare a riscoprire una soluzione!
Fatalizza il

3

CJam (81 byte)

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

Demo online . Dovrebbe essere eseguito per l'input 4in un tempo ragionevole, ma non lo proverei con input più alti.

Dissezione

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

Una ricerca ricorsiva ingenua e piuttosto lenta. Impiega circa 15 secondi per calcolare i 7 primi termini su 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

Provalo online!

oppure prova questa versione modificata che genera la sequenza di set crescente crescente più lunga.

Come?

Per prima cosa calcoliamo il powerset di e lo memorizziamo in :a{1,2,,n}a

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

Parte ricorsiva:

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

1

Python 3 , 205 197 184 182 byte

  • Risparmiato otto ventuno byte grazie a ovs .
  • Salvato due byte grazie a ceilingcat .
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*

Provalo online!


197 byte usando suminvece di chain.from_iterable.
Ovs

@ceilingcat Grazie.
Jonathan Frech,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.