Skip to main content
added 54 characters in body
Source Link
anatolyg
  • 13.9k
  • 2
  • 39
  • 110

C, 260260 248 bytes

−12 bytes thanks to ceilingcat

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?

#define P ,s--||printf(
q=94,s,c,t,a;maint;main(a){char i[999]char*p,*p=ii[999],*e=p;gets*e=p=i;for(gets(i);for(;c=*p++;q=c=*p++,t=q^94|c^45?c%26==16c%26-16?c%16/3:c/46:c%16/3:1,s=(a="30PCqspP#!C@ #cS` #!cpp#q"[s*5+t])/16-3,a&1&&(p[-1]=0)1]*=~a&1,t||(!t?0 P"*0"),P"/x"),P"/x*%s",e),P"*ln(%s)",e),s=0):0,a&2&&(e=p)e=a&2?p:e,c;putcharprintf(q=c&c););}

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?

#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));}

C, 260 248 bytes

−12 bytes thanks to ceilingcat

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?

#define P,s--||printf(
q=94,s,c,t;main(a){char*p,i[999],*e=p=i;for(gets(i);q=c=*p++,t=q^94|c^45?c%26-16?c/46:c%16/3:1,s=(a="30PCqspP#!C@ #cS` #!cpp#q"[s*5+t])/16-3,p[-1]*=~a&1,!t?0 P"*0")P"/x")P"/x*%s",e)P"*ln(%s)",e),s=0:0,e=a&2?p:e,printf(&c););}
Added a note on using gets()
Source Link
anatolyg
  • 13.9k
  • 2
  • 39
  • 110

P.S. Watch out for that gets function: it has a security vulnerability that can let your teacher execute a rootkit in your mind by providing too long input...

P.S. Watch out for that gets function: it has a security vulnerability that can let your teacher execute a rootkit in your mind by providing too long input...

Source Link
anatolyg
  • 13.9k
  • 2
  • 39
  • 110

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;
    }
}