Python 3 , 177 170 163 130 bytes
lambda a,b:s(d(a)^d(b))
def s(n,x=0,s=''):
while n:n-=1;s+=chr(n%256);n>>=8
return s
def d(n,c=0):
while s(c)!=n:c+=1
return c
Experimente online!
-14 bytes graças a notjagan
-33 bytes graças a Leaky Nun (e endianness comutado)
Não tenho negócios tentando jogar golfe em Python, mas não queria usar Lua, pois esse método precisa de números inteiros exatos grandes para funcionar com picadas de comprimento razoável. (Nota: o algoritmo ainda é muito lento ao aumentar o comprimento da string.) Isso é apenas para fornecer uma resposta;)
Cada sequência é auto-inversa e a sequência vazia é a identidade. Isso simplesmente executa xor sob uma simples bijeção entre cadeias e números inteiros não negativos. s
é uma função auxiliar que calcula a bijeção (apenas de sentido único) e d
é a inversa.
Versão não lenta (148 bytes, cortesia de Leaky Nun):
lambda a,b:s(d(a)^d(b))
def s(n,x=0,s=''):
while n:n-=1;s=chr(n%256)+s;n>>=8
return s
def d(n,c=0):
while n:c=c*256+ord(n[0])+1;n=n[1:]
return c
Experimente online!
Vou sequestrar isso também para uma cartilha de teoria de grupos.
Qualquer inversa à direita é uma inversa à esquerda: inv (a) + a = (inv (a) + a) + e = (inv (a) + a) + (inv (a) + inv (inv (a))) = Inv (a) + (a + inv (a)) + inv (inv (a)) = (inv (a) + e) + inv (inv (a)) = inv (a) + inv (a (inv)) ) = e
Isso também significa que a é um inverso de inv (a) .
Qualquer identidade certa é uma identidade esquerda: e + a = (a + inv (a)) + a = a + (inv (a) + a) = a
A identidade é única, dada outra identidade f : e = e + f = f
Se a + x = a então x = e : x = e + x = (inv (a) + a) + x = inv (a) + (a + x) = inv (a) + a = e
Inversos são únicos, se a + x = e então: x = e + x = (inv (a) + a) + x = inv (a) + (a + x) = inv (a) + e = inv (a )
Seguir as provas deve facilitar bastante a construção de contra-exemplos para soluções propostas que não satisfazem essas proposições.
Aqui está um algoritmo mais natural que eu implementei (mas não joguei golfe) em Lua . Talvez isso dê uma ideia a alguém.
function string_to_list(s)
local list_val = {}
local pow2 = 2 ^ (math.log(#s, 2) // 1) -- // 1 to round down
local offset = 0
list_val.p = pow2
while pow2 > 0 do
list_val[pow2] = 0
if pow2 & #s ~= 0 then
for k = 1, pow2 do
list_val[pow2] = 256 * list_val[pow2] + s:byte(offset + k)
end
list_val[pow2] = list_val[pow2] + 1
offset = offset + pow2
end
pow2 = pow2 // 2
end
return list_val
end
function list_to_string(list_val)
local s = ""
local pow2 = list_val.p
while pow2 > 0 do
if list_val[pow2] then
local x = list_val[pow2] % (256 ^ pow2 + 1)
if x ~= 0 then
x = x - 1
local part = ""
for k = 1, pow2 do
part = string.char(x % 256) .. part
x = x // 256
end
s = s .. part
end
end
pow2 = pow2 // 2
end
return s
end
function list_add(list_val1, list_val2)
local result = {}
local pow2 = math.max(list_val1.p, list_val2.p)
result.p = pow2
while pow2 > 0 do
result[pow2] = (list_val1[pow2] or 0) + (list_val2[pow2] or 0)
pow2 = pow2 // 2
end
return result
end
function string_add(s1, s2)
return list_to_string(list_add(string_to_list(s1), string_to_list(s2)))
end
A idéia é basicamente dividir a string com base na potência de dois componentes de seu comprimento e tratá-los como campos com um componente ausente representando zero e cada componente não ausente representando números de 1 a 256 ^ n, então 256 ^ n + 1 total de valores. Em seguida, essas representações podem ser adicionadas módulo módulo 256 ^ n + 1.
Nota: Esta implementação de Lua terá problemas de estouro numérico para cadeias de tamanhos maiores que 7. Mas o conjunto de cadeias de comprimento 7 ou menos é fechado nesta adição.
Experimente online!