To pytanie jest inspirowane okładką książki „Godel, Escher, Bach”:
Wyzwanie polega na napisaniu funkcji, która mówi, czy trzy podane litery mogą wytworzyć rzeźbę 3D, którą można odczytać z trzech stron.
W tym ćwiczeniu jedynymi literami, których możesz użyć, są 26 bitmap * 5 pikseli * 5 pikseli:
Lub binarnie (od A do Z):
01110 11110 01111 11110 11111 11111 11111 10001 11111 11111 10001 10000 10001 10001 01110 11110 01110 11110 01111 11111 10001 10001 10001 10001 10001 11111
10001 10001 10000 10001 10000 10000 10000 10001 00100 00100 10010 10000 11011 11001 10001 10001 10001 10001 10000 00100 10001 10001 10001 01010 01010 00010
10001 11110 10000 10001 11100 11110 10011 11111 00100 00100 11100 10000 10101 10101 10001 10001 10001 11111 01110 00100 10001 01010 10001 00100 00100 00100
11111 10001 10000 10001 10000 10000 10001 10001 00100 10100 10010 10000 10001 10011 10001 11110 10011 10010 00001 00100 10001 01010 10101 01010 00100 01000
10001 11110 01111 11110 11111 10000 11111 10001 11111 11100 10001 11111 10001 10001 01110 10000 01111 10001 11110 00100 01110 00100 01010 10001 00100 11111
Rzeźba składa się z trzech liter w następującej kolejności:
- litera pierwsza na górze,
- litera druga po lewej
- litera trzecia po prawej
- dolna część litery pierwszej jest związana z górą litery drugiej.
Przykład:
Twoja funkcja może przyjąć jako dane wejściowe trzy wielkie litery (trzy znaki lub trzy ciągi jednej litery) i wygenerować wartość logiczną (prawda / fałsz lub 0/1) informującą, czy odpowiednia rzeźba może istnieć.
Przykład:
f("B","E","G") // true (because if you "sculpt out" B on top + E on the left + G on the right, and watch the three sides of the sculpture, you'll see exactly B, E and G as they are defined)
f("B","G","E") // false (because if you "sculpt out" B on top + G on the left + E on the right, and watch the three sides of the sculpture, you won't see a complete G and a complete E. Their shapes bother each other)
Uwaga: możesz zwrócić prawdę, nawet jeśli rzeźba zawiera „latające piksele” (kostki lub grupy kostek, które są przymocowane do niczego).
Obowiązują standardowe luki.
Mówiąc dokładniej, nie możesz używać zewnętrznych danych wejściowych poza trzema literami i nie możesz zakodować 17576 możliwych odpowiedzi w kodzie źródłowym
Najkrótsza odpowiedź w postaci w dowolnym języku wygrywa!
Baw się dobrze :)
Odpowiedzi:
Mathematica 423
Dodałem sekcję „Jak działa blokowanie”.
Nie golfił
(* Dane binarne alfabetu są przechowywane jako pojedynczy ciąg znaków w
s
.vars
Importuje je i konwertuje na tablicę.)Przykład
Czy kostka jest
{"B", "G", "E"}
ważna? (tj. czy trzy litery będą poprawnie rzutować na ściany?)Ilustracje
Poniższe liczby pokazują, w jaki sposób renderowany jest BGE. Górny rząd figur przyjmuje perspektywy ortogonalne, tak jakby widz znajdował się w nieskończonej odległości od sześcianu. Dolny rząd pokazuje, jak bloki wyglądałyby z bliska. Figury 3D można ręcznie obracać, aby dokładnie sprawdzić, gdzie są rozmieszczone poszczególne kostki jednostek.
Wystąpił problem z literą „G”. Nic nie łączy szeryfa z resztą listu.
BEG powinno jednak działać dobrze.
Jak działa blokowanie?
Przepraszam, jeśli wydaje się to oczywiste, ale być może niektórzy ludzie będą chcieli wyobrazić sobie, w jaki sposób litery kolidują ze sobą, anulując ich piksele 3D.
Zobaczmy, co stanie się z literą G w renderowaniu kostki BGE.
Zwrócimy szczególną uwagę na woksel (piksel 3D lub sześcian jednostkowy) poniżej. To piksel, który znika w sześcianie BGE. Jest to piksel odpowiadający wierszowi 4, kolumnie 5 w tablicy bitów i na odpowiednim wykresie tablicy.
W płaszczyźnie xy piksel odpowiada szaremu dyskowi w punkcie (5,2). Ponieważ jednak zamierzamy pracować w 3D, musimy rozważyć 5 pozycji w wale od (5,1,2) do (5,5,2). Jeśli któryś z tych pikseli przetrwa rzeźbienie za pomocą liter B i E, będziemy mogli zobaczyć interesujący piksel w projekcji 3D na ścianie.
Litery przeszkadzają, gdy piksele są usuwane z bryły. Czarna strzałka po lewej stronie przedstawia wycinanie pikseli, odpowiadające bitowi w prawym dolnym rogu; ma wartość 0 dla litery B. Wycięcie usuwa piksel w punkcie (5,1,2) wraz z tymi znajdującymi się bezpośrednio nad i pod nim. Należy uwzględnić cztery piksele.
Ale jak pokazuje prawy panel, litera E przedstawia pozostałe interesujące piksele, (5,2,2) (5,3,2), (5,4,2) i (5,5,2). (Wynika to z faktu, że litera E ma bity równe 0 w czwartym rzędzie, od kolumny 2 do kolumny 5.) W rezultacie nie ma ani jednego piksela spośród tych, które były potrzebne, aby zapewnić cień w punkcie (5) , 2) na przeciwległej ścianie (dla litery G). Zamiast tego będzie jasna plama odpowiadająca otworowi w literze G! Kostka BGE nie jest dobra, ponieważ niepoprawnie renderuje G.
Gra w golfa 423 znaki
Funkcja
h
pełniła tę samą rolę, covalidQ
w kodzie unGolfed. Funkcja renderowaniaperspective
nie jest uwzględniona, ponieważ nie przyczynia się do wyzwania i nie jest wymagana.źródło
Prolog,
440, 414Program nazywa się tak:
Prolog
wydawało się być dobrym wyborem, ponieważ łatwo jest przedstawić problem w logice pierwszego rzędu.Prolog
Zapewnia również potężną funkcjonalność do rozwiązywania tego rodzaju problemów.Ponieważ jednak kod jest golfowy, powinienem dodać wyjaśnienie.
Wersja lekko golfowa
Współrzędne odpowiadające pikselom z każdej strony kości można łatwo przekonwertować na układ współrzędnych 3D. Korzystać
T
,L
aR
z góry (1) i lewy (2) i (3) prawego boku.u
iv
są używane do współrzędnych na obrazach:(u,v) -> (4-v, ?, u)
(u,v) -> (?, v, u)
(u,v) -> (u, v, ?)
Wyniki dla każdego aktywnego (tj. Czarnego) piksela są łączone w zestaw „pikseli 3D”, które można aktywować bez zmiany wyglądu obiektu z tej strony. Przecięcie zbiorów dla każdej strony to wszystkie piksele 3D, które można aktywować bez dodawania pikseli, które utrudniają widok (tzn. Patrząc z przynajmniej jednej strony byłby piksel, którego nie powinno tam być).
Pozostaje tylko sprawdzić po każdej stronie, czy na skrzyżowaniu znajduje się piksel, który blokuje widok, tam gdzie jest to konieczne.
Prowadzi to do predykatów w programie:
c : sprawdza piksel na obrazie litery. Ciąg tam może wyglądać nieco dziwnie, ale jest to tylko kompaktowy sposób przechowywania danych obrazu. Jest to po prostu sekwencja znaków o następujących wartościach (zapis szesnastkowy):
Każdy z tych znaków przechowuje dane dla 3 wierszy pikseli w obrazie (obrazkach) (= 15 pikseli). Piksele są również ponownie uporządkowane, dzięki czemu dane są przechowywane w jednym miejscu i nie są dzielone na wiele wierszy, takich jak dane PO.
Formułowanie matematyczne
Dane wejściowe
Konwersja piksela w jednym znaku do zestawu pikseli 3D, które zasłaniają widok tego piksela
Piksele, które można bezpiecznie dodać (bez zasłaniania widoku w niewłaściwym miejscu)
Sprawdza z każdej strony, czy piksele, które muszą być zasłonięte, można bezpiecznie zasłonić
Kombinacja czeków dla każdej strony
źródło
J -
223197191 znakówFunkcja przyjmująca listę trzech znaków jako argument.
Ten golf w dużej mierze opiera się na potężnej funkcji J o nazwie rank , która daje nam niemal „za darmo” operacje „rzeźbienia” i „obserwowania”. Aby nieco to uprościć, ranga odnosi się do wymiarów rzeczownika lub naturalnych argumentów czasownika.
J ma tablice wielowymiarowe i oczywiste jest, że powiedzmy, tablica 3D może być interpretowana jako pojedyncza tablica 3D, lub jako lista macierzy, lub tablica 2D wektorów, lub tablica 3D skalarów. Tak więc każda operacja w J może mieć kontrolę nad aplikacją, jak rozłożyć na argument. Ranga 0 oznacza zastosowanie na skalarach, ranga 1 oznacza zastosowanie na wektorach i tak dalej.
Staje się to bardzo potężne, gdy wprowadzisz funkcje diadadowe (dwuargumentowe), ponieważ jeśli kształty dwóch argumentów (po uwzględnieniu rangi) są akceptowalne, J wykona pewne niejawne zapętlenie:
Kiedy wszystkie twoje kształty są akceptowalne i możesz sam określić rangę, istnieje wiele sposobów łączenia argumentów. Przedstawiamy kilka sposobów na pomnożenie macierzy 2D i macierzy 3D.
Zauważysz, że tak naprawdę nie ma liter w orientacji, o którą pyta pytanie, tylko zapisuje je, ale jest to wygodne dla logiki rangi. O ile nie zastosujemy odwrotu lub rotacji liter przed ich zastosowaniem, nie będzie działać poprawnie. Ale poprawianie takich rzeczy zajęłoby cenne znaki, więc zamiast tego zakodujemy litery tak, że kiedy J rzeźbi je w naturalny sposób, niektóre potrójne twarze będą we właściwej orientacji i we względnych pozycjach. Okazuje się, że najkrótszym rozwiązaniem jest obrócenie wszystkich liter o ćwierć obrotu przeciwnie do ruchu wskazówek zegara. Biorąc pod uwagę trzeci wymiar J, który reprezentuje oś przód-tył, przybliżony schemat poniżej pokazuje, dlaczego ten schemat działa.
Rycina A: Trzy boki sześcianu, w które rzeźbi J. Rycina B: Pytają trzy strony, których litery są zorientowane tak, jak pytanie.
Ten wybór w kodowaniu pozwala zaoszczędzić 12 znaków w stosunku do poprzedniej metody i sprawia, że całość jest ładniejsza. Rzeczywisty golf tworzy sześcian z rzeźby
"1
i"2
ma funky logikę, ze względu na niepowiązaną optymalizację.Następnie musimy sprawdzić twarze. Ponieważ zakodowania bloku co 1s i 0s, możemy po prostu zsumować wzdłuż każdej osi w sposób chcemy (są to
+/"1
,+/"2
i+/
bity), dostosować do wartości logiczne (0<
), a następnie porównać je wszystkie bezpośrednio do pierwotnego 90 ° - odwrócone litery.Schemat kompresji koduje każdy wiersz o wielkości 5 pikseli każdej litery jako podstawową 32 reprezentację liczby binarnej. Wykorzystując szereg cukrów składniowych i przeciążenie operatora,
".'1b',"#:
jest najkrótszym sposobem na przekształcenie listy znaków w podstawowe liczby 36. Cóż, technicznie rzecz biorąc, podstawa 32, ale J uważa, że to jednoargumentowe, więc kto liczy?Użycie jest poniżej. Zauważ, że łańcuchy są tablicami znaków w J, więc lista trzech elementów
'A','B','C'
może być napisana'ABC'
w skrócie. Również booleany wynoszą 1/0.źródło
Python,
687682671Zadzwoń z
v
:Wszystko poniżej pochodzi z mojej poprzedniej wersji bez golfa, która zawiera pomocne funkcje rysowania. Możesz go użyć jako punktu odskoczni.
Zadzwoń,
valid
aby go uruchomić:W tej chwili kod jest skonfigurowany do testowania poprawności
B E G
i wydrukowania powstałych powierzchni:Po
B G E
uruchomieniu możemy zauważyć, że G jest niepoprawny:źródło
g=[[0 for j in s]for i in s]
można skrócić dog=map(list,[[0]*5]*5)
. Ponadto można uniknąć wcięć bloków, jeśli są one jedno stwierdzenie:if c[e]:g[e[a]][e[a-2]]=1
.Python 3 + numpy, 327C
To rozwiązanie do gry w golfa wymaga zewnętrznej biblioteki numpy, która jest dość popularna, więc myślę, że można z niego korzystać.
Ciąg znaków Unicode składa się z 41 znaków, podczas gdy ta sama rzecz w odpowiedzi na prolog @ fabian to 44.
Najciekawsze jest tutaj to, że indeksowanie tablicy numpy. W
a[ix]
,ix
może być tablicą boolowską o takim samym kształcie jaka
. To to samo co mówieniea[i, j, k] where ix[i, j, k] == True
.Wersja bez golfa
Skrypt do kompresji tabeli
źródło