 |
Forum PHP Romania - Discutii despre PHP, MySQL, Javascript, AJAX, etc Comunitatea PHP Romania
|
| Subiectul anterior :: Subiectul următor |
| Autor |
Mesaj |
coditza
Data înscrierii: 23/Ian/2004
Mesaje: 298
Locație: cluj-napoca
|
| Trimis: Joi Iul 22, 2004 1:55 pm Titlul subiectului: random... preferential |
|
|
se da un sir de 10 numere, de la 1 la 10.
Se cere sa se scrie o functie care va returna in 60% din cazuri valoarea 5 si in restu de 40% din cazuri sa returneze una din restul de valori...
Solutia mea e de genul:
construiesc un nou sir, in care am numarul 1 de ceil(27/2) = 14 ori si restul de numere cate o data. Si fac un $key = rand(0,22) si returnez elementul din sirul nou creat de la keyul $key.
Problema e ca treaba asta trebe folosita la un sistem de banners rotators. S-ar putea ca arrayul respectiv sa devina destul de mare. Plus ca solutia nu mi se pare cea mai cea...
Are careva o alta idee? |
|
| Sus |
|
Birkoff
Data înscrierii: 18/Mar/2004
Mesaje: 2266
Locație: Bucuresti
|
| Trimis: Joi Iul 22, 2004 3:55 pm Titlul subiectului: |
|
|
o idee
incearca sa faci un script care sa scrie un nr in bd sau intr-un fisier text...
adica vizitez pagina odata se introduce nr 1 a doua oara nr 2 si tot asa...
in functie de anumite nr se afiseaza un anumit banner ( sa zicem ca din 5 in 5 afisari ale pagini se va afisa un anumit baner si in rest celelalte intr-o ordine prestabilita...
scriptul tau trebuie doar sa citeasca nr respectiv din bd si in functie de el (sau de valoarea lui) sa afiseze banerul corespunzator...
sper sa te ajute ideea |
|
| Sus |
|
coditza
Data înscrierii: 23/Ian/2004
Mesaje: 298
Locație: cluj-napoca
|
| Trimis: Joi Iul 22, 2004 4:08 pm Titlul subiectului: |
|
|
adik un fel de history la ce numere am scos deja or smth? e o idee, dar nu e mai buna decat cea folosita deja... asta ar insemna 3 queryuri la baza de date... 1 sa vad ce history am deja... unu sa fac update la history ala + unu sa scot baneru din baza de date. la solutia mea is numai 2 queryuri... scot toate idurile cu valorile lor de prioritate + query care scoate datele propriuzise
no, sa redefinesc "corect" problema: am o tabela cu tzajpe banere in care este pastrata si prioritatea. No, tre sa scot banneru Z de Z.priority ori (sau in Z.priority cazuri) etc
dupa un brainstorming cu coworkeri am ajuns la concluzia ca fara un counter extern nu poti sa scoti de exact 60% (cu rotunjirile de vigoare).
No, totusi, daca mai avetzi solutii, nu conteaza cand veniti cu ele, is bine primite. A devenit chestia asa un fel de "manie" personala |
|
| Sus |
|
Troto
Data înscrierii: 29/Iun/2004
Mesaje: 249
Locație: Brasov
|
| Trimis: Joi Iul 22, 2004 6:03 pm Titlul subiectului: |
|
|
Ce spui de asta
Nu stiu cum se comporta la matrici foarte mari. Testeaza si tu
<?php
// Dupa parerea mea este imposibil ca in 60% din cazuri sa iti afiseze un anumit banner.
// Tot ce poti face e sa aproximezi dand o marja de eroare.
// Oricum, am sa incerc ceva si mai discutam pe baza scriptului
// Indiferent ca numele, poza sau mai stiu eu ce a bannerului le ai intr-o baza de date sau un fisier
// trebuie sa verificam cate bannere sunt in total.
// Aici voi folosi o matrice. Matricea o poti genera dintr-o baza de date sau un fisier sau unde le ai
// $bannerul pe care il vom afisa
$banner_id_de_afisat = null;
// Matrice cu bannere
$matrice_cu_bannere = array(
array(
'id' => 0,
'afisari' => 0,
'nume' => 'Banner 1',
'poza' => 'images/banner/1.jpg'
),
array(
'id' => 1,
'afisari' => 0,
'nume' => 'Banner 2',
'poza' => 'images/banner/2.jpg'
),
array(
'id' => 2,
'afisari' => 0,
'nume' => 'Banner 3',
'poza' => 'images/banner/3.jpg'
),
array(
'id' => 3,
'afisari' => 0,
'nume' => 'Banner 4',
'poza' => 'images/banner/4.jpg'
),
);
// id-ul bannerului principal
$id_banner_principal = 0;
// acum setam procentul pt bannerul 1 (sa spunem pe care vrem sa il afisam in x % din cazuri)
$procent_necesar = 0.6;
// setam si o marja de eroare in caz ca vrem asa ceva, altfel o punem 0
$marja_eroare = 0.1;
// cate bannere avem
$nr_bannere = count($matrice_cu_bannere);
if ($matrice_cu_bannere[$id_banner_principal]['afisari'] == 0) {
$banner_id_de_afisat = $id_banner_principal; // daca bannerul principal nu a fost afisat deloc il afisam direct fara a mai calcula
} else {
// facem suma afisarilor tuturor bannerelor cu exceptia celui mai important
$suma_afisari_celalte_bannere = 0;
for ($i=0; $i<$nr_bannere; $i++) {
if ($i != $id_banner_principal) { // sa nu adunam bannerul important
$suma_afisari_celalte_bannere += $matrice_cu_bannere[$i]['afisari'];
}
}
// totalul afisarilor realizate pana in prezent
$total_afisari = $suma_afisari_celalte_bannere + $matrice_cu_bannere[$id_banner_principal]['afisari'];
// procentul realizat pana in rpezent de bannerulprincipal
$procent_curent_realizat = ($matrice_cu_bannere[$id_banner_principal]['afisari'] / $total_afisari);
if ($procent_curent_realizat <= $procent_necesar - $marja_eroare) {
// afisam bannerul principal
$banner_id_de_afisat = $id_banner_principal;
} else {
// in caz ca nu afisam bannerul principal calculam sa vedem ce alt banner afisam
// stergem bannerul principal din matrice
unset($matrice_cu_bannere[$id_banner_principal]);
// setam bannerul cu cele mai putine afisari un banner aleator
srand((float) microtime() * 10000000);
$index_random = array_rand($matrice_cu_bannere);
$min_b_id = $matrice_cu_bannere[$index_random]['id'];
$min_b_afis = $matrice_cu_bannere[$index_random]['afisari'];
reset($matrice_cu_bannere);
foreach($matrice_cu_bannere as $banner) {
// daca intalnim un banner care nu a fost afisat il afisam pe acela
if ($banner['afisari'] == 0) {
$banner_id_de_afisat = $banner['id'];
break;
} else {
// salvam valoarea minima intr-o variabila temporala
$tmp_min = min;
// calculam minimul dintre valoarea minima precedenta si a cea a bannerului curent
$min = min($min_b_afis, $banner['afisari']);
// daca valoarea minima se schimba inseamna ca am gasit o valoare ma mica si o salvam pe aia
if ($tmp_min != min) {
$min_b_afis = $min;
echo $min_b_id = $banner['id'];
}
}
}
// bannerulpe care il afisam e minimul gasit
$banner_de_afisat = $min_b_id;
}
}
print_r($matrice_cu_bannere[$banner_id_de_afisat]);
?>
Dupa ce afli ID-ul bannerului trebuie doar sa reactualizezi baza de data sau fisierul, sau unde tii tu toate datele, dar asta nu am mai facut :D |
|
| Sus |
|
coditza
Data înscrierii: 23/Ian/2004
Mesaje: 298
Locație: cluj-napoca
|
| Trimis: Joi Iul 22, 2004 9:14 pm Titlul subiectului: |
|
|
| is cam obosit acum, dar algoritmul pare ok. Nu am vazut asa la o prima citire nici o scapare. Il citesc maine iara, sa vedem ce chestii ar putea apare si/sau ce imbunatatiri se pot aduce |
|
| Sus |
|
Troto
Data înscrierii: 29/Iun/2004
Mesaje: 249
Locație: Brasov
|
| Trimis: Joi Iul 22, 2004 11:30 pm Titlul subiectului: |
|
|
E facut in graba in jma de ora.
cred eu ca sunt ceva scapari, dar in mare isi face treaba.
Oricum , trebuie adaptat dupa necesitatile tale. Oricum macar un inceput sper sa fie. de aici mai discutam pana il facem asa cumiti trebuie
Somn usor :P |
|
| Sus |
|
coditza
Data înscrierii: 23/Ian/2004
Mesaje: 298
Locație: cluj-napoca
|
| Trimis: Vin Iul 23, 2004 2:42 pm Titlul subiectului: |
|
|
Troto a scris: Somn usor :P
right... poate la noapte |
|
| Sus |
|
smallAdmin
Data înscrierii: 21/Mai/2004
Mesaje: 117
Locație: Bucuresti
|
| Trimis: Vin Iul 23, 2004 2:54 pm Titlul subiectului: Re: random... preferential |
|
|
Generalizat : vreau aleg un numar random din n. Fiecare numar are o pondere de aparitie.
Solutie : construiesc un vector cu n elemente, fiecare element avand ponderea fata de toate celelalte...
Aleg un numar aleator intre 0 si suma tuturor elementelor din vector.
Pentru exemplul de mai jos ($pond), numarul generat de rand daca e mai mic decat 5, insemna ca numarul cautat e 1, daca e intr 5 si 10 numarul cautat e 2 si tot asa...
<?php
// vectorul de ponderi...
// fiecare element din vector inseamna cata pondere are in facutul de random
$pond=array(0,5,5,5,5,55,5,5,5,5,5);
$total=array_sum($pond);
$n=count($pond);
$rand=rand(0,$total-1);
$add=0;
// caut cheia din vector care se potriveste cel mai bine
for($i=0;$i<$n;$i++){
$add+=$pond[$i];
if($add>$rand){ // am gasit numarul, asa ca ies
$randul_cautat=$i;
$i=$n;
}
}
echo 'Randomul cautat : '.$randul_cautat.', pondere : '.number_format($pond[$randul_cautat]/$total*100,2).'%';
?>
In exemplul de mai sus, fiecare pondere e fix procentul de care am nevoie. |
|
| Sus |
|
Troto
Data înscrierii: 29/Iun/2004
Mesaje: 249
Locație: Brasov
|
| Trimis: Vin Iul 23, 2004 3:08 pm Titlul subiectului: |
|
|
| Solutia asta nu e chiar asa de buna pentru ca de fiecare data iti returneaza acelsi rand cautat |
|
| Sus |
|
smallAdmin
Data înscrierii: 21/Mai/2004
Mesaje: 117
Locație: Bucuresti
|
| Trimis: Vin Iul 23, 2004 3:09 pm Titlul subiectului: |
|
|
varianta 2 ( folosind si o tabela MySQL )
an style="color: #000000"><?php // tabela bannere cu campurile : id(primary key), views, pondere
// ponderea e exprimata in procente
$res=mysql_query("select sum(views) from bannere");
list($total_views)=mysql_fetch_array($res,MYSQL_NUM);
$res=mysql_query("select *,pondere-(views/$total_views)*100 as diferenta from bannere order by diferenta desc limit 1");
$banner=mysql_fetch_array($res);
mysql_query("update bannere set views=views+1 where id=$banner[id]");
Ideea e ca incerci mereu sa iei un banner a carui pondere de afisare in momentul actual e cea mai departata de pondeea cu care trebuie sa fie afisat acel banner.
La fel ca in exemplul de mai sus, poti folosi oricate bannere, in schimb e mai dificil sa adaugi un banner pentru ca trebuie sa schimbi si celelalte ponderi astfel incat sa ai suma tuturor ponderilor 100.
E netestat, da' sper ca intelegi ce am vrut sa zic ;) |
|
| Sus |
|
Troto
Data înscrierii: 29/Iun/2004
Mesaje: 249
Locație: Brasov
|
| Trimis: Vin Iul 23, 2004 4:14 pm Titlul subiectului: |
|
|
smallAdmin a scris:
La fel ca in exemplul de mai sus, poti folosi oricate bannere, in schimb e mai dificil sa adaugi un banner pentru ca trebuie sa schimbi si celelalte ponderi astfel incat sa ai suma tuturor ponderilor 100.
tocmai de asta cred ca solutia mea este mai buna deoarece nu trebuie sa schimbi ponderile la fiecare adaugare a unui banner... daca ai f mute bannere o sa fie extrem de dificil |
|
| Sus |
|
smallAdmin
Data înscrierii: 21/Mai/2004
Mesaje: 117
Locație: Bucuresti
|
| Trimis: Vin Iul 23, 2004 7:10 pm Titlul subiectului: |
|
|
Troto a scris: Solutia asta nu e chiar asa de buna pentru ca de fiecare data iti returneaza acelsi rand cautat
Incearca mai multe refreshuri... statistic e corect. Dupa vreo 10 incercari ar trebui sa ai de 5-7 ori numarul 5...
Troto a scris: tocmai de asta cred ca solutia mea este mai buna deoarece nu trebuie sa schimbi ponderile la fiecare adaugare a unui banner... daca ai f mute bannere o sa fie extrem de dificil
Bine ma, e mai buna... :D da' tre' sa recunosti ca a mea e ingenioasa si merge pe cazul general ;) |
|
| Sus |
|
Troto
Data înscrierii: 29/Iun/2004
Mesaje: 249
Locație: Brasov
|
| Trimis: Vin Iul 23, 2004 8:14 pm Titlul subiectului: |
|
|
In primul rand variabila $total este intotdeauna 100 dupa cum ai spus tu..corect?
apoi inainte de a apela rand() (in care puiteai f bine sa pui rand(0,99)) trebuie sa ai ceva de genul
an style="color: #000000"><?php function make_seed() {
list($usec, $sec) = explode(' ', microtime());
return (float) $sec + ((float) $usec * 100000);
}
srand(make_seed());
Asta in cazul in care ai php 4.2 (eu am 4.3.8 dar se pare ca totusi un mic program care il folosesc pt testare esueaza la treburi de genul asta. .. asa ca acum l-am testat in server direct)
Ideea e buna, dar totusi nu prea ai control sigur asupra valorilor. Adica statistic vorbind e bine.. dar asta nu inseamna ca e si corect. Sti cum e .. daca am o palma in foc si alta in frigider .. statistic mie mi-e bine.. lucru care nu e tocmai asa :) |
|
| Sus |
|
coditza
Data înscrierii: 23/Ian/2004
Mesaje: 298
Locație: cluj-napoca
|
| Trimis: Lun Iul 26, 2004 5:44 pm Titlul subiectului: |
|
|
| deci 2 idei care merita discutate. pana maine sper sa le citesc si eu... pana una alta, hi sa discutam unpika despre criptarea parolelor in baza de date pe urmatorul topic :D |
|
| Sus |
|
coditza
Data înscrierii: 23/Ian/2004
Mesaje: 298
Locație: cluj-napoca
|
| Trimis: Mie Iul 28, 2004 5:37 pm Titlul subiectului: |
|
|
no, sefu mi-o dat cel mai bun algorit de pana acum :D
pur si simplu, cand userul intra prima oara pe pagina, ii generezi un "path" cum ii areti banerele... si tot elimi cate un baner din pathul ala. cand s-o golit, il regenerezi... simplu... doar un sir in $_SESSION ;) |
|
| Sus |
|
PHPRomania Bot
Bot Member
Data înscrierii: 27/Dec/2007
Mesaje: 1
Locaţie: Server Google |
| Trimis: Mie Dec 26, 2007 7:01 pm Titlul subiectului: Ad |
|
|
|
|
|
| Sus |
|
| |
|