Schrift
[thread]1344[/thread]

Algo für eine Prozentuale Warscheinlichkeit

Leser: 1


<< |< 1 2 >| >> 12 Einträge, 2 Seiten
SirLant
 2003-09-06 19:31
#17806 #17806
User since
2003-08-04
516 Artikel
BenutzerIn
[default_avatar]
Hoffe das Topic passt halbwegs :blush:

Mein Problem:
Ich möchte einen Zufallsgenerator haben, der aber nicht einfach
Zufallszahlen liefert sondern noch eine gewisse Prozent-Chance eimbezieht.

Also, wenn ich zum Beispiel zufällig einen Artikel(von 3Stück)
meines Shops auf der Startseite präsentieren möchte, dann soll
dieser nicht einfach zufällig ausgewählt werden, sondern noch
die Prozentuale Chance (Artikel1 60%, Artikel2 30%, Artikel3 10%)
mitberücksichtigt werden.

mein Problem ist, dass ich nicht weiß wie ich das formulieren soll :(

Habe den Thread nicht in das Allgemeine Perl Forum gepostet,
da ich ne allgemeine Lösung des Problems suche und nicht eine
nur in Perl Funktionierende :)

Es ist natürlich erlaubt, die Lösung des Problem anhand eines Perlskriptes aufzuzeigen :)\n\n

<!--EDIT|SirLant|1062862360-->
--Programming today is a race between Software Enginers striving to build bigger and better idiot-proof Programs,
and the Universe trying to produce bigger and better idiots.
So far, the Universe is winning!
SirLant
 2003-09-06 19:37
#17807 #17807
User since
2003-08-04
516 Artikel
BenutzerIn
[default_avatar]
Will nicht nochmal editieren :D

An die einfachste Möglichkeit habe ich schon gedacht,dass ich einfach folgendes mache:
-rand aufrufen, mit 1-10
-wenn 1 -> Artikel3
-wenn 2-4 -> Artikel2
-wenn 5-10 -> Artikel1

Aber denke da gibt es sicher noch ne bessere Variante :)
--Programming today is a race between Software Enginers striving to build bigger and better idiot-proof Programs,
and the Universe trying to produce bigger and better idiots.
So far, the Universe is winning!
Ishka
 2003-09-06 20:05
#17808 #17808
User since
2003-08-04
771 Artikel
HausmeisterIn
[Homepage] [default_avatar]
Wenn du alles Per Hand machen möchtest ;)
Der code hier gibt die verschiedenen Artikel mit gewichteter Wahrscheinlichkeit aus, dh. wenn die Zahl zB doppelt so graoß ist, ist es doppelt so wahrscheinlich, daß sie kommt
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@artikel=(
[5,'Artikel1'],
[10,'Artikel2'],
[20,'Artikel3']
);

print auswahl(@artikel);

sub auswahl{
my $g=0;
$g+=$_->[0] for @_;

my $zahl=rand $g;
my $h=0;
for(@_){
$h+=$_->[0];
return $_->[1] if $h>$zahl
}
}
sub z{if(@_){1while$x[$k=rand 10];t($t=$x[$k]=1)}print map"$z[$x[$_]]$_".($_%3?
"":"\n"),1..9}sub t{$j=0;$x[$_+1]==$t&&($j+=2**$_)for 0..8;z,die"Gewinner $z[$t]
"if grep$_==($j&$_),7,56,73,84,146,273,292,448;z,die"Gleichstand\n"if@x>9&&!grep
!$_,@x}@x=4;@z=qw{. [ (};z$^T&1;while(<>){next if$_>9||$x[$_];t$t=$x[$_]=2;z 1}
SirLant
 2003-09-06 20:15
#17809 #17809
User since
2003-08-04
516 Artikel
BenutzerIn
[default_avatar]
Werde deinen Code mal schöner schreiben und versuchen zu
verstehen was er tut :D

Habe den mal hier, aber was ist $h?
Kannst du der mal einen besseren Namen geben?
Sonst verstehe ich soweit das Skript

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/user/bin/perl -w
use strict;


my @artikel=([5,'Artikel1'],[10,'Artikel2'],[20,'Artikel3']);

print auswahl(@artikel);

sub auswahl{

  my $prozent=0;
  my $h=0;
        
  foreach my $artikel (@_){
        
    $prozent +=$artikel->[0];
        
  }

  my $zahl= rand ($prozent);
        
  foreach my $artikel (@_){
                
    $h+=$artikel->[0];
                
    return $artikel->[1] if $h>$zahl
        
  }

}


Was mir da noch einfällt, dein Skript tut ja genau das, was meine
Überlegung oben macht, also ist dies die einfachste und beste
Variante?\n\n

<!--EDIT|SirLant|1062865050-->
--Programming today is a race between Software Enginers striving to build bigger and better idiot-proof Programs,
and the Universe trying to produce bigger and better idiots.
So far, the Universe is winning!
Ishka
 2003-09-06 20:23
#17810 #17810
User since
2003-08-04
771 Artikel
HausmeisterIn
[Homepage] [default_avatar]
$h könnte man Schranke nennen, mir fällt aber auch kein passender Name ein.

Es ist definitiv die Einfachste Variante. Man kann sich aber, wenn man will, auch einen baum aufbauen, dann kommt man schneller durch. Allerdings sehen die rechenzeiten ungefähr so aus:

n:=Anzahl der Elemente

Die Variante:
Aufbau:
n
Suche:
n/2

mit Baum:
Aufbau:
5*n
Suche
ld n

dh: es lohnt sich nur den Baum aufzubauen, wenn du viele Zufallselemente haben willst
sub z{if(@_){1while$x[$k=rand 10];t($t=$x[$k]=1)}print map"$z[$x[$_]]$_".($_%3?
"":"\n"),1..9}sub t{$j=0;$x[$_+1]==$t&&($j+=2**$_)for 0..8;z,die"Gewinner $z[$t]
"if grep$_==($j&$_),7,56,73,84,146,273,292,448;z,die"Gleichstand\n"if@x>9&&!grep
!$_,@x}@x=4;@z=qw{. [ (};z$^T&1;while(<>){next if$_>9||$x[$_];t$t=$x[$_]=2;z 1}
SirLant
 2003-09-06 20:25
#17811 #17811
User since
2003-08-04
516 Artikel
BenutzerIn
[default_avatar]
Würdest du mir nen Modell mit einem Baum erstellen *Hundeblick mach* :)

Schranke finde ich passend :)
--Programming today is a race between Software Enginers striving to build bigger and better idiot-proof Programs,
and the Universe trying to produce bigger and better idiots.
So far, the Universe is winning!
Ishka
 2003-09-06 20:55
#17812 #17812
User since
2003-08-04
771 Artikel
HausmeisterIn
[Homepage] [default_avatar]
Mir ist noch ne bessere Idee gekommen, schreib ich mal mit Pseudocode auf:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@elemente=Liste aller Elemente, ergänzt mit 0en auf 2^n Elemente;
$gesammtzahl=Aufsummierte wahrscheinlichkeiten;

{
my $schrankenbilden=0;
for(@elemente)
{
$schrankenbilden+=$_->[0];$_->[2]=$schrankenbilden
}
}

### Element auswählen

my $sprungvar=@elemente/2-1;
my $schritt=@elemente/4;
my $ziel=rand $gesammtzahl;
while($schritt>1){
if($elemente[$sprungvar]->[2]>$ziel)
{
$sprungvar-=$schritt;
}else{
$sprungvar+=$schritt;
}
$schritt/=2;
}

Das dürfte sich sogar schon ab zwei oder drei zufälligen auswahlen rentieren - Umso mehr, je größer der array ist.

Minimal kann man noch optimieren, aber da bin ich jetzt zu faul zu ;)

ps:
Hundeblick bringt wenig, mag keine Hunde ;)\n\n

<!--EDIT|Ishka|1062867381-->
sub z{if(@_){1while$x[$k=rand 10];t($t=$x[$k]=1)}print map"$z[$x[$_]]$_".($_%3?
"":"\n"),1..9}sub t{$j=0;$x[$_+1]==$t&&($j+=2**$_)for 0..8;z,die"Gewinner $z[$t]
"if grep$_==($j&$_),7,56,73,84,146,273,292,448;z,die"Gleichstand\n"if@x>9&&!grep
!$_,@x}@x=4;@z=qw{. [ (};z$^T&1;while(<>){next if$_>9||$x[$_];t$t=$x[$_]=2;z 1}
SirLant
 2003-09-07 14:08
#17813 #17813
User since
2003-08-04
516 Artikel
BenutzerIn
[default_avatar]
Kannst du das ein wenig kommentieren?
Und mir nen Beispiel für das Array mit den Elementen geben?
Am frühen Morgen bin ich dazu wohl noch nicht in der Lage :(

Wozu hast du die for-schleife Eingeklammert?
Ich sehe da im mom keinen Sinn darin\n\n

<!--EDIT|SirLant|1062930092-->
--Programming today is a race between Software Enginers striving to build bigger and better idiot-proof Programs,
and the Universe trying to produce bigger and better idiots.
So far, the Universe is winning!
Ishka
 2003-09-07 20:03
#17814 #17814
User since
2003-08-04
771 Artikel
HausmeisterIn
[Homepage] [default_avatar]
die { } geht nicht nur um die for-Schleife, sondern auch um eine my-deklaration - und die soll außerhalb nicht mehr sichtbar sein.

Ich hab den code jetztausformuliert (und ncoh ein bissal verändert, weil noch zwei drei kleinere Fehler drin waren)

Der Code ist zwar nicht der beste stil und man kann noch ein bissal optimieren, aber ich denke, daß das Optimum maximal um 40% schneller ist.
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/usr/bin/perl

use strict;
use warnings;

my @elemente=(
[15,'Artikel1'],
[10,'Artikel2'],
[20,'Artikel3'],
[80,'Artikel4'],
[35,'Artikel5'],
[10,'Artikel6']
);

# Array festgelegt

{
my $potenz=2;
while($potenz<@elemente){$potenz*=2}
my @leer_array=map {[0,'']} @elemente..$potenz-1;
push @elemente,@leer_array;
}

# Array auf eine zweierpotenz gebracht

my $gesammtzahl=0;

for(@elemente)
 {
 $gesammtzahl+=$_->[0];
 $_->[2]=$gesammtzahl
 }

# Bei jedem Arrayelement steht jetzt dabei, wie groß die Summe
# der Wahrscheinlichkeiten für alle vorhergehenden Elemente ist

### Element auswählen

my $sprungvar=0;
my $schritt=@elemente/2;
my $ziel=rand $gesammtzahl;
while($schritt>=1){
if($elemente[$sprungvar]->[2]<$ziel)
{
$sprungvar+=$schritt;
}elsif($elemente[$sprungvar-1]->[2]>$ziel){
$sprungvar-=$schritt;
}else{last}# Wenn man beim richtigen Element ist
if($sprungvar<0){$sprungvar=0;last}# für den Fall, daß der
# Zufallsgenerator auf das erste Element zeigt
$schritt/=2;
}


print "$elemente[$sprungvar]->[1]\n";
sub z{if(@_){1while$x[$k=rand 10];t($t=$x[$k]=1)}print map"$z[$x[$_]]$_".($_%3?
"":"\n"),1..9}sub t{$j=0;$x[$_+1]==$t&&($j+=2**$_)for 0..8;z,die"Gewinner $z[$t]
"if grep$_==($j&$_),7,56,73,84,146,273,292,448;z,die"Gleichstand\n"if@x>9&&!grep
!$_,@x}@x=4;@z=qw{. [ (};z$^T&1;while(<>){next if$_>9||$x[$_];t$t=$x[$_]=2;z 1}
SirLant
 2003-09-07 20:22
#17815 #17815
User since
2003-08-04
516 Artikel
BenutzerIn
[default_avatar]
Danke, muss mich da ersteinmal reinarbeiten :)

Habe eben ein paar Probeläufe gemacht und es kam in ~70% der Fälle Artikel4 heraus, Zufall?\n\n

<!--EDIT|SirLant|1062951769-->
--Programming today is a race between Software Enginers striving to build bigger and better idiot-proof Programs,
and the Universe trying to produce bigger and better idiots.
So far, the Universe is winning!
<< |< 1 2 >| >> 12 Einträge, 2 Seiten



View all threads created 2003-09-06 19:31.