Based on Assignment VI Stanford course CS193P