Powrót do strony głównej

dc: programowanie na kalkulatorze stosowym

dc — stosowy kalkulator Unix jako język programowania z rejestrami, makrami i rekurencją. Artykuł omawia model stosowy, konstrukcje warunkowe, przykłady FizzBuzz i Peg Solitaire z pełnym kodem.

Programujemy FizzBuzz w dc: od stosu do gry
Advertisement 728x90

dc: kalkulator jako język programowy dla programistów

dc to klasyczny kalkulator z Unix, starszy niż język C, wchodzący w skład standardowych dystrybucji większości systemów, w tym macOS. Za fasadą prostego narzędzia kryje się pełnoprawny język programowania stosowy z rejestrami, makrami, konstrukcjami warunkowymi i rekurencją. Podstawowy model to stos: liczby i ciągi znaków są umieszczane na stosie za pomocą poleceń, operatory pobierają górne elementy, wykonują działanie i zwracają wynik.

Pierwsze obliczenie: dla sumy 2 + 2 wprowadź 2 2 + p. Tutaj 2 2 umieszcza liczby na stosie wiersz po wierszu, + sumuje dwa górne elementy, p wypisuje wynik.

2 2 +
p
4

Stos to kluczowy element: każdy literał (liczba lub [ciąg znaków]) wrzuca wartość na wierzch. Komentarze zaczynają się od #.

Google AdInline article slot

Praca z rejestrami i zmiennymi

dc zapewnia 256 rejestrów (a-z, 0-9 i inne znaki), przechowujących liczby lub ciągi znaków. Polecenia sR zapisują wierzchołek stosu do rejestru R, lR pobierają go z powrotem. Rejestry zachowują stan niezależnie od głównego stosu.

Przykład zapisania i przywrócenia ciągu znaków:

[Witaj świecie!] sx
lx
p
Witaj świecie!

Rejestry nadają się do zmiennych globalnych. Liczby w rejestrach są manipulowane tak samo jak na stosie: li do załadowania i na stos.

Google AdInline article slot

Makra jako funkcje

Funkcje w dc to makra: ciągi znaków w rejestrach, wykonywane poleceniem lRx, gdzie x to rejestr. Makra definiuje się jako [kod] sR.

Przykład funkcji sumującej rejestry a i b:

[la lb +] sS
1 sa
2 sb
lSx
p
3

Makra obsługują rekurencję i mogą wywoływać się nawzajem, tworząc podprogramy.

Google AdInline article slot

Konstrukcje warunkowe

Rozgałęzienia opierają się na porównaniach dwóch górnych elementów stosu. Operatory: =, >, <, != i inne. Jeśli warunek jest prawdziwy, wykonywane jest makro z określonego rejestru.

[[Równe] p] sE
[[Nierówne] p] sN
1 0
=E
1 0
!=N
Nierówne

Porównania zużywają dwa elementy ze stosu, wynik (0 lub 1) pozostaje.

Rekurencyjne pętle

Pętli nie ma, ale rekurencja jest realizowana przez samowywołanie makra. Przykład wypisywania liczb od 1 do 10:

[
	li p
	1 + si
	li 11 >C
] sC

1 si
lCx

Makro C wypisuje i, zwiększa i rekurencyjnie wywołuje się, dopóki i < 11. Bieżące i jest już na stosie przy wejściu.

  • Zalety rekurencji w dc: prostota, brak jawnych pętli.
  • Ograniczenia: ryzyko przepełnienia stosu przy głębokiej rekurencji.
  • Alternatywy: rekurencja ogonowa minimalizuje użycie stosu.

FizzBuzz w dc

Implementacja FizzBuzz do 100 demonstruje połączenie makr, warunków i rekurencji. Kluczowe polecenia: P (drukowanie bez nowej linii), c (czyszczenie stosu).

Pełny kod:

[[Fizz] P 0 sd] sF
[[Buzz] P 0 sd] sB
[li 3 % 0 =F li 5 % 0 =B] sW
[10 P] sP
[li p c] sD
[
  1 sd
  lWx
  ld 0 =P
  ld 1 =D
  li 1 + si
  li 101 >M
] sM

1 si
lMx

Logika: flaga d określa, czy drukować liczbę. Makro W sprawdza podzielność przez 3/5, ustawiając Fizz/Buzz. P z 10 (LF) dla nowej linii.

Zaawansowane zastosowania: Peg Solitaire

dc pozwala rozwiązywać złożone zadania, takie jak Peg Solitaire – łamigłówka ze skokami kołków na planszy. Stan planszy jest kodowany liczbą binarną, manipulacje odbywają się przez arytmetykę i operacje bitowe (dostępne przesunięcia, maski).

Formuły walidacji ruchów w RPN wyglądają skomplikowanie z powodu sprawdzeń bitowych, ale zapewniają pełną grę: od początkowej konfiguracji do końcowego kołka.

Takie podejście pokazuje dc jako narzędzie do prototypowania algorytmów bez kompilacji.

Co jest ważne

  • Stos to podstawa wszystkich operacji: literały wrzucają, operatory pobierają/wrzucają wyniki.
  • Rejestry (256 szt.) dla stanów, makra – dla podprogramów z lRx.
  • Warunki zużywają stos, rekurencja zastępuje pętle.
  • p/P do wypisywania, c do czyszczenia, % do modulo.
  • Nadaje się do skryptowania, prototypów, nauki RPN.

— Editorial Team

Advertisement 728x90

Czytaj dalej