algorithm simplified courtesy @Engelberg