Toon posts:

Algoritme voor samenvoegen positieve en negatieve integers?

Pagina: 1
Acties:

Vraag


Acties:
  • +1 Henk 'm!

Verwijderd

Topicstarter
Ik heb een hele lange lijst met (miljarden) integers (32-bit signed) met omstebeurt een positief getal en dan een negatief getal, bijvoorbeeld:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
10
-2
10
-1
12
-59
40
-2
1
-2
34
-10
10


Wat is nu nodig heb is een algoritme om deze nummers zo veel mogelijk samen te voegen om zo groot mogelijk positieve nummers te krijgen, dus in dit voorbeeld wil ik de volgende output genereren:

code:
1
2
3
4
5
29
-59
71
-10
10


Is dit een veelvoorkomend probleem waar misschien standaard algoritmes voor bestaan? Of heeft iemand tips hoe ik dit het beste kan aanpakken om de beste performance te realiseren?

Beste antwoord (via Verwijderd op 23-08-2017 18:53)


  • Henk007
  • Registratie: December 2003
  • Laatst online: 06-04 00:29
Volgens mij komt dit in de buurt:
Wiki maximum subarray problem

(Op een of andere manier lukt copy past niet in deze browser)
Het daarin genoemde algoritme is O(n)
Lees ook het wiki artikel: Subset sum problem

[ Voor 25% gewijzigd door Henk007 op 22-08-2017 17:34 ]

Alle reacties


Acties:
  • 0 Henk 'm!

  • armageddon_2k1
  • Registratie: September 2001
  • Laatst online: 27-07 10:18
Ik snap je voorbeeld niet helemaal, moet het geen: 29, -59, 81, -10, 10 zijn?

Engineering is like Tetris. Succes disappears and errors accumulate.


Acties:
  • +1 Henk 'm!

  • Henk007
  • Registratie: December 2003
  • Laatst online: 06-04 00:29
Zou je je doel iets preciezer kunnen opschrijven met een formule? Op deze manier is het erg onduidelijk hoe je van set A naar set B in je voorbeeld komt.

[ Voor 19% gewijzigd door Henk007 op 22-08-2017 17:14 ]


Acties:
  • +1 Henk 'm!

Verwijderd

Topicstarter
armageddon_2k1 schreef op dinsdag 22 augustus 2017 @ 17:09:
Ik snap je voorbeeld niet helemaal, moet het geen: 29, -59, 81, -10, 10 zijn?
Nee, volgens mij klopt het toch?

40 - 2 = 38
38 + 1 = 39
39 - 2 = 37
37 + 34 = 71

Acties:
  • 0 Henk 'm!

  • armageddon_2k1
  • Registratie: September 2001
  • Laatst online: 27-07 10:18
Check, ik was niet scherp. ;)

Engineering is like Tetris. Succes disappears and errors accumulate.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Henk007 schreef op dinsdag 22 augustus 2017 @ 17:12:
Zou je je doel iets preciezer kunnen opschrijven met een formule? Op deze manier is het erg onduidelijk hoe je van set A naar set B in je voorbeeld komt.
Ik weet eerlijk gezegd niet hoe ik dit in een formule kan gieten, ben helaas niet erg goed in wiskunde. Op dit moment weet ik alleen hoe ik het handmatig kan doen en op een hele brute-force manier in code, maar dit zou heel erg traag worden.

Wat ik tot nu toe van plan was is om meerdere keren over de lijst heen te gaan en elke keer proberen om twee positieve getallen (en het tussenliggende negatieve getal) samen te voegen mits het resultaat groter is dan elk van de positieve getallen op zich.

Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • Henk007
  • Registratie: December 2003
  • Laatst online: 06-04 00:29
Volgens mij komt dit in de buurt:
Wiki maximum subarray problem

(Op een of andere manier lukt copy past niet in deze browser)
Het daarin genoemde algoritme is O(n)
Lees ook het wiki artikel: Subset sum problem

[ Voor 25% gewijzigd door Henk007 op 22-08-2017 17:34 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ga dat eens allemaal rustig doornemen, bedankt!

Acties:
  • 0 Henk 'm!

  • emnich
  • Registratie: November 2012
  • Niet online

emnich

kom je hier vaker?

Verwijderd schreef op dinsdag 22 augustus 2017 @ 16:59:
Wat is nu nodig heb is een algoritme om deze nummers zo veel mogelijk samen te voegen om zo groot mogelijk positieve nummers te krijgen, dus in dit voorbeeld wil ik de volgende output genereren:

code:
1
2
3
4
5
29
-59
71
-10
10
Maar waarom kies je hiervoor en niet bijv voor:
code:
1
2
3
29
-59
71

m.a.w. wanneer besluit je dat het getal groot genoeg is?

Acties:
  • 0 Henk 'm!

  • g0tanks
  • Registratie: Oktober 2008
  • Laatst online: 00:18

g0tanks

Moderator CSA
emnich schreef op dinsdag 22 augustus 2017 @ 17:43:
[...]

Maar waarom kies je hiervoor en niet bijv voor:
code:
1
2
3
29
-59
71

m.a.w. wanneer besluit je dat het getal groot genoeg is?
-10 en +10 blijven toch gewoon over van de originele lijst? Je kan er niks mee doen om hoger uit te komen dan 71.

Ultrawide gaming setup: AMD Ryzen 7 2700X | NVIDIA GeForce RTX 2080 | Dell Alienware AW3418DW


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Wat g0tanks zegt klopt inderdaad, ze blijven over (en moeten ook behouden blijven) en ze kunnen niet verder samengevoegd worden om tot een groter getal te komen.

Acties:
  • 0 Henk 'm!

  • LightningBullet
  • Registratie: Augustus 2005
  • Laatst online: 09:46
Nvm. Mijn gedachte was incorrect. Ik sloeg een belangrijke stap over...

[ Voor 135% gewijzigd door LightningBullet op 22-08-2017 19:39 ]


Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 10:50

Reptile209

- gers -

Uit nieuwsgierigheid: wat stellen de getallen voor? Dat helpt misschien in het kiezen van het juiste algoritme. En hoe belangrijk is het dat je de beste oplossing vindt? Mag het ook 'close enough' zijn?

En moet je dit continu/elk uur/elke dag/eenmalig doen? Bij regelmatig gebruik wil je snel zijn, maar als het eenmalig of zelden is, kan je gewoon number crunching doen, boeien dat je dan een half uurtje op het resultaat moet wachten.

Tot slot nog een vraag over je randvoorwaarde van "zo groot mogelijk". Hoe weet je dat je moet stoppen, en dat er na je voorbeeld niet een +40 komt waarmee de som van alle getallen opeens het grootst zou worden? Of zal dat pas blijken als je de hele serie gezien hebt?

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik kan niet echt zeggen wat de getallen voorstellen, behalve dat het komt uit afbeeldingen. Het is wel belangrijk dat de data correct is, dus geen schattingen.

In principe is het on-demand, dus hoe sneller hoe beter, omdat dit voor een prettigere user experience zorgt.

Je weet in principe pas wat de grootst mogelijke combinatie is zodra je de hele reeks hebt doorlopen.

Ik ben nu bezig om met Kadane's algoritme (via Henk007's link) een versie te maken die snel genoeg is. Deze gaat door de reeks heen, haalt elke keer de grootste range eruit, en splits vervolgens de array op in twee arrays (stuk voor en het stuk na de gevonden range) en herhaal dit vervolgens totdat alle mogelijke combinaties zijn getest. Ik hoop dat dit een beetje snel is (<1 seconde).

Acties:
  • 0 Henk 'm!

  • Mijzelf
  • Registratie: September 2004
  • Niet online
Is het niet gewoon
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
som = 0;
while( true )
{
     geltal = LeesVolgendGetal();
     nieuwe_som = som + getal;
     if( nieuwe_som < 0 )
     {
         print som
         print getal;
         som = 0;
     }
     else
     {
         som = nieuwe_som;
     }
}

Acties:
  • 0 Henk 'm!

  • Flipull
  • Registratie: September 2012
  • Laatst online: 05-08-2023
Mijzelf schreef op woensdag 23 augustus 2017 @ 11:27:
Is het niet gewoon[code]som = 0;
[...]
Ik denk het niet. Van elke reeks, de som getallen die het grootst zal zijn, moet volgens mij als eerst gedaan worden. Als je dat niet doet, dan kan het zijn dat je deze grootste som niet meer kan behalen, omdat je een deel van de nodige getallen al gebruikt hebt in andere (voorgaande) sommen.


De TS kan uit de lijst het kleinste en grootste getal pakken en die als minimum stellen voor de nieuwe som. Dit is voor uitzonderingssituaties waar blijkt dat 1 getal een grotere (of kleinere) som is, dan elk andere mogelijke som in de lijst.

Om alle sommen te bepalen moet je O(n^2) doen ofzo

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
som (item 0)
kijk of het het grootst of het kleinst is, en sla het op
som (item 0 + item 1)
kijk of het het grootst of het kleinst is, en sla het op
[...]
som (item 0 + item 1 + [...] + item n-1)
kijk of het het grootst of het kleinst is, en sla het op
[...]
som (item 1)
kijk of het het grootst of het kleinst is, en sla het op
[...]
som (item 1 + [...] + item n-1)
kijk of het het grootst of het kleinst is, en sla het op
[...]
som (item n-2)
kijk of het het grootst of het kleinst is, en sla het op
som (item n-2 + item n-1)
kijk of het het grootst of het kleinst is, en sla het op
[...]
som (item n-1)
kijk of het het grootst of het kleinst is, en sla het op

(Hopelijk duidelijke uitleg waarom ik n^2 zie)


[edit]
Ow, je hebt geen negatieve antwoorden nodig, zie ik nu :9
En iemand die me kan uitleggen hoe je hier O(n) van maakt? :>

[ Voor 4% gewijzigd door Flipull op 23-08-2017 11:58 ]


Acties:
  • +1 Henk 'm!

  • breew
  • Registratie: April 2014
  • Laatst online: 07:42
Ik zou beginnen in R, met de adagio-package..
https://cran.r-project.org/web/packages/adagio/adagio.pdf
maxsub finds a contiguous subarray whose sum is maximally positive. This is sometimes called
Kadane’s algorithm.
maxsub will use a compiled and very fast version with a running time of O(n) where n is the length
of the input vector x.
maxsub2d finds a (contiguous) submatrix whose sum of elements is maximally positive. The approach
taken here is to apply the one-dimensional routine to summed arrays between all rows of A.
This has a run-time of O(n^3), though a run-time of O(n^2 log n) seems possible see the reference
below.
maxsub2d uses a Fortran workhorse and can solve a 1000-by-1000 matrix in a few seconds—but
beware of biggere ones
Pagina: 1