Trying F#

March 18th, 2013

As part of my ongoing interest in functional programming languages, I have decided to try F#. I have been looking at the Try F# page:

http://www.tryfsharp.org/

This provides an online REPL environment for exploring the language. I have a number of students at school who are exploring JavaScript and Python as first languages through Code Academy. I thought it would be a useful experiment to try this sort of educational activity with an unfamiliar language myself.

At first glance, I quite like the learning experience of reading through explanations and running some code, although it’s not as much fun as trying to make something yourself. In order to consolidate my learning, I tried to solve the first of the problems in Project Euler, which is to find the sum of the natural numbers less than 1000 that are multiples of 3 or 4. (I have already done this in Haskell).

I came up with this:

[0..999]
|> List.filter (fun x -> x % 3 = 0 || x % 5 = 0)
|> List.sum

One liner to show logs without Rotated Backup files

May 25th, 2012

I’ve been looking at the Apache log files on a web server this morning. There are many virtual hosts on the machine and the log rotation scripts have created many numbered backup files of the logs. To make the directory listing more readable, I have been using the following one-liner:

ls -l /var/log/apache2 | grep -Ev -e '[[:digit:]]+(\.gz)?$'

This will only display the current log files, assuming that /var/log/apache2 is the directory in which you store your Apache logs and that you do not store any other files there.

I hope it helps.

Decimal to Binary

April 13th, 2012

In order to prepare for teaching computing, I’ve been reading Introduction to Computing by David Evans.

In the first chapter there is an excellent explanation of binary numbers using binary search trees. You can build a bitstring for the binary representation of a number by starting at the root (highest node on the tree) and comparing the number to the midpoints of a range of numbers that you are searching. If you answer a question with “yes” append “1″ to your bitstring, otherwise append “0″.

The number 6 would be “Yes”, “Yes”, “No” or 110.

I decided to implement the logic of this binary tree in Java.

private static String decimalToBinary(int input) {
    if (input < 0 || input > 7) {
        throw new IllegalArgumentException();
    }
 
    StringBuilder result = new StringBuilder();
 
    if (input >= 4) {
        result.append('1');
        if (input >= 6) {
            result.append('1');
            if (input == 7) {
                result.append('1');
            } else {
                result.append('0');
            }
        } else {
            result.append('0');
            if (input == 5) {
                result.append('1');
            } else {
                result.append('0');
            }
        }
    } else {
        result.append('0');
        if (input >= 2) {
            result.append('1');
            if (input == 3) {
                result.append('1');
            } else {
                result.append('0');
            }
        } else {
            result.append('0');
            if (input == 1) {
                result.append('1');
            } else {
                result.append('0');
            }
        }
    }
 
    return result.toString();
}

This works for converting decimal numbers to binary strings. I think that writing a program like this might work as an exercise for secondary school students for learning about conditional statements in programming and binary numbers.

However, the range of inputs is severely limited (0 to 7 inclusive). I wrote another method and a recursive helper method that can take arbitrary non-negative decimals in the range of Java ints and return the corresponding binary number:

private static String decimalToBinaryRecursive(int input) {
    if (input < 0) {
        throw new IllegalArgumentException();
    }
 
    if (input == 0) {
        return "0";
    }
 
    if (input == 1) {
        return "1";
    }
 
    // Find how many bits we need.
    int bits = (int)(Math.log(input) / Math.log(2)) + 1;
 
    // Find the greatest number that can be represented with this many bits.
    int max = (int)Math.pow(2, bits);
 
    // We want to know how much to change this value by to search from the mid point.
    int delta = max / -2;
 
    StringBuilder result = new StringBuilder();
 
    return decimalToBinaryRecursiveHelper(input, max, delta, result);
}
 
private static String decimalToBinaryRecursiveHelper(int input, int previousMidpoint, int delta, StringBuilder result) {
    if (delta == 0) {
        return result.toString();
    }
 
    int midpoint = previousMidpoint + delta;
 
    if (input >= midpoint) {
        result.append('1');
        return decimalToBinaryRecursiveHelper(input, midpoint, Math.abs(delta) / 2, result);
    } else {
        result.append('0');
        return decimalToBinaryRecursiveHelper(input, midpoint, Math.abs(delta) / -2, result);
    }
}

The recursive method is considerably more complex and would be much harder for a secondary school student to write. The mathematics might be unfamiliar for most secondary school students, particularly the code to do with logarithms. You could simplify the mathematics of that code with a while loop that compared increasing powers of 2 to the input. It might be a possible extension task for a gifted and talented student. It could also be a task for a lesson on recursive methods.

I can see that teaching computing will present challenges. There are an enormous number of toy programs that we can get students to create in order to learn about programming. However, in order to extend any of these tasks to make them more practical and interesting, it is very easy to set challenges that are rely on outside skills, knowledge and understanding that many secondary school students do not have.

The whole program with a main method for testing looks like this:

package decimaltobinary;
 
/**
 * @author Robert Impey
 */
public class DecimalToBinary {
    public static void main(String[] args) {
        System.out.println("Simple Approach");
        for (int i = 0; i <= 7; i++) {
            System.out.printf("%d\t%s\n", i, decimalToBinary(i));
        }
 
        System.out.println("Recursive Approach");
        int bits = 8;
        for (int i = 0; i <= Math.pow(2, bits) - 1; i++) {
            System.out.printf("%d\t%s\n", i, decimalToBinaryRecursive(i));
        }
    }
 
    private static String decimalToBinary(int input) {
        if (input < 0 || input > 7) {
            throw new IllegalArgumentException();
        }
 
        StringBuilder result = new StringBuilder();
 
        if (input >= 4) {
            result.append('1');
            if (input >= 6) {
                result.append('1');
                if (input == 7) {
                    result.append('1');
                } else {
                    result.append('0');
                }
            } else {
                result.append('0');
                if (input == 5) {
                    result.append('1');
                } else {
                    result.append('0');
                }
            }
        } else {
            result.append('0');
            if (input >= 2) {
                result.append('1');
                if (input == 3) {
                    result.append('1');
                } else {
                    result.append('0');
                }
            } else {
                result.append('0');
                if (input == 1) {
                    result.append('1');
                } else {
                    result.append('0');
                }
            }
        }
 
        return result.toString();
    }
 
    private static String decimalToBinaryRecursive(int input) {
        if (input < 0) {
            throw new IllegalArgumentException();
        }
 
        if (input == 0) {
            return "0";
        }
 
        if (input == 1) {
            return "1";
        }
 
        // Find how many bits we need.
        int bits = (int)(Math.log(input) / Math.log(2)) + 1;
 
        // Find the greatest number that can be represented with this many bits.
        int max = (int)Math.pow(2, bits);
 
        // We want to know how much to change this value by to search from the mid point.
        int delta = max / -2;
 
        StringBuilder result = new StringBuilder();
 
        return decimalToBinaryRecursiveHelper(input, max, delta, result);
    }
 
    private static String decimalToBinaryRecursiveHelper(int input, int previousMidpoint, int delta, StringBuilder result) {
        if (delta == 0) {
            return result.toString();
        }
 
        int midpoint = previousMidpoint + delta;
 
        if (input >= midpoint) {
            result.append('1');
            return decimalToBinaryRecursiveHelper(input, midpoint, Math.abs(delta) / 2, result);
        } else {
            result.append('0');
            return decimalToBinaryRecursiveHelper(input, midpoint, Math.abs(delta) / -2, result);
        }
    }
}

This post contains content that was released with the following license:
http://creativecommons.org/licenses/by-nc-sa/3.0/us/
and is published with the same license.

New Domain for the Blog

February 6th, 2012

This blog will now be hosted at

http://www.reversing-entropy.com/

to reflect the title. Any requests to the old address:

http://impey.info/blog/

will be redirected to the new address.

Project Euler 1

December 11th, 2011

I took a look at the first problem on the Project Euler site earlier this afternoon:

http://projecteuler.net/problem=1

This asks you to find the sum of the natural numbers that are less than 1000 and are multiples of 3 or 5.

I decided that Haskell’s filter function and a lambda would make this problem trivially easy to solve. In GHCi:

Prelude> let sumMultiplesOf3Or5 max = sum(filter(\x -> (mod x 3 == 0) || (mod x 5 == 0))[1 .. max - 1])
Prelude> sumMultiplesOf3Or5 1000
233168

As I played around with other values for max, something unexpected appeared before my eyes. A pattern of repeated digits begins to emerge in the sums of the multiples of 3 and 5 less than 10 to the power of i as i increases.

Prelude> map sumMultiplesOf3Or5 (map (\i -> 10 ^ i) [1..6])
[23,2318,233168,23331668,2333316668,233333166668]

Something similar happens with the sums of the multiples of 3 or 5 less than 20, 200,…,30,300, and so on:

Prelude> map (\j -> map sumMultiplesOf3Or5 (map (\i -> j * 10 ^ i) [1..6])) [1..9]
[[23,2318,233168,23331668,2333316668,233333166668],[78,9168,931668,93316668,9333166668,933331666668],[195,20850,2098500,209985000,20999850000,2099998500000],[368,37268,3732668,373326668,37333266668,3733332666668],[543,57918,5829168,583291668,58332916668,5833329166668],[810,83700,8397000,839970000,83999700000,8399997000000],[1133,114218,11432168,1143321668,114333216668,11433332166668],[1428,148668,14926668,1493266668,149332666668,14933326666668],[1845,188550,18895500,1889955000,188999550000,18899995500000]]

Reformatted:

[[23,2318,233168,23331668,2333316668,233333166668], -- [10,100,1000,10000,100000,1000000]
[78,9168,931668,93316668,9333166668,933331666668], -- [20,200,2000,20000,200000,2000000]
[195,20850,2098500,209985000,20999850000,2099998500000], -- and so on
[368,37268,3732668,373326668,37333266668,3733332666668],
[543,57918,5829168,583291668,58332916668,5833329166668],
[810,83700,8397000,839970000,83999700000,8399997000000],
[1133,114218,11432168,1143321668,114333216668,11433332166668],
[1428,148668,14926668,1493266668,149332666668,14933326666668],
[1845,188550,18895500,1889955000,188999550000,18899995500000]]

I’m not sure if this continues indefinitely. I wonder if similar patterns emerge with numbers in different bases. I’m curious about trying multiples of numbers other than 3 or 5. At this point, I’ve really no idea why this happens, but my curiosity is aroused.

I’m also really impressed with Haskell, a language that I barely know. The only other time I’ve used functional programming seriously is with C# and VB.Net for LINQ, of which I am a huge fan.

GHCN Monthly and MS Access

December 4th, 2011

For some of the last few evenings, I have been learning about MS Access’s data import functionality in order to interrogate the data of the Global Historical Climatology Network-Monthly dataset. This dataset holds records of temperature readings dating back to the beginning of the eighteenth century from more than seven thousand stations around the globe.

GHCN Monthly

The data are in text files with a fixed width format. It’s very straightforward to set up the import format (although there are many columns!) and save the import specification so that future datasets can be imported as they are released with ease. The largest data files have almost half a million rows, yet Access can import the data in a few seconds. The resulting table of readings of average, minimum and maximum temperatures for each month for each station has more than one million rows. I have not experimented with adding indexes yet but, in spite of this, I can run queries that are not painfully slow.

Now that I have the data into an Access database, I hope to start analysing the data. I have produced a couple of charts for a single station but am yet to run any serious calculations. I have read of a similar project at:

A Quick and Dirty Analysis of GHCN Surface Temperature Data

The algorithm that caerbannog (the blogger) uses in his C++ program to smooth the data and calculate averages is fairly simple. Something similar should be possible (or even easy) using the MS Office tools.

Ultimately, my aim for this is to make this the basis of an ICT lesson or project. As caerbannog notes “Never in history has science been more accessible to the general public than it is now.” The quantities of data that can be accessed for free are as enormous as the power of the computers that are now cheaply available. I hope that my students will be inspired to look deeply into the issue and this will help develop their sense of empirical curiosity.

Mouse Utopia

August 17th, 2011

I’ve just read an interesting piece on a scientist who tried to create a utopia for mice and his results.

http://www.cabinetmagazine.org/issues/42/wiles.php

Science fiction writers have often presented a pessimistic vision of the future, where overpopulation is the problem and nihilism and violence are the consequences. That authors take this route is understandable as a functioning society is not much of a backdrop for a story. Also, despair is easier than hope.

It’s heartening that the scientist in the piece to which I link above was disappointed by the pessimistic fiction that he inspired. Whatever happens to our population and environment, we’re going to have to keep on keeping on.

In spite of the recent ugliness in the streets of London, I still feel that urban living and constantly being surrounded by other people is infinitely to be preferred to living like Robinson Cruesoe.

New Niece in Cheltenham

August 16th, 2011

At the weekend, we went over to Cheltenham to meet our new niece, Annabel Elizabeth Woodward.

2011-08-13 Cheltenham

Sardinia Beach Holiday

August 7th, 2011
2011-07-30 to 2011-08-07 Sardinia

Generics in VB.Net

June 14th, 2011

Taking a lead (again) from Java generic types for beginners, I decided to experiment with generic types in VB.Net. The ICT Cool blog covers the idea behind generics and the MSDN documentation on generic types in VB.Net gives more details on the topic, so I won’t repeat what has been explained elsewhere.

My code shows how generics can make code more robust by enforcing compile time type checking. The type safety of the various objects can be checked in Visual Studio by hovering the mouse over any of the variables in the code. This brings up a pop up that says the type of the object. Many of the lines of the main sub have been commented out because the project would not build otherwise. Try uncommenting them to see the errors that the IDE finds.

The code also shows that generic types allow coders to build and use type safe, polymorphic collections. Put simply, we can create a list (for example) that will only allow us to add an object of any type, so long as it implements an interface given at the time of construction.

GenericsInLists