Last active
December 19, 2015 13:58
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
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