Convert Bigdecimal to Timeformat for a string - java

Basically, I'm using app42 to store scores for a game. However my game uses times.
For example. If I submit a score of 0:3:85 ( 0 hours, 3 seconds and 85 milliseconds)
it would be stored as a bigdecimal as 385.
When i retrieve my score I retrieve it as 385, I have no idea how I can convert it back to my time format.
Example:
At the minute i'm using a function to count how many digits the number is.
int getNumberOfDecimalPlaces(BigDecimal bigDecimal) {
String string = bigDecimal.toPlainString();
int index = string.length();
return index;
}
then to actually work it out, i'm at a loss.
Im thinking something along the lines of
private String ConvertScore(BigDecimal Score){
int Len = getNumberOfDecimalPlaces(Score);
String Convert = Score.toString();
String Finished;
if( Len == 1){
}
else if(Len == 2){
}
else if(Len == 3)
{
Finished
}
return Finished;
}
but honestly I can't even think how i'd do it.
Thanks

Correct me if I'm wrong but your API that you're using returns you the score of the game (not the, not the time. And you won't have an ability to convert it correctly. Because there could be different score.
For example, how to convert 10345?
10 hours 3 seconds and 45 milliseconds
OR
is it 103 hours 0 seconds and 45 milliseconds and so on.

Related

Electronics Shop

I have been working on this question, and after submitting my code 7 cases passed, however, 9 cases failed. The question link is here of HackerRank : Electronic Shop
Problem Statement
A girl wants to buy a keyboard, and a USB drive, she want to spend as much as possible but within budget (combining both the items). And if the price of both the items exceeds her budget, return -1 or she can't buy. What is mandatory is that She wants to buy both the items, not a single one.
Example
A range of keyboards is given in the form of an array [40, 50, 60], and USB drives is given as [5,8,12]. Her max budget is 60. Now if we sum up both the things we get two max value of combination :
40 + 12 = 52
50 + 8 = 58
Since 58 one is greater, hence she will get the items worth of 50 and 8.
Input format
The first line contains three space-separated integers b, n, and m, her budget, the number of keyboard models and the number of USB drive models.
The second line contains space-separated integers , the prices of each keyboard model.
The third line contains space-separated integers , the prices of the USB drives.
Output Format
Print a single integer denoting the amount of money Monica will spend. If she doesn't have enough money to buy one keyboard and one USB drive, print -1 instead.
My Algo
1. Take answer variable as 0, and max value initialize it with first element of keyboard + first element of usb drives
2. loop through keyboard, make an inner loop for usb
3. Compare keyboard[i] + drives[j], if greater than b, then return -1.
4. Else find the max value and assign it to answer
5. return answer
My logic is as simple as the requirements, but somehow fails for the cases which has a very large number of elements in the array.
Code
static int getMoneySpent(int[] keyboards, int[] drives, int b) {
int answer = 0, maxAmount = keyboards[0] + drives[0];
//This will compare the value of i+j throughout the loop and returns the max one
for(int i: keyboards){
for(int j: drives){
// Ofcourse if all i+j values will be greater than the max budget then -1
if((i+j) > b)
answer = -1;
else if((i+j) == b){
answer = i+j;
}else{
/*If the value is smaller than the max budget, the finding the max value we get after adding them and comparing with the maxAmount variable */
if((i+j) > maxAmount){
maxAmount = i+j;
answer = maxAmount;
}
}
}
}
return answer;
}
I'm having two cases which failed,, here they are :
Failed Test Case 1
Input =>
539855 818 628
380710 674456 878173 532602 868253 721585 806107 141310 790209 212031
304748 818920 80938 322601 403071 22899 173564 153826 695108 223665
346178 957539 975830 573171 641117 932941 822666 575293 132555 479463
862209 313799 922966 606508 487172 139230 606390 898464 764983 829520
174879 317603 502680 953013 398753 825387 146407 666457 367618 121790
68188 478342 25818 506222 135197 232604 963333 79984 549654 776899
966040 122063 432596 594425 311887 936661 506256 876303 439611 277816
105689 851641 640971 333 216087 17692 619728 602689 650348 364881
152060 386548 61364 564569 780938 191826 459905 211804 58177 484711
995091 754424 57794 619638 695192 297423 983901 430435 239234 170704
142282 74647 121413 782873 303344 265448 101069 177807 692318 691774
62306 618191 509537 633333 996922 228947 814154 232698 615359 220853
306323 173792 624037 655872 527161 848207 426180 724481 130740 792273
886804 404890 449886 654224 194667 354317 367843 525624 414224 481744
827725 176927 733780 387166 769479 964040 1{-truncated-}
Expected Output
539854
For full input data here is the link : Input Array Data Full
Failed Test Case 2
Input =>
374625 797 951
183477 732159 779867 598794 596985 156054 445934 156030 99998 58097
459353 866372 333784 601251 142899 708233 651036 20590 56425 970129
722162 832631 938765 212387 779 181866 992436 183446 617621 304311
611791 524875 7068 432043 23068 291295 524893 611991 399952 139526
46677 292211 973975 366445 232824 456173 90627 785353 618526 199719
382549 514351 983453 592549 466869 46461 860135 607682 680461 170563
450601 65067 13268 949100 942415 965850 563416 808580 385504 304683
15970 97695 230946 684388 241080 440252 683418 122066 610135 495289
833383 34397 173404 909526 391149 258839 182278 662672 755532 311782
425252 520186 207989 546834 567829 184897 31321 969804 842475 775308
449856 939711 395240 895029 926868 598035 727436 922082 326615 88513
570573 196028 520952 45238 961389 325404 844725 388765 747489 271411
539814 828925 586884 356834 965473 280998 607171 542819 276062 140956
296341 802378 165305 74568 15640 987110 423497 772419 394971 198761
293555 5524 14083 815646 198888 707017 711503 729172{-truncated-}
Expected Output
374625
For full input array data for this one follow this link : Failed Test Case 2 Full Input
I'm there almost but somehow I'm confused why my code is not working for long input array elements. Any help would be appreciated, as it will make me learn new thing in my future endeavor.
You misunderstood the question. Answer should be -1 if you can't buy any keyborad+usb. Not if there is one set unaffordable, but if they all are. With your current code, what would it return if the very last set is unaffordable?
Here is a code that should work. And comments to explain:
int answer = -1; // that's the default answer.
int maxAmount = 0; // what if first keyboard + first usb are unaffordable? let's put it to 0
//This will compare the value of i+j throughout the loop and returns the max one
for(int i: keyboards){
for(int j: drives){
if((i+j) > b) {
// do nothing, it's unaffordable (and remove this block)
}else if((i+j) == b){
answer = i+j;
return answer;// it can't be more, stop the loop and return the solution
} else if((i+j) > maxAmount){ // no need to put an else, then an if both conditions are related
maxAmount = i+j;
answer = maxAmount;
}
}
}
Of course, if you remove the first empty ifblock from the above code, you will have to change the last condition in order to check if it's below the max allowed:
if((i+j)>maxAmount && (i+j)<=b)
int getMoneySpent(int keyboards_count, int* keyboards, int drives_count, int* drives, int b) {
int price=-1;
for(int i=0;i<drives_count;i++)
{
for(int j=0;j<keyboards_count;j++)
{
if((drives[i]+keyboards[j]>price) && (drives[i]+keyboards[j]<=b))
{
price=drives[i]+keyboards[j];
}
}
}
return price;
}
Javascript Solution:
function getMoneySpent(keyboards, drives, b) {
const combos = [];
let maxCost = 0
keyboards.forEach(keyboard => {
drives.forEach(drive => {
let currentComboCost = keyboard+drive;
maxCost = ((currentComboCost <= b) && (currentComboCost > maxCost)) ? currentComboCost : maxCost;
})
})
return maxCost || -1;
}

Using a clock while loop to read files in a while loop

Currently taking my Data Structures class and we're to employ a queue in our next program.
We are given an input file such as this one:
10 324 Boots 32.33
11 365 Gloves 33.33
12 384 Sweater 36.33
13 414 Blouse 35.33
I am to read the first int (which is a unit of time) and use that as a reference for my clock that keeps running in the background.
I did something along these lines:
Scanner infp = new Scanner(new File(FILE));
while (busy) {
clock = 0;
clock += clockCount++;
while (infp.hasNext()) {
timeEntered = infp.nextInt();
infp.nextLine();
System.out.println(timeEntered);
busy = true;
if (timeEntered == clock) {
itemNum = infp.nextInt();
type = infp.nextLine();
itemPrice = infp.nextDouble();
}
}
}
The problem is, when I run it I get an 'InputMismatchException' error. I'm cognizant of the fact that you need to skip the carriage before a String, which is what I believe I am doing.
I have no clue where to go from here.
So given these columns:
10 324 Boots 32.33
11 365 Gloves 33.33
12 384 Sweater 36.33
13 414 Blouse 35.33
For each line, you read the first column into timeEntered.
And then you do infp.nextLine() and that's a mistake.
When you call nextLine, the scanner reads everything unread on the current line until the end.
That means you cannot read the other column values.
But you need them. So don't call nextLine when you still want to process values on a line. Call it after.
And you have the exact same kind of problem again later when your read type and itemPrice.
Replace the while (infp.hasNext()) with this:
while (infp.hasNextLine()) {
int timeEntered = infp.nextInt();
System.out.println(timeEntered);
busy = true;
if (timeEntered == clock) {
itemNum = infp.nextInt();
type = infp.next();
itemPrice = infp.nextDouble();
}
infp.nextLine();
}

Using objects in java (entities)

I'm new to java and I've developed a program that allows the user to enter his in- and outcome, and also to see a summary of both (second code sample).
I use text files to store the data (first sample). I'm using two text files per user, one for the income and one for the outcome.
Bonus //category
21 //amount
28/12/2015 //date
Salary
13
03/01/2016
Savings Deposit
33
03/01/2016
The following code sample sums up the in- and outcome of the user (Note: opnEsoda is a scanner):
try {
while (opnEsoda.hasNextLine());
do //I read only the lines with the amounts from textfile
{
String[] entry = new String[3];
int x =0;
for (int i = 0; i < 3; i++)
{
if (opnEksoda.hasNextLine())
{
// Trim removes leading or trailing whitespace.
entry[i] = opnEksoda.nextLine().trim();
}
}
x = Integer.parseInt(entry[1]); // converts string numbers to int
sumeksoda += x ; // addition ... Amounts of the txt file
}
while (opnEksoda.hasNextLine());
// information dialog that show the money spent and got.
JOptionPane.showMessageDialog(null,
"You got: "+sumesoda+" €",
"Your stats",
JOptionPane.INFORMATION_MESSAGE,icon);
} catch (FileNotFoundException e) {
System.out.println("COULD NOT READ FILE!!!");
}
This will print: You got 67 €
My goal is to give out the money spent this week and this month. I also want to know the amount of money spent on each category (optional). What is the best way to do that?
To calculate the income for the current month, you must analyze entry[2] (the date) inside the loop, and sum up only those values whose month is the same.
At the beginning of your program, store the current date:
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(new Date()); // store the current date
int curYear = cal.get(cal.YEAR );
int curMonth = cal.get(cal.MONTH);
Then, when reading the file, parse the date and compare the year and month:
cal.setTime(new SimpleDateFormat("dd/MM/yyyy").parse(entry[2])); // parse the date
if( cal.get(cal.YEAR)==curYear && cal.get(cal.MONTH)==curMonth ){
x = Integer.parseInt(entry[1]); // converts string numbers to int
sumeksoda += x ; // addition ... Amounts of the txt file
}
To calculate the income from each category, you must analyze entry[0] (the category). If the categories are known in advance, then simply create several distinct sum variables:
int sumeksodaSalary=0;
int sumeksodaBonus=0;
And then, inside the loop:
if("Salary".equals(entry[0])) sumeksodaSalary += x ;
if("Bonus" .equals(entry[0])) sumeksodaBonus += x ;

Java Optimizing arithmetic and Assignment Operators for large input

I have a piece of code that must run extremely fast in terms of clock speed. The algorithm is already in O(N). It takes 2seconds, it needs to take 1s. For most A.length inputs ~ 100,000 it takes .3s unless a particular line of code is invoked an extreme number of times. (For an esoteric programming challenge)
It uses a calculation of the arithmetic series that 1,2,..N -> 1,3,4,10,15..
that can be represented by n*(n+1)/2
I loop through this equation hundreds of thousands of times.
I do not have access to the input, nor can I display it. The only information I am able to get returned is the time it took to run.
particularly the equation is:
s+=(n+c)-((n*(n+1))/2);
s and c can have values range from 0 to 1Billion
n can range 0 to 100,000
What is the most efficient way to write this statement in terms of clock speed?
I have heard division takes more time then multiplication, but beyond that I could not determine whether writing this in one line or multiple assignment lines was more efficient.
Dividing and multiplying versus multiplying and then dividing?
Also would creating custom integers types significantly help?
Edit as per request, full code with small input case (sorry if it's ugly, I've just kept stripping it down):
public static void main(String[] args) {
int A[]={3,4,8,5,1,4,6,8,7,2,2,4};//output 44
int K=6;
//long start = System.currentTimeMillis();;
//for(int i=0;i<100000;i++){
System.out.println(mezmeriz4r(A,K));
//}
//long end = System.currentTimeMillis();;
// System.out.println((end - start) + " ms");
}
public static int mezmeriz4r(int[]A,int K){
int s=0;
int ml=s;
int mxl=s;
int sz=1;
int t=s;
int c=sz;
int lol=50000;
int end=A.length;
for(int i=sz;i<end;i++){
if(A[i]>A[mxl]){
mxl=i;
}else if(A[i]<A[ml]){
ml=i;
}
if(Math.abs(A[ml]-A[mxl])<=K){
sz++;
if(sz>=lol)return 1000000000;
if(sz>1){
c+=sz;
}
}else{
if(A[ml]!=A[i]){
t=i-ml;
s+=(t+c)-((t*(t+1))/(short)2);
i=ml;
ml++;
mxl=ml;
}else{
t=i-mxl;
s+=(t+c)-((t*(t+1))/(short)2);
i=mxl;
mxl++;
ml=mxl;
}
c=1;
sz=0;
}
}
if(s>1000000000)return 1000000000;
return s+c;
}
Returned from Challenge:
Detected time complexity:
O(N)
test time result
example
example test 0.290 s. OK
single
single element 0.290 s. OK
double
two elements 0.290 s. OK
small_functional
small functional tests 0.280 s. OK
small_random
small random sequences length = ~100 0.300 s. OK
small_random2
small random sequences length = ~100 0.300 s. OK
medium_random
chaotic medium sequences length = ~3,000 0.290 s. OK
large_range
large range test, length = ~100,000 2.200 s. TIMEOUT ERROR
running time: >2.20 sec., time limit: 1.02 sec.
large_random
random large sequences length = ~100,000 0.310 s. OK
large_answer
test with large answer 0.320 s. OK
large_extreme
all maximal value = ~100,000 0.340 s. OK
With a little algebra, you can simply the expression (n+c)-((n*(n+1))/2) to c-((n*(n-1))/2) to remove an addition operation. Then you can replace the division by 2 with a bit-shift to the right by 1, which is faster than division. Try replacing
s+=(n+c)-((n*(n+1))/2);
with
s+=c-((n*(n-1))>>1);
I dont have access to validate all inputs. and time range. but this one runs O(N) for sure. and have improved. run and let me know your feedback.i will provide details if necessary
public static int solution(int[]A,int K){
int minIndex=0;
int maxIndex=0;
int end=A.length;
int slize = end;
int startIndex = 0;
int diff = 0;
int minMaxIndexDiff = 0;
for(int currIndex=1;currIndex<end;currIndex++){
if(A[currIndex]>A[maxIndex]){
maxIndex=currIndex;
}else if(A[currIndex]<A[minIndex]){
minIndex=currIndex;
}
if( (A[maxIndex]-A[minIndex]) >K){
minMaxIndexDiff= currIndex- startIndex;
if (minMaxIndexDiff > 1){
slize+= ((minMaxIndexDiff*(minMaxIndexDiff-1)) >> 1);
if (diff > 0 ) {
slize = slize + (diff * minMaxIndexDiff);
}
}
if (minIndex == currIndex){
diff = currIndex - (maxIndex + 1);
}else{
diff = currIndex - (minIndex + 1);
}
if (slize > 1000000000) {
return 1000000000;
}
minIndex = currIndex;
maxIndex = currIndex;
startIndex = currIndex;
}
}
if ( (startIndex +1) == end){
return slize;
}
if (slize > 1000000000) {
return 1000000000;
}
minMaxIndexDiff= end- startIndex;
if (minMaxIndexDiff > 1){
slize+= ((minMaxIndexDiff*(minMaxIndexDiff-1)) >> 1);
if (diff > 0 ) {
slize = slize + (diff * minMaxIndexDiff);
}
}
return slize;
}
Get rid of the System.out.println() in the for loop :) you will be amazed how much faster your calculation will be
Nested assignments, i. e. instead of
t=i-ml;
s+=(t+c)-((t*(t+1))/(short)2);
i=ml;
ml++;
mxl=ml;
something like
s+=((t=i-ml)+c);
s-=((t*(t+1))/(short)2);
i=ml;
mxl=++ml;
sometimes occurs in OpenJDK sources. It mainly results in replacing *load bytecode instructions with *dups. According to my experiments, it really gives a very little speedup, but it is ultra hadrcore, I don't recommend to write such code manually.
I would try the following and profile the code after each change to check if there is any gain in speed.
replace:
if(Math.abs(A[ml]-A[mxl])<=K)
by
int diff = A[ml]-A[mxl];
if(diff<=K && diff>=-K)
replace
/2
by
>>1
replace
ml++;
mxl=ml;
by
mxl=++ml;
Maybe avoid array access of the same element (internal boundary checks of java may take some time)
So staore at least A[i] in a local varianble.
I would create a C version first and see, how fast it can go with "direct access to the metal". Chances are, you are trying to optimize calculation which is already optimized to the limit.
I would try to elimnate this line if(Math.abs(A[ml]-A[mxl])<=
by a faster self calculated abs version, which is inlined, not a method call!
The cast to (short) does not help,
but try the right shift operator X >>1 instead x / 2
removing the System.out.println() can speed up by factor of 1000.
But be carefull otherwise your whole algorithm can be removed by the VM becasue you dont use it.
Old code:
for(int i=0;i<100000;i++){
System.out.println(mezmeriz4r(A,K));
}
New code:
int dummy = 0;
for(int i=0;i<100000;i++){
dummy = mezmeriz4r(A,K);
}
//Use dummy otherwise optimisation can remove mezmeriz4r
System.out.print("finished: " + dummy);

Array and Java string error: [Ljava.lang.String;#19c42c4b

I've created a program that allows a user to enter in Journal entries (up to 7 days) and then allows a person to call up one of those days after they enter in an entry. Unfortunately, this has left me with some weird string error that I'm not familiar with.
Code as follows:
public class eDiary{
public static void main (String args[]){
int[] days = new int[7];//get our days
days[0] = 1;//start with 1 and not 0
days[1] = 2;
days[2] = 3;
days[3] = 4;
days[4] = 5;
days[5] = 6;
days[6] = 7;
String [] events = new String[7];//events for the days
int i = 0;
//asks for input and counts
for(i=0; i<7; i++){
String event = Console.readString("Tell me the major event of day " + days[i] + "\n");
events[i] = event;
}
int journal_entry = Console.readInt("Enter what day you want to hear or Enter 0 to stop \n");
while (journal_entry != 0) {
System.out.println(events);
journal_entry = Console.readInt("Enter what day you want to hear or Enter 0 to stop \n");
//get r dun!
The input and output:
Tell me the major event of day 1
one
Tell me the major event of day 2
two
Tell me the major event of day 3
thre
Tell me the major event of day 4
four
Tell me the major event of day 5
five
Tell me the major event of day 6
six
Tell me the major event of day 7
seven
Enter what day you want to hear or Enter 0 to stop
1
[Ljava.lang.String;#10181f5b
Enter what day you want to hear or Enter 0 to stop
0
Howdy y'all!
Thanks a lot for the quick responses. One thing it seems to be doing now is when replacing
System.out.println(events);
with
System.out.println(events[journal_entry]);
Now gives me input such as this:
Tell me the major event of day 1
first day
Tell me the major event of day 2
second day
Tell me the major event of day 3
third day
Tell me the major event of day 4
fourth day
Tell me the major event of day 5
fifth day
Tell me the major event of day 6
sixth day
Tell me the major event of day 7
seventh day
Enter what day you want to hear or Enter 0 to stop
1//the day im asking for
second day//spitting out the next day's entry instead of the first day's entry
Enter what day you want to hear or Enter 0 to stop
0//this is me stopping it
It's not an error.
System.out.println(events);
In this line you are trying to print the array, but that statement doesn't print the array contents, it only prints the object class name followed by its hashcode.
To print the array content you have to use
System.out.println(Arrays.toString(events));
Or, if you want, loop through the array and print its values
The [Ljava.lang.String;#10181f5b stuff is what you get when you explicitly or implicitly call Object.toString() and the target object's class doesn't override toString(). In this case, the issue is that Java array types do not override toString().
If you want to output an array, use java.util.Arrays.toString(...) to convert it to a String, then output that.
But in this case, you actually need to output a specific entry, not the entire array. The fix is to change
System.out.println(events);
to
System.out.println(events[journal_entry]);
For the record, the stuff above consists of the classes internal name ("[Ljava.lang.String;") and the object's identity hashcode (in hexadecimal).
This is not a "weird error string".
The output you are getting is because:
In Java, each object has toString() method, the default is displaying the class name representation, then adding # and then the hashcode.
You should use Arrays#toString(), which is implemented this way:
3860 public static String toString(int[] a) { {
3861 if (a == null)
3862 return "null";
3863 int iMax = a.length - 1;
3864 if (iMax == -1)
3865 return "[]";
3866
3867 StringBuilder b = new StringBuilder();
3868 b.append('[');
3869 for (int i = 0; ; i++) {
3870 b.append(a[i]);
3871 if (i == iMax)
3872 return b.append(']').toString();
3873 b.append(", ");
3874 }
3875 }
This will help you to better understand arrays.
Of course you can manually loop on the array and print it:
for(String event: events) {
System.out.println(event);
}
There is nothing wrong and that's not an error message.
Instead, it's the string representation of an array. Consider this line:
System.out.println(events);
You are printing the whole array, so you get that representation -- which happens to be a bit ugly, indeed. You want to print only one element, the one corresponding to the selected day. Use:
System.out.println(events[journal_entry]);
And perform bound checks.
This is not an error. You want to print the value of variable events. [Ljava.lang.String;#10181f5b means that events is an array of type java.lang.String and 10181f5b is hashcode of this variable. What you want to println is event[i] where i is the number of a day.
In java array's are consider as object. you are printing the event array object that's not what you want.
You need to print name of the day in a week. You need to replace
System.out.println(events);
to
System.out.println(events[journal_entry]);
It won't print out the answer correctly because you just pointed System.out.println() to events which is supposed to be an array pointer and not the actual variable. You should just replace this line with
System.out.println(events[journal_entry]);
For it to make sense. Run it with the conmmand and see if it will run properly.
Thanks for all the responses! I was able to resolve the issue. Here's the code if anyone is curious:
public static void main (String args[]){
int[] days = new int[7];//get our days
days[0] = 1;//start with 1 and not 0
days[1] = 2;
days[2] = 3;
days[3] = 4;
days[4] = 5;
days[5] = 6;
days[6] = 7;
String [] events = new String[7];//events for the days
int i = 0;
//asks for input and counts
for(i=0; i<7; i++){
String event = Console.readString("Tell me the major event of day " + days[i] + "\n");
events[i] = event;
int journal_entry = Console.readInt("Enter what day you want to hear or Enter 0 to stop \n");
while (journal_entry != 0) {
System.out.println("On day " + days[i = 0] + " " + events[journal_entry - 1]);
journal_entry = Console.readInt("Enter what day you want to hear or Enter 0 to stop \n");

Categories