I was a bit unsure how 2013 was going to turn out after the great vintage we had in Eastern Australia in 2012. I have been trying a few of the new wines that have been coming through and an outstanding wine is the Pepperjack 2013 Shiraz. A typical Barrosa Shiraz – smooth, powerful and very flavoursome. About the only thing wrong with it is the alcohol content which is getting a bit high at 15%, but this is not some cold climate wine so you can expect a bit of alcohol. At $16.85 a bottle right now at Dan Murphy’s it is a steal.
Price $16.85
Value $30.00
Let’s kill the term “lifestyle business” for founder-focused startups
Just a rant about venture capital. The industry has a name for startups that are not aiming to be extreme outliers – a lifestyle business. This term is used by venture capitalists to dismiss any business that is not completely focused on becoming the 1 in 10,000 company that will be worth more than a billion dollars (a unicorn).
The term lifestyle business did not originally have such pejoratively connotations. It was coined by William Wetzel to describe any business unlikely to generate economic returns large enough to interest outside investors, but it has now come to be used as a put-down of any startup where the founders are not working towards creating a billion dollar company. The not-too-subtle implication is if a startup is not “shooting for the moon” then it is just some sort of hobby business unworthy of consideration.
While many new companies are true lifestyle businesses (e.g. small home-based consultancies, one-man software businesses, etc), many others are not. These non-venture capital backed startups (which I have termed founder-focused startups) are serious growth businesses run with the aim of maximising returns to the founder(s). The owners of these business work as hard (or even harder) as any VC-funded startup, but they have a totally different focus. The typical features and aims of founder-focused startups are:
- Self-funded or bootstrapped
- Managed to balance risk and reward
- Substance over hype
- Sustainable long-term growth
- Long-term planning
It is my opinion that founder-focused businesses are what all most founders should be starting. As a founder do you want 0.01% chance of making $100 million with a 99.99% chance of making nothing after 10 years (the VC-backed startup model), or a 10% chance of making $20 million with a 40% chance of making $1 million (the founder-focused startup model)? Is your life really going to be that much better if you make $100 million rather than just $20 million? If not, then why take the very real risk of ending up with nothing for all your hard work?
The aim of any startup should be to hit the founder’s personal wealth target(s) (e.g. own equity worth $15 million) with the minimum amount of risk.
The ultimate proof of this proposition is to look at what venture capitalists actually do, not what they tell startups to do. It is an open secret within the VC industry that all the venture capitalists are running the very type of businesses that they are so busy disparaging (i.e. founder-focused businesses). The venture capitalists own businesses are laser-focused on minimising risk by investing in dozen of companies, sustaining long-term growth (the 2+20 model), using long-term planing by locking in the limited partners money for years, and maximising returns for themselves (2+20 again). Don’t believe the venture capital hype that the only “real” startups are those that benefit venture capital – focus on generating real wealth for the founders (yourself) with the minimum of risk.
Does this mean that I think all startups should never accept money from outside investors? No, but you should only do so if it will increase your chances of reaching your personal wealth target. If not, then say no politely and get on with building your business.
Why do we need to do anything about Ebola?
Figure 1. The Ebola virus (source CDC).
This is a good question. The current outbreak Ebola is happening in a part of the world (west Africa) where death is unfortunately all too common and where diseases like Malaria or HIV are killing many more people. Why should we care more about Ebola than HIV? Wouldn’t the resources required to stop Ebola be better spent controlling mosquitos (Malaria), or providing antiretroviral drugs to HIV patients? While I think these diseases are very important, and I wish the world did put more money into all infectious diseases, Ebola is different.
Speed
Ebola is spreading at a very rapid rate with the new case numbers doubling every 20 days or so. Diseases like Malaria and HIV are not spreading at anywhere near this rate, and while very serious, are not a threat that must be stopped today. The speed at which Ebola is spreading gives us very little time to develop control measures — we just don’t have the time to develop new drugs or vaccines (they are needed). Any delay makes the problem much, much bigger. Ebola is a problem that you can’t put off for tomorrow.
Ebola is not (yet) a human disease
This is a really important difference and one we should be most concerned about. Diseases like Malaria and HIV are human diseases, while Ebola is still a zoonotic disease caused by a virus picked up from an animal. Human diseases are adapted to infecting humans and being passed efficiently from person to person. How efficient a disease is passed from person to person is described by scientists using the term R0. This term tells you how many new people a person infected with the disease will on average infect. For example, a human disease like Polio has a R0 of between 5 and 7 (i.e. each person that gets infected with Polio will infect between 5 and 7 new people in an unvaccinated population). The R0 for Ebola in this outbreak is unknown (it ranges between under 1 to over 20 depending on the conditions), but the best estimate across the region is it is in the range of 1.3 to 1.8. This is quite low for an human disease and reflects that Ebola is not very good at being passed from person to person. This is not surprising when you remember that Ebola is a virus that normally infects flying foxes (fruit bats).
The major reason Ebola is not good at getting passed from person to person is that it kills you so quickly. Once you have symptoms you are normally dead (or hopefully on the way to recovery) within 7 to 10 days and before you have symptoms you are normally not infectious. This leaves very little time for Ebola to infect the next person, in fact Ebola is about as quick at killing humans as any disease can be and still be able to spread. If Ebola killed people any quicker (say within 3 days) then its R0 would be below 1 and the virus would have died out in humans on its own and never become a problem.
The fact that Ebola is infecting and killing thousands of people despite not being very good at it is worrying. Each person that gets infected produces hundreds of trillion of new viral particles. Many of these viral particles will have mutations (mistakes) in their genome (Ebola has a genome made up of RNA not DNA like in our own genome). Almost all of these mutated viruses are losers in the sense that the changes don’t improve Ebola’s ability to spread in humans, but just like with a lottery, the more tickets you buy the greater the chance you have of winning. By letting this outbreak run wild we are effectively buying trillions of tickets in a lottery we do not want to win — the human adapted Ebola lottery. Each person infected is making it a little more likely that a new mutant Ebola strain will arise with a much higher R0.
How would a such a mutated Ebola viral strain act? This is hard to say as we don’t know how well adapted Ebola can become to humans (we are in a way running a massive uncontrolled natural experiment to see how well adapted Ebola can become to infecting humans), but do we really want to find the answer to this question? Would it be wise to let a new strain arise that say took a month to kill you (thus allowing you to infect many more people), or one where you are infectious for a couple of weeks before the normal deadly symptoms arise? If such a strain arose then all our plans for containment of Ebola in western countries would be worthless.
We know how to stop Ebola
Unlike most human disease we actually know how to stop Ebola. All we need to do is get 70% of the infected people into simple treatment facilities where they can be cared for and where they can stop infecting new people. We have done this dozen of times with previous Ebola outbreaks and it has always worked. If we do this now we won’t have to worry about Ebola as future problem beyond being vigilant if any new zoonotic outbreaks occur. If we don’t stop this outbreak then we risk letting Ebola becoming entrenched in the human population like HIV or Polio. It is rare to have the ability to stop a new disease before it gets too big to control – let’s not let this opportunity go to waste.
Economics
One area that has received relatively little attention is the economics of Ebola. Even if the case numbers stay relatively low (say under 100,000), Ebola has the ability to cause major economic damage. As we have seen in recent weeks in the USA and other western countries, even a single imported case can cause mass concern (hysteria) leading to counterproductive proposals like travel bans and stopping flights. There is a real risk that politicians will overreact to the fears of an ill informed public and introduce policies that will disrupt international trade. The world economy is very weak; Europe is in or near to recession, China’s growth is slowing, Japan’s economy is running out of steam on the back of large VAT increases, and the resource-rich countries like Australia are slowing as commodity prices fall. With global interest rates at or near zero levels there is little that the world’s central banks can do to protect the world economy from even a small slow down in trade. With a fragile world economy we don’t want to be taking risks allowing anything that could derail growth and trade to run wild. Time to get serious.
Why do we need to go to full-scale military mobilisation to stop Ebola?
I posted last week that we need to move to full-scale military mobilisation if we are going to stop the current Ebola outbreak. After having some discussions about this on HN I thought that I should explain in more detail why we need to use the military and why we need full-scale mobilisation.
Scale of Problem
The problem is far beyond what any non-military organisation can deal with. This recent post from Les Roberts who is leading the WHO response in Freetown, Sierra Leone explains the scale of the problem.
The prediction landscape is looking bad. The official numbers reported are laboratory confirmed cases. Typically, we think people need 7-10ish days to become symptomatic. Typically people have symptoms for 7 days before they get into a health facility. A month ago, it was one day, now it typically takes 4 days from when a patient is sampled to when the patient is told the result of their test (and lots get lost and mislabeled….). Thus, the numbers that you hear about new cases today reflect the transmission dynamics from over 2 weeks ago…..and we thought the doubling time of the outbreak was 30 days, it seems to be less than that here. We knew the ~350 confirmed cases last week were an undercount….we now think there are 7-900 in reality. The need for hospital beds is climbing more than the ability to get them up and running. There might be 200ish ebola treatment beds now countrywide. There are perhaps 600 more in “holding areas.” We have schemes to get 500 or 600 ebola treatment beds up and running over the next 8 weeks. As Foreign Medical Team Coordinator, helping to get these beds up and supported is one of my primary tasks. If there are really 3000 cases this month, and 6000 next month…with all going perfectly on the treatment bed establishment side, we will have 30% of the beds we need next month, slightly worse than the situation now.
Need for effective quarantine
If we are going to get on top of the outbreak we need effective quarantine in the affected areas. Given the geographical scale of the outbreak, the poor infrastructure, and the limited local policing and military forces available, we need to bring in a lot of troops to do this. We also need to provide protection for the healthcare personnel and assist them in getting the sick out of homes and into treatment facilities. Only the military can provide this support.
Need for large numbers of healthcare personnel
We need thousands of doctors and nurses to run the treatment facilities. While we may get enough volunteers, the required numbers could soon exceed the number of volunteers we can recruit. If we run out of volunteers we would need to conscript the needed personnel and doing this would be impossible unless full-scale mobilisation had been authorised.
Toxic politics
Only full-scale mobilisation is going to short-circuit the political games being played. We have seen how hard politically it has been to get even a token number of USA troops deployed to west Africa. To send 40,000 or 80,000 troops and the associated healthcare personnel would be impossible in the current political climate. The only way to get the needed resources on the ground would be to effectively declare Ebola an international emergency and use the war powers available to Obama to do what needs to be done.
My fear is that we are not going to do this until the problem gets so huge that it will be beyond the world’s military to handle. The problem is doubling in size every 20 − 30 days, so each month of delay is making the problem more than twice as big. This is all without considering the risk of an Ebola strain arising that it is more infectious. Time to get serious.
Ebola: What needs to be done right now
I am a scientist with a background in Microbiology and Virology and what is happening (or more importantly what is not happening) with the current Ebola outbreak is very worrying. Rather than just scare my family I thought I should do a write up about what needs to be done.
Figure 1. Scale of the Ebola outbreak October 2014 (source WHO).
Where are we right now?
Ebola is completely out of control and the case numbers are doubling every 20 days or so. It does not look like Ebola had changed (it certainly could), it has just overwhelmed the containment systems we had in place in west Africa. The hospitals in the affected areas have reached (exceed) capacity and are not able to take in any new patients so the virus is running wild (this point seems to have been reached around August). A consequence of this is we really have a very poor idea of the number of cases since no-one is recording the cases that don’t make it to hospital.
What is going to happen?
Ebola is actually a very well studied virus from an epidemiological perspective so we can model its spread quite accurately. Here is what is going to happen according to the CDC.
Figure 2. Estimated impact of delaying intervention* on daily number of Ebola cases, with and without correction for underreporting† — EbolaResponse modeling tool, Liberia, 2014–2015 (source CDC).
* Intervention: Starting on September 23, 2014 (day 181 in model), and for the next 30 days, the percentage of all patients in Ebola treatment units was increased from 10% to 13%. This percentage was again increased on October 23, 2014 (day 211 in model) to 25%, on November 22, 2014 (day 241 in model) to 40%, and finally on December 22, 2014 (day 271 in model) to 70%. Day 1 in model is March 3, 2014. The impact of a delay of starting the increase in interventions was then estimated by twice repeating the above scenario but setting the start day on either October 23, 2014, or November 22, 2014.
† Corrected for potential underreporting by multiplying reported cases by a factor of 2.5 (Table 4).
§ New Ebola patients at peak of each start date. (Note that when the intervention is started on November 22, 2014, the peak is not reached by January 20, 2014, which is the last date included in the model.)
The only thing missing from this modelling is the “do nothing” option since the CDC has assumed that we will start doing something by November 22nd (unlikely). They have also been too scared to model past January 2015.
This modelling also assumes that the virus does not become better adapted to spread in humans which could, and may even be likely, to happen. The most probable adaption would not be for Ebola to become airborne (this is only slightly less likely than pigs becoming airborne), but for the virus to slow down in the speed in which it kills people so they stay infectious for a longer period of time. A strain could arise that takes a month to kill you (rather than a week) and where you are asymptomatic, but infectious, for a couple of weeks. Such a strain would allow each patient to infect many more people before they died or recovered. One of the reasons that Ebola has not caused major outbreaks in the past is that it kills so rapidly that there is little time for each patient to infect new people. The selection pressure on Ebola to slow the speed in which it kills is extremely strong and the more people infected the more likely it becomes that such a mutation will occur.
Why did this Ebola outbreak get so bad?
This is a good question as it is not the first Ebola outbreak. The best explanation I have seen is from the discoverer of Ebola, Professor Piot, as quoted in De Spiegel.
SPIEGEL: Why did WHO react so late?
Piot: On the one hand, it was because their African regional office isn’t staffed with the most capable people but with political appointees. And the headquarters in Geneva suffered large budget cuts that had been agreed to by member states. The department for hemorrhagic fever and the one responsible for the management of epidemic emergencies were hit hard. But since August, WHO has regained a leadership role.
What do we need to do to stop Ebola?
We need to get the R0 below 1. This means each infected person needs to infects less than one new person. Right now the R0 is somewhere between 2 and 10 (i.e. each infected person is infecting between 2 to 10 new people). To get the R0 of Ebola below 1 we need to move at least 70% of infected people into properly functioning infection control hospitals. Sounds easy doesn’t it?
How do we actually do this?
This outbreak is now beyond the ability of the governments in the affected areas, the WHO, or any NGO to bring under control (the head of MSF has stated that the outbreak is now beyond their ability to deal with). There is only one option left which is full-scale military mobilisation. In practicable terms this is what needs to happen:
- The UN Security Council needs to authorise the use of all available resources to control and contain the outbreak in the affected countries and surrounding regions including the use of international military force. This needs to be done as soon as possible (days not weeks).
- Those countries with the ability to do this (the USA mostly) need to move to full-scale military mobilisation (i.e. war level)*. This may require conscription of the required healthcare workers, but if we are lucky and act soon we might be able to get by with just volunteers.
- Start an outside-in Ebola containment/infection control process in the region. This will require putting large numbers of troops and medical personnel on the ground in the surrounding countries and then moving into the worst affected areas as more hospitalisation capacity is brought online. The key is to fight Ebola where it can be controlled so that it does not spread further and not waste our resources fighting it in those areas where we can’t get the R0 below 1 (i.e. where we can’t achieve the required 70% hospitalisation rate).
*Why do we need mobilisation? In theory we don’t, but politics in the USA is so toxic that unless this is treated as war it won’t be possible to get the required resource on the ground quickly enough. An example of this is the 3000 troops announced a couple of weeks back that were going to be sent to Liberia to help have still not left as they are being held up by congress as politics is played.
What do I think will actually happen?
A lot of dithering and token efforts from the UN and the rest of the world until January 2015 when wholesale panic sets in and we then move to full-scale mobilisation. If we are lucky the virus won’t have mutated and will only destroy west Africa. By the end of 2015 a 100 million people could be dead and the world in a massive recession as international trade grinds to a halt. Of course I could be wrong (I certainly hope I am), but based on what I know and what I see happening (or more importantly not happening) I am not that hopeful. Time to get serious.
Tracking down global variables in C code
I recently had the fun job of making some complex legacy C code (200,000+ lines) thread safe. Of course there were globals spread through the code so finding them all turned into a massive easter egg hunt. The initial problem was how to track them all down. If you ever have this fun job here are the steps I used.
1. I searched for the word “global”. If the person who wrote the code took care then all the global variables will have been commented as such (ha ha). Maybe surprisingly this did managed to find around 50% of the globals – while not perfect, it was a good start. I also found a few more unlabelled globals by searching for “thread-safe” and “thread” since some of the non-thread safe code was actually commented as being not thread-safe (I wish it all had been).
2. I next opened the .map file (generated by Visual Studio in debug mode) and looked for any “common” class variables (these are found down towards the bottom of the .map file). This process managed to shake out another 40% of the globals.
3. The last 5% of globals I found by doing a manual search through the entire code base for the “static” keyword. I of course then had to then trawl through several thousand static function declarations, but the last of the globals were in here too.
The most interesting thing about this painful exercise is how often people use globals when they are not really needed. 90% of the globals were being used only two or three times and were able to be made thread safe with very little code change. Of course the last 10% were used in more than 100 locations spread throughout the entire code base so the whole thread safe conversion exercise was not easy.
To keep the required code change to a minimum (I am very reluctant to make major structural changes to complex code even if I have written it) I solved the problem by just packaging up the difficult globals into a thread-safe strut declared in the main entry function and passed the pointer to this strut into each of the functions that were using the globals. While not a trivial job, this approach avoided disturbing code I knew was working well and which would have taken months to re-write.
Lovers Not Toreadors Tempranillo 2011
There are many great Spanish wines and we get so few of them here in Australia. Most of the Spanish wines we do get here really should have been tipped down the drain in Spain (I am looking at you Aldi), but on occasion we get a Spanish wine that is both great value and very drinkable. The Lovers Not Toreadors 2011 Tempranillo is one such wine. Flavoursome and easy drinking it makes a great change from the common garden variety Australian shiraz. At under $16 dollars a bottle it is really worth buying – just ignore the stupid label.
Cost $15.90
Value $25.00+
Base32 implementation of the Damm error detection algorithm in PHP
I have ported the Base32 Damm error detection code to PHP (more annoying than hard). I have put the code on GitHub Base32 implementation of the Damm error detection algorithm in PHP & C. I have also uploaded the C version there too.
Base32 implementation of the Damm error detection algorithm in C
The Damm algorithm is a fantastic check digit algorithm that detects all single-digit errors and all adjacent transposition errors. It detects all occurrences of altering one single digit and all occurrences of transposing two adjacent digits, the two most frequent transcription errors. The Damm algorithm also has the benefit that prepending leading base encoding zeros does not affect the check digit so you can use it on fixed size strings. All in all it is a great algorithm for checking if there have been any user errors when entering a number.
The only problem with the Damm algorithm is that all the current implementations are base 10 (0-9) only. I wanted to be able to use it to check alpha-numerical strings (passwords) so I wrote a base32 implementation of the Damm algorithm in C/C++. With the commonly confused characters (0/o and 1/l/i) avoided in the base32 encoding you can make a rather nice password checker. Any desired encoding scheme with 32 characters (or less) can be used.
I use the damn32 program in a bash one-liner to generate 10 (9 + the damn check) character password strings. You can make longer or shorter strings by changing the head -c switch.
# openssl rand -base64 50 | tr -dc '23456789abcdefghjkmnpqrstuvwxyz' | head -c9 | xargs damn32
Here is the code for damn32.c. It can be compiled with gcc using:
# gcc damn32.c -o damn32
I will to port this to javascript and php when I get the chance, but if someone wants to do it now I am happy to link to your code or post it here.
Edit.Thanks Michael for pointing out that due to some stupidity on my behalf the code got called damn.c not damm.c – I have updated the post title, but I will leave the code as is as a reminder to be more careful next time :)
#include/* Base32 implementation of the Damm error detection algorithm in C Copyright (c) 2014, Daniel Tillett All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. BACKGROUND The Damm algorithm is a check digit algorithm that detects all single-digit errors and all adjacent transposition errors. It detects all occurrences of altering one single digit and all occurrences of transposing two adjacent digits, the two most frequent transcription errors. The Damm algorithm has the benefit that it makes do without the dedicatedly constructed permutations and its position specific powers being inherent in the Verhoeff scheme. Prepending leading base encoding zeros does not affect the check digit. https://en.wikipedia.org/wiki/Damm_algorithm */ /* A base32 (or less) encoding. With this example encoding the base 0 is '2' and contains 31 characters that avoids using characters that could be confused with each other (i.e. 0/o or 1/i/l). The encoding can be any scheme with 32 or less characters. To change the encoding update encodeLen and base32 to the desired values. In this example on 31 characters are used */ const int encodeLen = 31; const char base32[encodeLen] = "23456789abcdefghjkmnpqrstuvwxyz"; /* Returns index position of the base32 digit if the digit exists in the base32 string or encodeLen if not. */ int base32Index(char p) { int i; for (i = 0; i < encodeLen; i++) { if (p == base32[i]) { break; } } return i; } /* Damn algorithm base32 check digit calculator. Returns the base32 check digit defined by the base32 string or '-' if the base32 number contains a character that is not defined in the base32 string. Input must be a null terminated C string. */ char damm32Encode(char *code) { int i, interim = 0; char *p; /* WTA quasigroup matrix of order 32 http://stackoverflow.com/questions/23431621/extending-the-damm-algorithm-to-base-32 This was constructed according to Damm Lemma 5.2 by Michael (http://stackoverflow.com/users/3625116/michael) I suspect this Michael is the Michael Damm, but I really don't know :) */ char damm32Matrix[32][32] = { { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 3, 1, 7, 5, 11, 9, 15, 13, 19, 17, 23, 21, 27, 25, 31, 29}, { 2, 0, 6, 4, 10, 8, 14, 12, 18, 16, 22, 20, 26, 24, 30, 28, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, { 4, 6, 0, 2, 12, 14, 8, 10, 20, 22, 16, 18, 28, 30, 24, 26, 7, 5, 3, 1, 15, 13, 11, 9, 23, 21, 19, 17, 31, 29, 27, 25}, { 6, 4, 2, 0, 14, 12, 10, 8, 22, 20, 18, 16, 30, 28, 26, 24, 5, 7, 1, 3, 13, 15, 9, 11, 21, 23, 17, 19, 29, 31, 25, 27}, { 8, 10, 12, 14, 0, 2, 4, 6, 24, 26, 28, 30, 16, 18, 20, 22, 11, 9, 15, 13, 3, 1, 7, 5, 27, 25, 31, 29, 19, 17, 23, 21}, {10, 8, 14, 12, 2, 0, 6, 4, 26, 24, 30, 28, 18, 16, 22, 20, 9, 11, 13, 15, 1, 3, 5, 7, 25, 27, 29, 31, 17, 19, 21, 23}, {12, 14, 8, 10, 4, 6, 0, 2, 28, 30, 24, 26, 20, 22, 16, 18, 15, 13, 11, 9, 7, 5, 3, 1, 31, 29, 27, 25, 23, 21, 19, 17}, {14, 12, 10, 8, 6, 4, 2, 0, 30, 28, 26, 24, 22, 20, 18, 16, 13, 15, 9, 11, 5, 7, 1, 3, 29, 31, 25, 27, 21, 23, 17, 19}, {16, 18, 20, 22, 24, 26, 28, 30, 0, 2, 4, 6, 8, 10, 12, 14, 19, 17, 23, 21, 27, 25, 31, 29, 3, 1, 7, 5, 11, 9, 15, 13}, {18, 16, 22, 20, 26, 24, 30, 28, 2, 0, 6, 4, 10, 8, 14, 12, 17, 19, 21, 23, 25, 27, 29, 31, 1, 3, 5, 7, 9, 11, 13, 15}, {20, 22, 16, 18, 28, 30, 24, 26, 4, 6, 0, 2, 12, 14, 8, 10, 23, 21, 19, 17, 31, 29, 27, 25, 7, 5, 3, 1, 15, 13, 11, 9}, {22, 20, 18, 16, 30, 28, 26, 24, 6, 4, 2, 0, 14, 12, 10, 8, 21, 23, 17, 19, 29, 31, 25, 27, 5, 7, 1, 3, 13, 15, 9, 11}, {24, 26, 28, 30, 16, 18, 20, 22, 8, 10, 12, 14, 0, 2, 4, 6, 27, 25, 31, 29, 19, 17, 23, 21, 11, 9, 15, 13, 3, 1, 7, 5}, {26, 24, 30, 28, 18, 16, 22, 20, 10, 8, 14, 12, 2, 0, 6, 4, 25, 27, 29, 31, 17, 19, 21, 23, 9, 11, 13, 15, 1, 3, 5, 7}, {28, 30, 24, 26, 20, 22, 16, 18, 12, 14, 8, 10, 4, 6, 0, 2, 31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1}, {30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0, 29, 31, 25, 27, 21, 23, 17, 19, 13, 15, 9, 11, 5, 7, 1, 3}, { 3, 1, 7, 5, 11, 9, 15, 13, 19, 17, 23, 21, 27, 25, 31, 29, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 2, 0, 6, 4, 10, 8, 14, 12, 18, 16, 22, 20, 26, 24, 30, 28}, { 7, 5, 3, 1, 15, 13, 11, 9, 23, 21, 19, 17, 31, 29, 27, 25, 4, 6, 0, 2, 12, 14, 8, 10, 20, 22, 16, 18, 28, 30, 24, 26}, { 5, 7, 1, 3, 13, 15, 9, 11, 21, 23, 17, 19, 29, 31, 25, 27, 6, 4, 2, 0, 14, 12, 10, 8, 22, 20, 18, 16, 30, 28, 26, 24}, {11, 9, 15, 13, 3, 1, 7, 5, 27, 25, 31, 29, 19, 17, 23, 21, 8, 10, 12, 14, 0, 2, 4, 6, 24, 26, 28, 30, 16, 18, 20, 22}, { 9, 11, 13, 15, 1, 3, 5, 7, 25, 27, 29, 31, 17, 19, 21, 23, 10, 8, 14, 12, 2, 0, 6, 4, 26, 24, 30, 28, 18, 16, 22, 20}, {15, 13, 11, 9, 7, 5, 3, 1, 31, 29, 27, 25, 23, 21, 19, 17, 12, 14, 8, 10, 4, 6, 0, 2, 28, 30, 24, 26, 20, 22, 16, 18}, {13, 15, 9, 11, 5, 7, 1, 3, 29, 31, 25, 27, 21, 23, 17, 19, 14, 12, 10, 8, 6, 4, 2, 0, 30, 28, 26, 24, 22, 20, 18, 16}, {19, 17, 23, 21, 27, 25, 31, 29, 3, 1, 7, 5, 11, 9, 15, 13, 16, 18, 20, 22, 24, 26, 28, 30, 0, 2, 4, 6, 8, 10, 12, 14}, {17, 19, 21, 23, 25, 27, 29, 31, 1, 3, 5, 7, 9, 11, 13, 15, 18, 16, 22, 20, 26, 24, 30, 28, 2, 0, 6, 4, 10, 8, 14, 12}, {23, 21, 19, 17, 31, 29, 27, 25, 7, 5, 3, 1, 15, 13, 11, 9, 20, 22, 16, 18, 28, 30, 24, 26, 4, 6, 0, 2, 12, 14, 8, 10}, {21, 23, 17, 19, 29, 31, 25, 27, 5, 7, 1, 3, 13, 15, 9, 11, 22, 20, 18, 16, 30, 28, 26, 24, 6, 4, 2, 0, 14, 12, 10, 8}, {27, 25, 31, 29, 19, 17, 23, 21, 11, 9, 15, 13, 3, 1, 7, 5, 24, 26, 28, 30, 16, 18, 20, 22, 8, 10, 12, 14, 0, 2, 4, 6}, {25, 27, 29, 31, 17, 19, 21, 23, 9, 11, 13, 15, 1, 3, 5, 7, 26, 24, 30, 28, 18, 16, 22, 20, 10, 8, 14, 12, 2, 0, 6, 4}, {31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 28, 30, 24, 26, 20, 22, 16, 18, 12, 14, 8, 10, 4, 6, 0, 2}, {29, 31, 25, 27, 21, 23, 17, 19, 13, 15, 9, 11, 5, 7, 1, 3, 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0} }; for (p = code; *p != '\0'; ++p) { i = base32Index(*p); if (i == encodeLen) { return '-'; } interim = damm32Matrix[interim][i]; } return base32[interim]; } /* Damm32 Check Returns 1 if the base32 number is error free and 0 if it contains an error or the last digit is not equal to the error check digit. */ int damm32Check(char *code) { return (damm32Encode(code) == base32[0]) ? 1 : 0; } /* Prints to stdout the input base32 number, the base32 check digit, and the damm32 check result. */ int main(int argc, char **argv) { if (argc == 2 && argv[1]) { printf("Input: %s\nCheck Digit: %c\nChecked: %d\n", argv[1], damm32Encode(argv[1]), damm32Check(argv[1])); return 1; } else { printf("Usage: damm32 [base32 number]\n"); return 0; } }
Taltarni Pyrenees Shiraz 2010
Wow what a wine. 2010 was a great year in the Victorian Pyrenees wine region and Taltarni have made an absolutely fabulous shiraz. I loved the 2009, but the 2010 is even better. The only downsides is it costs $30 a bottle and Taltarni are still using corks which means I have to waste 15 seconds rummaging around my kitchen for my corkscrew to open it. Buy as much as you can when you see it.
Cost: $30
Value: $60+
- « Previous Page
- 1
- 2
- 3
- 4
- 5
- 6
- …
- 9
- Next Page »