For me it was How to Design Programs (HtDP) by Felleisen et al.
Before that I wrote code that I know hate from my core. It really taught me how to write code properly using functions. More than that it taught me how to break down a problem into parts and solve each part correctly.
Very few books teach problem solving and programming together is such a fantastic way.