public Action getMove(CritterInfo info) {
count++;
Direction d = info.getDirection();
if (count < 100) {
if (info.getFront() == Neighbor.OTHER) {
return Action.INFECT;
} else {
return Action.RIGHT;
}
}
if (count >= 100) {
if (info.getFront() == Neighbor.OTHER) {
return Action.INFECT;
} else if (count / 100.0 < 2.0 && count / 100.0 >= 1.0 && !(d == Direction.EAST)) {
return Action.LEFT;
} else if (count / 100.0 < 3.0 && count / 100.0 >= 2.0 && !(d == Direction.WEST)) {
return Action.RIGHT;
} else {
return Action.HOP;
}
}
return Action.INFECT;
}
Right now I have this code that is part of my critter and i'm having problems are the if (count >= 100) part of the code. I can't get my go east and go west code to repeat itself because when I divide count by 100.0, it only works up until 299 then it just stays going west running into the wall. I've tried to set an else if statement after my go west code stating
} else if (count == 299) {
count = 0;
}
but this didn't solve my problem either. Any ideas? I just want my critter to sweep east and west over and over again.
Just use variables instead of your numbers, and change them each time their numbers are reached.Then you can create a method that changes the direction each time the number reaches 100+(100*n).
So, if you reach 200, it will check that the condition I set above is true and will therefore change directions for the next 100 numbers.
Was this what you were looking for , or did I misunderstand what you wanted?
You can use some kind of "cyclic" function like modulo (%) instead of the absolute value of count. E.g.
public Action getMove(CritterInfo info) {
count++;
Direction d = info.getDirection();
if (count < 100) {
if (info.getFront() == Neighbor.OTHER) {
return Action.INFECT;
} else {
return Action.RIGHT;
}
}
else {
int choiceOfAction = (count - 100)%200;
if (0 <= choiceOfDir && choiceOfDir < 100 && !(d == Direction.EAST)) {
return Action.LEFT;
} else if (100 <= choiceOfDir && choiceOfDir < 200 && !(d == Direction.WEST)) {
return Action.RIGHT;
} else {
return Action.HOP;
}
}
}
The line int choiceOfAction = (count - 100)%200; will yield a value of choiceOfAction with:
if count is in [100, 200[ : choiceOfAction is in [0, 100[
if count is in [200, 300[ : choiceOfAction is in [100, 200[
if count is in [300, 400[ : choiceOfAction is in [0, 100[
etc.
Note that I removed the last return in your method that was never reached, and also, that in the case above you will HOP only when you reach the limit and change direction.
Related
I have to write a lot of conditions, but SonarLint is giving me error, asking to refactor the method to reduce its cognitive complexity.
How to resolve this. I tried switch-case, but that is also giving the same error.
public enum ExampleEnum {
UNKNOWN(-1),
D0_D100(0),
D100_D200(100),
D200_D300(200),
D300_D400(300),
D400_D500(400),
D500_D600(500),
D600_D700(600),
D700_D800(700),
D800_D900(800),
D900_D1000(900);
private int score;
ExampleEnum(int score) {
this.score = score;
}
}
public static ExampleEnum getScoreType(Integer score) {
if (Objects.isNull(score) || score < D0_D100.score) {
return UNKNOWN;
} else if (score >= D0_D100.score && score < D100_D200.score) {
return D0_D100;
} else if (score >= D100_D200.score && score < D200_D300.score) {
return D100_D200;
} else if (score >= D200_D300.score && score < D300_D400.score) {
return D200_D300;
} else if (score >= D300_D400.score && score < D400_D500.score) {
return D300_D400;
} else if (score >= D400_D500.score && score < D500_D600.score) {
return D400_D500;
} else if (score >= D500_D600.score && score < D600_D700.score) {
return D500_D600;
} else if (score >= D600_D700.score && score < D700_D800.score) {
return D600_D700;
} else if (score >= D700_D800.score && score < D800_D900.score) {
return D700_D800;
} else if (score >= D800_D900.score && score < D900_D1000.score) {
return D800_D900;
} else {
return D900_D1000;
}
}
Put the logic into a loop. something like:
public static ExampleEnum getScoreType(Integer score) {
if (Objects.isNull(score) || score < D0_D100.score) {
return UNKNOWN;
for (int i =0; i< ExampleEnum.values().length-1;i++) {
if (ExampleEnum.values()[i].score <= score && ExampleEnum.values()[i+1].score > score )
return ExampleEnum.values()[i];
}
return D900_D1000;
}
You can use of the Stream API to remove this redundancy.
For that, you make use of the fact that the natural order of your enum-members reflects the order of the corresponding score.
As the source of the stream, you can use an array returned by the values() call or an EnumSet (which a specialized ordered collection) generated via EnumSet.allOf().
While iterating over the enum-members we need to find the first constant which score is equal or less to the given score. Because score property of your enum represent the lower boundary of the range, only one condition would be sufficient to find out if the given score falls into the range corresponding to a particular enum-member.
This logic can be expressed by using combination of operations filter() + findFirst():
public static ExampleEnum getScoreType(Integer score) {
if (score == null || score < ExampleEnum.D0_D100.score) {
return ExampleEnum.UNKNOWN;
}
return EnumSet.allOf(ExampleEnum.class).stream()
.filter(e -> score >= e.score)
.findFirst()
.orElse(ExampleEnum.D900_D1000);
}
Note: you're not checking if the given score exceeds the maximum range, in such case the last enum-constant would be returned. But since its name D900_D1000 signifies that it represents a limited range values, you might want to add this check.
int count = charFreq.get(guessChar);
int matchedChars = updatedCharFreq.get('_');
if (updatedKeyVals.contains('_')) {
if (count == matchedChars) {
;
}
if (count < matchedChars) {
;
}
else {
count = count - matchedChars;
}
Method works if count < matchedChars, and also the else statement. It just skips past the if equality statement. I have been trying to figure it out, but just can't seem to.
As commented, you neglected to chain the first if with an else.
I suggest accounting for all cases explicitly plus an extra final case that should never be reached. The extra check is for defensive programming, to guard against editing errors.
if (count == matchedChars) {
// No code needed here.
} else if (count < matchedChars) {
// No code needed here.
} else if (count > matchedChars) {
count = count - matchedChars;
} else {
throw new IllegalStateException( … ) ; // Should never reach this point.
}
It seems you only care about the case where the first number is bigger than the second. So we could shorten this code.
if (count > matchedChars) {
count = count - matchedChars;
}
Alternatively, you can use the static method Integer.compare. To quote the Javadoc:
Returns: the value 0 if x == y; a value less than 0 if x < y; and a value greater than 0 if x > y
if( Integer.compare( count , matchedChars ) > 0 ) {
count = count - matchedChars;
}
I'm more of an intermediate android dev and I want to learn how to write more clean and effective code, and I've come to this problem on my app that requires to check a bunch of statements like if a variable is less than something or more for each individual rating.
private void rateStock(double peRatio) {
//For Dividend Stocks
if(currentDiv != 0 && fiveYearDiv != 0){
double dividendDiff = currentDiv - fiveYearDiv;
if (peRatio <= 20 && peRatio > 0 && dividendDiff >= 0.01 && payoutRatio <= 0.65) {
int stockRatingDividend = 5;
addItems(stockRatingDividend);
} else if (peRatio > 20 && peRatio <= 25 && dividendDiff >= 0.005 && payoutRatio <= 0.75) {
int stockRatingDividend = 4;
addItems(stockRatingDividend);
} else if (peRatio > 25 && peRatio <= 30 && dividendDiff >= 0.001 && payoutRatio <= 0.85) {
int stockRatingDividend = 3;
addItems(stockRatingDividend);
} else if (peRatio > 30 && peRatio <= 35 && payoutRatio <= 0.95) {
int stockRatingDividend = 3;
addItems(stockRatingDividend);
} else if( peRatio > 35 && peRatio <= 40 && currentDiv > fiveYearDiv && payoutRatio >= 100) {
int stockRatingDividend = 2;
addItems(stockRatingDividend);
} else if( peRatio > 40 || peRatio < 0 && fiveYearDiv > currentDiv && payoutRatio >= 100) {
int stockRatingDividend = 1;
addItems(stockRatingDividend);
} else {
int stockRatingDividend = 0;
addItems(stockRatingDividend);
}
}
}
As you can see by the code above it's very messy and cluttered and doesn't even work correctly, because there are too many conditions it has to check and it usually doesn't fit into any else if statement and just returns 0
I know it might be a lot but can someone at least guide me to a post or something on how I could write more effective and clean code rather than a cluttered mess of else if statements for this block of code?
the possible values of your parameters are not fully represented by the choices in youre if/else branches. So the best way would be to implement a class which decides by itself, if it is responsible for the computation of your single resulting value stockRatingDividend. a sketch of this (with no getters, constructor and no handling, if one border for the min/max is not set) would be:
public class SRDResolver {
public class SRDRolver {
private int peRatioMin;
private int peRatioMax;
private double dividendDiffMin;
private double dividendDiffMax;
private double payoutRatioMin;
private double payoutRatioMax;
private double stockRatingDividend;
public boolean hasSolution(int peRatio,double dividendDiv,double payoutRatio){
return peRatio > peRatioMin && peRatio <= peRatioMax && dividendDiv > dividendDiffMin && dividendDiv <= dividendDiffMax && payoutRatio > payoutRatioMin && payoutRatio <= payoutRatioMax;
}
}
}
then you put the intances in a list. You then get the correct instance from streaming that list with filter(i-> i.hasSolution(...).findFirst(), which gives you an Optional as a result. If it is present, you take it's stockRatingDividend,otherwise you use your fallback value of 0.
That way you can easyily add new instances, if you need,without cluttering if/else. You might add some checks, when you put the instances into the list to ensure, that the number spaces span of the instances do not overlap.
For any future wanderers, that have the same question, I have come up with a solution myself!
What I did was split it into different classes and in the first class ValueLists.java
I created all the ranges and made a getter for the list.
public List<Range> getPeRatioRanges() {
Range range20 = new Range(0, 20);
Range range25 = new Range(21, 25);
Range range30 = new Range(26, 30);
Range range35 = new Range(31, 35);
Range range40 = new Range(36, 40);
List<Range> list = new LinkedList<>(Arrays.asList(range40, range35, range30, range25, range20)); // add in reverse order cuz index = rating
return list;
}
And in the other class CheckRatingOfStock.java I created a simple loop for iterating through the ranges and get the rating.
List<Range> peRatioRanges = getPeRatioRanges();
for (int i = 0; i < peRatioRanges.size(); i++) {
Range range = peRatioRanges.get(i);
int intPERatio = (int) rawPEratio;
if (range.contains(intPERatio)) {
rating = i + 1;
}
}
Here the index of the range is the rating + 1, so if its 0-20 its the rating of 5, because the list is reversed.
This way with 2 blocks of code I avoid a lot of back and forth and the clutter of mass else if statements, and also make it much more easily maintainable and cleaner, atleast in my opinion.
This could be implemented as a method:
static int getIndexOfRange(int intPERatio, List<Range> ranges)
{
for (int i=0; i< ranges.size(); i++)
if (ranges.get(i).contains(intPERatio))
return i+1; //if found, return immediatelly
return -1; //if it reaches this line, means the item was not found
} //return -1 as representation of this
The below two could be combined as it does the same thing.
else if (peRatio > 25 && peRatio <= 30 && dividendDiff >= 0.001 && payoutRatio <= 0.85) {
int stockRatingDividend = 3;
addItems(stockRatingDividend);
} else if (peRatio > 30 && peRatio <= 35 && payoutRatio <= 0.95) {
int stockRatingDividend = 3;
addItems(stockRatingDividend);
}
Also, I would recommend refactoring the if-else block to a new method which returns stockRatingDividend. This would keep the dividend computation logic separate from the other logic, which would actually make the code more understandable.
if(currentDiv != 0 && fiveYearDiv != 0){
double dividendDiff = currentDiv - fiveYearDiv;
addItems(getStockRatingDividend(/*arguments*/));
}
problem
Given an array of ints, return true if every 2 that appears in the array is next to another 2.
twoTwo({4, 2, 2, 3}) → true
twoTwo({2, 2, 4}) → true
twoTwo({2, 2, 4, 2}) → false
my code is only mising this case
twoTwo({2, 2, 7, 2, 1}) → false; but returns true;
my code
public boolean twoTwo(int[] nums) {
int notFound = 0;
int i = 0;
boolean found = false;
if (nums.length == 0) {
return true;
}
if (nums.length == 1 && (nums[0] != 2)) {
return true;
}
for (i = 0; i < nums.length - 1; i++) {
if ((nums[i] == 2 && nums[i + 1] == 2)) {
found = true;
}
if (nums[nums.length - 1] == 2 && nums[nums.length - 2] != 2) {
return false;
}
if (nums[i] != 2) {
notFound++;
}
}
if (nums[i] != 2) {
notFound++;
}
if (notFound == nums.length) {
return true;
}
return found;
}
There is never a "wrong" way to code a working solution, but there are bad ways. In your solution, I think you try to handle every individual case in chaotic ways instead of tackling the overarching problem. You have floating variables all over the place and hard coded numbers that are very specific to each case. You have unnecessary and excessive returns.
My suggestion is to work on solving your own question "Return true if all 2's are next to another 2" - instead of trying to code for each specific case. You aren't REALLY solving a problem if you are hard coding to work on a specific subset of that problem.
Just my critique; keep working at it.
Consider refactoring your for loop with this as a starting point, see if you can figure out the logic (semi pseudo code):
for(int i = 1; i < nums.length-1; i++) { // Why do I start i at 1?
if(nums[i]==2) {
if(nums[i-1] == 2 || nums[i+1] == 2) // What does this if check?
do something; // What to do here? Look up the 'continue' keyword.
else
return false;
}
}
return true;
You will find this for loop is JUST a starting point. There will be more needed to add, but hopefully a good jumping point for you.
Best of luck!
public boolean twoTwo(int[] nums)
{
if (nums.length == 1 && nums[0] == 2)
return false;
for (int i = 0; i < nums.length - 1; i++)
if (nums[i] == 2)
if (nums[i + 1] != 2 && (i > 0 && nums[i - 1] != 2))
return false;
return true;
}
Basically this goes through each number in the list, and if it finds a 2, it checks it against the previous and next numbers. That's all it does.
I made a Board and I set the board's layout to null. So I position my token's by moving them pixel by pixel. But when turning the corners I am having a trouble. After first 10 position token can make the turn and continue for the next 10 position. But it is impossible for my token to make the 2. turn.
Can anyone advice me a better code for this problem. I think I make things get more complicated than it is.
if(g.getPosx() <= 650 && g.getPosx() >= 50 && g.getPosy()==650) {
if(g.getPosx()-unitChange*d.getDice() <= 50) {
temp = unitChange*d.getDice() - (g.getPosx() - 50);
g.setPosx(50);
g.setPosy(g.getPosy()-temp);
}
else {
g.setPosx(g.getPosx()-unitChange*d.getDice());
temp = 0;
}
}
else if(g.getPosy() <= 650 && g.getPosy() >= 50 && g.getPosx()==650) {
if(g.getPosy()-unitChange*d.getDice() <= 50) {
temp = unitChange*d.getDice() - (g.getPosy() - 50);
g.setPosy(50);
g.setPosx(g.getPosx()-temp);
}
else {
g.setPosy(g.getPosy()-unitChange*d.getDice());
temp = 0;
}
}
else if(g.getPosx() <= 650 && g.getPosx() >= 50 && g.getPosy()==50) {
if(g.getPosx()-unitChange*d.getDice() <= 50) {
temp = unitChange*d.getDice() - (g.getPosx() - 50);
g.setPosx(50);
g.setPosy(g.getPosy()-temp);
}
else {
g.setPosx(g.getPosx()-unitChange*d.getDice());
temp = 0;
}
}
else if(g.getPosy() <= 650 && g.getPosy() >= 50 && g.getPosx()==50) {
if(g.getPosy()-unitChange*d.getDice() <= 50) {
temp = unitChange*d.getDice() - (g.getPosy() - 50);
g.setPosy(50);
g.setPosx(g.getPosx()-temp);
}
else {
g.setPosy(g.getPosy()-unitChange*d.getDice());
temp = 0;
}
}
Instead of using the current X and Y positions to track which location the piece is stopped on, try tracking which property the piece has landed on instead. so property 1 would be the first stop on the board after GO all the way up to boardwalk at position 39. Then you can have a function like
movePlayerToLocation(Player player, int location){
// calculate your x and y based on the property locatoin
if(locatoin < 11){
// on first edge
} else if (location < 21) {
// on second edge
} else if (location < 31)
// on third edge
} else {
// on fourth edge of the board
}
// do your g.setPos-ing
}