Basically, I have a variable 'prime'. It can only take values between 0 and 6. Based on its value, I want a string 'result' to be Sunday if prime is 0, Monday if 1, etc. Currently, it's coded this way:
String result = new String();
if (prime == 0)
{
result = "Sunday";
}
if (prime == 1)
{
result = "Monday";
}
if (prime == 2)
{
result = "Tuesday";
}
if (prime == 3)
{
result = "Wednesday";
}
if (prime == 4)
{
result = "Thursday";
}
if (prime == 5)
{
result = "Friday";
}
if (prime == 6)
{
result = "Saturday";
}
else
{
result = "Check your code.";
}
I'm wondering if there's a faster way to do this? I've created an array with the days of the week:
String[] days = new String[7];
days [0] = "Sunday";
days [1] = "Monday";
days [2] = "Tuesday";
days [3] = "Wednesday";
days [4] = "Thursday";
days [5] = "Friday";
days [6] = "Saturday";
How do I quickly and elegantly code it so that if the value of prime is 0, the string 'result' is the first element of the array, and so on until if prime is 6, the string 'result' is the seventh element?
You already have all the valid values stored in a simple lookup table, you just need to ensure that the requested value is within the range of available values.
The basic answer would be to do something like...
if (prime >= 0 && prime < days.length) {
result = days[prime];
} else {
result = prime + " is not within a valid range";
// Or throw an exception
}
What this does is makes sure that the prime value is within the valid range of acceptable values (0..days.length - 1), other wise it returns an error message (or you could throw an exception).
Remember, arrays are 0 indexed, hence the need to use < days.length (less then) and not <= days.length (less then or equals to)
You were close. For those saying Switch or if chains, it's overkill for this problem.
result = days[Math.abs(prime % days.length)];
The array acts like a switch statement, and the modulus operator wrapped in the Math.abs (absolute value) acts like a safety net to stay with in the valid range of the array 0-6.
Credits to #MadProgrammer for the Math.abs
From Tutorials Point
Modulus - Divides left hand operand by right hand operand and returns remainder
Why don't you use the DayOfWeek class?
import java.time.DayOfWeek;
and try this...
try {
DayOfWeek dayOfWeek = DayOfWeek.of(++prime);
System.out.println(dayOfWeek.getDisplayName(TextStyle.FULL, Locale.getDefault()));
} catch (java.time.DateTimeException ex) {
System.out.println("Invalid value for DayOfWeek");
}
Note that we have to do ++prime since your code starts in zero and the enum in one.
If you have to set Sunday as the first day (instead of Monday that is the first in the enum)... the minus method will do the trick:
DayOfWeek dayOfWeek = DayOfWeek.of(++prime).minus(1);
EDIT: advantages and disadvantages of the solution
Pros:
Don't require an object to maintain your days.
Don't use a conditional statement.
The text style and language can easily be changed.
Cons:
java 1.8 is required
You could simply do:
if (prime >= 0 && prime < days.length) result = days[prime];
else result = "Check your code."
Because prime is essentially the index of the day that you want.
You can use Enum and define yourself
public enum Week {
SUNDAY(1, "Sunday"), Monday(2, "Monday"), TUESDAY(3, "Tuesday"), WEDNESDAY(
4, "Wednesday"), THURSDAY(6, "Thursday"), FRIDAY(6, "Friday"), SATURDAY(
7, "Saturday");
private int id;
private String name;
static Map<Integer, String> map = new HashMap<Integer, String>();
static {
for (Week w : Week.values()) {
map.put(w.getId(), w.name);
}
}
private Week(int id, String name) {
this.setId(id);
this.setName(name);
}
public static String getNameById(int id) {
return map.get(id);
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
Related
I'm having a problem making an efficient algorithm that validates my date and odometer input within a given sorted data set. I'm trying to implement a gas mileage tracking program. The sorted data has a date with corresponding odometer value.
Sample Data Set:
Date Odometer Index
2021-2-14 156830 0
2021-2-5 156572 1
2021-2-4 156255 2
Index 0 being the top and recent data entry.
Sample Input:
Date: 2021-2-15
Odometer: 157000
I have to determine which position/order the inputted date belongs inside my data set. Since the user date input is greater than my top/recent date I know this belongs to the very top. Then I compare the odometer from that data to my input. If user odometer input is greater than data odometer then it is valid. If its less than then its invalid.
Another Sample Input:
Date: 2021-2-14
Odometer: 156255
Its okay if the user date input has the same date given in the data set. However, odometer cannot be less than the previously recorded at 156572 on 2021-2-5. So its invalid.
Here is my test input validation algorithm so far:
public static Date[] dates = new Date[3];
public static int[] odometer = new int[3];
public static void main(String[] args)
{
dates[0] = new Date(2021,2,14);
dates[1] = new Date(2021,2,5);
dates[2] = new Date(2021,2,4);
odometer[0] = 156830;
odometer[1] = 156572;
odometer[2] = 156255;
//Inputs
Date inputDate = new Date(2021,2,14);
int inputOdo = 156255;
if(!hasDuplicate(inputDate, inputOdo))//Checks for duplicate
{
int index = -1;
for(int i=0; i<dates.length; i++)
{
if(inputDate.compareTo(dates[i]) >= 0)
{
index = i;
break;
}
}
if(index == 0)
{
if(inputOdo <= odometer[index] && inputDate.compareTo(dates[index]) > 0)
{
System.out.println("Mileage cannot be less than "
+ "your previously recorded fill-up at\n"+odometer[index]+" miles on "+dates[index].toString()+".\n");
}
}else{
if(index > 0)
{
int top = index-1;
int bottom = index;
if(inputOdo >= odometer[top])
{
System.out.println("Mileage cannot be higher than "
+ "your previously recorded fill-up at\n"+odometer[top]+" miles on "+dates[top].toString()+".\n");
}else{
if(inputOdo <= odometer[bottom] && bottom != dates.length-1 && !inputDate.equals(dates[bottom]))
{
System.out.println("Mileage cannot be less than "
+ "your previously recorded fill-up at\n"+odometer[bottom]+" miles on "+dates[bottom].toString()+".\n");
}
}
}else{
int bottom = dates.length-1;
if(inputOdo >= odometer[bottom])
{
System.out.println("Mileage cannot be higher than "
+ "your previously recorded fill-up at\n"+odometer[bottom]+" miles on "+dates[bottom].toString()+".\n");
}
}
}
System.out.println("Gas has been added!");
}else{
System.out.println("Another fill-up with this date and mileage already exist.");
}
hasDuplicate method:
//Checks for duplicate
public static boolean hasDuplicate(Date date, int odo)
{
boolean duplicate = false; //Initialize duplicate variable
//Checks if date and mileage exist already
for(int i=0; i<dates.length; i++)
{
if(date.equals(dates[i]) && odo == odometer[i]) {
return true;
}
}
return duplicate;
}
I hope someone can understand what I am trying to achieve here. Any help and idea will be great! I'm a newbie.
Some changes which you may do-
Instead of having different array of data and odometer, use an object which implements Comparable interface
class MileageData implements Comparable<MileageData> {
LocalDate date;
int odometer;
public MileageData(LocalDate date, int odometer) {
this.date = date;
this.odometer = odometer;
}
#Override
public boolean equals(final Object obj) {
MileageData anotherData = (MileageData)obj;
return anotherData.date.equals(this.date) && anotherData.odometer == this.odometer;
}
#Override
public int hashCode(){
int hash = 7;
hash = 31 * hash + this.date.hashCode();
hash = 31 * hash + this.odometer;
return hash;
}
#Override
public int compareTo(final MileageData o) {
if (o.date.isBefore(this.date)) {
return -1;
} else if (o.date.isAfter(this.date)) {
return 1;
} else {
return 0;
}
}
#Override
public String toString(){
return this.date.toString()+" "+this.odometer;
}
}
Storing MileageData in Treeset which will sort data in the order given in compareTo method of MileageData.
Set<MileageData> data = new TreeSet<>();
data.add(new MileageData(LocalDate.of(2021,2,14),156830));
data.add(new MileageData(LocalDate.of(2021,2,4),156255));
data.add(new MileageData(LocalDate.of(2021,2,4),156255));
data.add(new MileageData(LocalDate.of(2021,2,5),156572));
As Treeset will not store duplicate data, you don't need separate check for duplicates. Above set will return only three objects instead of four.
I have a business case where I need to get the decimal values as a new integer and
then traverse it from left to right to evaluate.
Eg: I have a integer value int val=1345679;
square root of val is double sqrt_val=1160.03405122; //sqrt(1345679), decimal values are limit to 8 digits
Now I need decimal value(03405122) to store it into integer variable
int decimalValue=03405122;
With this decimal value I want to verify with some number which is given by business.
Let's take some number as 45.
now I have to verify decimalValue until it meets the below condition
03405122<=45 if yes just take the decimal value
if no then remove the 1st digit from left side until condition satisfiet
3405122<=45
405122<=45
05122<=45
5122<=45
122<=45
22<=45.
So, 22 is the number I have to take for further implementation.
This is the code which I have written, and give me some suggestions that If I can write in a better way.
// Extracting Decimal value
public int extractDecimal(int computeRandomNumber)
{
int _computeRandom = computeRandomNumber;
double sqrt = Math.sqrt(_computeRandom);
BigDecimal df;
df = round(sqrt, 8);
// System.out.println(df);
String sqrt_round = String.valueOf(df);
// System.out.println(sqrt_round);
int index = sqrt_round.lastIndexOf('.') + 1;
String sqrt_round_deci = sqrt_round.substring(index);
// System.out.println(sqrt_round_deci);
return Integer.parseInt(sqrt_round_deci);
}
//Comparing with the some number to find the random number
public int findRandomNumber(int value, int totalRange) {
int _val;
System.out.println("calling rec::: val:" + value);
if (value <= totalRange) {
System.out.println("Success... returing on final value:" + value);
return value;
}
String new_str = String.valueOf(value);
String final_str = new_str.substring(1);
// System.out.println("str:"+final_str);
int val = Integer.parseInt(final_str);
// System.out.println("val:"+val);
_val = findRandomNumber(val, totalRange);
return _val;
// System.out.println("Returning flag:"+flag);
}
Thanks in Advance!
As you provided a pseudo-code only question, I will be generous and provide a pseudo-code only answer:
1) Get the String value of sqrt_val
2) Use the substring() method to get only the places1 after the .
3) Loop through the length2 of said substring
4) Check on each iteration if the valueOf your String is less than your target
5a) If so, there's your result
5b) If not, get the substring starting from position 1
1 If this begins with a 0, your results may vary so I'll leave this for you to work out
2 If you use this way, be careful if your loop goes via String.length as you use a substring in the else
I am in no way convinced that this is the best solution but here's an alternative solution which doesn't use Strings.
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
// Value to be less than
BigDecimal lessThan = new BigDecimal(80);
int test = 333444;
BigDecimal bd = new BigDecimal( Math.sqrt(test) );
System.out.println(bd);
while( bd.scale() > 0 ) {
// get the fractional value and make it a whole number
BigDecimal fractionOnly = bd.divideAndRemainder(BigDecimal.ONE)[1];
fractionOnly = fractionOnly.movePointRight(fractionOnly.scale());
// do the check
System.out.println( fractionOnly + " < " + lessThan );
if ( fractionOnly.compareTo( lessThan ) < 0 ) {
System.out.println( "Yes" );
break;
}
// method kinda says it
bd = bd.movePointRight(1);
}
}
}
I want to implement format with dynamic floating point for different length of input data in specified length for display. For example x.xxxx, xx.xxxx, xxx.xx, xxxx.x.
In other words,
if I have 1.4, I need 1.4000.
if 13.4 then I need 13.400, for every case length should be 5 digits (with no dot).
I'm using
DecimalFormat df2 = new DecimalFormat("000000");
but can't build a correct pattern. Is there any solution for this?
Thanks for helping.
The following is not production code. It doesn’t take a leading minus into account, nor very high values of the noDigits constant. But I believe you can use it as a starting point. Thanks to Mzf for inspiration.
final static int noDigits = 5;
public static String myFormat(double d) {
if (d < 0) {
throw new IllegalArgumentException("This does not work with a negative number " + d);
}
String asString = String.format(Locale.US, "%f", d);
int targetLength = noDigits;
int dotIx = asString.indexOf('.');
if (dotIx >= 0 && dotIx < noDigits) {
// include dot in result
targetLength++;
}
if (asString.length() < targetLength) { // too short
return asString + "0000000000000000000000".substring(asString.length(), targetLength);
} else if (asString.length() > targetLength) { // too long
return asString.substring(0, targetLength);
}
// correct length
return asString;
}
I wrote Java code to convert String to long. However, when dealing with overflow problem, I don't have clues how to solve it. If a number is overflowed, computer believe every number is legal in storage. How to let program, with 64bit jdk ,detect the real number is overflowed is the key problem. And I'm not allowed to use any built-in library such as parseLong or others.
public static long strTolong(String s){
//error checking
if(s == null) return 0;
s = s.trim();//remove all space character
boolean neg = false;//judge the number is negative or positive
int pos = 0 ; //index of string
long result = 0;
//check positive or negative
if(s.charAt(pos) == '-'){
neg = true;
pos++;
}else if(s.charAt(pos) == '+') pos++;
//calculate result
while(pos<s.length()){
if(s.charAt(pos) >='0' && s.charAt(pos) <='9'){
result = result*10+(s.charAt(pos) - '0');
}else
break;
pos++;
}
if(neg) result =-result;
//check overflow
if(result >Long.MAX_VALUE) {
return Long.MAX_VALUE;
}
if(result<Long.MIN_VALUE){
return Long.MIN_VALUE;
}
return result;
}
If data is larger than long.maxvalue, the result can't be stored in computer correctly.
How to solve this problem?
Your best option is probably to do a lexicographical comparison between the input and the minimum/maximum numbers before you start.
static int compare(String v1, String v2) {
boolean neg1 = v1.startsWith("-");
boolean neg2 = v2.startsWith("-");
return neg1 ? (neg2 ? -comparePositives(v1.substring(1),v2.substring(1)):-1)
: (neg2 ? 1 : comparePositives(v1, v2));
}
static int comparePositives(String v1, String v2) {
// Is one longer?
if (v1.length() != v2.length())
return v1.length() < v2.length() ? -1 : 1;
// Both empty?
if (v1.isEmpty())
return 0;
// First digit differs?
if (v1.charAt(0) != v2.charAt(0))
return v1.charAt(0) < v2.charAt(0) ? -1 : 1;
// Recurse on rest of number
return comparePositives(v1.substring(1), v2.substring(1));
}
Use it for instance as follows:
if (compare(s, ""+Long.MIN_VALUE) == -1)
throw new NumberFormatException("Input too small");
if (compare(s, ""+Long.MAX_VALUE) == 1)
throw new NumberFormatException("Input too large");
Tested here: http://ideone.com/HmMkJ3
Note that the code does not check that the input is well formed. I suggest you do such check first. (Be aware of cases like 0 and -0 etc.)
You could do the same thing that Long#parseLong would do:
throw new NumberFormatException("too long (pun intended): "+s);
I am not sure what you trying to achieve here. If String is greater than Long.MAX_VALUE means that is no more a Long value.
If your String value is withing the range of Long, you can use Long.parseLong() with out this kind of hard ways.
If you want to have huge number you can use BigDecimal easily
String max = Long.MAX_VALUE+"";
System.out.println(max);
long maxL=Long.parseLong(max)+1;
System.out.println(maxL);
BigDecimal bigDecimal=new BigDecimal(max).add(new BigDecimal("1"));
System.out.println(bigDecimal);
Out put:
9223372036854775807 // long max value
-9223372036854775808 // incorrect result in long
9223372036854775808 // BigDecimal gives you correct one
For your case you can throws an Exception if value is greater than Long.MAX_VALUE or lower than Long.MIN_VALUE
When I try to run this program, the result is always null, 0 0. Why do the values of monthName, day, and year not show up when the getDay() method is invoked and printed on the screen.
public class Assignment1 {
public static void main(String[] args) {
//creates an array of type Date filled with two LongDate objects
Date [] collectionOfDates = { new LongDate("February",2,1996), new LongDate("February",13,1999) };
// loops through the array and displays output of getDate() for each object
for( int i = 0; i < collectionOfDates.length; i++ ) {
System.out.println( collectionOfDates[i].getDate() );
}
}
}
For your information, the LongDate class is a subclass of the Date class which contains methods editDay() and editYear() along with several others. The LongDate method is listed below.
Any help greatly appreciated, Thanks. Also, feel free to comment if you want more information.
public class LongDate extends Date {
private String monthName;
private int day;
private int year;
public LongDate() {
}
public LongDate(String m, int d, int y) {
super.editday(d);
super.edityear(y);
editMonth(m);
}
public void setDate(String m, int d, int y) {
monthName = m;
day = d;
year = y;
}
public String getDate() {
StringBuilder fullDate = new StringBuilder();
fullDate.append(monthName);
fullDate.append(" ");
fullDate.append(day);
fullDate.append(", ");
fullDate.append(year);
return fullDate.toString();
}
public String getShortDate() {
int month = 0;
if (monthName == "January") {
month = 1;
} else if (monthName == "February") {
month = 2;
} else if (monthName == "March") {
month = 3;
} else if (monthName == "April") {
month = 4;
} else if (monthName == "May") {
month = 5;
} else if (monthName == "June") {
month = 6;
} else if (monthName == "July") {
month = 7;
} else if (monthName == "August") {
month = 8;
} else if (monthName == "September") {
month = 9;
} else if (monthName == "October") {
month = 10;
} else if (monthName == "November") {
month = 11;
} else if (monthName == "December") {
month = 12;
}
StringBuilder shortDate = new StringBuilder();
shortDate.append(month);
shortDate.append("/");
shortDate.append(day);
shortDate.append("/");
shortDate.append(year);
return shortDate.toString();
}
protected String editMonth(String m) {
// asks person to try again if month is not capitalized and spelled properly
if (m != "January" && m != "February" && m != "March" && m != "April" && m != "May" && m != "June" && m != "July" && m != "August" && m != "September" && m != "October" && m != "November" && m != "December") {
m = Input.getString( "Invalid month. Please type the month again." );
return m;
} else
return m;
}
}
There's nothing in the constructor of LongDate which sets the fields (monthName, day, and year) that getDate() reads.
I assume that the Date#editDay() and Date#editYear() functions look similar to LongDate#editMonth(). Note that editMonth() does not assign a value to the monthName field!
You should compare your strings with equals() and not ==. The equals() method compares string values, whereas == compares object references, which is not what you want here. So change:
if (monthName == "January") {
to:
if (monthName.equals("January")) {
and similarly for the other comparisons.
Couple of issues. First:
public LongDate(String m, int d, int y) {
super.day(d);
super.year(y);
editMonth(m);
}
You don't show Date so it is unclear to us what day() and year() are supposed to do, but regardless:
public class LongDate extends Date {
private String monthName;
private int day;
private int year;
...
}
Your declarations of these fields are hiding any similar fields that the base presumably has. In any case, at no point in your constructor are you setting this.day or this.year to anything, and so, of course, they remain at their initial value of 0.
You need to clean up your code a bit. Either refer to the correct day and year, or make sure you are setting and getting the base class' version of those fields instead of redeclaring them in the subclass (again, not sure what your base implementation does).
You may want to have a look at the official tutorial on Inheritance. It's concise and well-written and covers topics like overriding methods, hiding fields, etc. I think it will give you a good starting point for solving your issues here.
And, of course, comparing strings with == here will lead to other issues in the future: How do I compare strings in Java?
Your editMonth method returns a string, instead it should set the month:
monthName = m;
Another option is to keep the editMonth method the same, but in your constructor put:
monthName = editName(m);