final solution with test cases