Julia'da golf için ipuçları


20

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:


19

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ı

  1. Sık kullanılan ikili fonksiyonlara sahip aşırı yük operatörleri . Örneğin, çok sayıda tamsayı bölme yapmanız gerekiyorsa ve ters bölmeye gerek yoksa, kullanın \ =divve a\bbunun 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 divAlex A. tarafından belirtildiği gibi,
  2. Koşullu çıktı için dizelerle ^ kullanın . Olduğunu ziyade a>0?"Hi":"", kullanım "Hi"^(a>0)bir bayt kaydetmek veya boole a için kullanın "Hi"^aüç bayt kaydedin.
  3. (bazen) Küçük sabit boyutlu vektörleri ayrı değişkenler olarak saklayın . Örneğin, yerine 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 ave bataması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.
  4. Dizinin ilk öğesine erişim[] - diziler için ifade A[]eşittir A[1]. İlk karakteri almak istiyorsanız Dizeler için veya Tuples için çalışmaz.
  5. Diziler, Tuples veya Dizeler için isempty kullanmayın - bunun yerine ==[]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.
  6. "İf" yerine doğru kısa devre boole operatörünü kullanın . Julia'ya özgü biraz daha az olabilir, ancak akılda tutmaya değer. bir karakterin kaydedilmesi x<=1&&"Hi"şeklinde yazılabilir x>1||"Hi"(booleanın dönüşü önemli olmadığı sürece).
  7. Dizedeki karakterin varlığını kontrol etmek için içerir kullanmayın - temel ASCII ile sınırlıysanız, 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 .
  8. Bir dizideki minimum / maksimum değerleri mi arıyorsunuz? Minimum veya maksimum kullanmayın kullanmak yerine - minimum(x)ya maximum(x), kullanım min(x...)veya max(x...)biliyorsanız, kodunuzun kapalı bir karakter tıraş, xen az iki öğe olacaktır. Alternatif olarak, öğesinin tüm öğelerinin xnegatif olmayacağını biliyorsanız , minabs(x)veyamaxabs(x)
  9. Mümkün olduğunda ve meydan okuma tarafından izin verildiğinde, \ n yerine gerçek bir yeni satır kullanın - bunun kodunuzun okunmasını zorlaştıracağını ve insanların gerçekten anlayabilmelerini sağlamak için "ungolfed" sürümünü sağlamanız gerektiği anlamına gelebilir. o.
  10. Normal ifade dizesinden sonra seçenekleri koyun - çok satırlı modda normal ifade dizesi kullanmak istiyorsanız, örneğin üç karakter kaydetmeyin r"(?m)match^ this", yazın r"match^ this"m, yazın .
  11. Flipud kullanarak ters 1-D dizileri - reverse(x)bir bayt daha uzundur flipud(x)ve aynı işlemi gerçekleştirir, bu nedenle ikincisi daha iyidir.
  12. Mümkün olduğunda, push!, Unshift!, Append!, Orpend! Yerine dizi birleştirme kullanın! - normal diziler için bu kolayca yapılabilir. Dizi öğelerine sahip Any dizileri için, eklenen dizilerin çevresinde (yani {[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]].
  13. Bir dizinin veya dizenin boyutunu almak için dizi dizine ekleme özelliğini kullanın - dizi dizine eklemeend 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.
  14. Dizi indeksleme kullanarak bir dizin yineleyici alın - 13'e benzer şekilde, kullanarak bir dizinin uzunluğuyla eşleşen bir yineleyici de alabilirsiniz A[k=1:end], bu durumda kbir yineleyici eşleşmesi tutar 1:length(A). Diziyi Aaynı anda kullanmak istediğinizde bu yararlı olabilir .
  15. Bir dizeyi char dizisine dönüştürmek için koleksiyon kullanmayın - bunun yerine , aynı şeyi yapacak ve 4 bayt tasarruf edecek şekilde collect(A)kullanın [A...].
  16. Bir dizeye dönüştürülmüş bir numaraya mı ihtiyacınız var? Kullanın "$(s[i])"veya dec(s[i])ifadeler veya çok karakter değişkenleri için ve "$i"tek karakterlik değişkenler için.
  17. Kullanım ?:yerine &&veya ||şartlı atama için - Yalnızca bazı şartla atama gerçekleştirmek istiyorsanız,, sen yazarak bir bayt kaydedebilirsiniz cond?A=B:1yerine cond&&(A=B)veya cond?1:A=Byerine cond||(A=B). Not 1, burada, bir kukla değerdir.
  18. unionunique- 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.

2
Python'daki ilk numarayı nasıl seveceğim.
seequ

split("Hi there")Desen bağımsız değişkeni varsayılan olarak bir boşluk olduğu için boşlukları bölebilirsiniz .
Alex

@AlexA. - Biliyorum, ama bahşiş noktası değil ve bahşiş her iki şekilde de eşit derecede iyi.
Glen O

Nokta 12, 0.5 olarak değişti.
Lyndon White

@Oxinabox - Şaşırmadım, şu an birkaç tanesinin modası geçmiş olduğundan eminim. Başlangıçta 0.3 için ipuçlarının çoğunu yazdım, sanırım.
Glen O

15

İşlevleri tanımlamak için işleçleri yeniden tanımlama

Operatörleri yeniden tanımlamak parantez ve virgüllere çok sayıda bayt kaydedebilir.

Özyinelemeli tekli operatörler

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

Çevrimiçi deneyin!

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.

İkili işleçler

Ö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

Çevrimiçi deneyin!

Yinelemeli ikili işleçler

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

Çevrimiçi deneyin!

^Ö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.


11
  1. 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ış Dicttipte döndürülmesi . Bu nedenle, istediğiniz verileri elde etmek için maliyetli collect(keys())ve collect(values())potansiyel olarak a catve a gerektirir sort. Çoğu durumda, deneme bölümü tarafından sadece çarpanlarına ayırmak daha ucuz olabilir. Acı ama gerçek.

  2. Haritayı kullanmak map , döngüye mükemmel bir alternatiftir. Arasındaki farkın farkında olun mapve map!ve sonrakinin yerinde işlevselliğini zaman yapabilirsiniz istismar.

  3. Mapreduce kullanımı mapreduce , haritanın işlevselliğini daha da genişletir ve önemli bir bayt tasarrufu olabilir.

  4. Anonim işlevler harika! ..özellikle yukarıda belirtilen mapfonksiyonlara geçildiğinde .

  5. Birikimli dizi işlevleri cumprod , cumsumlezzetli cumminve 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)

  6. 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]

  7. İşlevler için tek satırlı gösterimi kullanma Bunun yerine function f(x) begin ... endgenellikle basitleştirebilirsinizf(x)=(...)

  8. Üç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 endvs
    x<10?true:false


3
Yeryüzünde Julia'ya özgü "üçlü operatörü kullan" nasıl olur? Sahip olduğu her dil ile ilgilidir.
Peter Taylor

5
Onun olması önemlidir. Birçok dilde ayrıca harita, anonim veya saf işlevler, herhangi bir / tüm için kısayol, kümülatif işlevler vb. .
Jonathan Van Matre

3
Tanrım, sadece yeni başlayanlar için tüm fonksiyonel olanlar, her şeyin bir değer döndürdüğü, böylece üçlü bir op gereksiz olurdu. Belirli örneklere sahip olmanız gerekiyorsa: Go, Haskell, Scala, Lua, VB, Prolog, PL / SQL ... hatta Python pek çok sürüm için yoktu. İpuçları iş parçacığı üçlü operatör bahseden düzinelerce dilden sadece benim için il olmayı seçmenin bir nedeni var mı?
Jonathan Van Matre

3
Hey, en azýndan eţit fýrsat bir curmudgeon'sýn. ヘ ( ̄ ー  ̄ ヘ)
Jonathan Van Matre

1
3. ucu ayarlamanızı önerebilir miyim? mapreduce, mapfoldl veya mapfoldr'den daha uzundur ve uygulamaya bağlı olarak farklı davranışlarda bulunabilir. mapfoldl ve mapfoldr (sırasıyla) sol ve sağ ilişkiseldir ve bu nedenle daha iyi bir seçimdir. Bu aynı zamanda genel olarak azaltmak için de geçerlidir (katlama veya katlama kullanın).
Glen O

9

Fonksiyonlar üzerinde yineleme

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|yher işlem için ve xve yarzu 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 +, -, conjve invdaha sonra hesaplar ~x, istenen tüm karmaşık sayılar için.

Gerçek yarışmalara örnekler


6
  1. 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 1ve end. Bu aynı zamanda endyakın bir parantezden sonra meydana gelmesi için de geçerlidir )end.

  2. 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 .

  3. Mümkün olduğunda değil vec()veya A[:](bazı diziler için A) kullanın reshape().

  4. 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
  5. 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, ndöngünün içindeki artıştan daha kısadır .


6
  1. Yazmareturn f(x)=x+4 aynıdır ancak daha kısadır f(x)=return x+4. Julia her zaman son ifadenin sonucunu döndürür.
  2. İn yerine = kullanın . [x for x in 1:4]3 karakterden daha uzun, ancak[x for x=1:4]

5

Yayın işlevi çağrılarını kullanın.

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 karakter

Halen daha iyi:

  • map(a->g(a,y),x) - 16 karakter
  • g.(x,[y]) - 9 karakter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.