Search code examples
javawhile-looptermination

While loop early termination


I have this task that produces pancake and users can also eat it at the same time. The condition is that it's only 12 pancake that can be produced within 30 seconds. The problem I am having is that as the pancake are being produced, users are eating it as expected but when it produces the last pancake (i.e the 12th one), it terminates without the user eating it, leaving 1 pancake wasted. My final output is thus:

Total number of cake produced is 12
Total number of cake eaten is 11
Total number of pancake remained is 1
public class PanCakeTask {

    int consumedPancake;
    int availablePancake;
    int totalPancakeProduced;
    List<String> usersList = new ArrayList<>();

     void producePancake(HashMap<String,Integer>users){

          consumedPancake =0;
          availablePancake = 0;
          totalPancakeProduced = 0;

        if ( totalPancakeProduced <12) {

            for (String user: users.keySet()){
                consumedPancake +=users.get(user);
            }

            //only continue with the production of pancakes if the number of pancakes
            //produced has not exceeded the quota that was given (i.e 12)

            System.out.println("Pancake produced");
            //increment the number of pancakes available
            availablePancake +=1;
            totalPancakeProduced = consumedPancake + availablePancake;

            eatPancake(users);

        }
    }
     void eatPancake(HashMap<String,Integer>users){
         if (usersList.size()>=1){
             System.out.println("The list is "+usersList);
             //first pick the user at random
             Collections.shuffle(usersList)

             int numberEaten = users.get(usersList.get(0));
             
             //get the user that is on index zero after the list has been shuffled
             //then check how many pancake that the picked user has eaten
             //because each user is expected to eat a maximum of 5 pancake

             if (numberEaten >=5){
                 //This means that this user has exhausted his/her quota so he/she cannot
                 //be allowed to eat again
                 //In this case, the eatPancake method is called again to randomly pick another user
                 //I am thinking of removing the user from the list here so that he/she cannot be picked again
                 usersList.remove(0);
                 eatPancake(users);
             }else {
                 //Meaning that the user still has some quota left for him/her to eat
                 //In this other condition, it will check if there is an available pancake produced

                 if (availablePancake >=1){
                     //user will now eat the pancake
                     //then increment the number of pancake eaten by that user
                     // and decrement the number of pancakes available

                     int newCount = numberEaten + 1;
                     availablePancake -=1;

                     //finally update the user that just eaten the pancake
                     users.put(usersList.get(0),newCount);
                 }
             }
         }
    }
    public void performTask(){

        //Hashmap is used to store the users because of key-value pairs
        HashMap <String,Integer> users = new HashMap<>();
        users.put("user1",0);
        users.put("user2",0);
        users.put("user3",0);

        usersList.addAll(users.keySet());

        System.out.println(users);
        System.out.println(usersList);


        //This task can only be executed in 20 seconds

        Instant stop = Instant.now().plusSeconds(20);
        System.out.println("The starting time is "+Instant.now());

        while (stop.isAfter(Instant.now())){
            //only continue the process if it has not exceeded 20 seconds

            if (totalPancakeProduced <12){
                producePancake(users);
            }else {
                break;
            }
        }
        int available = totalPancakeProduced - consumedPancake;
        int numbersLeftToMeetTheDemand = totalPancakeProduced - 15;
        System.out.println("The ending time is "+Instant.now());
        System.out.println("Total number of cake produced is "+totalPancakeProduced);
        System.out.println("Total number of cake eaten is "+consumedPancake);
        System.out.println("Total number of pancake remained is "+available);
                
}

Solution

  • You are updating consumedPancake only within the producePancake method.

    This will be an issue when your loop reaches its last iteration. Because, producePancake will calculate consumedPancake based on the users map. After that, eatPancake is called, which updates the map. This will lead in wrong number of consumed pancakes because consumedPancake isn't updated again after eatPancake in the last iteration.

    To fix this, instead of modifying consumedPancake in the producePancake method, increment it in the eatPancake method after a pancake is eaten.

    Like this:

        void eatPancake(HashMap<String,Integer>users){
             if (usersList.size()>=1){
                 System.out.println("The list is "+usersList);
                 //first pick the user at random
                 Collections.shuffle(usersList)
    
                 int numberEaten = users.get(usersList.get(0));
                 
                 //get the user that is on index zero after the list has been shuffled
                 //then check how many pancake that the picked user has eaten
                 //because each user is expected to eat a maximum of 5 pancake
    
                 if (numberEaten >=5){
                     //This means that this user has exhausted his/her quota so he/she cannot
                     //be allowed to eat again
                     //In this case, the eatPancake method is called again to randomly pick another user
                     //I am thinking of removing the user from the list here so that he/she cannot be picked again
                     usersList.remove(0);
                     eatPancake(users);
                 }else {
                     //Meaning that the user still has some quota left for him/her to eat
                     //In this other condition, it will check if there is an available pancake produced
    
                     if (availablePancake >=1){
                         //user will now eat the pancake
                         //then increment the number of pancake eaten by that user
                         // and decrement the number of pancakes available
    
                         int newCount = numberEaten + 1;
                         availablePancake -=1;
                         //finally update the user that just eaten the pancake
                         users.put(usersList.get(0),newCount);
                         //here
                         consumedPancake++;
                     }
                 }
             }
        }
    

    amd remove from producePancake:

    void producePancake(HashMap<String,Integer>users){
    
              //consumedPancake =0;
              availablePancake = 0;
              totalPancakeProduced = 0;
    
            if ( totalPancakeProduced <12) {
                /*
                for (String user: users.keySet()){
                    consumedPancake +=users.get(user);
                }
                */
    
                //only continue with the production of pancakes if the number of pancakes
                //produced has not exceeded the quota that was given (i.e 12)
    
                System.out.println("Pancake produced");
                //increment the number of pancakes available
                availablePancake +=1;
                totalPancakeProduced = consumedPancake + availablePancake;
    
                eatPancake(users);
    
            }
        }
    

    Also, there are some redundant parts in your code, but that doesn't seem to be the cause of the problem, so ignored them.