LUA > Nilgiri > Mindig új elemet adó iterátor/bejáró

Bajban vagyok az iterátor elnevezésével, mert ez egy olyan iterátor, ami örökké fut és mindig új elemet szolgáltat a paraméterként átadott táblából, ha kiszedte az összes elemet, akkor újra kezdi. De azért találtam neki nevet: ÖrökkéLottó :D

Az algoritmus úgy működik, hogy készít egy másolatot a bemeneti táblából úgy, hogy kulcs és az érték is a táblaindex, tehát egy öt elemű táblánál:

shadow = {
[1] = 1,
[2] = 2, -- *
[3] = 3,
[4] = 4,
[5] = 5
}
shadow.count = 5

Ha kisorsoltuk a 2-es indexet, akkor a shadow tábla így módosul:

shadow = {
[1] = 1,
[2] = 4, -- *
[3] = 3,
[4] = 5,
[5] = 5
}
shadow.count = 4

Ha kisorsoltuk a 2.indexet 4-es értékkel kivesszük a buliból és behozzuk az utolsó elemet, majd szűkítjük a shadow count értékét, tehát

shadow = {
[1] = 1,
[2] = 5,
[3] = 3,
[4] = 5,
[5] = 5,
}

és így tovább...


function iter_lottoforever(t)
	-- feltetelezi, hogy a tabla nem valtozik --

	
	local shadow = {}
	for i=1,#t do
		table.insert(shadow, i)
	end
	shadow.count=#t
	
	return function()
	
		if shadow.count == 0 then
			shadow = {}
			for i=1,#t do
				table.insert(shadow,i)
			end
			shadow.count = #shadow
		end
			last = shadow.count
			--print(last)
			rnd_idx = shadow[math.random(1,last)]
			
			value = shadow[rnd_idx]
			--change:
			shadow[rnd_idx] = shadow[last]
			shadow.count = last - 1
			return t[value]
		
	end
end

for e in iter_lottoforever(lws) do
	print(e)
end

Működő verzió


	if not self._shadow or #self._shadow == 0 then
			self._shadow = {}
			for k in ipairs(self.ST) do
				table.insert(self._shadow, k)
			end
		end
		rnd = math.random(1, #self._shadow)
		table.remove(self._shadow, rnd)
		self._act = self._shadow[rnd]

Hozzászólások

ez a shadow tabla szerintem csak felesleges memoriapazarlas. ha otoslottot jatszol, akkor van egy kisebb helyigenyu megoldas is:
van egy kepzeletbeli tombod, ahol kezdetben a tombindexek megyegyeznek a tarolt ertekkel. minden huzas utan a kihuzott elemet kiveszed, a kepzeletbeli tombot ujraindexeled. a kihuzott erteket pedig hozzaadod egy listahoz, amit novekvo sorrendbe rendezel.
a random szamokat 0 es kepzeletbeli_tomb.length-1 kozott generalod, majd vegignezed a mar kihuzott ertekek listajat, ha az aktualisan huzott szam nagyobb vagy egyenlo, mint a i-edik elem, akkor az aktualis szamhoz hozzaadsz egyet, es lepsz tovabb a listan.

adott tömb elemeiből szeretnél kiválasztani mindig egyet úgy, hogy még egyszer ugyanazt már ne, és közben hatékonyan? remélem jól értem.

akkor én így csinálnám: a véletlen index helyén és az utolsó elemet felcserélem, így az egyszer már kiválasztott elem a tömb végére kerül mindig, és az eddigi hossz -1 nagyságon nézem már a következőt csak, és véletlen számot is mindig eggyel kisebb intervallumon generálok.

részemről python-ban így nézne ki:


#!/usr/bin/python

import random

lista = ["szeppen1", "szippan2", "szappan3", "csappan4", "csuppan5"]

count = len(lista)-1

while count > -1:
    num = random.randint(0, count)
    lista[num], lista[count] = lista[count], lista[num]
    print lista[count]
    count -= 1