Advanced Technologies in Healthcare

Nigel Whittle - Head of Medical & Healthcare

By: Nigel Whittle
Head of Medical & Healthcare

21st March 2019

4 minute read

Home » Blog

Some of the biggest changes in the practice of medicine and healthcare over the past 70 years have resulted from improvements in the way diseases and illnesses can be diagnosed and studied. Innovative technologies now allow doctors to discover increasing amounts of detailed information about both the progression and treatment of disease, allowing new treatment options and care pathways.

The most significant developments which are likely to change the face of medicine over the next few decades include:

  • Enhanced self-management for patients and the elderly through technology support systems to empower understanding and control of conditions.
  • Improved patient access to health service infrastructure through utilisation of remote care and monitoring systems.
  • Further developments in medical imaging and the application of Artificial Intelligence systems to effectively analyse and diagnose conditions.
  • Precision medicine that can target medical interventions to specific sub-groups of patients based on genomic data.
  • Robotic surgical systems that can conduct exquisitely precise operations in difficult-to-reach anatomical areas without flagging or losing concentration.

Self-Management for Patients

Day-to-day physiological monitoring technology, driven particularly by the spread of a variety of consumer wearable devices with communication capabilities, has the ability to collect and integrate health information from a variety of sources, both medical and consumer-based. The next generation of wearables is likely to significantly blur the division between technology lifestyle accessory and medical device, as reliable non-invasive sensors for the measurement of blood pressure, blood sugar, body temperature, pulse rate, hydration level and many more become increasingly implemented within these devices. The provision and integration of these derived complex sets of data has the potential to provide valuable information, that enabling a holistic approach to healthcare. The US FDA is currently working closely with industry to facilitate the introduction and effective use of these more advanced devices.

Enhanced Patient Access

In the UK, the NHS has brought high-quality medical services to every citizen, but often at the cost of long waits for visits to the doctor when a patient is concerned about his health. The introduction of improved access systems, including video-conferencing facilities, electronic health records and AI-powered chatbots, promises to be a powerful and game-changing move. In particular, chatbots systems such as Babylon Health or Ada can provide a highly accessible medical triage procedure, which can alleviate the pressure on over-worked doctors in GP surgeries, and allow those doctors to focus on patients with more serious conditions. With increasing sophistication, these chatbots can potentially provide accurate diagnostic advice on common ailments without any human interaction or involvement. The key concern is, of course, ensuring that the algorithms operate with patient safety foremost, which requires fine tuning to balance between over-caution and under diagnosis.

Medical Imaging and Artificial Intelligence

Following admission to a hospital, a key element of modern medicine is the use of imaging systems for clinical diagnosis, and the main challenge for doctors is to interpret the complexity and dynamic changes of these images. Currently, most interpretations are performed by human experts, which can be time-consuming, expensive and suffer from human error due to visual fatigue. Recent advances in machine learning systems have demonstrated that computers can extract richer information from images, with a corresponding increase in reliability and accuracy. Eventually, Artificial Intelligence will be able to identify and extract novel features that are not discernible to human viewers, allowing enhanced capabilities for medical intervention. This will allow doctors to re-focus on their interaction with patients, which is often cited as the most valued aspect of medical intervention.

Precision Medicine

The current paradigm for medical treatment is changing through the development of powerful new tools for genome sequencing which allows scientists to understand how genes affect human health. Medical decisions can now take account of genetic information, allowing doctors to tailor specific treatments and prevention strategies for individual patients.

In essence, precision medicine is able to classify patients into sub-populations that are likely to differ in their response to a specific treatment. Therapeutic interventions can then be concentrated on those who will benefit, sparing expense and often unpleasant side effects for those who will not.

Robotic Surgery

Currently, robotic surgical devices are simply instruments that can translate actions outside the patient to inside the patient, often working through incisions as small as 8mm. The benefits of this are clear in terms of minimally invasive surgery, and by allowing surgeons to conduct the operations in a relaxed and stress-free environment. At the moment the robot does not do anything without direct input, but with the increasing development of AI systems, it is likely that in 10 or 15 years, certain parts of an operation such as suturing may be performed automatically by a robot, albeit under close supervision.

What will new technology mean for healthcare?

It is fiendishly difficult to predict the impact of innovative technological advances on medical practice and patient care. However, the overall message is clear – improvements in front end technology will allow patients to have a greater responsibility for their own personal health and well-being. Increased access to medical practice through innovative and efficient mechanisms will allow doctors to focus their time on the patients identified as suffering from more serious illnesses. Highly trained AI systems can then complement the doctors’ prowess in identifying and diagnosing particular diseases. Finally, treatment options will be highly tailored to individual patients and their conditions, increasing the cost-effectiveness of treatment.

However, each of these technology developments comes with associated costs and challenges. Not least, new technology could fundamentally change the way that medical staff work, requiring new skills and mindsets to effectively transform medical care into a radically new approach.

For an informative chat on how Plextek can assist with your Healthcare technology project, please contact Nigel at healthcare@plextek.com

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Some of the biggest changes in the practice of medicine and healthcare over the past 70 years have resulted from improvements in the way diseases and illnesses can be diagnosed and studied. Innovative technologies now allow doctors to discover increasing amounts of detailed information about both the progression and treatment of disease, allowing new treatment options and care pathways.

The most significant developments which are likely to change the face of medicine over the next few decades include:

  • Enhanced self-management for patients and the elderly through technology support systems to empower understanding and control of conditions.
  • Improved patient access to health service infrastructure through utilisation of remote care and monitoring systems.
  • Further developments in medical imaging and the application of Artificial Intelligence systems to effectively analyse and diagnose conditions.
  • Precision medicine that can target medical interventions to specific sub-groups of patients based on genomic data.
  • Robotic surgical systems that can conduct exquisitely precise operations in difficult-to-reach anatomical areas without flagging or losing concentration.

Self-Management for Patients

Day-to-day physiological monitoring technology, driven particularly by the spread of a variety of consumer wearable devices with communication capabilities, has the ability to collect and integrate health information from a variety of sources, both medical and consumer-based. The next generation of wearables is likely to significantly blur the division between technology lifestyle accessory and medical device, as reliable non-invasive sensors for the measurement of blood pressure, blood sugar, body temperature, pulse rate, hydration level and many more become increasingly implemented within these devices. The provision and integration of these derived complex sets of data has the potential to provide valuable information, that enabling a holistic approach to healthcare. The US FDA is currently working closely with industry to facilitate the introduction and effective use of these more advanced devices.

Enhanced Patient Access

In the UK, the NHS has brought high-quality medical services to every citizen, but often at the cost of long waits for visits to the doctor when a patient is concerned about his health. The introduction of improved access systems, including video-conferencing facilities, electronic health records and AI-powered chatbots, promises to be a powerful and game-changing move. In particular, chatbots systems such as Babylon Health or Ada can provide a highly accessible medical triage procedure, which can alleviate the pressure on over-worked doctors in GP surgeries, and allow those doctors to focus on patients with more serious conditions. With increasing sophistication, these chatbots can potentially provide accurate diagnostic advice on common ailments without any human interaction or involvement. The key concern is, of course, ensuring that the algorithms operate with patient safety foremost, which requires fine tuning to balance between over-caution and under diagnosis.

Medical Imaging and Artificial Intelligence

Following admission to a hospital, a key element of modern medicine is the use of imaging systems for clinical diagnosis, and the main challenge for doctors is to interpret the complexity and dynamic changes of these images. Currently, most interpretations are performed by human experts, which can be time-consuming, expensive and suffer from human error due to visual fatigue. Recent advances in machine learning systems have demonstrated that computers can extract richer information from images, with a corresponding increase in reliability and accuracy. Eventually, Artificial Intelligence will be able to identify and extract novel features that are not discernible to human viewers, allowing enhanced capabilities for medical intervention. This will allow doctors to re-focus on their interaction with patients, which is often cited as the most valued aspect of medical intervention.

Precision Medicine

The current paradigm for medical treatment is changing through the development of powerful new tools for genome sequencing which allows scientists to understand how genes affect human health. Medical decisions can now take account of genetic information, allowing doctors to tailor specific treatments and prevention strategies for individual patients.
In essence, precision medicine is able to classify patients into sub-populations that are likely to differ in their response to a specific treatment. Therapeutic interventions can then be concentrated on those who will benefit, sparing expense and often unpleasant side effects for those who will not.

Robotic Surgery

Currently, robotic surgical devices are simply instruments that can translate actions outside the patient to inside the patient, often working through incisions as small as 8mm. The benefits of this are clear in terms of minimally invasive surgery, and by allowing surgeons to conduct the operations in a relaxed and stress-free environment. At the moment the robot does not do anything without direct input, but with the increasing development of AI systems, it is likely that in 10 or 15 years, certain parts of an operation such as suturing may be performed automatically by a robot, albeit under close supervision.

What will new technology mean for healthcare?

It is fiendishly difficult to predict the impact of innovative technological advances on medical practice and patient care. However, the overall message is clear – improvements in front end technology will allow patients to have a greater responsibility for their own personal health and well-being. Increased access to medical practice through innovative and efficient mechanisms will allow doctors to focus their time on the patients identified as suffering from more serious illnesses. Highly trained AI systems can then complement the doctors’ prowess in identifying and diagnosing particular diseases. Finally, treatment options will be highly tailored to individual patients and their conditions, increasing the cost-effectiveness of treatment.
However, each of these technology developments comes with associated costs and challenges. Not least, new technology could fundamentally change the way that medical staff work, requiring new skills and mindsets to effectively transform medical care into a radically new approach.

For an informative chat on how Plextek can assist with your Healthcare technology project, please contact Nigel at healthcare@plextek.com

Save

Save

Save

Save

Save

Save

Save

Save

Save

The New Science of Genetic Medicine

Nigel Whittle - Head of Medical & Healthcare

By: Nigel Whittle
Head of Medical & Healthcare

9th January 2019

Home » Blog

With surprisingly little fanfare, in October 2018 NHS England became the first health service in the world to routinely offer genetic medicine in the fight to treat cancer.

From that date, hospitals across England have been linked to specialist centres that can read, analyse and interpret DNA isolated from patients with cancer. Through this service, cancer patients can be screened for the existence of key mutations within their tumours that can indicate the best drugs for treatment or to point towards clinical trials of experimental therapies that may be beneficial.

The move marks a big step towardprecision medicine, which offers more effective therapies that are tailored to individual patients.

What is the science underpinning this move?

Firstly, a quick crash course in cancer biology:

  • Cells are the building blocks of every living organism.The instructions (or genes) that tell a cell how to develop and what to do are encoded in long linear molecules of DNA found in the nucleus of the cell.
  • These DNA molecules can be damaged over time or through exposure to chemicals or environmental changes. Cells become cancerous when specific changes in the DNA, called ‘driver mutations’, tell cells to grow faster and behave abnormally.
  • Many cancers form solid tumours, which are masses of tissue, while cancers of the blood, such as leukaemia, generally do not form solid tumours.
  • As these cancer cells multiply to form a tumour, selective pressure increases the number and type of harmful mutations found within the DNA.
  • The cells may acquire additional properties through mutation, such as malignancy which means that they can spread into, or invade nearby tissues. In addition, as these tumours grow, some cancer cells break off and travel to distant parts of the body and form new tumours far from the original site.

Accordingly, although every cell of a particular cancer is related to the same original “parent” cell, the mixture of cells within a tumour becomes increasingly complex. The idea that different kinds of cells make up one cancer is called “tumour heterogeneity”, and in practice means that every cancer is unique. So two people with, say, lung cancer who are the same age, height, weight, and ethnicity, and who have similar medical histories, will almost certainly have two very different cancers.

By the time a cancer tumour is 1cm in diameter, the millions of cells within it are very different from each other, and each cancer has its own genetic identity created by the DNA in its cells.

This, of course, makes the treatment of cancer incredibly difficult and explains why scientific breakthroughs in the understanding of cancer biology do not always lead to significant improvements in overall survival rates.

How will cancer treatment change?

Precision medicine is an approach to patient care that allows doctors to select the best treatments for patients based on a genetic understanding of their disease. The idea of precision medicine is not new, but recent advances in science and technology have allowed the ideas to be brought more fully into clinical use.

Normally, when a patient is diagnosed with cancer, he or she receives a standard treatment based on previous experience of treating that disease. But typically, different people respond to treatments differently, and until recently doctors didn’t know why. But now the understanding that the genetic changes within one person’s cancer may not occur in others with the same type of cancer has led to a better understanding of which treatments will be most effective.

At the simplest level, this understanding allows targeted therapy against cancer, in which drugs (quite often complex biological molecules) are used to target very specific genetic changes in cancer cells. For example, around 15–20% of malignant breast cancers contain cells with a higher than normal level of a protein called HER2 on their surface, which stimulates them to grow. When combined with a suitable test, it means that not only can the drug be given to those patients most likely to benefit, but also the drug, with its associated side effects, need not be given to patients who will not benefit from its use.

So genetic medicine has already transformed the treatment of some cancer patients. The advent of widespread genetic medicine within the NHS is likely to lead to significant benefits for cancer patients, including:

• The identification of patients who are most likely to benefit from particular cancer therapy.

• The avoidance of unnecessary treatments that are less likely to work for specific groups of patients.

• The development of novel therapies targeted at specific tumour cells or cellular pathways.

Not only will precision medicine allow the development of precise and effective treatment strategies for cancer patients whilst improving the overall quality of life, but it will also finally destroy the myth of ‘one size fits all’ cancer therapy.

For an informative chat on how Plextek can assist with your Healthcare technology project, please contact Nigel at healthcare@plextek.com

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save


With surprisingly little fanfare, in October 2018 NHS England became the first health service in the world to routinely offer genetic medicine in the fight to treat cancer.

From that date, hospitals across England have been linked to specialist centres that can read, analyse and interpret DNA isolated from patients with cancer. Through this service, cancer patients can be screened for the existence of key mutations within their tumours that can indicate the best drugs for treatment or to point towards clinical trials of experimental therapies that may be beneficial.

The move marks a big step towardprecision medicine, which offers more effective therapies that are tailored to individual patients.

What is the science underpinning this move?


Firstly, a quick crash course in cancer biology:

  • Cells are the building blocks of every living organism. The instructions (or genes) that tell a cell how to develop and what to do are encoded in long linear molecules of DNA found in the nucleus of the cell.
  • These DNA molecules can be damaged over time or through exposure to chemicals or environmental changes. Cells become cancerous when specific changes in the DNA, called ‘driver mutations’, tell cells to grow faster and behave abnormally.
  • Many cancers form solid tumours, which are masses of tissue, while cancers of the blood, such as leukaemia, generally do not form solid tumours.
  • As these cancer cells multiply to form a tumour, selective pressure increases the number and type of harmful mutations found within the DNA.
  • The cells may acquire additional properties through mutation, such as malignancy which means that they can spread into, or invade nearby tissues. In addition, as these tumours grow, some cancer cells break off and travel to distant parts of the body and form new tumours far from the original site.


Accordingly, although every cell of a particular cancer is related to the same original “parent” cell, the mixture of cells within a tumour becomes increasingly complex. The idea that different kinds of cells make up one cancer is called “tumour heterogeneity”, and in practice means that every cancer is unique. So two people with, say, lung cancer who are the same age, height, weight, and ethnicity, and who have similar medical histories, will almost certainly have two very different cancers.

By the time a cancer tumour is 1cm in diameter, the millions of cells within it are very different from each other, and each cancer has its own genetic identity created by the DNA in its cells.


This, of course, makes the treatment of cancer incredibly difficult and explains why scientific breakthroughs in the understanding of cancer biology do not always lead to significant improvements in overall survival rates.

How will cancer treatment change?

Precision medicine is an approach to patient care that allows doctors to select the best treatments for patients based on a genetic understanding of their disease. The idea of precision medicine is not new, but recent advances in science and technology have allowed the ideas to be brought more fully into clinical use.

Normally, when a patient is diagnosed with cancer, he or she receives a standard treatment based on previous experience of treating that disease. But typically, different people respond to treatments differently, and until recently doctors didn’t know why. But now the understanding that the genetic changes within one person’s cancer may not occur in others with the same type of cancer has led to a better understanding of which treatments will be most effective.

At the simplest level, this understanding allows targeted therapy against cancer, in which drugs (quite often complex biological molecules) are used to target very specific genetic changes in cancer cells. For example, around 15–20% of malignant breast cancers contain cells with a higher than normal level of a protein called HER2 on their surface, which stimulates them to grow. When combined with a suitable test, it means that not only can the drug be given to those patients most likely to benefit, but also the drug, with its associated side effects, need not be given to patients who will not benefit from its use.

So genetic medicine has already transformed the treatment of some cancer patients. The advent of widespread genetic medicine within the NHS is likely to lead to significant benefits for cancer patients, including:

• The identification of patients who are most likely to benefit from particular cancer therapy.

• The avoidance of unnecessary treatments that are less likely to work for specific groups of patients.

• The development of novel therapies targeted at specific tumour cells or cellular pathways.


Not only will precision medicine allow the development of precise and effective treatment strategies for cancer patients whilst improving the overall quality of life, but it will also finally destroy the myth of ‘one size fits all’ cancer therapy.

For an informative chat on how Plextek can assist with your Healthcare technology project, please contact Nigel at healthcare@plextek.com

Save

Save

Save

Save

Save

Save

Save

Save

Save

Being Your User

Nicholas Hill - Chief Executive Officer

By: Nicholas Hill
Chief Executive Officer

19th December 2018

Home » Blog

One of the important steps in the Design Council’s recommendations for good design is called “Being Your Users” and is a “Method to put yourself into the position of your user.” Its purpose is “building an understanding of and empathy with the users of your product …” Approaching product design from this perspective is critical to ensuring that the features incorporated are actually beneficial to the user – as opposed to features that are of benefit to the manufacturer, for example, or “because we can” features that have no obvious benefit at all.

It’s clear that domestic appliances are becoming more sophisticated, a trend which is facilitated by the availability of low-cost sensors and processing power. This has some clear benefits, such as the availability of more energy- or water-efficient wash cycles for example. And if designers stay focused on providing something of value to the end user this is a trend to be welcomed.

In practice, I see examples of what looks rather like engineers wondering what else they can do with all this additional sensor data, rather than being driven by user need. One example is the growing size of the error codes table in the back of most appliance manuals. These may occasionally add value, but for the most part, I see them as reasons why the product you paid good money for is refusing to do the job it is supposed to.

Here’s an example: the “smart” washing machine that I own doesn’t like low water pressure. It has a number of error codes associated with this. What does it do if the mains pressure drops temporarily – e.g. if simultaneously a toilet is flushed and the kitchen tap is running? It stops dead, displays the error code and refuses to do anything else until you power off the machine at the wall socket, forcing you to start the wash cycle again from scratch. This gets even more annoying if you’d set the timer and come back to a half-washed load. In the days before “smart” appliances, a temporary pressure drop would have either simply caused the water to fill more slowly, or else the machine would pause until pressure returned.

In what way does this behaviour benefit the user? Clearly, it doesn’t, and a few moments thought from a design team that was focussed on user needs, “being your user”, would have resulted in a different requirement specification being handed to the engineering team. It’s a good example of what happens when you start implementing a solution without properly considering the problem you are trying to solve.

My “intelligent” dishwasher has a different but equally maddening feature: it doesn’t like soft water. Its designers have clearly put water saving above all else, and the machine relies on either hard water or very dirty plates to counteract the natural foaming of the detergent tablets. With soft water, if you try washing lightly soiled dishes on a quick wash cycle (as you might expect appropriate), the machine is unable to rinse off the detergent. About 20 minutes into the cycle it skips to the end and gives up, leaving you with foamy, unrinsed plates.

I say unable, when the machine is actually unwilling, as all that is required is the application of sufficient water to rinse off the detergent – which is what I, as a user, then have to do manually. Who is working for whom here? Once again the user’s needs have not been at the top of the designer’s agenda when the requirement specification was passed to the engineering team. A truly smart device would finish the job properly, using as much water as was needed, and possibly suggest using less detergent next time.

Unless designers get a better grip, keeping the end user experience on the agenda, I fear examples of this type of machine behaviour will proliferate. We will see our devices, appliances and perhaps vehicles develop an increasingly long list of reasons why they can’t (won’t) perform the function you bought them for – because they’re having a bad hair day today, which becomes your problem to solve.

All to a refrain of “I’m sorry Dave, I’m afraid I can’t do that.”

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

One of the important steps in the Design Council’s recommendations for good design is called “Being Your Users” and is a “Method to put yourself into the position of your user.” Its purpose is “building an understanding of and empathy with the users of your product …” Approaching product design from this perspective is critical to ensuring that the features incorporated are actually beneficial to the user – as opposed to features that are of benefit to the manufacturer, for example, or “because we can” features that have no obvious benefit at all.

It’s clear that domestic appliances are becoming more sophisticated, a trend which is facilitated by the availability of low-cost sensors and processing power. This has some clear benefits, such as the availability of more energy- or water-efficient wash cycles for example. And if designers stay focused on providing something of value to the end user this is a trend to be welcomed.

In practice, I see examples of what looks rather like engineers wondering what else they can do with all this additional sensor data, rather than being driven by user need. One example is the growing size of the error codes table in the back of most appliance manuals. These may occasionally add value, but for the most part, I see them as reasons why the product you paid good money for is refusing to do the job it is supposed to.

Here’s an example: the “smart” washing machine that I own doesn’t like low water pressure. It has a number of error codes associated with this. What does it do if the mains pressure drops temporarily – e.g. if simultaneously a toilet is flushed and the kitchen tap is running? It stops dead, displays the error code and refuses to do anything else until you power off the machine at the wall socket, forcing you to start the wash cycle again from scratch. This gets even more annoying if you’d set the timer and come back to a half-washed load. In the days before “smart” appliances, a temporary pressure drop would have either simply caused the water to fill more slowly, or else the machine would pause until pressure returned.

In what way does this behaviour benefit the user? Clearly, it doesn’t, and a few moments thought from a design team that was focussed on user needs, “being your user”, would have resulted in a different requirement specification being handed to the engineering team. It’s a good example of what happens when you start implementing a solution without properly considering the problem you are trying to solve.

My “intelligent” dishwasher has a different but equally maddening feature: it doesn’t like soft water. Its designers have clearly put water saving above all else, and the machine relies on either hard water or very dirty plates to counteract the natural foaming of the detergent tablets. With soft water, if you try washing lightly soiled dishes on a quick wash cycle (as you might expect appropriate), the machine is unable to rinse off the detergent. About 20 minutes into the cycle it skips to the end and gives up, leaving you with foamy, unrinsed plates.

I say unable, when the machine is actually unwilling, as all that is required is the application of sufficient water to rinse off the detergent – which is what I, as a user, then have to do manually. Who is working for whom here? Once again the user’s needs have not been at the top of the designer’s agenda when the requirement specification was passed to the engineering team. A truly smart device would finish the job properly, using as much water as was needed, and possibly suggest using less detergent next time.

Unless designers get a better grip, keeping the end user experience on the agenda, I fear examples of this type of machine behaviour will proliferate. We will see our devices, appliances and perhaps vehicles develop an increasingly long list of reasons why they can’t (won’t) perform the function you bought them for – because they’re having a bad hair day today, which becomes your problem to solve.

All to a refrain of “I’m sorry Dave, I’m afraid I can’t do that.”

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Twelve Ways to Style The Twelve Days

By: Kevin Jones
Senior Consultant, Embedded Systems

6th December 2018

Home » Blog

At this time of year I sometimes think about a now-famous piece of obfuscated C code. This was the winning entry in the 1988 International Obfuscated C Code Contest [see reference 1] and, believe it or not, will print the entire lyrics to “The Twelve Days of Christmas”:

#include <stdio.h>
main(t,_,a)
char *a;
{
return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#\
;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \
q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \
){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \
iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \
}'+}##(!!/")
:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
:0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,
"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);
}

There are plenty of articles online that explain how this works; just use your favourite search engine to find out more [see reference 2]. Rather than repeat those descriptions, I’ll stick to the festive theme that prompted this blog and illustrate twelve ways to improve the readability of this wonderful algorithm.

1) Extract the Constant Strings

There are two strings lurking in the source code. The longer string contains an encoded version of the song lyrics and the shorter string contains a substitution cipher to decode the lyrics. The source code is immediately much clearer if these strings are declared near the beginning of the file. In the following example, “static” limits the scope of the strings to one source file and “const” declares them as read-only. I like to use uppercase symbols for constants but that’s nothing more than personal choice. Here’s the modified source code:

#include <stdio.h>

static const char *CIPHER =
"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry";

static const char *LYRICS =
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#\
;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \
q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \
){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \
iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \
}'+}##(!!/";

main(t,_,a)
char *a;
{
return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,LYRICS)
:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
:0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

2) Reformat the Strings

The two strings are recursively indexed to decode and display the lyrics. Reformatting these strings helps to understand the algorithm. In the next step the lyrics and the cipher are declared using C’s alternative string concatenation syntax. The substitution cipher is split after the 31st character, the lyrics are split at each “/” character and the original code’s “\” concatenation in the lyrics string has been eliminated. There’s also some indentation to improve readability:

#include <stdio.h>

static const char *CIPHER =
     "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:"
    "\nuwloca-O;m .vpbks,fxntdCeghiry";

static const char *LYRICS =
    "@n'+,#'/"
    "*{}w+/"
    "w#cdnr/"
    "+,{}r/"
    "*de}+,/"
    "*{*+,/"
    "w{%+,/"
    "w#q#n+,/"
    "#{l+,/"
    "n{n+,/"
    "+#n+,/"
    "#;#q#n+,/"
    "+k#;*+,/"
    "'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/"
    "+k#;q#'r}eKK#}w'r}eKK{nl]'/"
    "#;#q#n'){)#}w'){){nl]'/"
    "+#n';d}rw' i;# ){nl]!/"
    "n{n#'; r{#w'r nc{nl]'/"
    "#{l,+'K {rw' iK{;[{nl]'/"
    "w#q#n'wk nw' iwk{KK{nl]!/"
    "w{%'l##w#' i; :{nl]'/"
    "*{q#'ld;r'}{nlwb!/"
    "*de}'c ;;{nl'-{}rw]'/"
    "+,}##'*}#nc,',#nw]'/"
    "+kd'+e}+;#'rdq#w! nr'/"
    " ') }+}{rl#'{n' ')# }'+}##(!!/";

main(t,_,a)
char *a;
{
return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,LYRICS)
:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
:0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

3) Add Some Comments

All good programmers know that comments are useful. Annotating the constant strings immediately helps understand the algorithm even before any changes are made to the function. I prefer block comments for maximum portability but end-of-line comments would work just as well:

static const char *CIPHER =
    /*
    * Substitution cipher:
    * Replace '!' with '\n'
    * Replace 'e' with 'u'
    * ...
    * Replace ':' with 'y'
    */
     "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:"
    "\nuwloca-O;m .vpbks,fxntdCeghiry";

static const char *LYRICS =
    "@n'+,#'/"  /* On the */
    "*{}w+/"    /* first */
    "w#cdnr/"   /* second */
    "+,{}r/"    /* third */
    "*de}+,/"   /* fourth */
    "*{*+,/"    /* fifth */
    "w{%+,/"    /* sixth */
    "w#q#n+,/"  /* seventh */
    "#{l+,/"    /* eighth */
    "n{n+,/"    /* ninth */
    "+#n+,/"    /* tenth */
    "#;#q#n+,/" /* eleventh */
    "+k#;*+,/"  /* twelfth */

    /* day of Christmas my true love gave to me\n */
    "'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/"

    /* twelve drummers drumming, */
    "+k#;q#'r}eKK#}w'r}eKK{nl]'/"

    /* eleven pipers piping, */
    "#;#q#n'){)#}w'){){nl]'/"

    /* ten lords a-leaping,\n */
    "+#n';d}rw' i;# ){nl]!/"

    /* nine ladies dancing, */
    "n{n#'; r{#w'r nc{nl]'/"

    /* eight maids a-milking, */
    "#{l,+'K {rw' iK{;[{nl]'/"

    /* seven swans a-swimming,\n */
    "w#q#n'wk nw' iwk{KK{nl]!/"

    /* six geese a-laying, */
    "w{%'l##w#' i; :{nl]'/"

    /* five gold rings;\n */
    "*{q#'ld;r'}{nlwb!/"

    /* four calling birds, */
    "*de}'c ;;{nl'-{}rw]'/"

    /* three french hens, */
    "+,}##'*}#nc,',#nw]'/"

    /* two turtle doves\nand */
    "+kd'+e}+;#'rdq#w! nr'/"

    /* a partridge in a pear tree */
    " ') }+}{rl#'{n' ')# }'+}##(!!/";

4) Indent the Function Contents

This step is straight forward… simply indent the contents of the single function:

main(t,_,a)
char *a;
{
    return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
    1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
    main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,LYRICS)
    :t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
    :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

5) Eliminate Implicit Types

If you’re compiling the examples then you may have noticed that there are plenty of implicit type warnings. The main function uses an old C syntax to declare parameter “a” as pointer-to-char. The remaining parameters are implicit integers and the return type of the main function is also an implicit integer. These are fixed in the next sample while taking the opportunity to include the “const” type qualifier:

int main(int t, int _, const char *a)
{
    return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
    1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
    main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,LYRICS)
    :t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
    :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

6) Rename the Underscore Parameter

The second parameter of the main function is a single underscore. While this is perfectly legal in C, it’s a lot harder to read than an alphabetic character. The next sample has replaced all instances of the underscore parameter with the single character “b”:

int main(int t, int b, const char *a)
{
    return!0<t?t<3?main(-79,-13,a+main(-87,1-b,main(-86,0,a+1)+a)):
    1,t<b?main(t+1,b,a):3,main(-94,-27+t,a)&&t==2?b<13?
    main(2,b+1,"%s %d %d\n"):9:16:t<0?t<-72?main(b,t,LYRICS)
    :t<-50?b==*a?putchar(31[a]):main(-65,b,a+1):main((*a=='/')+t,b,a+1)
    :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

7) Reformat the Ternary Conditional Operator

The obfuscated implementation makes extensive use of the ternary conditional operator. The next sample reformats these ternary operators with some additional whitespace:

int main(int t, int b, const char *a)
{
    return
    !0<t
    ?
        t<3
        ?
            main(-79,-13,a+main(-87,1-b,main(-86,0,a+1)+a))
        :
            1, t<b
            ?
                main(t+1,b,a)
            :
                3, main(-94,-27+t,a)&&t==2
                ?
                    b<13
                    ?
                        main(2,b+1,"%s %d %d\n")
                    :
                        9
                :
                    16
    :
        t<0
        ?
            t<-72
            ?
                main(b,t,LYRICS)
            :
                t<-50
                ?
                    b==*a
                    ?
                        putchar(31[a])
                    :
                        main(-65,b,a+1)
                :
                    main((*a=='/')+t,b,a+1)
        :
            0<t
            ?
                main(2,2,"%s")
            :
                *a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

8) Replace the Ternary Conditional Statements with If-Else

A simple replacement of the ternary conditional statements with if-else statements improves the presentation of the algorithm. In the following sample, there is yet more white space and the multiple return points have been rationalised into a single point of return by using a temporary integer variable “r”:

int main(int t, int b, const char *a)
{
    int r;
    if (!0 < t)
    {
        if (t < 3)
        {
            main(-79, -13, a + main(-87, 1 - b, main(-86, 0, a + 1) + a));
        }
        else
        {
            1;
        }
        if (t < b)
        {
            main(t + 1, b, a);
        }
        else
        {
            3;
        }
        if (main(-94, -27 + t, a) && t == 2)
        {
            if (b < 13)
            {
                r = main(2, b + 1, "%s %d %d\n");
            }
            else
            {
                r = 9;
            }
        }
        else
        {
            r = 16;
        }
    }
    else
    {
        if (t < 0)
        {
            if (t < -72)
            {
                r = main(b, t, LYRICS);
            }
            else
            {
                if (t < -50)
                {
                    if (b == *a)
                    {
                        r = putchar(31[a]);
                    }
                    else
                    {
                        r = main(-65, b, a + 1);
                    }
                }
                else
                {
                    r = main((*a == '/') + t, b, a + 1);
                }
            }
        }
        else
        {
            if (0 < t)
            {
                r = main(2, 2, "%s");
            }
            else
            {
                r = *a == '/' || main(0, main(-61, *a, CIPHER), a + 1);
            }
        }
    }
    return r;
}

9) Simplify an Array Access

This change is straight forward. The array access “31[a]” is exactly the same as “a[31]” yet the latter is much easier to understand in the context of the 31 character substitution cipher:

    ...
    r = putchar(a[31]);
    ...

10) Add Brackets to Logical Expressions

Personally, I prefer plenty of brackets in compound logical expressions. The following snips are small improvements:

    ...
    if (main(-94, -27 + t, a) && (t == 2))
    ...

    ...
    r = ((*a == '/') || (main(0, main(-61, *a, CIPHER), a + 1)));
    ...

11) Remove Misdirection

There are several instances where the implementation is deliberately misleading. Given the reformatted source code so far, it’s easy to see that there are two “else” clauses with no side effects (“else {1;}” and “else {3;}”). Less obvious is that the parameters that look like string formatting specifiers passed to the main function are unused in that iteration of the function and can be replaced with zero:

    ...
    if (b < 13)
    {
        r = main(2, b + 1, 0);
    }
    ...

    ...
    r = main(2, 2, 0);
    ...

12) Implement a Stand-Alone Recursive Function

The entire algorithm so far uses the single “main” function in an unusual recursive manner. After the last of the twelve changes, the main function looks like a standard C main function and there’s a separate local-scope (static) recursive function which, in time-honoured programmer’s tradition, is called “foo”. This gives the final complete sample after all twelve changes:

#include <stdio.h>

static const char *CIPHER =
    /*
    * Substitution cipher:
    * Replace '!' with '\n'
    * Replace 'e' with 'u'
    * ...
    * Replace ':' with 'y'
    */
     "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:"
    "\nuwloca-O;m .vpbks,fxntdCeghiry";

static const char *LYRICS =
    "@n'+,#'/"  /* On the */
    "*{}w+/"    /* first */
    "w#cdnr/"   /* second */
    "+,{}r/"    /* third */
    "*de}+,/"   /* fourth */
    "*{*+,/"    /* fifth */
    "w{%+,/"    /* sixth */
    "w#q#n+,/"  /* seventh */
    "#{l+,/"    /* eighth */
    "n{n+,/"    /* ninth */
    "+#n+,/"    /* tenth */
    "#;#q#n+,/" /* eleventh */
    "+k#;*+,/"  /* twelfth */

    /* day of Christmas my true love gave to me\n */
    "'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/"

    /* twelve drummers drumming, */
    "+k#;q#'r}eKK#}w'r}eKK{nl]'/"

    /* eleven pipers piping, */
    "#;#q#n'){)#}w'){){nl]'/"

    /* ten lords a-leaping,\n */
    "+#n';d}rw' i;# ){nl]!/"

    /* nine ladies dancing, */
    "n{n#'; r{#w'r nc{nl]'/"

    /* eight maids a-milking, */
    "#{l,+'K {rw' iK{;[{nl]'/"

    /* seven swans a-swimming,\n */
    "w#q#n'wk nw' iwk{KK{nl]!/"

    /* six geese a-laying, */
    "w{%'l##w#' i; :{nl]'/"

    /* five gold rings;\n */
    "*{q#'ld;r'}{nlwb!/"

    /* four calling birds, */
    "*de}'c ;;{nl'-{}rw]'/"

    /* three french hens, */
    "+,}##'*}#nc,',#nw]'/"

    /* two turtle doves\nand */
    "+kd'+e}+;#'rdq#w! nr'/"

    /* a partridge in a pear tree */
    " ') }+}{rl#'{n' ')# }'+}##(!!/";

static int foo(int t, int b, const char *a)
{
    int r;
    if (!0 < t)
    {
        if (t < 3)
        {
            foo(-79, -13, a + foo(-87, 1 - b, foo(-86, 0, a + 1) + a));
        }
        if (t < b)
        {
            foo(t + 1, b, a);
        }
        if (foo(-94, -27 + t, a) && (t == 2))
        {
            if (b < 13)
            {
                r = foo(2, b + 1, 0);
            }
            else
            {
                r = 9;
            }
        }
        else
        {
            r = 16;
        }
    }
    else
    {
        if (t < 0)
        {
            if (t < -72)
            {
                r = foo(b, t, LYRICS);
            }
            else
            {
                if (t < -50)
                {
                    if (b == *a)
                    {
                        r = putchar(a[31]);
                    }
                    else
                    {
                        r = foo(-65, b, a + 1);
                    }
                }
                else
                {
                    r = foo((*a == '/') + t, b, a + 1);
                }
            }
        }
        else
        {
            if (0 < t)
            {
                r = foo(2, 2, 0);
            }
            else
            {
                r = ((*a == '/') || (foo(0, foo(-61, *a, CIPHER), a + 1)));
            }
        }
    }
    return r;
}

int main(int argc, char *argv[])
{
    return foo(1, 0, 0);
}

There are plenty of changes that could still be made to improve readability, such as more comments and replacing the recursive algorithm with iterative loops… but I’ve made my promised twelve improvements, leaving you with plenty of opportunity to make some of your own.



[1] At the time of writing this blog, the original code can be found on the International Obfuscated C Code Contest website on the “Winning Entries” web page, listed as “phillipps.c” under the 1988 sub-heading.

[2] Credit goes to an analysis by Mike Markowski and to a similar exercise in reformatting the source code by Michael Nahas.

At this time of year I sometimes think about a now-famous piece of obfuscated C code. This was the winning entry in the 1988 International Obfuscated C Code Contest [see reference 1] and, believe it or not, will print the entire lyrics to “The Twelve Days of Christmas”:

#include <stdio.h>
main(t,_,a)
char *a;
{
return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#\
;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \
q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \
){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \
iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \
}'+}##(!!/")
:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
:0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,
"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);
}

There are plenty of articles online that explain how this works; just use your favourite search engine to find out more [see reference 2]. Rather than repeat those descriptions, I’ll stick to the festive theme that prompted this blog and illustrate twelve ways to improve the readability of this wonderful algorithm.

1) Extract the Constant Strings

There are two strings lurking in the source code. The longer string contains an encoded version of the song lyrics and the shorter string contains a substitution cipher to decode the lyrics. The source code is immediately much clearer if these strings are declared near the beginning of the file. In the following example, “static” limits the scope of the strings to one source file and “const” declares them as read-only. I like to use uppercase symbols for constants but that’s nothing more than personal choice. Here’s the modified source code:

#include <stdio.h>

static const char *CIPHER =
"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry";

static const char *LYRICS =
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#\
;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \
q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \
){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \
iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \
}'+}##(!!/";

main(t,_,a)
char *a;
{
return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,LYRICS)
:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
:0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

2) Reformat the Strings

The two strings are recursively indexed to decode and display the lyrics. Reformatting these strings helps to understand the algorithm. In the next step the lyrics and the cipher are declared using C’s alternative string concatenation syntax. The substitution cipher is split after the 31st character, the lyrics are split at each “/” character and the original code’s “\” concatenation in the lyrics string has been eliminated. There’s also some indentation to improve readability:

#include <stdio.h>

static const char *CIPHER =
     "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:"
    "\nuwloca-O;m .vpbks,fxntdCeghiry";

static const char *LYRICS =
    "@n'+,#'/"
    "*{}w+/"
    "w#cdnr/"
    "+,{}r/"
    "*de}+,/"
    "*{*+,/"
    "w{%+,/"
    "w#q#n+,/"
    "#{l+,/"
    "n{n+,/"
    "+#n+,/"
    "#;#q#n+,/"
    "+k#;*+,/"
    "'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/"
    "+k#;q#'r}eKK#}w'r}eKK{nl]'/"
    "#;#q#n'){)#}w'){){nl]'/"
    "+#n';d}rw' i;# ){nl]!/"
    "n{n#'; r{#w'r nc{nl]'/"
    "#{l,+'K {rw' iK{;[{nl]'/"
    "w#q#n'wk nw' iwk{KK{nl]!/"
    "w{%'l##w#' i; :{nl]'/"
    "*{q#'ld;r'}{nlwb!/"
    "*de}'c ;;{nl'-{}rw]'/"
    "+,}##'*}#nc,',#nw]'/"
    "+kd'+e}+;#'rdq#w! nr'/"
    " ') }+}{rl#'{n' ')# }'+}##(!!/";

main(t,_,a)
char *a;
{
return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,LYRICS)
:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
:0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

3) Add Some Comments

All good programmers know that comments are useful. Annotating the constant strings immediately helps understand the algorithm even before any changes are made to the function. I prefer block comments for maximum portability but end-of-line comments would work just as well:

static const char *CIPHER =
    /*
    * Substitution cipher:
    * Replace '!' with '\n'
    * Replace 'e' with 'u'
    * ...
    * Replace ':' with 'y'
    */
     "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:"
    "\nuwloca-O;m .vpbks,fxntdCeghiry";

static const char *LYRICS =
    "@n'+,#'/"  /* On the */
    "*{}w+/"    /* first */
    "w#cdnr/"   /* second */
    "+,{}r/"    /* third */
    "*de}+,/"   /* fourth */
    "*{*+,/"    /* fifth */
    "w{%+,/"    /* sixth */
    "w#q#n+,/"  /* seventh */
    "#{l+,/"    /* eighth */
    "n{n+,/"    /* ninth */
    "+#n+,/"    /* tenth */
    "#;#q#n+,/" /* eleventh */
    "+k#;*+,/"  /* twelfth */

    /* day of Christmas my true love gave to me\n */
    "'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/"

    /* twelve drummers drumming, */
    "+k#;q#'r}eKK#}w'r}eKK{nl]'/"

    /* eleven pipers piping, */
    "#;#q#n'){)#}w'){){nl]'/"

    /* ten lords a-leaping,\n */
    "+#n';d}rw' i;# ){nl]!/"

    /* nine ladies dancing, */
    "n{n#'; r{#w'r nc{nl]'/"

    /* eight maids a-milking, */
    "#{l,+'K {rw' iK{;[{nl]'/"

    /* seven swans a-swimming,\n */
    "w#q#n'wk nw' iwk{KK{nl]!/"

    /* six geese a-laying, */
    "w{%'l##w#' i; :{nl]'/"

    /* five gold rings;\n */
    "*{q#'ld;r'}{nlwb!/"

    /* four calling birds, */
    "*de}'c ;;{nl'-{}rw]'/"

    /* three french hens, */
    "+,}##'*}#nc,',#nw]'/"

    /* two turtle doves\nand */
    "+kd'+e}+;#'rdq#w! nr'/"

    /* a partridge in a pear tree */
    " ') }+}{rl#'{n' ')# }'+}##(!!/";

4) Indent the Function Contents

This step is straight forward… simply indent the contents of the single function:

main(t,_,a)
char *a;
{
    return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
    1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
    main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,LYRICS)
    :t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
    :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

5) Eliminate Implicit Types

If you’re compiling the examples then you may have noticed that there are plenty of implicit type warnings. The main function uses an old C syntax to declare parameter “a” as pointer-to-char. The remaining parameters are implicit integers and the return type of the main function is also an implicit integer. These are fixed in the next sample while taking the opportunity to include the “const” type qualifier:

int main(int t, int _, const char *a)
{
    return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
    1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
    main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,LYRICS)
    :t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
    :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

6) Rename the Underscore Parameter

The second parameter of the main function is a single underscore. While this is perfectly legal in C, it’s a lot harder to read than an alphabetic character. The next sample has replaced all instances of the underscore parameter with the single character “b”:

int main(int t, int b, const char *a)
{
    return!0<t?t<3?main(-79,-13,a+main(-87,1-b,main(-86,0,a+1)+a)):
    1,t<b?main(t+1,b,a):3,main(-94,-27+t,a)&&t==2?b<13?
    main(2,b+1,"%s %d %d\n"):9:16:t<0?t<-72?main(b,t,LYRICS)
    :t<-50?b==*a?putchar(31[a]):main(-65,b,a+1):main((*a=='/')+t,b,a+1)
    :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

7) Reformat the Ternary Conditional Operator

The obfuscated implementation makes extensive use of the ternary conditional operator. The next sample reformats these ternary operators with some additional whitespace:

int main(int t, int b, const char *a)
{
    return
    !0<t
    ?
        t<3
        ?
            main(-79,-13,a+main(-87,1-b,main(-86,0,a+1)+a))
        :
            1, t<b
            ?
                main(t+1,b,a)
            :
                3, main(-94,-27+t,a)&&t==2
                ?
                    b<13
                    ?
                        main(2,b+1,"%s %d %d\n")
                    :
                        9
                :
                    16
    :
        t<0
        ?
            t<-72
            ?
                main(b,t,LYRICS)
            :
                t<-50
                ?
                    b==*a
                    ?
                        putchar(31[a])
                    :
                        main(-65,b,a+1)
                :
                    main((*a=='/')+t,b,a+1)
        :
            0<t
            ?
                main(2,2,"%s")
            :
                *a=='/'||main(0,main(-61,*a,CIPHER),a+1);
}

8) Replace the Ternary Conditional Statements with If-Else

A simple replacement of the ternary conditional statements with if-else statements improves the presentation of the algorithm. In the following sample, there is yet more white space and the multiple return points have been rationalised into a single point of return by using a temporary integer variable “r”:

int main(int t, int b, const char *a)
{
    int r;
    if (!0 < t)
    {
        if (t < 3)
        {
            main(-79, -13, a + main(-87, 1 - b, main(-86, 0, a + 1) + a));
        }
        else
        {
            1;
        }
        if (t < b)
        {
            main(t + 1, b, a);
        }
        else
        {
            3;
        }
        if (main(-94, -27 + t, a) && t == 2)
        {
            if (b < 13)
            {
                r = main(2, b + 1, "%s %d %d\n");
            }
            else
            {
                r = 9;
            }
        }
        else
        {
            r = 16;
        }
    }
    else
    {
        if (t < 0)
        {
            if (t < -72)
            {
                r = main(b, t, LYRICS);
            }
            else
            {
                if (t < -50)
                {
                    if (b == *a)
                    {
                        r = putchar(31[a]);
                    }
                    else
                    {
                        r = main(-65, b, a + 1);
                    }
                }
                else
                {
                    r = main((*a == '/') + t, b, a + 1);
                }
            }
        }
        else
        {
            if (0 < t)
            {
                r = main(2, 2, "%s");
            }
            else
            {
                r = *a == '/' || main(0, main(-61, *a, CIPHER), a + 1);
            }
        }
    }
    return r;
}

9) Simplify an Array Access

This change is straight forward. The array access “31[a]” is exactly the same as “a[31]” yet the latter is much easier to understand in the context of the 31 character substitution cipher:

    ...
    r = putchar(a[31]);
    ...

10) Add Brackets to Logical Expressions

Personally, I prefer plenty of brackets in compound logical expressions. The following snips are small improvements:

    ...
    if (main(-94, -27 + t, a) && (t == 2))
    ...

    ...
    r = ((*a == '/') || (main(0, main(-61, *a, CIPHER), a + 1)));
    ...

11) Remove Misdirection

There are several instances where the implementation is deliberately misleading. Given the reformatted source code so far, it’s easy to see that there are two “else” clauses with no side effects (“else {1;}” and “else {3;}”). Less obvious is that the parameters that look like string formatting specifiers passed to the main function are unused in that iteration of the function and can be replaced with zero:

    ...
    if (b < 13)
    {
        r = main(2, b + 1, 0);
    }
    ...

    ...
    r = main(2, 2, 0);
    ...

12) Implement a Stand-Alone Recursive Function

The entire algorithm so far uses the single “main” function in an unusual recursive manner. After the last of the twelve changes, the main function looks like a standard C main function and there’s a separate local-scope (static) recursive function which, in time-honoured programmer’s tradition, is called “foo”. This gives the final complete sample after all twelve changes:

#include <stdio.h>

static const char *CIPHER =
    /*
    * Substitution cipher:
    * Replace '!' with '\n'
    * Replace 'e' with 'u'
    * ...
    * Replace ':' with 'y'
    */
     "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:"
    "\nuwloca-O;m .vpbks,fxntdCeghiry";

static const char *LYRICS =
    "@n'+,#'/"  /* On the */
    "*{}w+/"    /* first */
    "w#cdnr/"   /* second */
    "+,{}r/"    /* third */
    "*de}+,/"   /* fourth */
    "*{*+,/"    /* fifth */
    "w{%+,/"    /* sixth */
    "w#q#n+,/"  /* seventh */
    "#{l+,/"    /* eighth */
    "n{n+,/"    /* ninth */
    "+#n+,/"    /* tenth */
    "#;#q#n+,/" /* eleventh */
    "+k#;*+,/"  /* twelfth */

    /* day of Christmas my true love gave to me\n */
    "'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/"

    /* twelve drummers drumming, */
    "+k#;q#'r}eKK#}w'r}eKK{nl]'/"

    /* eleven pipers piping, */
    "#;#q#n'){)#}w'){){nl]'/"

    /* ten lords a-leaping,\n */
    "+#n';d}rw' i;# ){nl]!/"

    /* nine ladies dancing, */
    "n{n#'; r{#w'r nc{nl]'/"

    /* eight maids a-milking, */
    "#{l,+'K {rw' iK{;[{nl]'/"

    /* seven swans a-swimming,\n */
    "w#q#n'wk nw' iwk{KK{nl]!/"

    /* six geese a-laying, */
    "w{%'l##w#' i; :{nl]'/"

    /* five gold rings;\n */
    "*{q#'ld;r'}{nlwb!/"

    /* four calling birds, */
    "*de}'c ;;{nl'-{}rw]'/"

    /* three french hens, */
    "+,}##'*}#nc,',#nw]'/"

    /* two turtle doves\nand */
    "+kd'+e}+;#'rdq#w! nr'/"

    /* a partridge in a pear tree */
    " ') }+}{rl#'{n' ')# }'+}##(!!/";

static int foo(int t, int b, const char *a)
{
    int r;
    if (!0 < t)
    {
        if (t < 3)
        {
            foo(-79, -13, a + foo(-87, 1 - b, foo(-86, 0, a + 1) + a));
        }
        if (t < b)
        {
            foo(t + 1, b, a);
        }
        if (foo(-94, -27 + t, a) && (t == 2))
        {
            if (b < 13)
            {
                r = foo(2, b + 1, 0);
            }
            else
            {
                r = 9;
            }
        }
        else
        {
            r = 16;
        }
    }
    else
    {
        if (t < 0)
        {
            if (t < -72)
            {
                r = foo(b, t, LYRICS);
            }
            else
            {
                if (t < -50)
                {
                    if (b == *a)
                    {
                        r = putchar(a[31]);
                    }
                    else
                    {
                        r = foo(-65, b, a + 1);
                    }
                }
                else
                {
                    r = foo((*a == '/') + t, b, a + 1);
                }
            }
        }
        else
        {
            if (0 < t)
            {
                r = foo(2, 2, 0);
            }
            else
            {
                r = ((*a == '/') || (foo(0, foo(-61, *a, CIPHER), a + 1)));
            }
        }
    }
    return r;
}

int main(int argc, char *argv[])
{
    return foo(1, 0, 0);
}

There are plenty of changes that could still be made to improve readability, such as more comments and replacing the recursive algorithm with iterative loops… but I’ve made my promised twelve improvements, leaving you with plenty of opportunity to make some of your own.

[1] At the time of writing this blog, the original code can be found on the International Obfuscated C Code Contest website on the “Winning Entries” web page, listed as “phillipps.c” under the 1988 sub-heading.

[2] Credit goes to an analysis by Mike Markowski and to a similar exercise in reformatting the source code by Michael Nahas.

Ai, healthcare, alzheimers, medical imaging

The Future Impact of Artificial Intelligence in Medical Practice

Nigel Whittle - Head of Medical & Healthcare

By: Nigel Whittle
Head of Medical & Healthcare

5th December 2018

Home » Blog

We are all aware of the challenges facing healthcare in general, and the NHS in particular. Shortage of funding, increased demands for services, rising costs of innovative drug treatments, the needs of an ageing population. All these issues limit the efficacy of our healthcare service.

There is only so much that can be done with improved efficiency. But what if we could improve diagnosis, so that diseases are detected and treated earlier? In almost every disease, early diagnosis would allow cheaper and more effective treatment, with improved patient outcomes. But of course accuracy is important too, so that scarce resources can be targeted to the right patients.

And that is what makes clinical diagnosis so difficult, requiring skilled and knowledgeable practitioners, whether the local GP or the Harley Street physician. These skills, developed by years of medical training, allow effective diagnosis of disease based not just on clinical information, but also on the patients past history, social background, age and ethnicity.

But at the end of the day, the clinician is simply processing data. And this is the primary strength of Artificial Intelligence.

So which areas are likely to be most impacted by AI?

Medical Imaging

medical imaging, HEALTHCARE , AIUK hospitals generate a staggering 50 petabytes of data every year, of which the vast majority comes from medical imaging. But more than 97% of that data is unused or unanalysed, perhaps because it is unusable, or redundant, or simply swamping the capacities of the clinicians. But AI-powered medical imaging systems can now reliably produce scans that help radiologists identify subtle patterns, helping them treat patients with emergent conditions more quickly. Will this lead to the disappearance of radiology as a clinical profession? Perhaps a more likely outcome is that radiologists will be able to allocate their time more effectively, to work closely with patients with the most serious or complex conditions.

Similarly, cancer diagnosis can be made more accurate through the use of AI systems running scans linked to complex recognition algorithms. When cancer is detected early, treatment is more likely to be successful. But too often, cancers are diagnosed at a late stage when they’re much harder to treat. But AI systems are beginning to take on some of the workload: for example, an algorithm has been developed to diagnose skin cancer more accurately than dermatologists (95% compared with 87%). But in doing so, we must remember that AI systems are not infallible, and the relationship between the patient and the doctor is important so that false negatives are not dismissed out of hand.

In another example, researchers at Imperial College London are working with DeepMind Health to develop AI-based techniques to improve the accuracy of breast cancer screening, using a database of 7,500 anonymised mammograms to develop screening algorithms that can spot early signs of breast cancer whilst reducing over-diagnosis.

But perhaps more interestingly, could there be ways to detect hidden clues in people’s lives that point to cancer? As we generate, collect and share more data than ever before, some of which may be relevant to our health, is there a way to gather this information and help detect diseases such as cancer earlier? And even if it is possible, is it something that we would allow big data systems and corporations to do?

Alzheimer’s Disease

Currently, there’s no easy way to diagnose Alzheimer’s Disease: no single test exists, and brain scans alone can’t determine whether someone has the disease. But alterations in the brain can cause subtle changes in behaviour and sleep patterns years before people start experiencing confusion and memory loss. Artificial intelligence could recognize these changes early and identify patients at risk of developing the most severe forms of the disease, allowing clinicians to target drug and behavioural therapies most effectively.

ai, healthcare, patient doctor

The role of the doctor

It is clear that managing patient data is a core component of the healthcare delivery process, and AI systems will increasingly play an important role in this process. AI is capable of processing larger amounts of data and at a faster rate than human clinicians, is capable of achieving a higher level of accuracy and is not subject to fatigue or burnout.

Which naturally raises a question, what will be the future role of the doctor?

No matter is strengths, AI lacks human sensitivity; clinical applications still require human expertise in the interpretation of data and recommendations. As the role of the physician evolves in the era of AI, the humanity of healthcare delivery will remain critical, and rituals (‘the bedside manner’) that may have been lost in the rush for efficiency savings may emerge with a new-found focus on the patient at the centre of treatment.

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

 

 

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save


If you are interested in talking to Nigel Whittle, our Head of Medical & Healthcare about how Plextek can assist with your project, please email nigel.whittle@plextek.com

We are all aware of the challenges facing healthcare in general, and the NHS in particular. Shortage of funding, increased demands for services, rising costs of innovative drug treatments, the needs of an ageing population. All these issues limit the efficacy of our healthcare service.

There is only so much that can be done with improved efficiency. But what if we could improve diagnosis, so that diseases are detected and treated earlier? In almost every disease, early diagnosis would allow cheaper and more effective treatment, with improved patient outcomes. But of course accuracy is important too, so that scarce resources can be targeted to the right patients.

And that is what makes clinical diagnosis so difficult, requiring skilled and knowledgeable practitioners, whether the local GP or the Harley Street physician. These skills, developed by years of medical training, allow effective diagnosis of disease based not just on clinical information, but also on the patients past history, social background, age and ethnicity.

But at the end of the day, the clinician is simply processing data. And this is the primary strength of Artificial Intelligence.

So which areas are likely to be most impacted by AI?

Medical Imaging

medical imaging, HEALTHCARE , AIUK hospitals generate a staggering 50 petabytes of data every year, of which the vast majority comes from medical imaging. But more than 97% of that data is unused or unanalysed, perhaps because it is unusable, or redundant, or simply swamping the capacities of the clinicians. But AI-powered medical imaging systems can now reliably produce scans that help radiologists identify subtle patterns, helping them treat patients with emergent conditions more quickly. Will this lead to the disappearance of radiology as a clinical profession? Perhaps a more likely outcome is that radiologists will be able to allocate their time more effectively, to work closely with patients with the most serious or complex conditions.

Similarly, cancer diagnosis can be made more accurate through the use of AI systems running scans linked to complex recognition algorithms. When cancer is detected early, treatment is more likely to be successful. But too often, cancers are diagnosed at a late stage when they’re much harder to treat. But AI systems are beginning to take on some of the workload: for example, an algorithm has been developed to diagnose skin cancer more accurately than dermatologists (95% compared with 87%). But in doing so, we must remember that AI systems are not infallible, and the relationship between the patient and the doctor is important so that false negatives are not dismissed out of hand.

In another example, researchers at Imperial College London are working with DeepMind Health to develop AI-based techniques to improve the accuracy of breast cancer screening, using a database of 7,500 anonymised mammograms to develop screening algorithms that can spot early signs of breast cancer whilst reducing over-diagnosis.
But perhaps more interestingly, could there be ways to detect hidden clues in people’s lives that point to cancer? As we generate, collect and share more data than ever before, some of which may be relevant to our health, is there a way to gather this information and help detect diseases such as cancer earlier? And even if it is possible, is it something that we would allow big data systems and corporations to do?

Alzheimer’s Disease

ai, healthcare, patient doctorCurrently, there’s no easy way to diagnose Alzheimer’s Disease: no single test exists, and brain scans alone can’t determine whether someone has the disease. But alterations in the brain can cause subtle changes in behaviour and sleep patterns years before people start experiencing confusion and memory loss. Artificial intelligence could recognize these changes early and identify patients at risk of developing the most severe forms of the disease, allowing clinicians to target drug and behavioural therapies most effectively.

The role of the doctor

It is clear that managing patient data is a core component of the healthcare delivery process, and AI systems will increasingly play an important role in this process. AI is capable of processing larger amounts of data and at a faster rate than human clinicians, is capable of achieving a higher level of accuracy and is not subject to fatigue or burnout.

Which naturally raises a question, what will be the future role of the doctor?

No matter is strengths, AI lacks human sensitivity; clinical applications still require human expertise in the interpretation of data and recommendations. As the role of the physician evolves in the era of AI, the humanity of healthcare delivery will remain critical, and rituals (‘the bedside manner’) that may have been lost in the rush for efficiency savings may emerge with a new-found focus on the patient at the centre of treatment.

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save


If you are interested in talking to Nigel Whittle, our Head of Medical & Healthcare about how Plextek can assist with your project, please email nigel.whittle@plextek.com