Sottosequenze sommate massime con elementi non adiacenti


23

Introduzione:

Ispirato da queste due domande SO (senza dubbio della stessa classe): stampare gli elementi nel sottoarray della somma massima senza elementi adiacenti java e la somma massima degli elementi non adiacenti di un array, da stampare .

Sfida:

Dato un elenco di numeri interi, genera una sottosequenza composta da elementi non adiacenti che hanno la somma più alta. Ecco alcuni esempi:

  • [1,2,3,-1,-3,2,5]comporterebbe [1,3,5](con una somma di 9) agli indici basati su 0 [0,2,6].
  • [4,5,4,3]si tradurrebbe in [4,4](con una somma di 8) negli indici basati su 0 [0,2]o [5,3](anche con una somma di 8) negli indici basati su 0 [1,3].
  • [5,5,10,100,10,5]comporterebbe [5,100,5](con una somma di 110) in entrambi gli indici basati su 0 [0,3,5]o [1,3,5].

La cosa più importante di questi esempi sopra, gli indici che contengono gli elementi sono almeno 2 l'uno dall'altro. Se guardiamo l'esempio [5,5,10,100,10,5]più in profondità: abbiamo la seguente sottosequenza potenziale contenente elementi non adiacenti; con i loro indici sottostanti; con le loro somme sotto che:

[[5],[10],[100],[10],[5],[5],[100,5],[10,5],[10,10],[5,5],[5,10],[5,100],[5,5],[5,10],[5,100],[5,10],[5,100,5],[5,100,5],[5,10,5],[5,10,10]]   // non-adjacent subsequences
[[5],[ 4],[  3],[ 2],[1],[0],[  3,5],[ 2,5],[ 2, 4],[1,5],[1, 4],[1,  3],[0,5],[0, 4],[0,  3],[0, 2],[1,  3,5],[0,  3,5],[0, 2,5],[0, 2, 4]]   // at these 0-based indices
[  5,  10,  100,  10,  5,  5,    105,    15,     20,   10,    15,    105,   10,    15,    105,    15,      110,      110,      20,       25]   // with these sums
                                                                                                            ^         ^                        // and these two maximums

Dal momento che le somme massime sono 110, produciamo [5,100,5]come risultato.

Regole della sfida:

  • È consentito generare coppie chiave-valore dell'indice + valore. Quindi, invece di [5,100,5]te, puoi produrre [[0,5],[3,100],[5,5]]o [[1,5],[3,100],[5,5]]come risultato (o [[1,5],[4,100],[6,5]]/ [[2,5],[4,100],[6,5]]quando viene usato l'indicizzazione in base 1 anziché in base a 0).
    • Se usi coppie chiave-valore, possono anche essere in ordine inverso o casuale, poiché è chiaro quali valori si intendono a causa dell'indice accoppiato.
    • Non è consentito fornire solo gli indici senza valori. Dovrebbe produrre i valori o i valori / indici come coppie chiave-valore (o due elenchi separati per "chiavi" e "valori" della stessa dimensione se le coppie chiave-valore non sono possibili nella lingua scelta).
  • Hai il permesso di produrre tutte le sottosequenze possibili con la somma massima invece di una sola.
  • Come puoi vedere dagli esempi, l'elenco di input può contenere anche valori negativi e duplicati. Puoi supporre che gli interi di input siano compresi nell'intervallo [999,999] .
  • L'elenco di output non può essere vuoto e deve sempre contenere almeno un elemento (se un elenco contiene solo valori negativi, un elenco contenente il singolo valore negativo più basso verrà quindi emesso come risultato - vedere gli ultimi due casi di test).
  • Se esiste un output possibile ma per più indici diversi, è consentito output entrambi anche se potrebbero sembrare duplicati. (vale a dire l'esempio sopra, può essere generato [[5,100,5],[5,100,5]]per entrambe le possibili combinazioni di indici).

Casi test:

Input:                   Possible outputs:       At 0-based indices:     With sum:

[1,2,3,-1,-3,2,5]        [1,3,5]                 [0,2,6]                 9
[4,5,4,3]                [4,4]/[5,3]             [0,2]/[1,3]             8
[5,5,10,100,10,5]        [5,100,5]               [0,3,5]/[1,3,5]         110
[10]                     [10]                    [0]                     10
[1,1,1]                  [1,1]                   [0,2]                   2
[-3,7,4,-2,4]            [7,4]                   [1,4]                   11
[1,7,4,-2]               [7]                     [1]                     7
[1,2,-3,-4,5,6,-7]       [2,6]                   [1,5]                   8
[800,-31,0,0,421,726]    [800,726]/[800,0,726]   [0,5]/[0,3,5]/[0,2,5]   1526
[-1,7,8,-5,40,40]        [8,40]                  [2,4]/[2,5]             48
[-5,-18,-3,-1,-10]       [-1]                    [3]                     -1
[0,-3,-41,0,-99,-2,0]    [0]/[0,0]/[0,0,0]       [0]/[3]/[6]/[0,3]/
                                                  [0,6],[3,6]/[0,3,6]    0

Se esiste più di un set identico (ma di indici diversi) è corretto elencarli tutti? ad esempio [5,100,5]due volte per il tuo terzo esempio.
Nick Kennedy,

1
powersetè un insieme di sottoinsiemi vero? ma sembra che tu stia restituendo una serie di sottosequenze? [4,5,4,3] si tradurrebbe in [4,4] in cui [4,4] non è chiaramente un insieme.
Dati scaduti il

1
@Arnauld Sì, se i valori sono coppie chiave-valore con il loro indice, è chiaro quali valori indicizzati sono intesi nell'input, quindi possono essere in qualsiasi ordine. Lo modificherà anche nella descrizione della sfida.
Kevin Cruijssen,

2
Giusto per essere sicuri: l'output degli indici non è un'opzione, vero?
Shaggy,

1
Il termine classico è "sottosequenza" . Questo ha lo stesso problema delle persone che pensano a sottosequenze contigue. Direi "sottoinsieme" se in realtà stessimo lavorando con i set qui, ma queste sono sicuramente sequenze: sono consentiti argomenti di ordine e duplicati.
user2357112 supporta Monica il

Risposte:


6

Buccia , 11 byte

►Σ†!¹mü≈tṖŀ

Provalo online!

Spiegazione

►Σ†!¹mü≈tṖŀ  Implicit input, say L=[4,5,3,4].
          ŀ  Indices: [1,2,3,4]
         Ṗ   Powerset: [[],[1],[2],[1,2],..,[1,2,3,4]]
        t    Tail (remove the empty list): [[1],[2],[1,2],..,[1,2,3,4]]
     m       For each,
      ü      de-duplicate by
       ≈     differing by at most 1.
             For example, [1,2,4] becomes [1,4].
  †          Deep map
   !¹        indexing into L: [[4],[5],[4],..,[5,4],[4,3]]
►            Maximum by
 Σ           sum: [5,4]

6

Haskell , 60 byte

snd.([]%)
r%(h:t)=max(r%t)$(r++[h])%drop 1t
r%_=(sum r<$r,r)

Provalo online!

La funzione di supporto si %dirama ricorsivamente sulla scelta se includere il primo elemento e rilasciare il secondo o saltare il primo elemento. Prende il massimo di tutti i risultati, che sono tuple il cui primo elemento è la somma e il cui secondo elemento è l'elenco corrispondente che viene estratto per l'output.

Per gestire la regola secondo cui l'elenco vuoto è vietato anche se avrebbe il trucco più piccolo, facciamo un trucco carino di scrittura sum r<$rpiuttosto che sum r. Questo crea un elenco i cui elementi sono tutti sum re la cui lunghezza è quella di r. In questo modo, quando scegliamo il massimo, diamo la priorità a qualsiasi elenco rispetto a un vuoto r, ma altrimenti i confronti dipendono dal primo elemento che è sum r.


6

R , 136 125 byte

function(l,G=unlist(Map(combn,list(y<-seq(a=l)),y,c(function(x)'if'(all(diff(x)>1),l[x],-Inf)),F),F))G[which.max(Map(sum,G))]

Provalo online!

-6 byte grazie a digEmAll , che per inciso mi ha anche superato .

Restituisce la sottosequenza più breve come a list, rompendo i legami lessicografici per primi dagli indici.

La forza bruta genera tutte le sottosequenze dell'indice, quindi Filters per quelle non adiacenti, ovvero dove all(diff(x)>1). Poi sottoinsiemi [in lusando questi indici, selezionando [[la prima in cui la somma è il massimo ( which.max).

Sono abbastanza sicuro che questa sia la prima risposta R che abbia mai scritto che usi Filter! triste, Filterè ungolfy, non c'è da stupirsi che non l'ho mai usato ...



@digEmAll grazie!
Giuseppe,

5

05AB1E , 14 byte

Salvato 1 byte grazie a Kevin Cruijssen

ā<æʒĆ¥≠W}èΣO}θ

Provalo online! o come una suite di test

Spiegazione

ā<               # push [0 ... len(input)-1]
  æ              # compute powerset
   ʒ    }        # filter, keep lists where:
      ≠W         # no element is 1 in the
     ¥           # deltas
    Ć            # of the list with the head appended
         è       # index into the input with each
          ΣO}    # sort by sum
             θ   # take the last element

Potresti non essere felice, ma è ancora più corto di 4 byte rispetto alla mia soluzione iniziale. ;) E puoi giocare a golf 1 in più cambiando ¤ªa Ć.
Kevin Cruijssen,

@KevinCruijssen: Oh yeah! Per qualche ragione mi ero convinto di aver bisogno di un elemento ripetitivo alla fine. Grazie!
Emigna,

5

Brachylog (v2), 14 byte

{~ba~c∋₁ᵐ}ᶠ+ᵒt

Provalo online!

Invio di funzioni; input da sinistra, output da destra, come al solito. Molto lento; un elenco di cinque elementi è probabilmente il massimo per i test su TIO.

{~ba~c∋₁ᵐ}ᶠ+ᵒt
 ~b              Prepend an arbitrary element to the input
   a             Take a prefix or suffix of the resulting list
    ~c           Ordered partition into contiguous sublists
      ∋₁         Take the second element
        ᵐ          of each sublist
{        }ᶠ      Find all possible ways to do this
           +ᵒ    Sort by sum
             t   Take the greatest

I risultati che otteniamo dai prefissi non sono errati, ma non sono interessanti; tutti i possibili risultati sono generati prendendo un suffisso (che è probabilmente l'elenco stesso, ma non può essere vuoto), ma "suffisso" è più dettagliato in Brachylog che "prefisso o suffisso", quindi sono andato con la versione più terser (e meno efficiente ma ancora corretto). L'idea di base è che per ogni elemento desiderato nell'elenco di output, la partizione in elenchi secondari contigui deve posizionare l'elemento e l'elemento prima nello stesso elenco secondario (poiché l'elemento è il secondoelemento dell'elenco secondario), pertanto nel risultato non possono essere visualizzati due elementi consecutivi. D'altra parte, è abbastanza chiaro che qualsiasi risultato senza due elementi consecutivi può apparire nel risultato. Quindi, una volta che abbiamo tutte le possibili liste dei candidati, possiamo semplicemente prendere le somme di tutte e vedere quale è la più grande.



3

JavaScript (ES6),  138 132 130 129  126 byte

Emette coppie chiave-valore.

a=>a.reduce((a,x,i)=>[...a,...a.map(y=>[[x,i],...y])],[[]]).map(m=a=>a.some(s=p=([v,i])=>p-(s=~~s+v,p=i)<2)|s<m||(r=a,m=s))&&r

Provalo online!

Passo 1

Per prima cosa calcoliamo il powerset dell'input con [vun'lue,iondeX] accoppiamenti.

a.reduce((a, x, i) => // for each value x at position i:
  [                   //   update a[] to a new array consisting of:
    ...a,             //     all previous entries
    ...a.map(y =>     //     for each value y in a[]:
      [[x, i], ...y]  //       append [x, i], followed by all original entries
    )                 //     end of map()
  ],                  //   end of new array
  [[]]                //   start with a = [[]]
)                     // end of reduce()

Passo 2

Quindi cerchiamo la somma massima mtra questi insiemi, scartando insiemi con almeno due elementi adiacenti. Viene memorizzato il set migliorer.

.map(m =              // initialize m to a non-numeric value
  a =>                // for each entry a[] in the powerset:
  a.some(s = p =      //   initialize s and p to non numeric values
    ([v, i]) =>       //   for each value v and each index i in a[]:
    p - (             //     compute p - i
      s = ~~s + v,    //     add v to s
      p = i           //     update p to i
    ) < 2             //     if p - i is less than 2, yield true
  ) |                 //   end of some()
  s < m ||            //   unless some() was truthy or s is less than m,
  (r = a, m = s)      //   save a[] in r[] and update m to s
) && r                // end of map(); return r[]

3

Haskell, 81 80 byte

snd.maximum.map((,)=<<sum).tail.f
f(a:b:c)=f(b:c)++map(a:)(f c)
f a=[]:map(:[])a

Provalo online!

fcrea tutte le sottosequenze valide saltando l'elemento successivo ( f(b:c)) o utilizzandolo e saltando il successivo ( map(a:)(f c)) e ricorsivamente lavorando sul resto. Per il risultato, crea tutte le sottosequenze ( f), elimina la sottosequenza vuota (che si verifica per prima nell'elenco:) tail, crea coppie (<sum>,<subsequence>)(map((,)=<<sum) ), trova il massimo (le coppie vengono confrontate in ordine lessicografico) -> maximum) e rilascia la somma ( snd).

Modifica: -1 byte grazie a @Lynn.


1
map(:[])aè un byte più corto di (pure<$>a)^^
Lynn il


3

T-SQL, 122 119 118 byte

L'input è una variabile di tabella.

Questa query seleziona tutti gli elementi dalla variabile della tabella, combinandoli con tutti gli elementi non adiacenti con valori di posizione più alti e mostra il testo generato per la somma più alta di questi valori.

WITH C(y,j,v)as(SELECT*,x*1FROM @
UNION ALL
SELECT y+','+x,i,v+x
FROM @ JOIN C ON~-i>j)SELECT
TOP 1y FROM C ORDER BY-v

Provalo online senza licenza



2

Pyth, 19 byte

esDm@LQdtf!q#1.+TyU

Provalo online qui o verifica tutti i casi di test contemporaneamente qui .

esDm@LQdtf!q#1.+TyUQ   Implicit: Q=eval(input())
                       Trailing Q inferred
                  UQ   Generate range [0-len(Q))
                 y     Take the powerset of the above
         f             Filter keep elements of the above, as T, using:
              .+T        Take differences of consecutive elements of T
           q#1           Keep those differences equal to 1
          !              Logical NOT - empty lists evaluate to true, populated ones to false
                       Result of the filter is those sets without consecutive numbers
        t              Drop the first element (empty set)
   m                   Map the remaining sets, as d, using:
     L d                 For each element of d...
    @ Q                  ... get the element in Q with that index
 sD                    Order the sets by their sum
e                      Take the last element, implicit print

2

Gaia , 24 byte

e:w;ċz⟨ọ1>¦ẏ⟩⁇‼⁇E‡ev2%Σ⌠

Provalo online!

Uffa, E‡fa delle cose strane ... secondo la documentazione dovrebbe fare qualcosa del tipo " iset di elenchi di Xlunghezza e jset di indici di lunghezza Y, ritorno X[i][Y[j]]", ma restituisce invece [X[i][Y[j]] X[i][Y[-j]]dove l'indicizzazione negativa rappresenta il complemento, quindi dobbiamo fare ev2%per estrarre solo quelli che vogliamo.

e				| eval as a list l
 :				| dup
  w				| wrap as a list
   ;				| push l again
    ċ				| push [1..len(l)]
     z				| push all subsets of [1..len(l)] -- index powerset.
      ⟨      ⟩⁇			| filter this for:
       ọ			| deltas
        1>¦			| are greater than 1
           ẏ			| all (all deltas greater than 1)
	       ‼⁇		| filter for non-empty lists
		 E‡		| table extract elements. Given l and index set i, this pushes
				| [l[i] l[setdiff(1..l,i)]] for some reason
		   ev2%		| get the l[i] only by unlisting, reversing, and taking every other element
		       Σ⌠	| Get the one with the maximum sum

Per curiosità, perché l'output ha due finali ]]anziché uno?
Kevin Cruijssen,

@KevinCruijssen Solo un'altra stranezza divertente dell'interprete; tutti gli elenchi vengono stampati in questo modo, quindi [[1] [2]]viene stampato, il [[1]] [2]]]]che rende estremamente difficile la lettura / il debug dell'output dell'elenco.
Giuseppe,

Penso che sia a causa dell'espressione re.sub(" ?$","]",result)nell'interprete che dovrebbe essere invece, re.sub(" +$","]",result)ma il mio pitone è super cattivo.
Giuseppe,

2

R , 108 107 byte

function(v,M=-Inf){for(j in J<-seq(a=v))for(i in combn(J,j,,F))if(all(diff(i)>1)&sum(v[i])>sum(M))M=v[i]
M}

Provalo online!

-1 grazie a @Giuseppe


2

Wolfram Language (Mathematica) , 70 63 byte

MaximalBy[Select[q=Rest@Subsets@#,!FreeQ[q,#~Riffle~_]&],Tr,1]&

Provalo online!

Ricerca di alto livello

          Select[q=Rest@Subsets@#,                     ]        (*choose nonempty subsets of the input such that*)
                                  !FreeQ[q,          ]&         (*there exists a subset of the input which matches*)
                                           #~Riffle~_           (*this list, with an item inserted between adjacent elements*)
MaximalBy[                                              ,Tr,1]& (*and return one with the greatest total*)

,1è necessario per non restituire inavvertitamente set non validi (altrimenti, ad esempio, un input di {1,1,1}provocherebbe un output di {{1,1},{1,1},{1,1}})


1

Haskell , 300 168 byte

import Data.List
h[]=1>2
h(x:y)=fst$foldl(\a c->((fst a)&&(c-snd a>1),c))(1<2,x)y
z=snd.last.sortOn fst.map((,)=<<sum.snd).filter(h.fst).map unzip.subsequences.zip[0..]

Provalo online!

-132 byte grazie a tutti i feedback di @nimi :)


Originale

Ungolfed (originale)

import Data.List
import Data.Function

f :: [Int] -> [(Int, Int)] -- attach indices for later use
f [] = []
f xs = zip xs [0..length xs]

g :: [[(Int, Int)]] -> [([Int], [Int])] -- rearrange into list of tuples
g [] = []
g (x:xs) = (map fst x, map snd x) : g xs

h :: [Int] -> Bool -- predicate that checks if the indices are at least 2 apart from each other
h [] = False
h (x:xs) = fst $ foldl (\acc curr -> ((fst acc) && (curr - snd acc > 1), curr)) (True, x) xs
j :: [([Int], [Int])] -> [([Int], [Int])] -- remove sets that don't satisfy the condition
j xs = filter (\(elements, indices) -> h indices) xs

k :: [([Int], [Int])] -> [(Int, ([Int], [Int]))] -- calculate some of elements
k xs = map (\(elements, indices) -> (foldl1 (+) elements, (elements, indices))) xs

l :: [(Int, ([Int], [Int]))] -> ([Int], [Int]) -- grab max
l xs = snd $ last $ sortBy (compare `on` fst) xs

z -- put things together
```

1
Alcuni consigli: capovolgere l'elemento e l'indice entro le coppie restituite da f: f x=zip[0..length x]xcosì fdiventa f=zip[0..]. gè giusto g=map unzip. La funzione da filtrare con in jè h.fst(<- coppie capovolte!). j=filter(h.fst). Il foldl1+da kè sume con una creazione di coppie inutili k=map((,)=<<sum.snd). sortBy(...)può essere sostituito da sortOn fst: l=snd.last.sortOn fst. Infine, come si è utilizzare tutte le funzioni di una sola volta, è possibile InLine in una singola espressione pointfree:z=snd.last.sortOn fst.map((,)=<<sum.snd).filter(h.fst).map unzip.subsequences.zip[0..]
Nome del modello


oh, e non è più necessario importare Data.Function.
nimi,

È fantastico, grazie per il feedback :)
bug

Successivamente h: stiamo cercando elementi non adiacenti, ovvero la differenza degli indici adiacenti deve essere >1. zipWith(-)=<<tailcostruisce un simile elenco delle differenze, ma non riesce per la lista vuota, quindi abbiamo bisogno di un ulteriore tailsul subsequencesper sbarazzarsi di esso. In linea di nuovo. Provalo online!
nimi,

1

Carbone , 46 byte

≔⟦υ⟧ηFθ«≔υζ≔Eη⁺κ⟦ι⟧υ≔⁺ζηη»≔Φ⁺υηιη≔EηΣιζI§η⌕ζ⌈ζ

Provalo online! Il collegamento è alla versione dettagliata del codice. Spiegazione:

≔⟦υ⟧η

La variabile uè predefinita con un elenco vuoto. Questo viene inserito in un elenco a cui è assegnato h. Queste variabili fungono da accumulatori. ucontiene le liste secondarie che includono l'ultimo elemento dell'input qmentre hcontiene le liste secondarie che non lo fanno (e quindi sono adatte per aggiungere il prossimo elemento dell'input).

Fθ«

Passa sopra gli elementi dell'input.

≔υζ

Salvare l'elenco di elenchi secondari che contengono l'elemento precedente.

≔Eη⁺κ⟦ι⟧υ

Prendi tutti gli elenchi secondari che non contengono l'elemento precedente, aggiungi l'elemento corrente e salva il risultato come elenco di elenchi secondari che contengono l'elemento corrente. (Non utilizzo Pushqui perché devo clonare l'elenco.)

≔⁺ζηη»

Concatena entrambi i precedenti elenchi nel nuovo elenco di elenchi che non contengono l'elemento corrente.

≔Φ⁺υηιη

Concatenare le liste secondarie un'ultima volta e rimuovere l'elenco vuoto originale (che comunque Carbone non può sommare).

≔EηΣιζ

Calcola le somme di tutte le liste secondarie.

I§η⌕ζ⌈ζ

Trova un indice della somma maggiore e genera l'elenco secondario corrispondente.



1

Japt -h , 21 byte

Hai mai avuto una di quelle sfide in cui hai completamente dimenticato come giocare a golf ?!

ð¤à fÊk_än ø1îmgUÃñx

Provalo

ð¤à fÊk_än ø1îmgUÃñx     :Implicit input of array U
ð                         :Indices of elements that return true when
 ¤                        :  Converted to a base-2 string (to account for 0s)
  à                       :Combinations
    f                     :Filter by
     Ê                    :  Length (to remove the empty combination)
      k_                  :Remove elements that return true
        än                :  Deltas
           ø1             :  Contains 1
             Ã            :End remove
              ®           :Map
               m          :  Map
                gU        :    Index into U
                  Ã       :End map
                   ñ      :Sort by
                    x     :  Sum
                          :Implicit output of last element

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.