Starbeamrainbowlabs

Stardust
Blog


Archive


Mailing List Articles Atom Feed Comments Atom Feed Twitter Reddit Facebook

Tag Cloud

3d 3d printing account algorithms android announcement architecture archives arduino artificial intelligence artix assembly async audio automation backups bash batch blender blog bookmarklet booting bug hunting c sharp c++ challenge chrome os cluster code codepen coding conundrums coding conundrums evolved command line compilers compiling compression conference conferences containerisation css dailyprogrammer data analysis debugging defining ai demystification distributed computing dns docker documentation downtime electronics email embedded systems encryption es6 features ethics event experiment external first impressions freeside future game github github gist gitlab graphics guide hardware hardware meetup holiday holidays html html5 html5 canvas infrastructure interfaces internet interoperability io.js jabber jam javascript js bin labs latex learning library linux lora low level lua maintenance manjaro minetest network networking nibriboard node.js open source operating systems optimisation outreach own your code pepperminty wiki performance phd photos php pixelbot portable privacy problem solving programming problems project projects prolog protocol protocols pseudo 3d python reddit redis reference release releases rendering research resource review rust searching secrets security series list server software sorting source code control statistics storage svg systemquery talks technical terminal textures thoughts three thing game three.js tool tutorial twitter ubuntu university update updates upgrade version control virtual reality virtualisation visual web website windows windows 10 worldeditadditions xmpp xslt

Learning Prolog: Lab #10

The new learning prolog banner!

We are in double figures! Welcome to my solutions for the tenth and final lab session for this semester. This lab lets you in easy, and then hits you with a really nasty problem right at the end.

The first problem asked for a rule that returned the length of a list. I found this one easy:

listlength([], 0).
listlength([ _ | Tail ], Length) :-
    length(Tail, RecursiveLength),
    Length is RecursiveLength + 1.
?- listlength([ hurricane, typhoon, cyclone ], Length).
Length = 3.

I simply recurse over the list in question and add one to a counter variable on the way out. The next one is a bit harder, but still very easy - A rule that returns the nth element in a list.

nthelement(0, [ Head | _ ], Head).
nthelement(N, [ _ | Tail ], Result) :-
    N > 0,
    NRecurse is N - 1,
    nthelement(NRecurse, Tail, Result).
?- nthelement(2, [sequoia, baobab, redwood], Item).
Item = redwood .

My solution works very similary to my listlength/2 solution, but instead counts down from the number you give it until it reaches zero ,at which point it climbs back out of the recursion again and returns the item that it got up to.

The last problem was a really tough one. It demands flattened list containing all the elements in a given list of lists of arbitrary depth (exceptempty lists). It took me a while (and some help) in order to figure this one out:

squash([[]], []).
squash([], []).
squash([ [ HeadHead | HeadTail ] | Tail ], Result) :-
    squash([ HeadHead | HeadTail ], HeadResult),
    squash(Tail, TailResult),
    append(HeadResult, TailResult, Result).
squash([ Head | Tail ], Result) :-
    squash(Tail, TailResult),
    append([Head], TailResult, Result).

Cracking particular problem requires a new brain-breaking type of recursion, called Top-and-Tail recursion. It's specific to Prolog (as far as I know), and means that instead of just recursing over the tail of the list in order to iterate over it, you iterate over the head of the list as well.

Since Prolog lets us break arguments down to any depth we like, I break the incoming list down into its head and tail, and then I break the head down into its component head and tail in order to ensure that it is actually a list.

I then recurse over the head of the list ad the tail of the list separately, and concatenate the result of the two recursive calls at the end.

If the head isn't a list, then I only recurse over the tail, and append the head to the flattened tail on the way out.

I also declare that both an empty list and an empty lsit inside an empty list should return a single empty list. This allows us to avoid any rogue empty lists that might happen to be floating around from finding their way into the solution by mistake. Here's an example:

?- squash([[[a],b],[c],[d,[e],[]]], Result).
Result = [a, b, c, d, e] .

That concludes all the AI labs for semester 1, although I have another AI lab scheduled for the coming Monday. If it turns out that there's another lab, I'll post about it here. Otherwise, I'll resume this series in sesmeter 2.

Learning Prolog: Lab #9

The new learning prolog banner!

Sorry this post is rather late! I had multiple ACW deadlies to deal with, and I now have a nasty cold as of the time of writing :(

I had a bit of trouble with this lab - I originally lost the code that I had written due to a bug in my chromebook where it doesn't resume properly when I lift the lid...! Anyway, the main point of this lab was to practice the Prolog that we have learnt already. A lot. There were 7 problems to solve, 6 of which I have a solution for. The first two aren't very interesting, so I'll just include the code and some examples below and move on.

sbrlmember(Item, [ Head | Tail ]) :-
        Item = Head ;
        sbrlmember(Item, Tail).

lastitem([ LastItem | [] ], LastItem).
lastitem([ _ | Tail ], LastItem) :-
        lastitem(Tail, LastItem).
?- sbrlmember(Item, [ apple, orange, grape ]).
Item = apple ;
Item = orange ;
Item = grape ;
false.
?- lastitem([ car, bus, truck, lorry, aeroplane ], Result).
Result = aeroplane .

The above contains definitions for two rules: sbrlmember and lastitem. sbrlmember works exactly like the member function that's built into Prolog, and lastitem, given a list, tells you what the last item in that list is.

The next one in the sequence is a rule that, given a list, returns the reverse of that list. Here's my solution, and an example:

listreverse([ Head | [] ], [Head]).
listreverse([ Head | Tail ], Result) :-
    listreverse(Tail, TailReversed),
    append(TailReversed, [Head], Result).
?- listreverse([windows, max, linux], Result).
Result = [linux, max, windows] .

Basically, it recurses over the tail of the list until there is just a single item left, at which point it returns the head on it's own in a list. When it comes back out of the recursion, it sticks everything back on the end of the list again in the reverse order.

The next problem we were given was to, given a pair of lists, return a third list containing all the items that appeared in both of the original lists. I decided to cheat a bit here and use an accumulator

intersection([], _, []).
intersection([ Head | Tail ], ListB, Result) :-
    member(Head, ListB),
    intersection(Tail, ListB, RecResult),
    append(RecResult, [Head], Result).
intersection([ _ | Tail ], ListB, Result) :-
    intersection(Tail, ListB, Result).

Complicated problems call for complicated solutions, so I decided to recurse over the first list and check to see if the current item is present in the second list. If so, then we add it to the result - if not, then we simply ignore it and carry on recursing. When it hits the end o fthe recursion, I start it off with an empty list, which it then adds to as it climbs its way back out of the recursion.

?- intersection([snow, rain, wind, flame], [snow, flame], Result).
Result = [flame, snow] .

The last problem I built a solution for asked for a rule that deleted the given atom (I think that's what you call them in Prolog?) from the given list.

deleteall(_, [], []).
deleteall(Item, [ Head | Tail ], [ Head | Result ]) :-
    not(Item = Head),
    deleteall(Item, Tail, Result).
deleteall(Item, [ _ | Tail ], Result) :-
    deleteall(Item, Tail, Result).
?- deleteall(snake, [ squirrel, bird, cat, snake ], Result).
Result = [squirrel, bird, cat] .

My solution copies everything in the list over to the result (rather like the intersection problem above actually), unless the next item along is equal to the item we are supposed to be ognoring, in which case we skip it. I do this by adding a condition on the rule that copies the item over to the result that it can't be the item that we were told to remove.

That's the last problem from this lab - I'll have the solutions for the 10th lab up soon.

Bitwise Operators in C++

A while ago I was given some directed reading on bitwise operators in C++. I've been so busy with coursework, I haven't had time to take a look! Thankfully, I found some time and thought that it would make a good post here.

Bitwise operators in C++ appear to be very similar to those in Javascript. They operate on things at a binary level - i.e. operating on the individual bits that make up a number. Apparently there are 6 different operators:

  • & - Bitwise AND
  • | - Bitwise OR
  • ^ - Bitwise XOR (eXclusive OR)
  • ~ - Bit inversion (monadic)
  • << - Shift bits to the left
  • >> - Shift bits to the right

I'll explain each of these with examples below.

Bitwise AND

Bitwise AND takes a bit from each thing (usually a number), and outputs a 1 if they are both 1s, and a 0 otherwise. Here's an example:

87654321
--------
01011010 // 90
11010101 // 213
-- AND --
01010000 // 80

In the above example, the only 1s that actually make it through to the final result are positions 7 and 5, which are worth 64 and 16 respectively. This can be useful for extracting a specific bit from a number, like this:

#include <iostream>
using namespace std;
void main() {
    int c = 58, d = 15;

    cout << "c " << (c & 32) << endl;
    cout << "d " << (d & 32) << endl;
}

In the above, I create 2 variables to hold the 2 numbers that I want to test, and then I perform an AND on each one in turn, writing the result to the console. It should output something like this:

c 32
d 0

This is because 58 is 00111010, and 32 is 00100000, so only the 6th bit has a chance of making ti through to the final result.

Bitwise OR

Bitwise OR outputs a 1, so long as any of the inputs are true. Here's an example:

87654321
--------
10110101
00011101
-- OR --
10111101

Bitwise XOR

Bitwise XOR stands for exclusive OR, and outputs a 1 so long as either of the inputs are 1, but not both. For example, 1 ^ 0 = 1, but 1 ^ 1 = 0.

87654321
--------
10101101
11001110
-- XOR --
01100011

Bit inversion

Bitwise inversion is a monadic operator (i.e. it only takes one operand), and flips every bit of the input. For example 11011101 (221) would become 00100010 (34), although this greatly depends of the type and length of the number you are using.

Bit shifting

Bitshifting is the process of shifting a bit of bits to the left or right a given number of places. For example, if you shift 1010 (10) over to the left 1 place you get 10100 (20), and if you shift 0111 (7) over to the right by one place you get 0011 (3). If you play around with this, you notice that this has the effect of doubling and halving the number:

cout << "f ";
int f = 5;
for(int i = 0; i < 5; i++)
{
    f = f << 1;
    cout << f << " ";
}
cout << endl;
cout << "g ";
int g = 341;
for(int i = 0; i < 5; i++)
{
    g = g >> 1;
    cout << g << " ";
}
cout << g << endl;

It doesn't deal with the decimal place, though - for that you need something like a float or a double. Here's some example output from the above:

f 10 20 40 80 160
g 170 85 42 21 10 10

At first glance, the bit shifting operators in c++ look the same as the ones used to stream things to and from an input / output stream - I'll have to be careful when using these to make sure that I don't accidentally stream something when I meant to bitshift it.

Bitshifting can be useful when working with coloured pixels. You can set a colour like this:

unsigned int newCol = ((unsigned int) 248)<<16) +
    ((unsigned int) 0)<<8) +
    ((unsigned int) 78);

I think that just about covers bitwise operators in C++. If you're interested, you can find the source code that I've written whilst writing this post here (Raw).

Learning Prolog: Lab #8 - findall/3

The new learning prolog banner!

This week's lab was all about findall/3, and a little bit more about lists. To summarise, findall lets you, well, um, find everything that matches a given rule or set of rules. For example, if we have the following dataset:

mountain(everest).
mountain(k2).
mountain(matterhorn).
mountain(kangchenjunga).
desert(sahara).
desert(gobi).
desert(atacama).

tall(everest).
tall(k2).
tall(kangchenjunga).

We could ask Prolog to give us a list of all the mountains in it's world. It's rather like issuing a database with an SQL query, asking it to find all the records that match a set of criteria and return them.

?- findall(Mountain, mountain(Mountain), MountainList).
MountainList = [everest, k2, matterhorn, kangchenjunga] .

?- findall(Mountain, (mountain(Mountain), tall(Mountain)), List).
MountainList = [everest, k2, kangchenjunga] .

?- findall(Desert, desert(Desert), DesertList).
DesertList = [sahara, gobi, atacama].

?- findall(Place, (desert(Place); mountain(Place)), Places).

Places = [sahara, gobi, atacama, everest, k2, matterhorn, kangchenjunga] .

As I demonstrated above, you can combine multiple criteria with a set of brackets and a few commas or semi-colons.

The other thing that we looked at was a rule that would return the last item in a list. Here's what I came up with:

% Stopping condition - stop when we reach the last item
lastitem([ LastItem | [] ], LastItem).
% If we haven't reached the end of the list, recurse on the rest of the list.
lastitem([ _ | Rest ], LastItem) :-
    lastitem(Rest, LastItem).

The above keeps throwing away the first item in the given list until it finds the last item, which it then stores in the variable LastItem. It knows which the last item is because lists in Prolog are always terminated with an empty list ([]). Here's an example of the above in action:

?- findall(Place, (desert(Place); mountain(Place)), Places), lastitem(Places, LastPlace), write('The last place is '), write(LastPlace), write('.'), nl.
The last place is kangchenjunga.
Places = [sahara, gobi, atacama, everest, k2, matterhorn, kangchenjunga],
LastPlace = kangchenjunga .

That brings us to the end of the 8th Prolog lab session. This post feels a bit short, but I'm sure that there will be more to post about next time. If you're interested, here is a link to the Prolog file that I have written whilst writing this post.

Learning Prolog: Lab #7

The new learning prolog banner!

Today's lab introduced lists, and they are a lot harder to comprehend than the other things that we have done so far. You can define a list in Prolog with square brackets, like so:

?- Sandwiches = [ cheese, chicken, cucumber, lettuce_and_tomato ].

This isn't particularly useful, but the real fun comes later on after you've written a bunch of utility rules. Before I get into that though, I should explain a little bit about heads and tails. In Prolog, you can split a list up into its head and its tail with a bar character (|), like so:

printhead([ Head | Tail ]) :-
    write(head).

Here's a quick example of the above in action:

?- printhead([ apple, orange, grape ]).
apple
true.

This is especially useful for recursion, as we shall see in a moment. With that out of the way, here are few utility rules that I put together. There's one that writes out all the items in a list, one that counts up all the numbers in a list, one to concatenate two lists together, and one to calculate the length of a list. They all use loops, so if you don't understand those you should go back and read my previous blog post before continuing.

writelist([]). % Stopping condition.
writelist([ Head | Tail ]) :-
    % Write out the head of the list.
    write(' - '), write(Head), nl,
    % Recursively write out the rest of the list.
    writelist(Tail).

concat([], List, List). % Stopping condition - The 2nd list and the result should be one and the same
% Add the head of the first list onto the result
concat([ Head | Tail ], List2, [ Head | Result ]) :-
    % Recursively add the next item in the first list to the result
    concat(Tail, List2, Result).

countlist([ LastItem | [] ], LastItem). % Stopping condition - Don't continue if we reach the end of the list.
countlist([ Head | Rest ], Result) :-
    % Recursively count the rest of the list
    countlist(Rest, RecursiveResult),
    % Add the head to the result from recursively counting the rest of the list.
    Result is RecursiveResult + Head.

listlength([ _ | [] ], 1).
listlength([ _ | Tail ], Result) :-
    listlength(Tail, RecursiveResult),
    Result is RecursiveResult + 1.

All of the above use a similar loop structure. They recursively sort out the tail, and then deal with the tail when we coming back out again. Here are some examples of the above rules (virtual cookie for whoever works out what all the things in each of the lists below have in common). Don't forget to ask questions in the comments if you don't understand something.

?- writelist([ cat, dog, parrot, elephant, whale]).
- cat
- dog
- parrot
- elephant
- whale
true
?- countlist([ 4, 7, 2, 18, 48, 364 ], Result).
Result = 443 .
?- listlength([ alpha_centauri, sirius, barnards_star, epsilon_eridani, tau_ceti], Length).
Length = 5 .
?- concat([elysium_mons, arsia_mons, aeolis_mons], [skadi_mons, maat_mons], Result).
Result = [elysium_mons, arsia_mons, aeolis_mons, skadi_mons, maat_mons].

Find all the things!

The other thing we looked at this week was the findall/3 predicate. In a nutshell, findall will find everything that matches the given criteria and put them in a list. Here's a simple example:

loves(cat, milk).
loves(dog, bone).
loves(mouse, cheese).
loves(mouse, seeds).
loves(cat, cheese). % Yes, my cat does love cheese...!
loves(parrot, seeds).
?- findall(Who, loves(Who, cheese), Result), writelist(Result).
 - mouse
 - cat
true.

In the above example, we ask Prolog to find us everyone who loves cheese, and then print out the result. The second argument is the criteria we want Prolog to use when searching, the first argument is the variable from the criteria that we want to store, and the third argument is the list we want populating.

As an exercise, try to work out how to ask Prolog who likes seeds, given the above dataset. If you find that easy, try asking Prolog to list everyone who likes both seeds and cheese. The answers will be in the comments.

findall can be used to search many different datasets. Here's another more complicated example:

isa(polly, parrot).
isa(parrot, bird).
isa(bird, living_thing).
hasa(parrot, wings(2)).
hasa(polly, perch).
hasa(polly, colour(green)).
?- findall(green_birds(Who), hasa(Who, colour(green)), Result).
Result = [green_birds(polly)] .

That concludes this blog post on the 7th Prolog lab. If you are interested, here are some links to the source code for the examples found in this post, along with a few extras.

Learning Prolog: Lab Session #6 - More Looping

The new learning prolog banner!

Fireworks

Before I get into today's post, I wanted to include a picture of some firework that I managed to photograph a few days ago on my phone. A heard them outside and when I took a look out of the window, this is what I saw!

Anyway, Today's Prolog lab session was about more loops. These loops are different to the failure driven loops that we did last time though in that they are recursive instead. Here's an example:

loopa :-
    write('Enter \'end.\' to exit.'), nl,
    read(Input), (Input = end ; loopa).

The above is a simple rule that keeps asking for user input until the user enters 'end'.

?- loopa.
Enter 'end.' to exit.
|: hello.
Enter 'end.' to exit.
|: cheese.
Enter 'end.' to exit.
|: end.
true.

This is done through the semi colon, which acts as an or operator. Although this works, it isn't very readable. Let's try something else.

% Stopping condition
loopb(end).
% Main loop
loopb(Input) :-
    write('Enter \'end.\' to exit.'),
    read(Input2),
    loopb(Input2).

% Starter rule
go :-
    loopb(something).

Much better. The above is divided up into the stopping condition (i.e. when the user types end), the main loop, and a rule that kicks the rest of the program off. When go is called, we call loopb with something as a parameter immediately. Since this doesn't match the fact loob(end), Prolog looks at the rule we defined, loopb(Input). Then it asks the user for input, and starts the process over again until the user inputs end.

Here's an example of the above in action:

?- go.
Enter 'end.' to exit.gdsfgdrt.
Enter 'end.' to exit.sdfgsdgf.
Enter 'end.' to exit.sdfgsdfgertr.
Enter 'end.' to exit.cheese.
Enter 'end.' to exit.end.
true.

Having learnt this, one of the challenges was to write a rule in Prolog. A factorial is where you multiply an integer by all the integers greater than 0 but less than the integer. For example, 4! (4 factorial) is 4x3x2x1, which is 24). Here's what I came up with:

factorial(1, 1).
factorial(N, Factorial) :-
    N2 is N - 1,
    factorial(N2, Ans),
    Factorial is N * Ans.

And here's an example of the above in action:

?- factorial(6, Answer).
Answer = 720 .

That concludes this post on the 6th Prolog lab session. If you don't understand something (or I've made a mistake!) please post a comment below and I'll do my best to help you. Also, if you have any, post your firework pictures below. I'd be interested to see them!

On CPU Registers in Assembly

I've been given some directed reading from the Intel Software Developer's Manual recently, and I found it complicated enough that I had to make about 2 1/2 pages of notes on what I read. This post is an attempt to explain to you what I learnt, in the hopes that I don't forget it! There will probably be mistakes in here - please point them out in the comments below!

The x86 instruction set contains a number of registers, each of which can be accessed in a number of different ways depending on the number of bits you wish to get or set.

Description 8 bit (byte) 16 bit (word) 32 bit (dword) 64 bit (qword)
General purpose AL AX EAX RAX +
General purpose BL BX EBX RBX +
General purpose CL CX ECX RCX +
General purpose DL DX EDX RDX +
General purpose (high byte) AH * - - -
General purpose (high byte) BH * - - -
General purpose (high byte) CH * - - -
General purpose (high byte) DH * - - -
? DIL + DI EDI RDI +
? SIL + SI ESI RSI +
Base Pointer BPL + SP ESP RSP +
Stack Pointer SPL + BP EBP RBP +
General Purpose R8L + R8W + R8D + R8 +
General Purpose R9L + R9W + R9D + R9 +
General Purpose R10L + R10W + R10D + R10 +
General Purpose R11L + R11W + R11D + R11 +
General Purpose R12L + R12W + R12D + R12 +
General Purpose R13L + R13W + R13D + R13 +
General Purpose R14L + R14W + R14D + R14 +
General Purpose R15L + R15W + R15D + R15 +

This table requires some explanation. Registers suffixed with * may only be utilised in 32 bit assembly. Similarly, registers suffixed with + may be utilised in 64 bit assembly only. Each row is a register, and each column represents a different number of bits. For example, the EAX register can be accessed as an 8 bit register with AL, 16 bit as AX, 32 bit as EAX, and 64 bit as RAX.

The exception here is the AL, BL, CL, DL, AH, BH, CH and DH registers. These actually refer to the same register. Let's take AL and AH for example. The AL register refers to the first 8 bits of the AX register, and the AH register refers to the second 8 bits. This is called the Low byte and the High byte.

In addition to the registers above, there are two others which can also be accessed as 8, 16, 32 and 64 bit registers:

Description 16 bit 32 bit 64 bit
Instruction Pointer IP EIP RIP
CPU Flags FLAGS EFLAGS RFLAGS

These registers should not be written to under normal usage though, as the CPU uses these to maintain its internal state. The instruction pointer points to the instruction that the CPU is currently executing, whereas the CPU Flags register holds all of the current flags, such as the result of a cmp (comparison).

That concludes this post on CPU registers. I don't think I can quite believe I'm posting this actually.... a year ago I would never have suspected I'd be learning about how to program the CPU itself in assembly.

Learning Prolog: Lab Session #5 - Backtracking

The new learning prolog banner!

The next lab in the series introduces the idea of backtracking. Apparently Prolog is somewhat persistent in its attempts to prove things that you ask it, leading it to go back to where it last had a choice and try a different route when faced with failure.

Let's take this dataset (or knowledge base) for example:

food(apple,fruit).
food(tomato,fruit).
food(lettuce,salad).
food(beef,meat).
food(cucumber,salad).

This is a simple set of foods, along with their types.

What if we were lazy and wanted to get Prolog to output all the different salad foods in the above dataset? It's too much work for us to us (there might be thousands of lines to search in future), so let's insert the following lines:

display_salad_food :- food(Food,salad),
    write(Food), write(' is a salad'), nl, fail.

(Pastebin, Raw)

The above is a rule that can be satisfied by fetching a food of type salad. It then writes out the food to the console, then a new line, and then hits fail - a brick wall that tells Prolog that it, well, erm... failed. This causes Prolog to backtrack to the last choice it made (in this case food(Food,salad)) and try finding a different route. Here's some example output from the above:

?- display_salad_food.
lettuce is a salad
cucumber is a salad
false

This construct is called a failure driven loop. This is because it gets Prolog to try all possibilities by backtracking - causing it to fail over and over again while it searches out alternative routes.

The other thing this lab introduced was repeat predicate. This acts as a 'checkpoint', so to speak, which lets Prolog continue from this point, even if it doesn't find any path to take. Here's an example, though I should warn you that running it will crash Prolog! (unless you are using the web based editor or course - then you can just hit the abort button)

hello_world :- write('Hello '), repeat, write('World'), nl, fail.

And here's some example output:

Hello World
World
World
World
World
World
World
World
World
World
...

The reason it crashes is because it contains an infinite loop. Prolog writes out Hello,, and writes out World and a new line, and then hits fail. Going back, it spots a repeat statement, which allows it to continue. It then writes out World again, hits the fail, and so on and on and on.....

That concludes this post about lab #5. If you found it helpful, please comment (I love reading comments)! Suggestions and constructive criticism are always welcome too!

Learning Prolog: Lab Session #4 - Reading and Writing

The new learning prolog banner!

This week we were asked to do another 2 labs in one session - this blog post will cover lab #4, and there will be another one coming out on Thursday for lab #5.

Before we start though, I want to mention Swish. It's an online editor for Prolog that runs in the browser. It apparently doesn't support all the features that the desktop version does, but the editor itself is so much better than the desktop version. It's actually bearable! If at all possible, I'll be using it from now on.

This week's (first) lab was all about reading and writing from the console. You would have thought that this would be the first thing you'd learn as a hello world, but apparently that isn't the case. 3 weeks into the course, and we finally know enough to write our first hello world in Prolog!

Anyway, reading and writing are quite simple actually - once you've learnt rules. Here's an example:

go :-
    write('Hello, world!').

If you query go. on the above, you should get an output something like this:

?- go.
Hello, world!
true

The write/1 (write arrity 1) statement lets us write out a message to the console. Note that the string we want to output is enclosed in single quotes. This is important, because apparently some Prolog environments interpret double quotes to mean "output the ASCII character codes of the characters in this string", and not "output the characters themselves in this string". Personally I haven't found that to be the case, but it's best to be aware of it.

Writing messages to the console is neat, but not particularly useful in itself. Let's upgrade it to ask the user's name, and then say hello to them:

go :-
    write('Enter name: '), read(Name),
    write('Hello, '), write(Name), write('!'), nl.

Here's an example output:

?- go.
Enter name:
|: starbeamrainbowlabs.
Hello, starbeamrainbowlabs!
true.

When you ask Prolog go., it then asks you what your name is - and then says hello to you. There are several things to note here. Firstly, nl/0 is a special predicate that simply write a newline character to the console. Secondly, read/1 is a special predicate to read in a string from the console and drop it into the given variable.

read/1 can be rather weird when it comes to actually getting input from the user. The string the user enters must be terminated by a full stop (.), otherwise it will continue to ask for input. It must also start with a lower case letter, otherwise strange stuff starts to happen. I theorise that this is probably related to the fact that variables in Prolog start with an uppercase letter.

Thankfully, we can get around the second issue by enclosing strings in double quotes:

?- go.
Enter name:
|: 'Starbeamrainbowlabs'.
Hello, Starbeamrainbowlabs!

Much better. Let's actually use these new functions to do something (kind of) useful. Here's the first excercise:

Write a Prolog program using facts in the form month/1 that displays the month depending on the integer entered by the user, e.g. if the user enters 3 the program will display The Month is March.

Initially I was started with a program beginning like this:

month(January) :-
    % ...

But soon found that it didn't work. The solution here is to invert it, so that Prolog gets to choose which path it takes based on the input it gets. It makes sense, I suppose, considering Prolog is a language for writing artificial intelligences.

Here's some example output:

?- month(1).
January
true.
?- go.
Enter month code:
|: 4.
April
true.

In the above, we can either call query month/1 directly, or query go., which will ask us for the month code directly and call month/1 for us.

That concludes the 4th lab. I'll write up another post for lab #5, which should hopefully be out on Thursday. As an aside, I used the embed code from PasteBin in this post instead of embedding the code directly and then linking to the PasteBin. Which would you prefer? Why? Do you have another idea? Let me know in the comments!

Static Variable Memory Allocation

Recently we were asked in an Advanced Programming lecture to write a program that proves that static variables in C++ are located in a different area of memory to normal variables. This post is about the program I came up with.

But first I should probably explain a little bit about memory allocation in C++. I'm by no means an expert (I'm just learning!), but I'll do my best.

There are two main areas of memory in C++ - the stack and the heap. The stack is an ordered collection of data that contains all the local variables that you define. It grows downward from a given address in memory. The stack is split up into frames, too, with each frame being a specific context of execution. You can find more information about this in the Intel Software Developer's Manual, Section 6.2.

The second area of memory is the heap. The heap is a large portion of memory that can be used for storing large lumps of unordered data. I haven't taken a look at this yet, so I don't know much more about it.

Apparently variables that are declared to be static are not located in the stack (where they are located I'm not entirely sure), and we were asked to prove it. Here's what I came up with:

#include <iostream>
#include <string>

using namespace std;

void staticTest()
{
    static int staticD = 0;
    cout << "staticD: " << &staticD << endl;
}

int main()
{
    int a = 50;
    int b = 200;
    int c = 23495;

    cout << "a: " << &a << endl;
    cout << "b: " << &b << endl;
    cout << "c: " << &c << endl;

    staticTest();

    int e = 23487;
    cout << "e: " << &e << endl;

    //cin.get();

    return 0;
}

The above simply creates 3 normal variables, outputs their addresses, calls the staticTest() function to create a static variable and output it's memory address, and then creates a 4th normal variable and outputs its address too. The above program should output something like this:

a: 0091F8C4 b: 0091F8B8 c: 0091F8AC staticD: 00080320 e: 0091F8A0

In the above output, the normal variables a, b, c, and e are all located next to each other in memory between the adresses 0091F8C4 and 0091F8A0 (note how the memory address is decreasing - the stack grows downward, like a stalactite). The static variable staticD, however, is located in an entirely different area of memory over at 00080320. Since it's located in an entirely different area of memory, it's safe to assume, I think, that static variables are not stored in the stack, but somewhere else (I'm not sure where - the heap maybe?).

If you know where they are stored, please leave a comment below!

Art by Mythdael