Java enum ordinal returning -1? - java

Alright so I'm currently writing some code for a project I'm working on, and I decided an Enum for data storage will be my best bet. But in the first time in my life, the enum.ordinal() returns -1?
Heres the code:
DuelRules.Rules rule = DuelRules.Rules.values()[(buttonId - (buttonId < 29 ? 18 : 19))];
if (buttonId == 29) {
rule = DuelRules.Rules.POCKET;
}
System.out.println(rule + ", " + rule.ordinal());
rules.swapRule(player, other, rule);
reset(false);
This statement here:
System.out.println(rule + ", " + rule.ordinal());
It prints the correct rule value, but when it prints rule.ordinal() it is printing -1?
Example:
HAT, -1
My Enum:
public enum Rules {
HAT(5000, 1),
CAPE(5000, 2),
AMULET(5000, 4),
WEAPON(5000, 8),
BODY(5000, 16),
SHIELD(5000, 32),
LEG(5000, 128),
GLOVE(5000, 512),
BOOT(5000, 1024),
RING(5000, 4096),
ARROW(5000, 8192),
POCKET(17837, 1),
FORFEIT(4989),
MOVEMENT(4990),
RANGE(4991),
MELEE(4992),
MAGIC(4993),
DRINKS(4994),
FOOD(4995),
PRAYER(4996),
OBSTACLES(4997),
FUN_WEAPONS(4998),
NO_ABILITIES(4999),
SUMMONING(5001);
private final int varbitId;
private final int value;
private Rules(int id, int... value) {
this.varbitId = id;
this.value = value.length > 0 ? value[0] : 0;
}
}
Note, that enum is inside of another class, not sure if that can effect the outcome. Thanks for your help, I'm completely lost with this one.
EDIT: Upon farther review I found that the ordinal is being changed by passing it as an argument?
Screnshot of console:
Code:
} else if (buttonId >= 18 && buttonId <= 42) {
DuelRules.Rules rule = DuelRules.Rules.values()[(buttonId - (buttonId < 29 ? 18 : 19))];
System.out.println("Point one: "+rule + ", " + rule.ordinal());
rules.swapRule(player, other, rule);
getDuel(other).rules.setRules(player, other, rules
.rules);
reset(false);
sendFlash(interfaceId, buttonId);
}
Where it prints Point one, the Rule and its .ordinal is correct, in this case OBSTACLES, 20
But where it passes the rule paramters in rules.swapRule, it changes the ordinal to -1?
public boolean swapRule(Player player, Player other, Rules rule) {
System.out.println("Point 2(swapRule): " + rule + ", " + rule.ordinal());
}
What is causing the Rule parameters to be changes when getting passed as an argument?

Your approah defeats the sheer purpose of using an enumerator. Instead of mangling with indices you could use the Enum directly like this
button.setActionCommand (Rules.HAT.toString ());
Then in your ActoinListener you can determine which button was clicked by using this
public void actionPerformed (ActionEvent e) {
if (Rule.valueOf (e.getActionCommand()) == Rules.HAT) {
//HAT related button was called, process it
}
}

You can get this result by reflection:
import java.lang.reflect.Field;
public class Main {
enum Fruit { APPLE }
public static void main(String[] args) {
try {
Field field = Fruit.class.getSuperclass().getDeclaredField("ordinal");
field.setAccessible(true);
field.set(Fruit.APPLE, -1);
} catch (Exception e) {
}
System.out.println(Fruit.APPLE + ", " + Fruit.APPLE.ordinal());
}
}
However I doubt anyone could do this by mistake.

Related

float variable beign changed without beign explicitely atributted

I don't event know how to describe this weird behaviour i'm dealing with right now, but the thing is:
I have a class Player.java that has a private float life, pretty basic.
this float has its setter / getter and there is NO other way of retrieving / attributing this variable without using the getter / setter.
also, i have put a println in each, so i can have a feedback of when this variable is being retrieved, and when is beign attributed, and i get THIS on my console:
my console
i don't think the stack trace is usefull in any way, but if you want to, i can paste the code behind the stack trace too
anyway, if you haven't notice, there is a retrieve of life = 61, FOLLOWED by a retriving of life = 70, with NO attribution WHATSOEVER of this variable back to 70.
also, i dont know if this is useful, but here is the code that prints the "1 damaged 0, broadcasting to clients - Sent":
it resume in:
- decreases the player life
- if it has died, mark as dead and do other little effect things
- send event to google analytics
- after all that, if the game is a server, broadcast the damage event to all clients
public void takeDamage(float amount, Player owner, boolean showBlood, boolean local){
if(local && KambojaMain.getInstance().multiplayerConnection && !KambojaMain.getInstance().isServer) return;
if(imunity <= 0){
//new Exception().printStackTrace();
setLife(getLife() - amount * def);
if(owner != null) {
owner.score += amount*def;
}
if(showBlood)
state.showBlood(body.getWorldCenter());
System.out.println(" - DAMAGE DETECTED from " + owner.getId() + " to " + getId() + " with value " + amount + ", it was a local? " + local + ", and show blood is: " + showBlood);
System.out.println("target life is now at " + getLife());
hitTimer = 1f;
if(getLife() <= 0){
if(!isDead()){
deaths++;
if(owner != null){
owner.kills ++;
owner.ghosts.add(new Ghost(getId(), getPosition()));
owner.score += 100;
}
setDead(true);
body.getFixtureList().get(0).setSensor(true);
getState().showSkull(body.getWorldCenter(), getAngle());
String playerType = "controller";
if(isKeyboard()) {
playerType = "keyboard";
}
if(this instanceof BetterBot) {
playerType = "bot";
}
HashMap<String, String> customs = new HashMap<String, String>();
customs.put("cd1", KambojaMain.getMapName());
customs.put("cd3", getWeapon().getClass().getSimpleName());
customs.put("cd4", "player_" + playerType);
String ow = "Suicide";
if(owner != null)
ow = owner.getWeapon().getClass().getSimpleName();
KambojaMain.event("game", "player_kill", ow, customs);
}
}
if(gruntTimer < 0){
if(GameState.SFX)
grunt[(int)(Math.random()*5)].play();
gruntTimer = 0.5f;
}
if(KambojaMain.getInstance().multiplayerConnection && KambojaMain.getInstance().isServer) {
KambojaPacket kp = new KambojaPacket(PacketType.PLAYER_DAMAGE);
PlayerDamage pd = new PlayerDamage();
pd.damage = amount;
pd.showBlood = showBlood;
pd.owner = owner.getId();
pd.target = getId();
kp.data = pd;
System.out.print(pd.owner + " damaged " + pd.target + ", broadcasting to clients - ");
KambojaMain.getInstance().broadcast(kp, Protocol.TCP);
System.out.println("Sent");
}
}
}
note: i AM using multi threading environment because this is a lan multiplayer game, and this variable can be retrieved in other threads different from the main thread.
I have searched about the volatile keyword, Atomic classes (AtomicFloat dont exist, and the implementation of it using AtomicInt as a bit data also was used), but none of this could prevent this from happening and i have NO idea of what is this behaviour and what is causing it
can someone please help me? i don't know what to search anymore
Try making your method synchronized (this would make sure only one thread can be running this method, on an instance of your class).
public synchronized void takeDamage(.... // same as before
Check out this post, it has a similar question with more info about running blocks of code atomically.

Java code issue [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm having an issue with my code. It won't compile and every time I try to fix it I get an error. I can't see what the problem with it is. I may be just overlooking or looking too hard. I haven't done Java coding since 2006 until I took this class. The class doesn't go a lot into the coding and I'm trying to work off of my memory. I have been working on this code and looking at this code since I wrote it over a week ago. Can someone look and tell me what I screwed up. It's already past-due. I already showed the teacher but haven't got any help and my school doesn't currently have a tutor for this class during this semester. Please help! Code and errors are below:
Errors:
/*
* File: Guitar2.java
* Author: Eppards,Michael
* Date: June 11, 2018
*/
class Guitar2 {
private int numStrings;
private double guitarLength;
private Color guitarColor;
private Manufacturer guitarManufacturer;
enum Manufacturer {
GIBSON,
FENDER,
IBANEZ;
}
enum Color {
RED,
BLUE,
BLACK;
}
// Default Constructor
private Guitar2() {
this.numStrings = 6;
this.guitarLength = 28.2;
this.guitarColor = Color.RED;
this.guitarManufacturer = Manufacturer.GIBSON;
}
// Argument Constructor
private Guitar2(int numStrings, double guitarLength, Color guitarColor, Manufacturer guitarMaker) {
this.numStrings = numStrings;
this.guitarLength = guitarLength;
this.guitarColor = guitarColor;
this.guitarManufacturer = guitarMaker;
}
// Getters
public int getNumStrings() {
return numStrings;
}
public double getGuitarLength() {
return guitarLength;
}
public Color getGuitarColor() {
return guitarColor;
}
public Manufacturer getGuitarManufacturer() {
return guitarManufacturer;
}
// playGuitar method for 16 randomly selected musical notes
enum Notes {
A(1),
B(4),
C(1),
D(2),
E(0.25),
F(0.5),
G(0.5);
double duration;
private Notes(double duration) {
this.duration = duration;
}
}
public String playGuitar() {
String play = "[";
int a;
int b;
// initiate a random number
Random rn = new Random();
// for loop to select random notes
for (int k = 0; k < 16; k++) {
a = rn.nextInt(7);
b = rn.nextInt(5);
play = play + Notes.values()[a] + "(" + Notes.values()[a].duration + ")";
if (k != 15) play = play + ",";
}
play = play + ']';
return play;
}
// used to return the info in a string
public String toString() {
String infoString = "(numStrings=" + this.numStrings + ", guitarLength=" + this.guitarLength + ",guitarManufacturer=" + this.guitarManufacturer + ",guitarColor=" + (this.guitarColor == null ? "none" : this.guitarColor.name()) + ")";
return infoString;
}
}
Guitar2.java:80: error: cannot find symbol
Random rn = new Random();
^
symbol: class Random
location: class Guitar2
Guitar2.java:80: error: cannot find symbol
Random rn = new Random();
^
symbol: class Random
location: class Guitar2
2 errors
-Hello, World!-
There were quite a few issues with the code that caused it to not compile. I fixed all of them (I think) and have written out what was wrong:
Public needs to be changed to public
The second Guitar constructor is missing all it's parameters.
Enums need to be referenced by their name, you can't just type in their values.
Your curly braces were all over the place. There were way more closing than opening, so I deleted a bunch of them at the end and ones that were tossed into the middle of the class.
Methods must be within classes.
Enums can't be declared inside methods, only inside classes.
Variable declarations must have a space between the type and the name of the variable. Example: int_a; needs to be int a;
Your Duration enum has no constructor that accepts and int.
Getting a random value of an enum based on its index is done by doing Notes.values()[a];, not Notes[a];
No idea where the return Optional.empty(); line should be, so I deleted it.
You're missing the import for the Random class.
Strings can't be on multiple lines.
.orElse() is not a method. Deleted this, unsure what it was supposed to do.
colorName() is not a method. I changed it to: (this.guitarColor == null ? "none" : this.guitarColor.name()).
The name of the variable in the toString() method is not the same as what you try to return. I changed them both to infoString.
You have a TON of typos, namely with things like Manufacturer being Manufacur and return being rturn.
When initializing a variable, you must have a space after new.
Your getter methods do not return the correct type.
The name of the variable numString is repeatedly referred to as numStrings. I added the s to the original variable declaration.
Below are a list of things you really SHOULD change, but you don't need to change.
All enum names should be in ALL CAPS.
Method names should be written using camelCase. Example: myVal would have a getter named getMyVal().
Have blank lines between methods, constructors, and types.
Have a space after the start of a comment. Example: // Comment Bad Example: //Comment
Have some sort of sorting pattern for enums. For notes, it should be alphabetical.
There is no need to have another enum for the duration of notes. This can easily be done in the note itself.
There is no need to do String.valueOf(someObject) for concatenation. It is better to do someObject.toString() and best to just leave it as someObject because the runtime will do that operation for you.
There should be a space before and after arithmetic operators like + and -.
I would highly recommend you read up on some basic Java tutorials and look at the Google Java Style Guide. It is what I use and what I'm sure a lot of people use to determine how code should look.
With all the changes and with the proper use of style, your code looks like this:
import java.util.Random;
/*
* File: Guitar.java
* Author: Eppards,Michael
* Date: June 11, 2018
*/
class Guitar {
private int numStrings;
private double guitarLength;
private Color guitarColor;
private Manufacturer guitarManufacturer;
enum Manufacturer {
GIBSON,
FENDER,
IBANEZ;
}
enum Color {
RED,
BLUE,
BLACK;
}
enum Notes {
A(1),
B(4),
C(1),
D(2),
E(0.25),
F(0.5),
G(0.5);
double duration;
private Notes(double duration) {
this.duration = duration;
}
}
// Default Constructor
private Guitar() {
this.numStrings = 6;
this.guitarLength = 28.2;
this.guitarColor = Color.RED;
this.guitarManufacturer = Manufacturer.GIBSON;
}
// Argument Constructor
private Guitar(int numStrings, double guitarLength, Color guitarColor, Manufacturer guitarMaker) {
this.numStrings = numStrings;
this.guitarLength = guitarLength;
this.guitarColor = guitarColor;
this.guitarManufacturer = guitarMaker;
}
// Getters
public int getNumStrings() {
return numStrings;
}
public double getGuitarLength() {
return guitarLength;
}
public Color getGuitarColor() {
return guitarColor;
}
public Manufacturer getGuitarManufacturer() {
return guitarManufacturer;
}
// playGuitar method for 16 randomly selected musical notes
public String playGuitar() {
String play = "[";
int a;
int b;
// initiate a random number
Random rn = new Random();
// for loop to select random notes
for (int k = 0; k < 16; k++) {
a = rn.nextInt(7);
b = rn.nextInt(5);
play = play + Notes.values()[a] + "(" + Notes.values()[a].duration + ")";
if (k != 15) play = play + ",";
}
play = play + ']';
return play;
}
// used to return the info in a string
public String toString() {
String infoString = "(numStrings=" + this.numStrings + ", guitarLength=" + this.guitarLength + ",guitarManufacturer=" + this.guitarManufacturer + ",guitarColor=" + (this.guitarColor == null ? "none" : this.guitarColor.name()) + ")";
return infoString;
}
}
Hope this helps! Friendly reminder that I made a LOT of changes to this code. You really should go look at the steps I took and make the changes yourself, otherwise you could get in trouble with your school for submitting work that is not your own.

Java 8: No errors - Why is this for loop running forever and not showing anything?

My issue is with the following code. Eclipse IDE gives me no errors or warnings, yet when I print out a simple System.out.println("Test" + i);, I would get a running program up to the number 2509, or currently 2517 after rebooting Eclipse.
Essentially, I want to take an array of objects, say an array of "persons," and place them in random spots in another object array, say "bus stops." Assume that I have properly made the object arrays for "busStops and "people"
Yes, I realize that it defeats the purpose of making the "person" object as of yet, but that is something that can be included later.
Edit: Null values are simulated areas where people can't go, like a lake.
Edit2: replaced for with while loop, replaced decremented i with continue keyword.
Edit3: added more of the methods to elaborate the imperfections of my code. Then again, maybe most of it is good and I'm not understanding something important about loops.
private static void distributePeople() {
boolean temp = true;
int i = 0;
while (temp) {
// Select random points in array
int a = rand.nextInt(busStops.length);
int b = rand.nextInt(busStops[0].length);
// At random busStop, check if available and check if not full.
// If it is not full, place a person there.
if (busStops[a][b] == null) {
// if null, reset this run
continue;
} else {
if (busStops[a][b].isMaxPeople() == false) {
busStops[a][b].setNumberOfPeople(1);
i++;
System.out.println("Test: " + i);
} else {
// if true, reset this run
continue;
}
}
if (i == people.length) {
temp = false;
}
}
}
private static void setMaxPeopleAtBusStop() {
busStops[0][0].setMaxNumberOfPeople(1977 + 2);
busStops[1][0].setMaxNumberOfPeople(2 + 1643);
busStops[2][0].setMaxNumberOfPeople(1643 + 1201);
busStops[3][0].setMaxNumberOfPeople(1201 + 1267);
busStops[0][1].setMaxNumberOfPeople(366 + 0);
busStops[2][1].setMaxNumberOfPeople(0 + 797);
busStops[3][1].setMaxNumberOfPeople(797 + 34);
busStops[0][2].setMaxNumberOfPeople(1740 + 0);
busStops[2][2].setMaxNumberOfPeople(0 + 1444);
busStops[3][2].setMaxNumberOfPeople(1444 + 1963);
busStops[0][3].setMaxNumberOfPeople(839 + 1131);
busStops[1][3].setMaxNumberOfPeople(1131 + 1092);
busStops[2][3].setMaxNumberOfPeople(1092 + 912);
busStops[3][3].setMaxNumberOfPeople(912 + 1965);
busStops[0][4].setMaxNumberOfPeople(1552 + 1297);
busStops[1][4].setMaxNumberOfPeople(1297 + 1345);
busStops[2][4].setMaxNumberOfPeople(1345 + 614);
busStops[3][4].setMaxNumberOfPeople(614 + 1108);
busStops[0][5].setMaxNumberOfPeople(1490 + 228);
busStops[1][5].setMaxNumberOfPeople(228 + 187);
busStops[2][5].setMaxNumberOfPeople(187 + 906);
busStops[3][5].setMaxNumberOfPeople(906 + 36);
busStops[0][6].setMaxNumberOfPeople(634 + 1293);
busStops[1][6].setMaxNumberOfPeople(1293 + 0);
busStops[3][6].setMaxNumberOfPeople(0 + 1929);
busStops[0][7].setMaxNumberOfPeople(759 + 388);
busStops[1][7].setMaxNumberOfPeople(388 + 0);
busStops[3][7].setMaxNumberOfPeople(0 + 1149);
busStops[0][8].setMaxNumberOfPeople(1809 + 1880);
busStops[1][8].setMaxNumberOfPeople(1880 + 1979);
busStops[2][8].setMaxNumberOfPeople(1979 + 954);
busStops[3][8].setMaxNumberOfPeople(954 + 1332);
busStops[0][9].setMaxNumberOfPeople(1890 + 408);
busStops[1][9].setMaxNumberOfPeople(408 + 1771);
busStops[2][9].setMaxNumberOfPeople(1771 + 587);
busStops[3][9].setMaxNumberOfPeople(557 + 1961);
}
From the appropriate BusStop class:
static int MAX_PEOPLE_HERE;
public int setNumberOfPeople(int a) {
return numberOfPeopleHere += a;
}
protected boolean isMaxPeople() {
if (numberOfPeopleHere >= MAX_PEOPLE_HERE) {
return true;
} else {
return false;
}
}
public void setMaxNumberOfPeople(int a) {
MAX_PEOPLE_HERE = a;
}
Note: I should have a max number of 13000 people, which is smaller than the room available above.
Ok so your problem is that you're using a static variable for MAX_PEOPLE_HERE but you're trying to use it in a non static way. Thus ever time you call setMaxNumberOfPeople on any bus stop you set it for all bus stops.
This means that MAX_PEOPLE_HERE will end up being 557 + 1961 = 2518.
I'm guessing that numberOfPeopleHere is also static and thus you can only ever 2518 people to bus stops. If you try to do more than this then you'll end up with an infinite loop as you are seeing.
Change both MAX_PEOPLE_HERE (rename this to maxPeopleHere) and numberOfPeopleHere to local instance variables and I suspect everything will start working.
Use continue instead of i-- to skip current iteration. As #Hovercraft Full Of Eels stated, you've got infinite loop because of index modification within the loop

Extended class issues

I have had some issues involving code that accesess variables defined in a superclass that were later revised in a child class. Ie
//start of Stat class. Variables in question are defined here. (Name, Level, Experience, totalXP)
public class Stat {
public static String Name = " ";
public static int Level = 0;
public static double Experience = 0;
public static double totalXP = 0;
//Sets Name
public static void setName(String NameIn) {
Name = NameIn;
}
//Sets Level
public static void setLevel(int LevelIn) {
Level = LevelIn;
}
//Sets Experience
public static void setExperience(double ExperienceIn) {
Experience = ExperienceIn;
}
//Sets totalXP
public static void settotalXP(double totalXPIn) {
totalXP = totalXPIn;
}
//Sets up Attributes
public static void setall() {
setName("Herp");
setLevel(1);
setExperience(0);
settotalXP(0);
}
//Displays a Stat's Attributes
public static void DisplayLevel() {
System.out.println(Name);
System.out.println("Level: " + Level);
System.out.println(Experience + " out of " + totalXP + " total experience.");
}//End of method
public static void Levelup() {
if(Experience >= totalXP) {
Level++;
totalXP = totalXP * 1.3;
Experience = 0;
}//end of if statement
}//end of Levelup method
}//end of Stat.class
public class Agility extends Stat{
{//Revisionary Block
Name = "Agility";
Level = 1;
Experience = 0;
totalXP = 125;
}
public static int runnappDodge(int Dodge) {
Random generator = new Random(10);
Dodge = generator.nextInt(10);
if (Dodge == 0) {
Player.incomingDMG = 0;
}//end of if statement
return Dodge;
}
//start of the method located on player.class. This prints out " ", 0.0 and 0.0 for all //of the fields.
public static void checkLevel() {
System.out.println("You are level: " + Level);
System.out.println("You have " + experience + " experience out of " + totalXP + " total experience");
System.out.println(stat.Attack.Name + " Level: " + stat.Attack.Level + ": Experience: " + stat.Attack.Experience + "/" + stat.Attack.totalXP);
System.out.println(stat.Archery.Name +" Level: " + stat.Archery.Level +": Experience: " + stat.Archery.Experience + "/" + stat.Archery.totalXP);
System.out.println(stat.Agility.Name +" Level: " + stat.Agility.Level + ": Experience: " + stat.Agility.Experience + "/" + stat.Agility.totalXP);
}//end of checkLevel method
my full code is here: http://pastebin.com/6nPGwJQe
reddit was no help so I now turn to you. (not that you arent helpful, but I just use reddit more so it is more convenient). I think that my code should be updating the variables in the subclasses but it doesnt. When I refrence the variable it ends up being excactly what it was when defined by super class, in Aaron.name's case, " " rather than "Aaron". I'm not sure if a getter and setter might be useful here, but I appreciate all advice
PS: My first question on stackoverflow!
Edit: Thanks for the feedback. This was example code. The last commenter helped out a lot, but my real code is entirely independent from this. It was to convey an example. So please see the link because that code is really what matters.
Edit 2: Because I can see that one might need to see the structure of my project for imports and references sake, here is an image of my project structure: http://imgur.com/VhDzRrm
Edit 3: No longer does my post use an example that is incorrect, it uses my actual code.
Java is very clear about case-sensitivity. Since you have extended the Derp class your Aaron class now has two String fields. name and Name. That is why it is displaying nothing, because you have instantiated your name String to "". if you replaced it with Aaron.Name you will have what you are looking for.
I'll go over a few issues in your code.
First obviously, it doesn't compile, as others have pointed out. You should take your actual code and strip out anything that's not germane to the problem. Keep stripping until your sample code is as small as what you posted here, but make sure it still compiles. See http://sscce.org/
Odds are, you'll find the bug as you go, in which case post your own answer to the question (yes, you can do that). If not, edit your question with the actual code.
Now, to address your issues:
There was no need to use an anonymous constructor for Aaron. It should have been
public class Aaron extends Derp {
public Aaron() { Name = "Aaron"; IQ = 10; }
}
(Something tells me you're coming from a C++ background.)
"name" is an instance variable, which means that it only exists as part of an object of type Derp (or Aaron). You first need to create an object, then reference that.
public static void main() {
Aaron aaron = new Aaron();
System.out.println("Hi, my name is: " + aaron.name + "!\n");
}
You could also have made name a class variable:
static String name = " ";
but there's no good way to override that variable in a subclass, so we won't go there.
One final nit: you didn't need that "\n" in the println() call, since that function appends a newline for you.

Class to count variables design issue

I'm new to OO programing and having a bit of trouble with the design of my program to use the concepts. I have done the tutorials but am still having problem.
I have a recursion that takes a value of items(could be anything in this example, stocks) and figures out what number of them are needed to equal a specific value(in this code 100). This part works but I want to know if a stock's weighting exceeds a threshold. Originally I approached this problem with a method that did a for loop and calculated the entire list of values but this is super inefficient because its doing it on every loop of the recursion. I thought this would be a good time to try to learn classes because I could use a class to maintain state information and just increment the value on each loop and it'll let me know when the threshold is hit.
I think I have the code but I don't fully understand how to design this problem with classes. So far it runs the loop each step of the recursion because I'm initially the class there. Is there a better way to design this? My end goal is to be notified when a weighting is exceeded(which I can somewhat already do) but I want to do in way that uses the least bit of resources(avoiding inefficient/unnecessary for loops)
Code(Here's the entire code I have been using to learn but the problem is with the Counter class and its location within the findVariables method):
import java.util.Arrays;
public class LearningClassCounting {
public static int[] stock_price = new int[]{ 20,5,20};
public static int target = 100;
public static void main(String[] args) {
// takes items from the first list
findVariables(stock_price, 100, new int[] {0,0,0}, 0, 0);
}
public static void findVariables(int[] constants, int sum,
int[] variables, int n, int result) {
Counter Checker = new Counter(stock_price, variables);
if (n == constants.length) {
if (result == sum) {
System.out.println(Arrays.toString(variables));
}
} else if (result <= sum){ //keep going
for (int i = 0; i <= 100; i++) {
variables[n] = i;
Checker.check_total_percent(n, i);
findVariables(constants, sum, variables, n+1, result+constants[n]*i);
}
}
}
}
class Counter {
private int[] stock_price;
private int[] variables;
private int value_so_far;
public Counter(int[] stock_price, int[] variables) {
this.stock_price = stock_price;
this.variables = variables;
for (int location = 0; location < variables.length; location++) {
//System.out.println(variables[location] + " * " + stock_price[location] + " = " + (variables[location] * stock_price[location]) );
value_so_far = value_so_far + (variables[location] * stock_price[location]);
}
//System.out.println("Total value so far is " + value_so_far);
//System.out.println("************");
}
public void check_total_percent(int current_location, int percent) {
// Check to see if weight exceeds threshold
//System.out.println("we are at " + current_location + " and " + percent + " and " + Arrays.toString(variables));
//System.out.println("value is " + stock_price[current_location] * percent);
//formula I think I need to use is:
if (percent == 0) {
return;
}
int current_value = (stock_price[current_location] * percent);
int overall_percent = current_value/(value_so_far + current_value);
if (overall_percent > 50 ) {
System.out.println("item " + current_location + " is over 50%" );
}
}
}
What you're describing sounds like a variant of the famous knapsack problem. There are many approaches to these problems, which are inherently difficult to calculate.
Inherently, one may need to check "all the combinations". The so-called optimization comes from backtracking when a certain selection subset is already too large (e.g., if 10 given stocks are over my sum, no need to explore other combinations). In addition, one can cache certain subsets (e.g., if I know that X Y and Z amount to some value V, I can reuse that value). You'll see a lot of discussion of how to approach these sort of problems and how to design solutions.
That being said, my view is that while algorithmic problems of this sort may be important for learning how to program and structure code and data structures, they're generally a very poor choice for learning object-oriented design and modelling.

Categories