Węgiel drzewny to język stworzony przez ASCII i DLosc, który specjalizuje się w wyzwaniach artystycznych ASCII.
Jakie masz wskazówki dotyczące gry w golfa w Charcoal? Oczywiście szukam wskazówek związanych konkretnie z węglem drzewnym, a nie tych, które można zastosować do większości - jeśli nie wszystkich - języków.
Odpowiedzi:
Skorzystaj z deverbosifier
Użycie deverbosifier oznacza, że możesz pisać w ASCII (
--dv
lub--deverbosify
deverbosify,-v
lub--verbose
wykonać jako pełny kod). Ponadto kompresuje ciągi dla Ciebie, co może być przydatne w niektórych wyzwaniach ASCII-art, gdy ciąg do skompresowania jest zbyt długi.@ Neil zaleca używanie
-vl
lub-v --sl
. Jest to skrót od--verbose --showlength
, co oznacza, że zostanie zinterpretowany jako pełny węgiel drzewny, a długość normalnego kodu węgla drzewnego zostanie pokazana. Ponadto podczas dewerbosyfikacji sprawdź dane wyjściowe, aby upewnić się, że dane wejściowe zostały poprawnie przeanalizowane, ponieważ węgiel drzewny generalnie ignoruje błędy analizy. Jeśli tam jest błąd składni, użycie-a
(--astify
) lub--oa
(--onlyastify
), aby pomóc dowiedzieć się problem.źródło
-v -sl
. Ponadto podczas dewerbosyfikacji sprawdź dane wyjściowe, aby upewnić się, że dane wejściowe zostały poprawnie sparsowane, ponieważ nie zawsze pojawia się błąd analizy.Użyj przeciążeń
Na przykład wiele poleceń wymaga tylko jednego argumentu:
Rectangle
,Oblong
IBox
zrobić kwadrat, jeśli tylko jeden argument podanoReflect
polecenia domyślnie odzwierciedlają prawoRotate
polecenia domyślnie wynoszą 90 stopni przeciwnie do ruchu wskazówek zegaraPolygon
iPolygonHollow
może przyjmować wielokierunkową i boczną długość. Można tego użyć, jeśli wszystkie boki mają tę samą długość.źródło
PolygonHollow
przypadkiem. Możesz mieć nawet kilku wielokierunkowych, ale muszą oni stawić się przed normalnymi strzałkami (nie wiem, czy to ograniczenie jest zamierzone). Użyłem tego w mojej odpowiedzi na wyzwanie „Draw a cube”.ReflectButterfly dls
się, że zadzwonięReflectButterfly
w każdym kierunku, ale (jak wiki poprawnie dokumentuje) tak naprawdę wołaReflectOverlap
.Unikaj kolejnych stałych tego samego typu
Na przykład
Plus(Times(i, 2), 1)
tłumaczy jako⁺×鲦¹
, ale można zapisać bajt, zmieniając parametry:Plus(1, Times(i, 2))
tłumaczy jako⁺¹×ι²
iPlus(Times(2, i), 1)
jako⁺ײι¹
oba zapisują bajt.Plus(1, Times(2, i))
(co tłumaczy się jako⁺¹×²ι
) byłoby jeszcze lepsze, gdyby następowała po nim inna stała liczbowa.źródło
Użyj predefiniowanych zmiennych
Oto lista wszystkich zmiennych, których można użyć, podając zwięzłą grecką literę i pełną, reprezentującą ją literę.
Zmienne reprezentujące dane wejściowe będą puste, jeśli nie będzie wystarczającej ilości danych wejściowych, ale wszystkie inne nie pokazane tutaj zmienne muszą zostać przypisane przed użyciem.
źródło
y
i czyf
jest na odwrót od tego, co wkleiłem? (Być może błędnie odczytałem greckie litery, kiedy je pierwotnie napisałem.)Naucz się swoich odbić i obrotów
Istnieje wiele odmian podstawowego odbicia i obrotu, więc opłaca się wiedzieć, jakie są subtelne różnice. Klucz do tabel:
/
może stać się\
po obrocie lub odwrocie.Refleksje
Kierunek odbicia jest opcjonalny. Ustawieniem domyślnym jest odbicie raz w prawo. W przypadku odbić, które zachowują oryginał, dozwolony jest wiele kierunków, które po prostu powtarzają polecenie dla każdego kierunku. (Oznacza to, że na przykład
ReflectMirror(:¬)
faktycznie utworzą w sumie cztery kopie).Kursor jest przesuwany wraz z odbiciem (nawet gdy oryginał jest zachowany).
Rotacje
Dla tych obrotów, które zachowują oryginał, istnieje opcjonalne źródło obrotu. Domyślnie jest to dolny prawy obszar roboczy. Dozwolonymi wartościami są dowolne kierunki po przekątnej.
Wielkość obrotu (w krokach co 45 °) jest opcjonalna. Wartość domyślna to 2, tzn. 90 ° przeciwnie do ruchu wskazówek zegara (przeciwnie do ruchu wskazówek zegara). Dla tych obrotów, które zachowują oryginał, istnieją dwie alternatywne opcje: liczba całkowita dla wielu cyfr określa obrócenie obszaru roboczego raz dla każdej cyfry, a następnie scalenie wyników, podczas gdy lista liczb całkowitych po prostu powtarza polecenie dla każdego obrotu, a wyniki zmiennych zależą od tego, w jaki sposób płótno zmienia się pomiędzy.
źródło
Transform
znaczy?Transform
działa gdzieś w odpowiedzi.Używaj poleceń bez znaku polecenia
Wyrażenie, które nie jest częścią polecenia, jest drukowane.
Jeśli poprzedza go kierunek, wyrażenie jest drukowane w określonym kierunku.
Liczby są drukowane jako linia o określonej długości przy użyciu znaku wybranego z
\/-|
.Jeśli po kierunku nie następuje wyrażenie, jest ono liczone jako ruch o jedną spację w określonym kierunku.
Uwaga: Czasami można to liczyć jako część poprzedniego polecenia, więc znak polecenia może być faktycznie wymagany. (dzięki Neil za przypomnienie)
źródło
Używaj wielokierunkowych
Niektóre polecenia mogą przyjąć multidirectionals:
+X*|-\/<>^KLTVY7¬⌊⌈
. To, do czego się rozwijają, jest tutaj . Ogólnie rzecz biorąc, lista kierunków zaczyna się od góry i kontynuuje zgodnie z ruchem wskazówek zegara.źródło
ReflectButtterflyOverlap(:¬, Modulo(g, 2));
.)Wykorzystaj w pełni
Sum
Sum
ma wiele przydatnych przeciążeń:Join(..., "")
zamiast tego..
znak pobiera sumę cyfr.-
liczy się jako separator).Dogodnym efektem ubocznym dwóch ostatnich zasad jest to, że jeśli użyjesz
Sum
znaku, cyfry1-9
zostaną przypisane do ich wartości, a wszystko inne zwróci zero, w przeciwieństwie do wartościCast
, które zawodzą w przypadku wartości innych niż cyfry.źródło
Użyj podziału dla tablicy ciągów, podziel i rzutuj dla tablicy liczb
Podział tablicy ciągów to tylko trzy znaki narzutu, a podział i rzut to tylko cztery znaki narzutu. Porównaj to do pisania tablicy dosłownie, co wymagałoby początku i końca tablicy oraz separatora między każdym elementem tablicy.
Jeśli tablica liczb ma tylko liczby mniejsze niż 95, użyj rzutowania (jeśli wszystkie liczby są mniejsze niż 10) lub zindeksuj do jednej ze wstępnie zdefiniowanych zmiennych.
źródło
Użyj Filtru, aby wyciąć pierwszy znak z tablicy lub łańcucha
Nawet jeśli masz szczęście, używając
Slice
do krojenia pierwszy znak z łańcucha zajmuje 2 bajty:Slice(..., 1)
. Zajmie to więcej czasu, jeśli wyrażenie, które ma być pocięte, kończy się liczbą wymagającą separatora lub jeśli poniższy kod może być interpretowany jako wyrażenie, ponieważ w takim przypadkuSlice
będzie chciał użyć go jako dodatkowego parametru.Zamiast tego po prostu użyj
Filter(..., k)
, który upuszcza pierwszy element, osiągając w ten sposób pożądany rezultat. (Oczywiście użyj odpowiedniej zmiennej indeksu pętli, jeśli twoje wyrażenie jest zagnieżdżone w innej pętli.) Zawsze są to 2 bajty i otaczający kod nie może na nie wpływać.źródło