Pascal: For loop not completing - for-loop

This is supposed to ask for a students name, three test grades, project and exam grade.
After all of the inputs are done its supposed to calculate their final grade, award and letter grade. Then print their name, final grade, award and letter grade.
Program Student_Report;
USES CRT;
var
s_name, stu_award:string;
test1, test2, test3, AVG_cwgrade, exam_grade, project, exam, finalgrade, cw_wieght:real;
letter_grade:char;count:integer;
begin
for count:= 1 to 30 do;
begin
writeln('Enter students name');
read(s_name);
writeln('Enter test grades');
read(test1, test2, test3);
writeln('Enter project grade');
read(project);
writeln('Enter exam grade');
read(exam_grade)
AVG_cwgrade :=(test1 + test2 + test3 + project) /4;
cw_wieght :=(0.45 * AVG_cwgrade);
exam :=(0.55 * exam_grade);
finalgrade :=(exam + cw_wieght);
stu_award :='Pass';
if (finalgrade >= 80) then
letter_grade := 'A';
stu_award := 'Honors';
IF (finalgrade >= 60) then
letter_grade := 'B';
IF (finalgrade >= 50) then
letter_grade := 'C';
IF (finalgrade >= 40) then
letter_grade := 'D'
else letter_grade := 'E';
end;
Writeln('The student name is', s_name);
Writeln('The student final grade is', finalgrade);
Writeln('The award the student recieved is', stu_award);
Writeln('The letter grade the student recieved is', letter_grade);
end.
Only the the beginning of the for loop is being executed
begin
for count:= 1 to 30 do;
begin
writeln('Enter students name');
read(s_name);
writeln('Enter test grades');
read(test1, test2, test3);
writeln('Enter project grade');
read(project);
writeln('Enter exam grade');
read(exam_grade);
This part is not done-
AVG_cwgrade :=(test1 + test2 + test3 + project) /4;
cw_wieght :=(0.45 * AVG_cwgrade);
exam :=(0.55 * exam_grade);
finalgrade :=(exam + cw_wieght);
stu_award :='Pass';
if (finalgrade >= 80) then
letter_grade := 'A';
stu_award := 'Honors';
IF (finalgrade >= 60) then
letter_grade := 'B';
IF (finalgrade >= 50) then
letter_grade := 'C';
IF (finalgrade >= 40) then
letter_grade := 'D'
else
letter_grade := 'E';
end;
Writeln('The student name is', s_name);
Writeln('The student final grade is', finalgrade);
Writeln('The award the student recieved is', stu_award);
Writeln('The letter grade the student recieved is', letter_grade);
end.

There are a few problems.
stu_award :='Pass';
if (finalgrade >= 80) then
letter_grade := 'A';
stu_award := 'Honors';
The line "stu_award := ..." will always be executed, irrilevant of the test outcome, because the line "letter_grade := ..." terminates (better: separates) (lexycally) the if statement. I don't think this is what you want.
Spaces, indentation and similar are not significant in pascal - this is not python. Even line endings are not particularly significant. What you need is a block, a begin/end couple:
stu_award :='Pass';
if (finalgrade >= 80) then begin
letter_grade := 'A';
stu_award := 'Honors';
end;
Then there is a logic error:
IF (finalgrade >= 60) then
letter_grade := 'B';
IF (finalgrade >= 50) then
letter_grade := 'C';
Suppose "finalgrade" is 60. The first test succeeds, and "letter_grade" is set to 'B'. But the second test also succeeds, so "letter_grade" is set to 'C'. In a row, it will be set to 'B', then 'C', then 'D'...
You must exclude (i.e. don't execute) other following tests. You can use several else clauses.
In this particular case you can also reorder the tests:
IF (finalgrade >= 50) then
letter_grade := 'C';
IF (finalgrade >= 60) then
letter_grade := 'B';
Again "letter_grade" will take several values one after the other but the greater will win. Suppose finalgrade=55: letter_grade will be set to 'C', but the next test will not overwrite the value.
I didn't check other possible problems, but these two are the most preminent.

Related

Get the minimum amount of degrees recorded in a day

I need to make a program that gets the minimum amount of degrees recorded in a day at what hour, I made the program, I am getting the correct hour at which the min amount of degrees were recorded but I am not getting the correct amount of degrees
Program P1;
Type
Hour = 0..23;
Degrees = -40..40;
Temperature = array [Hour] of Degrees;
var
t : Temperature;
i, min_t, max_t, hour_t_min, hour_t_max : integer;
procedure test;
begin
for i := 0 to 23 do
begin
writeln('Enter the temperature at hour ', i);
readln(t[i]);
min_t := t[0];
if min_t > t[i] then
begin
min_t := t[i];
ora_t_min := i;
end;
if max_t < t[i] then
begin
max_t := t[i];
ora_t_max := i;
end;
end;
writeln('temp min ', min_t, ' at hour ', hour_t_min);
writeln('temp max ', max_t, ' at hour ', hour_t_max);
end; {procedure}
begin { main }
test;
end.
Min_t (and max_t) should be initialized outside and before the loop.
You are assigning min_t:=t[0] in each loop, this is wrong, and max_t is not being initialized. Also, I think this is a typo, ora_t_min and ora_t_max should be changed to hour_t_min and hour_t_max:
Something like this:
min_t := 40;
max_t := -40;
for i := 0 to 23 do
begin
writeln('Enter the temperature at hour ', i);
readln(t[i]);
if min_t > t[i] then begin min_t := t[i]; hour_t_min := i; end;
if max_t < t[i] then begin max_t := t[i]; hour_t_max := i; end;
end;
writeln('temp min ', min_t, ' at hour ', hour_t_min);
writeln('temp max ', max_t, ' at hour ', hour_t_max);
end;

Difference between two dates in Pascal

This program is supposed to find the difference between two dates but it has a bug and I can't find it.
It keeps returning a big number - please help
Program tp4;
Type
dt = Record
jour : Integer;
mois : Integer;
annee : Integer;
End;
Var
date : dt ;
y,x,i,s : Integer;
Begin
x := 0;
s := 0;
For y:=1 To 2 Do
//2 dates
Begin
Writeln('Entrez un date : jour mois année ');
Readln( date.jour, date.mois, date.annee);
While ((date.jour<=0) Or (date.jour>31) Or (date.mois>12) Or (date.annee<=0) ) Do
//verfication loop
Begin
Writeln('Entrez une date valide : jour mois année ');
Readln(date.jour ,date.mois ,date.annee);
End;
s := s+date.jour ;
For i:= 1 To date.mois-1 Do
Case i Of
3,5,7,8,10,12,1 : s := s+31;
4,6,9,11 : s := s +30;
2 : If ((date.annee Mod 100)=0) And ((date.annee Mod 400) = 0 ) Then //convert months to days
s := s+29
Else If date.annee Mod 4 = 0 Then
s := s+29
Else s := s+28;
End; //Convert years to days
For i:= 1 To date.annee Do
If (i Mod 100 = 0) And (i Mod 400 = 0) Then s := s+366
Else If (i Mod 4 =0) Then s := s+366
Else s := s+365;
x:=s-x ;
End;
If (x)<=0 Then
Writeln('la difference est :',-x)
Else Writeln('la difference est :',x);
Readln;
End.
**input**
12 03 2019
13 03 2019
**output**
737510
I think the error was somewhere in s and x (x:=s-x; etc.), I did refactoring:
Program tp4;
Type dt = Record
jour : Integer;
mois : Integer;
annee : Integer;
End;
Type
arrayDate = array[1..2] of dt;
Var
y,i,f,s : Integer;
arrDate: arrayDate;
function Leap (Y : Word): Boolean;
Begin
If (Y Mod 4) <> 0 Then Leap := FALSE
Else If (Y Mod 100) <> 0 Then Leap := TRUE
Else Leap := (Y Mod 400) = 0;
End;
function Lenght (date: dt) : Integer;
Begin
Lenght := 0;
Lenght := Lenght + date.jour;
For i := 1 To date.mois Do
Case i Of
3, 5, 7, 8, 10, 12, 1 : Lenght := Lenght + 31;
4, 6, 9, 11 : Lenght := Lenght + 30;
2 : If Leap (date.annee) Then Lenght := Lenght + 29 Else Lenght:= Lenght + 28;
End;
For i := 1 To date.annee Do //Convert years to days
If Leap (i) Then Lenght := Lenght + 366 Else Lenght := Lenght + 365;
End;
Begin
For y := 1 To 2 Do //2 dates
Begin Writeln ('Entrez un date : jour mois année ');
Readln (arrDate[y].jour, arrDate[y].mois, arrDate[y].annee);
While ((arrDate[y].jour <= 0)
Or (arrDate[y].jour > 31)
Or (arrDate[y].mois > 12)
Or (arrDate[y].annee <= 0)) Do //verfication loop
Begin
Writeln ('Entrez une date valide : jour mois année ');
Readln (arrDate[y].jour, arrDate[y].mois, arrDate[y].annee);
End;
End;
f := Lenght(arrDate[1]);
s := Lenght(arrDate[2]);
Writeln ('la difference est :', Abs(s - f)); // absolute |s-f|
Readln;
End.
You are using the For y ... loop to request input and to calculate number of days for each input. Within the loop, the s variable is the days counter.
The error you do is that you zero s bfore the For y ... loop and not at the beginning of the loop. Therefore, the second time you request a date, s still has the value from the first date, on top of which you then start to calculate the days for the second date.
The correction is of course to move s := 0; to the beginning of the For y ... loop,
or change the first assignment of s from
s := s + date.jour;
to
s := date.jour;
Finding the difference between two dates 6,000 years apart in a loop? And (ab)using the name of a standard function "Length"? Ouch!
Try this:
//----------------------------------------------------------------------
// Convert a date to its Julian Day Number
//----------------------------------------------------------------------
procedure cj(dd, mm, yyyy: longint; var jdn, dow: longint);
var
cj_y,
cj_c,
cj_x,
cj_y: double;
begin
if dd = 0 then
begin
jdn:= -1
dow:= -1;
end
else
begin
cj_y:= yyyy + (mm - 2.85) / 12;
cj_c:= 0.75 * trunc(cj_y * 0.01);
cj_x:= frac(cj_y);
cj_y:= trunc(cj_y);
jdn:= trunc(
trunc(
trunc(367 * cj_x) + 367 * (cj_y) -
1.75 * cj_y + dd) - cj_c) +
1721115.0;
dow:= jdn mod 7;
end;
end; {cj}
Formula as given is valid for days after 1582-10-15, a small tweak will allow dates going back to 0000-03-01.
Follow the link in https://groups.google.com/g/comp.lang.pascal.borland/c/itwgcfYpLEU which I posted in August 1998 in comp.lang.pascal.borland for explanations.

Find block number and floor by flat number

Imagine - there's a house with 80 flats. It has 4 floors and 5 blocks. Each block has 4 flats.
User is asked to input flat number and Pascal program is supposed to calculate and output flat number. This must be calculated using some kind of formula. The only tip I have is that I have to use div and mod operations.
This is how the house looks like -
So far, I've created program, that loops through all 80 flats and after each 16 flats increases block value and after each 4 blocks increases stair.
This is my code:
program project1;
var
i, floors, blocks, flats, flat, block, floor, blockCounter, floorCounter : integer;
begin
floors := 4;
blocks := 5;
flats := 80;
while true do
begin
write('Flat number: ');
read(flat);
block := 1;
floor := 1;
blockCounter := 0;
floorCounter := 0;
for i := 1 to 80 do
begin
blockCounter := blockCounter + 1;
floorCounter := floorCounter + 1;
if (floorCounter = 4) then
begin
floorCounter := 0;
floor := floor + 1;
end;
if (blockCounter > 16) then
begin
block := block + 1;
blockCounter := 0;
floorCounter := 0;
floor := 1;
end;
if (i = flat) then
begin
writeln('Flat nr. ', flat, ' is in ', floor, '. floor and in ', block, '. block!');
end;
end;
end;
end.
Is there anyone who can help me with this?
I've finally solved my problem myself.
I finally undersood how div works, so I was able to solve this.
program Maja;
var dzivoklis, kapnutelpa, stavs : integer;
begin
while true do
begin
write('Ievadi dzivokla numuru: ');
read(dzivoklis);
kapnutelpa := ((dzivoklis - 1) div 16) + 1;
stavs := (((dzivoklis - 1) mod 16) div 4) + 1;
writeln('Kapnutelpa: ', kapnutelpa);
writeln('Stavs: ', stavs);
writeln();
end;
end.

PL/SQL Check Digit, luhn using MOD 11

So here is the question:
Write code to take in an id and determine if the check digit is correct
UPDATED CODE:
Set SERVEROUTPUT ON
DECLARE
val_num NUMBER := '&user_input';
holder NUMBER := 0;
y NUMBER := 0;
conv_string VARCHAR2(20);
BEGIN
conv_string := to_char(val_num*10);
for x in 1..length(conv_string) loop
y := to_number(substr(conv_string, -x, 1));
if mod(x,2) = 0 then
y := y * 2;
if y > 9 then
y := y - 9;
end if;
end if;
holder := holder + y;
end loop;
dbms_output.put_line ('Check is '||(11-Mod(holder, 11)));
END luhn;
/
SET SERVEROUTPUT ON
The return is:
SQL> # loop
Enter value for user_input: 036532
old 2: val_num NUMBER := '&user_input';
new 2: val_num NUMBER := '036532';
Check is 2
It should be 6
Before actual execution
SET SERVEROUTPUT ON
to enable SQL*Plus to fetch database output buffer.
Here is solution: https://community.oracle.com/thread/837639?start=0&tstart=0
There are lots of different variations of the luhn algorithm, so looking at these implementations and your (I think incomplete) description in the comments I think this may be fairly close to what you are looking for, and gives the correct checksum for 036532 as per your initial question.
Hope it is helpfull
Set SERVEROUTPUT ON
DECLARE
val_num number := '036532';
holder NUMBER := 0;
y NUMBER := 0;
conv_string VARCHAR2(20);
BEGIN
conv_string := to_char(val_num);
FOR X IN 1..LENGTH(CONV_STRING) LOOP
Y := TO_NUMBER(SUBSTR(CONV_STRING, -X, 1));
IF ((X+1) > 10) THEN
Y := Y * 10;
ELSE
Y := Y * (X + 1);
END IF;
IF (Y >= 10) THEN
HOLDER := HOLDER + TO_NUMBER(substr(TO_CHAR(Y), 1, 1)) + TO_NUMBER(substr(TO_CHAR(Y), 2, 1));
ELSE
HOLDER := HOLDER + Y;
END IF;
END LOOP;
HOLDER := MOD(HOLDER, 11);
Holder := 11 - mod(holder, 11);
dbms_output.put_line ('Check is '|| holder);
END luhn;
/
SET SERVEROUTPUT ON

All sums of a number

I need an algorithm to print all possible sums of a number (partitions).
For example: for 5 I want to print:
1+1+1+1+1
1+1+1+2
1+1+3
1+2+2
1+4
2+3
5
I am writing my code in Pascal. So far I have this:
Program Partition;
Var
pole :Array [0..100] of integer;
n :integer;
{functions and procedures}
function Minimum(a, b :integer): integer;
Begin
if (a > b) then Minimum := b
else Minimum := a;
End;
procedure Rozloz(cislo, i :integer);
Var
j, soucet :integer;
Begin
soucet := 0;
if (cislo = 0) then
begin
for j := i - 1 downto 1 do
begin
soucet := soucet + pole[j];
if (soucet <> n) then
Write(pole[j], '+')
else Write(pole[j]);
end;
soucet := 0;
Writeln()
end
else
begin
for j := 1 to Minimum(cislo, pole[i - 1]) do
begin
pole[i] := j;
Rozloz(cislo - j, i + 1);
end;
end;
End;
{functions and procedures}
{Main program}
Begin
Read(n);
pole[0] := 101;
Rozloz(n, 1);
Readln;
End.
It works good but instead of output I want I get this:
1+1+1+1+1
2+1+1+1
2+2+1
3+1+1
3+2
4+1
5
I can't figure out how to print it in right way. Thank you for help
EDIT: changing for j:=i-1 downto 1 to for j:=1 to i-1 solves one problem. But my output is still this: (1+1+1+1+1) (2+1+1+1) (2+2+1) (3+1+1) (3+2) (4+1) (5) but it should be: (1+1+1+1+1) (1+1+1+2) (1+1+3) (1+2+2) (1+4) (2+3) (5) Main problem is with the 5th and the 6th element. They should be in the opposite order.
I won't attempt Pascal, but here is pseudocode for a solution that prints things in the order that you want.
procedure print_partition(partition);
print "("
print partition.join("+")
print ") "
procedure finish_and_print_all_partitions(partition, i, n):
for j in (i..(n/2)):
partition.append(j)
finish_and_print_all_partitions(partition, j, n-j)
partition.pop()
partition.append(n)
print_partition(partition)
partition.pop()
procedure print_all_partitions(n):
finish_and_print_all_partitions([], 1, n)

Resources