This PDA is not trivial. You have to work with two branches (one for increment (A and B) and one for decrement (C)). The trick is to place a top-of-the-stack-marker and look for this marker. if you hit it hold on (don't go further on your band) switch branch and push negatives on your branch.
In the following I define a transition by a triple: (input, pop, push)
For example:
- (A,ϵ,#) means: read A from input, pop nothing, push # to the stack
- (ϵ,#,B) means: read nothing (stop at the actual position and don't go further in this step), pop #, push B
- (AB,ϵ,X) means: read A or B and push X
For your example:
S = starting state
Q1 = "switch branches" state, from here the stack is empty and we move in the branch we need in dependend of the next character read from the input band.
Q2, Q3 = States of the there-is-an-A-or-B-next branch
Q4, Q5 = States of the there-is-a-C-next branch
Q6 = State of acceptance (the only one. all other states are not accepting)
Now the transitions:
S -(ϵ,ϵ,#)-> Q1 ' # is our top-of-the-stack-marker
' first branch (for more As and Bs)
Q1 -(AB,ϵ,+)-> Q2 ' for every A or B push a + sign on the stack
Q2 -(AB,ϵ,+)-> Q2
Q2 -(C,+,ϵ)-> Q3 ' for every C consume a + sign
Q3 -(AB,ϵ,+)-> Q2
Q3 -(C,+,ϵ)-> Q3
Q3 -(ϵ,#,#)-> Q1 ' if we reach the top of the stack, return to the Q1 state
Q2 -(ϵ,#,#)-> Q1
Q2 -($,+,+)-> Q6 ' if the input is processed and the stack is not empty => go in the state of acceptance
Q3 -($,+,+)-> Q6 ' if the input is processed and the stack is not empty => go in the state of acceptance
' second branch (for more Cs)
Q1 -(C,ϵ,-)-> Q4 ' for every C push a - sign on the stack
Q4 -(C,ϵ,-)-> Q4
Q4 -(AB,-,ϵ)-> Q5 ' for every A or B consume a - sign
Q5 -(AB,-,ϵ)-> Q5
Q5 -(C,ϵ,-)-> Q4
Q5 -(ϵ,#,#)-> Q1
Q4 -(ϵ,#,#)-> Q1
Q4 -($,-,-)-> Q6 ' if the input is processed and the stack is not empty => go in the state of acceptance
Q5 -($,-,-)-> Q6 ' if the input is processed and the stack is not empty => go in the state of acceptance
Logic describtion:
We push a #-sign on the stack to detect the top of the stack.
Now we operate in two "zones". The first zone handles a positive number of A and Bs compared to Cs and the other zone handles a negative number of As and Bs compared to Cs.
We're working with three signs that are part of the Stack:
- '# = top marker
- '+ = there are more As and Bs read than Cs
- '- = there are more Cs read than As or Bs
The first transition is from starting state to a new starting state. This transition is only used in reason of pushing the top marker on the stack. The new original starting state is never reached again.
The new starting state is the switch and is hit everytime we hit the top marker on the stack. From this state we're visiting the zones in dependency of the next A and B or C.
I hope that explains it. The described automaton should give you a good idea. I think there is a little error in it, but if you follow the idea and you got it right then you can fix it :)
I build the described automaton with an online simulator to test it. You can find it here. This simulator uses epsilon as initialization for the input band and for doing nothing... so it's a bit confusing. I added some tests that can be run by clicking the green arrow next to "Bulk Testing".