Rubin
Rev 3, 55 bajtów
i=1
'S, OJ1*$HCH(#%0'.bytes{|e|puts "%x"%i+=e*130&9011}
Jako dalszy rozwój pomysłu Randomry, rozważ poniższą tabelę wyników i różnic. Tabela różnic może być skompresowana jak poprzednio i rozszerzona przez pomnożenie przez 65 = binarne 1000001 i zastosowanie maski 11001100110011. Jednak Ruby nie działa przewidywalnie z 8-bitowymi znakami (zwykle interpretuje je jako Unicode).
Co zaskakujące, ostatnia kolumna jest całkowicie parzysta. Z tego powodu w kompresji możemy wykonać przesunięcie praw do danych. Dzięki temu wszystkie kody mają 7 bitów ASCII. W rozszerzeniu po prostu mnożymy przez 65 * 2 = 130 zamiast 65.
Pierwsza kolumna jest również całkowicie równa. Dlatego w razie potrzeby możemy dodać 1 do każdego elementu (32 do każdego bajtu), aby uniknąć znaków kontrolnych. Niechciane 1 jest usuwane za pomocą maski 10001100110011 = 9011 zamiast 11001100110011.
Solution 59 of document linked in question
Start0001
Out Diff
2223 2222
2433 0210
2433 0000
4445 2012
6555 2110
6577 0022
6687 0110
6887 0200
8897 2010
aa99 2202
caa9 2010
cab9 0010
cbbb 0102
cdbd 0202
cddd 0020
Chociaż używam 15 bajtów do tabeli, tak naprawdę używam tylko 6 bitów każdego bajtu, co w sumie daje 90 bitów. W rzeczywistości istnieje tylko 36 możliwych wartości dla każdego bajtu, co w sumie daje 2,21E23 możliwości. To zmieściłoby się w 77 bitach entropii.
Rev 2, 58 bajtów, stosując podejście przyrostowe Randomry
i=0
'UPEIP@bPHPBETTEPRADT'.bytes{|e|puts "%x"%i+=e*65&819}
Wreszcie coś krótszego niż naiwne rozwiązanie. Przyrostowe podejście Randomry, z metodą obejścia z Rev 1.
Rev 1, 72 bajty, wersja 0 gry w golfa
Wprowadzono pewne zmiany w linii bazowej, aby uwzględnić zmianę kolejności kodu ze względu na grę w golfa, ale nadal wprowadzono to dłużej niż naiwne rozwiązanie.
i=0
'UPUIYD&!)$&V*).);c+*'.bytes{|e|i+=1;puts "%x"%(i/2*273+(e*65&819))}
Przesunięcia są kodowane w każdym znaku ciągu magicznego w bazie 4 w formacie BAC
, tj. Z 1-mi reprezentującymi prawy symbol, 16-mi reprezentującymi środkowy symbol, a lewy symbol ustawia się w pozycji 4. Aby je wyodrębnić, kod ascii jest mnożony przez 65 (binarny 1000001), aby dać BACBAC
, a następnie jest dodawany do 819 (binarny 1100110011), aby dać .A.B.C
.
Niektóre kody ascii mają ustawiony siódmy bit, tzn. Są o 64 wyższe od wymaganej wartości, aby uniknąć znaków kontrolnych. Ponieważ ten bit jest usuwany przez maskę 819, jest to nieistotne, z wyjątkiem sytuacji, gdy wartość C
wynosi 3, co powoduje przeniesienie. g
Trzeba to poprawić tylko w jednym miejscu (zamiast tego musimy użyć c
.)
Rev 0, wersja bez golfa
a= %w{000 010 000 201 100 100 011 021 110 120 011 112 111 221 211 221 122 123 112 222}
i=2
a.each{|e|puts "%x"%(i/2*273+e.to_i(16));i+=1}
Wynik
111
121
222
423
433
433
455
465
665
675
677
778
888
998
a99
aa9
abb
abc
bbc
ccc
Wyjaśnienie
Od następującego rozwiązania odejmuję linię bazową, podając przesunięcie, które przechowuję jako dane. Linia bazowa jest regenerowana jako liczba szesnastkowa w kodzie o i/2*273
(273 po przecinku = 111 szesnastkowo).
solution baseline offset
AAA AAA 000
ABA AAA 010
BBB BBB 000
DBC BBB 201
DCC CCC 100
DCC CCC 100
DEE DDD 011
DFE DDD 021
FFE EEE 110
FGE EEE 120
FGG FFF 011
GGH FFF 112
HHH GGG 111
IIH GGG 221
JII HHH 211
JJI HHH 221
JKK III 122
JKL III 123
KKL JJJ 112
LLL JJJ 222