Python 781 731 605 579 Chars
Há muito mais e melhores respostas desde quando vi isso pela primeira vez, mas perdi muito tempo no meu script python, então vou publicá-lo de qualquer maneira, seria incrível ver sugestões para encurtá-lo ainda mais,
Edit: graças às sugestões de Ed H 2 caracteres picados, para ir mais longe, talvez eu precise reestruturar muita coisa aqui que vai levar algum tempo
s="e |nd|-We| a|-(Ooh|N| what|ive| go|ay it-|I|er|G|o |make5 |D| th| othH |A| tF|ing |nna |tell|'s been|'rS|-You|-N4| know|L5 up|PR | you|evHK>| how I'm feeling-|O, g7)|O)9gL, n4gL-(G7)|-I just wa>=53Gotta EuRHstaR-.|Q've8n eachBfor sFlong:r heart<Pch?but:;toFshy@sJInsidSwSboth8M<K?onQ8CSgame6we;go>plJ|9g79let5 down9runProuR6desHt59Ecry9sayKodbye9=P lie6hurt5-|\n|Q;nFstrangHs@love:8CSrules6sFdFI-A full commitment'sM I'mCink?of: wouldn't getCis fromPnyBguy0/AR if5Psk me3Don't = me5;toFbliR@see-..2211-/0..";i=83
exec"x,s=s.split('|',1);s=s.replace(chr(i),x);i-=1"*39
print s
Após a primeira vez que produzi manualmente a string (muito entediante), escrevi uma função para encontrar recursivamente a substituição do padrão que era mais lucrativa (nessa etapa), o que me deu uma solução, mas acabou aumentando o tamanho em 10 caracteres.
Portanto, tornei meu algoritmo um pouco menos ganancioso, em vez de fazer a classificação final apenas em 'caracteres reduzidos', classificando em uma função de 'caracteres reduzidos', 'comprimento do padrão' e 'contagens do padrão'
comprimento padrão = contagem de comprimento = contagem
rank = [(length-1)*count - length - 2] + lengthWeight * length + countWeight * count
Então eu perguntei a minha pobre laptop para executar infinitamente, atribuindo valores aleatórios para lengthWeight
e countWeight
e obter diferentes tamanhos de compressão final, e armazenar os dados para tamanhos mínimos de compressão em um arquivo
Em meia hora, surgiu a string acima (tentei mexer ainda mais para ver se era possível encurtar o código), e não diminuirá mais, acho que estou perdendo alguma coisa aqui.
aqui está o meu código para ele, também max_pattern
é muito lento (Nota: o código cospe uma string semelhante ao formulário na minha versão anterior da solução, eu trabalhei manualmente para obter o formulário atual, quer dizer manualmente, manualmente no shell python)
import itertools
global pretty
global split
split = False
pretty = False
# try to keep as much visibility as possible
def prefrange():
return range(32,127) + ([] if pretty else ([10, 9, 13] + [x for x in range(32) if x not in (10, 9, 13)] + [127]))
def asciichr():
return [chr(x) for x in prefrange()]
def max_pattern(s, o, lenw, numw):
l = len(s)
patts = []
for c in range(l/2+1,1,-1):
allsub = [s[i:i+c] for i in range(0, l, c)]
subcounts = [[a, s.count(a)] for a in allsub if len(a) == c]
repeats = [(x, y, ((c-o)*y - o*2 - c)) for x, y in subcounts if y > 1]
ranks = [(x, y, (z + lenw*c + numw*y)) for x,y,z in repeats if z > 0]
patts = patts + ranks
try:
return sorted(patts, key=lambda k: -k[2])[0]
except:
return None
def sep():
return '~~' if pretty else chr(127) + chr(127)
def newcharacter(s):
doable = [x for x in asciichr() if x not in s]
if len(doable) == 0:
doable = list(set(x+y for x in asciichr() for y in asciichr() if x+y not in s and x+y != sep()))
if len(doable) == 0:
return None
return doable[0]
def joined(s, l):
one = [x for x in l if len(x)==1]
two = [x for x in l if len(x)==2]
return ''.join(reversed(two)) + sep() + ''.join(reversed(one)) + sep() + s
def compress(s, l=[], lenw=0, numw=0):
newchr = newcharacter(s)
if newchr == None:
if not l:
return s
return joined(s,l)
else:
ptn = max_pattern(s, len(newchr), lenw, numw)
if ptn == None:
if not l:
return s
return joined(s, l)
s = s.replace(ptn[0], newchr)
s = ptn[0] + newchr + s
l.append(newchr)
return compress(s, l, lenw, numw)
def decompress(s):
lst2, lst, s = s.split(sep(),2)
li = [lst2[i:i+2] for i in xrange(0, len(lst2), 2)]+list(lst)
for c in li:
x, s = s.split(c, 1)
s = s.replace(c, x)
return s
def test(times):
import random
rnd = random.random
tested = {(1001, 1001): (10000, 10, False),}
org = open('text').read()
minfound = 1000
for i in xrange(times):
l,n = 1001,1001
while (l,n) in tested:
# i guess this would be random enough
xr = lambda: random.choice((rnd(), rnd()+rnd(), rnd()-rnd(), rnd()*random.choice((10,100,1000)), -1*rnd()*random.choice((10,100,1000)),))
n = xr()
l = xr()
sm = compress(org, l=[], lenw=l, numw=n)
try:
dc = decompress(sm)
except:
tested[l,n] = (len(sm), len(sm)/float(len(org)), 'err')
continue
tested[l,n] = (len(sm), len(sm)/float(len(org)), dc==org)
if len(sm) < minfound:
minfound = len(sm)
open('min.txt','a').write(repr(tested[l,n])+'\n')
print '~~~~~~~!!!!!!! New Minimum !!!!!!!~~~~'
return tested
if __name__ == '__main__':
import sys
split = False
try:
if sys.argv[2] == 'p':
pretty = True
except:
pretty = False
org = open(sys.argv[1]).read()
try:
l=float(sys.argv[3])
n=float(sys.argv[4])
except:
l,n=0,0
sm = compress(org,lenw=l,numw=n)
print 'COMPRESSED -->'
print sm, len(sm)
#open('new.py','w').write(sm)
print len(sm)/float(len(org))
print 'TRYING TO REVERT -->'
dc = decompress(sm)
#print dc
print dc==org