• Please review our updated Terms and Rules here

SETs in Pascal

CP/M User

Veteran Member
Joined
May 2, 2003
Messages
2,986
Location
Back of Burke (Guday!), Australia
Not sure if what I'm trying to do is possible with SETs.

I was trying to write small program, so I defined:

Code:
type palette=0..26;
     ink = set of palette;

var  col : ink;

begin

col:=[0,15];
...

all well and good, but now I want to extract that Data into a variable, which I think is where I'm crossing the line, because all the examples I have in my Pascal book, seems to be suggesting Information from a variable pointing to a SET, isn't meant to be extracted. The best example I seem to have of this in my book is from a Snakes & Ladders game, where certain numbers holds the ladders & snakes, and only gets checked when the variable I have lands on one of those numbers.

But what I was trying to do was extract for example the 0 & 15 for use in defining a Colour Palette.

I was trying to do it like this because my Pascal Compiler doesn't support CONST Array's with values in it, the other method is to setup an array and use a loading command (supplied within the Language), to load the Data into the Array, which is sort of annoying for small amounts of Information.

Otherwise I might be able to find another way of Poking Values into an Array.
 
Sets are useful if you need to do Boolean math on them. I do use them quite a bit; I'm not sure how many other people do.

You can certainly use them in this case but you will have to use Boolean math. Don't "poke", that's poor practise and you lose any portability.

In the bad old days, I always had initialisation procedures to fill arrays.

I assume you want to pull values from a set:

For loop:= 0 to 26 do
Begin
If [0] in col then HandleZero;
If [15] in col then Handle15
End;

It seems to me you should be able to simplify that with a Case, but apparently I'm not as sharp as I used to be.
 
Thanks for that, it's given me some ideas.

I should of clarified that I'm using Hisoft Pascal, which doesn't have any support for constant arrays, in the past I used to do things that way with Turbo Pascal 3.

But if I come up with a workable solution that looks portable, I'll post it here. :)
 
Using sets will certainly be portable; it's when you do things "outside the bounds of the language" such as manually making arrays in memory by using the OS, inline assembler, etc. that you lose portability.
 
Well I wasn't able to use the code you posted,

Code:
if [0] in col then ....

gave me error 47, which means Scalar (not including real) expected.

So I wrote this which is my closest running example to date, I've modified the program so it works in Turbo Pascal 3:

Code:
PROGRAM SetExample;
 
TYPE palette = 0..26;
     ink = SET OF palette;

VAR col : ink;
     mp : ARRAY[0..2] OF integer;
    pen : ARRAY[0..26] OF integer;
     lp : byte;
     ps : integer;

BEGIN
  FOR lp:=0 TO 26 DO
    pen[lp]:=lp;
  ps:=0;
  col:=[26,1,5];
  FOR lp:=0 TO 26 DO
    BEGIN
      IF (pen[lp]) IN col THEN
      BEGIN
        mp[ps]:=pen[lp];
        ps:=ps+1
      END;
    END;   { FOR Loop }
  FOR lp:=0 TO 2 DO
    writeln(mp[lp])
END.

So what I did in Hisoft Pascal was setup another array (which this TP program does) and place all numbers from 0 to 26, then I define my set, so this uses 3 Digits '26','1','5', so when those values come up in the array and match with the numbers in the set, that value goes into the second array. But in all respect I don't need a 2nd array and it can be simplified to some count variable, so when it matches the numbers in the set, I can just store that in my array.

The only problem I'm having with this, is the order of the numbers. I've simply created a program which sorts numbers out, for example in my set col 26 is the first number (reading from left to right), but my second number is 1 and my third is 5, so when I print those numbers out, mp[0]=1 mp[1]=5 and mp[2]=26, guess I didn't specify this when I made my initial enquiry, so I'm unsure how to get mp[0]=26, mp[1]=1 and mp[2]=5

Still I guess it's better than nothing.
 
Ok, that error is odd. You clearly didn't use a Real type, and you effectively did the same thing other places with no problem.

You could solve that by

If [palette(0)] in col then HandleZero;
If [palette(15)] in col then Handle15;

Unless your compiler will pack four 0..26s into one byte, you'd be just as well off not defining type Palette, but rather making ink a set of Byte.

But your order problem can't be solved with a set. Sets do not have order, they are like a bucket you put values in. To keep an order, you'd have to use an array.

Also, not applying to your situation, but a set also doesn't contain duplicates. [26,1,5,26] only contains 26, not 26 and 26.
 
Ok, that error is odd. You clearly didn't use a Real type, and you effectively did the same thing other places with no problem.

Well it looks like I have two odd compilers, Turbo Pascal 3 doesn't like it either - error 47 "Operand type(s) does not match operator" :)

I think those compilers are complaining because they are fixed values rather than variable ones.

You could solve that by

If [palette(0)] in col then HandleZero;
If [palette(15)] in col then Handle15;

Unfortunately no, TP 3 won't like that either.

Unless your compiler will pack four 0..26s into one byte, you'd be just as well off not defining type Palette, but rather making ink a set of Byte.

But your order problem can't be solved with a set. Sets do not have order, they are like a bucket you put values in. To keep an order, you'd have to use an array.

Also, not applying to your situation, but a set also doesn't contain duplicates. [26,1,5,26] only contains 26, not 26 and 26.

It's probably not important how I obtain the INK values from my set after I've setup the inks for the first and second position in the array, in that sense I can work out which numbers will go into their respected PENs, the values wouldn't be repeating, so in my case I have 13 other PEN colours to setup INKs between 0 & 26.

Though perhaps another way I could do it is setup a CHAR array with the numbers in it, the compiler I'm using to do all this in doesn't have a BYTE type, though I've been able to work around that by using a CHAR array.
 
Hmm. I haven't used TP3, I don't think. But I spent years with TP4, and if it doesn't work there then I've forgotten more that I think..

You can define your own Byte. :) But, if you only need 27 values, you don't need a byte, of course. You could use an array of Char, or an array of Palette. Don't forget to use a packed array if you are allowed.

I'd like to say that if I saw the bigger picture of what you are doing, I could come up with a pretty elegant solution. But, it's been more than a few years since I wrote anything in Pascal, and it's starting to sink in.
 
I'd like to say that if I saw the bigger picture of what you are doing, I could come up with a pretty elegant solution. But, it's been more than a few years since I wrote anything in Pascal, and it's starting to sink in.

Well the bigger picture is going to involve more System orientated code, I want to use the numbers to setup Pen Colours , the method I'm using above I should be able to get colours into the relevant procedure. I've been having a look to see if I could do the same sort of thing by having values from a character array, I thought this was going to be straightforward, but is harder than what I thought. In that situation, I'm using an array[1..2] of char with numbers in it, but the problem with that is I cannot get a '1' back to a 1, and the further issue is trying to get the 2nd number from the character array
 
Oh boy, it's starting time sound like "Instant Pascal", (incidentally anything but instant).

I think what you mean is that you store a #1, but want to retrieve an ordinal 1. I think your compiler calls ordinals Scalar. (?)

Normally I'd use Ord() to convert Char to ordinal but I have a feeling you don't have that option.

Early compilers are why I think most people hate Pascal. They really do have some stupid limitations, and in a lot of cases appear to be intended only to compile certain classroom code.

I'm spoilt, in that I didn't learn Pascal until TP4, by which time the language was very serious, and certainly has all the capabilities of other languages.

My solution to this problem has been to write my own compiler. Unfortunately, in ten years I have got absolutely nowhere on that.

Anyway back to your problem, I think the compiler just expects you to use Integers for all non-Real numbers.

I'll have to check out this Hisoft Pascal.. I'm still confused though because Hisoft wrote HighSpeed Pascal, which was an excellent clone of Turbo Pascal 5 that even had improvements over that. It really was the cat's meow. It was even faster than TP, and generated smaller code!

I wonder if there weren't two different Hisofts.
 
Oh boy, it's starting time sound like "Instant Pascal", (incidentally anything but instant).

I think what you mean is that you store a #1, but want to retrieve an ordinal 1. I think your compiler calls ordinals Scalar. (?)

Normally I'd use Ord() to convert Char to ordinal but I have a feeling you don't have that option.

Yes I can use ORD() in HiSoft Pascal or Turbo Pascal 3, I think it's a very standard Pascal Function, if it's not there, then it will be a very limited Pascal Language.

The good news is I have been able to write a function which converts a number string into a number (see below).

Early compilers are why I think most people hate Pascal. They really do have some stupid limitations, and in a lot of cases appear to be intended only to compile certain classroom code.

Unfortunately I don't know a great deal about the Pascal Compilers in the 70s, Chuck(G) listed some of those Problems in the "Status of Pascal" thread and I came across the Limitations on a String Length to be Fixed, so a CHAR Array needs to equal the Length specified.
Turbo Pascal seems to have been a bit of a game changer for the Language and manages Strings with a bit more flexibility, early Turbo Pascal Languages had to define a STRING globally, as my example shows, though later versions were able to Define Strings just about anywhere I think.
In Hisoft Pascal, there's no String type, so an char array is the next best thing, the PACKED keyword exists for compatibility reasons for other Pascal Compilers, though HiSoft state in their manual that all arrays are Packed, but it's only really the Boolean Array's which would take the most advantage of a Packed Array.

I've stuck with the language since school, though I was initially using Apple Pascal on a Mac around the early to mid-90s, then I was using Delphi for Windows 95, part of that course involved translating Turbo Pascal into Delphi & after School was porting Turbo Pascal stuff using Turbo Pascal 3, obviously not everything worked, but managed to get a bit of stuff compiled, so it would run under CP/M-86. I then turned to TP3 for CP/M, so I could write code on my Amstrad, but as my Turbo Pascal site shows, quite a bit of Machine Specific crept into it, so I've turned my attention to Hisoft Pascal, which doesn't rely on CP/M being present, so programs are RUN from the BASIC prompt, I can also save programs to Tape as well.

I'm spoilt, in that I didn't learn Pascal until TP4, by which time the language was very serious, and certainly has all the capabilities of other languages.

TP4 was when Borland turned their attention to the DOS platform, I think it was when they had significantly changed their Editor to have Pull-Down Menus, Units were also introduced as well as LongInts & Word Types, not sure if INC(); & DEC(); were also brought in as well. EXE files were generated, I'm unsure how big they were, I've used TP 5.5, which was able to produce a Small EXE file, due to the Compiler being able to selectively use what the Program Required.
All very well and good except there's no more CP/M Compilers. TP3 produced COM files (in CP/M & DOS), CMD if you had CP/M-86 version, TP3 had a single Library (no units), the IBM PC version had the largest files because of all the extra goodies included in a Library, so everything used & not used was put into a COM (or CMD) File. So in Tp3 you could program for a 8bit computer or 16bit. Editor for it is very Basic, no pull-down menus and one has to send a key command to get back to the menu options [CTRL]+[K]+[D].

My solution to this problem has been to write my own compiler. Unfortunately, in ten years I have got absolutely nowhere on that.

A couple of people have started writing Pascal compilers for 8bit computers, though one of the guys ceased writing due to lack of time & had noticed that someone had written a BASIC compiler to produce some very tight Assembly & as I've probably mentioned elsewhere, C has become a popular language to generate cross-compilable code for whatever old machine you have. It just means you using a Powerful Computer to produce the Code.

Anyway back to your problem, I think the compiler just expects you to use Integers for all non-Real numbers.

Yes, so in my earlier program with SET of Palette, I've written an array with values from 0 to 26 in it, the Type Palette = 0..26; holds the Range of values, so when I define "ink = set of palette;" it will only accept numbers between 0 & 26. My col : ink; allows me to assign a set of values to it, I'm not sure how many values it can allow, given there's 27 combinations, I'm only allowed to use 16 of those cause my computer in Low-Resolution only lets me use 16 Colours (0-15).

I'll have to check out this Hisoft Pascal.. I'm still confused though because Hisoft wrote HighSpeed Pascal, which was an excellent clone of Turbo Pascal 5 that even had improvements over that. It really was the cat's meow. It was even faster than TP, and generated smaller code!

I wonder if there weren't two different Hisofts.

Ok, so from what I can see HighSpeed Pascal is an Amiga & Atari Pascal Compiler written by HiSoft, I don't know when they first started writing it v1.13 is dated 1990 I noticed. Hisoft Pascal from what I can work out started on the ZX Spectrum System (an 8bit system) in 1983, shortly after Alan Sugar launched the Amstrad CPC464 in 1984, Hisoft Pascal 4T was one of the early languages distributed for it (which is what I'm using). I don't know a great deal about the ZX Spectrum version of Hisoft Pascal, though a number of things were added to the Amstrad version to cater for some of the features of the machine and in particular it's possible to tab into the Library of routines without the need of writing Inline M/C. Though the Compiler does provide a number of Pascal Functions, so something more generic can be produced, though like TP3, it produces a Library file of those routines, so it resolves that by letting the user tap into the Library bank of the machine.

So this is what I came up with, I made some alterations so the code works in TP3, so in this example I can turn a string from 00 to 99 and return it into it's Number format. I've used ORD() to get the Ordinal Value subtracted 48 from it to get the actual number and then use CASE on that number and use isgreater based on the digit, so that lets me get the actual digit from the string value passed through ConvNum.

Code:
PROGRAM GetNumber;

TYPE anum = STRING[2];

VAR str : anum;
    num : integer;

FUNCTION ConvNum(str : anum) : integer;
VAR mynum     : byte;
    num1      : byte;
    num2      : byte;
    isgreator : byte;
BEGIN
  num1:=ord(str[1])-48;
    CASE num1 OF
      0 : isgreator:=0;
      1 : isgreator:=9;
      2 : isgreator:=18;
      3 : isgreator:=27;
      4 : isgreator:=36;
      5 : isgreator:=45;
      6 : isgreator:=54;
      7 : isgreator:=63;
      8 : isgreator:=72;
      9 : isgreator:=81
    END; { CASE Statement }
    num2:=ord(str[2])-48;
    mynum:=num1+isgreator+num2;
    ConvNum:=mynum;
END;

BEGIN
  num:=convnum('26');
  writeln('Your Number is: ',num);
END.

All I need to do is see if I can send a longer string of numbers, and have them converted to their proper values.
 
I wish I could write in response to all of that, but I'm so tired I can barely manage to type! It was a very good read though.

In my tiredness I will show what I would do, which may or not help you at all. Obviously, I used an ANSI String, which you can't.

Code:
FUNCTION ConvNum(S:String):Integer;
VAR Result:Integer;Loop:Byte;Negative:Boolean;

BEGIN
Result:=0;
IF S[1]='-' THEN Negative:=TRUE ELSE Negative:=FALSE;
FOR Loop:=1 TO Length(S) DO IF (S[Loop]>=#48)AND(S[Loop]<=#57) THEN Result:=Result*10+Ord(S[Loop])-48;
IF Negative THEN Result:=0-Result;
ConvNum:=Result
END;
 
I wish I could write in response to all of that, but I'm so tired I can barely manage to type! It was a very good read though.

In my tiredness I will show what I would do, which may or not help you at all. Obviously, I used an ANSI String, which you can't.

Code:
FUNCTION ConvNum(S:String):Integer;
VAR Result:Integer;Loop:Byte;Negative:Boolean;

BEGIN
Result:=0;
IF S[1]='-' THEN Negative:=TRUE ELSE Negative:=FALSE;
FOR Loop:=1 TO Length(S) DO IF (S[Loop]>=#48)AND(S[Loop]<=#57) THEN Result:=Result*10+Ord(S[Loop])-48;
IF Negative THEN Result:=0-Result;
ConvNum:=Result
END;

Cool, just needed to make some small adjustments, I don't need negative numbers in my situation, so have taken that out, so I defined:

Code:
type str = array[1..4] of char;

my function looks like this:

Code:
function ConvNum(num : str) : integer;

obviously I called it num, so my if & result statements has num[loop] instead of s[loop], and the rest comes into place. Obviously under the rules of Hisoft Pascal the number requires 4 digits based on the size defined at str, my only dilemma is to get the numbers into an array.

So in my program now I have:

Code:
 mynum:=ConvNum('2000');

but what I would like to do is define an array, ironically it would be type char because Hisoft Pascal doesn't have byte, so the digits feed into it like this:

myarray[1]:=20
myarray[2]:=00

and so on. Obviously I would be extending str, let say 10 digits so I can put more numbers into the string:

Code:
ConvNum('2026010009')

so my array can look like this:

myarray[1]=20
myarray[2]=26
myarray[3]=01
myarray[4]=00
myarray[5]=09

Incidentally, I forgot to mention one of the missing links in the chain with the Hisoft Pascal's. Between the early version I'm using HP4T and HiSpeed Pascal, Hisoft released "Hisoft Pascal 80", I think this came out in 1986, this is also a 8bit Compiler, but has been made for CP/M 2.2, this would of eventuated from the release of the Amstrad PCW Business Machines, which operated solely through CP/M, though anyone with a Disk Based CPC could also have CP/M and use Hisoft Pascal 80 as well.
 
So what I did in Hisoft Pascal was setup another array (which this TP program does) and place all numbers from 0 to 26, then I define my set, so this uses 3 Digits '26','1','5', so when those values come up in the array and match with the numbers in the set, that value goes into the second array. But in all respect I don't need a 2nd array and it can be simplified to some count variable, so when it matches the numbers in the set, I can just store that in my array.

The only problem I'm having with this, is the order of the numbers. I've simply created a program which sorts numbers out, for example in my set col 26 is the first number (reading from left to right), but my second number is 1 and my third is 5, so when I print those numbers out, mp[0]=1 mp[1]=5 and mp[2]=26, guess I didn't specify this when I made my initial enquiry, so I'm unsure how to get mp[0]=26, mp[1]=1 and mp[2]=5

Still I guess it's better than nothing.

I've worked out a solution to this and have published a fairly generic Pascal program on my LinkedIn account if anyone was interested.

In summary the solution seems to be to create a sorted array of seemingly random values and have a second procedure with a sequence of values which point to anywhere in that sorted array. The sequence of values in my case are letters which are converted into digits with ord(), so the final result can have an array arranged out of a SET of data.
 
Back
Top