Skip to content

Instantly share code, notes, and snippets.

@Anaminus
Last active September 29, 2020 01:40
Show Gist options
  • Select an option

  • Save Anaminus/6242993 to your computer and use it in GitHub Desktop.

Select an option

Save Anaminus/6242993 to your computer and use it in GitHub Desktop.
Generates a function that maps an amount of integers to a single array index. Also generates a function that performs the inverse of the hash function.
--[[GenerateHashFunc
Generates a function that maps an amount of integers to a single array index.
Also generates a function that performs the inverse of the hash function.
Input: The first two arguments indicate the base of the input and the output,
respectively. If not given, they default to 0 for the input, and 1 for the
output.
Each argument afterwards represents one argument to be passed to the generated
hash function. The value of each argument indicates the number of possible
states for the hash argument.
Output: The hash function, and the dehash function.
Example:
-- 0-based input, 1-based output
hash, dehash = GenerateHashFunc ( 0,1, 2,3 )
hash ( 0, 0 ) --> 1
hash ( 0, 1 ) --> 2
hash ( 0, 2 ) --> 3
hash ( 1, 0 ) --> 4
hash ( 1, 1 ) --> 5
hash ( 1, 2 ) --> 6
dehash ( 1 ) --> 0, 0
dehash ( 2 ) --> 0, 1
dehash ( 3 ) --> 0, 2
dehash ( 4 ) --> 1, 0
dehash ( 5 ) --> 1, 1
dehash ( 6 ) --> 1, 2
]]
function GenerateHashFunc(ib, ob, ...)
ib = ib or 0
ob = ob or 1
local states = {...}
local n = #states
local err = 1
local args, hash, dehash, dret = "", "return ", "", "return "
for i = 1, n-1 do
local mult = 1
for s = i+1, n do
mult = mult * states[s]
end
err = err + mult
args = args .. "_" .. i .. ","
hash = hash .. "_" .. i .. "*" .. mult .. "+"
dehash = dehash .. "h/" .. mult .. "%" .. states[i] .. ","
dret = dret .. "_" .. i .. "-_" .. i .. "%1"
if ib < 0 then
dret = dret .. "-" .. -ib
elseif ib ~= 0 then
dret = dret .. "+" .. ib
end
dret = dret .. ","
end
args = args .. "_" .. n
hash = hash .. "_" .. n
dehash = dehash .. "h%" .. states[n]
dret = dret .. "_" .. n .. "-_" .. n .. "%1"
if ib < 0 then
dret = dret .. "-" .. -ib
elseif ib ~= 0 then
dret = dret .. "+" .. ib
end
local off = ob - err*ib
if off < 0 then
hash = hash .. "-" .. -off
elseif off ~= 0 then
hash = hash .. "+" .. off
end
dehash = "local " .. args .. "=" .. dehash .. " " .. dret
if ob > 0 then
dehash = "h=h-" .. ob .. " " .. dehash
elseif ob ~= 0 then
dehash = "h=h+" .. -ob .. " " .. dehash
end
return
loadstring(string.format([[return function(%s)%s end]], args, hash))(),
loadstring(string.format([[return function(h)%s end]], dehash))()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment