This kind of problem has really short solutions when you have access to collection-at-a-time operations. For example, in Haskell:
pascal 1 = [1]
pascal i = zipWith (+) ([0] ++ pascal (i - 1)) (pascal (i - 1) ++ [0])
I'm not answering your question but just wanted to pique your interest in this because you were asking about language choice and had mentioned that your solution took 50 lines.
The above solution expresses the recursive solution as the sum of two earlier rows after appending some zeros. There is very little room for errors to hide and it provides you with a kind of 'definitional' starting point to begin optimizing if you want.
1) When you're writing a function on integers or lists using explicit recursion, usually there's need for only one base case. Do you really need a separate definition for pascal 2? What about sum' [1]?
2) Often it's better to use fold instead of explicit recursion. If you wonder whether you can rewrite your function in terms of fold...
The above solution expresses the recursive solution as the sum of two earlier rows after appending some zeros. There is very little room for errors to hide and it provides you with a kind of 'definitional' starting point to begin optimizing if you want.