# Let's optimize for joy.

This part of the website is dedicated to hosting fun programming challenges. It's a bit like kaggle but the types of challenges that we host here is very different. The main goal of these challenges isn't to win. Instead we hope they are just fun and educational. There's a slight competative element, but only slightly. The hope is that these challenges offer something fun for online communities during the COVID lockdown.

To participate, all you'll need is a token. You can get one by logging in with github below. Keep it safe!

# The Travelling SalesmanShip.

You might be familiar with the traveling salesman problem. It's a shortest-distance kind of a problem and it's a classic in computer-science. Given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city exactly once and returns to the origin city?

We host a variant of this problem here, but there's a twist! Instead of using a truck that goes to each city we're using a sailboat, which adds another dimension to the problem.

Boats can't simply make a 180 degree turn. Once they get going, they'll need a lot of power to make a switch. That means that two paths of equal length may not have the same costs. The cost of travelling from between three cities is defined via;

$$\text{cost}(A \to B \to C) = \frac{\text{dist}_{A \to B}}{2} + \frac{\text{dist}_{B \to C}}{2} + c \measuredangle(ABC)$$

Note that $c$ here is a penalty that's assigned to the angle $\measuredangle(ABC)$ which is calculated in radians. The total score (which we want to minimize) can be written down as;

$$\text{score}(\text{paths}) = \sum_{A \to B \to C \in \text{paths}} \text{cost}(A \to B \to C)$$

If you're interested in participating in this challenge you can find the docs below.

# Getting Started.

To make it easier to get started, we offer a utility library.

pip install python

Once installed, you can retreive scores in the Jupyter notebook.

from calmcode.challenge import TravellingSalesmanShip
import random

# This is a random tour, obviously we can do better
problem = TravellingSalesmanShip.from_predefined("sail-base")
tour = list(range(problem.n_ports))
random.shuffle(tour)

problem.score({"tour": tour})

This is the result.

{
'score': 658.488,
'total_distance': 136.98,
'total_angle': 521.501
}

Once you've made progress and you'd like to record your score then you can use the requests library to post the score. Make sure that you've got your API token first.

import requests as rq

url = "https://calmcode.io/api/"
"challenge": "tsp-sail-base",
"submission": {
"tour": tour
}
}

rq.post(url, data=payload)

# A few things about the API.

1. You only need to send us a request when you've made an improvement. You won't get higher on the leaderboard if you submit a worse score.
2. We've got a hard limit on the API to keep traffic at bay. Only 3 requests per day are allowed.
3. The TravellingSalesmanShip class has some other utilities that might help you solve the challenge, like a distance matrix. Feel free to explore the API.
4. Make sure that you use the correct variant when you call .from_predefined("sail-base"). The class is flexible but you want to make sure that our server settings match the settings you've got locally.