K'da golf için ipuçları


17

K, Arthur Whitney tarafından tasarlanan APL ailesinde bir programlama dilidir. Resmi tercüman kapalı ve ticari olsa da, 32 bit adres alanı (kod golfü için sorun oluşturmaması gereken) çalışma alanı sınırına sahip bir deneme sürümü Kx Systems web sitesinde bulunabilir. Kdb + veritabanının bir parçası olarak paketlenen bu sürüm konuşma dilinde "K4" olarak bilinir. K3 tabanlı Kona ve oK adlı kendi tercümanım da dahil olmak üzere açık kaynaklı K uygulamaları da mevcut. K5 tabanlı ve tarayıcı tabanlı REPL içeren .

Kx Systems, K4 / kdb + / Q bilgilerine sahip bir wiki'ye sahiptir ve Kona GitHub sayfası da mükemmel bir koleksiyona sahiptir. referans malzemelerin. OK / k5 için kullanışlı bir referans olabilecek bir kılavuz yazmaya başladım .

Gibi J ve APL, K çok veciz ve güçlü bir dildir ve genellikle kod golf gösteren iyi olmasını sağlayabilen. Lütfen keşfettiğiniz ipuçlarını, püf noktalarını ve deyimleri paylaşın ve daha önce K'yi denemediyseniz, bir dönüş yapmayı düşünün! Her cevap için bir ipucu gönderin, lütfen!

Yanıtlar:


5

Bir Dyad Çağırma

İkili (2 bağımsız değişken) bir işleve sahip olduğunuzu varsayarsak f:

f: {x+2*y}

Normalde şöyle derdiniz:

f[3;47]

Bir karakteri ilk argümanda kıvırıp sonra ortaya çıkan kısmi işlevi yan yana yerleştirerek ikinci argümana uygulayarak bir karakteri kaydedebilirsiniz:

f[3]47

Aynı şey doğal olarak dizi indeksleme için de geçerlidir:

  z: (12 17 98;90 91 92)
(12 17 98
 90 91 92)

  z[1;2]
92

  z[1]2
92

5

Yeni satır yazdırma

Çıktınızın yeni bir satırı olması gerekiyorsa , bunu yapmaya cazip gelebilirsiniz:

`0:whatever,"\n"

Yapma . K2 (ve muhtemelen diğer sürümler), bir satır listesi yazdırabileceğiniz düzgün bir özelliğe sahiptir:

  `0:("abc";"def")
abc
def

Dolayısıyla, çıktıya yeni satır eklemeniz gerekiyorsa, şunları yapın:

`0:,whatever

3

aralıklar

Normalde, kullandığınız ardışık sayıların bir vektörünü oluşturmak istiyorsanız !:

  !5
0 1 2 3 4

Sıfır dışında bir sayı ile başlayan bir aralık oluşturmak istiyorsanız, sonuçta elde edilen vektöre bir uzaklık eklersiniz:

  10+!5
10 11 12 13 14

Belirli bir durum için daha iyi çalışabilecek birkaç alışılmadık yaklaşım vardır. Örneğin, tabanınız ve uzaklığınız zaten bir listenin üyesiyse, iki kez "nerede" kullanabilirsiniz:

  &10 5
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1
  &&10 5
10 11 12 13 14

Daha yavaş büyüyen diziler için, "where" ile "take" birleştirmeyi düşünün:

  5#2
2 2 2 2 2
  &5#2
0 0 1 1 2 2 3 3 4 4

Bir dizi kat oluşturmak istiyorsanız, sonucun çarpımını yapabilir !veya \adım boyutundaki kopyaların bir listesini tarayabilirsiniz ( ):

  2*!5
0 2 4 6 8
  +\5#2
2 4 6 8 10

Parantezlerden kaçınmaya çalışıyorsanız, sekansın uzunluğu değişkense ve adım boyutu sabitse, ilki daha iyidir, adım boyutu değişme eğilimi olan adım ise daha iyidir. Doğru varyasyonu seçmek 1 veya 2 karakter kaydedebilir. Tek tek fark sizin lehinize de çalışabilir.


2

Dizelerden yayınlar pahalıdır. Sadece eval kullanın. Bu:

0.0$a

sadece bu olabilir:

. a

K5'te, bir bayt daha kısadır:

.a

2

Her Hak

Bazen her monad aracılığıyla uygulanan parantez içine alınmış bir ifade yazarken (veya basitleştirerek ulaştığınızda) kendinizi bulabilirsiniz:

  (2#)'3 4 5
(3 3
 4 4
 5 5)

Bu kalıbı her bir sağın bir uygulamasına dönüştürmek bir karakter daha kısadır:

  2#/:3 4 5
(3 3
 4 4
 5 5)

1

Devirli Permütasyonlar

!K3 / K4'teki ikili "döndür" dür:

  2!"abcd"
"cdab"
  -1!"abcd"
"dabc"

"Tarama" ( \) bir monadik fiil ile sağlandığında, sabit nokta operatörü görevi görür. K'de, sabit nokta operatörleri ilk değer yeniden gözden geçirilene veya değer değişmeyi bırakana kadar fiillerini bir değere tekrar tekrar uygular. Döndürmeyi sabit noktalı tarama ile birleştirmek, bir listenin bir dizi döngüsel permütasyonunu hesaplamak için çok uygun bir yol sağlar:

  ![1]\1 2 4 8
(1 2 4 8
 2 4 8 1
 4 8 1 2
 8 1 2 4)

!Fiil trenini oluşturmak için parantez üzerinden köri veya parantez içine alabilirsiniz (1!):

![1]\
(1!)\

(Bunu not et 1!\ Tamamen farklı bir davranışa sahip !) Bunların her birinin uzunluğu eşittir, ancak rotasyon adımı 1'den başka bir şeyse, ilk seçenek daha arzu edilebilir; bu durumda, parantezler "ücretsiz" olarak parantez içine alınmış bir alt ifadeyi sınırlar.

Örnek olarak, x dizesinin y dizgesini y (döngüsel olarak!) İçerip içermediğini kaba kuvvetle test eden kısa bir program:

{|/(y~(#y)#)'![1]\x}

K5 kullanıcıları dikkat! K5, ikiliğin anlamını değiştirdi !, bu yüzden bu teknik o kadar kolay değil. Kona'da beklendiği gibi çalışacaktır.


1

Koşullardan Kaçının

K, :[Lisp stiline eşdeğer bir koşullu yapıya ( ) sahiptir cond:

:[cond1;result1; cond2;result2; cond3;result3; default]

İstediğiniz kadar koşulunuz olabilir ve bunlardan hiçbiri eşleşmezse varsayılan değer döndürülür.

Bazen (özyinelemeli programlarda veya bir dizi yan etkiye dayanan programlarda olduğu gibi), bunlardan birini kullanmanın bir yolu yoktur. Ancak, biraz fazladan iş yapmayı göze alabileceğiniz durumlarda, genellikle bir "cond" i liste indeksleme ile değiştirebilirsiniz.

Kötü şöhretli fizzbuzz programını düşünün . Geleneksel bir zorunluluk programlama tarzında yazılmış, biz ile gidebiliriz:

{:[~x!15;"FizzBuzz";~x!3;"Fizz";~x!5;"Buzz";x]}'1+!100

Bölünebilirlik testlerinde burada biraz tekrar var. Farklı bir yaklaşım, 4 vaka olduğunu (bir sayı, sadece 3'e bölünebilirlik, sadece 5'e bölünebilirlik, 3 ve 5'e bölünebilirlik) olduğunu ve bu vakalardan birini listeden seçen bir dizini doğrudan hesaplamaya çalışır:

{(x;"Fizz";"Buzz";"FizzBuzz")@+/1 2*~x!/:3 5}'1+!100

İki karakter daha kısadır ve dili daha iyi kullanır. Liste değişmezlerinin sağdan sola değerlendirildiğini bilerek, yeniden kullanılan alt ifadeleri birleştirmek için bazı ek golf fırsatları da elde ederiz. Dize durumları seçilmedikleri takdirde hiç değerlendirilmediğinden, koşul tabanlı sürümde bunu kolayca yapamazdık:

{(x;4#t;4_ t;t:"FizzBuzz")@+/1 2*~x!/:3 5}'1+!100

Şimdi toplamda 5 karakter kaydettik. Bu arada, bu belirli örnek k5'te daha iyi çalışır, çünkü /bir katsayı vektörü ile çarpma ve toplama adımını işlemek için "paket" aşırı yükümüz vardır:

{(x;4_t;4#t;t:"FizzBuzz")@2 2/~3 5!\:x}'1+!100

Ayrıca ?, öğe bulunmazsa anahtar listesinin sonundan sonra bir dizin oluşturan "find" ( ) davranışının, bu tür bir dizin oluşturma işleminde "varsayılan" bir vakanın işlenmesini desteklemek üzere özel olarak tasarlandığını unutmayın. Sesli harfleri büyük harfe dönüştürmek için bu parçayı düşünün:

{("AEIOU",x)"aeiou"?x}'

Aşağıdakilerden birine karşı:

{t:"aeiou"?x;:[t<5;"AEIOU"t;x]}'
{:[~4<t:"aeiou"?x;"AEIOU"t;x]}'

(Hangisini de okumayı tercih ettiğimi biliyorum!)

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.