How to check values in a string? - java

So i have a string in military time format : "1532" corresponding to 3:32pm.
I'm trying to write a method to check if each digit in time string is an appropriate digit. So the first element cannot be greater than 2 or equal to 0, and so forth. Currently, my code doesn't run past the second log statement and I'm hoping you guys could help!
cheers!
String mOpen = "1532";
Log.d("hoursTesting","pass1, length is > 2");
if(mOpen.getText().length() == 4)
{
Log.d("hoursTesting","pass2, length is == 4");
char[] tempString = mOpen.getText().toString().toCharArray();
if(tempString[0] != 0 && tempString[0] < 3)
{
Log.d("hoursTesting","pass3, first index is != 0 and < 3");
if(tempString[0] == 1)
{
Log.d("hoursTesting","pass4, first index is 1");
if(tempString[2] <= 5)
{
Log.d("hoursTesting","pass5, third index is <= 5, success!");
}
}
else //tempString[0] is equal to 2
{
Log.d("hoursTesting","pass4, first index is 2");
if(tempString[1] < 4)
{
Log.d("hoursTesting","pass5, second index is <3");
if(tempString[2] <= 5)
{
Log.d("hoursTesting","pass6, third index is <= 5, success!");
}
}
}
}
}

tempString contains characters, not numbers.
i.e. '0' not 0 etc.
Easiest fix is to compare characters e.g. tempString[0] == '1' Alternatively, you can do something like int digit1 = tempString[0] - '0'; - but that kind of assumes you already know you just have digits in the string.
Note that cos of those clever ASCII guys and their tricky character set '0' < '1' < '2' etc, so you can still say if (str[0] < '2') etc. You just need to be a bit careful that you are only dealing with digits.
Personally I'd convert the first 2 chars to a number and the second 2 chars to a number and then just check 0 <= number1 <= 23 and 0 <= number2 <= 59.

You are comparing char with int here:
if(tempString[0] != 0 && tempString[0] < 3)
It should work like this:
if(tempString[0] != '0' && tempString[0] < '3')

I would substring the hours and minutes components and then check to see if each one be in range:
public boolean isTimeValid(String mOpen) {
int hours = Integer.parseInt(mOpen.substring(0, 2));
int minutes = Integer.parseInt(mOpen.substring(2));
if ((hours >= 0 && hours <= 24) && (minutes >= 0 && minutes <= 59)) {
return true;
}
else {
return false;
}
}

Related

Solution codewars to car Mileage problem, running out of ideas?

I am trying to work out a solution to the CodeWars challenge Catching Car Mileage Numbers:
Write the function that parses the mileage number input, and returns a 2 if the number is "interesting" (see below), a 1 if an interesting number occurs within the next two miles, or a 0 if the number is not interesting.
Interesting numbers are 3-or-more digit numbers that meet one or more of the following criteria:
Any digit followed by all zeros: 100, 90000
Every digit is the same number: 1111
The digits are sequential, incementing†: 1234
The digits are sequential, decrementing‡: 4321
The digits are a palindrome: 1221 or 73837
The digits match one of the values in the awesomePhrases array
† For incrementing sequences, 0 should come after 9, and not before 1, as in 7890.
‡ For decrementing sequences, 0 should come after 1, and not before 9, as in 3210.
I can pass all tests in the first batch, but fail to pass the second batch.
Any feedback would be very much appreciated, not only on a possible solution but also to the way I'm thinking about the exercise.
public static int isInteresting(int number, int[] awesomePhrases) {
for (int offSet = 0; offSet <= 2; offSet++) {
int testNumber = number;
testNumber += offSet;
boolean isYellow = testNumber != number;
int yellowOffset = 0;
if (isYellow) {
yellowOffset = 1;
}
//check three or more digit number
boolean greaterThan99 = testNumber > 99;
int[] numbers = Integer.toString(testNumber).chars().map(c -> c - '0').toArray();
int zeroCounter = 0;
int identicalCounter = 0;
int incrementingCounter = 0;
int decrementingCounter = 0;
int palindromeCounter = 0;
boolean endsInZero = numbers[numbers.length - 1] == 0;
for (int i = 0; i < numbers.length; i++) {
//check digit followed by zeros
if (numbers[i] == 0) {
zeroCounter++;
}
if (i + 1 < numbers.length) {
//check every digit is the same
if (numbers[i] == numbers[i + 1]) identicalCounter++;
//check ascending order
if (numbers[i + 1] - numbers[i] == 1) incrementingCounter++;
//check descending order
if (numbers[i] - numbers[i + 1] == 1) decrementingCounter++;
}
}
if (greaterThan99) {
//check awesomePhrases
for (int phrase : awesomePhrases) {
if (phrase == testNumber) return 2 - yellowOffset;
}
//check palindrome
int reversedIndex = numbers.length - 1;
for (int i = 0; i < numbers.length; i++) {
if (numbers[reversedIndex] == numbers[i]) {
palindromeCounter++;
}
reversedIndex--;
}
if (zeroCounter == numbers.length - 1) return 2 - yellowOffset;
if (identicalCounter == numbers.length - 1) return 2 - yellowOffset;
if (incrementingCounter == numbers.length - 1) return 2 - yellowOffset;
if (incrementingCounter == numbers.length - 2 && endsInZero) return 2 - yellowOffset;
if (decrementingCounter == numbers.length - 1) return 2 - yellowOffset;
if (decrementingCounter == numbers.length - 2 && endsInZero) return 2 - yellowOffset;
if (palindromeCounter == numbers.length) return 2 - yellowOffset;
}
}
return 0;
}
I've tried pretty much all I know but to no result, all the tests I try pass, would love to know what I'm doing wrong.
The problem is in how your code tests for increasing sequences that end in a zero. It is not enough to test that the sequence has n-2 increments and the last digit is a zero, because that will give a false positive on numbers like 6780. It is required that the one-but-last digit is a 9.
A similar issue exist for the decreasing sequence logic, however, there you would not need a special test for an ending zero at all. This condition is covered by counting n-1 decrements, where the ending could be a 1 followed by a zero. There is no special case to be handled here.
To fix the first problem, I would suggest you not only check whether the last digit is a zero, but whether the last two digits are 9 and 0, or in other words, that the number modulo 100 is equal to 90.
You could replace this:
boolean endsInZero = numbers[numbers.length - 1] == 0;
by this:
boolean endsInNinety = testNumber % 100 == 90;
and then replace:
if (incrementingCounter == numbers.length - 2 && endsInZero) return 2 - yellowOffset;
by:
if (incrementingCounter == numbers.length - 2 && endsInNinety) return 2 - yellowOffset;
and finally remove this test:
if (decrementingCounter == numbers.length - 2 && endsInZero) return 2 - yellowOffset;
This will fix it.
Note that it can be helpful to have your function print the input it gets, so that when a test fails, at least you can know for which input there was a problem:
System.out.println("input " + number);

I dont understand why my Java code isnt reading IX as 9 but is reading LIX as 59

I am trying to create some code to read roman numerals and turn them into an integer. the issue im having is the 9s and 4s. I am able to get it to read if the 9 or 4 is inside a number (I.E LIV is 54 and LXI is 59) but by its self (IV and IX) it only reads 6 and 11.
here is my code:
public static void RomantoInt(String s) {
HashMap<Character, Integer> RomanNums = new HashMap<>();
int count = 0;
RomanNums.put('I', 1);
RomanNums.put('V', 5);
RomanNums.put('X', 10);
RomanNums.put('L', 50);
RomanNums.put('C', 100);
RomanNums.put('D', 500);
RomanNums.put('M', 1000);
LinkedList<Character> UserInput = new LinkedList<>();
//Adds Each numeral to the Array
for (int i = 0; i < s.length(); i++) {
char userint = s.charAt(i);
UserInput.add(userint);
}
//loop through the array backwards and adds up the count.
for(int j =UserInput.toArray().length -1; j> -1 ; j--) {
int grab = RomanNums.get(UserInput.get(j));
count += grab;
// Checks for 4s and 9s.
if(grab == RomanNums.get('X') && (j - 1) == RomanNums.get('I')) {
count -= 2;
}
}
System.out.println(count);
Comparing j - 1 -- which is a position in a string -- to the value of a roman numeral does not seem to make any sense.
Specifically, it only works when the roman 'I' is the second character, exactly.
What you really want to be testing is whether the character at the (j-1)'th position is 'I'.
The correct formulation should be something like
if (grab == RomanNums.get('X') &&
j > 0 &&
UserInput.get(j-1) == 'I') ...
This was my solution for leetcode: https://leetcode.com/problems/roman-to-integer/
You have the right idea about reading the input backwards and one loop should be enough to get the job done.
All you need to do is account for the cases when you have to subtract the roman numeral, and you can do that by keeping track of the previous roman numeral for comparison.
For example when input string is: "IX"
We start at 'X' in the first iteration and since previous is equal to '?' we just add 10 and set previous to 'X'. Now when we attempt to sum up 'I' in the next iteration, we look at previous and notice that it is an 'X' and instead of adding 1 to the running sum , we should subtract 1. The total should be 9.
public int romanToInt(String s) {
int sum = 0;
char prev = '?';
for(int i = s.length()-1;i >= 0;i--) {
switch(s.charAt(i)) {
case 'I' : sum += prev == 'V' || prev == 'X' ? -1 : 1;
break;
case 'V' : sum += 5;
break;
case 'X' : sum += prev == 'L' || prev == 'C' ? -10 : 10;
break;
case 'L' : sum += 50;
break;
case 'C' : sum += prev == 'D' || prev == 'M' ? -100 : 100;
break;
case 'D' : sum += 500;
break;
case 'M' : sum += 1000;
break;
default :
break;
}
prev = s.charAt(i);
}
return sum;
}
Time complexity is O(n) - Iterated the length of the input string
Space complexity is O(1) - No additional data structure was needed

How to define 00-90 when I have charAt each of it

What I need to do is write a program that makes the first character (which is charAt(0) )and the second character (which is charAt(1) ) to become a value that not exceeding 90 which is (0 ~ 90) , but I also have to define them as an independent digit , because my program will make it to invalid if it is other than a digit.
So for an example it will become invalid if I type in 91
and it will valid if I type in number between 0~90
but I have no idea how to do this...
if(Character.isDigit(loop1.charAt(0))&&
Character.isDigit(loop1.charAt(1)))
I have tried this ,but not working
if(Character.isDigit(loop1.charAt(0)) &&
Character.isDigit(loop1.charAt(1)) &&
((loop1 >= 0)&&(loop1 <= 90)))
also this one but this is not working( I have no idea what I'm doing)
if(Character.isDigit(loop1.charAt(0)) &&
(((int)loop1.charAt(0)) >= 0) && <=9
Character.isDigit(loop1.charAt(1)) &&
((int)loop1.charAt(1)) <= 9)
Please help me... thanks a million !
Assuming I understand your question, parse loop1 and test the values using a simple if check, like
int t = Integer.parseInt(loop1);
if (t < 0 || t > 90) {
System.out.println("Value outside accepted range.");
} else {
System.out.println("Value valid.");
}
If I am getting this right you want to convert the first two characters of a string into a number and check is that number bigger than 90. Also you want the digits to be stored in different variables(?). If so this code should do it:
int digit1 = loop1.charAt(0) - '0';
int digit2 = loop1.charAt(1) - '0';
int number = digit1 * 10 + digit2;
if ( number <= 90 && number >= 0 )
System.out.println("Input is good");
else
System.out.println("Input is bad");

Formatting with Array[i] Logic

I'm trying to build a program that prints 75 random caps and lowercase letters, 25 per line. I think I have all the logic worked out, but whenever I run it the formatting is all off and rather than printing 25 characters per line, it prints a random number. Here's my code so far:
char allLetters[] = new char[3700];
for(int i = 1; i <= 75; i++) { //Begin for loop
int max = 122;
int min = 65;
allLetters[i] = (char)(Math.random() * (max - min) + min);
if(i % 25 != 0){
if (allLetters[i] <= 90) {
System.out.printf("%s,",allLetters[i]);
}
if (allLetters[i] >= 97) {
System.out.printf("%s,",allLetters[i]);
}
} //Close if
else {
if (allLetters[i] <= 90) {
System.out.printf("%s\n",allLetters[i]);
}
if (allLetters[i] >= 97) {
System.out.printf("%s\n",allLetters[i]);
}
}
} //End for
Currently, the output is something like:
U,i,y,e,v,T,G,p,P,a,U,G,e,B,w,U,o,F,G,w,j,m,R
O,X,w,w,u,p,t,g,X,J,R,c,w,I,d,H,R,m,y,b,o
C,p,M,F,X,U,v,O,a,Y,F,E,x,s,x,k,C,b,D,R,r,H
I've tried using different variables besides i, playing around with numbers and such but I can't seem to find the exact flaw in the logic that throws the formatting off. Any help would be greatly appreciated!
The problem with your logic is that you are counting each chosen character even when you do not print it. The ASCII characters falling between 90 and 97, exclusive, are not characters, and you rightfully skip printing them. Yet the loop is still counting those iterations as if a valid letter has been printed. This is resulting in an incorrect count in the output.
The workaround used in the code snippet below is to keep picking characters in a loop until we actually get a lowercase or uppercase letter. Only then do we continue with your previous logic.
char allLetters[] = new char[3700];
int max = 122;
int min = 65;
for (int i = 1; i <= 75; i++) {
char next;
do {
next = (char)(Math.random() * (max - min) + min);
} while (next > 90 && next < 97);
allLetters[i] = next;
if (i % 25 != 0) {
System.out.printf("%s,", next);
}
else {
System.out.printf("%s\n", next);
}
}
Demo
Your two conditions that you put on your random characters, namely allLetters[i] <= 90 and allLetters[i] >= 97, do not cover the entire interval of possible characters, which in your program is 65 to 122, inclusive. When a character between 91 and 96 gets generated, your program does not print anything. The probability of getting one of these six random characters is roughly 10%, so you get 21..23 characters printed.
If you really want to skip these six characters, fix the problem by using a while loop instead of a for loop, and increment the counter of printed characters only when you print something:
int printed = 0;
while (printed != 75) {
char ch = (char)(Math.random() * (max - min) + min);
if (ch >= 91 && ch <= 96) continue;
printed++;
System.out.print(ch);
if (printed % 25 == 0 {
System.out.println();
} else {
System.out.print(',');
}
}
I was looking at your problem, and there's a "clever" solution using Java 8+ IntStream and lambdas. Generate 75 random int(s) between 0 and 26, map each value to a one-character String offset from either 'a' or 'A' by using nextBoolean() from Random. Collect that to a single seventy-five character String. Then print the three twenty-five character substring(s) we're interested in. Like,
Random rand = new Random();
String s = IntStream.generate(() -> rand.nextInt(26)).limit(75)
.mapToObj(i -> Character.toString(
rand.nextBoolean() ? (char) (i + 'a') : (char) (i + 'A')))
.collect(Collectors.joining());
System.out.println(s.substring(0, 25));
System.out.println(s.substring(25, 50));
System.out.println(s.substring(50));

rangeOrOdd - Return 1 if an input number is in a range and/or odd

I am trying to solve this : Given an integer, return 1 if the number is between -5 and 5 exclusive and/or if it is an odd integer. If neither properties apply, return 0.
Here is what I have tried:
int rangeOrOdd(int val) {
if (val < 5)
return 1;
else if (val > 5)
return 1;
else if ((val%2)!=0)
return 0;
else
return 0;
}
The problem is that you are checking the different conditions individually. For instance, as soon as your number is smaller than 5, you return 1, which is wrong, because you would then return 1 for numbers like -1000.
Also, you are returning 0 for an odd number. You were supposed to return 1 in that case.
You have to combine your conditions using ANDs (&&) and ORs (||).
Here is a one liner that combines the different conditions correctly:
return ((val < 5 && val > -5) || val % 2 == 1) ? 1 : 0;
And if you don't like it in one line, you can always split it like this (but it's the same thing):
if ((val < 5 && val > -5) || val % 2 == 1) {
return 1;
} else {
return 0;
}

Categories

Resources