Wskazówki do gry w golfa w K

17

K to język programowania w rodzinie APL zaprojektowany przez Arthura Whitneya. Podczas gdy oficjalny tłumacz jest językiem zamkniętym i komercyjnym, wersję próbną z ograniczeniem przestrzeni roboczej do 32 bitów przestrzeni adresowej (co nie powinno stwarzać problemów dla kodu golfa) można znaleźć na stronie Kx Systems . Ta wersja dołączona jako część bazy danych kdb + jest potocznie nazywana „K4”. Dostępne są również implementacje K typu open source, w tym Kona , która jest oparta na K3, oraz mój własny interpreter oK , który jest oparty na K5 i ma REPL oparty na przeglądarce .

Kx Systems ma wiki z informacjami K4 / kdb + / Q, a strona Kona GitHub ma również doskonałą kolekcję materiałów referencyjnych. Zacząłem pisać instrukcję dla ok / k5, która może być przydatnym źródłem informacji.

Podobnie jak J i APL, K jest bardzo zwięzłym i potężnym językiem i często potrafi dobrze pokazać się w golfie kodowym. Podziel się wskazówkami, sztuczkami i idiomami, które odkryłeś, a jeśli wcześniej nie próbowałeś K, zastanów się nad tym, aby spróbować! Napisz jedną wskazówkę na odpowiedź, proszę!

JohnE
źródło

Odpowiedzi:

5

Wezwanie Diada

Zakładając, że masz funkcję diadadową (2-argumentową) f:

f: {x+2*y}

Zwykle nazwałbyś to tak:

f[3;47]

Możesz zapisać znak, curry zamiast pierwszego argumentu, a następnie stosując wynikową funkcję częściową do drugiego argumentu przez zestawienie:

f[3]47

To samo oczywiście działa w przypadku indeksowania tablic:

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

  z[1;2]
92

  z[1]2
92
JohnE
źródło
5

Drukowanie nowych linii

Jeśli twój wynik musi mieć nowy wiersz, możesz ulec pokusie zrobienia tego:

`0:whatever,"\n"

Nie rób tego . K2 (i prawdopodobnie inne wersje) ma ciekawą funkcję, w której można wydrukować listę linii:

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

Tak więc, jeśli chcesz dołączyć nowy wiersz do wyniku, po prostu wykonaj:

`0:,whatever
kirbyfan64sos
źródło
3

Zakresy

Zwykle, jeśli chcesz utworzyć wektor liczb sekwencyjnych, którego używasz !:

  !5
0 1 2 3 4

Jeśli chcesz utworzyć zakres zaczynający się od liczby innej niż zero, możesz dodać przesunięcie do wynikowego wektora:

  10+!5
10 11 12 13 14

Istnieje kilka nietypowych podejść, które mogą działać lepiej w konkretnej sytuacji. Na przykład, jeśli podstawa i przesunięcie są już elementami listy, możesz dwukrotnie użyć „gdzie”:

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

W przypadku wolniej rosnących sekwencji rozważ połączenie „gdzie” z „weź”:

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

Jeśli chcesz utworzyć zakres wielokrotności, możesz pomnożyć wynik !lub zeskanować ( \) listę kopii wielkości kroku:

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

Jeśli starasz się unikać nawiasów, to pierwsze jest lepsze, jeśli długość sekwencji jest zmienna, a wielkość kroku jest stała, a druga jest lepsza, jeśli wielkość kroku jest tym, co zwykle się zmienia. Wybór odpowiedniej odmiany może zapisać 1 lub 2 znaki. Różnica indywidualna może również działać na twoją korzyść.

JohnE
źródło
2

Odlewy ze sznurków są drogie. Po prostu użyj eval. To:

0.0$a

może stać się tak:

. a

W K5 jest to bajt krótszy:

.a
kirbyfan64sos
źródło
2

Każde prawo

Czasami może się zdarzyć, że piszesz (lub upraszczasz) nawiasowe wyrażenie stosowane za pomocą każdej monady:

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

Jest o jeden znak krótszy, aby przekonwertować ten wzór na aplikację każdego prawa:

  2#/:3 4 5
(3 3
 4 4
 5 5)
JohnE
źródło
1

Cykliczne permutacje

Dyadic !w K3 / K4 jest „obracany”:

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

Kiedy „scan” ( \) jest dostarczany z czasownikiem monadycznym, działa on jako operator punktu stałego. W K operatory stałoprzecinkowe wielokrotnie stosują swój czasownik do wartości, dopóki wartość początkowa nie zostanie przywrócona lub wartość przestanie się zmieniać. Łączenie obrotu z skanowanie w punkcie stałym zapewnia bardzo wygodny sposób obliczania zestawu cyklicznych permutacji listy:

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

Możesz albo curry !za pomocą nawiasów, albo nawias, aby utworzyć ciąg czasownika (1!):

![1]\
(1!)\

(Zauważ, że 1!\ma zupełnie inne zachowanie!) Każda z nich ma równoważną długość, ale ta pierwsza może być bardziej pożądana, jeśli krok obrotu jest inny niż 1; w tym przypadku nawiasy ograniczają nawiasy podwyrażeniowe „za darmo”.

Jako przykład podajemy krótki program, który za pomocą brutalnej siły sprawdza, czy łańcuch x zawiera podciąg y (cyklicznie!):

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

Użytkownicy K5 strzeżcie się! K5 zmieniło znaczenie dyadic !, więc ta technika nie jest taka łatwa. Będzie działać zgodnie z oczekiwaniami w Kona.

JohnE
źródło
1

Unikaj warunków warunkowych

K ma konstrukcję warunkową ( :[) równoważną stylowi Lisp cond:

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

Możesz mieć tyle warunków, ile chcesz, a jeśli żaden nie pasuje, zwracana jest wartość domyślna.

Czasami (tak jak w programach rekurencyjnych lub programach, które w innym przypadku polegają na sekwencji efektów ubocznych), nie można się obejść przy użyciu jednego z nich. Jednak w sytuacjach, w których możesz sobie pozwolić na odrobinę dodatkowej pracy, często możesz zastąpić „cond” indeksowaniem list.

Zastanów się nad niesławnym programem fizzbuzz . Napisane w tradycyjnym stylu programowania imperatywnego, możemy użyć:

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

W testach podzielności jest sporo powtórzeń. Inne podejście uznaje, że istnieją 4 przypadki (liczba, podzielność tylko 3, podzielność tylko 5, podzielność 3 i 5) i próbuje bezpośrednio obliczyć indeks, który wybiera jeden z tych przypadków z listy:

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

Dwa znaki krótsze i lepsze wykorzystanie języka. Wiedząc, że literały listy są oceniane od prawej do lewej, zyskujemy także dodatkowe możliwości gry w golfa w celu połączenia ponownie używanych podwyrażeń. Nie moglibyśmy tego łatwo zrobić w wersji opartej na warstwie, ponieważ przypadki ciągów znaków nie są w ogóle oceniane, jeśli nie zostaną wybrane:

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

Teraz zapisaliśmy 5 znaków ogółem. Nawiasem mówiąc, ten konkretny przykład działa jeszcze ładniej w k5, ponieważ mamy przeciążenie „paczką” /do obsługi kroku mnożenia przez wektor współczynników i sumowania:

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

Zauważ też, że zachowanie „find” ( ?), które tworzy indeks poza końcem listy kluczy, jeśli element nie zostanie znaleziony, jest specjalnie zaprojektowane do obsługi obsługi „domyślnego” przypadku tego rodzaju indeksowania. Rozważ ten fragment, aby przekonwertować samogłoski na wielkie litery:

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

W porównaniu z jednym z:

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

(Wiem też, co wolałbym przeczytać!)

JohnE
źródło