Friday, June 30, 2006

Brown vs Dickens / Germany vs Argentina

Last night I started reading Dan Brown's "The Da Vinci Code" - just because someone remarked that, "You, of all people, haven't read that book?"

It's true that I have been into this sort of thing: the Fibonacci sequence, the Golden Ratio... etc etc. But I had never been into what I call "pop fiction". Anyway, I picked up the book and started reading. As reference, I always use Charles Dickens' "Great Expectations" which must be familiar to anyone who knows me (or this blog). It has the merit of being the only classic I have read cover-to-cover more than once (apart from being a heavy influence on me, almost a blueprint of where my life is going).

Getting back to the topic at hand - Dan Brown's so-called masterpiece, selling more than 60 million copies (right?) and translated into 40+ languages (somehow all popular books end up being translated into 40 or 42 languages, never 20 or 30 or 70).

A second reason for my having started reading the book was that the movie was out. It is a habit of mine to read the book a movie is based on, beforehand. For example, Great Expectations, David Copperfield, Merchant of Venice etc. Since I was already reading Memoirs of a Geisha these days, I thought about adding The Da Vinci Code to the list as well.

The novel begins with a "Facts" page, as everyone knows, a page listing three facts. It then launches straight into a murder scene. I knew what was in store. It is a thriller after all.

The book is filled with historical references, especially to art history, secret societies and Christianity. By about the 34th chapter (a third of the novel), I figured I had had enough Christian Catholic secret history-mystery nonsense. I decided to stop reading this "Hollywood screenplay" novel. I went on to Wikipedia and read the remaining plot outline. Interesting story.

Dan Brown's writing style is usually simplistic. He is a commercial writer - the way he writes is designed to clutch a reader in until he has finished the book. That's why his books sell. That's also why Sydney Sheldon sells. Brown is more concerned with captivating the reader - thrilling her with what is going on in the story. Dickens, on the other hand, was concerned with using language to paint a picture and let the reader figure out herself what was being described. Brown's style is narrative, Dickens' is artistic.

Dickens created immortal characters - so complex that you are left wondering whether one is a hero or a villain or just supporting cast. Look at Philip Pirrip, who himself proclaims that he "is a complex mixture of good and bad." Or the little Mar's Davey transmogrifying into the intimidating profile of an adolescent David Copperfield. That's Characterization. Brown fails miserably here. The most powerful character, Robert Langdon, is reduced to a hollow encyclopedia who does nothing more than blabber out history texts from memory. Sophie Nevue, "the chick", is a typical, much-needed clever hotshot spy-type woman ubiquitous in any kind of thriller novel. All dead characters.

In any case, comparing Brown with Dickens is pointless. Some may laugh, but most will agree. It is like comparing Mozart with Michael Jackson. Jackson's music is not bad, and it is more popular than Mozart's in his time. Still there is no comparison.

That said, the other match tonight, the one between Germany and Argentina, ended with a victory for Deutschland..... as I had been saying all along, yet people took Argentina's side because they were leading with 1-0 at one point. But well... they are OUT. (And just look at the un-sportsman-ship displayed by them after the match, in that melee that broke out).

Tuesday, June 27, 2006

Skype Zones ??

I can't comprehend the idea behind Skype's new service "SkypeZones". It's still in beta testing phase, though. Basically it enables anyone with a Wifi enabled device to make and receive Skype calls when they are in range of a Skype-friendly wifi hotspot. For this they are charging €2.5 for two hours or €6.5 for a whole month.

Now wtf ?!

What was wrong with going online in a wifi area, logging on to Skype and making calls? That's how anyone who has wireless (or any kind of internet access anywhere) will do. Recently, while travelling back to India, I waited about an hour at the Vienna airport, in transit. I had checked their website already and knew that they had free wireless internet there, so I took out my laptop, logged on to Skype, plugged my headset and started making calls. Talked home for half hour at no extra cost (except Skype outgoing rate, of course).

Where exactly does this new type of service, "SkypeZones" come in then?

Even if one has to pay for WiFi access, logging on to Skype after that should be no problem at all. Is Skype trying to create its own WiFi network across the world? If yes, then at a cost of 6.5 euro/month for unlimited access, I think it is perhaps the cheapest service ever, if they also allow access to the general internet. If not, then only Skype honchos know what they are up to.

What is funnier is their choice of locations. There are 5 SkypeZones in India - all in relatively obscure places in Bangalore. In France there are 6-7 airport locations - but no Charles de Gaulle (Paris' main int'l airport). And many such oddities. Like only 2 hotel locations in Luxembourg, Skype's corporate headquarter.

Friday, June 23, 2006

I think India should go the USA way and change the standard electricity supply voltage to 110 volts, since 220 obviously seems impossible for these guys to maintain. Perhaps even change it to 55 V, because right now the supply voltage is less than 80.

Wednesday, June 21, 2006

Roots

This post is in celebration of receiving an A in a humanities course (and a projected D in Computer Science, but their grading is screwed up and they are fixing it right now).

I figured it would be nice to re-affirm that I am still a "hardcore science person" (as someone attributed to me), I decided to take a look at my homework submissions in CS. Now our CS class homeworks are/were the most engaging and "hardcore" assignments because of two facts - the pace of the course is incredibly fast. One week you start to learn about boolean circuits and next week you are already writing compilers. The other reason being that we had 'encounters' with no less than 10 programming languages* through the course of our freshman year - but settled on using an arcane, esoteric functional programming language called Standard ML. We never used 'for' loops!

One of our assignments was to use SML to write an interpreter for a register machine (assembly language interpreter, in other words). That was one behemoth of an assignment. A full night of coding in the lab (how nerdy) and by 6 am I had my submission ready - 6 hours after the deadline. (please no comments).

The grader's comments - "Nothing much to say. 100/100. You came, you saw, you owned."

The next assignment was to write a Fibonacci sequence generator using pure assembly (and a rather restricted subset of assembly... we had only 4 registers in total, among other things). The real fun was to write this program and test it on the register machine (affectionately called the REGMA) we had just built. It worked beautifully. Now some of you might laugh at all this hyperexcitement, but believe me, for someone who has coded in VB and C++ for basically half his life, writing his own language, compiler, interpreter; not just from an implementation point of view, but from understanding the theory behind it, is incredibly exciting.

Another assignment was to create a compiler for our own imperative (C-like) language. It was called SW (Simple While - because it only had a simple while loop instead of for loops). Our job was to convert programsn written in this single-typed (integer only), rigid syntax language into a stack-based virtual machine code (also a severely restricted subset of any commercial VM implementation). That was rather fun.

So, not forgetting that I straight out failed the first humanities course (Intro to Social Psychology), I present hereforth, my code for the REGMA.

Cheers.


(******************************************************************************************************************)
(* Problem 1.4 - REGISTER MACHINE SIMULATOR *)

exception UnhaltedProgram; (* raised when program counter goes beyond the last instruction but there was no STOP *)
exception AccessViolation; (* heavy MS-Windows influence to be seen here.. ;) *)
exception FatalException; (* not used.. just for fun :D *)
exception InvalidJump; (* self explanatory *)

datatype instruction =
(* Basic *) load | store | add | sub | loadi | addi | subi |
(* Index *) loadin1 | loadin2 | storein1 | storein2 |
(* Moves *) moveaccin1 | moveaccin2| movein1acc| movein2acc| movein1in2| movein2in1|
(* Jumps *) jump | jumpeq | jumpne | jumpless | jumpleq | jumpgeq | jumpmore |
(* Other *) nop | stop;

type datastore = int array;
type programstore = (instruction * int) array;

datatype CPUState = CPUState of int * int * int * int;
(* Stores the 4 registers : ACC PC IN1 IN2 *)

datatype Computer = Computer of programstore * datastore * CPUState;
(* Represents the whole computer... we'll toss it around between functions *)

fun change(arr, i, x) =
let
val blah = Array.update(arr, i, x)
in
arr
end;
(* quick function to update an array AND return it *)



(* The following function will take a "Computer" and an (instruction * int) and run that instruction on The computer.
Because the Computer datatype has the complete data store as well as the 4 register values, that one instruction
will be run in the proper context and environment. The function then returns the resultant Computer, with possibly
modified values of the registers or the data store *)

fun parseInstruction(The:Computer, a:(instruction * int)) =
let
(* First we get some values out of the Computer and into some variables *)
val Computer(Program, Data, CPU) = The
val CPUState(ACC, PC, IN1, IN2) = CPU
val (opcode, operand) = a
in
(* now the command execution.. after each operation, we return the computer.
basically I reconstruct the whole computer from its various parts, possibly changing some values
depending on the instruction being executed. For example, LOAD will rebuild the computer
but with a changed ACC in the CPUState *)

if opcode = nop then Computer(Program, Data, CPU) else (* just return same computer back *)
if opcode = load then
(* make sure that the guy is not trying to load from a non existent location *)
if operand >= Array.length(Data) orelse operand < 0 then raise AccessViolation
else Computer(Program, Data, CPUState(Array.sub(Data, operand), PC+1, IN1, IN2)) else
if opcode = store then
if operand >= Array.length(Data) orelse operand < 0 then raise AccessViolation
else Computer(Program, change(Data, operand, ACC), CPUState(ACC, PC+1, IN1, IN2)) else
if opcode = add then Computer(Program, Data, CPUState(ACC+Array.sub(Data, operand), PC+1, IN1, IN2)) else
if opcode = sub then Computer(Program, Data, CPUState(ACC-Array.sub(Data, operand), PC+1, IN1, IN2)) else
if opcode = loadi then Computer(Program, Data, CPUState(operand, PC+1, IN1, IN2)) else
if opcode = addi then Computer(Program, Data, CPUState(ACC+operand, PC+1, IN1, IN2)) else
if opcode = subi then Computer(Program, Data, CPUState(ACC-operand, PC+1, IN1, IN2)) else
if opcode = loadin1 then
(* same boilerplate checking...*)
if IN1+operand >= Array.length(Data) orelse IN1+operand < 0 then raise AccessViolation else
Computer(Program, Data, CPUState(Array.sub(Data, IN1+operand), PC+1, IN1, IN2)) else
if opcode = storein1 then
if IN1+operand >= Array.length(Data) orelse IN1+operand < 0 then raise AccessViolation
else Computer(Program, change(Data, IN1+operand, ACC), CPUState(ACC, PC+1, IN1, IN2)) else
if opcode = loadin2 then
if IN2+operand >= Array.length(Data) orelse IN2+operand < 0 then raise AccessViolation else
Computer(Program, Data, CPUState(Array.sub(Data, IN2+operand), PC+1, IN1, IN2)) else
if opcode = storein2 then
if IN2+operand >= Array.length(Data) orelse IN2+operand < 0 then raise AccessViolation
else Computer(Program, change(Data, IN2+operand, ACC), CPUState(ACC, PC+1, IN1, IN2)) else
(* move commands... pretty self explanatory. Only change is in the CPUState that's returned with the Computer *)
if opcode = moveaccin1 then Computer(Program, Data, CPUState(ACC, PC+1, ACC, IN2)) else
if opcode = moveaccin2 then Computer(Program, Data, CPUState(ACC, PC+1, IN1, ACC)) else
if opcode = movein1acc then Computer(Program, Data, CPUState(IN1, PC+1, IN1, IN2)) else
if opcode = movein2acc then Computer(Program, Data, CPUState(IN2, PC+1, IN1, IN2)) else
if opcode = movein1in2 then Computer(Program, Data, CPUState(ACC, PC+1, IN1, IN1)) else
if opcode = movein2in1 then Computer(Program, Data, CPUState(ACC, PC+1, IN2, IN2)) else
(* here are the jump commands.. instead of increasing PC by 1, we increase it by the operand.
I will NOT check for invalid jumps here. One simple check in the Boot function will do the trick *)
if opcode = jump then Computer(Program, Data, CPUState(ACC, PC+operand, IN1, IN2)) else
if opcode = jumpeq then
if ACC=0 then Computer(Program, Data, CPUState(ACC, PC+operand, IN1, IN2))
else Computer(Program, Data, CPUState(ACC, PC+1, IN1, IN2)) else
if opcode = jumpne then
if ACC<>0 then Computer(Program, Data, CPUState(ACC, PC+operand, IN1, IN2))
else Computer(Program, Data, CPUState(ACC, PC+1, IN1, IN2)) else
if opcode = jumpleq then
if ACC<=0 then Computer(Program, Data, CPUState(ACC, PC+operand, IN1, IN2))
else Computer(Program, Data, CPUState(ACC, PC+1, IN1, IN2)) else
if opcode = jumpgeq then
if ACC>=0 then Computer(Program, Data, CPUState(ACC, PC+operand, IN1, IN2))
else Computer(Program, Data, CPUState(ACC, PC+1, IN1, IN2)) else
if opcode = jumpless then
if ACC<0 then Computer(Program, Data, CPUState(ACC, PC+operand, IN1, IN2))
else Computer(Program, Data, CPUState(ACC, PC+1, IN1, IN2)) else
if opcode = jumpmore then
if ACC>0 then Computer(Program, Data, CPUState(ACC, PC+operand, IN1, IN2))
else Computer(Program, Data, CPUState(ACC, PC+1, IN1, IN2)) else Computer(Program, Data, CPU)
end;




(* This is the recursive function that takes a Computer and runs the instruction which is pointed to by the PC.
If the instruction is a STOP then it returns the value of ACC otherwise after executing the instruction it
feeds the computer back to itself to run the next instruction. The PC was incremented already *)
fun Boot(The:Computer) =
let
val Computer(Program, Data, CPU) = The
val CPUState(ACC, PC, IN1, IN2) = CPU
in
if PC >= Array.length(Program) then (* ..and the PC goes beyond the last line *) raise UnhaltedProgram else
if PC < 0 then (* negative PC... how the hell? *) raise InvalidJump else
let
val (operator, operand) = Array.sub(Program, PC)
in
if operator = stop then ACC else Boot(parseInstruction(The, Array.sub(Program, PC)))
end
end;




(* AND FINALLY.... THE REGMA FUNCTION. Just convert the prog and data to a Computer, initialize the registers to zero and Boot The Computer! *)
fun regma(prog,data) = Boot(Computer(prog,data,CPUState(0,0,0,0)));


(* Test cases .. *)

(* NOTE - 1) memory cells start from number 0, not one. so to load first number, load 0 will be the command *)
(* 2) the data store is NOT expandable. so if the assembly program uses let's say memory cells upto no. 5,
then the input data store must be at least 6 in length... no auto memory resizing (come on, not
even real computers do that.. they all have fixed memory! *)

(* simple program to add 3 numbers and store in the 4th cell *)
val prog1 = Array.fromList( [(load,0),(add,1),(add,2),(store,3),(stop,0)] );
val data1 = Array.fromList( [2,3,5,0] );
regma(prog1, data1); (* so result should be... 10 i think? .. and that 0 will be overwritten with the result but we cant see that of course *)
(* yep it was 10 ! *)

(*
you can test different programs by changing it above ^
try replacing (stop, 0) by something like (jump,~50)... you will get a nice InvalidJump exception.
or maybe load,~2 to get the equivalent thing of a Blue Screen :-P

I really wanted to return the whole data store. But since i'm not asked to do that in the problem statement, I won't.
But it's easy to do. Just have to change the "if operator = stop then ACC" in the Boot function
to "if operator = stop then Data" or maybe even the whole Computer together with the data, registers, program store.
*)




Sunday, June 11, 2006

This blog has gone into dormancy.
I am back in India and don't have easy net access.

Bis bald.
(see you soon)