Skip to content

Instantly share code, notes, and snippets.

@gonutz
Last active May 29, 2025 13:29
Show Gist options
  • Save gonutz/bcc89f0474fae455f4c05943f08d615d to your computer and use it in GitHub Desktop.
Save gonutz/bcc89f0474fae455f4c05943f08d615d to your computer and use it in GitHub Desktop.
Readability is Paramount

Readability is Paramount

I was pointed to a blog post about some new features in C++, the first language that I learnt when I started programming 15 years ago.

The author, a member of the C++ Standardization Committee, gives us an example of some basic algorithm to illustrate the use of a new C++ feature that he worked on. The task is rather simple: find triplets of integers a, b and c where a²+b²=c². Here are some examples:

3 4 5      because 3*3+4*4 = 9+16 = 25 = 5*5
6 8 10     because 6*6+8*8 = 36+64 = 100 = 10*10
5 12 13    because 5*5+12*12 = 25+144 = 169 = 13*13

This can be done as follows:

  • Step through all sorted pairs of a and b, so a < b.
  • For each of these pairs go through all numbers c and check whether a²+b²=c² holds true.
  • The trick is that given c the possible range of a and b is small: it can only be between 1 and c. No need to even compute a square root!

Haskell version: 6 lines, 130 characters

main = print (take 10 triples)

triples = [(a, b, c) | c <- [1..]
                     , a <- [1..c]
                     , b <- [a..c]
                     , a^2 + b^2 == c^2]

Go version: 20 lines, 250 characters

package main

import "fmt"

func main() {
    n := 0
    for c := 1; ;c++ {
        for a := 1; a < c; a++ {
            for b := a; b < c; b++ {
                if a*a+b*b == c*c {
                    fmt.Println(a, b, c)
                    n++
                    if n >= 10 {
                        return
                    }
                }
            }
        }
    }
}

C++ version: 50 lines, 1200 characters

#include <iostream>
#include <optional>
#include <ranges>

using namespace std;

template<Semiregular T>
struct maybe_view : view_interface<maybe_view<T>> {
    maybe_view() = default;
    maybe_view(T t) : data_(std::move(t)) {}
    T const *begin() const noexcept {
        return data_ ? &*data_ : nullptr;
    }
    T const *end() const noexcept {
        return data_ ? &*data_ + 1 : nullptr;
    }
private:
    optional<T> data_{};
};

inline constexpr auto for_each =
    []<Range R, Iterator I = iterator_t<R>,
            IndirectUnaryInvocable<I> Fun>(R&& r, Fun fun)
            requires Range<indirect_result_t<Fun, I>> {
        return std::forward<R>(r)
            | view::transform(std::move(fun))
            | view::join;
    };

inline constexpr auto yield_if =
    []<Semiregular T>(bool b, T x) {
        return b ? maybe_view{std::move(x)} : maybe_view<T>{};
    };

int main() {
    using view::iota;
    auto triples =
        for_each(iota(1), [](int z) {
            return for_each(iota(1, z+1), [=](int x) {
                return for_each(iota(x, z+1), [=](int y) {
                    return yield_if(x*x + y*y == z*z, make_tuple(x, y, z));
                });
            });
        });
    for(auto triple : triples | view::take(10)) {
        cout << '('
            << get<0>(triple) << ','
            << get<1>(triple) << ','
            << get<2>(triple) << ')' << '\n';
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment