I need to calculate a Level system for a friend of mine. The problem is that I have no clue how I should do that. He gave me a end point how much experience (31536000) is needed for the max level (44)
The level should increase in difficulty as higher you are (like degresive progression or logarithmic) I just have no clue how to calculate it backwards or even forward.
I am not that experience with Java since this is ages for me.
I need every experience needed for each level from 1 to 44 and you reach level 44 by earning 31536000 experience.
I have test some stuff but I am really not good at that and I know this is a little bit to high for me.
public class level{
public static final double base_exp = 1;
public static final double exp_increase_per_level = 0.40;
public static final int max_level = 44;
public static int level (double exp){
int i = 1;
double test_exp = base_exp;
while (i<max_level) {
if (test_exp > exp){
return i;
}
test_exp = test_exp + test_exp * exp_increase_per_level;
i++;
}
return max_level;
}
public static double level_to_exp (int level) {
if(level == 1)
return base_exp;
else {
double prev = level_to_exp(level-1);
return prev + prev * exp_increase_per_level;
}
}
public static double level_to_total_exp (int level) {
if(level == 1)
return base_exp;
else {
return level_to_total_exp(level-1) + level_to_exp(level-1) * (1 + exp_increase_per_level);
}
}
public static void main(String []args){
System.out.println("to level 1,"+level_to_exp(1)+"exp");
System.out.println("to level 2,"+level_to_exp(2)+"exp");
System.out.println("to level 44,"+level_to_exp(44)+"exp");
System.out.println("Total exp to level 44" +level_to_total_exp(44)+" acuumulated");
}
}
This is just basic maths. Your model appears to be:
score = base^level
So to get the level from the score:
log(score) = log(base^level) = level * log(base)
level = log(score) / log(base)
To calculate base, just substitute in level=44 and score=whatever, and rearrange.
Related
I am in the midst of learning about methods in Java and was curious to know if passing a method as an argument within another method is bad practice. Although I know there are many ways to achieve the same solution there are times in which code written in one way is more efficient than others.
For instance in the code exercise it was asked to create a method with two parameters(name and position)
and create a second method with one parameter(score). Then call both of these methods and display the results using the following score data (1500, 900, 400, 50).
My solution was written as follows:
public class Main {
public static void main(String[] args) {
displayHighScorePosition("Fred",calculateHighScorePosition(1500));
displayHighScorePosition("Ted", calculateHighScorePosition(900));
displayHighScorePosition("Jen", calculateHighScorePosition(400));
displayHighScorePosition("John",calculateHighScorePosition(50));
}
public static void displayHighScorePosition(String name, int highScorePosition) {
System.out.println(name + " managed to get into position " + highScorePosition + " on the high score table");
}
public static int calculateHighScorePosition(int score) {
int position = 4;
if(score >= 1000) {
position = 1;
} else if (score >= 500) {
position = 2;
} else if (score >= 100) {
position = 3;
}
return position;
}
}
This displayed the same output as what was expected by the exercise, but the code written in the exercise was
public class Main {
public static void main(String[] args) {
int highScorePosition = calculateHighScorePosition(1500);
displayHighScorePosition("Fred", highScorePosition);
int highScorePosition = calculateHighScorePosition(900);
displayHighScorePosition("Ted", highScorePosition);
int highScorePosition = calculateHighScorePosition(400);
displayHighScorePosition("Jen", highScorePosition);
int highScorePosition = calculateHighScorePosition(50);
displayHighScorePosition("John", highScorePosition);
}
public static void displayHighScorePosition(String name, int highScorePosition) {
System.out.println(name + " managed to get into position " + highScorePosition + " on the high score table");
}
public static int calculateHighScorePosition(int score) {
int position = 4;
if(score >= 1000) {
position = 1;
} else if (score >= 500) {
position = 2;
} else if (score >= 100) {
position = 3;
}
return position;
}
}
Does it make a difference? i.e. is one a better way to write or will I run into issues down the road when the code becomes much more complex?
You're not passing another method as a parameter, you're passing the return value of a method as a parameter, which is a totally different concept.
Anyway, the second example (apart from being syntactically wrong since you keep re-declaring a variable instead of just re-assigning a value to it) is just more verbose for no apparent gain, in this case.
It would make sense if you then used any of those declared variables someplace else down the method.
So I, have this code to trace and I had the results of 2.25 and 2.75. But when I compile it, I get 1.5 and 2.0. Why is that? Do the parentheses have anything to do with that?
public class TraceClass {
private double valBefore;
private double valAfter;
public TraceClass(double valIn) {
this.valBefore = valIn;
this.valAfter = 0.0;
}
public void doIt(boolean which){
if (which == true) {
this.valAfter = ((int) this.valBefore) + .5;
}
else {
this.valAfter = (int) (this.valBefore + .5);
}
}
public double getValAfter(){
return this.valAfter;
}
}
public class MainClass {
public static void main(String[] args) {
TraceClass traceObj = new TraceClass(1.75);
traceObj.doIt(true);
double temp = traceObj.getValAfter();
System.out.println("Result is " + temp);
traceObj.doIt(false);
temp = traceObj.getValAfter();
System.out.println("Result is " + temp);
}
}
edit: this is code that my teacher gave out ask practice for stack tracing. i got 2.25 because I added 1.75+.5= 2.25. But then I accidentally added .5 to 2.25 to get 2.75
edit2: typo
Both the parentheses and the casts to int affect the result, and the order matters.
For the true case, valBefore is casted to int first, yielding the integer value 1 (it is truncated). Then .5 is added, a double value, so 1 is widened to 1.0 and 1.5 results.
For the false case, valBefore is added to 0.5 first, and 1.5 + .5 is 2.0. Then that result is cased to int which yields 2. The assignment back to the double variable valAfter widens it back to double -- 2.0.
You are casting your variable to int for some strange reason which means you are adding 1 (integer part of 1.75) and 0.5 = 1.5 and in the second case you are casting the result of the addition to int so you get 1.5 + 0.5 = 2 (then casted to double again), so the second time you do not lose anything since the result happened to be an even integer.
Just remove all cast to int, it makes no sense when calculating with double values
When you cast the double value into an int, it just does not count the decimal parts. I just convert an int to double. you don't need to cast either.
import org.junit.jupiter.api.Test;
public class DoubleIssueStackOverflow {
#Test
public void test_first(){
TraceClass traceObj = new TraceClass(1.75);
traceObj.doIt(true);
double temp = traceObj.getValAfter();
System.out.println("Result is " + temp);
traceObj.doIt(false);
temp = traceObj.getValAfter();
System.out.println("Result is " + temp);
}
public class TraceClass {
private double valBefore;
private double valAfter;
public TraceClass(double valIn) {
this.valBefore = valIn;
this.valAfter = 0.0;
}
public void doIt(boolean which) {
if (which == true) {
this.valAfter = this.valBefore + .5;
} else {
this.valAfter = this.valBefore + .5;
}
}
public double getValAfter() {
return this.valAfter;
}
}
}
So I did search and read abut every factorial listing on this site but I cannot seem to figure out what is wrong with my code. Iv tried multiple different return methods but they all keep failing. Any ideas?
public class RecursivelyPrintFactorial {
public static void printFactorial(int factCounter, int factValue) {
int nextCounter = 0;
int nextValue = 0;
if (factCounter == 0) // Base case: 0! = 1
System.out.println("1");
}
else if (factCounter == 1) // Base case: print 1 and result
System.out.println(factCounter + " = " + factValue);
}
else { // Recursive case
System.out.print(factCounter + " * ");
nextCounter = factCounter - 1;
nextValue = nextCounter * factValue;
}
return factValue * printFactorial(factValue - factCounter);
}
}
public static void main (String [] args) {
int userVal = 0;
userVal = 5;
System.out.print(userVal + "! = ");
printFactorial(userVal, userVal);
}
}
I have a feeling I have the equation incorrect in my return but iv tried every combination I can think of. Its driving me insane. Every one reports an error. Any ideas?
return factValue * printFactorial(factValue - factCounter);
I assume that you should be using the "next" values instead of these.
Edit: Also note that the function takes two parameters and is void. Returning factValue times void doesn't make sense.
http://www.cstutoringcenter.com/problems/problems.php?id=103
For those who doesn't want to click it, it basically says there's a stepping stone, "-" and soldier "#", soldiers can only move right. If the soldier is behind another soldier, he must wait for the soldier to move first. The ending condition is when all soldiers reaches the end.
The number of ways 2 soldier can move across 5 stepping stones.
1) ##--- #-#-- -##-- -#-#- --##- --#-# ---##
2) ##--- #-#-- -##-- -#-#- -#--# --#-# ---##
3) ##--- #-#-- #--#- -#-#- --##- --#-# ---##
4) ##--- #-#-- #--#- -#-#- -#--# --#-# ---##
5) ##--- #-#-- #--#- #---# -#--# --#-# ---##
I'm using a breadth first search, with 5 stones, it's running within seconds, but with 10 stones, it's taking hours, the time is increasing exponentially with the depth. How can I deal with this?
My Codes:
States.java
import java.util.ArrayList;
public class State {
public int stones;
public Soldiers[] soldiers;
public String currentState ="";
public boolean visited = false;
public State(int stones,int Numsoldiers){
System.out.println(Numsoldiers);
this.stones = stones;
soldiers = new Soldiers[Numsoldiers];
System.out.println("length" + soldiers.length);
initState();
}
public State(int stones,Soldiers[] soldiers){
this.stones = stones;
this.soldiers = soldiers;
paintState();
}
public void initState(){
for(int i=0;i<soldiers.length;i++)
{
soldiers[i] = new Soldiers();
soldiers[i].position =i;
currentState+="#";
}
for(int j=soldiers.length;j<stones;j++)
{
currentState+="-";
}
}
private void paintState(){
for(int j=0;j<stones;j++)
{
currentState+="-";
}
char[] stateChar = currentState.toCharArray();
currentState = "";
for(int i=0;i<soldiers.length;i++){
stateChar[soldiers[i].position] = '#';
}
for(int k=0; k<stateChar.length;k++){
currentState += stateChar[k];
}
}
public void printState(){
System.out.println(currentState);
}
public ArrayList<State> getNextStates(){
ArrayList<State> States = new ArrayList<State>();
for(int i=0;i<soldiers.length;i++){
Soldiers[] newSoldiers = new Soldiers[soldiers.length];
for(int j=0;j<soldiers.length;j++){
newSoldiers[j] = new Soldiers(soldiers[j].position);
}
if(!((newSoldiers[i].position+1)==stones))
{
if((currentState.charAt((newSoldiers[i].position+1))=='-'))
{
newSoldiers[i].move();
States.add(new State(stones,newSoldiers));
}
}
}
if(States.size()==0)
{
TestSoldiers.count++;
}
return States;
}
}
Soldiers.java
public class Soldiers {
int position = 0;
public Soldiers(){
position =0;
}
public Soldiers(int pos){
position = pos;
}
public void move(){
position ++;
}
}
TestSoldiers.java
import java.util.LinkedList;
import java.util.Queue;
public class TestSoldiers {
public static int count=0;
public static void main(String[] args){
TestSoldiers t = new TestSoldiers();
}
public TestSoldiers()
{
State s = new State(10,3);
breadthFirstTraversal(s);
System.out.println(count);
}
public void breadthFirstTraversal(State rootNode){
Queue<State> q = new LinkedList<State>();
q.add(rootNode);
while(!q.isEmpty()){
State n = (State)q.poll();
n.printState();
for(State adj : n.getNextStates()){
q.add(adj);
}
}
}
}
How can I make it so that I will only consider each State once while maintaining the integrity of the total number of ways to end (counts in TestSoldiers.java)?
For those of you who want to modify the parameters, it's the new State(n,k) where n is the number of stones and k is the number of soldiers.
Memoization might come in handy.
The idea would be to run depth-first search to count the number of ways to get from the current state to the end, and store this result, then look up the already-calculated value if ever that state is repeated.
For instance, there are 2 ways to reach the end from -#-#-, so, storing this result when we get there via -##--, we could simply look up 2 when we get there via #--#-.
The simplest (but far from most efficient) way to store these would simply be to have a:
Map<Pair<Integer (Position1), Integer (Position2)>, Integer (Count)>
More generically, you could perhaps make that Pair a List.
A more efficient approach would be to have a bitmap where each bit corresponds to whether or not there's a soldier at some given position. So -#-#- would correspond to 01010, which could simply be stored in an int as 10 in decimal - if there are more than 64 stones (i.e. what would fit into a long), you could use a BitSet.
You might be better using combinatorics to compute the number of paths.
For example, suppose there are 2 soldiers and 5 steps.
Represent the distance the first soldier has moved by y, and the distance the second soldier has moved by x.
You are trying to count the number of monotonic paths from 0,0 to 3,3 such that y is never greater than x.
This is a well known problem and the answer is given by the Catalan numbers. In this case, the answer is given by the Catalan number for n=3, which is 5.
When you have more than 2 soldiers you will need to use multidimensional Catalan numbers. A useful guide and formula can be found on OEIS:
T(m, n) = 0! * 1! * .. * (n-1)! * (m * n)! / ( m! * (m+1)! * .. * (m+n-1)! )
My solution runs 10 positions in less than 1 second. The solution is quick and dirty, but the algorithm is what you should be interested in right?
The idea of my algorithm is:
manage a set of paths to compute. start with the path where both soldiers are at the left most positions.
if the set of paths to compute is not empty pick any path and remove it from the set.
if the path is terminated (both soldiers are at the most right positions) print the path. continue with 2.
extend the path by moving the head soldier if possible and put it into the set.
extend the path by moving the tail soldier if possible and put it into the set.
That's it.
public static void main(String[] args) {
List<Node> nodes = Node.newRootNode(10);
while (!nodes.isEmpty()) {
Node node = nodes.remove(0);
if (node.isLeaf()) node.printPath();
else {
if (node.headSoldierCanMove()) nodes.add(node.moveHeadSoldier());
if (node.tailSoldierCanMove()) nodes.add(node.moveTailSoldier());
}
}
}
static final class Node {
static List<Node> newRootNode(final int maxPos) {
return new ArrayList<Node>() {{
add(new Node(1, 2, maxPos, ""));
}};
}
private final int maxPos;
private final String path;
private int tailPos = 1;
private int headPos = tailPos + 1;
private Node(int tailPos, int headPos, int maxPos, String path) {
this.maxPos = maxPos;
this.tailPos = tailPos;
this.headPos = headPos;
this.path = addPath(path);
}
boolean tailSoldierCanMove() {
return tailPos < headPos - 1;
}
Node moveTailSoldier() {
return new Node(tailPos + 1, headPos, maxPos, path);
}
boolean headSoldierCanMove() {
return headPos < maxPos;
}
Node moveHeadSoldier() {
return new Node(tailPos, headPos + 1, maxPos, path);
}
void printPath() {
System.out.println(path);
}
boolean isLeaf() {
return headPos == maxPos && tailPos == headPos - 1;
}
private String addPath(String prefix) {
StringBuilder builder = new StringBuilder(prefix);
for (int pos = 1; pos <= maxPos; pos++) {
builder.append(tailPos == pos || headPos == pos ? "#" : "-");
}
return builder.append(" ").toString();
}
}
I have a TV class that has only 99 channel and 20 as the highest volume but my volume and channel setters are not working properly also when i add one to the volume instead of add 1
to 10 which is my default volume it only add one to the given volume digit
my tv class
public class TV
{
private String flag;
private int ch;
private int vol = 10;
public TV(String onOffSwitch, int channel, int volume)
{
flag = onOffSwitch;
ch = channel;
vol = volume;
}
public void setFlag(String onOffSwitch)
{
onOffSwitch = "Off";
}// End of setFlag
public String getFlag()
{
return flag;
}// End of getFlag
public void setCh (int newChannel)
{
if (newChannel >= 99)
{
ch = 99;
}else
{
ch = newChannel;
}
if(newChannel < 0)
{
ch = 0;
}
}//end of setCh
public int getCh ()
{
return ch;
}// End of getCh
public void setVol(int newVolume)
{
if(newVolume >= 20)
{
vol = 20;
}
if(newVolume < 0)
{
vol=0;
}
}// End of SetVolume
public void incrementVolume()
{
vol++;
}
public int getVol()
{
return vol;
}// ENd of getVolume
public String toString()
{
return String.format("%s :%s\n%s:%d\n%s :%d","TV is switched", flag,"TV channel",ch,"TV volume",vol);
}
}// End of TV class
my test Drive class
import java.util.Scanner;
public class TvTest
{
public static void main (String[] args)
{
String tvStatus;
int chan;
int volu;
Scanner input = new Scanner(System.in);
TV tv2 = new TV("off",105,10);
System.out.print(tv2);
System.out.println();
System.out.print("Turn TV On or Off ?");
tvStatus = input.nextLine();
System.out.print("Channel : ");
chan = input.nextInt();
System.out.print("Volume : ");
volu = input.nextInt();
TV tv1 = new TV(tvStatus,chan,volu);
tv1.incrementVolume();
System.out.println(tv1);
}
}
and the test output
TV is switched :off
TV channel:105
TV volume :10
Turn TV On or Off ?on
Channel : 105
Volume : 1
TV is switched :on
TV channel:105
TV volume :2
why isnt my setters working ???
Your constructor should be using your setters:
public TV(String onOffSwitch, int channel, int volume)
{
this.setFlag(onOffSwitch);
this.setCh(channel);
this.setVol(volume);
}
setFlag should be setting flag to the value passed in.
public void setFlag(String onOffSwitch)
{
this.flag = onOffSwitch;
}// End of setFlag
public void setFlag(String onOffSwitch)
{
onOffSwitch = "Off";
}// End of setFlag
onOffSwitch variable is not a field. That's the name in the parameter list, should be flag instead.
public void setVol(int newVolume)
{
if(newVolume >= 20)
{
vol = 20;
}
if(newVolume < 0)
{
vol=0;
}
}// End of SetVolume
That setter does not do anything unless the new value is out of range.
The problem isn't with your setters/getters (although they read a bit weird), the problem is, you're ignore them in your constructor...
public TV(String onOffSwitch, int channel, int volume)
{
flag = onOffSwitch;
ch = channel;
vol = volume;
}
Try using something like
public TV(String onOffSwitch, int channel, int volume)
{
setFlag(flag);
setCh(channel);
setVol(volume);
}
Instead...
The variable onOffSwitch is also undefined, so you example won't compile ;). It should read something like...
public void setFlag(String onOffSwitch)
{
flag = onOffSwitch;
}// End of setFlag
Mind you, I'd probably use a boolean value and have turnOn and turnOff methods, but that's just me...
I've been drinking all day so keep this in mind but I'm guess you were too since you couldn't finish this basic assignment. : p
First off, never, ever, I mean ever use a String to represent a two state value. Booleans are nice, so use them.
class Televsion {
power = false; # off
power = true; # on
}
Secondly, your variable names suck. Not to be mean, there is quite a bit of miss matched between them that needless complexes the program. Also don't use abbreviation or short hand variable names. I can understand if this was maybe 20 or 10 years ago, but modern editors tend have an auto completion features that help fill out the code in one or two key strokes.
It looks like you haven't learned about the keyword "this". When you use "this" inside a class, it specificity calls a specific variable or method from the class. The main takeaway is that it lets you avoid any name collisions from arguments and local variables.
class Televsion {
private boolean power;
private int channel;
private int volume;
public Televsion( boolean power, int channel, int volume ) {
this.power = power;
this.channel= channel;
this.volume = volume;
}
}
This way it's a little more saner for the reader ;P
Testing code in a main method is for newbs and loser. JUnit is virtually built into Java now, so why not use it, or you can use TestNG ^.^
Building out a Test suite can make it easier to design and rework code.
You also might want to take a look at Hamcrest as well.
public TelevsionTest {
private Televsion televsion;
#Before
public void boilerplateSetUpCode() {
// The before annonation has it's roots in apsectJ, I beleve.
// In this context it makes this method run before every test.
televsion = new Televsion();
}
#Test
public void testSwitchOn() {
televsion.switchOn();
assertTrue( televsion.getPowerState() == true );
# JUnits assertions are weak, that's why I like hamcrest.
}
}
Try to code for re-usability and maintainability. This can makes life easier in the long run, but a challenge in the shot term. What if you get cable or satellite, will this affect the channel numbers?
Here is a five minute hack on how I might rework the problem.
public class Televsion {
private Logger4j logger;
private ChannelSource channelSource; // Naming is a little weak
private int volume;
private boolean power;
public Tv() {
channelSource= channelSource.LOCAL;
volume = 0;
power = false;
}
public turnOn(){ power = true; }
public void turnOff() { power = false; }
public void muteVolume() { volume = 0; }
public void setVolume( volume ) {
if ( volume > -1 && volume < 100 ) {
this.volume = volume;
} else {
logger.dubug( String.format("Arg: %d", volume) );
// This is anti-pattern of how not to word a debugging statement.
// Plus, I'm lazy...
}
}
public void changeChannelSource( ChannelSource channelSource ) {
this.channelSource = channelSource;
}
public void changeChannelNumber( int channelNumber ) {
channelSource.changeChannelNumber( channelNumber );
}
// I like singletons
public enum ChannelSource {
LOCAL(0), ALT(0), CABLE(0);
private int channelNumber;
private ChannelSource( int channelNumber ) {
this.channelNumber = channelNumber ;
}
public int getChannelNumber() { return channelNumber; }
public void setChannelNumber( channelNumber ) {
// Lazy hack
if ( this.getName() == "LOCAL" ) {
if ( channelNumber > -1 && channelNumber < 100 ) {
this.channelNumber = channelNumber;
} else {
logger.debug(
String.format("Unable to change %s, channel to %d", this.getName(), channelNumber)
);
}
}
}
}
}
Hopefully, if you start improving your coding standards and start learning good programming techniques then you might enjoy coding enough to make an actual Stack Exchange account :)
This is a simple list of things you should learn to make your Java teacher happy.
- Unit Testing
+ Might as well let a computer grade the code then a human, free A's
- Data Structures
+ Just using collections good enough.
+ Side rant, If use this style of matrices, Object[][] I will haunt you down.
- It's inefficient, plus hard for people maintaining this shitty code
- Jagged arrays can work just as well List< List<Object> > or you can even just use a single array, [] and sprinkle in some magic.
- Annotations
+ Helps takes the Java out of Java
- Read Effective Java
+ It's not a difficult book, will make life easier.
- Know a little about concurrency
+ If you use the synchronized keyword, then you know something is wrong.
+ Take a look into concurrent utils API
+ Read Java Concurrency in Practice
- Spring
+ If you want to get paid for knowing Java
I'm sure there are plenty of other things I'm leaving out but that's should be enough for anyone starting out learning Java.