Jakie masz ogólne wskazówki na temat gry w golfa w Julii? Szukam pomysłów, które można by zastosować do problemów z golfem w kodzie, które są przynajmniej nieco specyficzne dla Julii (np. „Usuń komentarze” nie jest odpowiedzią).
20
UWAGA: poniżej może zawierać kilka przestarzałych wskazówek, ponieważ Julia nie jest jeszcze całkowicie ustabilizowana pod względem struktury.
Kilka sztuczek, aby uratować kilka postaci
\ =div
, a następnie możesz wpisać a\b
zamiast div(a,b)
. Zwróć uwagę na spację - jest to konieczne, aby uniknąć parsowania jako operatora „\ =”. Należy również pamiętać, że w przypadku przeciążenia na poziomie monitu REPL użyj (\)=Base.(\)
lub, \ =Base. \
aby go zresetować. UWAGA: niektóre funkcje mają wstępnie zdefiniowane istniejące operatory UTF-8, takie jak ÷
dla div
, jak zauważył Alex A.a>0?"Hi":""
używać "Hi"^(a>0)
do zapisania jednego bajtu, lub dla wartości logicznej a, "Hi"^a
do zapisania trzech bajtów.a=split("Hi there"," ")
być w stanie uniknąć a[1]
i a[2]
za pomocą a,b=split("Hi there"," ")
, które można określić jako a
i b
, oszczędzając trzy bajty dla każdego użycia, kosztem tylko dwóch dodatkowych znaków przy przypisaniu. Oczywiście nie rób tego, jeśli możesz pracować z operacjami wektorowymi.[]
- w przypadku tablic wyrażenie A[]
jest równoważne z A[1]
. Zauważ, że nie działa to dla Ciągów, jeśli chcesz zdobyć pierwszą postać, lub dla Tuples.==[]
dla tablic i ==()
krotek; podobnie, dla negatywu, użyj !=[]
i !=()
. W przypadku łańcuchów używaj ==""
dla pustych, ale używaj >""
dla niepustych, ponieważ „” jest leksykograficznie przed każdym innym ciągiem.x<=1&&"Hi"
można zapisać jako x>1||"Hi"
, zapisując znak (o ile powrót wartości logicznej nie jest ważny).in('^',s)
raczej niż contains(s,"^")
. Jeśli możesz użyć innych znaków, możesz zaoszczędzić nieco więcej '^'∈s
, ale pamiętaj, że ∈
w UTF-8 jest to 3 bajty.minimum(x)
lub maximum(x)
, użyj min(x...)
lub max(x...)
, aby zgolić jeden znak z twojego kodu, jeśli wiesz, że x
będą miały co najmniej dwa elementy. Alternatywnie, jeśli wiesz, że wszystkie elementy x
będą nieujemne, użyj minabs(x)
lubmaxabs(x)
r"(?m)match^ this"
, pisz r"match^ this"m
, zachowując trzy znaki.reverse(x)
jest o jeden bajt dłuższy flipud(x)
i wykona tę samą operację, więc ta druga jest lepsza.{[1,2]}
nie {1,2}
) - w przypadku Julii 0.4 byłoby to potrzebne Any[[1,2]]
.end
indeksowania tablic, automatycznie jest konwertowany na długość tablicy / łańcucha. Zamiast tego k=length(A)
użyj, A[k=end]
aby zapisać 3 znaki. Pamiętaj, że może to nie być korzystne, jeśli chcesz natychmiast użyć k. Działa to również w przypadku wielowymiarowym -A[k=end,l=end]
otrzyma rozmiar każdego wymiaru A
- jednak (k,l)=size(A)
w tym przypadku jest krótszy o jeden bajt, więc używaj go tylko wtedy, gdy chcesz natychmiast uzyskać dostęp do ostatniego elementu w tym samym czasie.A[k=1:end]
, w którym to przypadku k
zachowa iterator pasujący1:length(A)
. Może to być przydatne, gdy chcesz jednocześnie korzystać z tablicy A
.collect(A)
, użyj[A...]
, który zrobi to samo i pozwoli zaoszczędzić 4 bajty."$(s[i])"
lubdec(s[i])
do wyrażeń lub zmiennych wieloznakowych oraz "$i"
do zmiennych jednoznakowych.?:
zamiast &&
lub ||
do przypisania warunkowego - to znaczy, jeśli chcesz wykonać przypisanie tylko pod pewnymi warunkami, możesz zapisać jeden bajt, pisząc cond?A=B:1
zamiast cond&&(A=B)
, cond?1:A=B
a niecond||(A=B)
. Zauważ, że 1
tutaj jest to wartość pozorna.union
lub ∪
zamiastunique
- union(s)
zrobi to samo co unique(s)
i zapisze bajt w tym procesie. Jeśli możesz użyć znaków spoza ASCII, ∪(s)
zrobisz to samo i ∪
kosztuje tylko 3 bajty zamiast 5 bajtów w union
.
split("Hi there")
ponieważ argument wzorca domyślnie jest spacją.Przedefiniuj operatory, aby zdefiniować funkcje
Przedefiniowanie operatorów pozwala zaoszczędzić wiele bajtów w nawiasach i przecinkach.
Rekurencyjne operatory jednoargumentowe
Aby uzyskać jedyny przykład, porównaj następujące rekurencyjne implementacje sekwencji Fibonacciego:
Wypróbuj online!
Przedefiniowany operator zachowuje swój pierwotny priorytet.
Zauważ, że nie mogliśmy po prostu zamienić się
!
na~
, ponieważ~
jest już zdefiniowany dla liczb całkowitych, podczas gdy!
jest zdefiniowany tylko dla boolean.Operatory binarne
Nawet bez rekurencji ponowne zdefiniowanie operatora jest krótsze niż zdefiniowanie funkcji binarnej. Porównaj następujące definicje prostego testu podzielności.
Wypróbuj online!
Rekurencyjne operatory binarne
Poniżej przedstawiono sposób przedefiniowania operatora binarnego w celu obliczenia funkcji Ackermann:
Wypróbuj online!
Pamiętaj, że
^
jest to nawet dłużej niż zwykły identyfikator, ponieważ jego priorytet jest zbyt wysoki.Jak wspomniano wcześniej
nie działałby dla argumentów liczb całkowitych, ponieważ
|
w tym przypadku jest już zdefiniowany. Definicję liczb całkowitych można zmienić za pomocąale to zbyt długo. Jednak to robi pracę, jeśli mijamy pływaka jako argumentu lewej i prawej całkowitą jako argumentu.
źródło
Nie daj się łatwo uwieść czynnikowi (n) Kusząca funkcja biblioteki podstawowej
factor(n)
ma fatalną wadę: zwraca faktoryzację liczby całkowitej w nieuporządkowanymDict
typie. W związku z tym wymaga kosztownychcollect(keys())
icollect(values())
potencjalnie także acat
i a,sort
aby uzyskać potrzebne dane. W wielu przypadkach taniej jest po prostu wziąć pod uwagę podział prób. Smutne ale prawdziwe.Użyj mapy
map
to świetna alternatywa dla zapętlania. Zdawać sobie sprawę z różnicy pomiędzymap
amap!
i wykorzystać funkcjonalność ta ostatnia, kiedy można w miejscu.Zastosowanie mapreduce
mapreduce
jeszcze bardziej rozszerza funkcjonalność mapy i może być znaczącym oszczędzaniem bajtów.Anonimowe funkcje są świetne! .. szczególnie, gdy przejdziemy do wyżej wymienionych
map
funkcji.Funkcje skumulowanej tablicy
cumprod
,cumsum
aromatycznecummin
i inne podobnie nazwane funkcje umożliwiają kumulatywne operacje wzdłuż określonego wymiaru n-wymiarowej tablicy. (Lub * un * określono, jeśli tablica ma wartość 1-d)Krótka notacja dla Any Jeśli chcesz wybrać cały konkretny wymiar tablicy wielowymiarowej (lub Dict), np.
A[Any,2]
Możesz zapisać bajty za pomocąA[:,2]
Użyj funkcji jednowierszowej dla funkcji Zamiast tego
function f(x) begin ... end
często możesz uprościćf(x)=(...)
Użyj operatora trójskładnikowego Może to być oszczędność miejsca dla konstrukcji z wyrażeniem pojedynczym wyrażenia If-Then-Else. Ostrzeżenia: Chociaż w niektórych innych językach jest to możliwe, nie można pominąć części po dwukropku w Julii. Ponadto operator ma poziom wyrażeń w Julii, więc nie można go używać do warunkowego wykonywania całych bloków kodu.
if x<10 then true else false end
vsx<10?true:false
źródło
Iteracja po funkcjach
Jest to również możliwe w innych językach, ale zwykle dłużej niż prosta metoda. Jednak zdolność Julii do redefiniowania jej jednoargumentowych i binarnych operatorów sprawia, że gra jest dość golfowa.
Na przykład, aby wygenerować tabelę dodawania, odejmowania, mnożenia i dzielenia dla liczb naturalnych od 1 do 10, można użyć
który redefines binarnego operatora
|
jak+
,-
,*
i÷
, następnie obliczax|y
dla każdej operacji, ax
iy
w pożądanych granicach.Działa to również dla jednoargumentowych operatorów. Na przykład, aby obliczyć liczby zespolone 1 + 2i , 3-4i , -5 + 6i i -7-8i , ich negatywy, ich złożone koniugaty i ich multiplikatywne inwersje, można użyć
który redefines jednoargumentowy operatora
~
jak+
,-
,conj
iinv
, następnie oblicza~x
dla wszystkich żądanych liczb zespolonych.Przykłady w rzeczywistych konkursach
Sekwencje żeńskie i męskie (binarne)
Permutacja sprawy (jednostkowa)
źródło
Słowa kluczowe mogą czasami natychmiast następować po stałych bez potrzeby stosowania spacji lub średnika. Na przykład:
Zwróć uwagę na brak spacji między
1
iend
. Dotyczy to również zjawiskaend
występującego po zamknięciu miąższu, tj)end
.Wykonać Integer podział stosując
÷
zamiastdiv()
lub przeciążenia operatora. Zauważ, że÷
w UTF-8 jest wart 2 bajty.Użyj
vec()
lubA[:]
(dla niektórych tablicA
) zamiast,reshape()
gdy to możliwe.Twórz funkcje zamiast pełnych programów, jeśli jest to dozwolone w regułach wyzwania. Krótsze jest zdefiniowanie funkcji, która akceptuje dane wejściowe niż definiowanie zmiennych poprzez odczyt ze standardowego wejścia. Na przykład:
Zmienne można zwiększać wewnątrz argumentu funkcji. Na przykład, oto moja odpowiedź na wyzwanie Znajdź następny 1-rzadki numer binarny :
Jest to krótsze niż zwiększanie
n
wewnątrz pętli.źródło
return
f(x)=x+4
jest identyczny, ale krótszy niżf(x)=return x+4
. Julia zawsze zwraca wynik ostatniej instrukcji.[x for x in 1:4]
ma 3 znaki dłuższe niż, ale równoważne[x for x=1:4]
źródło
Użyj wywołań funkcji nadawania.
Wprowadzono w Julii 0.5. To jest jak mapa, ale zużywa mniej znaków i zachowuje się w stosunku do swoich argumentów - co oznacza, że możesz napisać mniej lambda do radzenia sobie z rzeczami.
Zamiast:
map(f,x)
- 8 znaków.f.(x)
- 5 znakówJeszcze lepiej:
map(a->g(a,y),x)
- 16 znakówg.(x,[y])
- 9 znakówźródło