rewrote recusion function for better efficiency