Ir para conteúdo

Featured Replies

Postado
  • Este é um post popular.

Fala rapeize, eu me propus um desafio de criar uma forma de transformar uma string em números que possam ser anexados no storage.
Basicamente isso resolve o problema dos TFS anteriores de não conseguir salvar nomes de personagens no storage sem ter que fazer source editing.
PS: É óbvio que é mais fácil fazer source editing, mas o desafio era esse e como não é todo mundo que tem source tb pode ser bastante útil.

Eu não fechei o código certinho em funções, mas pretendo fazer em breve (agora preciso dormir) e aí eu edito o tópico aqui.
Nos testes q eu fiz ele conseguiu serializar e deserializar 5 mil caracteres em 0,01 segundo o que provavelmente faz dele o melhor serializador do gênero xD

Limitações: Ele só funciona com um range bem específico de strings, se vc quiser serializar qualquer outra coisa procure um serializador na internet.

image.thumb.png.083a2510c356f3cd6a2e9bea3a3288f8.png

Ele é capaz de processar tudo que tá dentro do retangulo vermelho


Ele só funciona com NO MÁXIMO +- 8k de caracteres, se vc quiser mais que isso vai precisar trocar a função table.concat e talvez umas outras coisinhas

O que ele faz: Transforma qualquer texto num numero, divide esse número em espaços de 32 bits e nas posições da memória consecutivas (no exemplo eu to usando uma tabela, mas poderia ser num storage, por ex). Depois ele ainda é capaz de retornar a string original a partir do serial gerado.

Funcionamento: por incrivel q pareça a lógica é bem simples, pega o código ascii de cada caractere da string, subtrai 21 para deixar o numero menor (21 é o máximo que a gente consegue encurtar pq 32 - 21 é 11 e 127 - 21 é 106, aí se eu lê-se 10 eu não saberia dizer se é o código do espaço ou dos 5 ultimos ali da tabela)

Os storages são int_32 então o maior valor q eu consigo colocar dentro de um storage é 2^31 - 1, aí tudo q eu faço é ir pegando os 10 ultimos numeros e vendo se eles cabem dentro desse limite máximo, se não couber eu pego os 9 ultimos, até caber dentro do limite. Aí eu jogo pra tabela e contabilizo quantas vezes eu to fazendo isso (isso vai ser importante depois qnd formos inserir ou pegar do storage)
Como eu já li os lines ultimos numeros da string, eu posso retirar eles e refazer o processo até não restar mais nada.
No final dentro da tabela tb vc vai ter no i o numero q vc soma no storage e no v o valor que deve ir pro storage.

Pra deserializar o processo é parecido, primeiro eu percorro a tabela concatenando os numeros na ordem inversa e depois vou vendo 2 a 2 se o numero é menor que 11 (nosso menor código ascii que representaria o espaço, lembrando que removemos 21 para encurtar). Se ele for menor então significa que estamos lidando com um dos ultimos numeros da tabela (10X), nesse caso temos que ler 3 numeros ao invés de só 2. Depois de passar tudo pra caractere e concatenar, nos é retornado a string inicial.


Código:
 

Spoiler

local entrada = "Night Wolf"
print("String to serialize: "..entrada)
local maxValue = (2^31) -1

local bench = os.clock()
local function reduceQnt(r, ...)
  for i = 1, arg.n do 
    arg[i] = arg[i] - r
  end
  arg.n = nil
  return arg
end

-- Serialize

local summ = table.concat(reduceQnt(21, entrada:byte(1, #entrada)))
local counter = 0
print("Serial: "..summ)
local tb = {}

repeat
  local lines = 10
  local tmp = summ:sub(-lines)
  
  while (tonumber(tmp) > maxValue or tmp:sub(1, 1) == "0") do
    lines = lines - 1
    tmp = summ:sub(-lines)
  end
  
  tb[#tb + 1] = tmp
  summ = summ:sub(1, -(lines+1))
  counter = counter + 1
until summ == ""

-- Unserialize
print("Unserializing...")
local serial = ""
for i = #tb, 1, -1 do
  serial = serial..tb[i]
end

local index = 1
local name = ""
while (index < serial:len()) do
  local char = serial:sub(index, index + 1)
  if tonumber(char) < 11 then
    char = serial:sub(index, index + 2)
    index = index + 1
  end
  index = index + 2
  name = name..string.char(char + 21)
end
print("-> "..name)

print(string.format("Benchmark: %.5f\n", os.clock() - bench))

 



Quem quiser testar é só modificar a variável entrada pra qualquer texto que vc quiser e dar run. O resultado aparece na tela a direita.
https://repl.it/repls/LongtermVioletTakin

Editado por xWhiteWolf
esqueci de colocar text highlight em Lua (veja o histórico de edições)

Todos os meus trabalhos importantes estão na seção "Sobre mim" no meu perfil; Dá uma passada lá!

"Há três caminhos para o fracasso: não ensinar o que se sabe, não praticar o que se ensina, e não perguntar o que se ignora." - São Beda

I7Pm6ih.png

(obg ao @Beeny por fazer essa linda sign <3)

Postado
  • Autor

Pra quem quiser a versão como função:
 

Spoiler

local function reduceQnt(r, ...)
	for i = 1, arg.n do 
		arg[i] = arg[i] - r
	end
	arg.n = nil
	return arg
end

-- Serialize
local function serializeString(data)
	if type(data) ~= 'string' or #data == 0 then return false end
	local summ = table.concat(reduceQnt(21, data:byte(1, #data)))
	local serial = ""
	local maxValue = (2^31) -1 -- int32
	
	repeat
		local lines = 10
		local tmp = summ:sub(-lines)	  
		while (tonumber(tmp) > maxValue or tmp:sub(1, 1) == "0") do
			lines = lines - 1
			tmp = summ:sub(-lines)
		end	  
		serial = tmp..serial -- this is where you can change to intput in a storage.
		summ = summ:sub(1, -(lines+1))
	until summ == ""
	
	return serial
end

-- Unserialize
local function unserializeString(serial)
	local index = 1
	local data = ""
	
	while (index < serial:len()) do
		local char = serial:sub(index, index + 1)
		if tonumber(char) < 11 then
			char = serial:sub(index, index + 2)
			index = index + 1
		end
		index = index + 2
		data = data..string.char(char + 21)
	end
	
	return data
end

-- Como usar:
local entrada = "Night Wolf"
local sr = serializeString(entrada)
print(sr)
print(unserializeString(sr))

 


https://repl.it/repls/LongtermVioletTakin

Todos os meus trabalhos importantes estão na seção "Sobre mim" no meu perfil; Dá uma passada lá!

"Há três caminhos para o fracasso: não ensinar o que se sabe, não praticar o que se ensina, e não perguntar o que se ignora." - São Beda

I7Pm6ih.png

(obg ao @Beeny por fazer essa linda sign <3)

  • 1 year later...

Participe da conversa

Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.

Visitante
Responder

Quem Está Navegando 0

  • Nenhum usuário registrado visualizando esta página.

Estatísticas dos Fóruns

  • Tópicos 96.9k
  • Posts 519.7k

Informação Importante

Confirmação de Termo