2.3. Các giải pháp để giải quyết vấn đề
2.3.1 Các bài tập về câu lệnh for :
a. Bài tập 1: Viết chương trình tính tổng với được nhập vào từ bàn phím (a >2).
Program baitap1;
var a,i:longint;
s:real;
BEGIN
write('Moi nhap so a = '); read(a);
s:=0;
for i:=1 to 100 do s:=s+ 1/(a+i);
writeln('s=', s:1:2);
readln;
readln;
END.
Giá trị nhập vào
Kết quả lấy ra
3
3.38
15
2.01
b. Bài tập 2: Viết chương trình thực hiện nhập từ bàn phím hai số nguyên m và n (m < n), tính và đưa ra màn hình tổng các số chia hết cho 3 hoặc 5 trong phạm vi từ m đến n.
Giá trị nhập vào
Kết quả lấy ra
1
5
8
Trong bài tập trên sử dụng câu lệnh for dạng lặp tiến, giá trị đầu được xác định là m và giá trị cuối xác định giá trị n. Tùy thuộc vào giá trị của m và n ta được kết quả tương ứng.
c. Bài tập 3: Viết chương trình đưa ra các ký tự từ A đến Z
Program baitap3;
var ch: char;
BEGIN
for ch:='A' to 'Z' do write(ch:3);
readln;
readln;
END.
Bài tập trên yêu cầu đưa ra các ký tự từ A đến Z do đó ta xác định giá trị đầu là ký tự A và giá trị cuối là ký tự Z. Khi viết chương trình học sinh chú ý khai báo biến đếm có giá trị kiểu Char. Nhiều học sinh khai báo biếm đếm kiểu số nguyên dẫn đến chương trình không chạy được vì sai cú pháp.
d. Bài tập 4: Viết chương trình tính tổng
Program baitap4;
var i: longint;
s: real;
BEGIN
s:=0;
for i:=100 downto 1 do s:=s+1/i;
writeln('s=',s:1:2);
readln;
readln;
END.
Bài tập trên xác định giá trị đầu là 1 và giá trị cuối là 100. Câu lệnh lặp sử dụng là dạng for lùi, kết quả của bài toán lấy đến 2 số sau dấu phẩy là 5.19. Việc sử dụng câu lệnh dạng for lùi và dạng for tiến đều có kết quả như nhau. Tùy vào mỗi trường hợp, mỗi bài toán mà sử dụng cho thuận tiện.
2.3.2 Các bài tập về câu lệnh while do :
a. Bài tập 1: Viết chương trình tính tổng a>2 cho đến khi
Program baitap1;
var s : real;
a, n :longint;
BEGIN
write(' moi nhap a='); read(a);
s:=1/a; n:=1;
while (1/(a+n) >= 0.0001) do
begin
s:=s+1/(a+n);
n:=n+1;
end;
writeln('s=',s:1:2);
readln;
readln;
END.
Giá trị nhập vào
Kết quả lấy ra
3
8.29
Chương trình trên không thể xác định được giá trị đầu, giá trị cuối nên không thể sử dụng câu lệnh dạng for. Số lần lặp phụ thuộc vào điều kiện của đề bài và tham số a, điều kiện lặp kết thúc . Cấu trúc lặp được sử dụng là câu lệnh while do, với giá trị a =3 cho kết quả gần đúng sau hai số sau dấu phẩy là 8.29.
b. Bài tập 2: Viết chương trình tính cho đến khi
Program baitap2;
var i,n:longint;
s:real;
BEGIN
s:=1; n:=1; i:=1;
while (1/n >= 2*0.000001) do
begin
s:=s+1/n;
i:=i+1;
n:= n*i;
end;
writeln('s=', s:1:2);
readln;
readln;
END.
Chương trình trên không thể xác định được giá trị đầu và giá trị cuối mà chỉ biết được câu lệnh kết thúc khi do đó ta sử dụng cấu trúc lặp while do để thực hiện bài tập này. Bài tập liên quan đến giá trị của giai thừa rất lớn nên trong sáng kiến này xin chưa được đề cập đến, giá trị của bài toán sau khi thực hiện cho kết quả gần đúng là 2.72
c. Bài tập 3: Cho hai số nguyên dương M và N. Tìm ước chung lớn nhất của hai số nguyên dương M và N
Program baitap3;
var m,n:longint;
BEGIN
write(' moi nhap so m'); read(m);
write('Moi nhap so n '); read(n);
while m<>n do
if m >n then m:=m-n else n:=n-m;
writeln('Uoc chung lon nhat ', n);
readln;
readln;
END.
Bài toán tìm ước chung lớn nhất của hai số nguyên dương có rất nhiều cách giải tối ưu. Trong sáng kiến này đưa ra cách giải đơn giản nhất để tìm ước chung lớn nhất của hai số. Để tìm ước chung lớn nhất của hai số ta lấy số lớn trừ đi số nhỏ, quá trình trên lặp lại cho đến khi giá trị của hai số bằng nhau. Điều kiện để lặp ở bài toán là hai số khác nhau, khi hai số bằng nhau thì dừng câu lệnh while do.
Giá trị nhập vào
Kết quả lấy ra
3
4
1
2.3.3 Các bài tập tổng hợp về cấu trúc lặp :
a. Bài tập 1: Cho số nguyên dương N( 0 < N <105). Đưa ra màn hình thông báo số N vừa nhập có phải số nguyên tố hay không. Nếu N là số nguyên tố đưa ra màn hình YES và ngược lại NO
Sử dụng cấu trúc lặp với số lần biết trước (câu lệnh for):
Program baitap1;
var i,n:longint;
ok:boolean;
BEGIN
write(' moi nhap n '); read(n);
if n<=1 then ok:=false;
if (n=2) or (n=3) then ok:=true;
if n>=4 then
begin
ok:=true;
for i:=2 to trunc(sqrt(n)) do
if n mod i=0 then begin ok:=false; break ; end;
end;
if ok=false then writeln('So ',n,' khong phai la so nguyen to')
else writeln('So ',n,' la so nguyen to');
readln;
readln;
END.
Sử dụng cấu trúc lặp với số lần chưa biết trước (câu lệnh while do):
Program baitap1;
var i,n:longint;
ok:boolean;
BEGIN
write(' moi nhap n '); read(n);
if n<=1 then ok:=false;
if (n=2) or (n=3) then ok:=true;
if n>=4 then
begin
ok:=true;
i:=2;
while i <= trunc(sqrt(n)) do
begin
if n mod i=0 then begin ok:=false; break ; end;
i:=i+1;
end;
end;
if ok=false then writeln('So ',n,' khong phai la so nguyen to')
else writeln('So ',n,' la so nguyen to');
readln;
readln;
END.
Giá trị nhập vào
Kết quả lấy ra
4
NO
2
YES
Bài toán kiểm tra số nguyên dương N bất kỳ có phải là số nguyên tố có rất nhiều thuật toán tối ưu. Để minh họa cấu trúc lặp trong sáng kiến này tôi xin trình bày thuật toán theo cách trên. Bài toán được xác định với giá trị đầu 2 và giá trị cuối là phần nguyên của căn n do đó việc áp dụng bài toán theo hai cấu trúc lặp đều cho kết quả giống nhau.
b. Bài tập 2: Cho số nguyên dương N( 0< N <105). Đưa ra màn tổng các chữ số của N.
Program baitap2;
var s,i,n:longint;
BEGIN
write(' moi nhap n '); read(n);
s:=0;
while n <>0 do
begin
i:= n mod 10;
n:=n div 10;
s:=s+i;
end;
writeln('Ket qua ',s);
readln;
readln;
END.
Bài toán trên yêu cầu tính tổng các chữ số của số nguyên dương N. Để lấy các số hạng của số n ta lần lượt chia số đó cho 10 rồi lấy phần dư, quá trình trên lặp lại cho đến khi ta lấy hết các số hạng của n khi đó số n có giá trị là 0. Điều kiện để lặp là giá trị của n khác 0. Trong phạm vi kiến thức học sinh được học chỉ có thể sử dụng cấu trúc dạng while do, cấu trúc dạng for được sử dụng khi học sinh đã được học bài kiểu xâu.
Giá trị nhập vào
Kết quả lấy ra
12
3
b. Bài tập 3: Lập trình giải bài toán cổ sau :
Vừa gà, vừa chó
Bó lại cho tròn
Ba mươi sáu con,
Một trăm chân chẵn.
Hỏi có bao nhiêu con mỗi loại.
Sử dụng cấu trúc lặp với số lần biết trước (câu lệnh for):
Program baitap3;
var ga,cho:longint;
BEGIN
for ga:=1 to 35 do
begin
cho :=36-ga;
if 2*ga + 4*cho =100 then writeln('Ga=',ga,'Cho=',cho);
end;
readln;
readln;
END.
Sử dụng cấu trúc lặp với số lần chưa biết trước (câu lệnh while do):
Program baitap3;
var ga,cho:longint;
BEGIN
ga:=1;
while ga <=35 do
begin
cho :=36-ga;
if 2*ga + 4*cho =100 then writeln('Ga=',ga,'Cho=',cho);
ga:=ga+1;
end;
readln;
readln;
END.
Để sử dụng cấu trúc lặp ta giả sử số con gà nhận giá trị từ 1 đến 35, tương ứng với mỗi số con gà ta được số con chó là 36 trừ đi số con gà. Mỗi giá trị của số con gà, số con chó phải thõa mãn số chân thõa mãn là 100. Bài toán có nghiệm thõa mãn số con gà là 22, số con chó là 14. Nhiều học sinh khi gặp bài toán này sẽ nghĩ đến việc giải theo toán học đó là lập hệ phương trình nhưng khi gợi ý cho các em việc thử các giá trị của số gà ta sẽ nhận được bài toán giải rất đơn giản trong lập trình.
d. Bài tập 4: Viết chương trình tìm tất cả các số có ba chữ số abc sao cho tổng các lập phương của các chữ số bằng chính số đó.
Program baitap4;
var a,b,c:longint;
BEGIN
for a:=1 to 9 do
for b:=0 to 9 do
for c:=0 to 9 do
if (100*a +10*b +c =a*a*a + b*b*b +c*c*c) then writeln(a,b,c);
readln;
readln;
END.
Để tìm số có ba chữ số abc ta nhận thấy các giá trị của a nhận giá trị từ 1 đến 9, b và c nhận giá trị từ 0 đến 9. Với mỗi giá trị của a, b, c ta lần lượt kiểm tra xem có thõa mãn điều kiện của bài toán đề ra không. Chương trình được sử dụng là 3 câu lệnh for lồng nhau, kết quả của bài toán tìm được là các số 153, 370, 371, 407. Với những dữ liệu lớn việc sử dụng các cấu trúc lặp lồng nhau thời gian chạy sẽ rất lâu, tốn tài bộ nhớ. Để minh họa việc sử dụng cấu trúc lặp tôi đề xuất cách thực hiện chương trình như trên.
Bài toán đã sử dụng 3 câu lệnh for lồng nhau để giải, việc sử dụng cấu trúc câu lệnh while do tương tự như các bài toán trên.
2.4. Kết quả thu được.