Ostatnie wyzwanie ( Pixel-art, odcinek 1: pokaz Super Mario ) było tylko treningiem ... (i ukończyłeś je w niesamowity sposób, dzięki!)
Tym razem musisz trochę popracować. Musisz wyświetlić całą pierwszą mapę świata Super Mario bros na NES, bez wrogów i bez Mario.
Twój program lub funkcja musi wyświetlać wszystkie piksele poniższego obrazu LUB tworzyć plik obrazu podobny do niego (BMP, PNG lub GIF).
Twój program nie może w żaden sposób uzyskiwać dostępu do Internetu.
Dane wyjściowe można powiększać, jeśli chcesz, a piksele mogą być elementami ASCII lub HTML, jeśli chcesz, o ile mają odpowiedni kolor.
Oto model, którego musisz przestrzegać:
Cały obraz: http://i.stack.imgur.com/2kfVc.png
Zestaw klocków (jeśli jest potrzebny): http://img.ctrlv.in/img/14/10/19/5443f44c7eb78.png
Możesz stworzyć swój własny zestaw klocków, jego podzbiór lub nadzbiór.
Możesz użyć zestawu klocków jako osobnego pliku obrazu lub dołączyć go do kodu (na przykład w base64). Jeśli jest osobny, dodaj jego wynik w bajtach do swojego wyniku.Mapa ze współrzędnymi: http://goo.gl/c8xJIx lub http://img.ctrlv.in/img/14/10/19/544373adc9f64.png
Kolory:
Błękitny: # 5C94FC Czarny: # 000000 Różowy: # FCBCB0 (dla bloków i zamku) Brązowy: # C84C0C (dla bloków i zamku) Pomarańczowy: # FC9838 (dla bloku „?”) Jasnozielony: # 80D010 (na krzaki, góry, maszt, osnowę) Ciemnozielony: # 00A800 (na krzaki, góry, maszt, osnowę) Biały: #FCFCFC (chmury) Jasnoniebieski: # 3CBCFC (chmury)
Najkrótsza odpowiedź wygrywa.
EDYCJA: Będą dwie tablice wyników, jedna, w której wyniki są liczone w bajtach, a druga, gdzie są liczone w postaciach.
Powodzenia!
PS: Oto kilka uwag, które mogą pomóc w optymalizacji programu:
- Chmury, krzewy i góry mają powtarzający się wzór (co 48 kolumn)
- Latające klocki są obecne tylko na liniach 4 i 8
- Każdy kafelek lub duszek mapy używa maksymalnie 4 kolorów (w tym niebieskiego lub przezroczystego, w zależności od tego, jak to widzisz)
- Krzewy to po prostu „wierzchołek chmur” z inną paletą kolorów
- Pojedyncze, podwójne i potrójne krzewy / chmury można łatwo utworzyć przy użyciu tego samego mini zestawu 16 x 16 pikseli. Dotyczy to również pojedynczych i potrójnych gór
Odpowiedzi:
Kod maszynowy x86,
1729161914681382 bajtówJak to działa: Kafelki są generowane przez kombinację kompresji RLE, obrazów 2-bitowych i kodu proceduralnego. Po wygenerowaniu kafelków w pamięci program tworzy macierz indeksów kafelków. Najpierw jest ładowane powtarzające się tło. Następnie rury, pływające bloki, piramidy i maszt flagowy są rysowane proceduralnie. Rury, wzgórza, krzewy i piramidy mogą rozciągać się pod ziemią, ale są przykryte, gdy kolejne płytki kamienne zostaną zapisane. Wreszcie wartości kafelków zamku są po prostu kopiowane do właściwej lokalizacji. Aby wygenerować plik obrazu, nagłówek BMP i paleta są przechowywane w pliku jako dane i zapisywane jako pierwsze. Następnie program przechodzi przez macierz, zapisując odpowiedni wiersz z odpowiedniego kafelka dla każdej pozycji.
Sposób użycia: Uruchom mario.com, wygeneruje „m.bmp”, standardowy plik obrazu BMP. Plik jest tworzony jako plik ukryty, ponieważ skończył się nim mniej bajtów.
Pobierz plik ZIP zawierający kod źródłowy i plik binarny oraz dane wyjściowe.
Kod zestawu do wygenerowania pliku wykonywalnego:
źródło
Javascript zminimalizowane (*):
1285 1258 1253 1205 11861171 znaków(*) Zminimalizowane za pomocą Closure, RegPack i ObfuscaTweet, jak sugeruje xem
Wersja Unicode ma rozmiar 4549 bajtów, bez ObfuscaTweet (tylko Closure i Regpack), rozmiar to 2251 bajtów.
Historia:
1285 -> 1258: zmienna
A
dla 48 (thx @ hsl), połączyła niektórefor
pętle, połączyła sięmt()
imu()
używając indeksów kafelków zamiast ciągów kafelków zoptymalizowała png z PNGOUT1258 -> 1253: scalono więcej
for
pętli; przemianowanymt()
nar()
; usunięto niepotrzebne aparaty ortodontyczne; zmiennaB
dla 16; zdefiniowanie 16 nieużywanych duszków CSS (zastępuje 32A
); pokazano 1 nieużywany wiersz (zastępuje 14 naB
); usunięta funkcjae()
; skróconyt()
,g()
,c()
; używającfor(i=0;i<n;)f(i++)
zamiastfor(i=0;i<n;i++)f(i)
tam, gdzie to możliwe1253 -> 1205: przeniesiono styl nadwozia na część CSS zamiast
<body style=...>
; zastąpił niektórefor
pętlef
połączeniami; zoptymalizowane funkcjer
,q
;</head><body>
wydaje się również niepotrzebny<html><head>
;t(i)
usunięto funkcję mapowania CSS; Nazwy CSSb0
…b31
zamiasta
…z
,aa
…ff
1205 -> 1186:
n
zmieniono nazwę funkcji naN
; nowa funkcjan
działająca na tablicy z kodowaniem delta1186 -> 1171: wzgórza i osnowy można w dowolnym momencie narysować jako „duże”, dolne partie zostaną zasłonięte przez kamienne bloki; używać
d
zarówno do chmur, jak i krzewów; usunięto niepotrzebne średnikiTo jest próba proceduralna. Wszędzie są wzory, jedna z magicznych liczb to 48 (przerwa między chmurami, krzakami i górami). Zestaw klocków jest kodowany jako ciąg adresu URL danych Base64 i używany jako arkusz stylów CSS. W JavaScript, tablica 212x14
m
jest wypełniona indeksami kafelków. Zobacz skomentowaną wersję nieuprawnioną, aby uzyskać więcej informacji.Działa w Chrome 38 (Ctrl + T dla nowej karty, Ctrl + Shift + J dla konsoli javascript, wklej tam kod) i Firefox 33 (jeśli jest owinięty tagami javascript HTML). Istnieje również wersja bin JS .
Jest jeszcze miejsce na optymalizacje, opublikuję aktualizacje i byłoby miło, gdyby niektórzy ludzie JS / CSS / HTML mogli sugerować optymalizacje / poprawki.
Zminimalizowane:
Unminified and commented:
źródło
function l(i,j,s){for(k=0;k<j;k++)n(i+k*W,s);}
może być skrócony poprzez wyodrębnienie k ++ do funkcji, tak myślę? Podobnie może być następny wiersz z j.Python3
1638157616161513 bajtówKod 581 + 932 dane
↑ Ten top jest poziomem oryginalnym. W środku znajduje się PPM generowany przez ten skrypt. Na dole znajduje się diff, a to pokazuje, że paleta i mapa nie zgadzają się dokładnie! Odłożyłem to na usterkę danych, a nie mój skrypt;)
(bajty zliczane bez komentarzy, bez linii i wcięcia drugiego poziomu
\t
)Dane (zakodowane w formacie base64 do wklejenia; zdekoduj i zapisz jako plik o nazwie „i”):
Plik danych jest niestandardowym formatem utworzonym dla tego problemu i jest przechowywany jako LZMA.
Najpierw serializowane są wszystkie 32 kafelki. Paleta zawiera 9 kolorów, a to nie wymaga skompresowania 8219 bajtów. (Przekonałem się, że próba kompresji kafelków przy 4 bitach na piksel wcale nie pomogła w kompresji. Nie próbowałem brutalnie wymuszać najlepszego uporządkowania kafelków i prawdopodobnie straciłem tutaj kilka punktów.)
Mapa składa się z 212 x 14 = 2968 bloków.
Następnie instrukcje odtwarzania mapy są teraz kodowane.
Najpierw jest sekcja poleceń „umieść”, które umieszczają sekwencję kafelków z palety kafelków na mapie w określonym x, y. Ponieważ są 32 kafelki, określam przebieg tego samego kafelka, używając liczby większej niż 32 zamiast indeksu kafelków.
Następnie pojawia się sekcja poleceń „kopiuj”, które kopiują prostokąt z bieżącej mapy w inne miejsce. Istnieje specjalna maska bitowa, która zaznacza, czy kopia powinna być dublowana.
Krótki przykładowy bufor poleceń:
(Powiedziałem krótko , ale tak naprawdę to prawie połowa całkowitego bufora poleceń potrzebnego do stworzenia całej mapy; ogromna większość bajtów w danych to same 32 kafelki źródłowe)
Potem pojawia się druga sekcja poleceń „put” i wreszcie kolejna sekcja poleceń „copy”.
Ponieważ mogą się one wzajemnie nadpisywać, mogę tworzyć części do skopiowania, które później usuwam lub zmieniam.
Mogę bez wątpienia zgolić kilka dodatkowych bajtów, na przykład poprzez włączenie wstawiania w małe kopie i wykonanie
eval
sztuczki na spakowanym gzipie kod źródłowy lub granie z PNG (który jest DEFLATE z filtrami specyficznymi dla obrazu). Ale lubię rzeczy takie, jakie są pełne.źródło
3,11
wydaje się, że brakuje kafelka w palecie. Wygląda na to, że wokół mapy jest trochę hałasu,20,12
a ogólny zarys drzew i chmur może być nieprawidłowym wyrównaniem w palecie? Jest tylko 9 kolorów, więc nie może to być żaden mieszany artefakt.JavaScript,
106910721024 znaków (1957 bajtów)RegPacked i Obfuscatweeted
Kod nieobjawiony
Ukryłem ten kod, ponieważ poniżej znajduje się kod nierozszyfrowany.
Pokaż fragment kodu
Nieskluczony kod
Najpierw utworzyłem kafelki w sprajty przy użyciu zminimalizowanego identyfikatora URI @ schnaader.
0 ~ v
(czyli 0 ~ 31 w podstawie 31) reprezentuje każdą płytkę.I ręcznie przekształciłem mapę w kafelki. Te dane mają 212 znaków na wiersz.
Następnie zastąpiłem powtarzający się znak (jak
7
(niebo) i1
(ziemia)) narepeat()
.Znalazłem
7
s i kilka bloków, a kolejny7
wzór się powtarza. Zrobiłem więc inną funkcję, aby była kompaktowa. Możesz to zobaczyć w nieobjawionym kodzie źródłowym.W końcu ponownie spakowałem i Obfuscat opublikował mój 2341 bajtowy kod do gry w golfa.
To było bardzo zabawne wyzwanie. Dzięki! I dzięki @xem za więcej sztuczek.
źródło
JavaScript:
3620 (ouch)34293411Aktualizacje
Aktualizacja nr 1: Usunięto
var
definicje i umieściłem deklaracje zmiennych w nawiasach pierwszego użycia. Usunięty,getElementById()
ponieważ jest również dostępny przy obciążeniu jako zmienny przez identyfikator. UżywaniecloneNode()
zamiastcreateElement('CANVAS')
. Zmiana nazwy głównej zxMx
naM
. Usunięto funkcję skalowania :( (nadal dostępne w przykładzie ).Dodano kilka komentarzy do rozszerzonego kodu. (Ten kod nie jest aktualizowany wraz z usunięciem. Poniższy wiersz („Mini kod”) to.)
Aktualizacja nr 2: Usunięto główną funkcję
M()
jako całość i pozwól, aby kod działał w katalogu głównym . Wymagałoby to umieszczenia kodu w opakowaniu lub na końcu dokumentu.Aktualizacja nr 3: Dodano statystyki.
Mini kod:
Bla bla:
- Demo na końcu postu.
Wykorzystanie płótna jako podstawy do rozwiązania tego problemu. Skończyło się na około 6000 znakach, ale po trochę majstrowania (i niestandardowej kompresji - z majstrowaniem i poprawkami również) jestem teraz na podanej liczbie. Wciąż wysoka, ale znowu jakość jest dobra ;-).
Obejmuje ona również opcję skalę, pierwszy argument
xMx()
, alias „main” funkcję. 1 = normalny rozmiar (jak w 16-bitowych kafelkach). Nie ma wiele miejsca na ulepszenia, więc jeśli użyjesz ułamków, niektóre płytki nie pasują najlepiej do siebie. Przy liczbach całkowitych powinno być OK. [1]Ale: ostrzeganie, wchodzenie w górę, szybko zjada zasoby i tworzy ogromne płótno. (Wszystko jest pomalowane za jednym razem.) Gdy oryginalna szerokość wynosi 3392 pikseli, szybko staje się ogromna. [1]
[1] Od aktualizacji nr 1 została ona usunięta. Jest obecny w wersji demo.
Statystyki:
Main code : 870
Compression:
Main data : 2176 (17,480 bits)
Key : 128 ( 1,024 bits)
Code : 236
Whole she bang : 2540
Decompressed data : 5608 (44,864 bits)
Total : 3410
[1][1]: +1 bajt, „;”, między kodem głównym / danymi.
Skompresowane dane to jedna tablica Å i jeden „obiekt” Ø. Gdzie Å trzyma położenie płytki, a Ø zawiera dane do malowania płytek. Ø powinna być również tablicą - ale kiedy mój kod zaczął od czegoś takiego:
Skończyło się tak, jak jest. Może zobaczę, czy nie mogę tego naprawić. Idealnie sprawiłbym, że byłby to możliwe do przeanalizowania za pomocą JSON zamiast eval (), ale nie byłoby to celem w takich zawodach. W tej chwili nie można go przeanalizować z powodu brakujących cudzysłowów wokół części id.
Próbny
Oto skrzypce, w których można zobaczyć kod w akcji. Kod w skrzypce nieco rozszerzyłem (i dodałem trochę stylizacji HTML / CSS na całym świecie - ale sam obraz jest samowystarczalny.):
MARIOS WORLD
Rozszerzony kod:
Rozszerzony i (nieco) przestawiony kod:
źródło
var
do deklarowania zmiennych; są one automatycznie deklarowane po ich zdefiniowaniu, więc powinieneś mieć możliwość usunięciavar D,C,c,S,s,R,F,Z,
ze swojego kodu. (również można zastąpić/.{2}/
w/../
.)var
ale zostawiłem to, ponieważ musiałem uruchomić, kiedy go opublikowałem. Gotowe teraz RegExp był fajny, jakoś nie udało się tego zobaczyć;)ev(a|i)l
procedurę). Jeśli jest to „legalne”, to OK.eval(unescape(escape('𨑬𩑲𭀨𘣆𘠩').replace(/uD./g,'')))
działa zgodnie z przeznaczeniem. I tak, twój wynik jest liczony w postaciach, dzięki czemu możesz całkowicie używać sztuczek takich jak kompresja Unicode i eval. Z tym możesz uzyskać wynik blisko 1750!Pyton
133113261314127212681217 bajtów(kod:
219214202186182, dane:362 + 750 = 1112363 + 723 = 1086346 + 689 = 1035)Chodzi o to, że najpierw generuję mapę o rozmiarze 16 w każdym wymiarze, gdzie każdy piksel jest pokolorowany przez indeks na mapie kafelków. Aby upewnić się, że użyto tej samej palety, najpierw połączyłem podaną mapę kafelków i mapę w jeden obraz. Z tej i mapy kafelków (oba zminimalizowane pngs) możemy teraz zregenerować oryginalną mapę. (Kod tego procesu można zobaczyć poniżej kodu zgłoszenia). Należy zauważyć, że zapisałem mapę kafelków jako plik „t”, a wygenerowaną mapę jako obraz „m”
EDYCJA: Zacząłem badać, w jaki sposób kolejność kafelków wpłynęła na kompresję, i dla eksploracji wygenerowałem 10000 losowych permutacji i skompresowałem je z tym wynikiem: Wszystko to było z kafelkami w jednej linii, ponieważ zmniejszyło to dość kod kawałek. Próbowałem podobnych rzeczy w różnych konfiguracjach (2 * 16, 4 * 8), ale żadnych z lepszym średnim wynikiem.
Zakładając, że png lepiej kompresuje się z większymi ciągłymi podobnymi regionami, zbudowałem narzędzie, które pozwoliłoby mi przesuwać kafelki i używając tego, co uważałem za bardziej ciągły obraz, zmniejszyłem obraz kafelka do 723 z 750b.
EDIT2: Po wielu (dużo) dalszych analizach dotyczących tego, jak naprawdę działa png i wielu eksperymentach (wciąż trwających), obrazy zostały teraz skompresowane jeszcze bardziej. Link poniżej zaktualizowany. Więcej o tej analizie napiszę później, gdy będzie kompletna.
Nowe użyte obrazy są tutaj: http://imgur.com/a/RgkXx
Oto inne obrazy wygenerowane w procesie: http://imgur.com/a/HXTGA , choć niektóre są nieco nieaktualne z powodu powyższej edycji.
Skrypt, który napisałem, aby zmniejszyć mapę, jest dość prymitywny, ale proszę bardzo (może być również nieaktualny z powodu powyższych zmian):
źródło
Perl 5 + PNG: 689 + 593 = 1282
Nieudana próba zastąpienia skompresowanej mapy kafelków PNG z rozwiązania Christiana kodem Perl. Ostatecznie jest 65 bajtów dłużej. Pobiera te same kafelki PNG na wejściu i generuje PNG na wyjściu.
Stosowanie:
perl mario.pl <tiles.png >world.png
źródło
JS:
40123921 znakówJS służy do rozpakowywania wielu znaków Unicode i pisania znacznika img, którego src jest obrazem podanym w OP, zapisanym jako PNG, skompresowanym, zakodowanym w base64 i przyciętym.
Demo: http://jsbin.com/fojidejoco/1/
PS: Wiem, że to trochę oszustwo (nawet jeśli pozwalają na to reguły), ale przynajmniej daje nam cel: zrób to w mniej niż 4012 znakach.
Narzędzia użyte:
źródło