CodeScientist: End-to-End Semi-Automated Scientific Discovery with Code-based Experimentation