Looking at this RuneScape experience table: http://runescape.wikia.com/wiki/Experience/Table
You can see that an experience point amount correlates to a "level"
where:
if (xp < 83){
level = 0;
}
else if (xp >= 83 && xp < 174){
level = 1;
}
//etc
So when I save just the experience as a field for my player, how can I calculate the level they will be with their experience?
Without looping through 100 experience point integers.
i.e I don't want to do this: (Because a player will have many levels, meaning this will need to be looped many times)
for (int i =0; i < 100) {
if (playersExperience < experienceRequiredForLevel(i){
return i;
}
perhaps there is a faster way to do this?
Edit:
There is a formula to calculate the experience for level X here:
rsdo.net/rsdonline/guides/Experience%20formula.html
though I don't know how to reverse engineer that to find level instead
You can have a multiplier of X the experience levels. And you just take the integer part of division.
Ex if X=100: LVL1 = 100, LVL2 = 200; etc ...
In this case you just can just:
LVL = Experience / X;
Ex: 100 / 100 = 1 LVL, 200 / 100 = 2 ... etc
X can be any number.
Hope it helps.
You could use binary search to speed up things:
private static final int[] experiences={83, 174, ...};
int level(int experience) {
// boundary check
if (experience < experiences[0])
return 0;
if (experience >= experiences[experiences.length-1])
return experiences.length;
int minLevel = 0;
int maxLevel = experiences.length;
while (maxLevel - minLevel > 1) {
int chk = (maxLevel+minLevel)/2;
if (experience < experiences[chk])
maxLevel = chk;
if (experience >= experiences[chk])
minLevel = chk;
}
return maxLevel;
}
Related
I am trying to make a scoreboard with images in processing, with images from 0 to 9, but any number greater than 9 does not make changes
It should be something like this: 10, 11, 12, ..., 99
but it only changes the number on the left, try using a counter, converting it to a String and then to a Char[] to get the first digit of two numbers; for example: 25, it would have to be 2
when passing that number to the array, it sends "ArrayIndexOutOfBoundsException"
char[] digits;
PImage [] prueba = new PImage[10];
int contadorPrueba2 = 0;
int aa = 0;
void setup () {
size (781, 470);
tablero = loadImage("tablero.png");
flechaRight = loadImage("flechaRight.png");
flechaLeft = loadImage("flechaLeft.png");
for (int i = 0; i < prueba.length; i++) {
prueba[i] = loadImage("numero_" + i + ".jpg");
}
}
void draw () {
//flechas
image(flechaRight, x, y);
image(flechaLeft, x2, y);
image(prueba[0], x3, 50);
//cambiar de numeros
image(prueba[contadorPrueba2], x4, 50);
image(prueba[aa], x3, 50);
}
boolean isMouseOver (int x, int y, int w, int h) {
if (mouseX>x && mouseX <x+w && mouseY>y && mouseY <y+h) {
return true;
}
return false;
}
void mousePressed () {
if (isMouseOver (x, y, w, h) == true) {
contadorPrueba2++;
//image(uno, x3, 50);
} else if (isMouseOver (x2, y, w, h) == true) {
contadorPrueba2--;
}
if (contadorPrueba2 >= prueba.length)
contadorPrueba2 = 0;
count = String.valueOf(contadorPrueba2);
digits = count.toCharArray();
for (int i = 0; i < digits.length; i++) {
if (contadorPrueba2 >= 10) {
//aa = digits[0];
println(digits[i]);
aa = digits[i];
//aa = digits[i];
//print("pp" + aa);
if (i == 0) {
print("ksk" + digits[i]);
}
}
}
}
Chars aren't exactly the best way to keep track of a score, which can make for some headache at times. I strongly suggest that you keep track of the score with an integer number unless you really have no choice on the matter.
Now, to translate an integer into a bunch of index numbers associated with images of said numbers, things can also become complicated, but I got your back! In fact, you can use MATH and solve this quite easily. Are you familiar with the modulo operator? If you're not, read about it because it's a programmer's best friend. Long story short, it's a division that returns only the leftover numbers after the division. As an example, if I write:
10 / 3 == 3.333333 // as a division this makes sense
10 % 3 == 1 // modulo only keeps what's left when the division stops being an integer
because: 10 == [3+3+3] + 1
Ok, you probably already knew this, but if you didn't, now you do. Here's how I use this knowledge to simplify your issue with a commented example:
PImage[] digits = new PImage[10];
int score = 4780; // you can change this number for whatever integer number
void setup () {
size(200, 200);
for (int i = 0; i < digits.length; i++) {
digits[i] = loadImage(i + ".png"); // these 10 images are 10x10 pixels for easier handling
}
}
void draw () {
int i=1;
int j = 160; // arbitrary number: this is where i start drawing the score (the rightest number)
// oooh! This is a good opportunity to use a do...while(); loop! I don't have that many of those.
// This is because we have to show at least ONE digit even if the score is zero, but I coded this so you can have a score higher than 99 without issue
do {
i*=10; // using multiples of 10 with the modulo operator
// as we use base 10 in real life, multiples of 10 help isolate digits of interests
image(digits[(score%i)/(i/10)], j, 90); // j is the x coordinate of the current digit, 90 is an arbitrary y coordinate
// 'digits[(score%i)/(i/10)]' deserves an explanation:
// 'score%i' removes every unit besides the current digit of interests, as an example if we're looking for the hundreds digit of 3456 it'll be 400
// '/(i/10)' removes the unwanted zero (in the 3456 example it would leave only the number 4 instead of 400)
j-=10; // updating j for the next digit
} while(i<score);
}
I know I didn't tell you why you get ArrayIndexOutOfBoundsException and it's kinda on purpose: this is a very common error and although I have no trouble guessing why you get it, it's just more efficient to fix by improving the method than by meddling with the code. There are many articles on SO about why this error happens and I encourage you to read at least one, as it'll be something that you'll see again in the future. Yet, for now, you can just avoid it by switching to this method.
I hope this helps. Have fun!
I have on the first problem of Google Foobar Level 2. The problem is:
Being a henchman isn't all drudgery. Occasionally, when feeling generous, Commander Lambda hand out Lucky LAMBs (Lambda's All-purpose Money Bucks). Henchmen can use Lucky LAMBs to buy things like a second pair of socks, a pillow for their bunks, or even a third daily meal!
However, actually passing out LAMBs isn't easy. Each henchman squad has a strict seniority ranking which must be respected -- or else the henchmen will revolt and you'll all get demoted back to minions again!
There are 4 key rules which you must follow in order to avoid a revolt:
1. The most junior henchman (with the least seniority) gets exactly 1 LAMB. (There will always be at least 1 henchman on a team.)
2. A henchman will revolt if the person who ranks immediately above them gets more than double the number of LAMBs they do.
3. A henchman will revolt if the amount of LAMBs given to their next two subordinates combined is more than the number of LAMBs they get. (Note that the two most junior henchmen won't have two subordinates, so this rule doesn't apply to them. The 2nd most junior henchman would require at least as many LAMBs as the most junior henchman.)
4. You can always find more henchmen to pay - the Commander has plenty of employees. If there are enough LAMBs left over such that another henchman could be added as the most senior while obeying the other rules, you must always add and pay that henchman.
Note that you may not be able to hand out all the LAMBs. A single LAMB cannot be subdivided. That is, all henchmen must get a positive integer number of LAMBs.
Write a function called solution(total_lambs), where total_lambs is the integer number of LAMBs in the handout you are trying to divide. It should return an integer which represents the difference between the minimum and maximum number of henchmen who can share the LAMBs (that is, being as generous as possible to those you pay and as stingy as possible, respectively) while still obeying all of the above rules to avoid a revolt. For instance, if you had 10 LAMBs and were as generous as possible, you could only pay 3 henchmen (1, 2, and 4 LAMBs, in order of ascending seniority), whereas if you were as stingy as possible, you could pay 4 henchmen (1, 1, 2, and 3 LAMBs). Therefore, solution(10) should return 4-3 = 1.
To keep things interesting, Commander Lambda varies the sizes of the Lucky LAMB payouts. You can expect total_lambs to always be a positive integer less than 1 billion (10 ^ 9).
My code:
public class Solution {
public static int solution(int total_lambs) {
// person 1 gets 1 lamb
// person 2 gets more than 1 lamb
// person 3 gets more than or = person 1 + person 2 but less or = than double person 2
// person 4 gets more than person 3 + person 2 but less than or = double person 3
return (solution_conservative(total_lambs) - solution_generous(total_lambs));
}
public static int solution_generous(int total_lambs) {
int lamb_pay_current = 0;
int person_before = 0;
//int person_before_before = 0;
int person_counter = 0;
for (int lamb_pay_cumm = 0; lamb_pay_cumm < total_lambs; lamb_pay_cumm += lamb_pay_current) {
if (!(total_lambs > 0)) {break;}
if ((total_lambs == 1)) {break;}
if ((lamb_pay_cumm == 0) && (total_lambs > 0)) {
lamb_pay_current = 1;
person_counter++;
continue;
}
if ((lamb_pay_cumm) == 1 && (total_lambs > 1)) {
lamb_pay_current = 2;
person_before = 1;
person_counter++;
continue;
}
if (person_before == 1) {
person_before = 2;
}
if (person_before * 2 + lamb_pay_cumm > total_lambs) {continue;}
lamb_pay_current = person_before * 2;
person_counter++;
// person_before_before = person_before;
person_before = lamb_pay_current;
}
if (total_lambs == 1) {return 1;}
if (!(total_lambs > 0)) {return 0;}
return person_counter;
}
public static int solution_conservative(int total_lambs) {
int lamb_pay_current = 0;
int person_before = 0;
int person_before_before = 0;
int person_counter = 0;
for (int lamb_pay_cumm = 0; lamb_pay_cumm < total_lambs; lamb_pay_cumm += lamb_pay_current) {
if (!(total_lambs > 0)) {break;}
if ((total_lambs == 1)) {break;}
if ((lamb_pay_cumm == 0) && (total_lambs > 0)) {
lamb_pay_current = 1;
person_counter++;
continue;
}
if ((lamb_pay_cumm) == 1 && (total_lambs > 1)) {
lamb_pay_current = 1;
person_before = 1;
person_counter++;
continue;
}
if (person_before == 1) {
person_before_before = 1;
}
if (person_before + person_before_before + lamb_pay_cumm > total_lambs) {continue;}
lamb_pay_current = person_before + person_before_before;
person_counter++;
person_before_before = person_before;
person_before = lamb_pay_current;
}
if (total_lambs == 1) {return 1;}
if (!(total_lambs > 0)) {return 0;}
return person_counter;
}
}
What I am trying to get done is that I have 2 functions. One is to find the most "generous" possible way to give everyone the most amount of LAMBS possible before someone revolts. This pattern appears to be like this: 1, 2, 4, 8, 16 etc. I may be wrong. The other function is to find the most "conservative" possible way to give everyone the least amount of LAMBS possible before someone revolts. This pattern appears to be like this: 1, 1, 2, 3, 5, 8, 13, etc. I may also be wrong.
Whenever I do
"verify Solutions.java", it always fails Test #7. All other tests succeed, just this one fails. And I don't know what Test #7 is.
i have also tried most of the tests i knew of on Intellij Idea but all of them looked correct to me...
You are right about the patterns of generous and stingy. Generous path follows powers of two and the stingy follows pattern of fibonacci.
It is hard to figure out what is wrong with your code. But I think most probably your code doesn't calculate the number of henchmen correctly especially when there are remaining lambs that can be handed out without violating the restrictions.
Generous:
Start with the power of two = 1 and keep taking powers of two and adding to lambs to be paid, until you exceed the total_lambs. When you exceed make sure that you subtract the excess from the paid out lambs, so you get the original lambs paid. Also get the last two paid lambs which can be easily obtained by:
current_power_of_two/2 + current_power_of_two/4
See if it is less than or equal to remaining lambs = total_lambs - lambs_paid, then increment the henchmen by 1.
Stingy: Its the same approach except here you keep track of the last two paid lambs in the fibonacci series.
Here is one straightforward implementation for both generous and stingy handouts:
public static int solution_generous(int total_lambs) {
// Apply power of two
int power_of_two = 1;
int henchmen = 1;
int lambs_paid = 1;
while ( lambs_paid <= total_lambs ) {
power_of_two = 2*power_of_two;
lambs_paid += power_of_two;
if ( lambs_paid > total_lambs ) {
lambs_paid -= power_of_two;
power_of_two = power_of_two/2;
break;
}
henchmen++;
}
int last_one = power_of_two;
int last_before_one = power_of_two/2;
if ( last_one + last_before_one <= total_lambs - lambs_paid ) {
henchmen++;
}
return henchmen;
}
public static int solution_conservative(int total_lambs) {
//Fibonacci
int f1 = 1;
int f2 = 1;
int f12 = f1 + f2;
int henchmen = 1;
int lambs_paid = f1;
int last_two_paid = f2;
while ( lambs_paid <= total_lambs ) {
last_two_paid = f2;
f1 = f2;
f2 = f12;
f12 = f1 + f2;
lambs_paid += f1;
if ( lambs_paid > total_lambs ) {
break;
}
henchmen++;
}
if ( last_two_paid <= total_lambs - lambs_paid ) {
henchmen++;
}
return henchmen;
}
Problem Statement:
Find the minimum number of steps required to reach a target number x from 0 (zero), using only two operations: +1 (add 1 to the number) or *2 (multiply 2 with the number).
So here's the Logic that I came up with:
The best way is to work backwards. Start from the number you need:
Subtract 1 if the number is odd.
Divide by 2 if the number if even.
Stop when you get to zero.
For example, for 29, you get 28, 14, 7, 6, 3, 2, 1, 0.
And, here's what I have tried doing (Java 7):
kValues is an array that has the x values for which the steps are needed to be computed and stored in an array called result.
static int[] countOperationsToK(long[] kValues) {
int size = kValues.length,x,i,steps;
int result[] = new int[size];
for (i = 0; i < size; ++i)
{
steps = 0;
for (x = (int)kValues[i]; x != 0 ; ++steps)
{
if((x % 2) == 0)
x /= 2;
else x--;
}
result[i] = steps;
}
return result;
}
My Problem:
This is a Hackerrank question and I am supposed to write an efficient code. I was successful with 7/11 test cases and others were timed out. Since, it is a Hackerrank question, I can't change the function definition or the return type. That is the reason why I am converting from long to int in my for loop, in order to use % (modulus). I would like to know where I am going wrong. Is my algorithm taking too long to compute (for the number of values close to a million)? Which is obviously the case, but how do I alter my algorithm in order to pass all the test cases?
Thank you in advance :)
for (x = (int)kValues[i]; x != 0 ; ++steps)
The fact that you are casting a long to an int is very suspicious. You might get a negative number when you do that.
Say x == -2: you divide it by 2 to give -1, then subtract 1 to give -2. You'll keep doing that indefinitely.
Just define x to be a long, and remove the cast.
So, here's the working code. I had forgotten to append L while using the modulo. Silly mistake led to so much of typing. LOL!!
static int[] countOperationsToK(long[] kValues) {
int size = kValues.length,i,steps;
int result[] = new int[size];
long x;
for (i = 0; i < size; ++i)
{
steps = 0;
for (x = kValues[i]; x != 0 ; ++steps)
{
if((x % 2L) == 0)
x /= 2L;
else x -= 1L;
}
result[i] = steps;
}
return result;
}
Here is a very short version, using bit-analysis:
static int[] countOperationsToK(long... input) {
int result[] = new int[input.length];
for (int i = 0; i < input.length; i++)
if (input[i] > 0)
result[i] = Long.bitCount(input[i]) + 63 - Long.numberOfLeadingZeros(input[i]);
return result;
}
The idea here is to look at the binary number, e.g. for 29 that is 11101. There are 4 bits set, so we'd need to do +1 four times, and the highest bit position is 4, so we need to left-shift (i.e. *2) four times, for a total of 8 operations: +1, *2, +1, *2, +1, *2, *2, +1.
numberOfBits = Long.bitCount(x)
highBitNumber = floor(log2(x)) = 63 - Long.numberOfLeadingZeros(x)
The highBitNumber part doesn't work if value is zero, hence the if statement.
For input number x,
Minimum no. of Ops = (int)log2(x) + Long.BitCount(x)
So I made this game where I pick a random number 1-100 and the computer guesses and I tell it too high, too low, or whatever. It works pretty good, except that it gets stuck in cycles when I try binary search and I can't seem to prevent it. I'll demonstrate:
Say the number is 79. Eventually, the program will ask if the number is 42. No, that's too low. Then it asks if it's 71. Guess higher! Then it asks 82. Nope, lower. Then it goes back to 42 and the cycle repeats over and over. Here's my code (note that it's an excerpt from the full code, so excuse the lack of the importation of JOptionPane and whatnot):
int x = 50;
int y = x;
int[] alreadyGuessed = {};
boolean secondGuess = false;
//The user has to select, too high, too low, correct!
while (secondGuess == false) {
Object[] options = {"Too high", "Too Low", "Correct"};
int pick = JOptionPane.showOptionDialog(null, "Is your number " + x
+ "?", "Guess",
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
null, options, options[2]);
for (int positionInList = 0; positionInList >= 100; positionInList++) {
arrayDemo(x, positionInList);
}
if (pick == 0) {
int max = x - 1;
int min = 0;
x = ((max + min) / 2);
}
if (pick == 1) {
int max = 100;
int min = x+1;
x = ((max + min) / 2);
}
if (pick == 2) {
System.out.println("Yay! I win!");
secondGuess = true;
}
}
You need to keep track of both min and max. So in your code, when you say max = 100 or min = 0, the program is forgetting what the max & min are.
Delete those lines & you should be OK. In essence, you need to remember min & max all the way until you find the answer.
e.g. if the number is 42, min and max will be like:
0..100, guess 50 (too high)
0..49, guess 25 (too low)
26..49, guess 38 (too low)
39..49, guess 44 (too high)
39..43, guess 41 (too low)
42..43, guess 42 WIN!
Notice how both min and max zoom in on the answer. Carrying that information forward is what makes the strategy work.
The question as asked in the title has already been answered, but there are some constraints i am bound by that require a different solution.
The answer to finding the closest value in an array to a number:
int myNumber = 490;
int distance = Math.abs(numbers[0] - myNumber);
int idx = 0;
for(int c = 1; c < numbers.length; c++)
{
int cdistance = Math.abs(numbers[c] - myNumber);
if(cdistance < distance)
{
idx = c;
distance = cdistance;
}
}
int theNumber = numbers[idx];
For some background on what makes my problem specific enough to ask:
My program takes in a PriorityQueue of hospital patients. There are 3 operating rooms, and the program will output the 8 hour(a work day) schedule for those 3 operating rooms, in addition my "postpone" array, containing patients that did not make the cut for that day. I have an array called roomCapacity which contains the remaining hours in each room. Heres where my problem is more specific than the title. The above answer uses the distances between each number and in my case picks the roomCapacity with the least distance(best fit). But there are times when the DIFFERENCE is -1. I realize the Math.abs ensures the DISTANCE is positive, but in this particular case I have no reason to use absolute value for the reason being an operation may not be scheduled in a room if the duration of the operation is longer than the capacity of the room. The DISTANCE(absolute value of the difference) must be greater than OR equal to zero. I've spent what I have decided counterproductive trying to find a solution, and would greatly appreciate some hints.
In a hurry to get this done i slapped the above code into my method, and only after using the debugger realized that I was placing patients in rooms whos capacities were less than the operations duration, but would be the best fit neglecting said constraint.
(EDIT)Specific question: How do I find the closest number in my roomCapacity array to a value(int d) using a similar approach to the one shown above, while taking into account the difference may not be less than 0?
(This is my first question, appologies for the ambiguity)
my method:
public int getBestRoom(int d)//int d = currentOperationDuration
{
int roomNumber;
/**
*int distance = Math.abs(roomCapacity[0] - d);
*int idx = 0;
*for(int c = 1; c < 3; c++)
*{
* int cdistance = Math.abs(roomCapacity[c] - d);
* if(cdistance < distance)
* {
* idx = c;
* distance = cdistance;
* }
*roomNumber = idx;
*}
**/
return roomNumber;
}
Easy, remove all Math.abs and test for positive distances only:
int myNumber = 490;
int distance = Integer.MAX_VALUE;
int idx = 0;
for(int c = 0; c < numbers.length; c++)
{
int cdistance = numbers[c] - myNumber;
if (cdistance < distance && cdistance >= 0)
{
idx = c;
distance = cdistance;
}
}
int theNumber = numbers[idx];