Egy 0-255 tartományt hogyan tudok feltölteni véletlenszerűnek kinéző, de nem véletlen IGEN/NEM értékekkel?
Ehhez van egy darab paraméterem, szintén 0-255.
Tehát, ha például ez a paraméter nulla, akkor az első érték legyen pl. NEM, a következő IGEN, aztán megint IGEN, és így tovább, látszólag véletlenszerűen sorban a 256 érték. Ha a paraméter egy másik szám, akkor más, de szintén IGEN/NEM értékek, amelyek nem az előző eltolása, hanem másféle minta.
Úgy szeretném, ha ezek az értékek külön-külön számíthatóak lennének, tehát ne kelljen sorrendben számolni őket, és lehetőleg ne legyen nagy számítási igénye.
Megoldható ez így?
A beépített generátornak nem állíthatom át a magértékét, mert akkor nem lesz véletlen, innen kezdve az nem használható erre.
Nem én találok ki egyet: van egy ősrégi, még a múlt évezredből. PTK 1050-es gépen használtam valaha.
De közben kiderült egy még nagyobb baj: sajnos a magértéket elég nehéz lesz meghatározni.
Úgy néz ki, hogy ez a 256 érték egy véletlen, 16*16-os táj lesz.
Ha rajta állok, akkor semmi gond: számítható egy fix magérték, és elkészíthető a táj.
Ha mellette állok, akkor is van egy magérték, de akkor sajnos nem egyezik meg azzal, mintha rajta állnék.
Úgyhogy amikor átlépek az egyik tábláról a másikra, akkor hirtelen drasztikusan megváltozik a táj körülöttem, ami elég zavaró lesz.
A másik lehetőség, hogy mindig beírom arra a táblára a magot, ahova éppen benézek, és ha átlépek rá, akkor ezt valahova elmentem, úgy használom.
Akkor belépésnél nem is lesz gond, de a kilépésnél igen, ha nem ugyanoda lépek ki, ahonnan jöttem. Bár ez jobban belefér a történetbe, de macerásabb programozni.
Sajnos, ha valamit változtatni vagy bővíteni szeretnénk egy már működő rendszeren, akkor adódhatnak nehézségek.
Persze téged, aki majd csak a kész eredményt látod, ez nyilván nem érdekel.
De akkor minek írsz?
> Sajnos nem lehet beépítettet használni, az másra is kell.
Attól mert másra is kell, használhatod erre is, a legtöbb RNG-t akárhányszor újraseedelheted:
Beseedeled az RNG-t a programod elején úgy, ahogy eddig is csináltad.
Amikor elö kell állítanod a tömböt, újraseedeled a paraméterrel.
Miután elöállt a listád, újraseedeled az aktuális idövel.
Vagy ha nagyonnagyon fontos, akár még az RNG aktuális belsö állapotát is lementheted a tömb elöállítás elött, utánna pedig visszaállíthatod.
Van más opció is: Kigenerálod az összes tömböt fordításidöbe és statikusan beleteszed a binárisba: ha jól értem 256 különbözö fajta 256 hosszú tömbre van szükséged. Ha minden értéket egy byte-on tárolsz, 65 kilobyte-ba beleférsz. Mivel az érték, amit felvehet csak kétféle lehet, ezen még tömöríthetsz is úgy, hogy egy byte-on 8 értéket tárolsz, így 8 kilobyte memória is elég.
Persze ha ez se tetszik, betehetsz egy saját RNG implementációt a beépített mellé. Ha nem kell, hogy kriptográfiailag erös RNG-d legyen, akkor vannak egyszerü algoritmusok is. Keress rá mondjuk a 'Linear-feedback shift registerre'
"Sajnos nem lehet beépítettet használni, az másra is kell."
Ha ez alatt azt érted amit kifejtek akkor teljesen logikus a felvetésed : használod valamire a beépített random generátort és ettől függetlenül kell egy olyan random generátor amivel repordukálható 0,1 sorozazot akarsz. Ha ugyanazt a random generátort használod a repodukálható sorozatra is mint a más célra előállított pseudo random-ot akkor a reprodukálandó sorozat előállításába is bekavar.
"Attól mert másra is kell, használhatod erre is, a legtöbb RNG-t akárhányszor újraseedelheted:
Beseedeled az RNG-t a programod elején úgy, ahogy eddig is csináltad.
Amikor elö kell állítanod a tömböt, újraseedeled a paraméterrel.
Miután elöállt a listád, újraseedeled az aktuális idövel.
Vagy ha nagyonnagyon fontos, akár még az RNG aktuális belsö állapotát is lementheted a tömb elöállítás elött, utánna pedig visszaállíthatod."
Valaki írt python kódot, erre a fentebbi megoldásjavaslat szerinti seedeléses megoldás, módosítva azzal hogy másra is használom közbe:
Látható hogy mindig ugyanaz lesz a sorozat ugyanazzal a paraméterrel, nem kavar bele hogy előtte utána másra használtam.
def sorozat(parameter):
mentett_belso_allapot = random.getstate()
random.seed(parameter)
sorozat = [random.choice(["IGEN", "NEM"]) for _ in range(256)]
random.setstate(mentett_belso_allapot)
return sorozat
import random
print('masra hasznalt:',[random.randrange(100) for _ in range(10)])
parameter = 25 # lehet akármi más
print(f'sorozat {parameter} parameterrel : ',sorozat(parameter))
print('masra hasznalt:',[random.randrange(444) for _ in range(5)])
print(f'sorozat {parameter} parameterrel : ',sorozat(parameter))
Én más megoldásra gondoltam. Maga a beépített random generátornak másik példányát használjuk erre a célra, az alapból létező példányát meg megint másra:
import random
rnd = random.Random()
print('masra hasznalt:',[random.randrange(100) for _ in range(10)])
parameter = 25 # lehet akármi más
rnd.seed(25);print(f'sorozat {parameter} parameterrel : ',[rnd.choice(["IGEN", "NEM"]) for _ in range(256)])
print('masra hasznalt:',[random.randrange(444) for _ in range(5)])
rnd.seed(25)
rnd.seed(25);print(f'sorozat {parameter} parameterrel : ',[rnd.choice(["IGEN", "NEM"]) for _ in range(256)])
Ez utóbbi megoldás jobb, mert egyetlen egy ciklusmagon belül is tudjuk használni mind a kettő példányt simán, nem kell minden egyes használatkor az örökös belső állapot mentésekkel bajlódni. A tekintetben is jobb, ha több párhuzamos szál van, akkor az meg ingencsak megbonyolítaná az előbbi módszer hiszen miközben egyik szál használja egy ciklusba közbe a másik szál is belerondíthat a generátor belső állapotába. Több szál esetében könnyű izolálni a generátorokat, minden szálnak akár saját lokális random.Random példánya lehet.
Sajnos ez C program, csak ez az egy szál generátor van, és nem érhető el az állapota.
Viszont ez még nem lenne baj, mert elég lenne egy egyszerű, ahogy írták is - de belefutottam abba, hogy nem tudom jól megadni a magszámot.
Ha fejreállok, akkor is változik a táblák között lépkedve, tehát változni fog a táj ki/be/átlépéskor.
Maximum úgy tudnám megcsinálni, hogy minden méteren (3-4 lépésenként) változna, az még esetleg belefér a történetbe.
Előző (11:16-os) vagyok. A C az jó rég volt amikor programoztam benne. Megnéztem a standard C pseudo random generátor ilyen felhasználásra tényleg nincs felkészítve.
Találtam másikat hozzá ahol példányosítható a generátor : [link]
A példa kód is működik, ha már példányosítás, akkor írtam hozzá én is példát használatra, egyből 2 példányba futtatom r,r2 példányokba. A kód magáért beszél gondolom nem kell ecsetelnem : [link]
Bitenként meg ki tudod nyerni az értékeket az unsigned long-okból, gondolom az nem okoz gondot.
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!