From: Tucker Johnson Date: Tue, 24 Jun 2025 13:15:26 +0000 (-0400) Subject: analysis completed X-Git-Url: https://git.newer.systems/?a=commitdiff_plain;p=setclass.git analysis completed --- diff --git a/core.lua b/core.lua index 2448465..ef8ae96 100644 --- a/core.lua +++ b/core.lua @@ -14,7 +14,7 @@ local function load_csv() return false end for line in f:lines() do - local dec, set, sc, icv = line:match("^(%d+),([0-9AB]+),([0-9AB]+),(<[0-9AB]+>)") + local dec, set, sc, icv = line:match("^(%d+),(.+),(.+),(.+)") if dec then lookup[tonumber(dec)] = { set = set, @@ -28,18 +28,32 @@ local function load_csv() return true end +local function parse_set(input) + local mask = 0 + for i = 1, #input do + local char = input:sub(i, i) + local pc = tonumber(char, 16) + if pc and pc <= 11 then + mask = bit.bor(mask, bit.lshift(1, pc)) + end + end + return mask +end -function M.get_visual_selection() - local start_pos = vim.fn.getpos("'<") - local end_pos = vim.fn.getpos("'>") - local lines = vim.fn.getline(start_pos[2], end_pos[2]) - if #lines == 0 then return "" end - if #lines == 1 then - return string.sub(lines[1], start_pos[3], end_pos[3]) +local function m5_bitmask(mask) + local m5Map = { [0]=0,5,10,3,8,1,6,11,4,9,2,7 } + local result = 0 + for i = 0, 11 do + if bit.band(mask, bit.lshift(1, i)) ~= 0 then + local mapped = m5Map[i] + result = bit.bor(result, bit.lshift(1, mapped)) + end end - lines[1] = string.sub(lines[1], start_pos[3]) - lines[#lines] = string.sub(lines[#lines], 1, end_pos[3]) - return table.concat(lines, "\n") + return result +end + +local function complement(mask) + return bit.band(bit.bnot(mask), 0xFFF) end function M.analyze_set(inputStr) @@ -47,41 +61,12 @@ function M.analyze_set(inputStr) if not csvLoaded then local success = load_csv() if not success then - print("[SetClass] CSV not found — generating now...") + vim.notify("generating csv...") generator.generate_csv(csvPath) assert(load_csv(), "Failed to load generated set-classes.csv") end end - local function parse_set(input) - input = input:upper():gsub("[^0-9ABCDEF]","") - local mask = 0 - for i =1, #input do - local char = input:sub(i, i) - local pc = tonumber(char, 16) - if pc and pc <= 11 then - mask = bit.bor(mask, bit.lshift(1, pc)) - end - end - return mask - end - - local function m5_bitmask(mask) - local m5Map = { [0]=0,5,10,3,8,1,6,11,4,9,2,7 } - local result = 0 - for i = 0, 11 do - if bit.band(mask, bit.lshift(1, i)) ~= 0 then - local mapped = m5Map[i] - result = bit.bor(result, bit.lshift(1, mapped)) - end - end - return result - end - - local function complement(mask) - return bit.band(bit.bnot(mask), 0xFFF) - end - local mask = parse_set(inputStr) return { @@ -94,4 +79,45 @@ function M.analyze_set(inputStr) } end +function M.get_visual_selection() + local _, start_row, start_col, _ = unpack(vim.fn.getpos("'<")) + local _, end_row, end_col, _ = unpack(vim.fn.getpos("'>")) + + -- Ensure proper order + if start_row > end_row or (start_row == end_row and start_col > end_col) then + start_row, end_row = end_row, start_row + start_col, end_col = end_col, start_col + end + + local lines = vim.api.nvim_buf_get_lines(0, start_row - 1, end_row, false) + + if #lines == 0 then return "", {}, {} end + + lines[1] = string.sub(lines[1], start_col) + if #lines > 1 then + lines[#lines] = string.sub(lines[#lines], 1, end_col) + else + lines[1] = string.sub(lines[1], 1, end_col - start_col + 1) + end + + local selection = table.concat(lines, "\n") + + local collections = {} + local delimiters = {} + local allHex = {} + + for hex, delim in selection:gmatch("([0-9A-Fa-f]+)([^0-9A-Fa-f]*)") do + table.insert(collections, hex) + table.insert(allHex, hex) + if delim ~= "" and not selection:match(delim .. "$") then + table.insert(delimiters, delim) + end + end + + if #collections > 1 then + table.insert(collections, table.concat(allHex)) + end + return selection, collections, delimiters +end + return M diff --git a/generator.lua b/generator.lua index 7eda678..72deb9e 100644 --- a/generator.lua +++ b/generator.lua @@ -1,8 +1,6 @@ -local M = {} - local bit = require("bit") +local M = {} --- Convert bitmask to PC list (integers) local function mask_to_pcs(mask) local pcs = {} for i = 0, 11 do @@ -13,8 +11,7 @@ local function mask_to_pcs(mask) return pcs end --- Convert PC list to hex string (e.g., 10 -> A, 11 -> B) -local function pcs_to_hex(pcs) +local function format_set(pcs) local out = {} for _, pc in ipairs(pcs) do table.insert(out, string.format("%X", pc)) @@ -22,12 +19,10 @@ local function pcs_to_hex(pcs) return table.concat(out) end --- Transpose bitmask left by n local function transpose(mask, n) return bit.band(bit.lshift(mask, n) + bit.rshift(mask, 12 - n), 0xFFF) end --- Invert a bitmask (I-transform) local function invert(mask) local result = 0 for i = 0, 11 do @@ -39,7 +34,6 @@ local function invert(mask) return result end --- Find prime form of bitmask local function prime_form_bitmask(mask) local min = 0xFFF + 1 for i = 0, 11 do @@ -51,7 +45,6 @@ local function prime_form_bitmask(mask) return min end --- Generate ICV from bitmask local function icv_from_mask(mask) local pcs = mask_to_pcs(mask) local icv = {0, 0, 0, 0, 0, 0} @@ -68,21 +61,21 @@ local function icv_from_mask(mask) for _, v in ipairs(icv) do table.insert(out, string.format("%X", v)) end - return "<" .. table.concat(out) .. ">" + return table.concat(out) end --- Generate CSV with format: decimal,pc_order,prime_form,icv function M.generate_csv(path) local out = io.open(path, "w") local total = 4096 for mask = 0, total - 1 do - local pcs = mask_to_pcs(mask) - if #pcs > 0 then - local pc_order = pcs_to_hex(pcs) + if mask > 0 then + local pc_order = format_set(mask_to_pcs(mask)) local prime_mask = prime_form_bitmask(mask) - local prime_form = pcs_to_hex(mask_to_pcs(prime_mask)) + local prime_form = format_set(mask_to_pcs(prime_mask)) local icv = icv_from_mask(mask) out:write(string.format("%d,%s,%s,%s\n", mask, pc_order, prime_form, icv)) + else + out:write(string.format("%d,%s,%s,%s\n", mask, "null set", "null set", "null set")) end end out:close() diff --git a/init.lua b/init.lua index 5365bd0..b33604f 100644 --- a/init.lua +++ b/init.lua @@ -2,15 +2,21 @@ local M = {} local core = require("setclass.core") function M.analyze_selection() - local input = core.get_visual_selection() - local result = core.analyze_set(input) - if result then - vim.notify(" input: " .. result.input .. " (" .. result.decimal .. ")") - vim.notify(" set class: " .. result.set_class .. " " .. result.interval_class_vector) - vim.notify("abs. complement: " .. result.complement_class) - vim.notify(" m5 class: " .. result.m5_class) - else - vim.notify("unable to parse collection") + local input, collections, delimiters = core.get_visual_selection() + local analysis = {} + for i = 1, #collections do + table.insert(analysis, core.analyze_set(collections[i])) + end + for i = 1, #analysis do + if i == #analysis then + vim.notify("UNION", 3) + else + vim.notify("SUBSET" .. i, 3) + end + vim.notify("input: " .. analysis[i].input .. " (" .. analysis[i].decimal .. ")") + vim.notify("set class: " .. analysis[i].set_class .. " <" .. analysis[i].interval_class_vector ..">") + vim.notify("abs. comp: " .. analysis[i].complement_class) + vim.notify("m5 class: " .. analysis[i].m5_class) end end