Being visually honest with F#

It’s been a busy month, some top quality conferences – Code Mesh, Build Stuff, FuncBy and NDC London – all cramped into the space of 4 weeks. It has been a blast, lots of talks and valuable takeaways, and it was great to hang out with old friends and meet new ones. As soon as I find time I’ll put together some posts with my key takeaways from the conferences.

During these conferences, Kevlin Henney’s numerous talks have left a lasting impression on me. In his “Seven Ineffective Coding Habits of Many Programmers” talk at Build Stuff, he described the lack of visual honesty in code such as these:

public int howNotToLayoutMethodHeader(int firstArgument,

    string secondArgument)

and on what visual honesty means, he presented a number of quotes from Daniel Higginbotham’s excellent Clean Up Your Mess website:

“To answer the question “What is clean design?” most succinctly: a clean design is one that supports visual thinking so people can meet their information needs with a minimum of conscious effort.”

 

“You convey information by the way you arrange a design’s elements in relation to each other. This information is understood immediately, if not consciously, by the people viewing your design.”

 

“This is great if the visual relationships are obvious and accurate, but if they’re not, your audience is going to get confused. They’ll have to examine your work carefully, going back and forth between the different parts to make sure they understand.”

The quotes talk about laying out information so that their visual relationships are obvious and accurate.

So if you layout your method arguments in such a way that their visual relationships are not accurate and you do that purposefully, then you’re in fact being dishonest.

image

 

As I sat there, I finally understood why F# pipes are so awesome. I always knew it makes cleaner and more readable code, it’s intuitive, but I haven’t been able to find the words to explain why – the trouble with being able to understand something with minimum conscious effort is that your conscious mind can’t explain how it understood it.

Not anymore, now I finally understand it.

 

When we’re reading a piece of regular English text, we’re reading from left-to-right, then top-to-bottom. This convention controls the flow of information we receive as we read, so when we’re laying out information for people to consume, we lay them out in the order of left-to-right, then top-to-bottom.

image

But what about code?

When it comes to writing nested function calls, somehow this flow of information has been reversed!

image

With F#’s pipes (which has been adopted in both Elm and Elixir by the way), we have finally managed to restore some sanity and present sequence of function calls in a way that matches the way we consume any other textual information.

image

Visual honesty right before your eyes!

 

Links

Clean Up Your Mess – A guide to Visual Design for everyone

NDC Oslo 2014 – Takeaways from keynote “it’s a write/read web”

NDC Oslo 2014 – Takeaways from “career reboot for the developer mind”

Takeaways from Theo Schlossnagle’s talk on Scalable Internet Architecture

Takeaways from Hewitt, Meijer and Szyperski’s talk on the Actor model

Takeaways from Gael Fraiteur’s multithreading talk

Project Euler – Problem 68 Solution

Problem

Consider the following “magic” 3-gon ring, filled with the numbers 1 to 6, and each line adding to nine.

Working clockwise, and starting from the group of three with the numerically lowest external node (4,3,2 in this example), each solution can be described uniquely. For example, the above solution can be described by the set: 4,3,2; 6,2,1; 5,1,3.

It is possible to complete the ring with four different totals: 9, 10, 11, and 12. There are eight solutions in total.

image

By concatenating each group it is possible to form 9-digit strings; the maximum string for a 3-gon ring is 432621513.

Using the numbers 1 to 10, and depending on arrangements, it is possible to form 16- and 17-digit strings. What is the maximum 16-digit string for a “magic” 5-gon ring?

Solution

(see full solution here)

 

Before we go into details on the solution, let’s first structure the question in a way that’s easy for us to compute.

To construct the magic circle, be it for a 3-gon or a 5-gon ring, we can slice up the numbers into pairs – e.g. A => [1; 2], B => [3; 4], C => [5; 6], D => [7; 8], E => [9; 10] – and the problem becomes finding ways in which the numbers can be permuted such that:

  1. a0 is the smallest amongst a0, b0, c0, d0, and e0
  2. the sums of a0 + a1 + b1, b0 + b1 + c1, … are the same

For example:

image

 

First, we’ll find the different ways the numbers 1 to 10 can be permuted, and for each permutation slice the numbers into pairs:

image

(this makes use of a permute function defined in the Common.fs source file in the solution).

 

Then we need a function to sum a pair of number with the last element in the adjacent pair – e.g. a0 + a1 + b1:

image

 

For each permutation, we need to check:

  1. if a0 is the smallest amongst the head elements
  2. if the sums of the groups of 3 – i.e. a0 + a1 + b1, b0 + b1 + c1, etc. – are the same

image

This predicate function allows us to find arrangements that meet our criteria. All that’s left is to turn the result groups of 15 numbers into 16/17-digit strings and find the maximum (see full solution below).

 

Here’s the full solution:

image

 

This solution took 26s to execute on my machine.

Project Euler – Problem 64 Solution

Problem

All square roots are periodic when written as continued fractions and can be written in the form:

image

For example, let us consider ?23:

image

If we continue we would get the following expansion:

image

The process can be summarised as follows:

image

It can be seen that the sequence is repeating. For conciseness, we use the notation ?23 = [4;(1,3,1,8)], to indicate that the block (1,3,1,8) repeats indefinitely.

The first ten continued fraction representations of (irrational) square roots are:

?2=[1;(2)], period=1

?3=[1;(1,2)], period=2

?5=[2;(4)], period=1

?6=[2;(2,4)], period=2

?7=[2;(1,1,1,4)], period=4

?8=[2;(1,4)], period=2

?10=[3;(6)], period=1

?11=[3;(3,6)], period=2

?12= [3;(2,6)], period=2

?13=[3;(1,1,1,1,6)], period=5

Exactly four continued fractions, for N <= 13, have an odd period.

How many continued fractions for N <= 10000 have an odd period?

Solution

(see full solution here).

 

Based on the algorithm on continued fractions from Wikipedia, we can implement the expansion algorithm as:

image

From the Wikipedia page:

The algorithm can also terminate on ai when ai = 2 a0, which is easier to implement.

which corresponds to the termination condition we have in the Repeat active pattern (which also checks if the accumulator is empty):

image

Also, this algorithm doesn’t work on numbers that are perfect squares, i.e. 4, 9, 16, … hence we need to exclude them when searching for our answer.

Here’s the solution in full:

image

 

This solution took 92ms to execute on my machine.

Project Euler – Problem 80 Solution

Problem

It is well known that if the square root of a natural number is not an integer, then it is irrational. The decimal expansion of such square roots is infinite without any repeating pattern at all.

The square root of two is 1.41421356237309504880…, and the digital sum of the first one hundred decimal digits is 475.

For the first one hundred natural numbers, find the total of the digital sums of the first one hundred decimal digits for all the irrational square roots.

Solution

(see full solution here).

The premise of the problem itself is fairly straight forward, the challenge here is down to the way floating points are implemented on computers which lacks the precision necessary to solve this problem. So the bulk of the research went into finding a way to generate an arbitrary number of digits of a square root.

As usual, Wikipedia has plenty to offer and the easiest solution implementation wise is this solution by Frazer Jarvis.

image

which translates to:

image

The rest is really straight forward, with the only tricky thing being the conversion from char to int since this returns the internal integer value instead – e.g. int ‘0’ => 48 and int ‘1’ => 49 – hence the need for some hackery in the sum function.

Here is the full solution:

image

 

The solution took 95ms to complete on my machine.

Project Euler – Problem 61 Solution

Problem

Triangle, square, pentagonal, hexagonal, heptagonal, and octagonal numbers are all figurate (polygonal) numbers and are generated by the following formulae:

image

The ordered set of three 4-digit numbers: 8128, 2882, 8281, has three interesting properties.

  1. The set is cyclic, in that the last two digits of each number is the first two digits of the next number (including the last number with the first).
  2. Each polygonal type: triangle (P3,127=8128), square (P4,91=8281), and pentagonal (P5,44=2882), is represented by a different number in the set.
  3. This is the only set of 4-digit numbers with this property.

Find the sum of the only ordered set of six cyclic 4-digit numbers for which each polygonal type: triangle, square, pentagonal, hexagonal, heptagonal, and octagonal, is represented by a different number in the set.

Solution

(see full solution here),

The tricky thing here (at least for me) was to remember that the six 4-digit numbers have to come from different sets, but not necessarily in the order of P3, P4, … P8. Once that is cleared up, the rest is fairly straight forward. In the solution linked above, I first created a set of functions for generating triangle, square, pentagonal, … octagonal numbers:

image

Since the question concerns only 4-digit numbers, so for efficiency sake let’s generate the desired 4 digit numbers ahead of time and safe them for later use:

image

The is4digit predicate function is self-explanatory. naturalNumbers is an infinite sequence of integers starting from 1, we use this sequence to generate the figurate numbers we need, but only keep those that are actually 4 digits.

So far so good, we have all the figurate numbers in an array where [0] => P3, [1] => P4, and so on.

 

Next, create permutations of the figurate numbers such that we exhaust all possible sequence of figurate numbers:

P3 => P4 => P5 => P6 => P7 => P8

P3 => P4 => P6 => P7 => P8 => P5

P4 => P3 => P5 => P6 => P7 => P8

image

(P.S. the permute function here comes from the Common.fs source file in the solution)

 

To find the answer to the problem, we process each permutation to find our answer, take a moment to understand this code:

image

 

The processPermutation function processes one permutation of the figurate numbers and the termination conditions for the inner loop function are:

1. we have one number from each figurate number set and that the last 2 digits of the last number = first 2 digits of first number

Image

2. we have one number from each figurate number set but last 2 digits of last number <> first 2 digits of first number (so close!)

image

3. one of the figurate number set in the sequence doesn’t contain a number whose first 2 digits = the last 2 digits of the number selected from the last figurate number set (short-circuited)

Image

 

For each number in the current set of figurate numbers we build up a new predicate function – e.g. if x = 1282 then the predicate function would find 4-digit numbers whose first two digit = 82 – and use it to process the next set of figurate numbers in the sequence.

The loop function returns int list option where the int list represents the cyclic figurate numbers we’re looking for, so all that’s left is to unpack the option type and then sum the list.

image

 

This solution took 17ms to find the solution on my machine.