🎄👨‍💻 Day 11: Monkey in the Middle

It wasn’t enough to have risked our lives by falling off a rope bridge into the river flowing in the gorge below. Now we met a group of nasty monkeys who are taunting us by throwing the stuff from our backpack. As we try to figure out how to intervene, we are quite apprehensive about our belongings and assign a certain worry level to each item. The monkeys handle each object a bit and then throw it at each other based on how they see us worrying. Each monkey may show a different interest in our objects, and its actions may increase our worry level a little or a lot.

Part 1

The notes we took on the annoying primate pastime take this form:

Monkey 0:
  Starting items: 79, 98
  Operation: new = old * 19
  Test: divisible by 23
    If true: throw to monkey 2
    If false: throw to monkey 3

Each monkey examines a single item on her list, plays with it, and this will change the worry level according to the indicated operation. Then, according to the result, the monkey will choose whom to pass it to. Each turn of the game ends when all monkeys have gone through all the items they have. It’s thus possible that one monkey will end up with no items, or that another monkey who had none at the beginning of the turn will end up with some to play with.

At first, we tell ourselves that this is not such a big deal. As long as the monkeys don’t damage our stuff, we manage to keep our worry level under control. Before each monkey passes an object to another, our worry level is divided by a third.

Since it is impossible to focus on all the monkeys, we decide to focus on the two most active ones. We must then determine which of the groups are the most active after 20 rounds. They will be the ones who got their hands on the most objects.

The puzzle has an interesting input and can be approached in several ways. Perhaps complicating my life, I decided that I would use a dictionary – called monkeys – to keep track of each monkey and what items it has on its hands. In addition, the individual blocks of lines that describe a monkey inspired me to use regexes.

import re

def parse(puzzle_input):
    """Parse input"""
    monkey_re = re.compile(
        r"Monkey (?P<idx>\d+):\n"
        r"\s+Starting items: (?P<items>.*?)\n"
        r"\s+Operation: new = (?P<op>.*?)\n\s"
        r"+Test: divisible by (?P<test>\d+)\n"
        r"\s.*true.*?(?P<true>\d+).*?(?P<false>\d+)",
        re.MULTILINE | re.DOTALL,
    )
    monkeys = {}
    puzzle_input = puzzle_input.split("\n\n")
    for monkey in puzzle_input:
        if match := monkey_re.match(monkey.strip()):
            props = match.groupdict()
            idx = props.pop("idx")
            # re-arrange items to be a list of int
            props["items"] = list(map(int, props["items"].split(", ")))
            # exctract the operation
            _op = props.pop("op").split()
            if _op[0] == _op[-1]:
                op_type = operand = None
            else:
                operand = _op[2]
                op_type = _op[1]
            # create a new monkey
            monkeys[idx] = props
            monkeys[idx]["op"] = partial(op, operand=operand, op_type=op_type)
            monkeys[idx]["count"] = 0

    return monkeys

The pattern is a bit complicated for those not familiar with regex1. In a nutshell, it uses so-called named groups, so you can extract their corresponding values on the fly as a dictionary (with .groupdict()). The most interesting lines are as follows:

# exctract the operation
_op = props.pop("op").split()
if _op[0] == _op[-1]:
	op_type = operand = None
else:
	operand = _op[2]
	op_type = _op[1]
# ...
monkeys[idx]["op"] = partial(op, operand=operand, op_type=op_type)

partial is a very useful function of the functools module that allows you to specialize more generic functions by fixing some of their parameters. In this case, we create one for each operation: power elevation, sum, or multiplication. The code that defines the generic function is this:

def op(arg, operand=None, op_type=None):
    """Define operation"""
    if not operand:
        return arg**2
    if op_type == "*":
        return arg * int(operand)
    if op_type == "+":
        return arg + int(operand)
    return None

At each round of the game, each monkey will inspect and turn over to another all the elements it is holding. To answer Part 1, we need to increment the value of the count2 key, which keeps track of how many items that monkey has seen each round.

def monkey_turn(monkeys, part, divisors):
    """Run a monkey game round"""
    for monkey in monkeys.values():
        while monkey["items"]:
            monkey["count"] += 1
            # perform the operation
            item = monkey["op"](monkey["items"].pop(0))
            if part == 1:
                # Part 1
                item //= 3
            # test and send item
            test, true, false = monkey["test"], monkey["true"], monkey["false"]
            if item % int(test) == 0:
                monkeys[true]["items"].append(item)
            else:
                monkeys[false]["items"].append(item)

    return monkeys

Presumably we will have to simulate the game again in Part 2, so it is worth writing a run_game() function:

def run_game(monkeys, rounds=20, part=1):
    """Run a game"""
    counts = []
    for _ in range(rounds):
        monkeys = monkey_turn(monkeys, part, divisors)

    for monkey in monkeys.values():
        counts.append(monkey["count"])

    a, b = sorted(counts, reverse=True)[:2]

    return a * b

Part 2

Here’s where things get funky now. It does not seem the monkeys are going to give up their pastime any soon, and this makes us particularly anxious. This is an excuse to change two things: the values of the worry levels are no longer divided by 3 at each step, and the number of rounds will be much larger, probably 10 000.

And what is the problem with that, we might ask? Aren’t computers extremely fast machines? Sure, but they are not infinite machines, and above all, no machine can ever win against math. If we look at the input, we notice that a monkey performs the following operation: new = old * old. This is a rapidly exploding number, and well before we get to 10 000, it will take a virtually infinite amount of time to square a humongous number.

The solution is to figure out what these numbers are for: we only test their divisibility by certain factors (that they happen to be primes), and the result of the test determines to which monkey an object will be sent. There is a property of modular arithmetic that allows us to avoid the problem of exploding numbers. The property is this: consider a set of prime factors {p1, p2, p3} of which P is the product, and suppose that some number A is not divisible by p1, i.e. A mod p1 != 0. It can be shown3 that (A mod P) mod p1 != 0. And the same relationship applies to all p. The divisibility by any of the individual factors is preserved, we might say.

What we do is to take the result of the operation on each item (worry level) and compute the remainder of the division with the product of P all prime factors that in the puzzle input appear after Test: divisible by.

The code for the second part does not change much. It is only necessary to calculate the product of the factors and replace item //= 3 with item %= P, if we call P the product of the prime factors. The product P can be calculate conveniently with the function prod of the math module:

import math
divisors = math.prod([int(m["test"]) for m in monkeys.values()])

  1. You can try it at this website. Copy and paste the pattern and input shown just above. Select “Python” in the “Flavor” menu on the left. ↩︎

  2. As we read the input, each monkey is a dictionary to which corresponds a count key that is initialized to 0. ↩︎

  3. It’s quite straightforward. If A mod p1 ≠ 0 but (A mod P) mod p1 = 0, then it would mean that A mod P = r = m * p1, where m is a non-zero integer. In general, we can write an integer like A as k * P + r. If we substitute P = p1 * p2 * p3 and r = m * p1, we get that A = p1 (m + k * p2 * p3), which means that A is a multiple of the prime factor p1, and that invalidates our hypothesis. ↩︎

🎄👨‍💻 Day 10: Cathode-Ray Tube

Despite good will and cool heads, our modeling of rope physics didn’t help much. The rope bridge failed to hold, and we fell straight into the river below (there’s a vague Indiana Jones flavor here). We don’t realize in time, and the Elves from on top signal us that they will continue on and to get in touch with them via the device we repaired a few days ago.

Well, not quite. The screen is shattered, and we can only intuit its operation: it’s an old-fashioned CRT display, and maybe we can build one that will bring the device back to life.

Part 1

The device has a 40x6 pixel screen, but first we need to figure out how to handle the CPU. We have a list of instructions (the puzzle input) that shows only two possibilities. The first, a noop, which requires one clock cycle and does, well, nothing. The second addx ARG, which requires 2 clock cycles and, at the end of the second cycle, sums ARG to the current value of an X register, equal to 1 at the beginning of the program. We need to compute a particular value that appears to be associated with the signal sent from the CPU to the monitor. The value of the signal is calculated only at certain checkpoints: every 40 cycles, starting from the 20th, we take the value of the X register and multiply it by the value of the checkpoint.

Implementing the program is quite simple. However, one must pay attention to one detail, which led me down a wrong path and was difficult to debug: the signal is calculated during a given cycle. I calculated it at the end, that is, when an addx instruction had just updated the register. I don’t know if it was a fluke, but with the example input I could still reproduce 5 of the 6 results described in the problem text. It was not trivial to figure out where I was going wrong. I had to check the register values one by one from cycle 180 through 220 to figure out what was going on.

The key piece of the solution for Part 1 is the function that updates the register:

def run(instruction, register, cycle):
    """
    Run a given istruction
    return the cycles spent in the execution,
    and the register value
    """
    if instruction == "noop":
        cycle += 1
    elif instruction.startswith("addx"):
        _, arg = instruction.strip().split()
        register += int(arg)
        cycle += 2
    
    return cycle, register

After realizing my mistake, calculating the value of the signal correctly was a matter of adding a single variable that would save the value in the register before it was updated at the end of the second loop of an addx instruction. The piece of code that runs the program is just a for loop plus an if:

def part1(data):
    """Solve part 1"""
    reg = 1
    cycle = strength = 0
    check = 20
    for instruction in data:
        last_reg = reg
        cycle, reg = run(instruction, reg, cycle)

        if cycle >= check:
            strength += check * last_reg
            check += 40

Part 2

No spoilers, but I have to say right away that the end result of this second part is the most beautiful and fun we have had so far. Check out if you don’t believe me.

Now it is time to connect the CPU and monitor. We are told that the value of the X register indicates the position of a 3-pixel cursor. The monitor is able to render a single pixel at each cycle. A pixel will be turned on if, at a certain cycle, its position is among those occupied by the cursor at that same time. The key point here is that it can take 2 cycles for the cursor position to update, so we need to make sure that the current pixel is always synchronized with the clock cycles.

Since the screen is 40 pixels wide, the index of the current pixel should always be between 0 and 39. We construct the image on the screen as a single array of characters 240 (pixels) long.

# pixel_pos starts at 0
# we also initialized pixels to []
while pixel_pos < cycle:
	pixels.append(
		"#"
		if (pixel_pos % 40) >= last_reg - 1 and (pixel_pos % 40) <= last_reg + 1
		else "."
	)
	pixel_pos += 1

The last step will be to format the array into a 2D image; for this purpose, the partition() function we had written on Day 6 comes to rescue – see how it pays off to be able to write fairly generic code? The final result is obtained in two lines1:

def part2(data):
    """Solve part 2"""
    _, pixels = data # result from part1()
    screen = partition(pixels, 40) # neat, isn't it?!
    return screen
###..#..#..##..#..#.#..#.###..####.#..#.
#..#.#..#.#..#.#.#..#..#.#..#.#....#.#..
#..#.#..#.#..#.##...####.###..###..##...
###..#..#.####.#.#..#..#.#..#.#....#.#..
#.#..#..#.#..#.#.#..#..#.#..#.#....#.#..
#..#..##..#..#.#..#.#..#.###..####.#..#.

The letters that stand out, readable with some difficulty, are RUAKHBEK. This is certainly one of the most beautiful puzzles on the 2022 calendar! Undoubtedly one that deserves some kind of visualization. I will give it a try, I promise, this one will go straight into #to/revisit list.


  1. To avoid re-running the entire program, I modified the standard template for the function that solves Part 2 so that it takes as an argument the array of pixels computed in Part 1. Take a look at the complete solution on GitHub↩︎

🎄👨‍💻 Day 9: Rope Bridge

If this Advent of Code 2022 ended tomorrow, I could say with certainty that I have learned at least one fundamental thing: I’m struggling the most when translating a solution that is crystal clear in my head using the “words” of an algorithmic vocabulary. Any one. I read the text, understand the problem, and intuit the solution; for a simple example, I even manage to write it down with pen and paper (when possible). Then I get stuck when I ask myself, “and now how do I tell a computer to follow this reasoning and arrive at the result?”

Today’s puzzle is another Advent of Code classic: you have to navigate a two-dimensional grid of dots by following certain rules. Often the question is to count how many times you pass over a grid point or how many locations have never been visited. The interesting part is how you have to move around the grid.

Today’s back-story was slightly absurd, but only a little. Planck’s length even came up – just because it’s cool to mention it. It is fun to follow the rambling vicissitudes of these Elves, though. After all, it only serves the purpose of introducing the problem.

Part 1

We have a rope with two knots at each end. Each node can move along a grid of points, but obviously both are constrained to follow each other. The two nodes will tend to stay as close as possible. The distances between the two knots apply in all directions, even diagonally. The two ends of the string can also overlap, the most trivial case of adjacency.

The knots can move along the grid according to the following rules:

  • If the head node moves two steps in any direction along the XY Cartesian axes, the tail node will move an equal number of steps in the same direction.

  • If, after a move, the nodes are no longer adjacent and are neither on the same row and column, then the tail node will move diagonally by one step. Keep this rule in mind for Part 2.

Our input is a series of movements. Each line, two columns: the first character indicates the direction, the second the number of steps. We are asked to determine which grid points the tail node visits at least once.

Very schematically, for each move we must:

  1. Update the position of the leading node.
  2. Determine where the tail node will end up (it might even stay where it is).
  3. Add the new location of the tail node somewhere. Eventually, it will suffice to count the elements in this list. Since we are interested in points visited at least once, we must ignore any duplicates. It is possible for a node to pass over a point more than once, if the trajectory described by the input is a bit convoluted.

The most interesting part is step 2: determining how to update the tail coordinates. There are four possibilities:

  1. The head knot moves along the X axis: the Y coordinate of the tail remains the same, while the X will change by +1/-1, depending on the direction.
  2. The head moves along the Y axis: as above, but we will update the Y coordinate.
  3. The head moves diagonally: here we need to update both coordinates, combining what we did for X and Y separately.

There is a really important detail to point out, but first we need the code for this function called move(H, T), with a spark of imagination:

def move(H, T):
    """Adjust position of Tail w.r.t. Head, if need be"""
    xh, yh = H
    xt, yt = T

    dx = abs(xh - xt)
    dy = abs(yh - yt)

    if dx <= 1 and dy <= 1:
        # do nothing
        pass
    elif dx >= 2 and dy >= 2:
        # move both
        T = (xh - 1 if xt < xh else xh + 1, yh - 1 if yt < yh else yh + 1)
    elif dx >= 2:
        # move only x
        T = (xh - 1 if xt < xh else xh + 1, yh)
    elif dy >= 2:
        # move only y
        T = (xh, yh - 1 if yt < yh else yh + 1)

    return T

Let’s try to understand the last elif dy >= 2 block. If we said that X remains unchanged, why are we substituting the X coordinate xh of the head node? Because the two nodes can also be diagonally adjacent; in this case, the tail node will have to make a diagonal jump. Here’s a ridiculously simple example to clarify:

  (a)       (b)
......    ......
......    ....H.
....H.    ....*.
...T..    ...T..

When H moves from (4, 1) in (a) to (4, 2) in (b), T will have to move to the point indicated by *. The coordinates of T are (3, 0), and the distances are dx = 1 and dx = 2. If we left the X of T unchanged, it would not move at all along X! This is why we substitute the X of H. In the trivial case where H was moving up and T was exactly below, it would be irrelevant which X coordinate we keep.

The gist of the first part is all here. The rest of the code to get the solution is

Where the two dictionaries delta_x and delta_y simplify a lot the update of the coordinates of H, which can be done in a single, neat line.

delta_x = {"L": 1, "R": -1, "U": 0, "D": 0}
delta_y = {"L": 0, "R": 0, "U": 1, "D": -1}


def part1(data):
    H = (0, 0)
    T = (0, 0)
    tail_path = set([T])
    for direction, step in data:
        for _ in range(int(step)):
            # Update the head's position
            H = H[0] + delta_x[direction], H[1] + delta_y[direction]
            # Update the tail's position
            T = move(H, T)
            tail_path.add(T)

    return len(tail_path)

Part 2

Only two knots?! What is this trivial and boring stuff? Why don’t we use a rope of 10 knots! Sure, no problem, because we just need to update all nodes in pairs according to the same rules.

I must admit that my first implementation did not use the above function move(), but a more trivial one that simply determined whether node T should move or not. If yes, the position of T would be updated to the penultimate position of H.

Unfortunately, this method does not work with more than two nodes: there are multiple ways to move a node that bring it back adjacent to its nearest companion. The correct one is only the one that keeps the two nodes at the minimum distance. Another trivial example:

  (a)       (b)
......    ......
......    ....H.
....H.    ...*1.
4321..    432*..

The node 2 could move to either position indicated by * because both satisfy the adjacency criterion. But only one of them is at the minimum distance, namely the one immediately to the left of 1. By the same reasoning, also the other nodes should move up, and not to the left. It was the tricky detail of Part 2, but the function move() is general enough to deal with this scenario.

The code to solve Part 2 is only a tiny bit more complicated than Part 1: we basically have to add an extra for loop:

def part2(data):
    H = (0, 0)
    T = [(0, 0) for _ in range(9)]
    tail_path = set([T[-1]])
    for direction, step in data:
        for _ in range(int(step)):
            # Update the head's position
            H = H[0] + delta_x[direction], H[1] + delta_y[direction]
            # Update the first point that follows the head
            T[0] = move(H, T[0])
            # Update the remaining points
            for i in range(1, 9):
                T[i] = move(T[i - 1], T[i])
            # Add the tail's position to the path
            tail_path.add(T[-1])

    return len(tail_path)

After reading the puzzle’s text, I wanted to come up with some nice visualization of the strand moving on the grid, but I don’t have (yet) a clue on how to do that. I’ll collect all the puzzles where it could be fun to add some graphics and see to which one I can come back later. Now, I’ll pat on my shoulder for Day 9’s two stars! ⭐⭐

🎄👨‍💻 Day 8: Treetop Tree House

Eric keeps raising the bar with a problem that made me disown Python because otherwise I would have took much longer. I started sketching the solution with the Wolfram Language and wanted to finish the whole puzzle. I will try to recount the highlights of the code that, by the way, earned me today’s stars.

Part 1

The Elves’ project is to build a cozy treetop house. It is not clear how much time they have for this expedition, but so be it. The vast forest in which they find themselves covers a fairly regular area, and the Elves are able to reconstruct a two-dimensional map of it in which each tree is represented by its height1, from 0, the lowest height they have been able to measure, to 9.

The Elves first want to determine where it would be ideal to build the tree house. They need to find the most hidden location possible. They ask us to determine how many trees are visible to an observer outside the forest. A tree is visible if all other trees between it and the forest boundaries are shorter than it. It’s clear that all trees at the edges of the forest will always be visible, so we can already discard them as possible candidates (but we will come back to this in Part 2).

Reading the input is rather simple today: it’s a list of strings with integer digits from 0 to 9. We need to read it in as a matrix of integers:

Map[FromDigits, Characters /@ StringSplit["input.txt", "\n"], {2}]

Given a grid point, we must consider the points to the right, left, top, and bottom, and determine which trees are lowest. A tree will be visible if at least one of these “forest segments” contains only lower trees in height.

For each point (i, j), the row and column containing it will be row = forest[i][:] and col = forest[:][j]2.

From row and col we need to extract two sets of points: those to the right/left and above/below the point under consideration, excluding the point itself. The Wolfram Language has a dedicated function: TakeDrop[list, n] returns two lists, one containing the first n elements, and the second those remaining.

Here is the first piece of the function for the first part ((x, y) are the coordinates of the point):

With[{row = matrix[[x, ;;]], col = matrix[[;; , y]]},
 {sx, dx} = TakeDrop[row, y];
 {up, do} = TakeDrop[col, x];
]

The procedure for looking for visible trees could be put into words like this: look along the row, right then left, and check for all lower trees. Repeat along the column, up then down. The important logic is as follows: in the right/left (or top/bottom) direction, all trees must be lower than the one we’re considering. But only one part of a row/column must meet the criterion for the tree to be visible.

Here is the complete function that, given a point p, its coordinates, and the matrix-forest, tells us (True/False) whether the tree is visible:

VisibleQ[p_, {x_, y_}, matrix_] :=
 Block[{sx, dx, up, do},
  With[{row = matrix[[x, ;;]], col = matrix[[;; , y]]},
   {sx, dx} = TakeDrop[row, y];
   {up, do} = TakeDrop[col, x];
   AllTrue[Most@sx, p > # &] ||
    AllTrue[dx, p > # &] ||
    AllTrue[Most@up, p > # &] ||
    AllTrue[do, p > # &]
   ]
  ]

We just need to apply it to every point in the matrix-forest. Here we have to pull another gem out of Wolfram’s hat: MapIndexed. It does the same thing as Python map(), but it also passes the indices of the current list item to the function to be mapped. A trivial example:

MapIndexed[f, {a, b, c, d}]
(* {f[a, {1}], f[b, {2}], f[c, {3}], f[d, {4}]} *)

And it works with objects of any size! We just need to specify at what level we want to apply the function.

Count[
 MapIndexed[VisibleQ[#1, #2, forest] &, forest, {2}],
 True, {2}
 ]

Part 2

Now things definitely get more complicated, because we have to find the best tree. How? According to a scenic score which is the product of four numbers, one for each side. Each number is the maximum distance along which we can admire the view without being blocked by taller trees.

We must have a function that, given a point (tree) and a list (its row/column “neighbors”), calculates the 4 distances. It increments a counter variable for each lower tree. As soon as it encounters an equal or taller tree, it stops and returns the counter, which will be the distance searched.

counter[value_][list_] :=
 Catch[
  list === {} && Throw[0];
  Block[{total = 0},
   Scan[Which[# < value, ++total, # > value || # == value, 
      Throw[++total]] &, list];
   Throw[total]
   ]
  ]

Now we have two steps to get to the solution.

(1) For each point, we find once again the 4 lists of neighboring points (left/right, up/down):

Flatten[MapIndexed[pick[#2, forest] &, forest, {2}], 1]

pick is the middle portion of the VisibleQ function seen in Part 1. I have made it self-contained for simplicity. For instance, for the point (1, 1) of the example input, this function spits out something like: {3, {{}, {0, 3, 7, 3}, {}, {2, 6, 3, 3}}. The point (1, 1) corresponds to the height value 3 and:

  • on the left, it has no neighbors (it’s on the left border);
  • on the right, it has {0, 3, 7, 3}, in that exact order;
  • it has no neighbors above (so it’s in the upper right corner);
  • it has {2, 6, 3, 3} below.

(2) To apply the counter function3 we need a double Map: the first will scroll over lists like {p, {sx, dx, up, down}}. The second will apply counter` to each neighbor list, keeping the reference point fixed. It will come up with another list that will again be a matrix: each point-tree will be associated with the four distances, which, multiplied, will give the scenic score.

All that remains is to find the maximum of this list as a function of the product of the 4 distances. This is easy thanks to MaximalBy:

MaximalBy[
  Map[Map[counter[#[[1]]], #[[2]]] &, 
   Flatten[MapIndexed[pick[#2, data] &, data, {2}], 1]],
  Apply[Times]
  ] // Flatten /* Apply[Times]

The last bit, Flatten /* Apply[Times], is just multiplying the resulting 4 values to obtain the scenic score.

😓 It is 23:38 and I have not yet had my evening herbal tea. I’m really starting to believe that I don’t think I will endure until Christmas with this frantic pace of finding the solution and writing the report. I’m going to try, though, as long as I keep up.

Bonus: maps

Forest map example
An array plot of the example forest. It's easy to spot the tree with the best scenic score.
The forest map of my input. I had to change the color function to make more visible the tree with the highest scenic score: the small dot on the right side near the edge, in a dark-red color.

  1. A perfect representation of a field in physics. Inevitable note because the writer is proud of his scientific background, although he likes a lot computer science stuff. ↩︎

  2. This is not the right way to slice a 2D list in Python; it’s pseudo-code to give an idea. ↩︎

  3. Or at least in the way I wrote it. I thought of simplifying it to allow a clearer application, but I didn’t have time today. I’m sure I’ll go through these notes once again in the future, also because I want to write a Python solution as well. ↩︎

🎄👨‍💻 Day 7: No Space Left On Device

The dreaded day came, eventually. Without a little hint, I would not have been able to pull out the solution.

The problem was not that I didn’t have a clue on how to solve the puzzle, but that I was stuck with my first approach, refusing to change perspective. That is why the account of this seventh calendar day is perhaps the most important of all the previous ones. Because I found a difficulty that, at first, had completely blocked me. Then a change of point of view allowed me to find the correct solution.

Today’s problem, in short. The Elves’ apparatus has more than its messaging system malfunctioning. You attempt to execute a system update, but it does not go through since there is insufficient disk space available. You inspect the filesystem to examine what’s happening and record the terminal output generated.

The output is very similar to what you would get on a UNIX system. The cd and ls commands are used to change and list the contents of a directory. Each file is associated with its size in bytes (?).

Part 1

Since we have to try to free up space, the first thing to do is to calculate the size of each directory. One directory can contain others, and we have to take this into account to calculate the final size.

My initial idea was to build a data structure that was as similar as possible to the filesystem nested hierarchy. Each entity in this collection of elements had to contain, eventually, other entities (if it were a directory), or simply the name of the file and its size.

I therefore wrote this class:

class Dir:
    """A Dir class"""

    def __init__(self, name):
        self.name = name
        self.children = {}
        self.parent = None
        self.size = 0

    def add(self, child, value=None):
        """Add children to Dir"""
        self.children[child] = value

    def total(self):
        """Total size of this Dir"""
        if self.children:
            for child in self.children.values():
                self.size += child.total() if isinstance(child, Dir) else child
        return self.size

    def __repr__(self):
        return f"Dir({self.children}, parent: '{self.parent.name if self.parent else None}')"

The .total() method already does what one would expect: calculate the total of a directory, following recursively any nested directory. The real stumbling block I haven’t yet overcome was figuring out how to calculate the size of individual directories. Why? Because the puzzle clearly says that, for example, a baz.txt file in the /foo/bar/ directory will contribute to the size of both directories plus the root /. I swear I was unable to write the code that would allow me to do this simple operation.

I was taking too long, so I took a detour on YouTube and was inspired by a video by Jonathan Paulson, a competitive programmer who almost always manages to be in the top 100 people who solve both Advent of Code puzzles. I only had to listen to how he described the problem to figure out how to rewrite the solution. The idea was very simple: simply keep track of each path and its size in a trivial dictionary and without creating a nested object.

Here’s my second attempt with the parsing function:

from collections import defaultdict

def parse(puzzle_input):
    paths = []
    sizes = defaultdict(int)
    
    for line in puzzle_input.splitlines():
        words = line.strip().split()
        if words[1] == "cd":
            if words[2] == "..":
                paths.pop()
            else:
                paths.append(words[2])
        elif words[1] == "ls" or words[0] == "dir":
            continue
        else:
            size = int(words[0])
            for i in range(1, len(paths) + 1):
                sizes["/".join(paths[:i])] += size

	return sizes

For each line in the input, there are three action we can take:

  1. Change directory, either down or up. If down, record append the new path to the list of paths. If up, remove the last added path (with our friend .pop())
  2. List the content of the directory. We simply ignore this line.
  3. Read a directory’s content. If a line starts with dir, it indicates that the current file a directory, so we ignore it: we’re gonna explore that directory later on. If it starts with an integer, we save it.

The following bit of code it’s the interesting one. It’s where we add the size of the current file to all directories it belongs to. That is, to all of its parents up to /. We perform a loop over the parents paths, we build a nice UNIX-like path string, and then add the file size.

size = int(words[0])
for i in range(1, len(paths) + 1):
   sizes["/".join(paths[:i])] += size

Part 1 asks us to find all the directories that are at most 100 000 in size. That’s pretty easy with our sizes dictionary:

def part1(data):
    total = 0
    for size in data.values():
        if size <= 100_000:
            total += size
    return total

Part 2

The second part asks us to find the smallest directory that would allow running the upgrade. We know the total space available and the space required by the update. Thus:

avail = 70_000_000
needed = 30_000_000
max_used = avail - needed
free = data["/"] - max_used

The max_used is the maximum space we are allowed to use. The minimum space we need to free up is the total space we’re occupying, data['/'] – the space of the root directory – minus the allowed maximum. It means two operations: a filtering and then sorting.

def part2(data):
    avail = 70_000_000
    needed = 30_000_000
    max_used = avail - needed
    free = data["/"] - max_used
    
    candidates = list(filter(lambda s: s >= free, data.values()))
    
    return sorted(candidates)[0]

Day 7 is done, but I have to thank Jonathan Paulson because, without his hint, I doubt I would have been able to finish today. But that’s what happen when you’re trying to learn, right? You push yourself until it’s not longer easy and you’re stuck with a seemingly insurmountable difficulty. Then, with the help of someone more experienced or by studying the subject a little more, one is often able to overcome the stumbling block. And it is this experience that, as it accumulates, makes all the difference in the world in any learning process.

“Hey, Edoardo, do you have also a nice and elegant solution in the Wolfram Language?”

“Next time, my friend. Perhaps as a Christmas present. Now I’m pretty satisfied with what I got.”

🎄👨‍💻 Day 6: Tuning Trouble

The preparation phase is finally over, and the expedition in the jungle can begin. You and the Elves set off on foot, each with their backpack filled only with what you’ll need (hopefully). Suddenly, one of the Elves hands you a device. “It has fancy features,” he says, “but you need to set up its communication system right away.” He adds with a grin, ”I heard you know your way around signal-based systems - so this one should be easy for you!” They gave you an old, malfunctioning device that you need to fix. ‘Thanks a lot, friends!’

No sooner had he finished speaking, some sparks signals that the device is partially working! You realize it needs to lock onto their signal. To make it work as it should, you must create a subroutine that detects when four unique characters appear in sequence; this indicates the start of a packet in the communication data-stream.

Your task is clear: given an input buffer, find and report how many characters there are from its beginning to the end of that four-character marker.

Part 1

If we can scan the input and split it in overlapping subsequences of 4 chars, then we could compare them and find the first one that doesn’t contain duplicates characters. That one would be our marker string.

We need to have a utility function for that purpose. It should behave as if a four-characters wide windows scrolled over the string. The offset between one substring and the next is exactly one character. We also need to consider that we might end up with strings that are shorter than the target length if there are not enough characters left.

Here’s our partition() function:

def partition(l, n, d=None, upto=True):
    """
       Generate sublists of `l`
       with length up to `n` and offset `d`
    """
    offset = d or n
    return [
        lx for i in range(0, len(l), offset) 
        if upto or len(lx := l[i : i + n]) == n
    ]

To obtain the solution, we need to transform each sublist into a set to remove any duplicates. Only the resulting sets whose length is still 4 characters are potential candidates for our marker string. We can filter out the others and take the first one. Then, find the index in the original string where our substring starts. Python has the str.find(substr) method for that precise purpose.

def part1(data):
    pdata = list(map(set, partition(data, n=4, d=1, upto=False)))
    marker = list(filter(lambda x: len(x) == 4, pdata))[0]
    return ("".join(data)).find("".join(marker)) + 4

Why are we summing 4 at the end? Because the puzzle asks for “the number of characters from the beginning of the buffer to the end of the first such four-character marker.”

Part 2

There’s a slight plot twist: we also need to decode the start of messages with another, appropriate marker. This time, the marker string is 14 characters long. Once again, our partition() function is versatile enough: we only need to change the offset argument to 14. The code is identical to Part 1’s.

My source of inspiration

As I was able to find the complete solution in a short time, I took some time to make some comparisons with another programming language. A particularly special language since it was the first one I learned: the Wolfram Language (now “WL” for short). For this kind of tasks, it really excels, I have to say. The idea of implementing the partition() function came from remembering that WL has an identical function with many, many more options.

The elegance of the solution written in WL is astonishing (but, as I said, I’m completely biased). I let the reader judge by themselves.

With[{sample = inputDay6},
 Flatten/*Last@
  StringPosition[sample,
   StringJoin@Select[
     Partition[Characters@sample, 4, 1],
     DuplicateFreeQ, 1]
   ]
 ]

🎄👨‍💻 Day 5: Supply Stacks

It’s starting to get serious today, at least as far as input parsing is concerned. The Elves are still in the process of unloading the materials needed for the expedition. On the cargo ship, the material is arranged in crates stacked in a certain order. It would be too easy (and unrealistic) if we could unload all the crates. The ones we need are scattered on the ship, piled in different groups.

The ship’s operator is quick to determining in what order to move the crates so as to retrieve those that the Elves need. They, however, forgetful as they are, do not remember which crates will be the ones they can unload first, that is, the ones that will be at the top of each stack at the end of the “sorting” procedure.

Part 1

The input is divided into two parts. The first, the different stacks with crates before the intervention of the operator. The second, the list of rearrangement operations. It is the first part that is problematic. The example input reads

    [D]
[N] [C]
[Z] [M] [P]
1   2   3

If the operator were to move 2 crates from the second to the third stack, for example, she will move one at a time. Which means that the order of the crates will be reversed: the first crate moved will end up as far back as possible in the stack to which it is moved.

In order to handle crate stacks as if they were lists, we need to find a way to convert a list like [[D], [N,C], [Z,M,P]] to [[Z,N], [M,C,D], [P]]. Unfortunately, this is not a simple transposition, but two operations are needed:

  1. Reverse the matrix, that is, read it row-by-row from the bottom

  2. Now transpose the matrix

For the two steps to work, one more thing is necessary: you must keep the blanks. For example, the first line cannot be [ [D] ], but must be [ [blank, D, blank] ].

There is another problem to handle in parsing the input if we want the transpose operation to make sense: the array must be square, or at least rectangular.

The steps to parse the input are the following:

  1. Split the stacks initial configuration from the rearrangement procedure (easy: it’s just a double \n\n)

  2. Save how many columns we have, that’s important. It can be done by counting the number of digits at the very bottom of the stacks configuration

  3. Read the list of moves. I used the regular expression r"move (\d+) from (\d) to (\d)" to read in a tuple like (num, src, dest): num is how many crates are moved, src from which stack and dest to which one

And now, the fun part. To process the stacks configuration and obtain our matrix, we need to:

  1. Read each line of the stacks section and strip any non-letter character. We also replace any empty “slot” with a dot (.) placeholder, needed to have a square, transposable matrix

  2. If the number of rows is less than the number of cols, we need to add extra rows (filled with dots). Again, that’s to obtain a square matrix. How many rows? Enough to have rows == cols, that is, ["." * cols] * (cols - rows)

  3. Now we can transform our matrix. We reverse it first, and then transpose rows and columns

  4. Last step: we get rid of all the dot placeholders, which represent non-existent crates (or empty ones, if you want). This can be done with filter(lambda x: x != ".", stack)

I’m 99% sure that’s not the easiest or clearest way, but I had so much fun in trying to implement this matrix approach1. The problem resembles a lot the Hanoi Towers’ puzzle, and I bet there are hundreds of schemes or algorithms to solve it.

To obtain the answer to Part 1, we only need to process our stacks according to the list of moves. Remember: we must move the crates one by one. That’s easy enough now that we have our matrix of stacks:

def part1(data):
    stacks, moves = data
    for num, src, dest in moves:
        s, d, n = int(src) - 1, int(dest) - 1, int(num)
        for _ in range(n):
            stacks[d].append(stacks[s].pop())
    return "".join(map(lambda x: x[-1], stacks))

We also need to decrement all the indexes in each move because Python counts from zero. The return statement simply takes the topmost crate in each stack and then joins the characters to get the final answer 🎉.

Part 2

It has to be expected: it turns out that the “giant cargo crane” can move more than one crate at a time. Even better: as many as we want. The code change is minimal because the bulk of the work was reading and saving the crates stack in the right way.

The only thing that changes is that we don’t need the loop for _ in range(n) because we can move more than one crate at a time. We also cannot use pop() because it does not support a range, so we have to do it by hand: extract the elements we are interested in and then delete them.

def part2(data):
    stacks, moves = data
    for num, src, dest in moves:
        s, d, n = int(src) - 1, int(dest) - 1, int(num)
        stacks[d].extend(stacks[s][-n:])
        del stacks[s][-n:]
    return "".join(map(lambda x: x[-1], stacks))

It's 11:59 pm, and Day 5 is finally over. Unexpectedly tough.

  1. The complete solution is here↩︎

🎄👨‍💻 Day 4: Camp Cleanup

Today the Elves start working for real: they need to clear the base camp to make enough space to unload the rest of the material for the upcoming expedition.

“Let’s divide the whole area to clear,” an Elf suggests.

“Good idea, let me take care of it,” another one replies.

So the enthusiastic Elf divides the sections and assigns them to the other Elves who will work in pairs. Each pair will work on two ranges of sections, for example 2,4-6,8: the first Elf will handle sections 2 to 4, the second from 6 to 8.

Unfortunately, the enthusiastic Elf made a bit of a mess. He didn’t realize he assigned overlapping ranges. So we have to find out how many sections are already contained in others, so that we can reassign them and avoid unnecessary work for the Elves.

Part 1

As on Day 3, the anatomy of the problem suggests using sets. We need to determine if a group of numbers is a subset of another or which numbers two groups have in common. Both of these operations are immediate with a set.

Perhaps the most interesting part of today’s puzzle is how to parse the input. We have:

2-4,6-8  
2-3,4-5  
5-7,7-9
...

and we want

[
 [[2,4], [6,8]],
 [[2,3], [4,5]],
 [[5,7], [7,9]],
 ...
]

We can do the first step of input parsing in one line (because it’s fun):

data = [
 list(map(lambda p: list(map(int, p.split("-"))), pair.split(",")))
 for pair in puzzle_input.splitlines()
]
  1. We split each line at ,
  2. Each of the elements of this list is split again at -, and then each element is converted to integer with map and the lambda function.

The second step of the parsing phase is to build a “list of pairs of sets”, where each element of the pair includes all the IDs in the range. Here we need to consider one important detail: the ranges must include the last ID. Hence, we must increment by 1 the second element of each range, otherwise Python will ignore it. That’s a for loop and another map:

sets = []
for p1, p2 in data:
	# range must be inclusive
	p1[1] += 1
	p2[1] += 1
	p1, p2 = map(lambda x: set(range(*x)), (p1, p2))
	sets.append((p1, p2))

Once we did that, the solution to Part 1 is almost immediate: we only need to find if, in each pair, any set is a subset of the other, and count how many of these overlapping sets there are:

def part1(data):
    overlaps = 0
    for p1, p2 in data:
        if p1 <= p2 or p1 >= p2:
            overlaps += 1
    return overlaps

Part 2

The second part of the problem asks us to find (and count) those pairs of ID ranges that overlap for at least one ID. The total will necessarily be greater than the number found in Part 1. The way we read the input allows us to find the solution by changing only one line from Part 1:

def part2(data):
    overlaps = 0
    for p1, p2 in data:
        if p1 & p2:
            overlaps += 1
    return overlaps

🎄👨‍💻 Day 3: Rucksack Reorganization

It’s a classic problem of those who are not used to hiking: preparing a backpack and carrying only what is necessary, no extra unneeded stuff.

The Elves made a big mess with the backpacks. Each backpack has two equal compartments, and there is a finite list of items that they can bring with them. Our input is the list of contents of the backpacks. Each line is a string in which each character represents an item class. Some people put more stuff and some put less, but the two compartments contain the same number of items. The problem is that the person who made the backpacks put some items of the same type in both compartments. That’s unnecessary weight.

Part 1

Not all elements have equal priority, and we have to calculate the total priority of those elements that are present in both compartments. We know that there is only one class of items.

The priorities are calculated simply according to alphabetical order. Elements labeled a-z have priorities 1-26, while those A-Z will have 27-52. We can construct a dictionary on the fly that contains each element with its priority:

# a-z and A-Z letters
from string import ascii_lowercase, ascii_uppercase

prios = {letter: prio for prio, letter in \
         enumerate(ascii_lowercase + ascii_uppercase, start=1)} 

The gist of the problem is an intersection operation between the two compartments of each backpack. And again, everything is already built-in into Python thanks to sets1. Thus:

  1. We divide the string of each row in two and construct two sets.
  2. We do the intersection and then retrieve the priority of the common element.

Part one’s solution is the sum of all priorities:

def part1(data):
    """Solve part 1"""
    total = 0
    for line in data:
        mid = len(line) / 2
        first, second = set(line[:mid]), set(line[mid:])
        total += prio[(first & second).pop()]
    return total

Using .pop() seems to be naive as the resulting set will have only one element, but a standard set doesn’t support indexing2.

Part 2

We know that the Elves will take part in the expedition in groups of three. Each group splits the load into the three backpacks, but there is one item that each Elf must always have: their badge. Each trio will have a badge indicated with a different letter, but we do not know which letter each group’s badge corresponds to.

Since each Elf has only one badge, we need to find which item’s class is present in all their backpacks. Instead of the compartments of a single backpack, we must consider the entire contents of the three backpacks in the group:

def part2(data):
    """Solve part 2"""
    total = 0
    i = 0
    for line in data[::3]: # we jump by 3 lines
        group = set(line) & set(data[i+1]) & set(data[i+2])
        total += prio[group.pop()] # same thing as in Part 1
        i += 3 # don't forget to increase the counter!
    return total

I suspect that the for loop with the manual counter isn’t the best way to implement that logic, but I didn’t come up with a better solution (for the moment).


  1. Need a review? A set is a collection of unique elements where the order is irrelevant↩︎

  2. It doesn’t make too much sense without ordering, right? ↩︎

🎄👨‍💻 Day 2: Rock Paper Scissors

Second day, second warm-up.

The Elves are setting up base camp before venturing into the jungle. To decide who will get the best-positioned tent – that is, the one closest to the food supply meticulously calculated yesterday – the Elves are holding a Rock-Paper-Scissors tournament. The rules are the standard ones, but the scoring will be done as follows:

  • 1, 2, and 3 points are awarded to rock (indicated by A), paper (B), scissors (C), respectively;
  • Outcome points: 6 points for a win, 3 for a tie, and zero otherwise.

The input is the secret key provided to us by a friendly Elf so that we can easily win the tournament. There’s not much structure and it’s quite easy to parse, only a bunch of rows with two letters.

Part 1

The problem is on the interpretation of the input: we do not know what the second column indicates, where X, Y, and Z stand for rock, paper, and scissors.

We make an hypothesis: if the second column represents our choice during a single match, then we need only add the value associated with the character (A=1, B=2, C=3) in the second column to that of the outcome of the game.

def part1(data):
    """Solve part 1"""
    POINTS = {"X": 1, "Y": 2, "Z": 3}

    total_points = 0

    for line in data:
        opp, me = line.split()
        total_points += POINTS[me]
        if opp == "A":
            if me == "X":
                total_points += 3
            elif me == "Y":
                total_points += 6
        elif opp == "B":
            if me == "Y":
                total_points += 3
            elif me == "Z":
                total_points += 6
        else:
            if me == "Z":
                total_points += 3
            elif me == "X":
                total_points += 6

    return total_points

Part 2

There’s a second possibility, which turns out to be the correct one: the second column means the outcome that the game needs to have. In fact, it would be very suspicious if we won every game; someone would suspect that we are cheating (as we are).

In this case, we already know the score of the final outcome – that’s the score associated to X (0, lose), Y (3, draw), and Z (6, win). We have to find which choice between rock-paper-scissors will produce that outcome. The first column always represents our opponent’s choice.

We only need a couple more if...else, but the solution is fairly easy:

def part2(data):
    """
    Solve part 2

    X = lose
    Y = draw
    Z = win
    """
    ENDS = {"X": 0, "Y": 3, "Z": 6}

    total_points = 0

    for line in data:
        opp, end = line.split()
        total_points += ENDS[end]
        # lose
        if end == "X":
            if opp == "A": # rock
                total_points += 3
            elif opp == "B": # paper
                total_points += 1
            else:
                total_points += 2
        # draw
        elif end == "Y":
            if opp == "A": # rock
                total_points += 1
            elif opp == "B": # paper
                total_points += 2
            else:
                total_points += 3
        # win
        else:
            if opp == "A": # rock
                total_points += 2
            elif opp == "B": # paper
                total_points += 3
            else:
                total_points += 1

	return total_points

A very elegant solution (not mine)

One could say very Pythonic. It takes full advantage of the versatility of dictionaries1 and the sum operation between two strings which means to concatenate.

First, we create a dictionary that stores the values of the single choices (A=X=1, B=Y=2, C=Z=3) and the 9 possible outcomes (AX, AY, AZ, etc…).


points = dict(X=1, Y=2, Z=3,
             AX=3, AY=6, AZ=0,
             BX=0, BY=3, BZ=6,
             CX=6, CY=0, CZ=3)

The first part is practically solved in one line, without even an if...else block:


total_points = sum(points[me] + points[me + opp]
				   for opp, me in [line.split() 
				   for line in open('input.txt').readlines()])

Wow 🤯.


  1. Review: a built-in data-structure of key-value pairs ↩︎

🎄👨‍💻 Day 1: Calorie Counting

The first day - maybe the first week - is just warming up. It serves to get us back into the mood, a Christmas-flavored atmosphere that is anything but passive: it is not the awaiting of something or someone that is supposed to come, but a road that will get steeper day by day to make us sweat out the 25 stars before Christmas.

In this year’s adventure, the Elves are on an expedition to a mysterious island to retrieve Santa’s reindeers favorite food, food that contains the indispensable “magic energy”. There will be a jungle to traverse, so let’s get ready for some obstacle running or mazes among the trees.

Part 1

The Elves sort the food they brought with them and want to make sure they have enough. We need to count how much food each Elf brings. The puzzle input divides each Elf’s rations into blocks separated by blank lines. So here’s how to read the input: divide it at the blank lines and convert everything to integers.

lines = [
    list(map(int, line.strip().split("\n")))
    for line in re.split(r"^$", puzzle_input, flags=re.M)
]

We’ll end up with a list of lists. To find the solution, it suffices to sum up each sub-list, and then find the largest sum of all.

A quick explanatory note: we used the re.split() method (from the re standard library package) to be able to split the input at every empty line, represented by the regex ^$. The flag re.M (which is a shortcut to re.MULTILINE) is important to match each empty line. Otherwise ^$ would match the start/end of the whole string only.

sums = sorted([sum(l) for l in lines], reverse=True)
print(sums[0]) # the largest sum

Part 2

The Elves want to know the three in the group who have the most food, to make sure that no one will run out of food during the expedition. The solution is straightforward: all we have to do is pull out the first three items from the list of sums obtained in Part 1 (i.e., the top three), and then add up these three numbers. It’s as easy as

print(sum(sums[:3]))

E adesso?

Era ciò che li aveva spinti a lottare per il loro sogno, ed era ciò che faceva andare avanti me, e altre centinaia di escursionisti su lunga distanza, nei giorni più duri. Non aveva nulla a che fare con l’attrezzatura né con le calzature o la moda del trekking, niente a che vedere con filosofie di un’epoca particolare e neppure con il fatto di andare dal punto A al punto B. Aveva a che fare soltanto con la sensazione che ti dava stare nella natura. Con ciò che significava camminare per chilometri senza altra ragione se non vedere il succedersi di alberi e prati, montagne e deserti, torrenti e rocce, fiumi ed erba, albe e tramonti. Era un’esperienza potente e fondamentale.

—Cheryl Strayed, “Wild”

7 giorni di cammino, più di 120 chilometri percorsi (includendo le due vette, Cima d’Asta e Monte Mulaz), 7300 metri di dislivello positivo e 6500 metri di dislivello negativo. Potrei aggiungere i dati delle calorie bruciate, del numero di passi, o qualsiasi altra metrica, ma nessun numero renderebbe l’idea dell’esperienza “potente e fondamentale” che è stata questa traversata trentina, dalla Val di Fiemme alla Val Cordevole sul Sentiero Italia CAI.

Il blog che abbiamo aggiornato qui (quasi) quotidianamente ha provato a raccogliere sensazioni, pensieri, e alcune foto durante il trekking; abbiamo dovuto aspettare qualche giorno dopo averlo concluso per poter maturare dei pensieri a riposo. Frequento la montagna da anni e l’ho fatto in molti modi diversi, ma l’esperienza del trekking su lunga distanza per me è diventata la scelta prediletta per esplorarla, anzi, per conoscerla davvero. Anzitutto, c’è il tempo trascorso in ambiente, a volte assai variegato come su questo tratto del Sentiero Italia. Si parla di acclimatarsi solo quando si sale in verticale, soprattutto quando la meta è una vetta a una certa quota. Io credo che anche lungo un percorso perlopiù orizzontale serva un tempo simile. Un trekking lungo, anche solo un centinaio di chilometri, non si svela tutto subito, richiede pazienza e anche un po’ di dolore, non soltanto quello del corpo. Ti insegna davvero che cos’è un chilometro e cosa significa “mettere un piede davanti all’altro”. E poi andare avanti, percorrere quello successivo e quello dopo ancora. Tutto perché muoversi lentamente, a passo d’uomo, è un modo a cui siamo molto meno avvezzi nel mondo moderno, dove i chilometri riusciamo a consumarli a velocità incredibili rispetto a un secolo fa.

Un trekking di questo tipo mi ha dato anche l’occasione di mettere in pausa tutto ciò che non aveva direttamente a che fare con il trekking. Sarà un’ovvietà applicabile a qualunque vacanza, ma la mia esperienza dei sette giorni di cammino è stata davvero totalizzante, e non si è trattato solo di non avere (quasi) mai una connessione a internet per comunicare come siamo abituati oggi.

E poi ci sono le persone che puoi avere il tempo e l’occasione di conoscere durante un trekking del genere, a cominciare da quelle con cui decidi di pianificare il percorso. Sono fortunato a conoscere Federico, ormai compagno fisso di diverse avventure in montagna. So già che con lui c’è la sintonia ideale per questo tipo di vacanza, dove la soddisfazione è la fatica che devi metterci per portare a casa tutti i chilometri della tappa. Grazie Fede per aver scelto di organizzare e condividere anche questo trekking!

Sono preziosi anche gli incontri fortuiti con persone sconosciute che camminano lungo percorsi diversi dal tuo e con altre mete. Dalla bidella trentina a cui piace camminare in solitaria agli studenti di geologia in giro per i campionamenti; dagli scout con uno zaino da venticinque chili a quelli che fanno trail running e viaggiano ultraleggeri. La vita del rifugio, poi, nel condividere la cena con persone che non hai mai visto o raccontarsi la giornata davanti a una grappa prima che il bar chiuda, ti convince che forse siamo tutti lì per lo stesso scopo.

Anche se non abbiamo più da raccontare Cosa ci aspetta domani1, possiamo già anticipare quali sono i progetti in cantiere, o perlomeno quelli a cui abbiamo pensato o stiamo considerando da un po’ – anche a costo di mescolare una buona dose di sogni.

  1. Ci sono almeno altre due sezioni del Sentiero Italia che ci incuriosiscono parecchio: quella tra Piemonte e Val d’Aosta e quella che dal Piemonte porta in Lombardia, più o meno dove l’anno scorso abbiamo cominciato l’Alta Via dell’Adamello.

  2. Quest’anno sul Sentiero Italia abbiamo attraversato una varietà incredibile di ambienti montani, boschivi, rocciosi. Ma quello che ci è rimasto più nel cuore è il selvaggio Lagorai. Abbiamo scoperto che esiste la Translagorai, 5 giorni e poco meno di 80 chilometri immersi in questo ambiente quasi incontaminato, e non poteva che entrare di diritto nella lista Dove vorremmo andare prossimamente? L’idea che ci stuzzica di più è fare questo percorso in autonomia, ossia in tenda e bivacchi.

  3. Per ultima – ma solo perché, per adesso, si tratta di un’idea di progetto escursionistico che richiederà preparazione e allenamento (il problema al ginocchio mi ha insegnato qualcosa) – l’intenzione più ambiziosa di tutte: percorrere un tratto del Pacific Crest Trail, un lunghissimo2 trekking scenico che segue l’intera costa ovest degli Stati Uniti, dal Messico al Canada attraversando California, Oregon, e Washington. L’intero percorso è davvero un’impresa titanica non da poco, ma già progettare e riuscire a realizzare un paio di mesi di cammino su quel percorso è indubbiamente tra i miei3 sogni di long distance hiker.


  1. Anche perché stiamo scrivendo questa pagina ben tre settimane dopo la conclusione del trekking. ↩︎

  2. Senza alcun intento di stilare una classifica, il Pacific Crest Trail si sviluppa per un totale di 4270 km, sfiorando i 4000 metri di quota nel punto più alto. L’intero Sentiero Italia CAI copre ben 6170 km. ↩︎

  3. Ho soltanto sondato l’interesse di Federico a questo progetto. Non si è sbilanciato, ma mi pare che l’idea l’abbia incuriosito quanto basta. ↩︎

Giorno Sette: la Regina che era bianca

Dettagli tappa
Partenza Rifugio Contrin, 2012 m
Arrivo Arabba, 1645 m
Tappe intermedie Rifugio Castiglioni, 2045 m; Rifugio Padon, 2407 m
Lunghezza 20.7 km
Dislivello +908/-1283 m

La Cresta del Padon appartiene geograficamente al gruppo della Marmolada, anche se si discosta sia morfologicamente che cromaticamente dal resto del complesso montuoso. Qui, infatti, non dominano chiari calcari bensì scure rocce vulcaniche che fungono da fertile terreno per smeraldine praterie d’alta quota. L’ultima tappa della variante trentina si presenta non troppo faticosa, con una salita molto frequentata e una seguente discesa che sorprendentemente sa regalare degli attimi di intimità davvero impensabili al cospetto di impianti e piste da sci. Il punto di forza di questo percorso è indubbiamente quello panoramico, con lo sguardo che difficilmente riesce a scostarsi dal bianco velo della “regina” Marmolada prima e dal castello roccioso del Sella poi.

L’ultima tappa di questa nostra traversata trentina è ancora una modifica del percorso originale del Sentiero Italia: combineremo la tappa di collegamento che dal Rifugio Contrin porta al Rifugio Castiglioni con quella che taglia il versante opposto alla parete settentrionale della Marmolada, un vero e proprio belvedere sulla Regina delle Dolomiti.

Dopo una notte abbastanza ristoratrice e tranquilla – nonostante fossimo in una camerata da nove – quando arriviamo in sala da pranzo alle 7 e 30 la troviamo già piena; perciò dividiamo il tavolo con due ragazze canadesi1 che sono venute da Calgary, in Alberta, per farsi un giro sulle nostre Dolomiti: stanno percorrendo il nostro stesso percorso in senso inverso, dirette a Passo Rolle passando per Passo Valles. Sono rimasto davvero stupito dalla loro scelta, ma è pur vero che le Dolomiti sono patrimonio UNESCO e sono mete parecchio celebri oltre i confini italiani – in fondo, non è molto diverso dalla scelta di un europeo di andare a fare trekking sulle Ande cilene o la Sierra Nevada in California.

Vetta lunare

Dopo colazione, salutiamo le due ragazze al momento di chiudere gli zaini, e alle 8:31 siamo già sul sentiero 602 che scende attraversando la Val Contrin – altra valle totalmente votata all’alpeggio – fino al piccolo abitato di Alba, frazione di Canazei, ultimo paese della Val di Fassa. Il sentiero è in realtà una strada carrozzabile che permette di raggiungere il rifugio in fuoristrada (il permesso è riservato alle attività del rifugio), perciò riusciamo a fare un paio di scorciatoie per abbreviare la discesa, anziché seguire tutti i tornanti.

Prendiamo una deviazione quando siamo ormai a quota 1500 metri e ci dirigiamo verso Penìa, altra piccola frazione di Canazei. Da qui, il Sentiero Italia comincia a risalire il torrente Avisio, corso d’acqua d’importanza geologica notevole avendo scavato la Val di Fassa, la Val di Fiemme, e la Val Cembra prima di buttarsi nell’Adige. Sul sentiero che lo costeggia e che riprende lentamente quota, ci sono numerosi pannelli illustrativi che spiegano la storia dei paesi che sono nati intorno al torrente, dei ritmi stagionali che lo caratterizzano, nonché la flora e la fauna che lo popolano. È un tratto abbastanza riposante2 della doppia tappa di oggi.

Il sentiero attraversa un paio di volte e affianca per alcuni chilometri la strada statale in direzione del lago di Fedaia (e l’omonimo passo); poi si discosta definitivamente e rimane più in basso, attraversa lo spazio aperto di un pianoro chiamato Pian Trevisan, e raggiunge l’inizio del sentiero 605 nei pressi di un hotel alpino. Qui si comincia a fare sul serio perché il sentiero s’inerpica subito fra sassi e alti gradoni rocciosi, spianandosi dopo circa cento metri di dislivello. La salita riprende più dolce e graduale, in un ambiente boschivo perfetto per l’ennesima giornata molto calda, fino a raggiungere il Col Ciampè (circa 1850 m). Da qui, ormai al limite del bosco, percorriamo un ultimo tratto ripido che ci porta proprio sotto allo sbarramento della diga del lago di Fedaia vicino alla quale si trova il rifugio Castiglioni Marmolada. Siamo già ben oltre l’ora di pranzo, perciò ci concediamo una pausa più lunga e un pasto veloce al rifugio (gnocchetti al ragù di cinghiale e carne salada trentina).

Dopo pranzo, Federico si sente obbligato a fare un pit stop al lago artificiale per provare a recuperare il tono muscolare di gambe e piedi – entrambi ci hanno portato per più di 90 chilometri dalla Val di Fiemme – e anch’io provo a cercare un po’ di sollievo al ginocchio acciaccato.

Edo nel Fedaia

Decidiamo di modificare anche la tappa del pomeriggio per fare meno dislivello in salita: taglieremo il pezzo di sentiero che passa per il rifugio Luigi Gorza – altro autogrill invernale delle piste che scendono da Porta Vescovo – e andremo direttamente al rifugio Padon, prendendo una traccia di sentiero che sarà un po’ da inventare nel primo tratto.

Il primo pezzo della variante è giusto segnato nel punto in cui devia dal sentiero principale che porta al rifugio Gorza. Abbiamo però la mappa digitale, il GPS, e sappiamo in che direzione dobbiamo andare. Dobbiamo soltanto seguire la traccia a mezza costa – chiaramente un terreno battuto da capre e pecore – e prendere quota fino a circa 2400 metri. Incontriamo un paio di persone che hanno deciso di fare la stessa deviazione al contrario, e ciò ci convince di essere sul percorso giusto, anche se in alcuni punti l’unica traccia è solamente l’erba calpestata da chi è passato prima. In cambio, però, abbiamo la fortuna di poter ammirare il versante nord della Marmolada in tutta la sua vastità.

Marmolada nord

È impossibile non notare due cose. Si riesce a distinguere3 il punto in cui si è creata l’enorme voragine in seguito al distacco di inizio luglio: assomiglia molto all’ingresso di una caverna, ma si capisce che la geometria originale di quella parte di ghiacciaio è stata profondamente modificata da un evento improvviso. È anche innegabile la condizione pietosa del ghiacciaio: la seconda foto mostra chiaramente una lingua del ghiacciaio coperta con teli bianchi nella speranza di poterla salvare.

Ghiacciaio Marmolada
La parete nord, da un'altra angolazione e con un obiettivo che ci avvicina di più. Sulla sinistra, si nota la lingua di ghiacciaio ridotta allo stremo e coperta dai teli riflettenti la luce solare.

Due numeri, così per dare un’idea dello stato attuale:

Le ultime indagini sullo spessore del ghiaccio con georadar rivelano come l’intero bacino abbia ormai perso l'80% del proprio volume, passando dai 95 milioni di metri cubi nel 1954 ai 4 milioni attuali4.

Alcune ottimistiche previsioni sperano di mantenere il ghiacciaio per i prossimi 30 anni. Osservandolo dal vivo per la prima volta, noi due ci siamo detti che sarà già tanto se la parte più alta resisterà per altri 15 anni.

Marmolada nord selfie

Attraversiamo (letteralmente) un gregge di pecore che si muove verso prati più alti e, dopo essere ritornati su sentiero ben segnato – quello che avremmo percorso se fossimo saliti fino al rifugio Gorza – arriviamo al Passo del Padon in cui converge l’omonima cresta e su cui si sviluppa una famosa ferrata nota come Sentiero delle trincee. Qui si nota subito come le rocce siano di tutt’altra specie rispetto alle Dolomiti: si tratta di scure rocce vulcaniche che hanno favorito la crescita delle praterie in quota, adesso colonizzate da greggi di pecore. Mentre dal passo ci avviciniamo all’ultimo rifugio lungo un sentiero pianeggiante, notiamo anche dei massi conglomerati, abbastanza diffusi in questa zona: si tratta di rocce composte da una matrice di origine dolomitica e dal materiale di sgretolamento degli antichissimi edifici vulcanici che si trovavano in Val di Fassa. Pur non avendo la minima competenza in materia, è difficile non prestare attenzione alle “opere” di questo museo geologico a cielo aperto, che espone quasi 250 milioni di storia della Terra.

Al rifugio Padon la stanchezza si fa sentire parecchio. Beviamo due bevande zuccherate e mangiamo l’ultima barretta, ma sappiamo che l’energia necessaria l’attingeremo soltanto dalla certezza che la discesa verso Arabba sarà davvero l’ultima.

Alle tre ci rimettiamo in spalla gli zaini e cominciamo la discesa che sarà prevalentemente lungo piste da sci di Arabba, parte dell’enorme comprensorio del Sellaronda. Dopo un primo pezzo molto ripido che percorre una stretta traccia scomoda su ghiaia, camminiamo quasi in piano fino alla stazione intermedia della funivia, che da Arabba sale alla forcella Porta Vescovo. Inutile dire quanto siamo tentati di prendere la seconda funivia in discesa per risparmiare un po’ le gambe. Alla fine, però, ci ripetiamo il mantra che ha segnato questo trekking sin dall’inizio – “bisogna solo mettere un piede davanti all’altro” – e continuiamo la discesa. Usciamo dalla pista da sci percorrendo un pezzo del Sentiero Geologico di Arabba, e anche questo sentiero non ci fa sconti sulla pendenza. L’unico pregio del seguire lo sviluppo di una pista da sci è che sei sicuro di percorrere la via più breve: arriverai a destinazione senza troppe varianti di percorso, ma probabilmente anche senza più le gambe.

Gruppo sella

Alle 17:32 arriviamo alla stazione di partenza della funivia di Arabba e, prima di orientarci e capire dove sia il nostro ultimo alloggio, ci stringiamo la mano come abbiamo fatto tante altre volte arrivati in cima a una vetta o al termine di una via d’arrampicata: la variante trentina, quella storica5, del Sentiero Italia l’abbiamo ufficialmente conclusa6 🙌 🏔️

Complimenti
La meritatissima birra conclusiva, nel pub più vicino possibile al nostro b&b. Domani ci aspetta la tappa meno desiderata: il viaggio di ritorno in Pianura Padana.

  1. Edoardo si prende il merito di aver iniziato il discorso avendo notato che una di loro indossava una bandana del Banff National Park, un’area di wilderness di più di seimila chilometri quadrati, all’incirca quanto l’intera provincia di Trento, giusto per mettere le cose in prospettiva. Il parco nazionale fa parte di un’area anch’essa considerata UNESCO World Heritage. ↩︎

  2. “Riposante” per modo di dire, visto che già ieri Edoardo si è ritrovato un ginocchio abbastanza dolorante, soprattutto in discesa, forse a causa un piccolo problema ai legamenti. È evidente che non era abbastanza allenato per un trekking del genere. ↩︎

  3. La foto in questa pagina è troppo piccola. Si può sempre cliccarci sopra per aprirla nelle dimensioni originali e ingrandirla un po’, nonostante la qualità sia un po’ scarsa: non è stata scattata con un teleobiettivo particolare. ↩︎

  4. Dalla scheda a pag. 156 del volume 11 della collana Sentiero Italia CAI↩︎

  5. La seconda variante, più recente, del Sentiero Italia è quella altoatesina: dal Rifugio Potzmauer arriva sempre ad Arabba lungo un percorso più a nord e lungo il quale si passa dal Latemar, il Catinaccio, il lago di Carezza, l’Alpe di Tires e di Siusi, fino a Selva Val Gardena, Puez, e infine il gruppo del Sella. ↩︎

  6. A voler essere precisi, non abbiamo percorso la prima tappa della variante trentina, quella che va dal Rifugio Potzmauer a Molina di Fiemme. ↩︎

Giorno Sei: ambiente lunare sui Monti Pallidi

Dettagli tappa
Partenza Passo Valles, 2030 m
Tappe intermedie Passo S. Pellegrino, 1899 m
Arrivo Rifugio Contrin, 2012 m
Lunghezza 17.6 km
Dislivello +1260/-668 m

Tappa di media lunghezza dal buon dislivello che porta alla scoperta del versante meridionale del gruppo della Marmolada, caratterizzato da superbe cime rocciose e sicuramente meno celebrato di quello settentrionale che ospita il più esteso ghiacciaio dolomitico. Dalle bucoliche distese pascolive del Fuciade si raggiungono le alte zone rocciose del Passo delle Cirelle, passando prima per ampie praterie d’alta quota e importanti ghiaioni. Lo spettacolo non manca di sicuro, sia per la bellezza degli ambienti su cui ci si muove, sia per la vista sui numerosi gruppi montuosi che riempiono via via l’orizzonte. La vista sulla leggendaria Parete Sud della Marmolada, teatro di epiche ascensioni, è di quelle che difficilmente si possono dimenticare.

Il primo tratto di questa sesta giornata di cammino è stato il pezzo mancante di ieri, ossia la congiunzione del Passo Valles con il Passo S. Pellegrino. Il percorso era piuttosto semplice e abbastanza lineare dovendo collegare due passi alla stessa quota, però la guida ci aveva avvisato che la traccia non sarebbe stata sempre visibile, in mezzo a comprensori sciistici e incroci con altri sentieri. È bastato poco perché sbagliassimo direzione – avremmo potuto guardare un po’ più spesso la traccia GPS, ma il nostro passo era già spedito. Così ci siamo trovati in meno di due ore su al Col Margherita, a 2500 metri, il punto più alto del comprensorio del S. Pellegrino.

Col Margherita

L’errore ci sarebbe costato più di due ore se, ironia della sorte, non ci fosse stata la possibilità di prendere la funivia in discesa. Non abbiamo avuta molta scelta, ci mancavano troppi chilometri e dislivello per voler fare gli integralisti.

In cinque minuti, la funivia ci porta al San Pellegrino dove ci rendiamo subito conto che è un sabato di metà luglio. Sulla strada, tutta carrozzabile, che porta alla bucolica conca di Fuciade sembra di essere lungo un pellegrinaggio. In meno di venti minuti, su un comodo falsopiano raggiungiamo il Rifugio Fuciade1, una stupenda costruzione in legno in pieno stile trentino (sauna inclusa). L’avevamo pure considerata come un potenziale punto di appoggio, ma il listino prezzi per una notte con colazione ci ha subito dissuaso, senza contare l’affollamento turistico di questa zona – che però se lo merita tutta: i pascoli curatissimi che incorniciano alcune vette del gruppo della Marmolada da un lato e i profili delle Pale di San Martino dall’altro.

Da qui partirà il nostro sentiero (n. 607) che diventerà l’escursione vera e propria della tappa giornaliera. Cogliamo quindi l’occasione per mangiare un panino (l’inflazione della zona da vip si fa sentire) e poi, ben incremati, ripartiamo con destinazione intermedia il Pas de le Cirele. Saliamo con una pendenza graduale sempre tra i prati da pascolo, puntando alle vette minori del gruppo della Marmolada: la Punta Jigolé, l’Ombretola, e il Sasso di Valfredda. Dopo quasi un’ora, il sentiero si fa un po’ più ripido e i tornanti aumentano finché raggiungiamo un pianoro, il Busc da la Tascia, sotto l’omonima vetta (Sas da la Tascia). Qui incontriamo una coppia che si sta prendendo una pausa dopo aver concatenato un paio di vette, l’Ombreta (3011 m) e la sorella minore Ombretola (2930 m); quando gli raccontiamo del nostro percorso, anche loro ci fanno i complimenti per avere già quasi cento chilometri nelle gambe. Più tardi al rifugio, ci siamo chiesti come mai parlare del Sentiero Italia susciti un’ammirazione del genere in questa regione, visto che di percorsi impegnativi e lunghi ce ne sono in abbondanza. Però fa senz’altro piacere che qualcuno riconosca la nostra piccola impresa.

Pascoli fuciade
Verso Cirele
Il sentiero 607 che sale verso il Busc da la Tascia. Sullo sfondo, il Sas de Valfreida.

Pochi passi oltre il Busc il terreno diventa un tipico ghiaione, da cui ci si accorge di come questo punto era la soglia di un ghiacciaio ormai scomparso. Nonostante la traccia del sentiero sia ben visibile e salga comodamente la fiumana di ghiaie in cui ci troviamo, tra la pendenza e il sole del primo pomeriggio smettiamo di chiacchierare perché entrambi dobbiamo trovare il passo adatto a salire senza strappi.

Fede stanco Ancora ghiaione

Incontriamo solo poche persone che scendono – Cristina, la nostra prima conoscenza alla Malga Consèria, ci aveva avvisati che è talmente divertente percorrere questo ghiaione in discesa che quasi nessuno lo fa in salita – e, ormai al passo, abbiamo la fortuna di incrociare un camoscio: in meno di un minuto risale di corsa il versante opposto al passo, scavalca la cresta, e si butta a capofitto nel ghiaione dove noi abbiamo appena sudato per una buona ora e mezzo. Non c’è modo di riuscire a fare una foto o un video, perciò ci limitiamo a guardarlo e riconoscere che questa è casa sua, siamo noi gli estranei.

Quasi al passo

Scendiamo verso nord sul versante opposto, ancora tra ghiaie e roccette, su un sentiero un po’ meno faticoso del ghiaione. In pochi minuti, raggiungiamo un pulpito roccioso con un monumento ai caduti della Grande Guerra e uno splendido panorama sul Sassolungo.

Sassolungo
Federico ringrazia per la meravigliosa foto profilo. Avremmo anche tentato un autoscatto, ma un banale errore nelle impostazioni della fotocamera ci ha restituito tre foto tutte fuori fuoco.

Scendiamo rapidamente nella Val de le Cirele, verso i prati del Passo San Nicolò. Il terreno cambia di nuovo, alcuni abeti e un manto erboso sostituiscono roccia e ghiaia. Questo tratto del Sentiero è quello in cui abbiamo incontrato più animali: oltre alla cavalcata del camoscio e uno stambecco appostato su un cucuzzolo roccioso – impossibile fargli una foto senza un obiettivo adeguato – avremo intravisto almeno una decina di marmotte che uscivano dalle tane, correvano sui prati, e rientravano altrove dopo averci osservato per un po’ a distanza di sicurezza. Capiamo di essere ormai vicini alla meta quando attraversiamo alcuni pascoli e i loro abitanti, e pochi minuti dopo raggiungiamo la Malga Contrin (2027 m), in cui si possono acquistare diversi prodotti caseari. Il rifugio Contrin2 è proprio dietro l’angolo.

Malga Contrin

  1. Non abbiamo foto, ma fatevi un giro sulla pagina web del “rifugio” per capire di che zona idilliaca si tratti. E per dare un’occhiata ai prezzi, se volete. Evitate il weekend, se possibile. ↩︎

  2. Anche noto come “il rifugio degli Alpini” perché nel 1921, dopo averlo ricostruito una volta terminata la guerra, la SAT lo donò all’Associazione Nazionale Alpini. Si vede che è un rifugio attrezzato per ospitare almeno duecento coperti e forse un centinaio di posti letto, distribuiti in due edifici separati. ↩︎

Giorno Cinque: il richiamo del Mulaz

Dettagli tappa
Partenza Rifugio Capanna Cervino, 2084 m
Tappe intermedie Rifugio G. Volpi al Mulaz, 2570 m
Arrivo Passo Valles, 2030 m
Lunghezza 21 km
Dislivello +1308/-1307 m

Salite sulla cima di una montagna e piangendo ricercate una visione.

—Proverbio Sioux

Il titolo non lascia dubbi su quale opzione abbiamo scelto. La variante proposta da Michele, cuoco e fotografo di Capanna Cervino, era troppo più interessante della tappa del Sentiero Italia, tappa che noi avevamo già accorciata per questioni organizzative: anziché fermarci al passo San Pellegrino, abbiamo accorciato di quasi metà a Passo Valles, il confine tra Veneto e Trentino.

Dopo una colazione da re – in assoluto la migliore finora – rifacciamo gli zaini, salutiamo Elena, gestore del rifugio dicendole che saremmo andati verso il rifugio Mulaz, e lasciamo il Capanna Cervino poco prima delle nove. Dopo alcuni tornanti su strada forestale (stavolta gli scarponi li avevamo già indosso visto che avremmo dovuto salire su un vero sentiero dopo pochi chilometri) raggiungiamo la Baita Segantini, per poi continuare sulla stessa forestale che scende nella Val Venegia. Il nome di questa piccola valle, dedicata quasi totalmente a pascolo, deriva dalla città di Venezia, la Repubblica Marinara che comprava in esclusiva il pregiato legname.

Pascolo val Venegia

Il sentiero originale della tappa prevedeva di attraversare l’intera valle, risalire fino alla forcella Venegia, e poi scendere a passo Valles. Noi invece, non appena conclusa la discesa dalla baita, abbiamo preso subito sulla destra la deviazione per il rifugio G. Volpi di Misurata al Mulaz.

È un sentiero escursionistico ben diverso da quello previsto dalla tappa del Sentiero Italia. Non camminiamo molto prima di cominciare a salire a un buon ritmo, inizialmente tra un misto di massi e pini, poi soltanto fra rocce bianchissime che ci ricordano ancora una volta che qui, tanto tempo fa, doveva esserci il mare. Dovendo prendere poco più di seicento metri di dislivello in circa tre chilometri, il sentiero comincia a stringere i tornanti e salire rapidamente. Facciamo soltanto una pausa acqua appena prima di terminare la parte in ombra e arriviamo al Passo Mulaz (2619 m) in due ore e venti.

Passo Mulaz

Da qui, dieci minuti di discesa ci portano al rifugio, ma già a metà di questo sentiero di collegamento notiamo l’indicazione per la vera meta di questa impegnativa deviazione: la vetta del Monte Mulaz. Arriviamo al rifugio, abbandoniamo gli zaini, tiriamo un sorso d’acqua, e prendiamo la traccia di sentiero che sale in vetta.

Rifugio Mulaz

Sono altri 500 metri di dislivello, tra roccette, canalini, e un paio di traversi un po’ esposti ma che si possono percorrere senza particolari difficoltà. Da evitare, però, se si soffre di vertigini.

Edo contempla

Un balcone sul Mulaz

Non solo i 2906 metri del Mulaz sorpassano l’altra vetta che abbiamo salito, ma ci portano su un balcone strepitoso sulle Pale, la Marmolada, l’Antelao, il Civetta. Anche la catena del Lagorai e le Dolomiti di Brenta si riescono a intravedere in lontananza.

Vetta del Mulaz

“È obbligatorio suonare la campana” ci aveva detto Michele, e così facciamo – finalmente un oggetto in vetta con cui si può interagire, non la solita croce. Scambiamo due parole con un paio di altre persone che sono lì per lo stesso motivo: ammirare e contemplare il panorama, grazie anche alla bella giornata sebbene il cielo non sia proprio terso – si nota una certa umidità nell’aria tipica del caldo afoso che è già arrivato giù in città.

Peaks 1 Peaks 2

Un signore sulla sessantina sembra conoscere a menadito qualunque pizzo, vetta, o cima si possa distinguere da lassù. Ci chiede una mano per confermare la sua buona memoria quando si accorge che abbiamo un’app sullo smartphone che ci ha permesso di scattare quelle due foto là sopra. La moglie prova a obbligarlo a mangiare almeno un paio di cracker, ma lui è troppo estasiato dal riconoscere tutte queste cime, molte delle quali ha probabilmente salite quando era più giovane. “Se non ti sazia questo panorama, cos’altro?” ci dice.

Chiacchieriamo brevemente anche con una donna – anche lei tra i cinquanta e i sessanta – che ci chiede di farle una foto mentre suona la campana di vetta. È salita da sola e ci racconta che andare in montagna in solitaria è una sua passione da tempo – era in cima alla Marmolada la settimana prima del ben noto crollo di un pezzo del ghiacciaio, e ci confida più volte quanto si senta fortunata. Adesso che è in pensione, ci dice, ha parecchi progetti in cantiere che vorrebbe realizzare; noi gliene abbiamo regalato un altro parlandole del Sentiero Italia. Ci salutiamo (noi abbiamo una certa fame), con lei che si congratula con noi per aver fatto già tutta questa strada, su e giù per le montagne trentine. Giù diritti, quindi, e in mezz’ora ritorniamo sul sentiero per il rifugio dove ci rifocilliamo come si deve con un abbondante piatto di pasta – anche se Federico si è lamentato del troppo aglio nel suo piatto di tagliatelle ai funghi.

Il Passo Valles è ancora lontano: dobbiamo aggirare tutto il massiccio conico del Mulaz per andare a riprendere il Sentiero Italia nel punto in cui esce risalendo dalla Val Venegia.

Ore 14:53 siamo già in marcia, e i primi due-tre chilometri sono da percorrere con calma: è un tratto molto ripido, con alcuni passaggi su roccia e un paio di canali (tutti ben attrezzati però, serve la solita buona dose di attenzione). È un pezzo molto scenico dell’Alta Via n. 2 delle Dolomiti, che nel senso di marcia arriva al rifugio Mulaz risalendo proprio questo canale.

Alta via n2

La deviazione è stata meravigliosa, ma non certo a costo zero: arriviamo alla Forcella Venegiotta (quanta fantasia nei nomi di selle e passi qui), in cui si conclude il pezzo tecnico dell’Alta Via, e la stanchezza si fa ben sentire; i piedi si lamentano di essere ancora costretti negli scarponi, ma ci mancano ancora almeno due chilometri prima di incrociare il Sentiero Italia.

Non incontriamo anima viva (esclusi alcuni gruppi di vacche equilibriste1 al pascolo) fino all’ultima forcella: indovinate come si chiama2? Secondo il GPS, abbiamo percorso altri 2.6 chilometri. “Sembrava molto di meno sulla mappa”, ci diciamo, ma è la solita ovvietà di chi crede che segnare accuratamente una traccia su una mappa digitale ti sconti una parte della fatica che dovrai fare nel percorrerla, quella traccia.

Dalla forcella vediamo già il rifugio/albergo al Passo Valles, ma ci mancano ancora un centinaio di metri da scendere per arrivare a quota duemila. Ormai piedi e gambe vanno verso il basso grazie all’inerzia moltiplicata per l’affaticamento muscolare, e in meno di mezz’ora siamo al passo con un tempismo perfetto: mettiamo piede in camera – una minuscola tripla che è abitabile da sole due persone – e comincia a piovere, l’unica perturbazione veramente attiva che abbiamo incontrato da inizio settimana. Nota di merito al rifugio Valles per una cena davvero abbondante: abbiamo dovuto bere due tisane al finocchio a testa per digerire e riuscire ad andare a dormire, nonostante i venti chilometri e passa camminati.

Cosa ci aspetta domani

Altra tappa leggermente modificata rispetto al percorso del Sentiero Italia. Dovremo prima raggiungere il Passo S. Pellegrino (circa 8 km), passare dal villaggio alpino di Fuciade – una delle località più frequentate della Val di Fassa – e da lì salire fino al Pas de le Cirèle a duemila seicento metri. Dal passo, dopo seicento metri di discesa nella Val de le Cirele, arriveremo al Rifugio Contrin, ultimo pernotto in un rifugio alpino.


  1. Tutto vero, non è un nome inventato né una nuova specie di vacca. Generazioni di bovini allevati nei pascoli ripidi di queste valli hanno sviluppato un istinto naturale spiccato per individuare e percorrere sentieri tracciati da caprioli, camosci, e altri animali abituati a camminare su terreni che a noi umani sembrano impensabili. ↩︎

  2. Forcella Venegia, ovviamente ↩︎

Giorno Quattro: a Passo di sandalo

Dettagli tappa
Partenza Caoria, 854 m
Arrivo Rifugio Capanna Cervino, 2084 m
Tappe intermedie Malga Tognola, 1986 m
Lunghezza 21.3 km
Dislivello +1413/-332 m

Tappa molto lunga e faticosa che permette di lasciarsi alle spalle i graniti di Cima d’Asta e di tornare fra i porfidi del Lagorai, prima che questi lascino definitivamente spazio alle chiare dolomie delle Pale di San Martino. Una grandiosa cavalcata dal Vanoi al Primiero, su foreste che sono sempre state la fonte primaria di reddito in quest’angolo riservato del Trentino orientale. Durante il percorso in più occasioni si potrà cogliere questo aspetto, preservato e valorizzato dal Parco Naturale Paneveggio-Pale di San Martino e dall’Ecomuseo del Vanoi. Luoghi silenziosi a pochi passi dall’affollato (in alta stagione) centro di San Martino di Castrozza, boschi e praterie che ospitano una fauna degna di rispetto e che può essere facilmente osservata dall’escursionista discreto e rispettoso. Grandiosa vista sulle Pale di San Martino.

Il passo del titolo è ovviamente Passo Rolle, la meta di oggi e una delle più note nel Trentino turistico. Il cambio di ambiente è netto anche per quanto riguarda la geologia: le celebri Pale di San Martino segnano l’inizio delle rocce dolomitiche, verticali e levigate, piene di buchi e scavate all’interno da torrenti e corsi d’acqua sotterranei.

Partiti da Caoria dopo il comfort di un b&b a cui non eravamo abituati (il bagno privato è un optional), eravamo già preparati ad affrontare la tappa lunga. Grazie alla guida, sapevamo che i primi chilometri sarebbero stati su strada forestale, e ciò voleva dire una cosa: poter posticipare il momento in cui indossare le scarpe. Senza troppa paura, abbiamo imboccato il sentiero calzando i comodi sandali. Dopo alcune baite, siamo ufficialmente entrati nel Parco Naturale Paneveggio Pale di San Martino.

Parco Paneveggio

Il punto di riferimento era la Malga Tognola; raggiuntala, avremmo recuperato tutto il dislivello perso il giorno prima verso Caoria. In 2 ore e 50 minuti abbiamo percorso i 10 km per arrivare allo chalet Malga Tognola: metà tappa a bordo dei sandali! Davvero un lusso.

Fede coi sandali

Breve pausa pranzo con un maxi panino – da un classico menù per sciatori affamati – e poi il momento di cambiarci calzature è arrivato: il tracciato sarebbe stato più sconnesso, su sentieri stretti e meno agevoli di quelli percorsi la mattina. Destinazione intermedia successiva: il passo e i laghi di Colbricon, dove cominceremo ad assistere a un altro cambio di vegetazione con l’ingresso di pini cembri e abeti rossi.

La montagna svenduta

Se c’è un lato negativo che è emerso mentre ci avvicinavamo a Passo Rolle una volta ripartiti dalla Malga Tognola, è stato rendersi tristemente conto che queste zone sono predominio esclusivo di piste e impianti da sci. Ovunque. Ogni due-tre tornanti del sentiero, si passava sotto un pilone della seggiovia, o si attraversava una pista, contando il numero di cannoni da neve con i loro lunghi bracci grigi che si distinguono chiaramente come brutte aggiunte artificiali dell’uomo.

Anche la guida del Sentiero Italia dedicata a questa regione fa notare questo aspetto che un po’ stride con l’immagine di montagna meravigliosa e perfetta che spesso abbiamo1 del Trentino:

Uno dei lati negativi e dei cosiddetti “errori di gestione” riguarda certi valichi alpini, vittime, già in passato, di un’edilizia selvaggia e degna di una qualsiasi disordinata metropoli italiana. In realtà l’impressione è che si sia deciso di sacrificare del tutto quei luoghi, continuando a imbrattarli con nuovi caroselli di impianti che, senza ombra di dubbio, fanno e faranno allontanare sempre più il popolo dei camminatori. Sono scelte che presumibilmente accontentano qualcuno a discapito di altri. L’impressione è quella di una montagna svenduta, o meglio venduta una sola volta, rovinata e non più recuperabile per un turismo meno impattante. Una sorta di prodotto usa e getta.

Un ultimo commento a proposito riguarda il tipo di persone che questo genere di sfruttamento della montagna attira. È come una mensa economica che punta tutto su piatti che piacciono ai più – senza però trascurare la qualità (perlomeno non sempre). La maggioranza di chi verrà, lo farà per assaggiare uno di quei piatti, che lentamente dovranno essere preparati a ritmi quasi industriali. Qualcosa da qualche parte dovrà subirne le conseguenze. Arriveranno quindi persone a cui non interessa conoscere davvero e a fondo l’ambiente che le circonda, non hanno tempo (e forse neanche il fisico o la voglia) di esplorare lentamente valli e forcelle, di fare conoscenza con gli animali autoctoni o le piante tipiche – eccetto forse le erbe con cui si prepara qualche grappa, che si può degustare in uno dei tanti chalet per sciatori.

È volutamente un’osservazione critica questa, ma non serve troppo acume per capire come la pensiamo. Però non è da leggersi come un “verrà il giorno” di manzoniana memoria, ma semplicemente come una presa di coscienza: lo sci da discesa (e attività affini) ha un impatto violento sulla montagna; consuma enormi quantità di risorse (acqua, boschi, elettricità, carburanti). Vogliamo continuare a farlo perché è fonte imprescindibile per il turismo? Va benissimo, ma dobbiamo esserne consapevoli e essere disposti a accettare le conseguenze.


Ci concediamo una breve pausa al rifugio Colbricon per poi riprendere il comodissimo sentiero 348 che, quasi in piano, punta verso Malga Rolle.

Lago Colbricon Noi ai laghi di Colbricon

Usciti dal bosco, c’è un ultimo strappo in salita, in parte sulle piste da sci, per raggiungere Passo Rolle (1984 m), marcato confine geologico – comincia il regno indiscusso di porfidi e dolomie – e climatico (il pino cembro colonizza sostanzialmente questo versante, quello della Val di Fiemme).

Per evitare il luogo un po’ troppo turistico, noi alloggeremo al Rifugio Capanna Cervino, a 2084 metri.

Capanna Cervino

Un edificio vecchio stile che ricorda una baita d’altri tempi, con le pareti riempite di foto storiche della baita, di animali tipici della zona, e ovviamente dei panorami mozzafiato. Quella che segue era infatti la vista dalla finestra del bagno.

Pale panorama

Ci beviamo una birra per premiare degnamente la fatica del giorno, diamo le ordinazioni per la cena, e via diretti in doccia che è l’unico altro desiderio a chiusura della giornata.

Cosa ci aspetta domani

Tappa decisamente scenica e spettacolare, in cui congiungeremo due dei più estesi gruppi delle Dolomiti: le Pale di San Martino e la Marmolada.

C’è però una deviazione nell’aria. Parlando con il cuoco al rifugio Capanna Cervino, ci è stata consigliata una variante che ci porterebbe al Rifugio Mulaz, sotto l’omonima cima (2908 m, superando il primato di Cima d’Asta), per poi percorrere un tratto dell’Alta Via n.2 delle Dolomiti e ricollegarci al Sentiero Italia poco sopra il Passo Valles. Sceglieremo il consiglio di un locale – che cammina al triplo della nostra velocità – oppure rimarremo sul percorso prestabilito?


  1. Con “abbiamo” s’intende chi in Trentino-Alto Adige non ci vive, e in genere chi conosce questa regione da turista. ↩︎

Giorno Tre: varietà

Dettagli tappa
Partenza Rifugio Ottone Brentari, 2475 m
Arrivo Caoria, 854 m
Lunghezza 13 km
Dislivello +84/-1677 m

Altra tappa in ambiente granitico, caratterizzata da un traverso su pietraie dall’aspetto lunare e da una lunga discesa che porta nuovamente verso la catena del Lagorai. L’ambiente è solitario, frequentato solo dagli amanti delle lunghe traversate e dei luoghi lontani dall’affollamento. È questa una montagna scomoda che non ha mai richiamato folle di camminatori, una montagna che ha saputo mantenere la propria primordialità e un fascino che pochi altri angoli del Trentino sanno regalare. Il cammino termina nella Valle del Vanoi, dove il turismo di massa non è ancora giunto e dove la dimensione umana rappresenta ancora un valore da preservare. Come nella tappa precedente l’elemento chiave è l’acqua, raccolta qui in torrenti rumorosi che hanno inciso lunghe valli simili a quelle delle Alpi Occidentali.

Cima d'Asta al mattino

Tappa lunga e tutta in discesa, ma senz’altro una delle più varie. Si parte dai massicci brulli di Cima d’Asta, e dopo un breve sviluppo più o meno in piano tra enormi massi di granito, si percorre il ripido tratto attrezzato che dalla Forcella del Passetto (2490 m) – quasi cinquecento metri di zigzag tra strette tracce che vanno a genio ai camosci, un po’ meno a noi umani – porta alla Forcella della Val Regana (2047 m).

Forcella del Passetto Val Regana

Dopo la forcella si scollina e ci si inoltra lentamente in uno splendido ambiente boschivo. Non sono mancate più di una traversata di prati con erba più alta di noi (non poco fastidiosa, chiediamo scusa per le poche foto). L’ambiente così ricco di verde ci ha anche regalato una pausa merenda a base della tanto agognata frutta.

Mirtilli

Entracte: le occasioni della vita

Dopo il lungo tratto verticale del sentiero Gabrielli – là l’attenzione era concentrata sul mettere i piedi nel posto giusto e le mani su sassi che non si muovessero, almeno nel primo pezzo – abbiamo aperto la seguente discussione. Io, Edoardo, con tono volutamente polemico, ho detto che la vita ti dà le buone occasioni nei momenti sbagliati. Esempio: conosci una persona nuova che ti comincia a interessare un po’ (non per forza nel senso di un coinvolgimento sentimentale), ma poi non ci sono davvero le condizioni per poter andare oltre quel primo incontro fortuito. È come se la vita ti facesse desiderare un gustoso piatto di tagliatelle al ragù, dopo una faticosa salita, per poi servirti della carne in scatola senza neanche il contorno.

Federico ha cercato di riportare la discussione sul piano della realtà. Non è sempre così forse? Non è proprio come diceva Seneca? La fortuna non esiste: esiste soltanto il momento in cui il talento (o la preparazione) incontra l’occasione.

Abbiamo poi raggiunto una conclusione su cui eravamo entrambi d’accordo: sappiamo che cercare un lavoro costa fatica, che ottenere un titolo di studio costa fatica, ma sembra ci siamo dimenticati che coltivare delle buone relazioni e trovare le persone con cui vale la pena farlo costano anch’esse impegno e tempo. Forse dovremmo ripetercelo più spesso.


Seguendo un torrente sempre all’ombra (benedetta, vista la giornata molto calda) del bosco, il sentiero conduce alla strada forestale. In più punti ci siamo chiesti se valesse la pena fermarsi in una di quelle pozze cristalline per ristorare i piedi, ma abbiamo preferito resistere fino alla fine per non dover più rimettere gli scarponi.

Dolci Acque

Tra chiacchiere di politica e energia nucleare, su comoda strada forestale sbuchiamo nel piccolo abitato di Svaizera (Edo giura di aver letto “Svizzera” la prima volta, chiedendosi come potesse essere così vicina), con malghe e baite di legno perlopiù adibite a fienili (alcune in vendita, se può interessare). Neanche ci accorgiamo che un ultimo strappo in discesa ci ha finalmente portato a Caoria (ripasso: l’accento è sulla “i” per i non veneti), così cerchiamo la prima fontana per il troppo rimandato pediluvio ristoratore. Un signore locale, stupito di trovare due persone immerse nella fontana del paese, si è pure preoccupato che non ci prendessimo una broncopolmonite, ma noi eravamo troppo in estasi per dargli retta.

Fontana

Cosa ci aspetta domani

Altra tappa discretamente lunga con cui abbandoneremo il granito di Cima d’Asta per avvicinarci al calcare delle Dolomiti. Sarà quasi l’opposto di quella di oggi, prevalentemente tutta in salita fino alla quota in cui intravedremo le celebri Pale di San Martino intorno a cui faremo un bel tour tra la quarta e la quinta giornata. Di foto-cartolina ce ne saranno un po’, speriamo.

Giorno Due: respira, sei in Trentino

Dettagli tappa
Partenza Rifugio Malga Consèria, 1848 m
Tappe intermedie Cima Socéde, 2173 m (Sentiero della Memoria)
Arrivo Rifugio Ottone Brentari, 2475 m
Lunghezza 8.2 km
Dislivello +1017/-375 m

Breve tappa che porta nel cuore pulsante del gruppo di Cima d’Asta, sotto la formidabile Parete Sud della vetta principale, una grandiosa bastionata che precipita fin sulla scura superficie del famoso e omonimo lago alpino. È questo un mondo di granito, simile, almeno come tipo di ambienti, a quello del Lagorai, ma molto diverso dalle vicine Dolomiti. Una caratteristica che salta immediatamente all’occhio è l’elevata presenza di acqua superficiale dovuta all’impermeabilità del substrato roccioso. Zone umide, pietraie, fitti boschi e lunghi solchi vallivi, queste sono le meraviglie di un angolo di Trentino che preserva ancora un’elevata naturalità e una relativamente bassa frequentazione umana, intaccata solo nei pressi del Rifugio Brentari, il più noto e frequentato punto di appoggio di questa area montana.

Dopo una colazione a buffet con yogurt di malga, salutiamo il rifugista (che ci offre pure la doccia) e ci avviamo sull’ultimo tratto del sentiero che geograficamente si trova nella zona del Lagorai. Dopo un paio di alpeggi, arriviamo al Passo Cinque Croci dove troviamo il primo bivio e la prima scelta: saliamo a dare un’occhiata al piccolo museo aperto dedicato alle tracce della Grande Guerra o tiriamo dritto1?

La prima guerra

Quattro anni di lavoro hanno permesso di restaurare alcuni resti del primo conflitto mondiale che ha toccato anche il Lagorai. La cima Socéde è uno di quei luoghi in cui è ben visibile il passaggio: ci sono alcune trincee in legno e un paio di rifugi militari che si incontrano lungo il Sentiero della Memoria.

Trincea Cima Socede

Nulla a che vedere con ciò che si può visitare – o percorrere – nelle zone del Pasubio, ma è prezioso essere riusciti a recuperare anche questi reperti. Peccato non siano molto visitate perché in questa zona si è davvero in solitaria. Non neghiamo di aver temuto un po’ di dover lasciare gli zaini a un ricovero di pastori per fare la salita e discesa in leggerezza, ma nessun essere umano si è fatto vivo.

Dipendenze

Lagorai wilderness

Gli aurai alpini della zona – i numerosi specchi d’acqua che si trovano frequentemente e da cui arriva il nome Lagorai – hanno ispirato un’interessante digressione sulle dipendenze, non soltanto quelle da qualsiasi sostanza. Quali sono? Quante sono? Come le riconosciamo? Non tutte sono dannose, anzi: senza il meccanismo alla base di ogni dipendenza, regolato dalla dopamina, non ci alzeremmo dal divano neanche per mangiare. Però internet, i social, e chissà quale altra invenzione moderna ci hanno assuefatto in due modi almeno2:

  1. Ci hanno fatto dimenticare il piacere differito, la cui ricompensa va sudata e attesa, rendendoci sempre più esigenti sulla quantità di piacere che pretendiamo.
  2. Hanno ridotto enormemente la nostra soglia del dolore, o meglio del fastidio che siamo disposti a sopportare. Sempre più emozioni, situazioni, relazioni con altre persone ci risultato insopportabili troppo rapidamente.

Il rifugio Brentari

Cercando di non perdere la traccia del sentiero – sempre ben segnato, ma qualche volta non proprio visibile – arriviamo alla Forcella Magna.

Forcella Magna

Alla forcella ci accoglie uno strano odore di pesce. Prima di prendere di petto la salita che ci attende, decidiamo di recuperare energie e di mangiare qualcosa. La salita davanti a noi si presenta subito impervia, ma dopo pochi tornanti, il sentiero ritorna più sopportabile. Arrivati a un bivio, imbocchiamo il sentiero 326. Pochi passi e il sentiero si butta letteralmente verso il cosiddetto boalon (canalone) di Cima d’Asta, e perdiamo quota velocemente e anche rovinosamente per uno di noi (giusto un piccolo taglio sulla tibia). Ora siamo sul sentiero 327 in direzione rifugio Cima d’Asta. Vediamo già le bandiere sventolare, e anche i piloni della teleferica ci indicano che il rifugio è vicino. Mentre camminiamo, cominciamo già a fantasticare su cosa mangeremo al rifugio. Finalmente davanti a noi appare il magnifico lago di Cima d’Asta3 e appena oltre anche il rifugio si delinea nella sua interezza.

  • Lago Cima d'Asta
  • Rifugio Brentari
  • Pensatori

Le montagne di fuoco

Neanche a farlo apposta, al Brentari incontriamo tre geologi che sono in giro per dei campionamenti. Non in vacanza, ma senza dubbio il loro “ufficio” è di gran lunga migliore del mio. Ci raccontano brevemente che le vicine Dolomiti, generatesi in parte da barriere coralline – Ma c’era il mare qui? Eh già – sono bimbe giovani in confronto al gruppo granitico di Cima d’Asta, le cui rocce hanno sicuramente origine vulcanica (tecnicamente si chiamano ignimbriti). È pazzesco pensare – e ci ricorda anche della nostra insignificanza come esseri umani – che qualche centinaia di milioni di anni fa qui si avrebbe potuto assistere (per modo di dire) a vaste e potenti eruzioni vulcaniche i cui prodotti, solidificatisi lentamente e in profondità, hanno dato origine alla materia di cui è fatta Cima d’Asta. Tutto questo in un tempo che supera largamente i nostri duecentomila anni di esistenza (come Homo Sapiens).

Dopo qualche minuto di contemplazione (senza più gli zaini sulle spalle), ci siamo seduti a gustare due piatti di tagliatelle al ragù di cervo, e poi via con le sole bacchette per salire sulla vetta più alta che avremo modo di avvicinare in questa lunga traversata trentina. Il cielo un po’ coperto – in una giornata tersa si dovrebbe riuscire a vedere il Mar Adriatico e l’Appennino – ma un paio di foto ce le ha concesse.

  • Vetta Cima d'Asta
  • Bivacco Cavinato

Senza indugiare oltre, riprendiamo il sentiero della salita e rientriamo alla base sempre in un’ora, chiedendoci più volte come sarebbe vedere l’alba da lassù. Ce la proveremo a immaginare con qualche grappa tipica dopo cena, socializzando un po’ con gli altri inquilini (e pregando che nessuno dei compagni di stanza russi troppo!)

  • Brentari bar
  • Cima d'Asta al tramonto

Cosa ci aspetta domani

Altra tappa non troppo lunga (circa 13 km) ma soprattutto tutta in discesa: dai 2475 metri del rifugio Brentari agli 854 del paese di Caorìa (metto l’accento per i non veneti). Forse sarà anche la tappa più difficile tecnicamente: valutata EE, percorreremo un pezzo del sentiero attrezzato G. Negrelli, che passa sotto una cresta dal confortante nome: Cresta delle Streghe.


  1. Guardando una mappa più tardi, scopriamo che c’era un sentiero di collegamento. Ma vuoi mettere l’ebbrezza di lasciare giù lo zaino per una mezz’ora? ↩︎

  2. In particolare, abbiamo parlato del libro Dopamine nation di Anna Lembke↩︎

  3. Il lago di Cima d’Asta, con i suoi 91'000 metri quadrati di superficie e una profondità massima di 38 m, è tra i più grandi in Europa a questa quota. È anche la fonte di energia primaria del rifugio che, possiamo dirlo, funziona al cento per cento con energia rinnovabile grazie a una turbina a valle che attinge direttamente dal lago. Purtroppo, l’eccezionale siccità e le ondate di caldo precoci anche in quota di quest’anno hanno fatto scendere il livello del lago di circa 60 cm (parole del rifugista). ↩︎

Giorno Uno: la Magnifica Fiemme e il selvaggio Lagorai

Dettagli tappa
Partenza Molina di Fiemme, 853 m
Arrivo Rifugio Malga Consèria, 1848 m
Lunghezza 20.7 km
Dislivello +1508/-520 m

Lunga tappa, con primo tratto su asfalto, che dalla Val di Fiemme, nota per le sue estese foreste, porta nel cuore pulsante del Lagorai, il gruppo montuoso più selvaggio del Trentino. E proprio in questo tipo di ambiente si svolge la prima parte dell’escursione, lasciando spazio in quota a praterie alpine e “aurai”, i minuscoli specchi d’acqua che hanno dato il nome all’intero gruppo. Fra queste scure cime la presenza antropica è marginale, con alcune zone che raramente vengono calpestate da piede umano. Un vero paradiso per gli amanti dei silenzi e di quella natura apparentemente meno spettacolare che pian piano sa conquistare il cuore anche dei camminatori più esigenti1.

Inizio senza paura con la tappa più lunga del giro (21 km e 1600 m di dislivello positivo), lo sforzo nelle gambe alla fine non si è fatto pregare troppo. Partenza con le marce alte, quindi.

Dopo aver attraversato il paesino di Molina di Fiemme, abbiamo percorso la Magnifica valle affiancando il torrente Cadino su una strada asfaltata (un po’ noiosa, e sempre al sole ben caldo di luglio) fino al Ponte delle Stue.

Molina di Fiemme

Là comincia il sentiero vero e proprio, che fino alla Malga Cazzorga è stata una carrozzabile sterrata comoda. Qui i boschi di abeti e pini del Lagorai ci hanno regalato più volte un bel sollievo dal sole. Ma ciò che ci ha stupito di più è stato notare, anche qui, i danni devastanti della tempesta Vaia del 2018. Su alcuni pendii o versanti sembra sia passata un’enorme falce affilatissima che ha tagliato alla base qualunque albero o arbusto più alto di qualche metro. Davvero impressionante.

Sentiero 318

Il sentiero ha toccato il punto più alto presso la Forcella Valsorda (nome interessante), per poi fare un saliscendi fino al Passo Val Cion.

Forcella Valsorda

Avevamo preso un buon passo spedito, perciò non ci siamo fermati a contemplare gli alpeggi del Lagorai, complice anche un vento freddino che ci ha fatto compagnia finché abbiamo scollinato. Gambe e schiena – con un inusuale zaino da 8 chili circa – erano ben stanche da chiederci di tirare dritto fino al rifugio, sperando nella possibilità di fare una doccia calda più che poterci connettere a internet per dire che eravamo vivi (la rete cellulare non prendeva neanche per una chiamata 🆘 ). Entrambi i comfort ci sono stati garantiti. Dieci minuti e si fanno le ordinazioni della cena (zuppa di verdure e spezzatino con polenta). Si poteva chiedere altro?

Malga Conseria

Cosa ci aspetta domani

Tappa abbastanza corta: circa 8 km e quasi 800 metri di dislivello positivo. Sperando di non avere troppa stanchezza residua, sarà una tappa breve e rapida. La meta sembra essere particolarmente interessante e l’ambiente suggestivo: il rifugio Brentari circondato dalle pareti granitiche verticali di Cima d’Asta (che proveremo a salire, senza zaino dovrebbe essere fattibile in circa un’ora).

A domani2!


  1. Dal volume 11 della collana Sentiero Italia CAI di Denis Perilli e Lorenzo Comunian, Idea Montagna Edizioni, pag. 105. ↩︎

  2. Pare che il mio socio sia troppo provato dalla tappa di oggi. Appuntamento con lui a domani, promesso ↩︎

Giorno Zero: verso il campo base

Forse campo base è un po’ impropria come definizione: Bolzano è soltanto a 262 metri di altitudine, ma sarà comunque il nostro appoggio iniziale. Domani mattina un treno e un autobus ci porteranno in Val di Fiemme, il vero punto di partenza.

Per quanto questo Sentiero Italia 2022 non sarà un’impresa alpinistica ambiziosa, proveremo a fare una cosa che un pochino lo sarà: qui su queste pagine (tag #sentiero italia) terremo un diario di viaggio a due1, qualche riga in cui raccontare la giornata, cosa abbiamo visto, di cosa abbiamo parlato, le nostre impressioni o emozioni. E se la connessione internet ce lo permetterà, anche qualche foto. Sono già convinto che verrà fuori qualcosa di interessante.

Si parte! 🏔

P.s. I will translate all these pages in English after coming back. Because non-Italian readers are more than welcome!


  1. Ammetto che l’ispirazione l’ho avuta riguardando il film di Luis Buñuel La Via Lattea. Okay, decisamente ambizioso come modello, e non penso certo di raggiungere quei livelli. Ma ho detto che sarà solo un’ispirazione, no? ↩︎