Thursday, April 26, 2012

Seven Languages in Seven Weeks - Prolog Day 2 Self-Study

More fun with prolog! This self-study section consists in implementing some list operations.

Reverse the elements of a list
rev([], []).
rev([Head|Tail], List) :- append(X, [Head], List), rev(Tail, X).

Find the smallest element of a list.
min([X], X).
min([Head1|[Head2|Tail]], X) :- Head1 =< Head2, min([Head1|Tail], X).
min([Head1|[Head2|Tail]], X) :- Head1 > Head2, min([Head2|Tail], X).

Sort the elements of a list.
insert(X, [], [X]).
insert(X, [H|T], [X,H|T]) :- X =< H.
insert(X, [H|T], [H|Rest]) :- X > H, insert(X, T, Rest).

isort([], Acc, Acc).
isort([H|T], Acc, Sorted) :- insert(H, Acc, Acc2), isort(T, Acc2, Sorted).

Wednesday, April 25, 2012

Seven Languages in Seven Weeks - Prolog Day 1 Self-Study

For this book's section about prolog, I'll be using SWI-Prolog, as I'm currently getting an error installing the gnu-prolog macport. Here's the link to the SWI-Prolog online reference.

Make a simple knowledge base. Represent some of your favorite books and authors.
% books.pl
book(sevenLanguagesInSevenWeeks).
book(cleanCode).
book(cleanCoder).
book(programmingInScala).
author(odersky).
author(tate).
author(martin).
wrote(odersky, programmingInScala).
wrote(tate, sevenLanguagesInSevenWeeks).
wrote(martin, cleanCode).
wrote(martin, cleanCoder).

Find all books in your knowledge base written by one author.
?- ['books'].
% books compiled 0.00 sec, 13 clauses
true.

?- wrote(martin, X).
X = cleanCode ;
X = cleanCoder.

Make a knowledge base representing musicians and instruments. Also represent musicians and their genre of music.
% music.pl
instrument(flea, bass).
instrument(hendrix, guitar).
instrument(hancock, piano).
instrument(cash, guitar).
genre(flea, funk).
genre(hendrix, blues).
genre(hancock, jazz).
genre(cash, country).

Find all musicians who play the guitar.
?- ['music'].
% music compiled 0.00 sec, 10 clauses
true.

?- instrument(X, guitar).
X = hendrix ;
X = cash.

Wednesday, April 4, 2012

How to get a List of Installed JVMs on a Mac

I got this tip from a fellow worker:
$ /usr/libexec/java_home -V
This command will get you the list of installed Java Virtual Machines installed on your Mac OS X system.

Sunday, April 1, 2012

Inspecting the Process Environment Variables with GDB

While trying to solve the 4th level of the vortex wargame, I found it was necessary to learn how to inspect the location and content of the environment variables within the process memory.

GDB has built-in commands to inspect the process environment, see the GDB manual. You can either list all environment variables or a specific one (e.g. FOOBAR) using the following commands, which will output their values:
(gdb) show environment
(gdb) show environment FOOBAR
In order to locate the environment variables within the process memory, you can query the variable char** environ (see the libc reference and this entry on stack overflow):
(gdb) x/s *((char **)environ)
This will print the location of the first environment variable and its representation as string. To print the next variables, simply add an offset to the variable:
(gdb) x/s *((char **)environ + 1)

I also found these links to be useful:

Wednesday, March 28, 2012

Seven Languages in Seven Weeks - Io Day 3 Self-Study

It's been some time now, still I'm keeping up reading Seven Languages in Seven Weeks. Here's the last self-study section about the Io programming language.

Enhance the XML program to add spaces to show the indentation structure.

Builder := Object clone
Builder numIndents := 0
Builder doIndents := method (for (i, 1, numIndents, write(" ")))
Builder openTag := method(name, doIndents; writeln("<", name, ">"))
Builder closeTag := method(name, doIndents; writeln("</", name, ">"))
Builder forward := method (
  openTag(call message name);
  numIndents = numIndents + 1;
  call message arguments foreach (
    arg,
    content := self doMessage(arg);
    if (content type == "Sequence", doIndents; writeln(content))
  );
  numIndents = numIndents - 1;
  closeTag(call message name)
)

Builder ul(
  li("Javascript"),
  li("Lua"),
  li("Javascript")
)

Create a list syntax that uses brackets

squareBrackets := method(call message arguments)

Enhance the XML program to handle attributes: if the first argument is a map (use the curly brackets syntax), add attributes to the XML program. For example: book({"author": "Tate"}...) would print <book author="Tate">.

OperatorTable addAssignOperator(":", "atPutNumber")
Map atPutNumber := method(
  self atPut(
    call evalArgAt(0) asMutable removePrefix("\"") removeSuffix("\""),
    call evalArgAt(1)
  )
)
curlyBrackets := method(
  map := Map clone;
  call message arguments foreach(arg, map doMessage(arg));
  map
)

Builder := Object clone
Builder numIndents := 0
Builder doIndents := method (for (i, 1, numIndents, write(" ")))
Builder doAttributes := method(map, map keys foreach(key, write(" ", key, "=\"", map at(key) ,"\"")))
Builder forward := method (
  doIndents; write("<", call message name);
  if(call message arguments size == 0, writeln(">"));
  numIndents = numIndents + 1;
  call message arguments foreach (i, arg,
    content := self doMessage(arg);
    if (i == 0, 
      if(content type == "Map", doAttributes(content));
      writeln(">")
    )
    if (content type == "Sequence", doIndents; writeln(content));
  );
  numIndents = numIndents - 1;
  doIndents; writeln("</", call message name, ">")
)

Monday, March 12, 2012

Seven Languages in Seven Weeks - Io Day 2 Self-Study

Here's the next self-study section about the Io programming language. These are several exercises to get some practice.

A Fibonacci sequence starts with two 1s. Each subsequent number is the sum of the two numbers that came before; 1, 1, 2, 3, 5, 8, 13, 21, and so on. Write a program to get the nth Fibonacci number. fib(1) is 1, and fib(4) is 3. As a bonus, solve the problem with recursion and with loops

The recursive approach (very concise):
fib := method(n,  if (n <= 2, 1, fib(n-1) + fib(n-2)))
And with a loop:
fib := method(n,
  p := 1;
  q := 1;
  sum := 1;
  for (i, 3, n,
    sum := p + q;
    p := q;
    q := sum
  );
  sum
)
How would you change / to return 0 if the denominator is zero?
Number div := Number getSlot("/")
Number / := method(n, if (n == 0, 0, self div(n))
Write a program to add up all of the numbers in a two-dimensional array.
a := list(list(1, 2, 3, 4), list(5, 6, 7, 8))
s := 0
a foreach(sublist, s := s + sublist sum)
Or more concise:
a flatten sum
Add a slot called myAverage to a list that computes the average of all the numbers in a list. What happens if there are no numbers in a list? (Bonus: Raise an Io exception if any item in the list is not a number.)
List myAverage := method(self sum / self size)
And with exception handling:
List myAverage := method(
  sum := 0;
  self foreach(e,
    (e isKindOf(Number)) ifFalse(Exception raise("not a number"));
    sum := sum + e
  );
   sum / self size
)
Write a prototype for a two-dimensional list. The dim(x, y) method should allocate a list of y lists that are x elements long. set(x, y, value) should set the value, and get(x, y) should return that value
List2d := Object clone

List2d dim := method(x, y,
  self rows := List clone;
  for (i, 1, x,
    cols := List clone;
    for (j, 1, y,
      cols append(nil)
    );
    self rows append(cols)
  );
  self
)

List2d set := method(x, y, value, 
  self rows at(x) atPut(y, value);
  self
)

List2d get := method(x, y, 
  self rows at(x) at(y)
)
Bonus: write a transpose method so that (new_matrix get(y, x)) == matrix get(x, y) on the original list.
List2d transpose := method(
  transposed := List2d clone;
  transposed dim(self rows at(0) size, self rows size);
  self rows foreach(i, row, 
    row foreach(j, elem,
      transposed set(j, i, elem)
    );
  );
  transposed;
)
Write the matrix to a file, and read a matrix from a file
List2d toFile := method(filename,
  file := File clone open(filename);
  self rows foreach(col, 
    col foreach (elem,
      file write(elem asString, " ")
    );
    file write("\n")
  );
  file flush close;
  file
)

List2d fromFile := method(filename,
  self rows := List clone;
  file := File clone open(filename);
  file readLines foreach(line,
    cols := line split;
    self rows append(cols)
  );
  self
)
Write a program that gives you ten tries to guess a random number from 1--100. If you would like, give a hint of "hotter" or "colder" after the first guess.
secretNum := Random value(100) floor() + 1
in := File standardInput
for (i, 1, 10,
  write("Guess number (try #", i, "): ");
  guess := in readLine asNumber;
  if (guess == secretNum, write("Win!"); break);
  if (i > 1, 
    if ((secretNum - guess) abs < (secretNum - previousGuess) abs,
      write("hotter\n"),
      write("cooler\n")
    )
  );
  previousGuess := guess;
)

Thursday, March 8, 2012

Seven Languages in Seven Weeks - Io Day 1 Self-Study

Here's the first self-study section about the Io programming language. I didn't know Io before, I still find it a bit awkward, but I'm beginning to like it.

Evaluate 1 + 1 and then 1 + "one". Is Io strongly typed or weakly typed? Support you answer with code.
Io> 1 + 1
==> 2
Io> 1 + "one"

  Exception: argument 0 to method '+' must be a Number, not a 'Sequence'
  ---------
  message '+' in 'Command Line' on line 1
Io is strongly typed, operands of different types will not be implicitly converted:
Io> 1 + "2"

  Exception: argument 0 to method '+' must be a Number, not a 'Sequence'
  ---------
  message '+' in 'Command Line' on line 1
Is 0 true or false? What about the empty string? Is nil true or false? Support your answer with code.
Io> 0 and true
==> true
Io> "" and true
==> true
Io> nil and true
==> false
How can you tell what slots a prototype supports?

Invoking an object in the prompt will print the supported slots:
Io> Car
==>  Car_0x7fb039c9a1f0:
  type             = "Car"
  vroom            = method(...)
The slotNames message returns the list of slots:
Io> Car slotNames
==> list(type, vroom)
To get the slots defined by the parent, call the proto message:
Io> Car proto
==>  Vehicle_0x7fb039c6e270:
  description      = "Something that takes you far away"
  type             = "Vehicle"
What is the difference between = (equals), := (colon equals), and ::= (colon colon equals)? When would you use each one?
=Assigns value to slot if it exists, otherwise raises exception
:=Creates slot, assigns value
::=Creates slot, creates setter, assigns value
Run an Io program from a file
$ echo '"Hello, world!" println' > helloworld.io
$ io helloworld.io 
Hello, world!
Execute the code in a slot given its name

Unfortunately, I haven't been able to solve this one yet. I guess the intent is given a slot holding some code as a string, one should figure out a statement to execute this code.
Io> code := "\"hello\" println"
==> "hello" println