AutoCAD... AutoLISP... VisualLISP...

  [18] Ciąg arytmetyczny

index  

»  Ciąg arytmetyczny - nieco teorii

Przywołując najprostszą szkolną definicję ciągu arytmetycznego dowiemy się że:

"Skończony ciąg liczbowy (a1,a2, ... ,an) nazywamy ciągiem arytmetycznym wtedy i tylko wtedy, gdy jest on co najmniej trzywyrazowy , i którego każdy wyraz począwszy od drugiego, powstaje przez dodanie do wyrazu poprzedniego stałej liczby r, zwanej różnicą ciągu."

Cały czas będąc w kręgu tej szkolnej definicji, znając właściwości języka LISP łatwo można zauważyć, że w "nomenklaturze" lispowej byłaby to uporządkowana (rosnąca lub malejaca) lista elementów liczbowych. Przyglądając się uważniej otaczającej nas rzeczywistości, niewykluczonym jest dostrzeżenie pewnych prawidłowości - będących odzwierciedleniem ciągu arytmetycznego.

»  Ciąg a lista

W programowaniu AutoCAD-a, niejednokrotnie spotkałem się z potrzebą tworzenia list danych mającą strukturę ciągu arytmetrycznego. Przykładowo, lista (100 101 102 103 104 105) jest 6-elementową listą liczb całkowitych, gdzie pierwszym elementem jest 100 a różnica wynosi 1. Aby utworzyć taką listę wykorzystuje się standardową funkcję do deklarowania list czyli funkcję list. Wygląda to tak: (list 100 101 102 103 104 105). Zastosowanie takiej formy ma sens jedynie gdy znamy wszystkie elementy listy, i lista jest na tyle krótka że jest uzasadnione jej ręczne wpisanie jako kod programu. Inaczej jest gdy wartości parametrów nie są poczatkowo znane (wynikają one np. z obliczeń). Wtedy jedynym sposobem zdaje się być wykorzystanie odpowiedniej funkcji.

»  Definicja funkcji

Odchodząc od (tylko) matematycznego punktu widzenia, chcemy utworzyć listę o znanej długości, zaczynającej się od pewnej liczby, a następne elementy listy (zgodnie z definicją ciągu arytmetycznego), będą rosły lub malały o pewną stałą wartość. Oczywistym jest określenie warunków potrzebnych do obliczeń. Zakładamy trzy: pierwszy element listy, długość listy, i krok (różnica ciągu). Będą to argumenty funkcji - wiadomo też że wszystkie muszą być liczbami (długość listy - liczbą całkowitą). Funkcja będzie wyglądać tak:
(defun jk:CAL_Sequence (start lengt step / Tmp TmpList)
  (if
    (and (numberp start)(numberp lengt)(numberp step))
    (progn
      (setq Tmp Start)
      (while
        (< (length TmpList) (1- Lengt))
        (setq Tmp (+ Tmp Step))
        (setq TmpList (append (list Tmp) TmpList))
      )
      (cons Start (reverse TmpList))
    )
    Nil
  )
)

»  Zastosowanie

Podam tutaj kilka możliwych praktycznych zastosowań funkcji.

Rosnąca lista liczb całkowitych (trywialne)
Wywołanie: (jk:CAL_sequence 1 12 1) zwraca: (1 2 3 4 5 6 7 8 9 10 11 12)
Oczywiście gdy potrzebujemy, liczby możemy zamienić na łańcuchy tekstowe:
(mapcar 'itoa (jk:CAL_sequence 1 12 1)) zwraca:
("1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12")

Rosnąca lista liczb rzeczywistych (bez komentarza)
Wywołanie: (jk:CAL_sequence 0.0 10 25.4)
zwraca: (0.0 25.4 50.8 76.2 101.6 127.0 152.4 177.8 203.2 228.6)

Ponownie liczby całkowite (a więc alfabet)
Małe litery alfabetu:
(mapcar 'chr (jk:CAL_sequence 97 26 1))
daje w wyniku: ("a" "b" "c" "d" ... "w" "x" "y" "z")

Duże litery (genialne!):
(mapcar 'chr (jk:CAL_sequence 65 26 1))
("A" "B" "C" "D" ... "W" "X" "Y" "Z")

Wartości kątów podziału okręgu (tutaj na 12 części):
Wywołanie: (jk:CAL_sequence 0.0 12 (/ pi 6.0)) zwróci:
(0.0 0.523599 1.0472 1.5708 2.0944 2.61799 3.14159 3.66519 4.18879 4.71239 5.23599 5.75959)
Mając listę kątów - banalnym jest obliczenie punktów. Od ręki zbudujmy funkcję rysujacą linie o wspólnym początku, jednakowych długościach na podstawie listy kątów pochylenia:
(defun RysujLinie (Cen Len AngList)
  (mapcar
    '(lambda (%)
      (entmake
        (append
          '((0 . "LINE")(100 . "AcDbEntity")(100 . "AcDbLine"))
          (list (cons 10 Cen))
          (list (cons 11 (polar Cen % Len)))
        )
      )
    )
    AngList
  )
)
Wywołajmy teraz w linii poleceń:
(RysujLinie (getpoint "\nPunkt:") 200.0 (jk:CAL_sequence 0.0 12 (/ pi 6.0)))
Oczywiscie podział nie musi dotyczyc okregu - moze to byc łuk:
(RysujLinie (getpoint "\nPunkt:") 200.0 (jk:CAL_sequence 0.0 7 (/ pi 6.0)))

»  Zakończenie

Prezentowane tutaj przykłady są tylko częścią różnych możliwych zastosowań funkcji tworzącej listę wyrazów ciągu arytmetycznego.
Z powodzeniem może być wykorzystywana do obliczeń współrzednych punktów, odległości, kątów, tworzenia wykazów, zestawień, numerowania obiektów, itd. Myślę że w wielu przypadkach funkcja ta okaże się przydatna programującym.