Thursday, December 22, 2011

Saucony Hattori review

I've just bought a pair of Saucony Hattoris and they really good!



They're minimal, but have a lot more cushioning than Vibrams or the Evos since the EVA+ sole is quite soft and about 10mm thick. They're zero-drop and ultra light weight (250g/pair), about half the weight of the Evos and lighter than Vibram Sprints.

They're a really comfy fit, with no laces they are held on by a tight, thin "lycra" upper. Mine are maybe a little on the small side, so the velcro straps don't do anything useful.

The tight fitting upper has another advantage that no other shoes I've got come close too: It's virtually impossible to get sand in them, which is great as that's extra annoying when running sock-less.

Time will tell how the sole wears, but the hard reinforcements are in all the places I usually wear through, so I can't see why they won't last a fair while.

[Update, 7-June-2013] It slipped my mind to do an update on these, but I've been wearing them on my shorter runs pretty much all the time over the last 18 months. They've racked up more than 1,800km and though getting quite worn I'm sure they'll go past 2,000km without any problems.

As I suspected, I bought them a tiny bit too small, which has occasionally given me a blister on the tips of my toes and I've now got a couple of holes in the upper where my big toe sticks out. This doesn't cause any problems however and the extra ventilation can't hurt!

They get smelly fairly quickly, but washing them in warm water with a few tablespoons of white vinegar seems to clean them up nicely.

They're a great shoe & fantastic value for money.

Friday, August 12, 2011

Please unsubscribe me from the World Vision newsletter

God knows I've tried enough times, maybe posting it to a blog is how you get off the list?

Sunday, August 07, 2011

Terra Plana Evo review

My Vibrams are worn out (or through) so after having a good experience with the Merrell Trail Gloves I decided to get a pair of Terra Plana Evos.

It's a pain to get Vibram FiveFingers in Australia at the moment. They're hard to find in shops, can't be shipped here from the USA and they're about twice the price even though our dollar is currently trading higher than the USD.

The Evos are more expensive than the Vibrams but a little less "freaky" and provide a similar minimal experience to the Merrells. That is, your toes are free, there's no support or cushioning and you get a fair degree of "ground feel".

I considered a pair of Merrell True Gloves (the "road" equivalent of the Trail Gloves) but they had too much cushioning for my liking and unlike the Evos, they didn't have removable inner soles.

I bought them in the black/red style, which was probably not that smart. They contrast too much against my skin and tend to look a bit odd, they're a very small shoe and black emphasises that.

One thing to note, is that the women's model is identical to the men's, but quite a bit cheaper! Unfortunately they only go up to size 41, but it's something to take advantage of if you have small feet. Speaking of which, the Evos are sized pretty small, the 42 is plenty big enough for me, which is a size or two smaller than my regular shoes.

The lacing is the same as for the Merrell Trail Gloves, holding snuggly to the middle of the foot and leaving your toes free to splay. They don't lock onto my heel as nicely however and they tend to feel a little loose after running a few kms.

They are a minimal shoe and still a long way from barefoot, with less ground feel than Vibrams, even wearing them without socks and taking out the inner soles. Still, you feel pebbles and the contrast between concrete, asphalt, gravel, dirt, grass surfaces well enough and it doesn't seem to interfere with my stride. They don't have a lot of grip however and slip pretty easily if it gets muddy. While they'd probably do fine on dry trails, I don't think they feel very suitable for general trail running.

Not wearing socks did cause some significant rubbing issues however. That was partly due to me jumping straight into 12km runs with them, and I have to resort to prepping with vaseline. It's definitely something to be aware of as they press on different parts of your foot than the Five Fingers do.

I've done about 85km in them now and they feel good. They don't feel like they'll wear out too quickly, aren't too cold (though our winter has been fairly mild so far), and don't soak up water between the toes like the Five Fingers. They feel like they'll be fine in warmer weather too, the upper is a very thin and breathable mesh.

Overall, other than the price, they're great and I'd recommend them to any experienced minimalist shoe runners.

Wednesday, June 22, 2011

No, wait, that's not right, here's how I really solved it.

Yesterday I posted the solution to a puzzle in response to one created by Reilly. The solution is fine, but I explained it badly. The explanation just describes the finished code, which is all well and good, but it doesn't elucidate the steps I took to get there and isn't likely to help anyone as a result.

The following steps are much closer to what I actually did:

1. While reading Reilly's Prolog version I realized that SQL could probably solve the puzzle by generating a list of all the possible combinations of pieces (either by a join or in a temporary table) and then filtering those in some way to remove invalid solutions.

2. I left it at that for a while, but a few thoughts popped into my head during the day on the structure of a "pieces" table and an INSERT statement that could generate the 4 possible rotations of each piece. I also ran the numbers in my head and realized there were 4^9 = 2^18 = 262,144 combinations which is not many at all really.

3. I initially ran into a bit of a dead end imagining how a SELECT statement would generate all the combinations of pieces, but decided to just start writing it out and see where that led.

This was the crucial step: Starting with the desired result and working backwards.

So, I started with what I wanted: A list of piece numbers and rotations in each position of the puzzle:

SELECT A.piece_id AS A, A.rotation AS Ar, B.piece_id AS B, B.rotation AS Br, C.piece_id AS C, C.rotation AS Cr,
       D.piece_id AS D, D.rotation AS Dr, E.piece_id AS E, E.rotation AS Er, F.piece_id AS F, F.rotation AS Fr,
       G.piece_id AS G, G.rotation AS Gr, H.piece_id AS H, H.rotation AS Hr, I.piece_id AS I, I.rotation AS Ir

Then I started joining tables together to match the constraints of the puzzle (i.e. the animals on the adjacent edges match head-to-tail.) At this point I didn't know what fields were going to be in the table, or what it would be called, so I just made them up so the SELECT statement read nicely. First, I'll show the overall structure and come back to the "matches" bits:

FROM rotated_pieces A 
INNER JOIN rotated_pieces B ON -- A.right matches B.left --
INNER JOIN rotated_pieces C ON -- B.right matches C.left --
INNER JOIN rotated_pieces D ON -- A.bottom matches D.top --
INNER JOIN rotated_pieces E ON -- D.right matches E.left AND B.bottom matches E.top --
INNER JOIN rotated_pieces F ON -- E.right matches F.left AND C.bottom matches F.top --
INNER JOIN rotated_pieces G ON -- D.bottom matches G.top --
INNER JOIN rotated_pieces H ON -- G.right matches H.left AND E.bottom matches H.top --
INNER JOIN rotated_pieces I ON -- H.right matches I.left AND F.bottom matches I.top --

My "matches" criteria was initially something like:

(   (A.right = B.left AND A.right_head = 'head' AND B.left_head = 'tail')
 OR (A.right = B.left AND A.right_head = 'tail' AND B.left_head = 'head'))

This makes sure the animals are the same and it's either head-tail or tail-head.

That seemed like it might work which was a pretty good sign I was on the right track. I wasn't sure how many combinations this would match, so decided to leave a WHERE clause for later. I was hoping this would be a unique solution, or there may be just a couple and I could pick the proper solution out by hand. Either way, that was a problem for later.

4. From this sketch of a SELECT statement I was able to come up with an appropriate table structure for rotated_pieces:

CREATE TABLE rotated_pieces (
  piece_id     INTEGER, # unique piece id
  rotation     INTEGER, # 0 - top, 1 - left, 2 - bottom, 3 - right
  top         CHAR(10), # animal at top edge
  top_head    CHAR(10), # head or tail at top edge
  `right`     CHAR(10),
  right_head  CHAR(10),
  bottom      CHAR(10),
  bottom_head CHAR(10),
  `left`      CHAR(10),
  left_head   CHAR(10));

And then I started on an INSERT statement to populate the table with the piece layouts:

INSERT INTO rotated_pieces 
       (piece_id, rotation, 
              top,       top_head, `right`,   right_head, bottom,    bottom_head, `left`,    left_head) 
VALUES (1, 0, 'cheetah', 'tail',   'tiger',   'tail',     'lion',    'head',      'tiger',   'head'),
       (2, 0, 'lion',    'tail',   'lion',    'head',     'tiger',   'tail',      'cheetah', 'head'),
       (3, 0, 'tiger',   'tail',   'lion',    'head',     'panther', 'head',      'tiger',   'tail'),
       (4, 0, 'panther', 'tail',   'cheetah', 'head',     'panther', 'tail',      'lion',    'tail'),
       (5, 0, 'tiger',   'head',   'tiger',   'head',     'cheetah', 'head',      'lion',    'tail'),
       (6, 0, 'panther', 'tail',   'panther', 'head',     'cheetah', 'tail',      'tiger',   'head'),
       (7, 0, 'panther', 'head',   'cheetah', 'tail',     'cheetah', 'head',      'lion',    'tail'),
       (8, 0, 'panther', 'tail',   'lion',    'head',     'panther', 'head',      'cheetah', 'tail'),
       (9, 0, 'cheetah', 'head',   'tiger',   'head',     'panther', 'head',      'lion',    'tail');

While I was doing this I copy/pasted Reilly's equivalent bit of Prolog code and it was a simple text transformation between the two languages, another very good sign:

Prolog:
tile(1,     cheetah_tail,     tiger_tail,     lion_head,     tiger_head).
SQL:
    (1, 0, 'cheetah','tail', 'tiger','tail', 'lion','head', 'tiger','head'),

5. At this point, I realized that the "matches" criteria could be simplified a lot:

A.right = B.left AND A.right_head != B.left_head

6. Now I was able to write out the "rotation" function I'd envisioned earlier in the day and realized I wasn't going to need a "pieces" table at all, this program was only going to need the 36 rotated_pieces records, another good sign that I was on the right track.

# rotate (top --> left)
INSERT INTO rotated_pieces (piece_id, rotation, top, top_head, `right`, right_head, bottom, bottom_head, `left`, left_head) 
  SELECT piece_id, rotation+1, 
         `right` AS top, right_head AS top_head, 
         bottom AS `right`, bottom_head AS right_head, 
         `left` AS bottom, left_head AS bottom_head, 
         top AS `left`, top_head AS left_head 
    FROM rotated_pieces;

# rotate (top --> bottom, left --> right) 
INSERT INTO rotated_pieces (piece_id, rotation, top, top_head, `right`, right_head, bottom, bottom_head, `left`, left_head) 
  SELECT piece_id, rotation+2, 
         bottom AS top, bottom_head AS top_head, 
         `left` AS `right`, left_head AS right_head, 
         top AS bottom, top_head AS bottom_head, 
         `right` AS `left`, right_head AS left_head 
    FROM rotated_pieces;

7. Finally, I had all the code sketched out. I checked the syntax for a few things since I'd just been doing it off the top of my head and then executed it. After escaping `right` and `left` as they're keywords (not necessarily the best choice of field names...) the CREATE TABLE and INSERT statements ran. I did a sanity check of the rotated_pieces table and it looked good.

The result of my SELECT statement was disappointing though. As I sort of suspected, there are lots of solutions if you allow a piece to be used more than once and the SELECT returned 1272 rows.

8. I couldn't think of a neat way to check for duplicates so ended up just writing a WHERE clause to do it by brute force:

WHERE A.piece_id != B.piece_id AND A.piece_id != C.piece_id AND A.piece_id != D.piece_id
  AND A.piece_id != E.piece_id AND A.piece_id != F.piece_id AND A.piece_id != G.piece_id
  AND A.piece_id != H.piece_id AND A.piece_id != I.piece_id
  AND B.piece_id != C.piece_id AND B.piece_id != D.piece_id AND B.piece_id != E.piece_id
  AND B.piece_id != F.piece_id AND B.piece_id != G.piece_id AND B.piece_id != H.piece_id
  AND B.piece_id != I.piece_id AND C.piece_id != D.piece_id AND C.piece_id != E.piece_id
  AND C.piece_id != F.piece_id AND C.piece_id != G.piece_id AND C.piece_id != H.piece_id
  AND C.piece_id != I.piece_id
  AND D.piece_id != E.piece_id AND D.piece_id != F.piece_id AND D.piece_id != G.piece_id
  AND D.piece_id != H.piece_id AND D.piece_id != I.piece_id
  AND E.piece_id != F.piece_id AND E.piece_id != G.piece_id AND E.piece_id != H.piece_id
  AND E.piece_id != I.piece_id
  AND F.piece_id != G.piece_id AND F.piece_id != H.piece_id AND F.piece_id != I.piece_id
  AND G.piece_id != H.piece_id AND G.piece_id != I.piece_id
  AND H.piece_id != I.piece_id;

9. This had the desired result and I got back 4 rows.

'A', 'Ar', 'B', 'Br', 'C', 'Cr', 'D', 'Dr', 'E', 'Er', 'F', 'Fr', 'G', 'Gr', 'H', 'Hr', 'I', 'Ir'
2, 1, 1, 0, 6, 0, 8, 3, 9, 3, 7, 2, 5, 3, 3, 0, 4, 0
6, 1, 7, 3, 4, 1, 1, 1, 9, 0, 3, 1, 2, 2, 8, 0, 5, 0
4, 2, 3, 2, 5, 1, 7, 0, 9, 1, 8, 1, 6, 2, 1, 2, 2, 3
5, 2, 8, 2, 2, 0, 3, 3, 9, 2, 1, 3, 4, 3, 7, 1, 6, 3

The first row clearly matched Reilly's solution, but it wasn't immediately obvious what the other 3 rows were. After reformatting them into a 3x3 grid and staring for a little while I picked out the pattern of pieces 2-1-6 around the edges and realized it was the whole board being rotated. So there was a single solution after all.

2, 1, 6, 
8, 9, 7, 
5, 3, 4

6, 7, 4, 
1, 9, 3, 
2, 8, 5

4, 3, 5, 
7, 9, 8, 
6, 1, 2

5, 8, 2, 
3, 9, 1, 
4, 7, 6

10. The next step was to pretend I knew all that from the beginning and write it up in the previous blog post. Later that evening I thought again and realized that wasn't so truthful and that I should have another shot at writing it up.

Postscript: The ugly WHERE clause was still bugging me and I realized that it could be improved by making some kind of function involving all of the piece ids and checking the answer e.g. if they all add to 45 then that's a solution. Unfortunately, addition isn't a uniquely identifying function, and neither is multiplication or addition of 2^piece_id. What will work though is changing the piece ids to prime numbers and multiplying them all together. Keeping the first digit the same the ids are now:

11, 23, 31, 41, 53, 61, 71, 83, 97

The product of these primes has no other factors and we don't care about the order since multiplication is cummutative, so to ensure each piece appears only once the WHERE can now simply be:

WHERE A.piece_id * B.piece_id * C.piece_id 
    * D.piece_id * E.piece_id * F.piece_id 
    * G.piece_id * H.piece_id * I.piece_id
    = 11*23*31*41*53*61*71*83*97;

Tuesday, June 21, 2011

SQL: 3x3 Square Picture-Puzzle Solution

Update: A second attempt at a write up.

After Reilly solved a 3x3 square picture puzzle using Prolog I made a flippant remark that it would be interesting to solve using SQL and well, here goes...

First, create a table and populate it with the pieces:

# table of all pieces in all possible rotations
CREATE TABLE rotated_pieces (
  piece_id     INTEGER, # unique piece id
  rotation     INTEGER, # 0 - top, 1 - left, 2 - bottom, 3 - right
  top         CHAR(10), # animal at top edge
  top_head    CHAR(10), # head or tail at top edge
  `right`     CHAR(10),
  right_head  CHAR(10),
  bottom      CHAR(10),
  bottom_head CHAR(10),
  `left`      CHAR(10),
  left_head   CHAR(10));

# unrotated pieces (top)
INSERT INTO rotated_pieces 
       (piece_id, rotation, 
              top,       top_head, `right`,   right_head, bottom,    bottom_head, `left`,    left_head) 
VALUES (1, 0, 'cheetah', 'tail',   'tiger',   'tail',     'lion',    'head',      'tiger',   'head'),
       (2, 0, 'lion',    'tail',   'lion',    'head',     'tiger',   'tail',      'cheetah', 'head'),
       (3, 0, 'tiger',   'tail',   'lion',    'head',     'panther', 'head',      'tiger',   'tail'),
       (4, 0, 'panther', 'tail',   'cheetah', 'head',     'panther', 'tail',      'lion',    'tail'),
       (5, 0, 'tiger',   'head',   'tiger',   'head',     'cheetah', 'head',      'lion',    'tail'),
       (6, 0, 'panther', 'tail',   'panther', 'head',     'cheetah', 'tail',      'tiger',   'head'),
       (7, 0, 'panther', 'head',   'cheetah', 'tail',     'cheetah', 'head',      'lion',    'tail'),
       (8, 0, 'panther', 'tail',   'lion',    'head',     'panther', 'head',      'cheetah', 'tail'),
       (9, 0, 'cheetah', 'head',   'tiger',   'head',     'panther', 'head',      'lion',    'tail');

Then, rotate each of those pieces so we have all 36 variations:

# rotate (top --> left)
INSERT INTO rotated_pieces (piece_id, rotation, top, top_head, `right`, right_head, bottom, bottom_head, `left`, left_head) 
  SELECT piece_id, rotation+1, 
         `right` AS top, right_head AS top_head, 
         bottom AS `right`, bottom_head AS right_head, 
         `left` AS bottom, left_head AS bottom_head, 
         top AS `left`, top_head AS left_head 
    FROM rotated_pieces;

# rotate (top --> bottom, left --> right) 
INSERT INTO rotated_pieces (piece_id, rotation, top, top_head, `right`, right_head, bottom, bottom_head, `left`, left_head) 
  SELECT piece_id, rotation+2, 
         bottom AS top, bottom_head AS top_head, 
         `left` AS `right`, left_head AS right_head, 
         top AS bottom, top_head AS bottom_head, 
         `right` AS `left`, right_head AS left_head 
    FROM rotated_pieces;

Then, it's a pretty simple query to return the result. The code is messed up by the WHERE clause which ensures that each piece is used only once in the solution, if there's a neater way to do this I'd like to know.

# find solution
SELECT A.piece_id AS A, A.rotation AS Ar, B.piece_id AS B, B.rotation AS Br, C.piece_id AS C, C.rotation AS Cr,
       D.piece_id AS D, D.rotation AS Dr, E.piece_id AS E, E.rotation AS Er, F.piece_id AS F, F.rotation AS Fr,
       G.piece_id AS G, G.rotation AS Gr, H.piece_id AS H, H.rotation AS Hr, I.piece_id AS I, I.rotation AS Ir
  FROM rotated_pieces A 
INNER JOIN rotated_pieces B ON (A.`right` = B.`left` AND A.right_head != B.left_head)
INNER JOIN rotated_pieces C ON (B.`right` = C.`left` AND B.right_head != C.left_head)
INNER JOIN rotated_pieces D ON (A.bottom = D.top     AND A.bottom_head != D.top_head)
INNER JOIN rotated_pieces E ON (D.`right` = E.`left` AND D.right_head != E.left_head
                                AND B.bottom = E.top AND B.bottom_head != E.top_head)
INNER JOIN rotated_pieces F ON (E.`right` = F.`left` AND E.right_head != F.left_head
                                AND C.bottom = F.top AND C.bottom_head != F.top_head)
INNER JOIN rotated_pieces G ON (D.bottom = G.top     AND D.bottom_head != G.top_head)
INNER JOIN rotated_pieces H ON (G.`right` = H.`left` AND G.right_head != H.left_head
                                AND E.bottom = H.top AND E.bottom_head != H.top_head)
INNER JOIN rotated_pieces I ON (H.`right` = I.`left` AND H.right_head != I.left_head
                                AND F.bottom = I.top AND F.bottom_head != I.top_head)
WHERE A.piece_id != B.piece_id AND A.piece_id != C.piece_id AND A.piece_id != D.piece_id
  AND A.piece_id != E.piece_id AND A.piece_id != F.piece_id AND A.piece_id != G.piece_id
  AND A.piece_id != H.piece_id AND A.piece_id != I.piece_id
  AND B.piece_id != C.piece_id AND B.piece_id != D.piece_id AND B.piece_id != E.piece_id
  AND B.piece_id != F.piece_id AND B.piece_id != G.piece_id AND B.piece_id != H.piece_id
  AND B.piece_id != I.piece_id AND C.piece_id != D.piece_id AND C.piece_id != E.piece_id
  AND C.piece_id != F.piece_id AND C.piece_id != G.piece_id AND C.piece_id != H.piece_id
  AND C.piece_id != I.piece_id
  AND D.piece_id != E.piece_id AND D.piece_id != F.piece_id AND D.piece_id != G.piece_id
  AND D.piece_id != H.piece_id AND D.piece_id != I.piece_id
  AND E.piece_id != F.piece_id AND E.piece_id != G.piece_id AND E.piece_id != H.piece_id
  AND E.piece_id != I.piece_id
  AND F.piece_id != G.piece_id AND F.piece_id != H.piece_id AND F.piece_id != I.piece_id
  AND G.piece_id != H.piece_id AND G.piece_id != I.piece_id
  AND H.piece_id != I.piece_id;

This returns 4 rows, the first is our solution:

2,1, 1,0, 6,0, 
8,3, 9,3, 7,2, 
5,3, 3,0, 4,0

The remaining 3 are the same solution with the entire board rotated:

6,1, 7,3, 4,1, 
1,1, 9,0, 3,1, 
2,2, 8,0, 5,0

4,2, 3,2, 5,1, 
7,0, 9,1, 8,1, 
6,2, 1,2, 2,3

5,2, 8,2, 2,0, 
3,3, 9,2, 1,3, 
4,3, 7,1, 6,3

I would argue the SQL version is clearer, but the Prolog version is slightly terser and should be easier to extend to a 4x4 puzzle.

Monday, February 21, 2011

Merrell Trail Gloves review

A quick review of the Merrell Trail Glove minimalist trail running shoes.

After reading a few reviews of these shoes I was curious enough to fork out the money for them (Barefoot Running University and I run far.)

On your foot

The fit is snug in the heel and the laces really grip around the mid-foot and arch. I only have the Vibram FiveFingers and walking shoes to compare to, maybe regular running shoes are more like this too, but they are different to anything I have run in before. The toes have tonnes of room and are completely free to move, but don't slide around at all because the midfoot is held solidly.

They breath pretty well, a lot of the upper is mesh/fabric, the tongue's a bit thick so they're pretty warm but regular shoes+socks would be worse.

They let a bit of dirt in around the ankle and I think through the mesh/fabric (I wear them without socks), but because it can move around inside the shoe easily I don't think it's as annoying as when wearing Vibrams.

Most of my shoes are 43 or 44 (Vibrams are 42), and I got the Merrells in size 44 to make sure my toes would have room to splay and wouldn't hit the end heading downhill. This was a bit of a mistake, the way they fit means you won't slide inside them and the bit of extra length means I catch my toe on steps a bit more than I'd like. Not a show stopper, I just have to lift my feet higher.

On the ground

The sole has a bit of cushioning and feels a little soft on the footpath, but you don't notice it as soon as you get off road. It's much thicker and stiffer than the Vibrams, with less ground feel, but still very flexible and nothing like a normal running/trail shoe.

The tread has maybe 2-3mm deep chunks, bigger on the toe and heel. It's very curved and foot shaped, no attempts to control side ways stability or pronation, which is great and they are a tiny bit lighter than Vibram KSOs.

They feel bombproof, no fear treading on rocks/stones/sticks and I'm definitely not going to catch my little toe again like I did wearing Vibrams.

Conclusion

So, these are pretty much exactly what I've been waiting for. I'll only wear them on rough/rocky trails, and they're not "barefoot" by any stretch of the imagination, but they are great minimal shoes and the biggest problem I can see is that I'm going to be exhausted, the Vibrams give you an excuse to slow down occasionally "to negotiate tricky terrain" :)


Dandenong Ranges

Friday, February 04, 2011

LED Bike Light update

My home built LED bike light performed well for many years, but when I got my new bike, the battery holder and handlebar mounting solutions no longer functioned adequately so it was time for a redesign.

I had been planning on a new simplified version, eliminating the micro-controller and putting in a simple dimmer potentiometer. It turned out I never really used the battery monitoring features and simply used a multimeter to decide when to recharge, and using a dimmer would allow setting the brightness easily and quickly and also allow the "high beam" mode to remain on through hazardous sections when necessary.

I was still pretty keen on building this myself as all it really required was cannibalising my old light for parts and making a new case. Commercial solutions had dropped a lot in price but are still many times more expensive than DIY (a few friends have these AYUP lights for example and they seem great).

Then I discovered semi-cheap LED torches as an option and ended up buying a Fenix LD20 LED torch and a small clamp from Ebay (that I can't find again, glad I bought 2...)

This puts out almost exactly the same amount of light as my old version but is in a small waterproof and easy to use package. As a bonus, it's a torch I can take camping etc. too.

I'm simply rotating through the NiMH AA batteries from the old light and am a bit disappointed with the battery life, seeming to have to change them more often than I'd like, but that's pretty quick and an extra set of batteries isn't too much of a struggle to carry around.

All in all, for $80 you can't go too wrong.