Module:Rank-n scale: Difference between revisions

From Xenharmonic Wiki
Jump to navigation Jump to search
Akselai (talk | contribs)
Created page with "local infobox = require('Module:Infobox') local p = {} function p.rotate_word(str, n) -- rotate word s by n steps return string.sub(str, n+1, #str) .. string.sub(str, 1,..."
 
ArrowHead294 (talk | contribs)
mNo edit summary
 
(3 intermediate revisions by one other user not shown)
Line 1: Line 1:
local p = {}
local infobox = require('Module:Infobox')
local infobox = require('Module:Infobox')


local p = {}
local function rotate_word(str, n) -- rotate word s by n steps
 
function p.rotate_word(str, n) -- rotate word s by n steps
     return string.sub(str, n+1, #str) .. string.sub(str, 1, n)
     return string.sub(str, n+1, #str) .. string.sub(str, 1, n)
end     
end     


function p.rotate_word_full(str)
local function rotate_word_full(str)
local full = {}
local full = {}
for i = 1, #str do
for i = 1, #str do
full[i] = p.rotate_word(str, i-1)
full[i] = rotate_word(str, i-1)
end
end
return full
return full
end
end


function p.bright_dark_chiral(str)
local function bright_dark_chiral(str)
local full = p.rotate_word_full(str)
local full = rotate_word_full(str)
local bright, dark = str, str
local bright, dark = str, str
for i = 2, #str do
for i = 2, #str do
Line 46: Line 46:
end
end


function p.table_length(T)
local function table_length(T)
local count = 0
local count = 0
for _ in pairs(T) do count = count + 1 end
for _ in pairs(T) do count = count + 1 end
Line 52: Line 52:
end
end


function p.abelianize(str) -- sorts string by letter. from rosetta code because I'm lazy.
local function abelianize(str) -- sorts string by letter. from rosetta code because I'm lazy.
local t = {} str:gsub("(%S)", function(c) t[#t+1]=c end) -- use "(.)" as pattern to preserve whitespace
local t = {} str:gsub("(%S)", function(c) t[#t+1]=c end) -- use "(.)" as pattern to preserve whitespace
     table.sort(t, function(a,b) return a<b end) -- implicitly
     table.sort(t, function(a,b) return a<b end) -- implicitly
Line 58: Line 58:
end
end


function p.list_step_varieties(str)
local function list_step_varieties(str)
local strstr = str .. str
local strstr = str .. str
local step_vars = {}
local step_vars = {}
Line 64: Line 64:
local r = {}
local r = {}
for j = 1, #str do
for j = 1, #str do
local u = p.abelianize(string.sub(strstr, j, j+i-1))
local u = abelianize(string.sub(strstr, j, j+i-1))
r[u] = true
r[u] = true
end
end
Line 72: Line 72:
end
end


function p.max_variety(str)
local function max_variety(str)
local lsv = p.list_step_varieties(str)
local lsv = list_step_varieties(str)
local max_var = 0
local max_var = 0
local is_strict = "yes"
local is_strict = "yes"
for i = 1, math.floor(#str/2) do
for i = 1, math.floor(#str/2) do
i_step_var = p.table_length(lsv[i])
i_step_var = table_length(lsv[i])
if i_step_var > max_var then
if i_step_var > max_var then
if max_var ~= 0 then
if max_var ~= 0 then
Line 88: Line 88:
end
end


function p.create_infobox(str)
function p.create_infobox(frame)
local mv = p.max_variety(str)
local scale = frame.args["scale"]
local bdc = p.bright_dark_chiral(str)
local mv = max_variety(scale)
local bdc = bright_dark_chiral(scale)
local brightest_mode
local brightest_mode
Line 115: Line 116:
{"Has strict variety?", mv["is strict?"]},
{"Has strict variety?", mv["is strict?"]},
}
}
return infobox.build_multilink(str, entries)
return infobox.build_multilink(scale, entries)
end
end



Latest revision as of 14:00, 19 May 2025

Module documentation[view] [edit] [history] [purge]
This module should not be invoked directly; use its corresponding template instead: Template:Rank-n scale.

This module generates an information table for scales of 3- or higher arity.


Introspection summary for Module:Rank-n scale 
Functions provided (1)
Line Function Params
90 create_infobox (invokable) (frame)
Lua modules required (1)
Variable Module Functions used
infobox Module:Infobox build_multilink

No function descriptions were provided. The Lua code may have further information.


local p = {}

local infobox = require('Module:Infobox')

local function rotate_word(str, n) -- rotate word s by n steps
    return string.sub(str, n+1, #str) .. string.sub(str, 1, n)
end    

local function rotate_word_full(str)
	local full = {}
	for i = 1, #str do
		full[i] = rotate_word(str, i-1)
	end
	return full
end

local function bright_dark_chiral(str)
	local full = rotate_word_full(str)
	local bright, dark = str, str
	for i = 2, #str do
		if bright > full[i] then
			bright = full[i]
		end
		if dark < full[i] then 
			dark = full[i]
		end
	end
	
	local bright2, dark2 = string.reverse(str), string.reverse(str)
	for i = 2, #str do
		local rev = string.reverse(full[i])
		if bright2 > rev then
			bright2 = rev
		end
		if dark2 < rev then 
			dark2 = rev
		end
	end
	if bright2 == bright then
		return {["blh"] = bright, ["brh"] = bright, ["dlh"] = dark, ["drh"] = dark, ["chiral"] = "no"}
	elseif bright2 < bright then
		return {["blh"] = bright, ["brh"] = bright2, ["dlh"] = dark, ["drh"] = dark2, ["chiral"] = "yes"}
	else
		return {["blh"] = bright2, ["brh"] = bright, ["dlh"] = dark2, ["drh"] = dark, ["chiral"] = "yes"}
	end
end

local function table_length(T)
	local count = 0
	for _ in pairs(T) do count = count + 1 end
	return count
end

local function abelianize(str) -- sorts string by letter. from rosetta code because I'm lazy.
	local t = {} str:gsub("(%S)", function(c) t[#t+1]=c end) -- use "(.)" as pattern to preserve whitespace
    table.sort(t, function(a,b) return a<b end) -- implicitly
    return table.concat(t)
end

local function list_step_varieties(str)
	local strstr = str .. str
	local step_vars = {}
	for i = 1, math.floor(#str/2) do
		local r = {}
		for j = 1, #str do
			local u = abelianize(string.sub(strstr, j, j+i-1))
			r[u] = true
		end
		step_vars[i] = r
	end
	return step_vars
end

local function max_variety(str)
	local lsv = list_step_varieties(str)
	local max_var = 0
	local is_strict = "yes"
	for i = 1, math.floor(#str/2) do
		i_step_var = table_length(lsv[i])
		if i_step_var > max_var then
			if max_var ~= 0 then
				is_strict = "no"
			end
			max_var = i_step_var
		end
	end
	return {["max variety"] = max_var, ["is strict?"] = is_strict}
end

function p.create_infobox(frame)
	local scale = frame.args["scale"]
	local mv = max_variety(scale)
	local bdc = bright_dark_chiral(scale)
	
	local brightest_mode
	local darkest_mode
	
	if bdc["chiral"] == "yes" then
		brightest_mode = {"Brightest mode", "LH " .. bdc["blh"] .. "\nRH ".. bdc["brh"]}
		darkest_mode = {"Darkest mode", "LH " .. bdc["dlh"] .. "\nRH ".. bdc["drh"]}
	else
		brightest_mode = {"Brightest mode", bdc["brh"]}
		darkest_mode = {"Darkest mode", bdc["drh"]}
	end
	
	local entries = {
		{"Scale structure"},
		
		{"Step pattern"},
		brightest_mode,
		darkest_mode,
		
		{"Is chiral?", bdc["chiral"]},
		
		{"Maximum variety", mv["max variety"]},
		{"Has strict variety?", mv["is strict?"]},
	}
	return infobox.build_multilink(scale, entries)
end

-- {"Mean variety", " "}
-- {"Is generator-offset?", " "},
-- {"Tuning ranges"},
-- {"Parent scales"},
-- {"Descendant scales"},

return p