slow version
better version
a good implementation