How to find the biggest number from a txt file? - pascal

I have to find out the biggest number from a txt file. Numbers are for example:
9 8 7 6 5
Someone told me, that it should works, but it didn't, and I have no clue how to work with file bcs.
program file;
uses crt;
var i,count,help:integer;
numb:array [1..9] of integer;
f:text;
begin
clrscr;
assign(f,'file1.txt');
reset(f);
readln(f,count);
for i:=1 to count do
readln(f,numb[i]);
close(f);
for i:=2 to count do
begin
if (numb[i-1] < numb[i]) then
help:=numb[i-1];
numb[i-1]:=numb[i];
numb[i]:=help;
end;
for i:=1 to count do
begin
write(numb[i]);
end;
readln;
end.

If you only want to know the highest number, you can use a running maximum while reading the numbers in the file.
As a user you don't have to know how many numbers there are in the file. The program should determine that.
I wrote a little test file, called file1.txt:
9 8 7 6 3 11 17
32 11 13 19 64 11 19 22
38 6 21 0 37
And I only read the numbers, comparing them with Max. That is all you need.
No need to read the data into an array and
no need to (try to) sort the data. You only want the highest number, right?
And there is also no need for the user to know or enter the number of numbers in the text file.
program ReadMaxNumber;
uses
Crt;
var
Max, Num: Integer;
F: Text;
begin
ClrScr;
Assign(F, 'file1.txt');
Reset(F);
Max := -1;
while not Eof(F) do
begin
Read(F, Num);
if Num > Max then
Max := Num;
end;
Close(F);
Writeln('Maximum = ', Max);
Readln;
end.
When I run this, the output is as expected:
Maximum = 64

There are a few mistakes in the code provided:
The program name is file. The program name cannot be a keyword;
You read from the file the variable count, but the actual value cannot be found in the file, so count=0. For this reason, the for loop which reads the data from the file is never executed. You either read it from a file or from the keyboard (in the solution below, I chose the second option);
You use readln when you read from the file. readln moves the cursor on the next line after it reads the data. This means that only the first number, 9, is stored into numb. Replace readln with read;
At the second for loop, you say that if ... then. If you want all the three instructions to be executed (and I think you do, because it's an exchange of values), put them between begin and end. Otherwise, only the first instruction is executed if the condition is true, the others are always been executed;
The method to determine the maximum is an overkill. Better if you take a variable, max, which initially gets the value of the first element in the array, then you cycle in the remaining values to see if a value is higher than max.
The final code looks like this:
program file1;
uses crt;
var i,count,help, max:integer;
numb:array [1..9] of integer;
f:text;
begin
clrscr;
assign(f,'file1.txt');
reset(f);
writeln('Please input a number for count :');
readln(count);
for i:=1 to count do
read(f,numb[i]);
close(f);
max:=numb[1];
for i:=2 to count do
if numb[i]>max then
max:=numb[i];
write('The result is: ',max);
readln;
end.

Related

Reading a text file and constructing a matrix from it

I need to construct a matrix; a number of columns and rows are also in the first row of the matrix, I'll make an example so its more clearer.
4 3
1 2 3
5 6 7
9 10 8
1 11 13
Where m=4 (number of rows) and n=3 (number of columns)
This is an example of a text file. Is something like this even possible?
Program Feb;
const
max=100;
type
Matrix=array[1..max,1..max] of integer;
var datoteka:text;
m,n:integer;
counter:integer;
begin
assign(datoteka,'datoteka.txt');
reset(datoteka);
while not eoln(datoteka) do
begin
read(datoteka, m);
read(datoteka, n);
end;
repeat
read eoln(n)
until eof(datoteka)
write (m,n);
end.
My code isn't a big help, cause I don't know how to write it.
First, have a look at the code I wrote to do the task, and then look at my explanation below.
program Matrixtest;
uses
sysutils;
var
NoOfCols,
NoOfRows : Integer;
Source : TextFile;
Matrix : array of array of integer;
FileName : String;
Row,
Col : Integer; // for-loop iterators to access a single cell of the matrix
Value : Integer;
begin
// First, construct the name of the file defining the matrix
// This assumes that the file is in the same folder as this app
FileName := ExtractFilePath(ParamStr(0)) + 'MatrixDef.Txt';
writeln(FileName); // echo it back to the screen so we can see it
// Next, open the file
Assign(Source, FileName);
Reset(Source);
read(Source, NoOfRows, NoOfCols);
writeln('Cols: ', NoOfCols, 'Rows: ', NoOfRows);
SetLength(Matrix, NoOfCols, NoOfRows);
readln(source); // move to next line in file
// Next, read the array data
for Row := 1 to NoOfRows do begin
for Col := 1 to NoOfCols do begin
read(Source, Value);
Matrix[Col - 1, Row - 1] := Value;
end;
end;
// Display the array contents
for Row := 1 to NoOfRows do begin
for Col := 1 to NoOfCols do begin
writeln('Row: ', Row, ' contents', Matrix[Col - 1, Row - 1]);
end;
end;
Close(Source); // We're done with the file, so close it to release OS resources
readln; // this waits until you press a key, so you can read what's been displayed
end.
In your program, you can use a two-dimensional array to represent your matrix. Free Pascal supports multi-dimensional arrays; see https://wiki.lazarus.freepascal.org/Multidimensional_arrays for more information.
This is a complex task, so it helps to know how to do more basic things like reading an array of a size known at compile-time from a text file.
The wrinkle in this task is that you are supposed to read the dimensions (numbers of rows and columns) of the matrix at run-time from the file which contains the matrix's contents.
One inefficient way to do this would be to declare the matrix array with huge dimensions, larger than anything you would expect in practice, using the type of array declaration in the Wiki page linked above.
A better way is to use dynamic arrays, whose dimensions you can set at run-time. To use this, you need to know:
How to declare a dynamic array in Free Pascal
How to set the dimensions of the array at run-time, once you've picked them up from your matrix-definition file (hint: SetLength is the way to do this)
The fact that a Free Pascal dynamic array is zero-based
The easiest way of managing zero-based arrays is to write your code (in terms of Row and Column variables) as if the matrix were declared as array[1..NoOfRows, 1..NoOfColumns] and subtract one from the array indexes only when you actually access the array, as in:
Row := 3;
Column := 4;
Value := Matrix[Row - 1, Column - 1];

Ada thread to pass auto random generated data to a procedure

How would i go about creating a procedure that is a thread which continuously passes automatic random generated data within a specified range.
I currently would have to manually enter in each bit of data in the console using this procedure below. I want to creatre a procedure that when running is able to pass data to this procedure as if it was being typed into the console itself.
procedure Analyse_Data is
Data : Integer;
begin
DT_Put_Line("Data input by user");
loop
DT_Get(Data,"Data must be taken as a whole number");
exit when (Data >=0) and (Data <= Maximum_Data_Possible);
DT_Put("Please input a value between 0 and ");
DT_Put(Maximum_Data_Possible);
DT_Put_Line("");
end loop;
Status_System.Data_Measured := Data_Range(Data);
end Analyse_Data;
I havent included the specification files (.ads)
I am new to Ada and any help would be appreciated.
Use an instance of Discrete_Random to generate some number of random data values in the desired range:
subtype Valid_Range is Natural range 0 .. Maximum_Data_Possible;
package Some_Value is new Ada.Numerics.Discrete_Random(Valid_Range);
G : Some_Value.Generator;
…
procedure Generate is
N : Valid_Range;
begin
for I in 1 .. Count loop
N := Some_Value.Random(G);
Put(N);
end loop;
end;
Save the values to a file:
./generate > test_data.txt
Feed that file to your program using I/O redirection from the command line:
./analyse_data < test_data.txt
The exact details will depend on you actual program. See this related Q&A regarding empty lines in standard input.

Lazarus - .wav files playing in sequence

I'm making a number-to-speech program. I have all of the voice samples all recorded, and working, but every time the input has the numbers in sequential order (012... etc.), it will begin playing the rest of the numbers to 9, against the input.
For example, if 24601 is typed, it will say:
2..4..6..0..1..2..3..4..5..6..7..8..9..0..
It's not supposed to do that. It will even over-ride the remaining numbers with the sequence, if there are any.
Full code: http://pastebin.com/vFfBRYUu
Here's the offending code block. If you need the remaining pieces, I'll put them up:
procedure TForm1.Button1Click(Sender: TObject);
begin
for i := 0 to Length(input.Text) do
begin
case var1[i] of
'0': PlaySound('zero.wav',0,SND_SYNC);
'1': PlaySound('one.wav',0,SND_SYNC);
'2': PlaySound('two.wav',0,SND_SYNC);
'3': PlaySound('three.wav',0,SND_SYNC);
'4': PlaySound('four.wav',0,SND_SYNC);
'5': PlaySound('five.wav',0,SND_SYNC);
'6': PlaySound('six.wav',0,SND_SYNC);
'7': PlaySound('seven.wav',0,SND_SYNC);
'8': PlaySound('eight.wav',0,SND_SYNC);
'9': PlaySound('nine.wav',0,SND_SYNC);
'-': Delay(400);
'&': PlaySound('start.wav',0,SND_SYNC);
'*': PlaySound('call to mess.wav',0,SND_SYNC);
end;
Delay(100);
end;
The input-to-array:
procedure TForm1.inputChange(Sender: TObject);
begin
y := y+1;
var1[y-1] := input.Text[y]
end;
y variable seems to never reset, which means you append the text to a var1. But you play the text-length of elements from var1 always starting from the 0 element.
Input Text | Stored text | Played text
0123 0123 0123
876 0123876 012
12345678 012387612345678 01238761
111 012387612345678111 012
Sounds like a bug.
Also there is number of mistakes:
Seeing it always plays much too many numbers, input.Text length is not reset properly
You iterate over input.Text but you play from var1 variable. You should always iterate and access the same array/string!
The loop should be for i := 1 to Length(input.Text) do if you iterate over a string
Relying on hidden knowledge of text start position in var1
Might be just your example, but you haven't closed the for loop with a end;
Meaningless / non-speaking variable names
Formatting (I have fixed it in your question, plz check)
You might also do some debugging on your own, to isolate the bug, by outputting the var1 to display before "speaking" it. E.g. by ShowMessage(var1) or alike;

Weird runtime error while implementing a bubble sort in Pascal

This snippet not only causes a runtime error, it makes FPC close if I run it using the debugger.
procedure sortplayersbyscore(var vAux:tplayers);
procedure swap(var a:trplayers;var b:trplayers);
var
rAux:trplayers;
begin
rAux:=a;
a:=b;
b:=rAux;
end;
var
i,j:integer;
sorted:boolean;
begin
vAux:=playersarray;
i:=1;
sorted:=false;
while (i <= MAXPLAYERS -1) and not sorted do
begin
j:=1;
sorted:=true;
while (j <= MAXPLAYERS -i) do
begin
if (vAux[j].score < vAux[j+1].score) then
begin
swap(vAux[j],vAux[j+1]);
sorted:=false;
end;
inc(j);
end;
inc(i);
end;
end;
The code itself is part of a really big source file, I can post the whole thing but the responsible for the error is just that bunch of lines. The debugger terminates at line:
swap(vAux[j],vAux[j+1]);
tplayers is just a type defined as an array of records that contain score (an integer) among a bunch of other variables. trplayers is the type of the aforementioned records. I'm at a total loss; FPC (while not under debugging mode) spits an out-of-range error but under my watches I see that the variables I'm trying to read exist. Any help is really appreciated!
rAux:trplayers; have you typed a wrong symbol or the type here really contains "r" in its name?
It looks valid (other than typos) ... so let's try something simple.
What's the value of "j" when you abort?
If the debugger won't tell you, try adding:
writeln ('j = ', j);
just before the "swap" call.
As Yochai's question implied, your array needs to be dimensioned at least from
1 (or lower) to MAXPLAYERS (or larger). (I.e.: 0..MAXPLAYERS-1 would not work,
but 1..MAXPLAYERS should.)

How can I detect elapsed time in Pascal?

I'm trying to create a simple game in Pascal. It uses the console. The goal in the game is to collect as many 'apples' as you can in 60 seconds. The game structure is a simple infinite loop. Each iteration, you can make one move. And here's the problem — before you make the move (readKey), time can pass as much as it wants. For example, the user can press a key after 10 seconds! Is there any way to count time? I need the program to know when user plays (before and after a key is pressed), so I don't know how to prevent user from "cheating".
Here's simple structure of my game:
begin
repeat
{* ... *}
case ReadKey of
{* ... *}
end;
{* ... *}
until false;
end.
Full code: http://non.dagrevis.lv/junk/pascal/Parad0x/Parad0x.pas.
As far I know that there are two possible solutions:
getTime (from DOS),
delay (from CRT).
...but I don't know how to use them with my loop.
Check this link. There might be some useful information for you. And here is the same you're asking for. And here's what you're looking for (same as the code below).
var hours: word;
minutes: word;
seconds: word;
milliseconds: word;
procedure StartClock;
begin
GetTime(hours, minutes, seconds, milliseconds);
end;
procedure StopClock;
var seconds_count : longint;
c_hours: word;
c_minutes: word;
c_seconds: word;
c_milliseconds: word;
begin
GetTime(c_hours, c_minutes, c_seconds, c_milliseconds);
seconds_count := c_seconds - seconds + (c_minutes - minutes) * 60 + (c_hours - hours) * 3600;
writeln(inttostr(seconds_count) + ' seconds');
end;
begin
StartClock;
// code you want to measure
StopClock;
end.

Resources