Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A java practice problem

Tags:

java

logic

I came across this problem in javabat(http://www.javabat.com/prob/p183562):

We want to make a row of bricks that is goal inches long. We have a number of small bricks (1 inch each) and big bricks (5 inches each). Return true if it is possible to make the goal by choosing from the given bricks. This is a little harder than it looks and can be done without any loops.

makeBricks(3, 1, 8) → true
makeBricks(3, 1, 9) → false
makeBricks(3, 2, 10) → true

I came up with this solution:

public boolean makeBricks(int small, int big, int goal) {
    if (goal > small + big * 5)
        return false;
    else if (goal % 5 == 0) 
        return goal / 5 <= big;
    else
        return goal % 5 <= small;
}

This passed the test. But I found a counter-example myself: makeBricks(10, 0, 10) -> true. My logic will return false. How should I fix my logic? Or is there a better way to do this?

like image 940
fei Avatar asked Jun 28 '09 01:06

fei


3 Answers

The second test is entirely unnecessary. The first one checks to see that you have enough total length, and all is good.

But the second one again checks if you have enough total length (return goal / 5 <= big;) but this ignores the length added by small bricks. The issue is you are checking if it is a multiple of 5, and automatically assuming that you are going to use only large bricks if it is. In reality, you could use five small bricks instead. (or, as in your example, 10 small bricks.) The last check is correct, testing if you have enough granularity to get the right length, assuming you have enough length.

like image 153
Jeremy Salwen Avatar answered Nov 17 '22 22:11

Jeremy Salwen


I think you can just remove your second test. I would try this:

public boolean makeBricks(int small, int big, int goal) {
    if (goal > small + big * 5)
        return false;
    else
        return goal % 5 <= small;
}

The first test just checks how long the row would be if we just put all the bricks in a row. If that's not as long as the goal, then we know that it's impossible.

Next, we calculate the minimum number of small bricks: goal % 5. For example, if the goal is 8 and we have 1000 large bricks, how many small bricks do we need? 8 % 5 is 3, so we need 3 small bricks at the end of the row.

If we have enough small bricks, and the total length of all the bricks is enough, then we can meet the goal.

like image 18
Don Kirkby Avatar answered Nov 17 '22 21:11

Don Kirkby


Your logic is incorrect. This should do it:

public boolean makeBricks(int small, int big, int goal) {
  if (goal < 0 || big < 0 || small < 0) {
    throw new IllegalArgumentException();
  } else if (goal > big * 5 + small) {
    return false;
  } else if (goal % 5 <= small) {
    return true;
  } else {
    return false;
  }
}

is sufficient. This can be simplified to:

public boolean makeBricks(int small, int big, int goal) {
  if (goal < 0 || big < 0 || small < 0) {
    throw new IllegalArgumentException();
  } else {
    return goal <= big * 5 + small && goal % 5 <= small;
  }
}

Of course, the sanity check on negative goal, small or big is not strictly required but recommended. Without those checks, the result can simply be obtained by:

public boolean makeBricks(int small, int big, int goal) {
  return goal <= big * 5 + small && goal % 5 <= small;
}
like image 11
cletus Avatar answered Nov 17 '22 21:11

cletus