Julia'da golf oynamak için hangi genel ipuçlarınız var? Ben en azından biraz Julia'ya özgü (örneğin "yorumları kaldırmak" bir cevap değildir) genel kod golf sorunlarına uygulanabilecek fikirler arıyorum.
Julia'da golf oynamak için hangi genel ipuçlarınız var? Ben en azından biraz Julia'ya özgü (örneğin "yorumları kaldırmak" bir cevap değildir) genel kod golf sorunlarına uygulanabilecek fikirler arıyorum.
Yanıtlar:
NOT: Julia henüz yapı bakımından oldukça kararlı olmadığı için, aşağıda bazı eski ipuçları bulunabilir.
Birkaç karakteri kaydetmek için birkaç püf noktası
\ =div
ve a\b
bunun yerine yazabilirsiniz div(a,b)
. Alanı not edin - "\ =" operatörü olarak ayrıştırılmasını önlemek için bu gereklidir. Ayrıca, REPL komut istemi düzeyinde aşırı yüklendiğinde, sıfırlamak için (\)=Base.(\)
veya \ =Base. \
düğmesini kullanın . NOT: Bazı fonksiyonlar UTF-8 operatörleri gibi, önceden tanımlanmış mevcut olması ÷
için div
Alex A. tarafından belirtildiği gibi,a>0?"Hi":""
, kullanım "Hi"^(a>0)
bir bayt kaydetmek veya boole a için kullanın "Hi"^a
üç bayt kaydedin.a=split("Hi there"," ")
, sen kaçınmak mümkün olabilir a[1]
ve a[2]
kullanılarak a,b=split("Hi there"," ")
başvurulabilir hangi a
ve b
atamasının sadece iki ekstra karakter pahasına her kullanım için üç bayt tasarruf. Açıkçası, vektör işlemleriyle çalışabiliyorsanız bunu yapmayın.[]
- diziler için ifade A[]
eşittir A[1]
. İlk karakteri almak istiyorsanız Dizeler için veya Tuples için çalışmaz.==[]
diziler ve ==()
tuples için kullanın ; benzer şekilde, negatif için, !=[]
ve kullanın !=()
. Dizeler ==""
için boş için kullanın , ancak boş >""
olmayan için kullanın , çünkü "" diğer sözcüklerden önce sözlükbilimsel olarak.x<=1&&"Hi"
şeklinde yazılabilir x>1||"Hi"
(booleanın dönüşü önemli olmadığı sürece).in('^',s)
yerine kullanın contains(s,"^")
. Başka karakterler kullanabiliyorsanız, ile biraz daha fazla tasarruf edebilirsiniz '^'∈s
, ancak ∈
UTF-8'de 3 bayt olduğunu unutmayın .minimum(x)
ya maximum(x)
, kullanım min(x...)
veya max(x...)
biliyorsanız, kodunuzun kapalı bir karakter tıraş, x
en az iki öğe olacaktır. Alternatif olarak, öğesinin tüm öğelerinin x
negatif olmayacağını biliyorsanız , minabs(x)
veyamaxabs(x)
r"(?m)match^ this"
, yazın r"match^ this"m
, yazın .reverse(x)
bir bayt daha uzundur flipud(x)
ve aynı işlemi gerçekleştirir, bu nedenle ikincisi daha iyidir.{[1,2]}
, değil {1,2}
) süslü parantezlere ihtiyacınız olacaktır - Julia 0.4 için ihtiyacınız olacaktır Any[[1,2]]
.end
içinde kullandığınızda , otomatik olarak dizinin / dizenin uzunluğuna dönüştürülür. Bu nedenle k=length(A)
, A[k=end]
3 karakter kaydetmek için kullanın . Hemen k kullanmak istiyorsanız bunun yararlı olmayabileceğini unutmayın. Bu aynı zamanda çok boyutlu bir durumda da çalışır - A[k=end,l=end]
her bir boyutun boyutunu alacaktır A
- ancak, (k,l)=size(A)
bu durumda bir bayt daha kısadır, bu yüzden sadece son öğeye aynı anda erişmek istiyorsanız kullanın.A[k=1:end]
, bu durumda k
bir yineleyici eşleşmesi tutar 1:length(A)
. Diziyi A
aynı anda kullanmak istediğinizde bu yararlı olabilir .collect(A)
kullanın [A...]
."$(s[i])"
veya dec(s[i])
ifadeler veya çok karakter değişkenleri için ve "$i"
tek karakterlik değişkenler için.?:
yerine &&
veya ||
şartlı atama için - Yalnızca bazı şartla atama gerçekleştirmek istiyorsanız,, sen yazarak bir bayt kaydedebilirsiniz cond?A=B:1
yerine cond&&(A=B)
veya cond?1:A=B
yerine cond||(A=B)
. Not 1
, burada, bir kukla değerdir.union
∪
unique
- veya yerine - kullanınunion(s)
ve aynı unique(s)
işlemi yapar ve işlemde bir bayt kaydeder. ASCII olmayan karakterler kullanabiliyorsanız ∪(s)
, aynı işlemi yapar ve ∪
5 bayt yerine yalnızca 3 bayt tutar union
.split("Hi there")
Desen bağımsız değişkeni varsayılan olarak bir boşluk olduğu için boşlukları bölebilirsiniz .
Operatörleri yeniden tanımlamak parantez ve virgüllere çok sayıda bayt kaydedebilir.
Alışılmadık bir örnek için, Fibonacci dizisinin aşağıdaki özyinelemeli uygulamalarını karşılaştırın:
F(n)=n>1?F(n-1)+F(n-2):n # 24 bytes
!n=n>1?!~-n+!(n-2):n # 20 bytes
!n=n>1?!~-n+!~-~-n:n # 20 bytes
Yeniden tanımlanmış operatör ilk önceliğini korur.
Biz sadece dışarı takas edemeyeceği Not !
lehine ~
beri ~
zaten tamsayılar için tanımlanmış ise, !
sadece Booleans için tanımlanır.
Özyineleme yapılmasa bile, bir operatörün yeniden tanımlanması ikili bir fonksiyon tanımlamaktan daha kısadır. Basit bir bölünebilirlik testinin aşağıdaki tanımlarını karşılaştırın.
f(x,y)=x==0?y==0:y%x==0 # 23 bytes
(x,y)->x==0?y==0:y%x==0 # 23 bytes
x->y->x==0?y==0:y%x==0 # 22 bytes
x\y=x==0?y==0:y%x==0 # 20 bytes
Aşağıda Ackermann işlevini hesaplamak için ikili bir işlecin nasıl yeniden tanımlanacağı gösterilmektedir:
A(m,n)=m>0?A(m-1,n<1||A(m,n-1)):n+1 # 35 bytes
^ =(m,n)->m>0?(m-1)^(n<1||m^~-n):n+1 # 36 bytes
| =(m,n)->m>0?m-1|(n<1||m|~-n):n+1 # 34 bytes
m\n=m>0?~-m\(n<1||m\~-n):n+1 # 28 bytes
^
Önceliği çok yüksek olduğundan, normal bir tanımlayıcı kullanmaktan daha uzun olduğuna dikkat edin .
Önceden belirtildiği üzere
m|n=m>0?m-1|(n<1||m|~-n):n+1 # 28 bytes
|
bu durumda zaten tanımlandığından tamsayı bağımsız değişkenleri için çalışmaz . Tamsayılar için tanım olabilir ile değiştirilebilir
m::Int|n::Int=m>0?m-1|(n<1||m|~-n):n+1 # 38 bytes
ama bu çok uzun. Ancak, does biz sol argüman ve sağ argüman olarak bir tamsayı olarak bir float geçirirseniz işi.
Faktör (n) tarafından çok kolay baştan çıkarılmayın Cazip temel kütüphane işlevinin factor(n)
ölümcül bir kusuru vardır: tamsayılarınızın çarpanlarına ayrıştırılmamış Dict
tipte döndürülmesi . Bu nedenle, istediğiniz verileri elde etmek için maliyetli collect(keys())
ve collect(values())
potansiyel olarak a cat
ve a gerektirir sort
. Çoğu durumda, deneme bölümü tarafından sadece çarpanlarına ayırmak daha ucuz olabilir. Acı ama gerçek.
Haritayı kullanmak map
, döngüye mükemmel bir alternatiftir. Arasındaki farkın farkında olun map
ve map!
ve sonrakinin yerinde işlevselliğini zaman yapabilirsiniz istismar.
Mapreduce kullanımı mapreduce
, haritanın işlevselliğini daha da genişletir ve önemli bir bayt tasarrufu olabilir.
Anonim işlevler harika! ..özellikle yukarıda belirtilen map
fonksiyonlara geçildiğinde .
Birikimli dizi işlevleri cumprod
, cumsum
lezzetli cummin
ve diğer benzer şekilde adlandırılmış işlevler, bir n-boyutlu dizinin belirli bir boyutu boyunca birikimli işlemleri mümkün kılar. (Veya dizi 1-d ise * un * belirtilir)
Herhangi biri için kısa gösterim Çok boyutlu bir dizinin (veya Dict'ın) belirli bir boyutunu seçmek istediğinizde, örneğin A[Any,2]
baytlarıA[:,2]
İşlevler için tek satırlı gösterimi kullanma Bunun yerine function f(x) begin ... end
genellikle basitleştirebilirsinizf(x)=(...)
Üçlü işleci kullanma Tek ifadeli If-Then-Else yapıları için yer tasarrufu sağlayabilir. Uyarılar: Diğer bazı dillerde mümkün olsa da, Julia'daki iki nokta üst üste işaretinden sonraki bölümü atlayamazsınız. Ayrıca, operatör Julia'da ifade düzeyindedir, bu nedenle onu tüm kod bloklarının koşullu yürütülmesi için kullanamazsınız.
if x<10 then true else false end
vs
x<10?true:false
Bu, diğer dillerde de mümkündür, ancak genellikle doğrudan yöntemden daha uzundur. Bununla birlikte, Julia'nın tek ve ikili operatörlerini yeniden tanımlama yeteneği onu oldukça golfçüler kılar.
Örneğin, 1'den 10'a kadar olan doğal sayılar için toplama, çıkarma, çarpma ve bölme tablosu oluşturmak için
[x|y for x=1:10,y=1:10,| =(+,-,*,÷)]
burada yeniden tanımlar ikili operatörü |
olarak +
, -
, *
ve ÷
daha sonra hesaplar x|y
her işlem için ve x
ve y
arzu edilen seviyede.
Bu, tekli operatörler için de geçerlidir. Örneğin, 1 + 2i , 3-4i , -5 + 6i ve -7-8i karmaşık sayılarını , negatiflerini, karmaşık eşleniklerini ve çarpma terslerini hesaplamak için
[~x for~=(+,-,conj,inv),x=(1+2im,3-4im,-5+6im,-7-8im)]
burada yeniden tanımlar tekli operatörü ~
olarak +
, -
, conj
ve inv
daha sonra hesaplar ~x
, istenen tüm karmaşık sayılar için.
Kadın ve Erkek Dizileri (ikili)
Vaka Permütasyonu (tekli)
Anahtar kelimeler bazen boşluk veya noktalı virgül kullanmadan sabitleri hemen takip edebilir. Örneğin:
n->(for i=1:n n-=1end;n)
Arasında bir boşluk olmaması dikkat 1
ve end
. Bu aynı zamanda end
yakın bir parantezden sonra meydana gelmesi için de geçerlidir )end
.
Bir operatörü aşırı yüklemek veya aşırı yüklemek ÷
yerine tamsayı bölümü gerçekleştirin div()
. ÷
UTF-8'de 2 bayt değerinde olduğunu unutmayın .
Mümkün olduğunda değil vec()
veya A[:]
(bazı diziler için A
) kullanın reshape()
.
Meydan okuma kurallarında izin verildiğinde tam programlar yerine işlevler oluşturun. Stdin'den okuyarak değişkenleri tanımlamak yerine girişi kabul eden bir işlev tanımlamak daha kısadır. Örneğin:
n->(n^2-1)
n=read(STDIN,Int);n^2-1
Değişkenler, bir işlevin bağımsız değişkeninin içinde artırılabilir. Örneğin, aşağıdaki olan cevabım için Bul Sonraki 1-Seyrek İkili Sayı zorluk:
n->(while contains(bin(n+=1),"11")end;n)
Bu, n
döngünün içindeki artıştan daha kısadır .
Julia 0.5'te tanıtıldı. Harita gibidir, ancak daha az karakter kullanır ve onun argümanları üzerinde yayın davranışı yapar - bu, şeylerle uğraşmak için daha az lambda yazabileceğiniz anlamına gelir.
Ziyade:
map(f,x)
-- 8 karakter.f.(x)
- 5 karakterHalen daha iyi:
map(a->g(a,y),x)
- 16 karakterg.(x,[y])
- 9 karakter