C, 260
Hey, I think I know your teacher! Isn't it that one who has the supernatural ability to detect students executing library pattern-matching functions in their head?
So, using sscanf
is out of question... But don't worry:
#define P s--||printf(
q=94,s,c,t,a;main(){char i[999],*p=i,*e=p;gets(i);for(;c=*p++,t=q^94|c^45?c%26==16?c%16/3:c/46:1,s=(a="30PCqspP#!C@ #cS` #!cpp#q"[s*5+t])/16-3,a&1&&(p[-1]=0),t||(P"*0"),P"/x"),P"/x*%s",e),P"*ln(%s)",e),s=0),a&2&&(e=p),c;putchar(q=c));}
Running examples (input on stdin
; output goes to stdout
):
4*x^3-2
4*x^3/x*3-2*0
This format is much better than just 12*x^2
, because this way your teacher can be sure that you calculated the answer yourself and didn't cheat by copying it from someone else!
x+2^x
x/x+2^x*ln(2)
The output has a slight domain problem at x=0
, but it's correct almost everywhere!
For reference, here is an ungolfed, readable (by mere mortals) version. It uses a state machine with 5 states and 5 categories of input characters.
void deriv(char* input)
{
char* p = input; // current position
char* exp = p; // base or exponent
char q = '^'; // previous character
// State machine has 5 states; here are examples of input:
// state 0: 123
// state 1: 123*
// state 2: 123*x
// state 3: 123*x^456
// state 4: 123^x
int state = 0;
// Control bits for state machine:
// bit 0: special action: stop recording base or exponent
// bit 1: special action: start recording base or exponent
// bits 4-7: if first column, specify how to calculate the derivative:
// 3 - multiply the constant term by 0
// 4 - divide x by x
// 5 - divide x^n by x and multiply by n
// 6 - multiply n^x by ln(n)
// bits 4-7: if not first column, specify the next state
// (plus 3, to make the character printable)
const char* control =
"\x33\x30\x50\x43\x71"
"\x73\x70\x50\x23\x21"
"\x43\x40\x20\x23\x63"
"\x53\x60\x20\x23\x21"
"\x63\x70\x70\x23\x71";
for (;;) {
int c = *p++;
// Convert a char to a category:
// category 0: // - +
// category 3: // *
// category 2: // x
// category 4: // ^
// category 1: // numbers: 0...9 and decimal point
int category;
int action;
if (q == '^' && c == '-')
category = 1; // unary minus is a part of a number
else
category = c%26==16?c%16/3:c/46; // just does it
// Load new state and action to do
action = control[state * 5 + category];
if (action & 1)
p[-1] = 0;
state = (action >> 4) - 3;
if (category == 0)
{
if (state == 0)
printf("*0");
if (state == 1)
printf("/x");
if (state == 2)
printf("/x*%s", exp);
if (state == 3)
printf("*ln(%s)", exp);
state = 0;
}
if (action & 2)
exp = p;
if (c == 0 || c == '\n') // either of these can mark end of input
break;
putchar(c);
q = c;
}
}