More adventures in bicycling

I went out this morning intending to ride between 30 and 40 miles.  At about 8 miles I ran over a piece of glass, which somehow made it through my Gatorskin tire and punctured the tube.  Disappointing, but it doesn’t happen too often.  My last flat was back in July.

A flat tire isn’t normally a big deal.  I typically carry at least one spare tube, plus a patch kit.  I hate being stranded.  This morning, though, it was a problem.  You see, the first spare I pulled out was a new tube fresh out of the box.  Well, “fresh” in that I hadn’t used it yet.  It’s been in my seat bag for the last four months.  It wouldn’t hold air.

Undeterred, I grabbed the second spare that was in the seat bag.   That one was just stuffed into the bag, kind of like how I’d stuff a punctured tube in the bag after changing it out.  But a quick test showed that it would hold air, so I installed it, pumped up the tire, put my bike back together, and continued my ride.

For about two miles.

It turns out that the tube I installed is the one that punctured back in July.  It had a slow leak.  When I got home that day, I just put the new tube in the bag and forgot about fixing the old one.

I rummaged through the seat bag, pulled out the patch kit and the tube that was punctured a few moments before, found the hole, roughed up the rubber, opened the tube of vulcanizing compound and … nothing.  Damn!  That stuff has a tendency to dry up and it’d been in the seat bag all summer.  So I’m left with patches but no vulcanizing compound.  I considered trying to slap a patch on, depending on just the glue to hold it, but decided against the experiment.  Instead, I pumped up the tire (the one with the slow leak) and headed for home.

It’s kind of frustrating, having to stop every mile and a half in order to add more air.  But it beats walking barefoot, pushing the bike.  Walking any distance in those cycling shoes is not an option.

So my “30 or 40 mile” ride turned into 19 miles, more than half of which was done on a leaky back tire.

I obviously need to pay more attention to my emergency supplies.  I get flats so rarely that I’ve become complacent.  What was an inconvenience this morning could have been a very uncomfortable walk home.

I’ve been riding in the middle of the day the last few weeks, and often “in town” rather than out on the county roads.  I forgot how aggressive drivers can be.  Every ride in town includes incidents of drivers purposely cutting me off (typically to make a right turn), or failing to see me even though I’m wearing very bright colors.  I think I’ll re-think the idea of riding in town.  It’s too dangerous.

The prevalence of stop signs and traffic lights is also very frustrating.  Out of town, even the major roads will have maybe one traffic light every few miles, and the county roads have no lights and very few stop signs.  There are places where I can ride more than 10 miles without seeing a car.  It’s a much nicer environment for riding.

I’m closing in on my 20,000 mile goal.  After today’s ride, the computer reads 19,460.  I had hoped to have 19,500 before Thanksgiving because I’ll be out of town over the weekend.  That would give me just shy of five weeks to ride 500 miles:  easily doable.  I’ll get a ride in tomorrow, but I’ll probably be 10 miles or so shy of 19,500.  Provided the weather doesn’t turn too terrible in December, I’ll be at 20K before the new year.

And then I’ll back off on the bicycling for a bit.  I need to get into the gym and build a little upper body strength.  Contrary to what many think, bicycling does require some strength in the arms and the core muscles.  I experienced some lower back pain during longer rides this year, most likely because I haven’t been doing enough sit-ups and back extensions.  I’m planning some much longer rides for next year, so it’s time to build up those muscles.

The past two weekends, I attended free training workouts with Austin Cycle Camp.  The first weekend was a speed workout combined with some cornering drills.  This past weekend we did hills, working on maintaining a steady cadence and also on form.  I picked up some good tips, and hope to engage their coaching services next year when I start training for my big rides.  I’d like to get my century time down to under six hours.  That shouldn’t be too tough.  The harder one will be a 12-hour double century.  Yeah, I’m crazy like that.

Comparing ranges is harder than it looks

I’m developing a generic Range class in C# so that I can create comparison ranges.  The idea is that I can replace code like this:

int MinValue = 22;
int MaxValue = 42;
...
if (val >= 22 && val < 42)
{
}

with this:

Range<int> MyRange = new BoundedRange(
    22, RangeBoundType.Inclusive,
    42, RangeBoundType.Exclusive);
...
if (MyRange.Contains(val))
{
}

In isolation it doesn’t look like a win but if you’re doing that range comparison in multiple places or working with multiple ranges, some of which can have an open-ended upper or lower bound, or  bounds that can be inclusive or exclusive, working with a Range type can save a lot of trouble.

Before we go on, let me introduce a little bit of notation.

First, the characters ‘[‘ and ‘]’ mean “inclusive”, and the characters ‘(‘ and ‘)’ mean “exclusive.”  So, assuming we’re working with integral values, the range [1,30) means that the numbers 1 through 29 are in the range.  Similarly, (1, 30] means that the numbers 2 through 30 are in the range.

To specify “unboundedness,” I use the character ‘*’.  So the range [*,255] means all numbers less than or equal to 255.  And, of course, the range [*,*] encompasses the entire range of values for a particular type.  By the way, inclusive and exclusive are irrelevant when unboundedness is specified.  That is, [*,255] and (*,255] are identical ranges.

Range type also allows me to do things like compare ranges to see if they overlap, if one contains the other, etc. And therein lies a problem. Consider the two byte ranges [0,*] and [*,255].

It should be clear that, since the range of a byte is 0 through 255 (inclusive), the two ranges are identical. The first range has a lower bound of 0, inclusive, and is unbounded on the upper end.  The second range has defined bounds of 0 and 255.  As programmers, we can tell by inspection that the two ranges are identical.

Unfortunately, there’s no way to write generic code that can determine that the ranges are equivalent.  Although the primitive types available in C# all have defined maximum and minimum values (Int32.MaxValue and Int32.MinValue, for example), not all types do.   And since I might want to have ranges of strings or other types that don’t have defined bounds, there’s no general way to tell the difference between a range that has no defined upper bound and a range whose upper bound is the maximum possible value for that type.  If I wanted that ability, the only way would be to pass maximum and minimum possible values for each type to the Range constructor–something that I’m not willing to do and might not even be possible.  What’s the maximum value for a string?

The inability to determine that an unbounded range is equivalent to a bounded range makes for some interesting problems. For example, consider the two byte ranges [1,*] and [0,255].  It’s obvious to programmers that the second range contains the first range. But how would you write a function to determine that?

public bool Contains(Range<T> other)
{
    // returns true if the current range contains the other range
}

Since there’s no way to convert that unbounded value into a number, the code can only assume that the upper bound of the first range is larger than the upper bound of the second range. Therefore, Contains will return false.

Whether that’s an error is a matter of opinion.  Logically, having Contains return false in this case is the correct thing to do because “unbounded” is larger than any number.  But it seems like an error in the context of types like byte that have limited ranges, because there’s really no such thing as an unbounded byte.  Rather, byte has a maximum value of 255 and one would expect the code to know that.

As I said, it’d be possible to extend the Range class so that it knows the minimum and maximum values for the primitive types, and give clients the ability to add that information for their own types if they want.  That way, an unbounded upper value for an integer would get  Int32.MaxValue.   The code would then “do the right thing” for the built-in types, and clients could define minimum and maximum values for their own types if they wanted to.

But I wonder if it’s worth going to all that trouble.  Is it more sensible to explain the rules to programmers and expect them to define specific bounds (i.e. not use unbounded) if they think they’ll be working with ranges (as opposed to comparing values against ranges) of primitive types?

It’s more than miles

With a little more than seven weeks to go before the end of the year, I have to ride another 750 miles in order to achieve my goal of having 20,000 miles on the bike.  I’ll reach that goal, but I’ll admit that my motivation to do so has waned.

The primary reason I ride my bike is because I enjoy it.  More to the point, I enjoy setting long-term goals that force me to push my comfort zones–stretch to accomplish them.  In the context of bicycling, meeting those goals requires that I develop a training schedule and stick to it, improving my fitness and endurance a little at a time so that I’m prepared when the big event comes.  The training invariably involves riding a lot of miles, but the miles aren’t the point:  they’re a byproduct of the training.

Just “putting in the miles” is not effective training.  Doing long slow rides every day does very little in terms of increasing fitness.  It’s pointless exercise.  There’s nothing wrong with it, but it’s not going to increase my speed, build my ability to climb or sprint, or even make a difference in how far I can ride.  If I just want to get up and move, I’ll take Charlie for a walk.  Long slow distance is boring and pointless.

Bicycle training (and other types of physical training) involves three types of workouts:  base, overload, and recovery.  All three types have specific purposes.

In bicycle training, base mileage workouts are designed to build endurance, get you accustomed to spending hours in the saddle, learning how to measure your effort so that you can maintain a strong pace throughout the distance.  These rides are long steady distance, but also involve some high-heart rate efforts (climbing, for example) and periods of rest and recovery on the bike (after a hard effort).  Base mileage is the foundation.  It builds endurance and gives you a foundation on which you can build strength and speed.

Note that I said long steady distance rather than long slow distance.  The difference is that base mileage workouts are not necessarily (or even often) slow.  Most LSD rides are done at a medium aerobic effort, with some forays into high aerobic effort.  More infrequently, I’ll do an LSD ride at high effort and throw in some sprints or hill that push me into anaerobic territory.  “Slow” doesn’t usually enter into the equation.  I’m tired when I’m done with an LSD ride, but not completely exhausted.

“Overload” rides usually involve a lot of sprints and hill repeats, or a time trial that I ride as fast as possible.  These workouts are designed to push my body further than I’ve pushed it before.  I want to climb a larger hill, sprint faster, complete the time trial in less time.  When I’m done with one of these rides, I’m beat.  My legs are shaking, and climbing the stairs to the office is difficult.  These hard efforts “tear down” the muscles in my legs so that they can be rebuilt stronger.  Pushing my heart up to and beyond my lactate threshold increases the body’s ability to use oxygen and break down sugars for energy, and over time will actually increase the lactate threshold meaning that my aerobic range increases.

And then there are recovery rides.  Some coaches say that recovery is the most important part of training.  Base mileage is the foundation that allows you to do overload rides.  Recovery is the time when you let the body rest and rebuild after the overload ride.  Recovery for me is a combination of rest (taking a day off) or doing a slow ride for an hour or two, just to keep the muscles limber and the blood pumping.  A recovery ride involves sub-aerobic (i.e. “fat burning”) or low-aerobic effort.  Even so, my recovery rides aren’t just “slow distance”.  I use my recovery rides to practice bike handling skills, work on my pedaling form, test out different riding postures, etc.  And, of course, sit back and enjoy being outside, perhaps chatting with other cyclists who I encounter.

Those rides have specific purposes, and my overall training plan has a specific purpose:  to prepare me for whatever event I have in mind.  And it works.  I’ve used those training plans to train myself for many different events, and I used something very similar to help Debra go from not riding at all to completing a three-day, 335-mile ride in just a year of training.  The key is to make every ride count.

The problem is that my season has ended now.  I have events planned for next year, but I’m not going to start training specifically for them until late February.  I’ll continue to ride a bit, but this is the time I should be in the gym working on core and upper body strength.  Extreme endurance rides take a toll on the neck, arms, stomach, and back (especially the lower back), and I need to build strength in those areas if I want to meet next year’s goals.

Unfortunately, I’ve announced that 20,000 goal and I need to ride 100 miles per week until the end of the year in order to meet it.  And since I don’t have a particular event in mind–something I’m working towards–those miles are “just exercise”:  putting in the miles.  Thus my diminished motivation.

So if it’s more than miles, why do I talk about miles at all?  Because it’s a reference that will mean something to cyclists and non-cyclists alike.  Most non-cyclists will automatically assume that a 50 mile ride is harder than a 25 mile ride.  They won’t generally understand that the 10 hill sprints on the 25 mile ride made it much more difficult than the 50 mile ride at medium effort.  Another cyclist, though, who knows me and has an idea of my current fitness level, will infer quite a bit of information from a simple post about how many miles I rode this morning.  He’ll know that a 50 mile ride was probably base mileage, that a 10 mile ride was recovery, and anything in between was most likely overload:  sprints, hills, or time trial.

As for next year’s events:  nothing specific to announce yet.  I will say, however, that I’m planning at least one ride that’s longer than anything I’ve ever done before.