I recommend ProjectEuler, as it will complement your strengths.
It is a set of graded math/programming problems, each of which has a single unambiguous correct answer, and you can compare your solution to other people’s once you have found the answer. I recommend doing the problems in order.
What operating system is installed on your computer?
In that case I’d second the Python recommendation, and add Ruby, as mainstream choices; for a somewhat more exotic choice see Haskell which I’ve found excellent for Project Euler type problems.
Both Python and Ruby are interpreted (“scripting”) languages, which allows you to focus on the programming and not worry overmuch about ancillary matters such as compiling and linking.
Haskell is compiled but also has an interpreter; it’s a functional language, a programming paradigm which is perhaps closer to the mathematician’s way of looking at things. When I was playing with Project Euler it was as an exercise to learn Haskell, and I really liked how the language and the problems meshed together.
For instance you’d start on the first problem by defining a predicate, a boolean-valued function, determining divisibility. (You can type almost everything in what follows into the Haskell interpreter if you want to follow along.)
In the Haskell interpreter ghci this is done by using the keyword let, followed by the function name, followed by formal parameters, followed by “=”, followed by the function definition:
let divides d n = mod n d == 0
If you’ve done prime numbers already this should be somewhat familiar: “mod” is the modulo operator. (There is also a Haskell notation to express this in the more familiar infix form; you can look that up later.)
In Haskell as in math you can leverage your definitions in further definitions, so we can say, naming our predicate “divisible by 3 or 5” fizbuz in honor of a common programmer’s meme:
let fizbuz n = (divides 3 n) || (divides 5 n)
Where Haskell and other functional languages shine is that functions can be used as parameters to other functions. For instance, you can pass a predicate as a parameter to a primitive function named “filter”, which takes a predicate and a list, and returns only items in the list matching the predicate:
filter fizbuz [1,3,5,7]
should return [3,5]. Haskell has plenty of primitive functions which operates on lists—you can build lists, filter lists, but also for instance sum over lists:
sum [1,3,5,7]
will return 16. We can also use this syntax to define lists from more compact ranges: [1..10] means the integers between 1 and 10.
Another area where Haskell feels like home to a mathematician is that you can compose functions, and reason formally on the types of functions and their arguments. For instance the type of our function “filter” is this:
(Integer -> Bool) -> [Integer] -> [Integer]
(Don’t type this in at the ghci prompt. You rarely need to enter these types by hand, because Haskell figures them out for you. But you sometimes will have to, in order to lift some ambiguity for instance.)
We parse this as “a filter is a function which takes as arguments a function mapping integers to booleans, and a list of integers, and returns a list of integers”. The type of this function:
let filterBy3or5 = (filter fizbuz)
is therefore [Integer] → [Integer], that its, it takes a list and returns a list. Since the “sum” function takes a list and returns an integer, we can compose sum and this function (but, note well, not the other way around)
let sumFilteredList = sum . filterBy3or5
or equivalently
let sumFilteredList = (sum . (filter fizbuz))
The latter being “more expressive” and therefore preferable because it shows more clearly how our computation is arranged: we sum over a list filtered by a particular predicate.
Now finding the solution to problem 1 is as simple as entering:
sumFilteredList [1..10]
for the test case, and solving the real problem is left as an exercise for the reader.
What’s nice about this is that several early problems also take the form of “sum over a filtered list of integers in a certain range”. All you have to do to make these problems dead easy to solve is turn the predicate by which the range is filtered into a parameter to sumFilteredList. Then each such problem reduces to a particular case of the general procedure of filtered summing which you have already solved.
sum [ i | i ← [1..999], mod i 3 == 0 || mod i 5 == 0 ]
:)
Haskell is amazing for Project Euler. Lots of these problems are one liners in Haskell. Actually I think Project Euler is excellent for learning Haskell tricks specifically, even if you know how to program already. For certain types of tasks, Haskell is an immense force multiplier.
Of course the difficulty with Haskell is that it is both functional and lazy, which means it explicitly hides the causal order of operations from you for other gains (expressiveness, parallelism, etc.) The problem with this is that in order to debug a Haskell program (or any computer program), a human brain needs to construct an accurate causal model of what’s going on.
Debugging software is generally the act of repeated interventions into a malfunctioning system to figure out where the malfunction is. Languages like Haskell go against this grain by making it difficult to figure out what your intervention is doing due to the hidden causal order (try inserting a print statement into a Haskell program sometime). This is why, I believe, functional programming never caught on—functional programs are very convenient for compiler programs to reason about, but very inconvenient for people.
I recommend ProjectEuler, as it will complement your strengths.
It is a set of graded math/programming problems, each of which has a single unambiguous correct answer, and you can compare your solution to other people’s once you have found the answer. I recommend doing the problems in order.
What operating system is installed on your computer?
Windows 7
In that case I’d second the Python recommendation, and add Ruby, as mainstream choices; for a somewhat more exotic choice see Haskell which I’ve found excellent for Project Euler type problems.
Both Python and Ruby are interpreted (“scripting”) languages, which allows you to focus on the programming and not worry overmuch about ancillary matters such as compiling and linking.
Haskell is compiled but also has an interpreter; it’s a functional language, a programming paradigm which is perhaps closer to the mathematician’s way of looking at things. When I was playing with Project Euler it was as an exercise to learn Haskell, and I really liked how the language and the problems meshed together.
For instance you’d start on the first problem by defining a predicate, a boolean-valued function, determining divisibility. (You can type almost everything in what follows into the Haskell interpreter if you want to follow along.)
In the Haskell interpreter ghci this is done by using the keyword let, followed by the function name, followed by formal parameters, followed by “=”, followed by the function definition:
If you’ve done prime numbers already this should be somewhat familiar: “mod” is the modulo operator. (There is also a Haskell notation to express this in the more familiar infix form; you can look that up later.)
In Haskell as in math you can leverage your definitions in further definitions, so we can say, naming our predicate “divisible by 3 or 5” fizbuz in honor of a common programmer’s meme:
Where Haskell and other functional languages shine is that functions can be used as parameters to other functions. For instance, you can pass a predicate as a parameter to a primitive function named “filter”, which takes a predicate and a list, and returns only items in the list matching the predicate:
should return [3,5]. Haskell has plenty of primitive functions which operates on lists—you can build lists, filter lists, but also for instance sum over lists:
will return 16. We can also use this syntax to define lists from more compact ranges: [1..10] means the integers between 1 and 10.
Another area where Haskell feels like home to a mathematician is that you can compose functions, and reason formally on the types of functions and their arguments. For instance the type of our function “filter” is this:
(Don’t type this in at the ghci prompt. You rarely need to enter these types by hand, because Haskell figures them out for you. But you sometimes will have to, in order to lift some ambiguity for instance.)
We parse this as “a filter is a function which takes as arguments a function mapping integers to booleans, and a list of integers, and returns a list of integers”. The type of this function:
is therefore [Integer] → [Integer], that its, it takes a list and returns a list. Since the “sum” function takes a list and returns an integer, we can compose sum and this function (but, note well, not the other way around)
or equivalently
The latter being “more expressive” and therefore preferable because it shows more clearly how our computation is arranged: we sum over a list filtered by a particular predicate.
Now finding the solution to problem 1 is as simple as entering:
for the test case, and solving the real problem is left as an exercise for the reader.
What’s nice about this is that several early problems also take the form of “sum over a filtered list of integers in a certain range”. All you have to do to make these problems dead easy to solve is turn the predicate by which the range is filtered into a parameter to sumFilteredList. Then each such problem reduces to a particular case of the general procedure of filtered summing which you have already solved.
sum [ i | i ← [1..999], mod i 3 == 0 || mod i 5 == 0 ]
:)
Haskell is amazing for Project Euler. Lots of these problems are one liners in Haskell. Actually I think Project Euler is excellent for learning Haskell tricks specifically, even if you know how to program already. For certain types of tasks, Haskell is an immense force multiplier.
Of course the difficulty with Haskell is that it is both functional and lazy, which means it explicitly hides the causal order of operations from you for other gains (expressiveness, parallelism, etc.) The problem with this is that in order to debug a Haskell program (or any computer program), a human brain needs to construct an accurate causal model of what’s going on.
Debugging software is generally the act of repeated interventions into a malfunctioning system to figure out where the malfunction is. Languages like Haskell go against this grain by making it difficult to figure out what your intervention is doing due to the hidden causal order (try inserting a print statement into a Haskell program sometime). This is why, I believe, functional programming never caught on—functional programs are very convenient for compiler programs to reason about, but very inconvenient for people.
This lets you try 10ish different languages in your browser: http://codepad.org/
I second the Ruby nomination :) And to get started quickly (without any installation) I’d recommend:
Try Ruby