6/28/2008

Assorted (not so known) tips on MacOSX

I just came across these two tips recently, so you can find them either officially documented or in public forums like I did.

Tip #1: Dashboard widgets on your Desktop

Dashboard is one of those features that I believe are not very well explored in terms of desktop interaction, in MacOSX. I mean, many times it happened me (and I believe with most of you) to play a bit with some dashboard widgets but quickly end up forgetting about their existence, since one needs to change between dashboard mode and desktop mode. This tip I found out about a couple of days ago, when I first came across with a software review of Amnesty Singles. This piece of software basically allows you to transform any widget into a "standard" application. Nevertheless, if you are not willing to pay for such great software, there is quick and dirty tip that pretty much does the same thing (original link):

Preparation (1st time):


  • Open Terminal (just type "Terminal" in Spotlight, or alternately open Applications->Utilities->Terminal)

  • While in Terminal, type: defaults write com.apple.dashboard devmode YES

  • Logout, for the previous command to take effect, and Login again.



Everytime you want to add a widget to your desktop:

  • Press F12 to open Dashboard.

  • Press the mouse down to drag the widget of your choice.

  • Without releasing the mouse button, press F12 again to return to desktop mode.

  • When in desktop, you may release the mouse button and the widget will remain in your desktop!



Everytime you want to remove a widget from your desktop:

  • Press the mouse down to drag the widget of your choice.

  • Without releasing the mouse button, press F12 again to open Dashboard.

  • When in Dashboard, you may release the mouse button and the widget will return to it!



Not everything is perfect with this method. For instance, the widget will remain "always on top" and there is no way to minimise it to the Dock temporarily. The best thing you can do with most of them is to "reduce" their window size. This is why you should consider paying for Amnesty Singles if you are not satisfied with these limitations.

Tip #2: MacBook/Pro with open/closed lid, built-in display off (not dimmed) and external display (external USB keyboard not required)

Many of you usually prefer an external display, especially if you use your MacBook/Pro in a daily basis. Either because you find it distracting when using an external display or if you don't need your built-in display and want to save its life, you might find this tip useful. The option of whether to leave the lid open or closed is up to you, but the main reason to leave it open is to make the MacBook/Pro ventilate better. Some people even argue that with older Mac laptops such as PowerBooks, leaving the lid closed might cause it to melt under heat.

Ok, so here's the tip (original link):

  • First, make sure to connect your MacBook/Pro's power adaptor to a power source, if it's not already.

  • Plug in your external monitor to your MacBook/Pro. Turn the monitor on, if it's not already.

  • After a while, if an image does not appear in your external monitor, go to System Preferences->Displays and click a button entitled Detect Displays. An image should appear in your external monitor.

  • Now, the image that appears in your external monitor should represent either a mirrored desktop or an extended desktop. It is essencial that your MacBook/Pro is set to Mirrored Mode. If it is not, press F7 once and it should turn to "Mirrored Mode".

  • Close the lid of your MacBook/Pro and it will go to sleep

  • Now, plug in any USB device (e.g., an external keyboard, a mouse, a pen drive will also do it). If you already have an external mouse or keyboard attached to your laptop, you just need to press some key or button. This will make your MacBook/Pro awake from sleep and use the external screen as the main display.

  • When the external display shows your Desktop again or your MacBook/Pro prompts for a password (if you activated this security feature for protection), then you can open the lid, if you want your laptop to dissipate better.

  • Voilá! Your built-in display is turned off (not dimmed), your MacBook/Pro is not sleeping, and you can either use its built-in keyboard and mouse pad if you don't want to use an external USB mouse/keyboard like many forums advocate as necessary!



If you want to turn your built-in display back again:

  • Go to System Preferences->Displays and click a button entitled Detect Displays. The built-in screen should turn on again.

6/08/2008

Directory Utility and remote NFS mounts on Mac OS X Leopard

One of the graphical utilities I usually like to use on Mac OS X Leopard, in order to avoid unnecessary command-line tasks, is Directory Utility.

Directory Utility allows you to easily manage local/remote services and file systems. With this tool you can mount remote NFS file systems from *BSD, Linux and other UNIX-based Operating Systems. Although it only takes one command-line call to mount a remote filesystem, that's already very well documented in many Operating System manuals, so that is not the purpose of this post.

If you are wondering how to do it, or having problems doing it, you should launch Directory Utility first. You can access it through the Applications->Utilities folder or you can use Spotlight for that purpose (typing "Directory Utility").
If you want to add a mount, click in the following order after Directory Utility window appears:



The following dialog appears, and you should fill the fields in a similar way to the following:


If you are wondering what -P is, it's basically an indication to use a reserved socket port number. Many people claim this flag prevents connectivity problems associated to Directory Utility and NFS.

If your Mac does not verify your NFS mount and you are positively sure you entered everything correctly, then it's probably because you are connecting to a NFS server that only works with UDP protocol. You can either click Don't verify button while Directory Utility is searching for the NFS server; or, if you are the administrator of the NFS server, you can add support for TCP transports by appending the -t flag when you call nfsd. After you restart the NFS server and retry adding the mount, Directory Utility will probably be able to verify it successfully.

6/04/2008

Google Treasure Hunt 2008, 4th and last Puzzle

Two days ago, the 4th and last puzzle of GTH2008 was announced by Google, I suppose at 23:15 UTC/GMT.

I have to confess I didn't solve this problem in one shot. The first half of it was done before I got stoned of drowsiness! The second half was solved after a few hours of sleep. Shame on me... the problem was not difficult at all, and I'm not saying this because I have already solved it! It really was simple...

It can be said that the last puzzle could be, in my opinion, made up of two small puzzles:


  • first, how to deal with prime number generation and/or how to perform primality tests (quickly!)

  • second, how to sum the numbers correctly and find the smallest prime sum of consecutive prime numbers (quickly and hopefully without any mistake!)


I spent like 4 hours solving the whole puzzle in the first half but invested most of it in the first "small" puzzle. My solution for the first "small" puzzle was already fast enough for the problem at hand but I always got the program asking for **more and more** prime numbers... I was generating like millions and millions of prime numbers and even so it never seemed to find a result... My question was for the numbers [11, 83, 183, 631, 1037]. I thought that the sum of each set of 11, 83, 183, 631, and 1037 consecutive prime numbers to be simultaneously equal and a prime number itself would be the reason why it was taking so many prime numbers...

In the second half, after a deserved time sleeping, I decided to "attack" the second "small" puzzle when I immediately noticed a big mess.

Forth problem

When I decided to follow the ancient algorithm of the Sieve of Eratosthenes to pre-compute all the prime numbers up to a specified integer, I could see that second "small" puzzle was "lagging" the whole thing and not the first...

According to the reasoning I used in the algorithm to find the smallest sum of prime numbers, we must keep an eye on the current "smallest sum possible". This is to say that, if we start with two sets (call it "strings") of 3 and 7 consecutive prime numbers the initial smallest sum possible is defined by the first 7 primes (equals 41) because it is impossible for the sum of 7 consecutive prime numbers to be less than the first 7 primes.

Trying to put it simply:
The algorithm tries to shift every string of consecutive prime numbers (a string of length 3, and a string a length 7) by one prime number to the right if the sum of that string is smaller than the current "smallest sum possible". If a string is found whose sum is greater than the current "smallest sum possible", then it means the current "smallest sum possible" kind of "overflowed" and it is not possible to find two strings of length 3 and 7 whose sums are equal and up to the current "smallest sum possible". When this "overflow" happens, the current "smallest sum possible" must be updated to the minimum of the sums of the current strings.

Code for the solution

The following solution is written in C++ and sacrifices a lot of memory. As you will see, it even stores whether odd numbers, zero and one are prime or not which is not needed, as I didn't care much about it... Another problem with the program is that it does not ensure the defined MAX_NUMBER of prime numbers is enough to solve the problem, nor it tests that condition. If it is not enough, you will get a beautiful "segmentation fault", "bus error" or other crash =) Just set the value high enough paying attention to memory limits. The default value of 10000000 should be more than enough for all or most problems for the 4th puzzle.
Nevertheless, the program computes the solution for [11, 83, 183, 631, 1037] and others in about 4 seconds.

Update:
I've just updated my solution removing support for biging library as it is not required at all! My solution now takes a total of 0.233 seconds to print the result (0.221172 seconds for the prime generation up to 8000000 plus 0.00250829 seconds for the second "small" puzzle):

$ time ./sumprimes
Precalculating...
348513 primes pre-calculated
Took 0.224782 seconds
Result: *******
Took 0.00254872 seconds

real 0m0.233s


/**
* Google Treasure Hunt 2008 - Question 4
* by Mário Freitas (imkira at gmail dot com)
*/

// standard libraries
#include
#include

#import

// support for big integers
#include "BigInteger.hh"
#include "BigIntegerUtils.hh"

// please change as desired
#define MAX_NUMBER 8000000
#define NUM_NTH_PRIMES 5000000

// number of strings
#define NUM_STRINGS 5

typedef unsigned long long Counter;

// sarifice space for prime numbers...
bool gIsPrime[MAX_NUMBER+1];
Counter gMaxNumber(MAX_NUMBER);
Counter gMaxNthPrime(NUM_NTH_PRIMES);
Counter gNthPrimes[NUM_NTH_PRIMES+1];
Counter gSumIndices[NUM_STRINGS];
Counter gSumLengths[NUM_STRINGS];
Counter gSumTotals[NUM_STRINGS];

void buildPrimesErastothenes ()
{
Counter lNumber = 2, j, lTwo = 2;

// initialize array to true
memset(&gIsPrime, 1, sizeof(gIsPrime));
gIsPrime[0] = gIsPrime[1] = false;

// do not care about even numbers, zero or one...
// just calculate if an integer is prime or not!
while ((lNumber * lNumber) <= gMaxNumber)
{
j = lNumber * lTwo;

while (j <= gMaxNumber)
{
gIsPrime[j] = false;
j += lNumber;
}

++lNumber;

while ((lNumber <= gMaxNumber) && (!gIsPrime[lNumber]))
{
++lNumber;
}
}

j = 0;

// calculate an array which contains the Nth prime numbers
for (Counter i = 0; i <= gMaxNthPrime; ++i)
{
if (gIsPrime[i])
{
gNthPrimes[j] = i;
++j;
}
}

std::cout << j << " primes pre-calculated\n";
}

Counter sumConsecutivePrimes (Counter aNth, Counter aLength)
{
Counter lSum = 0, i = aNth;

aLength = i + aLength;

while (i < aLength)
{
lSum += gNthPrimes[i];
++i;
}

return lSum;
}

int main (int argc, char *argv[])
{
Counter lOne = 1, lMinimumSum, lNewMinimumSum;
int i = 0, j = 0;
uint64_t t0, t1, t;
mach_timebase_info_data_t info;
double nano, seconds;

// precalculate prime numbers up to MAX_NUMBER
printf("Precalculating...\n");
t0 = mach_absolute_time();
buildPrimesErastothenes();
t1 = mach_absolute_time();
t = t1 - t0;

mach_timebase_info(&info);
nano = 1e-9 * ( (double) info.numer) / ((double) info.denom);
seconds = (double)t * nano;

std::cout << "Took " << seconds << " seconds" << std::endl;

// initialize the size of each string
gSumLengths[0] = 11;
gSumLengths[1] = 83;
gSumLengths[2] = 183;
gSumLengths[3] = 631;
gSumLengths[4] = 1037;

t0 = mach_absolute_time();
// initialize the sums and starting offsets of all strings of consecutive primes
for (i = 0; i < NUM_STRINGS; ++i)
{
gSumIndices[i] = 0;
gSumTotals[i] = sumConsecutivePrimes(gSumIndices[i], gSumLengths[i]);
}

// calculate the initial "smallest sum possible"
lMinimumSum = gSumTotals[NUM_STRINGS-1];

// while the sums are not simultaneously equal and a prime number...
while ((j != 0) || (!gIsPrime[gSumTotals[NUM_STRINGS-1]]))
{
i = j = 0;
for (i = 0; i < NUM_STRINGS; ++i)
{
// keep the "smallest sum possible"
lNewMinimumSum = lMinimumSum;

// the sum of the string is too small?
if (gSumTotals[i] < lMinimumSum)
{
// remove the leftmost element of the sum
gSumTotals[i] -= gNthPrimes[gSumIndices[i]];
// shift the string to the right
++gSumIndices[i];
// add the new rightmost element to the sum
gSumTotals[i] += gNthPrimes[gSumIndices[i] + gSumLengths[i] - lOne];
// a mismatch was found...
++j;
}
else
// the sum of the string overflowed?
if (gSumTotals[i] > lMinimumSum)
{
// find the minimum "smallest sum possible" of the current strings
if (lNewMinimumSum == lMinimumSum)
{
lNewMinimumSum = gSumTotals[i];
}
else
if (gSumTotals[i] < lNewMinimumSum)
{
lNewMinimumSum = gSumTotals[i];
}

// a mismatch was found...
++j;
}

// update the "smallest sum possible"...
lMinimumSum = lNewMinimumSum;
}
}
t1 = mach_absolute_time();
t = t1 - t0;

// print the result!
std::cout << "Result: " << gSumTotals[NUM_STRINGS-1] << std::endl;

mach_timebase_info(&info);
nano = 1e-9 * ( (double) info.numer) / ((double) info.denom);
seconds = (double)t * nano;

std::cout << "Took " << seconds << " seconds" << std::endl;

exit(0);
}

6/01/2008

Google Treasure Hunt 2008, 3rd Puzzle

The 3rd puzzle was announced today.
I don't know why but I have the feeling I liked the first problem the most. I suppose the correct labelling for each puzzle type would be:


  • Robot Maze: computer-science

  • Product of sums: low-level UNIX trivia

  • Routing table: networking


What will be the 4th and last puzzle about? Maybe a mix of all the three topics?

Quoting the last post at Google Blog:
The fourth and final puzzle will be released at 1212448500

And after solving the 3rd problem:

Your answer was correct! Congratulations, you're part-way there.
There will more questions over the coming weeks, and the first person to answer them all correctly will win a prize, so keep trying!


If I am not mistaken, the number 1212448500 points to June 3, 2008 at 00:15:00 (like... tomorrow ???)
Update: The time is expressed as GMT+1, equivalent to 23:15:00 GMT+0.

I feel a bit sorry for getting to know about this contest only one month after it was launched - since I'm not used to reading the Official Google Blog - so it's already too late for me to think about prizes... but I feel like it was kind of fun to solve such problems :)

Like the first two problems, I'll be posting the solution to the third, although I believe you won't need much help solving it by yourself:

Third Problem

A "pseudo-algorithm" for the mechanism which describes the path taken by a network packet from a known node (call it S - source) to another node (call it D - destination) should be:

  • 1- Start at node S

  • 2- First, add the current network node to the path. If D is the current network node the algorithm outputs the path and ends since the packet was just delivered to D. Otherwise advance to the next step.

  • 3- Iterate each routing table entry:

  • 4- D matches the Nth entry's network? Set the current node as the Nth entry's target gateway and Jump to step 2

  • 5- D does *not* match any of the routing table entries? Set the current node as the current default gateway and Jump to step 2



Update:
Just for those who might be wondering how to calculate network addresses using netmasks (/24 etc.), I used ipcalc.