모듈:Random: 두 판 사이의 차이

리버티게임, 모두가 만들어가는 자유로운 게임
(메서드 sample 추가)
편집 요약 없음
 
(같은 사용자의 중간 판 2개는 보이지 않습니다)
37번째 줄: 37번째 줄:
math.randomseed(seed)
math.randomseed(seed)
if n ~= nil then
return math.random(unpack{m, n})
return math.random(m, n)
elseif m ~= nil then
return math.random(m)
else
return math.random()
end
end
end


174번째 줄: 168번째 줄:
     -- sep로 문자열을 분할하여 테이블로 변환하고 앞뒤 공백 제거
     -- sep로 문자열을 분할하여 테이블로 변환하고 앞뒤 공백 제거
     local items = {}
     local items = {}
     for item in string.gmatch(text, "([^" .. sep .. "]+)") do
     for item in mw.text.gsplit(text, sep, true) do
         local trimmedItem = item:match("^%s*(.-)%s*$") -- 앞뒤 공백 제거
         local trimmedItem = mw.text.trim(item) -- 앞뒤 공백 제거
         table.insert(items, trimmedItem)
         table.insert(items, trimmedItem)
     end
     end

2023년 10월 23일 (월) 00:12 기준 최신판


모듈 설명문서[보기] [편집] [역사] [새로 고침]

난수를 다루는 lua함수를 모아둔 모듈입니다.

리버티위키를 비롯한 미디어위키 사이트는 구문분석기 캐싱이 허용되어 있기에 별도의 설정을 거치지 않으면 아무리 새로고침을 해도 같은값이 나오게끔 되어있습니다.

해당 모듈을 래핑하는 틀을 만들거나 {{#invoke:random}}를 사용하는 문서에 {{캐싱방지}}를 추가해주세요.

rand[원본 편집]

이 부분의 본문은 틀:rand입니다.

choose[원본 편집]

이 부분의 본문은 틀:choose입니다.

lotto[원본 편집]

{{#invoke:random|lotto|a|b}}일 때, 1부터 b까지의 자연수 중 a개를 중복 없이 추출합니다.

사용법[원본 편집]

파라미터별 설명[원본 편집]

{{#invoke:random|lotto|추출할 표본수|전체갯수|추출할 보너스 갯수|표본 구분자|보너스 구분자|정렬 여부}}

파라미터 기본값[원본 편집]

{{#invoke:random|lotto|6|45|1|, | + |true}}

예시[원본 편집]

기본 예시[원본 편집]

code_blocks 코드
{{#invoke:random|lotto}}
code
낙서장에서 확인
description 결과
13, 18, 24, 25, 27, 31 + 39

보너스를 추출하지 않는 예시[원본 편집]

code_blocks 코드
{{#invoke:random|lotto|||0}}
code
낙서장에서 확인
description 결과
7, 8, 9, 24, 36, 42

0부터 10까지 숫자를 랜덤나열한 예시[원본 편집]

code_blocks 코드
{{#invoke:random|lotto|10|10|0|-||false}}
code
낙서장에서 확인
description 결과
6-3-8-2-9-7-10-5-1-4

sample[원본 편집]

가중치를 설정할 수 없고 문자열로 구분 가능한 choose입니다.

사용법[원본 편집]

파라미터별 설명[원본 편집]

{{#invoke:random|sample|텍스트|구분할 문자열}}

파라미터 기본값[원본 편집]

{{#invoke:random|sample||,}}


예시[원본 편집]

기본 예시[원본 편집]

code_blocks 코드
{{#invoke:random|sample|1,2,3,4,5}}
code
낙서장에서 확인
description 결과
4

구분자를 변경하는 예시[원본 편집]

code_blocks 코드
{{#invoke:random|sample|1-2-3-4-5|-}}
code
낙서장에서 확인
description 결과
1

특정 분류의 랜덤 게임을 출력하는 예시[원본 편집]

code_blocks 코드
{{#invoke:random|sample|{{#dpl:|category=함정 피하기 게임|namespace|format=,%PAGE%//}}|//}}
code
낙서장에서 확인
description 결과
짧은낚시


local p = {}

function p.randomseed()
    return math.floor(os.time() * os.clock() % 1000000)
end

function p._rand(m, n, o)
	local seed, key
	
	if type(m) == "table" then
		seed = tonumber(m.seed)
		key = tonumber(m.key)
		m = nil
		n = nil
	elseif type(n) == "table" then
		seed = tonumber(n.seed)
		key = tonumber(n.key)
		m = tonumber(m)
		n = nil
	elseif type(o) == "table" then
		seed = tonumber(o.seed)
		key = tonumber(o.key)
		m = tonumber(m)
		n = tonumber(n)
	else
		m = tonumber(m)
		n = tonumber(n)
	end


	if (seed or 0) == 0 then
		seed = p.randomseed()
	elseif (key or 0) ~= 0 then
		seed = seed * (key or p.randomseed())
	end
	
	math.randomseed(seed)
	
	return math.random(unpack{m, n})
end

function p.rand(frame)
	return p._rand(frame.args[1], frame.args[2], frame.args)
end

function p._choose(frame)
	local len = 0
	
	for index, value in ipairs(frame.args) do
		len = index
	end
	
	return frame.args[p._rand(len, frame.args)]
end

function p.choose(frame)
	return p._choose(frame:getParent())
end

-- 테이블을 문자열로 변환
function p.str_join(list, delimiter)
    local len = #list
    if len == 0 then
        return ""
    end
    local string = list[1]
    for i = 2, len do
        string = string .. delimiter .. list[i]
    end
    return string
end

-- 테이블의 일부를 추출
function p.table_slice(arr,start,stop)
    local res = {}
    local n = #arr

    start = start or 1
    stop = stop or n

    -- 음수
    if start < 0 then
        start = n + start + 1
    end
    if stop < 0 then
        stop = n + stop + 1
    end

    -- start보다 stop이 큰 경우
    if stop < start then
        stop = start
    end

    -- 루프
    for i = start, stop, 1 do
        res[#res+1] = arr[i]
    end

    return res

end


-- n개의 숫자를 무작위로 뽑아서 반환
function p._sampling(n, total)
    local numbers = {}
    for i = 1, total do
        numbers[i] = i
    end

    -- 숫자를 무작위로 섞기
    math.randomseed(p.randomseed())
    for i = total, 1, -1 do
        local r = math.random(i)
        numbers[i], numbers[r] = numbers[r], numbers[i]
    end

    -- 처음 n개 숫자 선택
    local sampled = {}
    for i = 1, n do
        table.insert(sampled, numbers[i])
    end

    return sampled
end

-- {{#invoke:random|lotto}}
function p.lotto(frame)
    local n = tonumber(frame.args[1]) or 6
    local total = tonumber(frame.args[2]) or 45
    local bonus = tonumber(frame.args[3]) or 1
    local sep = frame.args[4] or ", "
    local bonusSep = frame.args[5] or " + "
    local sort = frame.args[6] or "true"

    if n and total and n <= total and n > 0 then
        local allNums = p._sampling(n + bonus, total)
        -- 추출한 숫자들 중 n개 추출 및 정렬
        local nums = p.table_slice(allNums, 1, n)
        if sort == "true" then
            table.sort(nums)
        end

        -- bonus만큼 추출
        local bonusNums = p.table_slice(allNums, n + 1, n + bonus)
        if sort == "true" then
            table.sort(bonusNums)
        end

        -- 문자열로 변환
        local result = p.str_join(nums, sep)
        -- 보너스 번호가 있으면 추가
        if bonus > 0 then
            result = result .. bonusSep .. p.str_join(bonusNums, sep)
        end

        return result
    else
        return "{{색깔|Error: 파라미터가 올바르지 않습니다. 1 <= n <= total를 만족해야 합니다.|red}}"
    end
end

-- text에서 sep로 구분된 문자열 중 하나를 무작위로 반환합니다. 각 항목의 앞뒤 공백은 제거됩니다.
function p.sample(frame)
    local text = frame.args[1] or ""
    local sep = frame.args[2] or ","  -- 기본 구분자는 콤마입니다.

    -- sep로 문자열을 분할하여 테이블로 변환하고 앞뒤 공백 제거
    local items = {}
    for item in mw.text.gsplit(text, sep, true) do
        local trimmedItem = mw.text.trim(item) -- 앞뒤 공백 제거
        table.insert(items, trimmedItem)
    end

    -- 테이블에서 무작위로 하나의 항목을 선택하여 반환
    local index = p._rand(1, #items)
    return items[index]
end

return p