Solving a puzzle with constraint programming

Constraint programming can get some getting used to. In the usual programming frame of mind (whether with functional or imperative languages) you think of the algorithm and specify to the computer, via your code, exactly what steps to go through in order to solve the problem.

With constraint programming, you don’t tell the computer what to do. You describe in detail the nature of the problem and the computer does the rest.

Einstein’s riddle is usually given as an example to be solved with constraint programming, but to be different, I’ll show something a bit trickier. This is the problem (it’s named “Meeting the Challenge”):


Eight married couples meet to lend one another some books. Couples have the same surname, employment and car. Each couple has a favourite colour. Furthermore we know the following facts:

1. Daniella Black and her husband work as Shop-Assistants.
2. The book “The Seadog” was brought by a couple who drive a Fiat and love the colour red.
3. Owen and his wife Victoria like the colour brown.
4. Stan Horricks and his wife Hannah like the colour white.
5. Jenny Smith and her husband work as Warehouse Managers and they drive a Wartburg.
6. Monica and her husband Alexander borrowed the book “Grandfather Joseph”.
7. Mathew and his wife like the colour pink and brought the book “Mulatka Gabriela”.
8. Irene and her husband Oto work as Accountants.
9. The book “We Were Five” was borrowed by a couple driving a Trabant.
10. The Cermaks are both Ticket-Collectors who brought the book “Shed Stoat”.
11. Mr and Mrs Kuril are both Doctors who borrowed the book “Slovacko Judge”.
12. Paul and his wife like the colour green.
13. Veronica Dvorak and her husband like the colour blue.
14. Rick and his wife brought the book “Slovacko Judge” and they drive a Ziguli.
15. One couple brought the book “Dame Commissar” and borrowed the book “Mulatka Gabriela”.
16. The couple who drive a Dacia, love the colour violet.
17. The couple who work as Teachers borrowed the book “Dame Commissar”.
18. The couple who work as Agriculturalists drive a Moskvic.
19. Pamela and her husband drive a Renault and brought the book “Grandfather Joseph”.
20. Pamela and her husband borrowed the book that Mr and Mrs Zajac brought.
21. Robert and his wife like the colour yellow and borrowed the book “The Modern Comedy”.
22. Mr and Mrs Swain work as Shoppers.
23. “The Modern Comedy” was brought by a couple driving a Skoda.

Who likes Violet? And can you find out everything about everyone from this?


A constraint programming solution, using Choco is given below. This should give you some insight into the nature of this type of problem solving.

import static choco.Choco.*;
import choco.cp.model.CPModel;
import choco.cp.solver.CPSolver;
import choco.kernel.model.variables.integer.*;
import choco.kernel.solver.variables.integer.IntDomainVar;
import java.util.HashMap;

public class Meeting
{
    public static void main(String[] args)
    {
        int nElements = 8;

        String[] _attr = { "SURNAME", "EMPLOYMENT", "CAR", "COLOR", "MAN", "WIFE", "LENT", "BORROWED" };
        int SURNAME = 0; int EMPLOYMENT = 1; int CAR = 2; int COLOR = 3;
        int MAN  = 4; int WIFE = 5; int LENT = 6; int BORROWED = 7;

        String[] Surname = { "Black", "Horricks", "Smith", "Cermaks", "Kuril", "Dvorak", "Swain", "Zajac" };
        int BLACK = 0; int HORRICKS = 1; int SMITH = 2; int CERMAKS = 3; int KURIL = 4;
        int DVORAK = 5; int SWAIN = 6; int ZAJAC = 7;
 
        String[] Employment = { "Shop-Assistants", "Warehouse Managers", "Accountants", "Ticket-Collectors",
                                "Doctors", "Teachers", "Agriculturalists", "Shoppers" };
        int SHOP_ASSISTANTS = 0; int WAREHOUSE_MANAGERS = 1; int ACCOUNTANTS = 2;
        int TICKET_COLLECTORS = 3; int DOCTORS = 4; int TEACHERS = 5; int AGRICULTURALISTS = 6;
        int SHOPPERS = 7;
        
        String[] Car = { "Fiat", "Wartburg", "Trabant", "Ziguli", "Dacia", "Moskvic", "Renault", "Skoda" };
        int FIAT = 0; int WARTBURG = 1; int TRABANT = 2; int ZIGULI = 3; int DACIA = 4;
        int MOSKVIC = 5; int RENAULT = 6; int SKODA = 7;
        
        String[] Color = { "red", "brown", "white", "pink", "green", "blue", "violet", "yellow" };
        int RED = 0; int BROWN = 1; int WHITE = 2; int PINK = 3; int GREEN = 4;
        int BLUE = 5; int VIOLET = 6; int YELLOW = 7;
        
        String Man[] = { "Owen", "Stan", "Alexander", "Mathew", "Oto", "Paul", "Rick", "Robert"  };
        int OWEN = 0; int STAN = 1; int ALEXANDER = 2; int MATHEW = 3; int OTO  = 4;
        int PAUL = 5; int RICK = 6; int ROBERT = 7;
        
        String[] Wife     = { "Daniella", "Victoria", "Hannah", "Jenny", "Monica", "Irene", "Veronica", "Pamela" };
        int DANIELLA = 0; int VICTORIA = 1; int HANNAH = 2; int JENNY = 3; int MONICA  = 4;
        int IRENE = 5; int VERONICA = 6; int PAMELA = 7;

        String[] Books = { "The Seadog", "Mulatka Gabriela", "Shed Stoat", "Slovacko Judge", "Dame Commissar",
                          "Grandfather Joseph", "The Modern Comedy", "We Were Five" };
        int THE_SEADOG = 0; int MULATKA_GABRIELA = 1; int SHED_STOAT = 2; int SLOVACKO_JUDGE = 3;
        int DAME_COMMISSAR = 4; int GRANDFATHER_JOSEPH = 5; int THE_MODERN_COMEDY = 6;
        int WE_WERE_FIVE = 7;        
        
        String attvals[][] = { Surname, Employment, Car, Color, Man, Wife, Books, Books };
        
        CPModel model = new choco.cp.model.CPModel();

        // We'll assume the couples are numbered 0 to 7.
        // The value of the variable represents the couple belongs to,
        // i.e if x[SURNAME][BLACK] is 6 then couple with surname Black is couple number 6).
        
        IntegerVariable[][] x = new IntegerVariable[nElements][nElements];
        for (int i=0; i<nElements; i++)
        {
            x[i] = choco.Choco.makeIntVarArray( _attr[i], nElements, 0, nElements-1);
            // For a given attribute, Each different attribute value belongs to a
            // different couple number.
            model.addConstraint(allDifferent( x[i] ));
        }

        //1.  Daniella Black and her husband work as Shop-Assistants.
        model.addConstraint( eq( x[SURNAME][BLACK],
                                 x[EMPLOYMENT][SHOP_ASSISTANTS] ));

        model.addConstraint( eq( x[WIFE][DANIELLA],
                                 x[EMPLOYMENT][SHOP_ASSISTANTS] ));

        //2.  The book "The Seadog" was brought by a couple who drive a Fiat and love the color red.
        model.addConstraint( eq( x[LENT][THE_SEADOG],
                                 x[CAR][FIAT] ));

        model.addConstraint( eq( x[LENT][THE_SEADOG],
                                 x[COLOR][RED] ));
        
        //3.  Owen and his wife Victoria like the color brown.
        model.addConstraint( eq( x[MAN][OWEN],
                                 x[WIFE][VICTORIA] ));

        model.addConstraint( eq( x[MAN][OWEN],
                                 x[COLOR][BROWN] ));

        //4.  Stan Horricks and his wife Hannah like the color white.
        model.addConstraint( eq( x[MAN][STAN],
                                 x[WIFE][HANNAH] ));
        
        model.addConstraint( eq( x[MAN][STAN],
                                 x[COLOR][WHITE] ));

        //5.  Jenny Smith and her husband work as Warehouse Managers and they drive a Wartburg.
        model.addConstraint( eq( x[WIFE][JENNY],
                                 x[SURNAME][SMITH] ));

        model.addConstraint( eq( x[WIFE][JENNY],
                                 x[EMPLOYMENT][WAREHOUSE_MANAGERS] ));

        model.addConstraint( eq( x[WIFE][JENNY],
                                 x[CAR][WARTBURG] ));

        //6.  Monica and her husband Alexander borrowed the book "Grandfather Joseph".
        model.addConstraint( eq( x[WIFE][MONICA],
                                 x[MAN][ALEXANDER] ));

        model.addConstraint( eq( x[WIFE][MONICA],
                                 x[BORROWED][GRANDFATHER_JOSEPH] ));

        //7.  Mathew and his wife like the color pink and brought the book "Mulatka Gabriela".
        model.addConstraint( eq( x[MAN][MATHEW],
                                 x[COLOR][PINK] ));

        model.addConstraint( eq( x[MAN][MATHEW],
                                 x[LENT][MULATKA_GABRIELA] ));

        //8.  Irene and her husband Oto work as Accountants.
        model.addConstraint( eq( x[MAN][OTO],
                                 x[WIFE][IRENE] ));
        
        model.addConstraint( eq( x[MAN][OTO],
                                 x[EMPLOYMENT][ACCOUNTANTS] ));

        //9.  The book "We Were Five" was borrowed by a couple driving a Trabant.
        model.addConstraint( eq( x[BORROWED][WE_WERE_FIVE],
                                 x[CAR][TRABANT] ));

        //10. The Cermaks are both Ticket-Collectors who brought the book "Shed Stoat".
        model.addConstraint( eq( x[SURNAME][CERMAKS],
                                 x[EMPLOYMENT][TICKET_COLLECTORS] ));
  
        model.addConstraint( eq( x[SURNAME][CERMAKS],
                                 x[LENT][SHED_STOAT] ));

        //11. Mr and Mrs Kuril are both Doctors who borrowed the book "Slovacko Judge".
        model.addConstraint( eq( x[SURNAME][KURIL],
                                 x[EMPLOYMENT][DOCTORS] ));

        model.addConstraint( eq( x[SURNAME][KURIL],
                                 x[BORROWED][SLOVACKO_JUDGE] ));

        //12. Paul and his wife like the color green.
        model.addConstraint( eq( x[MAN][PAUL],
                                 x[COLOR][GREEN] ));

        //13. Veronica Dvorak and her husband like the color blue.
        model.addConstraint( eq( x[SURNAME][DVORAK],
                                 x[WIFE][VERONICA] ));

        model.addConstraint( eq( x[SURNAME][DVORAK],
                                 x[COLOR][BLUE] ));

        //14. Rick and his wife brought the book "Slovacko Judge" and they drive a Ziguli.
        model.addConstraint( eq( x[MAN][RICK],
                                 x[WIFE][VERONICA] ));

        model.addConstraint( eq( x[MAN][RICK],
                                 x[LENT][SLOVACKO_JUDGE] ));

        model.addConstraint( eq( x[MAN][RICK],
                                 x[CAR][ZIGULI] ));

        //15. One couple brought the book "Dame Commissar" and borrowed the book "Mulatka Gabriela".
        model.addConstraint( eq( x[LENT][DAME_COMMISSAR],
                                 x[BORROWED][MULATKA_GABRIELA] ));

        //16. The couple who drive a Dacia, love the color violet.
        model.addConstraint( eq( x[CAR][DACIA],
                                 x[COLOR][VIOLET] ));

        //17. The couple who work as Teachers borrowed the book "Dame Commissar".
        model.addConstraint( eq( x[EMPLOYMENT][TEACHERS],
                                 x[BORROWED][DAME_COMMISSAR] ));
        
        //18. The couple who work as Agriculturalists drive a Moskvic.
        model.addConstraint( eq( x[EMPLOYMENT][AGRICULTURALISTS],
                                 x[CAR][MOSKVIC] ));

        //19. Pamela and her husband drive a Renault and brought the book "Grandfather Joseph".
        model.addConstraint( eq( x[WIFE][PAMELA],
                                 x[CAR][RENAULT] ));

        model.addConstraint( eq( x[WIFE][PAMELA],
                                 x[LENT][GRANDFATHER_JOSEPH] ));

        //20. Pamela and her husband borrowed the book that Mr and Mrs Zajac brought.
        for (int book = 0; book<nElements; book++)
            model.addConstraint( ifOnlyIf( eq( x[WIFE][PAMELA],
                                               x[BORROWED][book] ),
                                           eq( x[SURNAME][ZAJAC],
                                               x[LENT][book])));
        
        //21. Robert and his wife like the color yellow and borrowed the book "The Modern Comedy".
        model.addConstraint( eq( x[MAN][ROBERT],
                                 x[COLOR][YELLOW] ));

        model.addConstraint( eq( x[MAN][ROBERT],
                                 x[BORROWED][THE_MODERN_COMEDY] ));
    
        //22. Mr and Mrs Swain work as Shoppers.
        model.addConstraint( eq( x[SURNAME][SWAIN],
                                 x[EMPLOYMENT][SHOPPERS] ));

        //23. "The Modern Comedy" was brought by a couple driving a Skoda.        
        model.addConstraint( eq( x[LENT][THE_MODERN_COMEDY],
                                 x[CAR][SKODA] ));

        // Create the solver
        CPSolver solver = new CPSolver();
        solver.read( model );

        // solver.solve();
        solver.solveAll();

        if (!solver.isFeasible())
            return;
        
        int colWidth[] = calcAttrWidths(_attr, attvals);

        do 
        {
            IntDomainVar[][]  s = new IntDomainVar[nElements][nElements];
            HashMap<Integer, String[]> couples = new HashMap<Integer, String[]>();

            System.out.print( "         ");
            for (int i=0; i<nElements; i++)
            {
                s[i] = solver.getVar( x[i] );
                couples.put( i, new String[ nElements ] );
                System.out.print( padRight( _attr[i], colWidth[i]) );
            }
            System.out.println();
            
            for (int i=0; i<nElements; i++) // iterate over attributes
                for (int j=0; j<nElements; j++)  // iterate over attribute values
                {
                    //  s[i][j].getVal() is the couple number where attribute i
                    //              has an attribute value of j
                    
                    int coupleNumber = s[i][j].getVal();
                    String[] attrs = couples.get( coupleNumber );
                    attrs[i] =  attvals[i][j];
                }

            
            for (int couple=0; couple<nElements; couple++)
            {
                System.out.print( "couple " + (couple+1) + ":" );
                String[] attrs = couples.get( couple );
                for (int attr=0; attr<nElements; attr++)
                    System.out.print( padRight( attrs[ attr ], colWidth[ attr ] ) );
                System.out.println();
            }
            System.out.println("---------------------");
            solver.printRuntimeStatistics();
        }
        while (solver.nextSolution() == Boolean.TRUE);
    }
    
    public static String padRight(String s, int n)
    {
         return String.format("%1$-" + n + "s", s);  
    }
    
    public static int[] calcAttrWidths(  String[] attrs, String[][] attvals )
    {
        int nElements = attrs.length;
        int[] atmax = new int[ nElements ];
        for (int i=0; i<nElements; i++)
            atmax[i] = attrs[i].length()+1;

        for (int i=0; i<nElements; i++)
        {
            int max = atmax[i];
            for (int j=0; j<nElements; j++)
            {
                int lenVal = attvals[i][j].length();
                if ( max < lenVal )
                    max = lenVal;
            }
            atmax[i] = max + 1;
        }
        return atmax;
    }

}

Constraint Programming

Constraint programming is a field that is about solving problems where you have to find a solution in a (usually large) search space given specific constraints. A classic problem of this sort is the eight queens puzzle.

There are quite a few good constraint program libraries, among them are java based Choco and C++ based Gecode.

At first I didn’t understand why such powerful libraries provide the eight queen puzzle as an example that can be solved using constraint programming, as it is trivial to generate all the solutions to the eight queens puzzle with simple DFS. I wrote the following C program to illustrate this (which actually shows all the solutions to the n queen problem using Depth First Search):

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    int *lines;
    int s,i, currentLine;


    if ( argc != 2 ) {
        printf( "Usage: nqueens <board-size>n" );
        return -1;
    }

    s = atoi( argv[1] );

    if ( s < 1 ) {
        printf( "Board size must be a positive number.n" );
        return -1;
    }

    lines = (int*) malloc( s * sizeof( int ) );

    for ( i=0; i < s; i++ ) {
        lines[ i ] = 0;
    }
    currentLine = 0;

    // begin the DFS
    while ( currentLine > -1 ) {
        while ( lines[ currentLine ]<s && !safe(currentLine, lines) )
            lines[ currentLine ]++;

        if ( lines[ currentLine ] == s ) {
            lines[ currentLine ] = 0;
            currentLine--;
            if ( currentLine > -1 )
                lines[currentLine]++;
            continue;
        }

        if (currentLine == s-1) {
            for (i=0; i<s; i++)
                printf( " %d", lines[ i ] );
            printf("n");
            lines[ currentLine ]++;
            continue;
        }

        currentLine++;
    }

    free( lines );
}

int safe( int currentLine, int* lines ) {
    int i;

    for ( i = currentLine-1; i > -1; i-- ) {
        if ( lines[ currentLine ] == lines[ i ] ||
                abs( lines[currentLine]-lines[i]) == (currentLine-i) )
        {
            return 0;
        }
    }

    return 1;
}

However, when the number of queens grows, the time it takes for the naive DFS method above grows much faster, and getting all the solutions for 30 queens and higher required waiting more time than I had patience for.

I then tested what Choco and Gecode could do with the same problem and was amazed. Both libraries generated results in seconds for 300 queens and higher. Note that each added queen exponentially expands the search space so this is very impressive.

Combining Qt and OpenCV

Before writing a minimal sample for some technology, I usually take the time to see if there already exist one on the net. For a simple example that illustrates how to combine Qt and OpenCV I found the following post. Just download the project at the end of that post.

This post explains compiling the sample code using Qt Creator.

Mac OS/X

In previous posts, I’ve mentioned how to install Qt and OpenCV on the OS/X by manually downloading and building them, however, the shortest route to get the above sample to compile and run on the Mac is to install Qt and OpenCV as follows:

brew install opencv
brew install qt

if you get errors during one of these installations, look at the message – its usually solvable by adding write permissions to the folder mentioned in the message. Note that its best that you uninstall any previous versions of Qt and OpenCV prior to doing that.

The ShowImage sample also requires pkg-config which is not installed by default. For that simply

brew install pkg-config

Again the above works great and saves you manually installing all the dependencies of pkg-config.

At this point, launch Qt Creator, and open the project ShowImage.pro
When you build the project you could get the following error during the build:

sh: pkg-config: command not found

At first I thought it was strange since invoking pkg-config from the command line worked, so it was definitely in the search path (which was confirmed by invoking which pkg-config from the command line). After some searching I realized that Qt Creator does not use the shell path to look for pkg-config. In order to let Qt Creator know where to find pkg-config you should explicitly add the path to the build environment by clicking the Projects icon on the left and adding the path the pkg-config in the Build Environment details (see below).

Qt Creator Build Envoronment
Qt Creator Build Environment

On Ubuntu

Loading and compiling the ShowImage.pro in Ubuntu had it’s own problems. Compilation failed with an error of

bits/predefs.h: No such file or directory

which was somewhere along the include tree required by Qt4.

I found the answer to this here and a sudo apt-get install gcc-multilib solved that compilation issue. This seemed strange since my ubuntu is a 32-bit installation and this solution was to install 32-bit headers on a 64-bit system – but for the time being I let that slide. However this left me with this new hurdle:

moc_mainwindow.cpp:14:2: error: #error "This file was generated using the moc from 4.7.3. It"
moc_mainwindow.cpp:15:2: error: #error "cannot be used with the include files from this version of Qt."
moc_mainwindow.cpp:16:2: error: #error "(The moc has changed too much.)"

A solution for this was explained by Anjum Kaiser here and indeed a

make distclean
qmake
make

from the command line resulted in an executable that worked.

However I wanted to make sure I can build a working executable from Qt Creator and attempting to build the project from Qt Creator after make distclean from the command line, returned the following error:

libopencv_calib3d.so: could not read symbols: File in wrong format

This got me thinking about the 32-bit/64-bit issue and it dawned on my that Qt Creator might not be building the project the same way it is built from the command line. A quick look in the Qt Creator projects configuration showed that indeed g++64 was specified instead of g++32. Fixing this (below) enabled smooth compilation.

Qt Config configure g++32 on Ubuntu
Qt Config configure g++32 on Ubuntu

However – when attempting to run the app – yet another surprise:

error while loading shared libraries: libopencv_highgui.so.2.4: 
cannot open shared object file: No such file or directory

a locate libopencv_highgui.so (remember to sudo updatedb first) showed that the library exists at /usr/lib but the loader doesn’t know about it. The next step was then sudo vi /etc/ld.so.conf, adding /usr/lib to the end of the file and finally sudo ldconfig.

This, finally, did the trick and the app could be successfully compiled and launched from within Qt Creator on Ubuntu 12.04

Installing OpenCV

OpenCV is considered by many to be the best open source computer vision library. It has versions for Windows, Linux, Mac, iOS and Android. As Windows installation is usually easier, I’ll focus on Linux/Mac.

OpenCV uses cmake (Cross Platform Make) to configure and build the library. You can download cmake for the relevant platforms here (unless you’re interested in compiling it, I suggest downloading the binary distribution).

Once cmake is installed (make sure its in the path by running cmake from the command line), download the OpenCV sources for Linux/Mac (a tar’ed bz2 archive) and extract them to a directory. Next, cd to that directory and issue:

cmake .
make
sudo make install

if you need to uninstall for any reason just issue sudo make uninstall from the same directory.

On OS/X a simpler (and possibly better option) is brew install opencv (brew), which will automate all the above.

Qt learning curve journal, part II

Being able to make and run the Qt samples is cool, but to really dig into learning a framework I prefer to have the ability to easily navigate to declarations, easily debug, auto completion, in short – an IDE.

There are two options that I recommend. The first is QtCreator – the IDE that comes with Qt. Although the site claims that “Qt Creator IDE can also be downloaded as a standalone application, although we recommend to get it via the SDK above if you need a complete Qt development environment”, I haven’t managed to find in in the SDK bundle. However you can download binary and source versions from here.

The second option is NetBeans which the cross platform IDE I’ve liked the most since I first tried it in back in 2003. I checked if it has built-in support for Qt. It does.

For developing Qt applications you need only download the smaller sized NetBeans for C++ from this page. You can easily create, compile and run a Qt project from NetBeans by following the explanation on this page.

Having done this, you have access to all the NetBeans goodies when developing your Qt application.

I’m sure Qt will work well with eclipse and other frameworks, though I haven’t checked and therefore can’t comment on them.

Qt learning curve journal, part I

The goal – to create a cross platform application infrastructure for Linux, Windows and Mac that will serve as the basis for future cross platform application.

I first thought of using wxwidgets but noticed that there were problems getting it to compile on Mountain Lion OS/X. In addition, Qt seemed more equipped to handle to sort of functionality and support I require in the projects that will be developed. Although Nokia recently sold Qt to Digia, my assumption is that it will continue to be developed and supported by a wide community of developers.

In addition, a secondary goal is to evaluate Necessitas, the Qt port for the Android platform and check work in process for iOS and Windows Phone.

I’ll first focus on the process for Linux (tested on Ubuntu 12.04) and OS/X (tested on Mountain Lion).

Installation

Linux
First thing’s first – download the Qt libraries for Linux/X11, extract, cd to the folder and ./configure. You will be asked if you want to use the open source or commercial license version (since the open source license is LGPL, I assume choosing this option creates a shared library). after some additional questions, the configure process will begin to create the make file (its a big project so give it time). Finally, if all goes well you should see:

Qt is now configured for building. Just run 'make'.
Once everything is built, you must run 'make install'.
Qt will be installed into /usr/local/Trolltech/Qt-4.8.3

To reconfigure, run 'make confclean' and 'configure'.

Expect make to take a very long while (as in take a long lunch break). This is a huge project.

OS/X
From the location specified above, you can either download the two dmg files (library and debug) or download the same file as for Linux if you wish to go through the compilation process. In the latter case, there are some changes in the compilation method that are specified here. I opted for the easier method of simply downloading and installing the dmg files.

Another (and perhaps better) option on OS/X is to install homebrew and simply issue an

brew install qt

Compiling and running an example

Linux
On Linux the tutorial sample is located at qt-everywhere-opensource-src-4.8.3/examples/tutorials/gettingStarted/gsQt/part1 (under the directory you extracted it to).

To make the sample, issue:

qmake -project
qmake
make

OS/X
On OS/X the tutorial sample is located at /Developer/Examples/Qt/tutorials/gettingStarted/gsQt/part1
To make the sample, issue:

qmake -spec macx-g++
qmake
make

On my Mac, the make resulted in the following error:

g++: error: x86_64: No such file or directory
g++: error: unrecognized option '-arch'
g++: error: unrecognized option '-Xarch_x86_64'
make: *** [main.o] Error 1

if you get compilation errors during make, your compilers could be different from the standard versions for your Xcode. If you have Xcode 4.3 or newer, you should install the Command Line Tools for Xcode from within Xcode’s Download preferences (via menu: Xcode->Preferences…).

I learned the above from homebrew (which by the way is a great package manager for OS/X – bye bye fink and macports) after installing it and running homebrew doctor. Once I installed the command line tools for Xcode the make completed smoothly.

Recursively remove specific filename in Linux

The trick is to use the find command with the -exec or -execdir parameter. I needed to remove all the files named serials_dev.db3 from multiple backup directories. The following did the job:

find . -type f -name "serials_dev.db3" -exec rm -f {} ;

Here are the relevant parts from the find man page:

       -exec command ;
              Execute command; true if 0 status is returned.  All following
              arguments to find are taken to be arguments  to  the  command
              until  an  argument  consisting  of  `;' is encountered.  The
              string `{}' is replaced by the current file name  being  pro‐
              cessed  everywhere it occurs in the arguments to the command,
              not just in arguments where it is alone, as in some  versions
              of  find.   Both  of  these  constructions  might  need to be
              escaped (with a `') or quoted to protect them from expansion
              by  the  shell.  See the EXAMPLES section for examples of the
              use of the -exec option.  The specified command is  run  once
              for each matched file.  The command is executed in the start‐
              ing directory.   There are unavoidable security problems sur‐
              rounding use of the -exec action; you should use the -execdir
              option instead.

       -exec command {} +
              This variant of the -exec action runs the  specified  command
              on  the  selected  files,  but  the  command line is built by
              appending each selected file name at the end; the total  num‐
              ber  of invocations of the command will be much less than the
              number of matched files.  The command line is built  in  much
              the  same  way that xargs builds its command lines.  Only one
              instance of `{}' is allowed within the command.  The  command
              is executed in the starting directory.

       -execdir command ;

       -execdir command {} +
              Like  -exec, but the specified command is run from the subdi‐
              rectory containing the matched file, which  is  not  normally
              the  directory  in  which you started find.  This a much more
              secure method for invoking commands, as it avoids race condi‐
              tions  during  resolution  of the paths to the matched files.
              As with the -exec action, the `+' form of -execdir will build
              a command line to process more than one matched file, but any
              given invocation of command will only list files  that  exist
              in  the  same subdirectory.  If you use this option, you must
              ensure that your $PATH environment variable does  not  refer‐
              ence  `.';  otherwise,  an attacker can run any commands they
              like by leaving an appropriately-named file in a directory in
              which  you  will  run  -execdir.   The same applies to having
              entries in $PATH which are empty or which  are  not  absolute
              directory names.

A collection of older information

This is the previous content of the nocurve.com site, where the idea was to store information that will assist in saving precious time when trying to develop something or fix something.

Geany

This is the home page

One crazy issue I had on Windows was that for some reason at some point the Geany window disappeared. The task was active, clicking the icon would bring it to focus but would not show the Window. It was obviously hidden or thrown out of the desktop view. I assumed the window saved it’s state with some insane coordinates but couldn’t get it back to show in the desktop.

Finally found the answer here – sure helps when you know some Windows basic techniques…

“I have installed Geany 0.19.1 on Windows 7, I run the Geany.exe shortcut and it appears running on my windows taskbar, if I hit Alt+Tab I see the Geany icon. But… no window is shown. Where is the Geany window? How to fix it?”

“Press Alt-Space, then M, then the arrow keys to move the window into view.” (you can also use the mouse instead of the arrow keys to speed up the process)

DIV Charts

Attachment “jsdivcharts.jpeg” not found
Free (LGPL) DIV based JavaScript Charts. This provides to main advantages to other JavaScript charting libraries:

  • It uses DIVs instead of Canvas or VML, which means it will work virtually on any browser (including the Android native Web browser which as of this writing does not support these technologies).
  • It is really simple to use. The charting library does all the thinking for you 🙂
  • Currently supported: Stacked Bar Charts, Bar charts (Which is just a Stacked Bar Chart with one group) Compound charts (stacked bars and lines), tooltips, Pie Charts, automatic Y axis step calculation, default color support

This charting library builds upon the amazing javascript wz_graphics library created by Walter Zorn. Unfortunately, I only recently learned that Walter Zorn passed away in May 2009. May this little contribution be a tribute to his work.

To view a demo of the DIVCharts library and download it, just go here

Change Google Chrome’s default language on Mac

To change the Google Chrome application language to English on Mac OS/X, open a terminal window and at the command prompt type the following.

defaults write com.google.Chrome AppleLanguages '(en-US)'

The next time you’ll open Chrome it will be in English (actually, its recommended to close Chrome before doing this).

Long Path to Short 8.3 MS-DOS path conversion

Every once in a (long) while I require this. Being surprised by the lack of such a simple utility I quickly made one for public use. You can download the VS2008 C++ project and source code from here. If you just want the executable, you can get it here (just drag the file in the long path to the upper field and click the OK button to get the short path inthe lower field.

Access MSSQL from PHP

On Ubuntu

First, install the LAMP (Linux,Apache,MySQL,PHP) package as follows:

$sudo apt-get install lamp-server^

Note that the ‘^’ at the end is not a typo !

Next, install MSSQL support for PHP (taken from here)

$sudo apt-get install php5-sybase
$sudo /etc/init.d/apache2 restart

On Windows

First install one of the available WAMP (Windows,Apache,MySQL,PHP) packages (I use this)

Next, download and install Microsoft’s PHP extension for MSSQL (from here)

The above setup contains quite a few candidates to be the PHP extension. Make sure you copy the relevant extension dll (in my case it was php_pdo_sqlsrv_53_ts_vc6.dll ) from Microsoft’s setup to the php extensions folder (in my case it is located at c:wampbinphpphp5.3.0ext ) and use either php.ini or the wampserver UI to add it to the list of extension dll’s PHP loads at startup.

Connecting to the MSSQL database

After you’ve done the above, you can now connect to the MSSQL server. The following code will work on both Ubuntu and Windows:

$serverName = "mymssqlserver.com"; 
$database   = "mydbname";
$uid        = "username";
$pwd        = "password";

try
{
    if ( stripos(php_uname(), "linux") === false )
    {
        $g_conn = new PDO( "sqlsrv:server=$serverName;Database=$database", $uid, $pwd);
    }
    else
    {
        $g_conn = new PDO( "dblib:host=$serverName;dbname=$database", $uid, $pwd);
    }
    
    $g_conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); 
}
catch( PDOException $e )
{
    die( "Error connecting to SQL Server" ); 
}

// You can now use $g_conn to execute pdo queries.

Simultaneous VPN and Internet Access on Ubuntu

This might be already solved in newer (>11.04) versions of Ubuntu.

The following assumes you installed a VPN connection in Ubuntu, but when you connect to the VPN you can’t access the public Internet. It took me some time until I found an answer that worked here:

“First, I determined what ip address ranges were being used on the VPN, in my case 192.168.32.* and 192.168.16.*. Then I connected to my vpn normally and sshed to a server on the network. I ran route on that machine and got the gateway address and metric being used. Then I added routes for the two ip address ranges to the routes field in the IPv4 settings tab and clicked on “Use this connection only for resources on its network” and “Ignore automatically obtained routes”. Then poof like magic it worked.”