15 tháng 12, 2008

Giới thiệu Pascal trên Ubuntu

Với Ubuntu 8.10 có thể dùng Free Pascal hoặc GNU Pascal. Cài đặt bằng lệnh:

$ sudo apt-get install fp-ide

hoặc

$ sudo apt-get install gpc

Free Pascal có IDE và hệ thư viện giống với Turbo Pascal của Borland năm xưa. Chạy chương trình fp là vào IDE của Free Pascal. Nếu không dùng IDE này (vốn không hỗ trợ Unicode/tiếng Việt) thì có thể dùng chương trình soạn thảo như vim, emacs, geany, gedit, bluefish, ... (có syntax hi-lightening, có hỗ trợ Unicode/tiếng Việt); khi ấy biên dịch (compile) bằng lệnh kiểu như fpc helloword.pas (với Free Pascal) hoặc gpc -o helloword helloword.pas (với GNU Pascal).

Ngoài ra, cũng có thể dùng Lazarus, môi trường lập trình (RAD - Rapid Application Development) cho Free Pascal, với giao diện tương tự Delphi của Borland.

$ sudo apt-get install lazarus

Lập trình Pascal hiện giờ nằm trong chương trình tin học phổ thông.

Tham chiếu:

Chương trình Pascal bảng số nguyên tố

prime-number-1.pas

(* ==================================================================

   Prime Numbers -- Số Nguyên Tố

   In tất cả các số nguyên tố trong khoảng 2..MaxNum

   Cách giải: Cho n chạy từ 2 đến MaxNum. Kiểm tra xem n có phải là
   số nguyên tố không. Nếu đúng thì in ra giá trị của n. Cách kiểm
   tra là cho i chạy từ 2 đến sqrt(n) và kiểm tra xem n có chia hết
   cho i không (n mod i ?= 0). Nếu chia hết cho một i nào đó thì n
   không phải là số nguyên tố.

   16-12-2008 triplc [at] gmail [dot] com

   ================================================================== *)

program PrimeNumbers;

const NumberPerRow = 6;        (* số các số mỗi dòng in *)
      NumberWidth  = 8;        (* độ rộng của từng số *)

var MaxNum       : longint;    (* dải các số cần tìm: 2..MaxNum *)
    n            : longint;    (* số đang được kiểm tra *)
    i            : longint;    (* phép kiểm tra n mod i = 0 *)
    PrimeFound   : longint;    (* số các số nguyên tố đã tìm được *)
    IsPrime      : boolean;    (* n có phải là số nguyên tố không *)

begin

  (* in tiêu đề chương trình *)
  WriteLn ('=================================================');
  WriteLn ('                  Prime Number                   ');
  WriteLn ('=================================================');
  WriteLn;

  (* đọc MaxNum *)
  Write ('MaxNum =? '); ReadLn (MaxNum); WriteLn;

  (* hiện nay mới tìm được 0 số nguyên tố *)
  PrimeFound := 0;

  (* kiểm tra tất cả các số từ 2 đến MaxNum *)
  for n := 2 to MaxNum do begin
    if (n <= 3) then
      (* n=2 và n=3 hiển nhiên là số nguyên tố *)
      IsPrime := True
    else begin
      (* kiểm tra xem n có chia hết cho i không, với mọi i*i<=n *)
      for i := 2 to Trunc (Sqrt (n)) do
        if (n mod i = 0) then break;
      (* n là số nguyên tố nếu n không chia hết cho i *)
      IsPrime := (n mod i <> 0);
    end;
    (* nếu n là số nguyên tố, thì ..... *)
    if IsPrime then begin
      (* in ra n *)
      Write (n:NumberWidth);
      (* tăng giá trị số đếm PrimeFound lên 1 đơn vị *)
      PrimeFound := PrimeFound + 1;
      (* in dấu xuống dòng mỗi khi in NumberPerRow số nguyên tố *)
      if (PrimeFound mod NumberPerRow = 0) then WriteLn;
    end;
  end;

  (* in phần kết của chương trình *)
  WriteLn;
  WriteLn;
  WriteLn ('Found ', PrimeFound, ' prime numbers in range 2..', MaxNum);
  WriteLn;
  WriteLn ('=================================================');

end.


prime-number-2.pas

(* ==================================================================

   Prime Numbers -- Số Nguyên Tố

   In tất cả các số nguyên tố trong khoảng 2..MaxNum

   Thuật giải "Sieve of Eratosthenes"
   http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
   http://en.wikipedia.org/wiki/Prime_number

   Diễn giải: Ban đầu giả sử tất cả các số từ 2 đến MaxNum đều là số
   nguyên tố. Sau đó loại ra tất cả các số nào không phải là số
   nguyên tố: tất cả bội số của 2, 3, 5... Ban đầu xét n=2, và thấy
   không bị loại (tức là n=2 là số nguyên tố), vậy ta loại tất cả bội
   của 2. Sau đó kiểm tra n=3, thấy chưa bị loại, vậy n=3 là số nguyên
   tố (vì nó không phải là bội của bất kỳ số nào nhỏ hơn nó), và ta
   loại tất cả bội của 3. Kiểm tra n=4 thì thấy đã bị loại (vì là bội
   số của 2), vậy bỏ qua. Kiểm tra với n=5, v.v. Đến khi loại hết tất
   cả các bội số của n với n <= sqrt(MaxNum) thì xong.

   16-12-2008 triplc [at] gmail [dot] com

   ================================================================== *)

program PrimeNumbers;

const MaxNum       = 1000;     (* dải các số cần tìm: 2..MaxNum *)
      NumberPerRow = 6;        (* số các số mỗi dòng in *)
      NumberWidth  = 8;        (* độ rộng của từng số *)

var IsPrime      : array [2..MaxNum] of boolean;
                               (* n có phải là số nguyên tố không *)
    i,n          : longint;    (* biến đếm *)
    PrimeFound   : longint;    (* số các số nguyên tố đã tìm được *)

begin

  (* khởi tạo IsPrime, giả sử tất cả đều là số nguyên tố *)
  for i := 2 to MaxNum do IsPrime[i] := True;

  (* cho n chạy từ 2 đến sqrt(MaxNum);
  n là giá trị cho biết rằng tất cả các IsPrime[i] với
  2 <= i <= n đều đã confirm đúng là số nguyên tố hay không *)
  for n := 2 to Trunc (Sqrt (MaxNum)) do
    (* nếu n không phải số nguyên tố thì không làm gì cả
    còn nếu n là số nguyên tố thì tất cả các bội số của n
    đều bị loại khỏi danh sách các số nguyên tố. Chỉ cần
    xác định các bội n*i với i>=n *)
    if IsPrime[n] then
      for i := n to Trunc (MaxNum / n) do
        IsPrime[n*i] := False;

  (* in tiêu đề chương trình *)
  WriteLn ('=================================================');
  WriteLn ('                  Prime Number                   ');
  WriteLn ('=================================================');
  WriteLn;

  (* hiện nay mới đếm được 0 số nguyên tố *)
  PrimeFound := 0;

  (* duyệt tất cả các số từ 2 đến MaxNum *)
  for n := 2 to MaxNum do begin
    (* nếu n là số nguyên tố, thì ... *)
    if IsPrime[n] then begin
      (* in ra n *)
      Write (n:NumberWidth);
      (* tăng giá trị số đếm PrimeFound lên 1 đơn vị *)
      PrimeFound := PrimeFound + 1;
      (* in dấu xuống dòng mỗi khi in NumberPerRow số nguyên tố *)
      if (PrimeFound mod NumberPerRow = 0) then WriteLn;
    end;
  end;

  (* in phần kết của chương trình *)
  WriteLn;
  WriteLn;
  WriteLn ('Found ', PrimeFound, ' prime numbers in range 2..', MaxNum);
  WriteLn;
  WriteLn ('=================================================');

end.