main algorithm