text:
Create a Boolean parser (continued)
Continuation of this challenge because the author is gone and the question is closed.

What you need to do is create a Boolean parser.

Boolean expressions, in case you haven't heard of them yet, have two inputs and one output.
There are four "gates" in boolean arithmetic, namely:

OR (represented by |) (binary operator, between arguments)
AND (represented by &) (binary operator, between arguments)
XOR (represented by ^) (binary operator, between arguments)
NOT (represented by !) (unary operator, argument on right)

These gates operate on their inputs which are either true (represented by 1) or false (represented by 0). We can list the possible inputs (A and B in this case) and the outputs (O) using a truth table as follows:
XOR
A|B|O
-----
0|0|0
0|1|1
1|0|1
1|1|0

OR
A|B|O
-----
0|0|0
0|1|1
1|0|1
1|1|1

AND
A|B|O
-----
0|0|0
0|1|0
1|0|0
1|1|1

NOT
A|O
---
0|1
1|0

An example input would be 1^((1|0&0)^!(1&!0&1)), which would evaluate to:
 1^((1|0&0)^!(1&!0&1))
=1^(( 1 &0)^!(1&!0&1))
=1^(   0   ^!(1&!0&1))
=1^(   0   ^!(1& 1&1))
=1^(   0   ^!(  1 &1))
=1^(   0   ^!    1   )
=1^(   0   ^    0    )
=1^0
=1

The output would be 1.
Details

As seen in the example, there is no order of prevalence. All are evaluated from left to right, except when inside parentheses, which should be evaluated first.
The input will only contain ()!^&|01.
You can choose any 8-byte character to replace the 8 characters above, but they must have a 1-to-1 mapping and must be stated.
Specifically, the function eval is not allowed to be used on any string derived from the input. Specifically, the function input (or the equivalent in the language) and any function that calls it cannot be used by eval. You also cannot concatenate the input into your string inside the eval.

Scoring
This is code-golf. Shortest solution in bytes wins.

Cheddar has a built in to generate a call stack from a string is that disallowed too?

Could you add some more test cases?

@CᴏɴᴏʀO'Bʀɪᴇɴ What test case would you like to see?

@KennyLau A few complicated ones, idk

Is there any condition that the test case did not handle? I think it pretty much handled everything already.

@KennyLau Considering that there are only 2 outputs, a program could still fail some cases even if it passes one test case.

I deliberately designed 1|0&0 so that if they evaluate & first, the output will fail.

Is eval disallowed even when it's not used on input data at all, but instead to golf the parser?

@orlp Is it clear enough now? People will just find loopholes if I make it too explicit (I forgot the name of the phenomenon).

@KennyLau I think you should explicitly say that the input is given as a string (and not any other epression, otherwise you could just use an identity function in many languages).

About testcases: with just 1 or 0 for output I can just put a random function and I will be right 50% of times

@edc65 Please do provide me with more testcases (just the input, I will produce the output) in case of doubt.

are 2 or more consecutive ! allowed? ie !!1

eval won't help as there are different operator priorities.

@JackAmmo Yes, though I do not see how that would posit any problem.

@KennyLau it's not so much a problem as verifying a case that needs to be dealt with

Not enough test cases. Testing my script on your input is just one test case, no matter how complex your test case is. I might get the right output despite getting wrong output on other cases.

One test case should make sure the script parses left-to-right instead of all false substrings first; another should make sure it parses left-to-right instead of all true substrings first; another should make sure it parses left-to-right instead of using the usual order of operations. (That last can probably be combined with one of the others.) Another should use !!.

JavaScript (ES6) 116 bytes
edit thx @user81655 for 3 bytes saved and a bug found
s=>[...s].map(x=>x<2?v=m[x]:x<6?m=[,,m[1]+m[0],0+v,v+1,v+(1^v)][x]:x>6?v=o.pop()[v]:m=o.push(m)&&a,o=[v=a=m='01'])|v

Probably not the best approach, but no eval and no boolean operators, just truth tables.
Character used:

! -> 2
& -> 3
| -> 4
^ -> 5
( -> 6
) -> 7

Test

f=s=>[...s].map(x=>x<2?v=m[x]:x<6?m=[,,m[1]+m[0],0+v,v+1,v+(1^v)][x]:x>6?v=o.pop()[v]:m=o.push(m)&&a,o=[v=a=m='01'])|v

console.log=(...x)=>O.textContent+=x+'\n'

test=[ ["1^((1|0&0)^!(1&!0&1))",1]
// be more careful, step by step
,["0&0",0],["0&1",0],["1&0",0],["1&1",1]
,["0|0",0],["0|1",1],["1|0",1],["1|1",1]
,["0^0",0],["0^1",1],["1^0",1],["1^1",0]
,["0&!0",0],["0&!1",0],["1&!0",1],["1&!1",0]
,["0|!0",1],["0|!1",0],["1|!0",1],["1|!1",1]
,["0^!0",1],["0^!1",0],["1^!0",0],["1^!1",1]
,["!0&0",0],["!0&1",1],["!1&0",0],["!1&1",0]
,["!0|0",1],["!0|1",1],["!1|0",0],["!1|1",1]
,["!0^0",1],["!0^1",0],["!1^0",0],["!1^1",1]
// nand, nor
,["!(0&0)",1],["!(0&1)",1],["!(1&0)",1],["!(1&1)",0]
,["!(0|0)",1],["!(0|1)",0],["!(1|0)",0],["!(1|1)",0]
     ]

test.forEach(([x,check]) => {
  // remap operators (each one on its line, just to be clear)
  var t = x.replace(/!/g,"2")
  t = t.replace(/&/g,"3")
  t = t.replace(/\|/g,"4")
  t = t.replace(/\^/g,"5")
  t = t.replace(/\(/g,"6")
  t = t.replace(/\)/g,"7")
  r = f(t)
  console.log((r==check?'OK':'KO')+' '+x +' '+r)
})

Did you really mean x>7?

r=f(x.replace(/./g,c=>"01!&|^()".indexOf(c)))

@Neil I'll check, thanks. Of course if >6

@Neil I'm adding test cases. I'm quite sure that given associativity and commutativity of the operators, the NOT should always work

It took me some time to work out why (say) 0|!0 works, but now I do, have my upvote.

Wow. My own solution was just at 299 btes.

Retina, 49 bytes
+`(<1>|!0|1[ox]0|0[ox]1|1[ao]1)|<0>|!1|\d\w\d
$#1

I have no idea how did it come out so short.
Character mapping:
^ -> x
& -> a
| -> o
( -> <
) -> >

1, 0, and ! are left unchanged.
This works by replacing all truthy expressions (single 1 in parentheses, !0, 1&1, 1^0, 0|1, etc.) with 1, and all other (single 0 in parentheses, !1, 1&0, 1^1, 0|0, etc.) with 0.
Try it online!
Try it online with automatic character mapping!

grep + shell utils, 131 bytes
rev|grep -cP '^(((0|R((?9)(x(?1)|a(?4))|(?2)([oxa](?4)|a(?1)|))L|(1|R(?1)L)!)(!!)*)[xo](?1)|(1|R(?1)L|(?2)!)([ao](?1)|[xo](?4)|))$'

The following chars are renamed:
( -> L
) -> R
| -> o
& -> a
^ -> x

I started trying to write a grep solution, but discovered that it did not work well with the left-associative infix operators. I needed to have a pattern like (chain of operators) = (chain of operators) (binary op) (single operand), but this contains a possible infinite recursion, so grep refuses to execute it. But I noticed that I could parse right-associative operators. This made the ! operator a pain, but it was still possible. So I made a regex for calculating backwards boolean expressions, and sent the input through rev. The regex itself, which matches true expressions, is 116 bytes.
TODO: choose different characters for the input so that I can distinguish all the used groups of operators with built-in character classes.

What does (?9) mean?

It means take the 9th capturing group and re-execute it (as distinct from \9 which would mean to match what the 9th capturing group matched). So for instance (\d)\1 matches the same digit twice, while (\d)(\?1) matches any two digits.

Python, 210 bytes
from operator import*;
def t(o):c=o.pop(0);return ord(c)-48if c in"01"else[p(o),o.pop(0)][0]if"("==c else 1-t(o)
def p(o):
 v=t(o)
 while o and")"!=o[0]:v=[xor,or_,and_]["^|&".index(o.pop(0))](v,t(o))
 return v

Really bad recursive descent, I expect this to be beaten in a heartbeat.

Mathematica, 139 129 bytes
a=StringPartition;StringReplace[#,{"(0)0&00&11&00|00^01^1"~a~3|"!1"->"0","(1)1&10|11|01|10^11^0"~a~3|"!0"->"1"},1]&~FixedPoint~#&

A simple string-replacement solution scores far better than I hoped for.

JavaScript ES6, 223 bytes
x=>(Q=[],S=[],[...x].map(t=>{q=+t&&Q.push(t);if(t==")")while((a=S.pop())!="(")Q.push(a);else if(!q)S.push(t)}),k=[],p=_=>k.pop(),Q.concat(S.reverse()).map(e=>k.push(+e||e<"#"?1-p():e<"'"?p()&p():e<","?p()|p():p()^p())),p())

Uses a shunting yard algorithm.
x=>(Q=[],S=[],[...x].map(t=>{q=+t&&Q.push(t);if(t==")")while((a=S.pop())!="(")Q.push(a);else
if(!q)S.push(t)}),k=[],p=_=>k.pop(),Q.concat(S.reverse()).map(e=>k.push(+e||e<"#"?1-p():e<"'"
?p()&p():e<","?p()|p():p()^p())),p())

Uses + for OR, ! for negation, ^ for XOR, and & for and. 0 and 1 are used for their respective values. Sure, I could golf some by making the operators numbers, but I'm not winning the JavaScript prize even if I do, so I thought I'd make it at least somewhat readable and correct.

C, 247
Golfed:
b(char*s){int i,j,k,l;if(*s==40){for(j=i=1;i+=s[++j]==41?-1:s[j]==40?1:0,i;);s[j++]=0;b(s+1);sprintf(s,"%s%s",s+1,s+j);}!s[1]?:(b(s+1),i=*s,j=1,k=s[1],i>47&i<50?:(s[1]=i==33?(j=0,k^1):(l=s[-1],i==38?k&l:i==94?k^l|'0':k|l),sprintf(s-j,"%s",s+1)));}

Ungolfed, with main() (takes expression as 1st arg). The golfed version has no debugging printfs and uses 2-digit ascii codes instead of char literals (40 == '('). I could have saved some characters by mapping ()|^&! to 234567 - this would have made many manipulations and tests easier after subtracting 48 from each.
char*z;                 // tracks recursion depth; not used in golfed version
b(char*s){
    int i,j,k,l;
    printf("%u> '%s'\n", s-z, s);
    if(*s=='('){        // handles parenthesis
        for(j=i=1;i+=s[++j]==')'?-1:s[j]=='('?1:0,i;);
        s[j++]=0;
        b(s+1);         // s+1 to s+j gets substituted for its evaluation
        sprintf(s,"%s%s",s+1,s+j);
    }
    !s[1]?:(            // if 1 char left, return
        b(s+1),         // evaluate rest of expression
        i=*s,
        j=1,
        k=s[1],
        printf("%u: '%c'\n", s-z, i),
        i>47&i<50?:(    // if 0 or 1, skip substitution
                        // otherwise, perform boolean operation
            s[1]=i=='!'?(j=0,k^1):(l=s[-1],i=='&'?k&l:i=='|'?k|l:k^l|'0'),
                        // and replace operation with result
            sprintf(s-j,"%s",s+1),printf("%u= '%s'\n", s-z, s-j)));
    printf("%u< '%s'\n", s-z, s);
}
int main(int argc, char **argv){
    char *s;
    sscanf(argv[1],"%ms",&s);
    z=s;
    b(s);
    printf("%s => %s\n", argv[1], s);
}

+1 for for(j=i=1;i+=s[++j]==')'?-1:s[j]=='('?1:0,i;);.

Java, 218
Uses pattern-matching, but avoids the out-of-order replacements of my previous failed Java attempt (sharp eyes there, @Kenny Lau!).
Golfed:
String e(String s){Matcher m=Pattern.compile("(<1>|1o[01]|0o1|1a1|1x0|0x1|n0)|(<0>|0o0|0a[01]|1a0|1x1|0x0|n1)").matcher(s);return m.find()?e(s.substring(0,m.start())+(m.group(1)==null?"0":"1")+s.substring(m.end())):s;}

Ungolfed, reads input from arguments and applies the mapping oaxn for |&^! and <> for ():
import java.util.regex.*;

public class B{
    String e(String s){
        System.out.println(s);
        Matcher m=Pattern
            .compile(
                "(<1>|1o[01]|0o1|1a1|1x0|0x1|n0)|"+
                "(<0>|0o0|0a[01]|1a0|1x1|0x0|n1)")
            .matcher(s);
        return m.find()?e(s.substring(0,m.start())+(m.group(1)==null?"0":"1")+s.substring(m.end())):s;
    }

    public static String map(String s, String ... replacements) {
        for (String r: replacements) {
            s = s.replace(r.substring(0,1), r.substring(1));
        }
        return s;
    }

    public static void main(String ... args){
        for (String s: args) System.out.println(new B().e(
            map(s,"(<",")>","|o","&a","!n","^x")
        ));
    }
}

Java's m.group(i) tells you which group matched; the 1st group is for true substitutions and the 2nd one for false ones. This is iterated in strict left-to-right order until no substitutions are performed.

Java, 459 bytes
String p(String s){int x,y;while((y=s.indexOf("b"))>=0){x=s.lastIndexOf("a",y);s=s.replaceAll(s.subString(x,y+1),p(s.subString(x+1,y)));}String t,a="1",b="0";while(s.indexOf("!")>=0){s=s.replaceAll("!0",a);s=s.replaceAll("!1",b);}while(s.length()>1){t=s.subString(0,3);if(t.charAt(1)=='l')s=s.replaceFirst(t,t.equals("0l0")?b:a);else if(t.charAt(1)=='&')s=s.replaceFirst(t,t.equals("1&1")?a:b);else s=s.replaceFirst(t,t.charAt(0)==t.charAt(2)?b:a);}return s;}

AND is &
OR is l(lowercase L)
XOR is x (or any other character that happens to play nice with String's methods such as String.replaceAll(...))
NOT is !
( is a
) is b
here's a more readable version:
String parseBoolean( String str ) {
    int start,end;
    //look for matching brackets ab
    while( (end = str.indexOf( "b" )) >= 0 ) {
        start = str.lastIndexOf( "a", end );
        str = str.replaceAll( str.subString( start, end + 1 ), parseBoolean( str.subString( start + 1, end ) ) );
    }
    String temp, one = "1", zero = "0";
    //handle all the !'s
    while( str.indexOf( "!" ) >= 0 ) {
        str = str.replaceAll( "!0", one );
        str = str.replaceAll( "!1", zero );
    }
    //handle the remaining operators from left to right
    while( str.length() > 1 ){
        temp = str.subString( 0, 3 );
        //check for OR
        if( temp.charAt( 1 ) == 'l' )
            str = str.replaceFirst( temp, temp.equals( "0l0" ) ? zero : one );
        //check for AND
        else if(t.charAt(1)=='&')
            str = str.replaceFirst( temp, temp.equals( "1&1" ) ? one : zero );
        //handle XOR
        else
            str = str.replaceFirst( temp, temp.charAt( 0 ) == temp.charAt( 2 ) ? zero : one );
    }
    return str;
}

try it online

As always with Java golfing, my favorite thing to do is replace char literals with their integer counterparts wherever I can. In this case, that would be in both the regular indexOfs, and the charAt comparisons. Also, if you change the character for AND to "n" instead of "&", you can use < or > statements with single ifs when checking for which operation you need to do.

Oh, one more thing. You can double up on the call to replaceAll in the second while loop, also saving you those brackets.

@Blue i always forget to char literals to ints, thanks. I'm not quite sure what you mean on doubling up on the replaceAll call for the !'s.

s=s.replaceAll("!0",a).replaceAll("!1",b);


text:
Permutations with Indistinguishable Items
Given a list of integers, output the number of permutations of the integers, with indistinguishable permutations counted once. If there are n integers, and each group of indistinguishable numbers has length n_i, this is n! / (n_1! * n_2! * ...)
Rules

Input will be some form of list as arguments to a function or the program with 1 to 12 non-negative integers.

Output will be printing or returning the number of permutations as described above.

No standard loopholes or built-in functions (generating permutations, combinations, etc.). Factorials are allowed.

Test Cases
Inputs:
1, 3000, 2, 2, 8
1, 1, 1
2, 4, 3, 2, 3, 4, 4, 4, 4, 4, 1, 1

Outputs:
60
1
83160

when you say no builtins, does this include what I did when I used a builtin for generating all the permutations?

This looks largely the same as Compute the multinomial coefficient. Does counting identical entries for the input make it sufficiently different not to be a dupe?

@xnor well here you actually have to count the duplicates, so it's not as straightforward I suppose. The other is pretty much straight plugging in values.

@Maltysen sadly yes, I will have to update the question

Your test cases only include positive integers. Is that always the case?

@LuisMendo Yes it is, though it should not make a difference as far as I can imagine

@qwr Well, it did in one of the approaches I was thinking of (I had to concatenate an element guaranteed to be different to any of the input numbers)

Python, 48 bytes
f=lambda l:l==[]or len(l)*f(l[1:])/l.count(l[0])

A recursive implementation.
In the formula, n! / (n_1! * n_2! * ...), if we remove the first element (say it's 1), the number of permutation for the remaining n-1 elements is
(n-1)! / ((n_1-1)! * n_2! * ...) ==
n! / n / (n_1! / n_1! * n_2! * ...) ==
n/n_1 * (n! / (n_1! * n_2! * ...)`)

So, we get the answer by multiplying by n/n1, the reciprocal-fraction of elements that equal the first one, by the recursive result for the rest of the list. The empty list gives the base case of 1.

Why don't you put /l.count(l[0]) at the end? Then you don't need that icky floating point.

MATL, 14 13 12 bytes
fpGu"@G=s:p/

Try it online!
Explanation
The approach is very similar to that in @Adnan's answer.
f       % Take input implicitly. Push array of indices of nonzero entries.
        % This gives [1 2 ... n] where n is input length.
p       % Product (compute factorial)
Gu      % Push input. Array of its unique elements
"       % For each of those unique values
  @     %   Push unique value of current iteration
  G=s   %   Number of times (s) it's present (=) in the input (G)
  :p    %   Range, product (compute factorial)
  /     %   Divide
        % End for each implicitly. Display implicitly

05AB1E, 15 14 13 bytes
Code:
D©g!rÙv®yQO!/

Explanation:
               # implicit input
D©             # duplicate and save a copy to register
  g!           # factorial of input length (total nr of permutations without duplicates)
    rÙv        # for each unique number in input
       ®yQO!   # factorial of number of occurances in input
            /  # divide total nr of permutations by this
               # implicit output

Uses CP-1252 encoding.
Try it online!.

JavaScript (ES6), 64 61 bytes
a=>a.sort().map((x,i)=>r=r*++i/(x-y?(y=x,c=1):++c),y=r=-1)|-r

Uses the formula given, except calculating each factorial incrementally (so for example the r=r*++i effectively calcluates n!).
Edit: Originally I accepted any finite numbers but I saved 3 bytes when @user81655 pointed out that I only needed to support positive integers (although I actually accept non-negative integers).

r*=++i/(x-y?(y=x,c=1):++c),y=r=-1)|-r?

@user81655 Ah, I hadn't read the question thoroughly enough and overlooked that I could rely on the values being positive integers. I don't like the *= though as that introduces rounding errors.

Pyth, 11 bytes
/.!lQ*F/V._

Test suite
Uses the standard formula, n! / (count1! * count2! * ...), except that the factorials of the counts are found by counting how many times each element occurs in the prefix leading up to that, then multiplying all such numbers together.
Explanation:
/.!lQ*F/V._
/.!lQ*F/V._QQ    Implicit variable introduction.
                 Q = eval(input())
         ._Q     Form all prefixes of the input.
       /V   Q    Count how many times each element occurs in the prefix
                 ending with that element.
     *F          Fold on multiplication - take the product.
 .!lQ            Take the factorial of the input length
/                Divide.

Pyth - 14 12 bytes
/F.!M+lQ/LQ{

Test Suite.

Ruby, 75 74 bytes
Kinda wish that Ruby's Math module had a factorial function so I didn't have to build my own.
->l{f=->x{x<2?1:x*f[x-1]};l.uniq.map{|e|f[l.count e]}.inject f[l.size],:/}

CJam, 17 bytes
q~_,\$e`0f=+:m!:/

Test it here.
Explanation
q~   e# Read input and evaluate.
_,   e# Duplicate and get length.
\$   e# Swap with other copy and sort it.
e`   e# Run-length encode. Since the list is sorted, this tallies the numbers.
0f=  e# Select the tally of each number.
+    e# Prepend the length of the input.
:m!  e# Compute the factorial of each number in the list.
:/   e# Fold division over it, which divides each factorial of a tally into
     e# the factorial of the length.

J, 13  bytes
#(%*/)&:!#/.~

Usage
   f =: #(%*/)&:!#/.~
   f 1 3000 2 2 8
60
   f 1 1 1
1
   f 2 4 3 2 3 4 4 4 4 4 1 1
83160

Explanation
#(%*/)&:!#/.~  Input: A
         #/.~  Partition A by equal values and get the size of each, these are the tallies
#              Get the size of A
      &:!      Take the factorial of both the size and the tallies
   */          Reduce using multiplication the factorial of the tallies
  %            Divide the factorial of the size by that product and return

Jelly, 8 bytes
W;ĠL€!:/

Try it online!
W;ĠL€!:/ example input:             [1, 3000, 2, 2, 8]
W        wrap:                      [[1, 3000, 2, 2, 8]]
  Ġ      group index by appearance: [[1], [3, 4], [5], [2]]
 ;       concatenate:               [[1, 3000, 2, 2, 8], [1], [3, 4], [5], [2]]
   L€    map by length:             [5, 1, 2, 1, 1]
     !   [map by] factorial:        [120, 1, 2, 1, 1]
      :/ reduce by division:        120÷1÷2÷1÷1 = 60

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
Watson-Crick palindromes
Problem
Create a function that can determine whether or not an arbitrary DNA string is a Watson-Crick palindrome. The function will take a DNA string and output a true  value if the string is a Watson-Crick palindrome and a false value if it is not. (True and False can also be represented as 1 and 0, respectively.)
The DNA string may either be in all uppercase or all lowercase depending on your preference.
Also, the DNA string will not be empty.
Explanation
A DNA string is a Watson-Crick palindrome when the complement of its reverse is equal to itself.
Given a DNA string, first reverse it, and then complement each character according to the DNA bases (A ↔ T and C ↔ G). If the original string is equal to the complemented-reverse string, it is a Watson-Crick palindrome.
For more, see this question. It is a different challenge where you must find the longest substring of a DNA string where that substring is a Watson-Crick palindrome.
Goal
This is code-golf and the shortest code wins.
Test Cases
The format is <input> = <output>.
ATCGCGAT = true
AGT = false
GTGACGTCAC = true
GCAGTGA = false
GCGC = true
AACTGCGTTTAC = false
ACTG = false

Related.

Someone should write a program in DNA# that is also a Watson-Crick palindrome. :D (might not be possible)

Or, if you like, "a word is a Watson–Crick palindrome if it has order 2 in the free group on 2 generators" (or on n generators!).

(I guess technically that's "order at most 2.")

Do the true and false values need to be "consistent"? I.e., only one true output and only one false output. (As opposed to e.g. returning the input string for true, and nil for false.)

Extending it to truthy and falsey values might lead to answers that return [1, 2, 3] as true and [] as false but would lead to many different possible outputs. It would be better to be consistent, always returning true when true and nil when false, or some other arrangement.

Is the name "Watson--Crick palindrome" a thing? It should really be "Watson--Crick--Franklin palindrome" :P

Possible Handy Hint: Odd length strings cannot be W-C Palindromes. The middle character will always transpose to something different.

@AndrasDeak According to Watsons book, Franklin was apparently mostly a thorn in their side. She repeatedly refused to hand over x-rays showing the helix (as I recall), because she refused to believe it. Its worth a read if you are interested in the discovery at any rate.

@ObsidianPhoenix funny, I've even read the book (to be fair, at the age of 12), and didn't remember this aspect, only that without the diffraction data they might not have figured out the structure. I guess I do have to re-read it, thanks:)

@AndrasDeak I was the same, at school and not since. My recollection could be skewed, but I seem to recall that was the case. I enjoyed it, should probably read it again some day.

@mbomb007 On it.

05AB1E, 10 7 bytes
Code:
Â'š×Â‡Q

Explanation:
To check if a string is a palindrome, we just need to check the input with the input, with at swapped and cg swapped and then reverse it. So that is what we are going to do. We push the input and the input reversed using Â (bifurcate). Now comes a tricky part. 'š× is the compressed version for creating. If we reverse it, you can see why it's in the code:
CreATinG
|  ||  |
GniTAerC

This will be used to transliterate the reversed input. Transliteration is done with ‡. After that, we just check if the input and the transliterated input are eQual and print that value. So this is how the stack looks like for input actg :
Â          # ["actg", "gtca"]
 'š×       # ["actg", "gtca", "creating"]
    Â      # ["actg", "gtca", "creating", "gnitaerc"]
     ‡     # ["actg", "cagt"]
      Q    # [0]

Which can also be seen with the debug flag (Try it here).
Uses CP-1252 encoding. Try it online!.

Very, er, creative...

This language has some very neat features

Jelly, 9 bytes
O%8µ+U5ḍP

Try it online! or verify all test cases.
How it works
O%8µ+U5ḍP  Main link. Argument: S (string)

O          Compute the code points of all characters.
 %8        Compute the residues of division by 8.
           This maps 'ACGT' to [1, 3, 7, 4].
   µ       Begin a new, monadic link. Argument: A (array of residues)
    +U     Add A and A reversed.
      5ḍ   Test the sums for divisibility by 5.
           Of the sums of all pairs of integers in [1, 3, 7, 4], only 1 + 4 = 5
           and 3 + 7 = 10 are divisible by 5, thus identifying the proper pairings.
        P  Take the product of the resulting Booleans.

I think Python is pretty close to competing with this answer! Compare the first nine bytes of my answer: lambda s:. That's almost the full solution!

Python 2, 56 45 44 bytes
lambda s:s==s[::-1].translate("_T_GA__C"*32)

lambda s:s==s[::-1].translate("TCG_A"*99) works in Python 3

Perl, 27 bytes
Includes +2 for -lp
Give input on STDIN, prints 1 or nothing:
dnapalin.pl <<< ATCGCGAT

dnapalin.pl:
#!/usr/bin/perl -lp
$_=y/ATCG/TAGC/r=~reverse

Replace $_= by $_+= to get 0 instead of empty for the false case

Pyth - 10 bytes
qQ_XQ"ACGT

Try it online here.
A 9 byte version: Try it online here.

Retina, 34 33 bytes
$
;$_
T`ACGT`Ro`;.+
+`(.);\1
;
^;

Try it online! (Slightly modified to run all test cases at once.)
Explanation
$
;$_

Duplicate the input by matching the end of the string and inserting a ; followed by the entire input.
T`ACGT`Ro`;.+

Match only the second half of the input with ;.+ and perform the substitution of pairs with a transliteration. As for the target set Ro: o references the other set, that is o is replaced with ACGT. But R reverses this set, so the two sets are actually:
ACGT
TGCA

If the input is a DNA palindrome, we will now have the input followed by its reverse (separated by ;).
+`(.);\1
;

Repeatedly (+) remove a pair of identical characters around the ;. This will either continue until only the ; is left or until the two characters around the ; are no longer identical, which would mean that the strings aren't the reverse of each other.
^;

Check whether the first character is ; and print 0 or 1 accordingly.

JavaScript (ES6), 59 bytes
f=s=>!s||/^(A.*T|C.*G|G.*C|T.*A)$/.test(s)&f(s.slice(1,-1))

Best I could do without using Regexp was 62 bytes:
f=s=>!s||parseInt(s[0]+s.slice(-1),33)%32%7<1&f(s.slice(1,-1))

Ruby, 35
I tried other ways, but the obvious way was the shortest:
->s{s.tr('ACGT','TGCA').reverse==s}

in test program
f=->s{s.tr('ACGT','TGCA').reverse==s}

puts f['ATCGCGAT']
puts f['AGT']
puts f['GTGACGTCAC']
puts f['GCAGTGA']
puts f['GCGC']
puts f['AACTGCGTTTAC']

->s{s.==s.reverse.tr'ACGT','TGCA'} is a byte shorter

@MitchSchwartz wow, that works, but I have no idea what that first . is for. The code looks more right to me without it, but it is required to make it run. Is it documented anywhere?

Are you sure you don't want to figure it out on your own?

@MitchSchwartz hahaha I already tried. I find ruby's requirements for whitespace very idiosyncratic. Strange requirements for periods is a whole other issue. I have several theories but all of them may be wrong. I suspect it may have something to do with treating == as a method rather than an operator, but searching by symbols is impossible.

You suspected correctly. :) It's just a plain old method call.

@MitchSchwartz  thanks, but that doesn't really explain why it can parse the code with the period but not without. If I get random syntax errors in future, I will try putting a period in front of operators and see what happens :D

Parentheses after a method call (here we are looking at tr) can only be omitted under certain circumstances. Maybe it would help you to consider why 1.==1 && 2==2 is valid syntax (and evaluates to false) while 1==1 && 2.==2 is a syntax error. I don't claim to have deep knowledge of Ruby parsing, but I also don't think that it is very surprising or strange in this case. Informally, I'd say you can omit the parentheses when (1) the method is being called without arguments, or (2) the method is not "in the middle" of an expression that could have things to the right of it.

Or maybe this plays better to the intuition: Would you expect 1 + 5.div 3 to be valid syntax? It is comparable to s == s.reverse.tr 'ACGT','TGCA' (notice where I added spaces).

Haskell, 48 45 bytes
(==)=<<reverse.map((cycle"TCG_A"!!).fromEnum)

Usage example: (==)=<<reverse.map((cycle"_T_GA__C"!!).fromEnum) $ "ATCGCGAT"-> True.
A non-pointfree version is
f x = reverse (map h x) == x           -- map h to x, reverse and compare to x
h c = cycle "TCG_A" !! fromEnum c      -- take the ascii-value of c and take the
                                       -- char at this position of string
                                       -- "TCG_ATCG_ATCG_ATCG_A..."

Edit: @Mathias Dolidon saved 3 bytes. Thanks!

Works with cycle "TCG_A"  too. :)

Retina, 52 bytes
^G(.*)C$
$1
^A(.*)T$
$1
^T(.*)A$
$1
}`^C(.*)G$
$1
^$

Julia, 47 38 bytes
s->((x=map(Int,s)%8)+reverse(x))%5⊆0

This is an anonymous function that accepts a Char array and returns a boolean. To call it, assign it to a variable.
This uses Dennis' algorithm, which is shorter than the naïve solution. We get the remainder of each code point divided by 8, add that to itself reversed, get the remainders from division by 5, and check whether all are 0. The last step is accomplished using ⊆, the infix version of issubset, which casts both arguments to Set before checking. This means that [0,0,0] is declared a subset of 0, since Set([0,0,0]) == Set(0). This is shorter than an explicit check against 0.
Try it online!
Saved 9 bytes thanks to Dennis!

Bash + coreutils, 43 32 bytes
[ `tr ATCG TAGC<<<$1|rev` = $1 ]

Tests:
for i in ATCGCGAT AGT GTGACGTCAC GCAGTGA GCGC AACTGCGTTTAC; do ./78410.sh $i && echo $i = true || echo $i = false; done
ATCGCGAT = true
AGT = false
GTGACGTCAC = true
GCAGTGA = false
GCGC = true
AACTGCGTTTAC = false

Jolf, 15 Bytes
Try it!
=~A_iγ"AGCT"_γi

Explanation:
   _i            Reverse the input
 ~A_iγ"AGCT"_γ   DNA swap the reversed input
=~A_iγ"AGCT"_γi  Check if the new string is the same as the original input

R, 101 bytes
g=function(x){y=unlist(strsplit(x,""));all(sapply(rev(y),switch,"C"="G","G"="C","A"="T","T"="A")==y)}

Test Cases
g("ATCGCGAT")
[1] TRUE
g("AGT")
[1] FALSE
g("GTGACGTCAC")
[1] TRUE
g("GCAGTGA")
[1] FALSE
g("GCGC")
[1] TRUE
g("AACTGCGTTTAC")
[1] FALSE
g("ACTG")
[1] FALSE

strsplit(x,"")[[1]] is 3 bytes shorter than unlist(strsplit(x,"")) and, here, is equivalent since x is always a single string of character.

Julia 0.4, 22 bytes
s->s$reverse(s)⊆""

The string contains the control characters EOT (4) and NAK (21). Input must be in form of a character array.
This approach XORs the characters of the input with the corresponding characters in the reversed input. For valid pairings, this results in the characters EOT or NAK. Testing for inclusion in the string of those characters produces the desired Boolean.
Try it online!

C#, 65 bytes
bool F(string s)=>s.SequenceEqual(s.Reverse().Select(x=>"GACT"[("GACT".IndexOf(x)+2)%4]));

.NET has some fairly long framework method names at times, which doesn't necessarily make for the best code golf framework. In this case, framework method names make up 33 characters out of 90. :)
Based on the modulus trick from elsewhere in the thread:
bool F(string s)=>s.Zip(s.Reverse(),(a,b)=>a%8+b%8).All(x=>x%5==0);

Now weighs in at 67 characters whereof 13 are method names.
Another minor optimization to shave off a whopping 2 characters:
bool F(string s)=>s.Zip(s.Reverse(),(a,b)=>(a%8+b%8)%5).Sum()<1;

So, 65 of which 13 are framework names.
Edit:
Omitting some of the limited "boilerplate" from the solution and adding a couple of conditions leaves us with the expression
s.Zip(s.Reverse(),(a,b)=>(a%8+b%8)%5).Sum()

Which gives 0 if and only if the string s is a valid answer.
As cat points out, "bool F(string s)=>" is actually replacable with "s=>" if it's otherwise clear in the code that the expression is a Func<string,bool>, ie. maps a string to a boolean.

Welcome to PPCG, nice first answer! :D

@cat Thanks for that! :)

I don't really know C#, but if this is a lambda, then you can leave out its type and assigning it, as anonymous functions are fine as long as they are assignable.

Also, can't you do !s.Zip... instead of s.Zip...==0? (Or can't you ! ints in C#?) Even if you can't boolean-negate it, you can leave out any sort of  inversion and state in your answer that this returns  for falsy and <this other deterministic, clearly discernable thing> for truthy.

@cat: You're right about dropping the type. I thought the code had to be directly executable, but making simple assumptions about input and output makes it a bit easier.
The other thing won't work, however - rightly so, in my opinion, since a boolean operation has no logical (hue hue) way to apply to a number. Assigning 0 and 1 the values of false and true is, after all, just convention.

sed, 67 61 bytes
G;H;:1;s/\(.\)\(.*\n\)/\2\1/;t1;y/ACGT/TGCA/;G;s/^\(.*\)\1$/1/;t;c0

(67 bytes)
Test
for line in ATCGCGAT AGT GTGACGTCAC GCAGTGA GCGC AACTGCGTTTAC ACTG
do echo -n "$line "
    sed 'G;H;:1;s/\(.\)\(.*\n\)/\2\1/;t1;y/ACGT/TGCA/;G;s/^\(.*\)\1$/1/;t;c0' <<<"$line"
done

Output
ATCGCGAT 1
AGT 0
GTGACGTCAC 1
GCAGTGA 0
GCGC 1
AACTGCGTTTAC 0
ACTG 0

By using extended regular expressions, the byte count can be reduced to 61.
sed -r 'G;H;:1;s/(.)(.*\n)/\2\1/;t1;y/ACGT/TGCA/;G;s/^(.*)\1$/1/;t;c0'

If you can do it in 61 bytes, then that's your score -- there's nothing against NFA or turing-complete regexp on this particular challenge. Some challenges disallow regex in full, but usually only [tag:regex-golf] will disallow non regular-expressions.

Jolf, 16 bytes
Try it here!
pe+i~Aiγ"GATC"_γ

Explanation
pe+i~Aiγ"GATC"_γ
    ~Aiγ"GATC"_γ  perform DNA transformation
  +i              i + (^)
pe                is a palindrome

Factor, 72 bytes
Unfortunately regex can't help me here.
[ dup reverse [ { { 67 71 } { 65 84 } { 71 67 } { 84 65 } } at ] map = ]

Reverse, lookup table, compare equal.

Wow, that's a lot of whitespace!!! Is it all necessary? Also, a link to the language homepage would be useful.

@LevelRiverSt Unfortunately, every bit of it is necessary. I'll add a link to the header.

Actually, 19 bytes
O`8@%`M;RZ`5@Σ%Y`Mπ

This uses Dennis's algorithm.
Try it online!
Explanation:
O`8@%`M;RZ`5@Σ%Y`Mπ
O                    push an array containing the Unicode code points of the input
 `8@%`M              modulo each code point by 8
       ;RZ           zip with reverse
          `5@Σ%Y`M   test sum for divisibility by 5
                  π  product

C,71
r,e;f(char*s){for(r=0,e=strlen(s)+1;*s;s++)r|=*s*s[e-=2]%5^2;return!r;}

2 bytes saved by Dennis. Additional 2 bytes saved by adapting for lowercase input: constants 37 and 21 are revised to 5 and 2.
C,75
i,j;f(char*s){for(i=j=0;s[i];i++)j|=s[i]*s[strlen(s)-i-1]%37!=21;return!j;}

Saved one byte: Eliminated parenthesis by taking the product of the two ASCII codes mod 37. The valid pairs evaluate to 21. Assumes uppercase input.
C,76
i,j;f(char*s){for(i=j=0;s[i];i++)j|=(s[i]+s[strlen(s)-i-1])%11!=6;return!j;}

Uses the fact that ASCII codes of the valid pairs sum to 138 or 149. When taken mod 11, these are the only pairs that sum to 6. Assumes uppercase input.
ungolfed in test program
i,j;

f(char *s){
   for(i=j=0;s[i];i++)                  //initialize i and j to 0; iterate i through the string
     j|=(s[i]+s[strlen(s)-i-1])%11!=6;  //add characters at i from each end of string, take result mod 11. If not 6, set j to 1
return!j;}                              //return not j (true if mismatch NOT detected.)

main(){
  printf("%d\n", f("ATCGCGAT"));
  printf("%d\n", f("AGT"));
  printf("%d\n", f("GTGACGTCAC"));
  printf("%d\n", f("GCAGTGA"));
  printf("%d\n", f("GCGC"));
  printf("%d\n", f("AACTGCGTTTAC"));
}

r,e;f(char*s){for(r=0,e=strlen(s)+1;*s;s++)r|=*s*s[e-=2]%37^21;return!r;} saves a couple of bytes.

@Dennis thanks, I really wasn't in the mood for modifying pointers, but it squeezed a byte out! I should have seen != > ^ myself. I reduced another 2 by changing to lowercase input: both magic numbers are now single digit.

Oracle SQL 11.2, 68 bytes
SELECT DECODE(TRANSLATE(REVERSE(:1),'ATCG','TAGC'),:1,1,0)FROM DUAL;

With SQL like that, I'm confident you must have written reports for some of my projects before...

J - 21 bytes
0=[:+/5|[:(+|.)8|3&u:

Based on Dennis' method
Usage
   f =: 0=[:+/5|[:(+|.)8|3&u:
   f 'ATCGCGAT'
1
   f 'AGT'
0
   f 'GTGACGTCAC'
1
   f 'GCAGTGA'
0
   f 'GCGC'
1
   f 'AACTGCGTTTAC'
0
   f 'ACTG'
0

Explanation
0=[:+/5|[:(+|.)8|3&u:
                 3&u:    - Convert from char to int
               8|        - Residues from division by 8 for each
            |.           - Reverse the list
           +             - Add from the list and its reverse element-wise
        [:               - Cap, compose function
      5|                 - Residues from division by 5 for each
    +/                   - Fold right using addition to create a sum
  [:                     - Cap, compose function
0=                       - Test the sum for equality to zero

Labyrinth, 42 bytes
_8
,%
;
"}{{+_5
"=    %_!
 = """{
 ;"{" )!

Terminates with a division-by-zero error (error message on STDERR).
Try it online!
The layout feels really inefficient but I'm just not seeing a way to golf it right now.
Explanation
This solution is based on Dennis's arithmetic trick: take all character codes modulo 8, add a pair from both ends and make sure it's divisible by 5.
Labyrinth primer:

Labyrinth has two stacks of arbitrary-precision integers, main and aux(iliary), which are initially filled with an (implicit) infinite amount of zeros.
The source code resembles a maze, where the instruction pointer (IP) follows corridors when it can (even around corners). The code starts at the first valid character in reading order, i.e. in the top left corner in this case. When the IP comes to any form of junction (i.e. several adjacent cells in addition to the one it came from), it will pick a direction based on the top of the main stack. The basic rules are: turn left when negative, keep going ahead when zero, turn right when positive. And when one of these is not possible because there's a wall, then the IP will take the opposite direction. The IP also turns around when hitting dead ends.
Digits are processed by multiplying the top of the main stack by 10 and then adding the digit.

The code starts with a small 2x2, clockwise loop, which reads all input modulo 8:
_   Push a 0.
8   Turn into 8.
%   Modulo. The last three commands do nothing on the first iteration
    and will take the last character code modulo 8 on further iterations.
,   Read a character from STDIN or -1 at EOF. At EOF we will leave loop.

Now ; discards the -1. We enter another clockwise loop which moves the top of the main stack (i.e. the last character) down to the bottom:
"   No-op, does nothing.
}   Move top of the stack over to aux. If it was at the bottom of the stack
    this will expose a zero underneath and we leave the loop.
=   Swap top of main with top of aux. The effect of the last two commands
    together is to move the second-to-top stack element from main to aux.
"   No-op.

Now there's a short linear bit:
{{  Pull two characters from aux to main, i.e. the first and last (remaining)
    characters of the input (mod 8).
+   Add them.
_5  Push 5.
%   Modulo.

The IP is now at a junction which acts as a branch to test divisibility by 5. If the result of the modulo is non-zero, we know that the input is not a Watson-Crick palindrome and we turn east:
_   Push 0.
!   Print it. The IP hits a dead end and turns around.
_   Push 0.
%   Try to take modulo, but division by zero fails and the program terminates.

Otherwise, we need to keep checking the rest of the input, so the IP keeps going south. The { pulls over the bottom of the remaining input. If we've exhausted the input, then this will be a 0 (from the bottom of aux), and the IP continues moving south:
)   Increment 0 to 1.
!   Print it. The IP hits a dead end and turns around.
)   Increment 0 to 1.
{   Pull a zero over from aux, IP keeps moving north.
%   Try to take modulo, but division by zero fails and the program terminates.

Otherwise, there are more characters in the string to be checked. The IP turns west and moves into the next (clockwise) 2x2 loop which consists largely of no-ops:
"   No-op.
"   No-op.
{   Pull one value over from aux. If it's the bottom of aux, this will be
    zero and the IP will leave the loop eastward.
"   No-op.

After this loop, we've got the input on the main stack again, except for its first and last character and with a zero on top. The ; discards the 0 and then = swaps the tops of the stacks, but this is just to cancel the first = in the loop, because we're now entering the loop in a different location. Rinse and repeat.

REXX 37
s='ATCGCGAT';say s=translate(reverse(s),'ATCG','TAGC')

Octave, 52 bytes
f=@(s) prod(mod((i=mod(toascii(s),8))+flip(i),5)==0)

Following Denis's trick ... take the ASCII values mod 8, flip and add together; if every sum is a multiple of five, you're golden.

That one whitespace is significant? That's... odd.

Also, you can leave out the f= assignment; unnamed functions are okay.

Vyxal, 17 11 10 8 bytes
Ṙ«Wṁ«ḂĿ=

Try it Online!
Explained
Ṙ«Wṁ«ḂĿ=
Ṙ        # Input reverse
 «Wṁ«ḂĿ  # Changes DNA and translate with string compression
       = # If original input is equal to the result output 1/0

, 13 chars / 17 bytes
⟮ïĪ`ACGT”⟯ᴙ≔Ⅰ

Try it here (Firefox only).
Explanation
Transliterate input from ACGT to TGCA and check if the resulting string is a palindrome.

Clojure/ClojureScript, 49 chars
#(=(list* %)(map(zipmap"ATCG""TAGC")(reverse %)))

Works on strings.  If the requirements are loosened to allow lists, I can take off the (list* ) and save 7 chars.

R, 70 bytes
f=function(x)all(chartr("GCTA","CGAT",y<-strsplit(x,"")[[1]])==rev(y))

Usage:
> f=function(x)all(chartr("GCTA","CGAT",y<-strsplit(x,"")[[1]])==rev(y))
> f("GTGACGTCAC")
[1] TRUE
> f("AACTGCGTTTAC")
[1] FALSE
> f("AGT")
[1] FALSE
> f("ATCGCGAT")
[1] TRUE

C, 71 bytes
Requires ASCII codes for the relevant characters, but accepts uppercase, lowercase or mixed-case input.
f(char*s){char*p=s+strlen(s),b=0;for(;*s;b&=6)b|=*--p^*s++^4;return!b;}

This code maintains two pointers, s and p, traversing the string in opposite directions.  At each step, we compare the corresponding characters, setting b true if they don't match.  The matching is based on XOR of the character values:
'A' ^ 'T' = 10101
'C' ^ 'G' = 00100

'C' ^ 'T' = 10111
'G' ^ 'A' = 00110
'A' ^ 'C' = 00010
'T' ^ 'G' = 10011
 x  ^  x  = 00000

We can see in the above table that we want to record success for xx10x and failure for anything else, so we XOR with 00100 (four) and mask with 00110 (six) to get zero for AT or CG and non-zero otherwise.  Finally, we return true if all the pairs accumulated a zero result in b, false otherwise.
Test program:
#include <stdio.h>
int main(int argc, char **argv)
{
    while (*++argv)
        printf("%s = %s\n", *argv, f(*argv)?"true":"false");
}

J, 19 bytes
|.-:-&.('+AGCT'i.])

Try it online!

Wolfram Language (Mathematica), 45 bytes
17-#==Reverse@#&@Mod[ToCharacterCode@#,11,2]&

Try it online!
Converts A to 10, T to 7, C to 12, and G to 5, by taking the ASCII codes mod 11 with offset 2. Then checks if the resulting list and its reverse add to 17 in each coordinate.

J-uby, 50 33 27 bytes
Based on Level River St’s Ruby answer.
:=~&(~:tr&'ACGT'&'TGCA'|:~)

Attempt This Online!

TI-Basic, 47 bytes
min(seq(inString("ATA CGC",sub(Ans,I,1)+sub(Ans,length(Ans)-I+1,1)),I,1,length(Ans

Takes input in Ans as an uppercase string.

Wolfram Language (Mathematica), 41 bytes
BioSequenceComplement@StringReverse@#==#&

Don't Try it online!
Takes input as a BioSequence.
Doesn't work on TIO due to it not supporting StringReverse on a BioSequence. Figured it was worth its own post intead of as a comment on the other Mathematica answer because it's significantly simpler and requires new-ish functionality.

Raku, 24 bytes
{TR/ATCG/TAGC/ eq .flip}

Try it online!
Straightforward solution.  Translates the characters in the input string to the complementary ones, then compares that to the reverse of the input string.

Swift 5.9, 87 bytes
let f={zip($0+"",$0.reversed()).allSatisfy{($0.0.asciiValue!+$0.1.asciiValue!)%16%5<1}}

Dennis' algorithm, slightly golfed down.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Taylor Series of a Function with Periodic Derivatives
Taylor series are a very useful tool in calculating values of analytic functions that cannot be expressed in terms of elementary functions, using only information about that function at a single point.
In this challenge, you won't be actually doing any math with them, but merely making string representations of taylor series of functions with periodic derivatives.
Specs
You will takes a input three things:

A cycle of the derivatives of the function, including the original function as a list of strings, e.g. ["sin(x)", "cos(x)", "-sin(x)", "-cos(x)"].
A number a, the point around which to center the approximation.
A positive integer n, the number of terms of the series to output.

The general form for the nth term of a taylor series is:
f^(n)(a)/n!*(x-a)^n

where f^(n) is the nth derivative of f. Here is the taylor series of f in a better formatted image from wikipedia:
.
The above example with sin(x), and a of 1, and n of 6, would have an output of:
sin(1) + cos(1)*(x-1) - sin(1)/2*(x-1)^2 - cos(1)/6*(x-1)^3 + sin(1)/24*(x-1)^4 + cos(1)/120*(x-1)^5

You can do the whitespace want. However, you have to replace + - and - - with - and + respectively. Also, if the series is a maclaurin series, and a is 0, you cannot have (x-0). (x) and just x is fine, but not (x-0). Niether can you have ^0 nor ^1 nor /1 . Additionally, you must expand out the factorials in the denominators. Multiplication by juxtaposition is not allowed.
Test cases
["e^x"], 0, 4  ->  e^0 + e^0*x + e^0*x^2/2 + e^0*x^3/6
["sin(x)", "cos(x)", "-sin(x)", "-cos(x)"], 1, 6 -> sin(1) + cos(1)*(x-1) - sin(1)/2*(x-1)^2 - cos(1)/6*(x-1)^3 + sin(1)/24*(x-1)^4 + cos(1)/120*(x-1)^5
["e^(i*x)", "i * e^(i*x)", "-e^(i*x)", "-i*e^(i*x)"], 0, 7 -> e^(i*0) + i*e^(i*0)*x - e^(i*0)*x^2/2 - i*e^(i*0)*x^3/6 + e^(i*0)*x^4/24 + i*e^(i*0)*x^5/120 - e^(i*0)*x^6/720

This is code-golf, so shortest code in bytes wins!

Are built ins allowed?

@Mego sure, if you can find one that doesn't evaluate the function and only does string manipulation.

What about something like this?

Additionally, can ** be used in place of ^?

May we assume that the derivatives only start with nothing or a single minus sign if they're negative?

Can the function's name include the letter x or will it only be the variable?

@Mego sure, sage is fine, and so is using **

@orlp you can assume that all occurrences of x refer to the variable.

@Maltysen That wasn't my question. Can we assume that the derivatives won't contain stuff like this: ["--sin(x)", "--cos(x)", "sin(x)*-1", "cos(x)*-1"]? Always either no sign or a single unary minus.

@orlp sorry, was on mobile, pinged wrong person. yeah assuming that is fine.

@Neil sorry, was on mobile pinged wrong person, you can assume that all occurrences of x refer to the variable

Your first example with e^x has 4 terms, not the requested 3.

@orlp whoops, fixing.

@Maltysen Is it okay if, for the first test case, e^0/2*x^2 is output for the third value in the series instead of e^0*x^2/2?

@R.Kap sure, that's fine

JavaScript (ES6), 183 bytes
(c,a,n)=>[...Array(n)].map((_,i)=>(s=c[i%c.length].replace(/x/g,a),i?s=s.replace(/^-?/,c=>c?` - `:` + `)+(a>0?`*(x-${a})`:a<0?`*(x+${-a})`:`*x`):s,i>1?s+`^${i}/${f*=i}`:s),f=1).join``

Lots of tedious string manipulation. Explanation:
(c,a,n)=>                               Parameters
 [...Array(n)].map((_,i)=>(             Loop i from 0 to n-1
  s=c[i%c.length]                       Get the right element from the cycle
   .replace(/x/g,a),                    Substitute a in for x
  i?                                    If i > 0
   s=s.replace(/^-?/,c=>c?` - `:` + `)  Turn the sign into an operator
    +(a>0?`*(x-${a})`                   If a > 0 then * (x - a)
     :a<0?`*(x+${-a})`                  If a < 0 then * (x + -a)
     :`*x`)                             If a == 0 then * x
   :s,                                  No change if i < 1
  i>1?                                  If i > 1
   s+`^${i}/${f*=i}`                    Append ^ i / i!
   :s),                                 No change if i < 2
  f=1                                   0! == 1
 ).join``                               Join all the results together

170 bytes if you remove all the whitespace:
(c,a,n)=>[...Array(n)].map((_,i)=>(s=c[i%c.length].replace(/x/g,a),i?s=(s[0]=='-'?'':'+')+s+(a>0?`*(x-${a})`:a<0?`*(x+${-a})`:`*x`):s,i>1?s+`^${i}/${f*=i}`:s),f=1).join``

Python 2, 181 bytes
D,a,N=input()
D=["+"*(d[0]!="-")+d.replace("x",`a`)for d in D]
x=a and"*(x-%s)"%a or"*x"
r=D[0][1:]+(D[1]+x)*(N>1)
n=f=2
while n<N:r+=D[n%len(D)]+"/"+`f`+x+"^"+`n`;n+=1;f*=n
print r

Maybe a short explanation on how this works?

@R.Kap There's nothing to explain, really. It's just a bunch of string concatenation. Each line reasonably speaks for itself.

I mean, what's going on in x? What are the and and or doing there?

@R.Kap x is simply "*(x-a)" or just "*x" if a is 0.

I would presume that you would have to use ternary if statements for that, but this I did not know was even possible.

@R.Kap Nope, 1 newline = 1 semicolon.

r returns a IndexError on ["e^x"],0,4. I did run this on Python 3, although, based on what r is supposed to be, it should work the same on both Python 2 and 3.

Python 3.5, 308 299 bytes:
def g(f,a,n,L=len,S=str):import math,re;A=S(a);print('+'.join(t.replace('x',A)+re.sub('(\W\(x-\d+\)\^0|/1|\*1|\^1|\*0)(?!\d+)','',g)for t,g in zip(f*(n//L(f))+f[:n%L(f)],['*'+A+'/'+S(math.factorial(n))+'*'+'(x-'+A+')^'+S(n)for n in range(n)])).replace('+-','-').replace('--','+').replace('x-0','x'))

This always outputs in the order according to the equation f^(n)(a)/n!*(x-a)^n. For instance, if the expected output for one of the terms is e^0*x^2/2, it instead outputs e^0/2*x^2. However, they are both basically the same answer, so I hope this is okay. Confirmed by OP that this is okay. This works perfectly as I have had no issues with it. I will shorten this over time wherever I can.
Note: In the output, all (x-0) are replaced with (x).
Try it online! (Ideone) (Accepts input on 3 lines, where the first line is the input list, f, the second line is a, and the third line is n)
Explanation
For the purposes of this explanation, assume the function is executed with the values "e^(i*x)", "i*e^(i*x)", "-e^(i*x)", "-i*e^(i*x)"],0,7. That being said, basically, what's going on in the main part, step-by-step, is:

'+'.join(t.replace('x',A)+re.sub('(\W\(x-\d+\)\^0|/1|\*1|\^1|\*0)(?!\d+)','',g)for t,g in zip(f*(n//L(f))+f[:n%L(f)],['*'+A+'/'+S(math.factorial(n))+'*'+'(x-'+A+')^'+S(n)for n in range(n)]))
A list is created from each item pair in a zip object containing the input list, f, with n number of items, and another list which contains each term in the sequence except the items in f. In this second list, *+a is added, followed by a /+ n! for each value, n, in the range n, and finally, a lone * followed by (x-a)^n. After all this is done, for each item pair in this zip object, t corresponding to each object in f and g corresponding to each value in the second list, each 'x' in t is replaced with a, and every g goes through a regular expression substitution, namely (\W\(x-\d+\)\^0|/1|\*1|\^1|\*0)(?!\d+), in which every (x-a)^0, /1,*1,^1, and *0 is matched and replaced with '' as long as each of those are not followed by any more integers. After all this substitution is done, each t and g are concatenated together, and each term created using this method is joined with +s and returned. For this particular case in which "e^(i*x)", "i*e^(i*x)", "-e^(i*x)", "-i*e^(i*x)"],0,7 is the input, this part would return:
e^(i*0)+i*e^(i*0)*(x-0)+-e^(i*0)/2*(x-0)^2+-i*e^(i*0)/6*(x-0)^3+e^(i*0)/24*(x-0)^4+i*e^(i*0)/120*(x-0)^5+-e^(i*0)/720*(x-0)^6

As you can see, those +-s, --s, and (x-0)s exist. However, these will all be replaced with -,+,and (x) respectively in the next part.
'+'.join(t.replace('x',A)+re.sub('(\W\(x-\d+\)\^0|/1|\*1|\^1|\*0)(?!\d+)','',g)for t,g in zip(f*(n//L(f))+f[:n%L(f)],['*'+A+'/'+S(math.factorial(n))+'*'+'(x-'+A+')^'+S(n)for n in range(n)])).replace('+-','-').replace('--','+').replace('x-0','x')
Here is where those substrings such as +-,++,and (x-0) in the now joined string are replaced with their correct substitutes using Python's built-in sub-string replacement function. After all the replacing has been done, this finally returns the finished product, which in this case would be:
e^(i*0)+i*e^(i*0)*(x)-e^(i*0)/2*(x)^2-i*e^(i*0)/6*(x)^3+e^(i*0)/24*(x)^4+i*e^(i*0)/120*(x)^5-e^(i*0)/720*(x)^6