» »

Matematično vprašanje v zvezi s lotom

Matematično vprašanje v zvezi s lotom

TheHijacker ::

Spravil sem se programirat en program za loto statistiko (za očeta, ampak bom program objavil tudi na internetu zastonj). Do sedaj imam že narejen vnos kombinacij ter bazo s vsemi žrebanji od leta 1991. Imam nek drug problem. Rad bi za vsako od teh žrebanj napisal katera izmed 15.380.937 kombinacij je bila izžrebana. Tu pa se meni ustavi. Mojo matematična logika je popolnoma na psu. Torej vse kar do sedaj vem da je:

1: 1, 2, 3, 4, 5, 6, 7
2: 1, 2, 3, 4, 5, 6, 8
3: 1, 2, 3, 4, 5, 6, 9
.
.
.
in
15.380.936: 32, 34, 35, 36, 37, 38, 39
15.380.937: 33, 34, 35, 36, 37, 38, 39.

Kako matematično izračunati vmesne pa ne vem. Potreboval pa bi obojestransko formulo, torej, da povem neko kombinacijo sedmih števil, on pa mi vrne zaporedno število in obratno. Spomnim se, da sem že videl program, ki je znal delati enako in mi je za 13.858.474 kombinacijo vrnil zaporedje 11, 12, 16, 17, 18, 24, 25.

Torej. Če kdo obvlada kombinatoriko ali se jo ravnokar uči na faksu, sem odprt za predloge.

Hvala
http://www.google.si

Thomas ::

Obstaja pragmatična in enostavna rešitev, ki pa NI optimalna.

V niz jih po vrsti napišeš vse te kombinacije - potem pa za dani niz scaniraš, keri je po vrsti

Če boš znal to - ti razložim še optimizacijo.

:)

Man muss immer generalisieren - Carl Jacobi

TheHijacker ::

15 miljonov zapisov ne mislim izdelati in potem skenirati za pravilnega (programiram v DOS-u, kjer sem še vedno omejen na 640k, zahvaljujoč Billu Gatesu).

Mi je pa že uspelo izdelati pravilen izračun in sicer sem našel program na starih disketah napisan v Pascalu neznanega avtorja, ki sem ga pretvoril v Clipper v katerem izdelujem ta program.

Kako deluje ne razumem, mi pa deluje. Thomas, vem, da mi boš znal razložiti ta postopek. Torej koda, ki sem jo uporabil izgleda sledeče:

function Stev_Komb
parameters k
declare prognoza[7]
afill(prognoza,0)
for st=1 To 7
if st-1=0
prognoza[st]=1
else
prognoza[st]=prognoza[st-1]+1
endif
do while (K-kombinac(39-prognoza[st],7-st)) > 0
K=K-kombinac(39-prognoza[st],7-st)
prognoza[st]=prognoza[st]+1
enddo
next
return prognoza

Function Kombinac
parameters n,r
IF r = 0
return 1
endif
IF n = 0
return 1
endif
IF r > n
return 0
endif
c=1
For i=1 to (n-r)
c=c*(i+r)/i
next
return c
return c

Proceduro stev_komb kličem s parametrom od 1 do 15.380.937. Pravilne vrednosti mi vrne v tabelo prognoza.

Stvar deluje, kako mi pa ni čisto jasno. Če si tako dober mi lahko prosim poveš še kako naj naredim obratno varianto iz tega in sicer, da pošljem tabelo s sedmimi vrednostmi in mi na koncu vrne zaporedno številko kombinacije... Pač matematika ni moje področje.
http://www.google.si

Zgodovina sprememb…

Thomas ::

Zvečer. Zdaj, mimogrede - ne morem. :)
Man muss immer generalisieren - Carl Jacobi

Tzar ::

BTW možnih kombinacij je 77.519.922.480,00
in ne 15 mio

good luck
Življenje je lepo!

blabla ::

pri 77.519.922.480 kombinacijah upoštevaš še pravilen vrstni red. Kombinacij pa je 15.380.937

TheHijacker ::

Thomas: Komaj čakam, ker sem že izgubil živce, ko sem sam trudil, da bi mi uspelo...

Po bazi imam zapise v pravlnem vrstnem redu in sicer jih je točno 590 od 13.10.1991.
http://www.google.si

Thomas ::

Hijacker

Tista obratna funkcija ni čisto trivialna - ampak takole naredI!

V NIZ(0) do NIZ(6) vnesi kombinacijo.

ZAPORED=0

for x0=1 to 33
for x1=x0+1 to 34
for x2=x1+1 to 35
for x3=x2+1 to 36
for x4=x3+1 to 37
for x5=x4+1 to 38
for x6=x5+1 to 39
    ZAPORED=ZAPORED+1
    IF NIZ(0)=x0 then
    IF NIZ(1)=x1 then
    IF NIZ(2)=x2 then
    IF NIZ(3)=x3 then
    IF NIZ(4)=x4 then
    IF NIZ(5)=x5 then
    IF NIZ(6)=x6 then
      print ZAPORED: exit sub

    endif
    endif
    endif
    endif
    endif
    endif
    endif

next
next
next
next
next
next
next



Ma da dela - in to dovolj hitro.

;)
Man muss immer generalisieren - Carl Jacobi

TheHijacker ::

Bom še to poskusil. Hvala!
http://www.google.si

Thomas ::

Takole gre pa obratno

KOMBNUM=92999
ZAPORED=0

for x0=1 to 33
for x1=x0+1 to 34
for x2=x1+1 to 35
for x3=x2+1 to 36
for x4=x3+1 to 37
for x5=x4+1 to 38
for x6=x5+1 to 39
    ZAPORED=ZAPORED+1
    if ZAPORED = KOMBNUM then

      print x0;x1;x2;x3;x4;x5;x6
      exit sub

    end if

next
next
next
next
next
next
next


Ta pa najde zaporednega. KOMBNUM - tega.

;)
Man muss immer generalisieren - Carl Jacobi

TheHijacker ::

Thomas ti si car! Sicer sem tudi sam pogruntal kako naj naredim reverzo s funkcijo, ki sem jo napisal nekaj postov gor. Sem pa vseeno tudi poskusil tvojo varianto.

Prvi vtis je....dela! Drugi pa je, da deluje počasi, kot še nobena funkcija, ki sem jo napisal doslej.

In kje je napača tvoje funkcije? V iteracijah. Če želim zvedeti katera kombinacija števil sestavlja kombinacijo 15.380.937 bo moral narediti točno toliko iteracij kar pa na TB 900Mhz traja v nedogled. Medtem ko tista moja funkcija to naredi v eni sekundi.

Enako je če želim zvedeti katera kombinacija števil sestavlja kombinacijo 15.380.937. Ponovno naredi 15.380.937 iteracij predno pride do 33, 34, 35, 36, 37, 38, 39. Je pa res, da sedaj zastopim, na kakšen način naj bi prišel do rešitve, medtem ko tiste iz pascala funkcije še vedno ne zastopim.

Lahko pa tudi preizkusiš sam. Če želiš že narejen program napisan v Clipperju ti ga rade volje pošljem lahko pa uporabiš samo del funkcije, ki mi to računa. Bom napisal še enkrat, je zelo kratka a zame pretežko razumljiva.

Iz števila vrne zaporedno kombinacijo (kot parameter pošlješ številko od 1-15.380.937). Ta paremeter potem funkcija obravnava kot K. Bi moralo biti razumljivo:

function stev_komb
parameters k
declare rezult[7]
afill(rezult,0)
for st=1 To 7
if st-1=0
rezult[st]=1
else
rezult[st]=rezult[st-1]+1
endif
do while (K-kombinac(39-rezult[st],7-st)) > 0
K=K-kombinac(39-rezult[st],7-st)
rezult[st]=rezult[st]+1
enddo
next
return rezult


Iz kombinacije vrne zaporedno številko. Ali_je spremenljivka naj te ne moti. Sem jo moral uporabiti, ker Clipperjeva tabela se začne s 1 in ne 0 kot Pascal. n_komb je tabela s vrednostni npr. n_komb[1,2,3,4,5,6,7]:

Function komb_stev
parameters n_komb
store 0 to n

For yy=1 to 7
if yy-1=0
ali_je=n_komb[yy] - 0
else
ali_je=n_komb[yy] - n_komb[yy-1]
endif
If (ali_je) >= 2
if yy-1=0
ali_je=0
else
ali_je=n_komb[yy-1]
endif
For jj=ali_je+1 To n_komb[yy]-1
n=n+kombinac(39-jj,7-yy)
next
endif
next
return n+1


Še funkcija kombinac, ki nekaj računa in mi ni točno jasna:

Function kombinac
parameters n,r
IF r = 0
return 1
endif
IF n = 0
return 1
endif
IF r > n
return 0
endif
c=1
For i=1 to (n-r)
c=c*(i+r)/i
next
return c
return c


Oboje iskanje mi deluje v manj kot sekundi, ne glede na podatke. Še enkrat pa poudarjam, da te funkcije NISO moje ampak sem jih našel pri programu loto, ki sem ga našel na starem CD-ju in je napisal v pascalu s izvorno kodo. Jaz sem ga samo prevedel v Clipper sintakso.

Če najdeš boljšo varianto...
http://www.google.si

Thomas ::

Hja, da je tole v clipperju počasno, ti kar verjamem. V VB pa bi moralo iti pod sekundo. Ne vem, ker ga nimam.


Ampak sprejmem izziv in ti napišem optimalno zadevo - tele dni enkrat.

:)
Man muss immer generalisieren - Carl Jacobi

Gandalfar ::

si optimiziral clipperjev exe z blinkerjem oz. cim podobnim? Uporalbjas clipper 5.2 ali imas se kaj starejsega? Poskusi zadevo prevesti z Alaska smtng..

TheHijacker ::

Hopla... Še eden, ki ve kaj je to Clipper... Da. Uporabljam Blinker ;) za kompiliranje, ki zna delati z overlajom. Do sedaj še nikoli nisem imel težav s 640k. Ne uporabljam Clipper 5.2 ampak dobri stari Clipper Summer 87'. Tako je. Prevajalnik iz leta 1987... Z njim se da delati čudovite programe. Za DOS, da se razumemo.

Tudi če bi prevedel z XXX prevajalnikom, dvamim da bo vse te zanke opravil v manj kot sekundi. Pravilno rešitev kako bi to naredil v Clipperju sem že napisal in deluje. Računa mi obojestranko in vrne rezultat v manj kot sekundi. Je pa res, da ga ne zastopim...

Kaj je smtng. Alaska vem kaj je ker jo imamo v službi za pisanje programov.
http://www.google.si

Thomas ::

Bom zvečer dal optimalno rešitev z razlago.

:)
Man muss immer generalisieren - Carl Jacobi

TheHijacker ::

Cool. Imam pa še eno vprašanje za katerega ne bom odpiral nove teme in sicer Random funkcija. Vem, da ni nobena funcija čisto natančna, ker vse delujejo tako da dobijo trenutni RTC čas in iz njega potem računajo.

Mi lahko daš še kakšen nasvet, kako naj izdelam random funkcijo, ko bo čimbolj natančna in seveda hitra. Trenutno sem naredil sledečo funkcijo, ki pa mi zaporedno vrača iste vrednost iznotraj ene sekunde.

FUNCTION tdRandom
Parameters nMax

if pcount() = 0
nMax=39
endif

n = 0.987654321

n = if(n = 0.987654321,n+(val(right(time(),2))/100),n)

n = (n * 123456789 + 1) / 10000

RETURN int((n - int(n)) * nMax


Bi mogoče gledal raje tisočinke časa ali pa desetinke? Imaš kakšno boljšo idejo?
http://www.google.si

OwcA ::

Poglej si Mersenne Twister, zelo dober in predvsem hiter (pseudo)random generator. Je pod GNU licenco, koda je na voljo v vecih jezikih.

Thomas ::

Takole:

Katera po vrsti je kombinacija:

4,6,7,13,17,19,38

Pred njo so najprej vse, kjer je prva številka manjša. Torej tiste, ki se začnejo z 1, 2, ali 3. Pa tiste, kjer je druga manjša. Torej tiste, ki imajo na drugem mestu 5. (Prva pa ostane). Pa tiste, ki imajo na tretjem mestu 8, 9, 10, 11, 12 ... (prvi dve pa kot sta) ....

ITD.

Koliko pa je takih, ki imajo na zadnjih N mestih M številk?


c=1: For i=1 to M: c=c*(n+1-i)/i: Next


Potem pa samo SEŠTEJEŠ za vse zgoraj navedene (in še nenavedene) primere.

:)


A je kej jasno?

Random pa tkole:

N=time

do

    Random=N mod 65537
    N=Random*Random

loop

Ja?
Man muss immer generalisieren - Carl Jacobi

TheHijacker ::

Thomas: Nič jasno, ampak je že vredu. To kar imam sedaj deluje. Jebi ga če ne zastopim. Bom pač, ko bom program objavil povedal, da del kode ni moj. Seveda bo šla zahvala tudi tebi ;).

OvcA: Mersenne Twister izgleda, da je zelo dober naključni generator številk, je pa preveč kompliciran, da bi njegovo kodo prevedel v compiler star 15. To kaj je napisal Thomas imam sedaj, pa ni dobro, ker mi v času ene sekunde prevečkrat ponovi številke...
http://www.google.si

Gandalfar ::

Hijacker: vredu delas v clipperju in verjetno ne bos sel tega portat. Kaj pa ce bi si zgeneriral neko .txt datoteko random stevil s pomocjo tega programa in potem samo beres ta stevila. Mar ni vseeno kdaj so bila ustvarjena?

OwcA ::

Hijacker: ce je interval med klici prekratek, enostavno uporabi spremenljivko v katero shranis zadnjo random vrednost, nakar ob vsakem klicu random generatorja preveri, ce je dobljena vrednost drugacna od stare. Ce ni, rocno povecaj/spremeni seed in klic ponovi.
Ce pa hoces imet "edinstvena" nakljucna stevila namesto ene same spremenljivke uporabi tabelo (array). Vendar pa tak pristop izvajanje dokaj upocasni, oziroma te prisili v dodatne komplikacije pri optimizaciji iskanja/dodajanja v tabelo (kaksno rdece-crno drevo...).


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

skriptni jezik

Oddelek: Programiranje
81220 (1020) CWIZO
»

[C++] Problem z dedovanjem šablon (template inhieritance)

Oddelek: Programiranje
131145 (1023) Gundolf
»

problem with c/c++ like program

Oddelek: Programiranje
7794 (619) OwcA
»

prog. za izjavni račun(c++)...

Oddelek: Programiranje
7820 (629) Thomas
»

štetje vpisanih znakov

Oddelek: Programiranje
8818 (731) bostek

Več podobnih tem