Skip to content

Instantly share code, notes, and snippets.

@auscompgeek
Last active December 19, 2015 13:58
Show Gist options
  • Save auscompgeek/3787b12acd46eafcc17d to your computer and use it in GitHub Desktop.
Save auscompgeek/3787b12acd46eafcc17d to your computer and use it in GitHub Desktop.
prelim SDD assignment - turn exam scores into statistics (spot the non-standard pascal)
{
exam_statistics.pas - transform exam scores into statistical information
Copyright (c) 2013 David Vo
All rights reserved
(unless specified)
This program is designed to take class scores from an exam out of 10 (no full marks)
and display a horizontal histogram and the mean, median, and range of the scores.
}
program ExamStatistics(input, output);
{ import terminal procedures, needed for "clrscr" }
uses crt;
// I was planning on using labels and goto, but nah... :)
{
Declare constants.
These are used to make these easy to change and to increase readability.
}
const LOWEST_POSSIBLE = 0;
HIGHEST_POSSIBLE = 9;
NUM_DP_TO_ROUND = 2; // how many decimal places to round the mean off
{ Declare all the variables! *fistpumps the air* }
var scores : array[LOWEST_POSSIBLE..HIGHEST_POSSIBLE] of Integer;
total, bottom, top, numOfScores, untilMedian : Integer;
score, i, C, frequency, lastScore, medianSum : Integer;
scoreRange : Integer;
scoreMean, _median : Real;
median, rx : String;
numOfScoresIsOdd : Boolean;
{ Get an integer as input from the user. }
function readInt(prompt : String) : Integer;
begin
write(prompt);
readln(rx);
// convert input to integer and store as return value
Val(rx, readInt, C);
{ ensure input is actually an integer
we do this by checking the interrupt position
if it is 0, the conversion succeeded }
if C <> 0 then
begin
// the input isn't an integer, keep asking until it is
writeln('That is not an integral number.');
readInt := readInt(prompt)
end
end;
{
Some may be interested to know there used to be a procedure named pause here.
It has since been deleted.
}
begin
// begin startup message
writeln('Exam Statistics - turn weekly class exam scores into statistical information');
writeln('Copyright (c) 2013 David Vo');
writeln('All rights reserved.');
writeln;
writeln('This program is designed to take your weekly class exam scores and display');
writeln('a horizontal histogram, the mean, median, and range of the scores.');
writeln;
writeln('You will first be asked for the number of scores. You may then type each score');
writeln('from 0 to 9 in succession. Statistical information about the scores will then');
writeln('be shown. The program will then clear the screen and run again.');
writeln;
writeln('If the mean is fractional, it will be rounded to ', NUM_DP_TO_ROUND, ' decimal places.');
writeln;
writeln('Enter 0 for the number of scores to exit.');
writeln;
writeln;
// end startup message
repeat { start the infinite loop }
// initalise variables
total := 0;
bottom := HIGHEST_POSSIBLE; // lowest score
top := LOWEST_POSSIBLE; // highest score
median := '';
lastScore := 0;
// initialise scores array
for i := LOWEST_POSSIBLE to HIGHEST_POSSIBLE do
scores[i] := 0;
// get number of scores
numOfScores := readInt('Number of scores (0 to exit): ');
{ exit if the number of scores is 0
this is the only place where the infinite loop is broken }
if numOfScores = 0 then
exit;
// get each score
for i := 1 to numOfScores do
begin
score := readInt('Score: ');
// check the score is within the allowed range
while (score < LOWEST_POSSIBLE) or (score > HIGHEST_POSSIBLE) do
begin
// the score isn't within the allowed range, keep asking
writeln('That score is not within the allowed range.');
score := readInt('Score: ')
end;
// increment the frequency of this score in the array
scores[score] += 1;
// add up the total of the scores
total += score;
// check if we have a new top or bottom score
if score > top then
top := score;
if score < bottom then
bottom := score
end; // for i
// is the number of scores an odd or even number?
numOfScoresIsOdd := Boolean(numOfScores and 1);
// calculate the position at which the median is
if numOfScoresIsOdd then
untilMedian := (numOfScores + 1) div 2
else
untilMedian := numOfScores div 2;
clrscr; // clear the terminal before displaying the statistics
writeln('Horizontal histogram:');
// loop through each possible score
for score := LOWEST_POSSIBLE to HIGHEST_POSSIBLE do
begin
frequency := scores[score];
// print next line of the histogram (in 10 easy steps :))
//if score < 10 then
write(' ');
write(score, ' ');
for i := 1 to frequency do
write('*');
writeln;
// find the median (yes, median is type String)
if (median = '') and (frequency <> 0) then
if untilMedian = 0 then
begin
// we get here if numOfScores is even and we've reached the median
medianSum := lastScore + score;
if Boolean(medianSum and 1) then
begin
// the sum of these two scores is not divisible by 2, we must round
_median := medianSum / 2;
// assign to median the string representation of _median rounded off
str(_median:0:1, median);
end
else
// the sum is divisible by 2, do integer division
// then assign string representation to median
str(medianSum div 2, median)
end // untilMedian = 0
else if untilMedian = frequency then
if numOfScoresIsOdd then
{ the number of scores is odd, so we've reached the median
assign string representation of score to median }
str(score, median)
else // !numOfScoresIsOdd
begin
{ numOfScores is even, so we need to account for the next score in the median
note this score so we can use it in the next loop iteration }
lastScore := score;
untilMedian := 0
end // !numOfScoresIsOdd
else if untilMedian < frequency then
// we've reached the median
str(score, median)
else
// we haven't reached the median yet
untilMedian -= frequency
end; // for score
writeln; // blank line separates histogram from mean/median/range
// calculate and display mean
if (total mod numOfScores) = 0 then
// total is divisible by numOfScores
// calculate the mean by integer division
writeln('Mean: ', total div numOfScores)
else
begin
// total is not divisible by numOfScores, we must round it off
scoreMean := total / numOfScores;
writeln('Mean: ', scoreMean:0:NUM_DP_TO_ROUND)
end;
writeln('Median: ', median);
scoreRange := top - bottom;
writeln('Range: ', scoreRange);
writeln;
// wait until the user presses enter
write('Press Enter to continue...');
readln;
clrscr // clear the screen for the next iteration of the program
until False { end of the infinite loop }
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment