Difference between revisions of "Module:Ulam spiral"

From blackwiki
Jump to navigation Jump to search
blackwiki>Gts-tg
(Module for creating Ulam spirals)
 
blackwiki>Gts-tg
(αριθμός to number)
Line 111: Line 111:
 
             number = math.floor(data[row .. ':' .. column])
 
             number = math.floor(data[row .. ':' .. column])
 
  --if bgcolor ~= '' and bgcolor ~= 'nil' then
 
  --if bgcolor ~= '' and bgcolor ~= 'nil' then
  result = result .. '[[' .. number .. ' (αριθμός)|' .. number .. ']]'
+
  result = result .. '[[' .. number .. ' (number)|' .. number .. ']]'
 
             --else 
 
             --else 
 
  --    result = result .. number
 
  --    result = result .. number

Revision as of 15:21, 2 September 2017

Implements {{Ulam spiral}}


-- Generate Ulam spiral based on primes, fibonacci, triangular numbers etc.
-- Gts@el wiki, Sep. 2017

local p = {}

-- determine whether number is prime
-- params: n (number)
-- return: boolean
local function is_prime(n)
    for i = 2, n^(1/2) do
        if (n % i) == 0 then
            return false
        end
    end
    return true
end

-- determine whether number is triangular
-- params: n (number)
-- return: boolean
local function is_triangular(n)
   x = (math.sqrt(8*n + 1) - 1) / 2
   return (x % 1 == 0)
end

-- determine whether number is part of standard fibonacci sequence
-- params: n (number)
-- return: boolean
local function is_fib(n)
    if n == 0 then
      return true
    end

    phi = 0.5 + (0.5 * math.sqrt(5.0))
    a = phi * n
    return math.abs(math.floor(a+0.5) - a) < 1.0 / n
end

-- determine total divisors of a number
-- params: n (number)
-- return: int
local function divisors(n)
    limit = n;
    total = 0;

    if n == 1 then
       return 1
    end

    for i = 1, limit-1 do
        if n % i == 0 then
            limit = n / i
            if limit ~= i then
               total = total + 1
            end

            total = total + 1
        end
    end

    return total
end

-- convert values to wikitable. The wikitable string is preproccessed in frame.
-- params: data (dictionary), size (int), fontSize (int)
-- return: string object
local function wikitable(data, size, fontSize)
	local fontSize = 1 --em
    if tonumber(size) > 10 and tonumber(size) <=30 then
       fontSize = '0.8'
    elseif tonumber(size) > 30 and tonumber(size) <= 50 then
       fontSize = '0.6'
    elseif tonumber(size) > 50 then   
    	fontSize = '0.3'
    end
	
	local result = '{| style="font-size:' .. fontSize .. 'em;text-align:center"'

    -- background colour of a number corresponding to number of divisors
    divi = {
                 [2] = 'lightskyblue',
                 [3] = '#86f99f',
                 [4] = '',
                 [5] = '',
                 [6] = '',
                 [7] = '',
                 [8] = '',
                 [9] = '',
               }

    -- create wikitable
	for row=0, size-1 do
		result = result .. '\n|-\n|'
		for column=0, size-1 do
            if column > 0 then
               result = result .. '||'
            end

            number = data[row .. ':' .. column]
            bgcolor =''

			divtotal = divisors(number)
            if divtotal > 60 then
              bgcolor = '#f98686'
            else
              bgcolor = tostring(divi[divtotal])
            end

            result = result .. 'title="' .. math.floor(number) .. '" style="border-radius:50%;background-color:'.. bgcolor .. ';color:black !important"|'

            number = math.floor(data[row .. ':' .. column])
 			--if bgcolor ~= '' and bgcolor ~= 'nil' then
 				result = result .. '[[' ..	number .. ' (number)|' .. number .. ']]'
            --else  		
 			--    result = result .. number
 			--end
        end
	end

	result = result .. '\n|}'

    -- preprocess string in frame and render table
    local frame = mw.getCurrentFrame()
 	result = frame:preprocess(result)

	return result
end

-- calculate ulam spiral value for each x,y tabular point.
-- algorithm concept based on Python version at GPL 3 https://rosettacode.org/wiki/Ulam_spiral_(for_primes)#Python
-- use of bitwise ops was attempted but Mediawiki Scribunto Lua doesn't seem to like them
-- params: n (int), x (int), y (int), start (int)
-- return: int
local function cell(n, x, y, start)
	local d = 0

	local x = x - math.floor((n - 1) /2)
	local y = y - math.floor(n / 2)

	l = 2 * math.max(math.abs(x), math.abs(y))

	if y <= x then
		d = (l*3) + x + y
	else
		d = l - x - y
	end

	return math.pow(l - 1, 2) + d + start - 1
end

-- prepare spiral display for output type (i.e. wikitable, coords only, etc)
-- params: size (int), start (int)
-- return: mixed
local function show_spiral(size, start)
   local result = {}

   for i=0, size-1 do
       for x=0, i do
         for y=0, i do
           result[x .. ':' .. y] = cell(size, x, y, start)
         end
      end
   end

   return wikitable(result, size)
end

-- main
-- params: frame
-- return: mixed
function p.ulam(frame)
	local size = tonumber(frame.args[1])
	local start = tonumber(frame.args[2])
    
    if size > 70 then
       return 'Maximum allowed size is 70x70'	
    end
    
	return show_spiral(size, start)
end

return p