Split Temporary Variable Refactoring Example - java

I'm preparing for my exams and I stumbled across a weird previous year actual exam question:
Perform Split Temporary Variable Refactoring on this piece of code:
public int createUniqueCasenumber (GregorianCalendar date, int departmentID) {
int temp = 0;
temp = date.get(GregorianCalendar.DAY_OF_MONTH);
temp = temp * 100;
temp = temp + date.get(GregorianCalendar.MONTH);
temp = temp * 100;
temp = temp + date.get(GregorianCalendar.YEAR);
temp = temp * 100;
temp = temp + (date.get(GregorianCalendar.HOUR_OF_DAY) * departmentID);
return temp;
}
Now I understand the Split Temporary Variable Refactoring as a case when a temp variable is used for different purposes and we simply "rename" it into two different making-sense-names.
But in this situation I can't really thinks of smart names, the function of this temp variable is rather similar to a loop collecting variable.
The only thing remotely close to the required refactoring would be:
public int createUniqueCasenumber (GregorianCalendar date, int departmentID) {
int result= 0;
int firstStep = 100 * date.get(GregorianCalendar.DAY_OF_MONTH);
int secondStep = 100 * (firstStep + date.get(GregorianCalendar.MONTH));
int thirdStep = 100 * (secondStep + date.get(GregorianCalendar.YEAR));
result = thirdStep + (date.get(GregorianCalendar.HOUR_OF_DAY) * departmentID);
return result;
}
But why would you do it "in real life" ? Or is there some deep meaning I don't see?
Any thoughts?
Thank you in advance :)

Your refactoring is incorrect; each -step variable does not depend on any of the others (note that each assignment to temp from a date.get overwrites what was there before). Also makes it clear that all of the assignments except the last, and all of the multiplications by 100, are useless.
This refactoring makes it clear that these values are independent, and could be assigned in any order (even in parallel, if that were allowed).

You can refactor this code in 2 steps
If you look closely, you may notice, that day multyplied by 100 three times, month - twice and year - once
So you can rewrite code in this manner:
public int createUniqueCasenumber(GregorianCalendar date, int departmentID) {
int temp = date.get(GregorianCalendar.DAY_OF_MONTH) * 100 * 100 * 100;
temp += date.get(GregorianCalendar.MONTH) * 100 * 100;
temp += date.get(GregorianCalendar.YEAR) * 100;
temp += date.get(GregorianCalendar.HOUR_OF_DAY) * departmentID;
return temp;
}
After that it's much easier to split temp variable:
public int createUniqueCasenumber(GregorianCalendar date, int departmentID) {
int magnifiedDay = date.get(GregorianCalendar.DAY_OF_MONTH) * 100 * 100 * 100;
int magnifiedMonth = date.get(GregorianCalendar.MONTH) * 100 * 100;
int magnifiedYear = date.get(GregorianCalendar.YEAR) * 100;
int magnifiedHour = date.get(GregorianCalendar.HOUR_OF_DAY) * departmentID;
return magnifiedDay + magnifiedMonth + magnifiedYear + magnifiedHour;
}

Related

How to the "decision/path" during recursion?

I want to calculate the minimal costs in production by choosing lot sizes with recursion. The value I get is correct, but I also want to save the correct decisions/path(how much to produce in each period n). I don't know how to save it correctly. This way I just overwrite it everytime.
n = period, i = inventory, pcap = production capacity, demand[n] = how much i sell in period n,
Thanks!
public double getMinC(int n, int i) {
if(demand[n]-i > pcap) return Double.MAX_VALUE;
if(this.n == n) {
if(demand[n] < i) { //not sure if i need this
decision[n] = 0;
return storagecost * i-demand[n];
}
decision[n] = demand[n]-i;
return varc * demand[n]-i + fixc;
}
double min = Double.MAX_VALUE;
double cost = min;
int xmin = Math.max(0, demand[n] - i);
int xmax = Math.min(storagecap-i+demand[n], pcap);
int bestx = -1;
for(int x=xmin; x<=xmax; x++) {
cost = getMinC(n+1, i+x-demand[n]) + storagecost * (i+x-demand[n]);
if(x!=0) cost += fixc + varc * x;
if(cost< min) {
min = cost;
bestx = x;
}
}
decision[n] = bestx;
return min;
}
Your function should return both the value of the best decision along with the set of values that lead to that best solution. Something like:
struct solution {
double min;
int *decision;
}
This code:
cost = getMinC(n+1, i+x-demand[n]) + storagecost * (i+x-demand[n]);
if(x!=0) cost += fixc + varc * x;
if(cost< min) {
min = cost;
bestx = x;
}
should be changed to:
sol = getMinC(n+1, i+x-demand[n]) + storagecost * (i+x-demand[n]);
if(x!=0) cost += fixc + varc * x;
if ( sol.min< minsol.min) {
minsol.min = sol.min;
minsol.decision=malloc (n, sizeof (int));
minsol.decision [0]=x;
// Copy content of sol.decision into minsol.decision starting at index 1
}
...
...
return minsol;
Note that you need to take care of deallocating the returned solution structure and take care of allocating a new solution structure to be returned. A more efficient way would be to return a linked list instead of the array within the solution struct and append minx to the returned linked list of decisions.
This is in no way complete but I hope you got the idea.

How can I use an array variable to IF statement?

I am developing a simple Taxi Meter Calculator system. I have no idea what to use to implement it. I have written a code but got stuck at IF statement where I had to insert an array variable. I am not sure whether this is the correct way to implement it.
This is the logic.
The first Km is 50/-.
Then the next 10Km will be charged 45/- per Km. eg : if 2km were gone
, charges would be 50/- + 45/- = 95/-, if 3km were gone 140/-.
The next 10km will be charged 35/- per km
25/- per km will be charged no matter how many kms gone after the above 10km exceed.
This is the code I have coded so far
private void btn_calActionPerformed(java.awt.event.ActionEvent evt) {
int kms1 = 50;
int kms2 = 45;
int kms3 = 35;
int kms4 = 25;
String[] firstkm={"3,4,5,6,7,8,9,10,11"};
if(txt_km.getText().equals("1")){
lblout.setText(""+kms1);
}
if(txt_km.getText().equals("2")){
lblout.setText(""+(kms1+kms2));
}if(txt_km.getText().equals(firstkm)){
int get = Integer.parseInt(txt_km.getText());
int rate = get+kms2;
lblout.setText(""+rate);
}
}
if there is any other method to solve this problem please mention it.
int fare = 0;
int distance = 0;
if (distance > 21) {
fare += (distance - 21) * 25;
distance = 21;
}
if (distance > 11) {
fare += (distance - 11) * 35;
distance = 11;
}
if (distance > 1) {
fare += (distance - 1) * 45;
distance = 1;
}
if (distance > 0) {
fare += distance * 50;
}
Then refactor by putting the magic numbers into arrays and loop through the arrays (4 times).
Here's a hint: Implement this method
/**
This method returns the amount a passenger must pay for this kilometer of their trip
*/
public int chargeForKilometer(int kilometerNumberInTrip) {
//...
}
try
String[] firstkm={3,4,5,6,7,8,9,10,11};
if(txt_km.getText().equals(firstkm[1])){
lblout.setText(""+kms1);
}
....
In case your conditions change and you want to avoid adding if conditions in your code, I wrote a configurable code.
public int calculateRate(int kmCount){
int baseRate = 50;
int[] stepRate = {45,35};
int step = 10;
int fare = 0;
int threshold = 21;
int beyondThresholdRate = 25;
if(kmCount>0){
fare = baseRate;
fare += (kmCount - threshold)<0?0:(kmCount - threshold)*beyondThresholdRate;
kmCount = kmCount - 1;
for(int i=0;i<=((kmCount/step) + (kmCount%step>0?1:0));i++){
fare += (kmCount/step)==0?(kmCount%step)*stepRate[i]:step*stepRate[i];
kmCount -=step;
if(i==stepRate.length-1) break;
}
}
return fare;
}
It is slightly complex, however, flexible.

Find closest number in array to a number not in the array

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];

Math.random() not working properly when using return

I have a program in which I want an object to return a value between two numbers. But the problem is that most of the time, the numbers I get are not in the boundaries. Here's the code:
public int getSize() {
int s = (int)Math.random() * (max - min) + min;
return s;
}
min and max are both defined in the code as 320 and 640, but i sometimes get values which are lower than what I need (for example I once got 283), and sometimes higher. Could anyone help please?
I don't see how you could possibly get 283 if min/max are 320/640.
That said, there is a bug in your code that would make it always return min. To fix it, use the following:
int s = (int)(Math.random() * (max - min) + min);
Note the added parentheses. Without them, you're casting the result of Math.random() to int. This always gives zero, making the entire expression evaluate to min.
if you have access to C#, can you try the following? This is functionally equivalent to your task and should not generate numbers outside of 320 and 640 range. If this is so, you can compare logic of your Java code with it to see where you make a mistake.
namespace TestRand
{
class TestRand
{
private static Random r;
private const int min = 320;
private const int max = 640;
public static void Main()
{
r = new Random();
for (int i = 0; i < 1000; i++)
{
Console.WriteLine("{0} - {1}", i, getSize());
}
}
public static int getSize()
{
int s = (int)(r.NextDouble() * (max - min)) + min;
return s;
}
}
}

Efficient implementation of mutual information in Java

I'm looking to calculate mutual information between two features, using Java.
I've read Calculating Mutual Information For Selecting a Training Set in Java already, but that was a discussion of if mutual information was appropriate for the poster, with only some light pseudo-code as to the implementation.
My current code is below, but I'm hoping there is a way to optimise it, as I have large quantities of information to process. I'm aware that calling out to another language/framework may improve speed, but would like to focus on solving this in Java for now.
Any help much appreciated.
public static double calculateNewMutualInformation(double frequencyOfBoth, double frequencyOfLeft,
double frequencyOfRight, int noOfTransactions) {
if (frequencyOfBoth == 0 || frequencyOfLeft == 0 || frequencyOfRight == 0)
return 0;
// supp = f11
double supp = frequencyOfBoth / noOfTransactions; // P(x,y)
double suppLeft = frequencyOfLeft / noOfTransactions; // P(x)
double suppRight = frequencyOfRight / noOfTransactions; // P(y)
double f10 = (suppLeft - supp); // P(x) - P(x,y)
double f00 = (1 - suppRight) - f10; // (1-P(y)) - P(x,y)
double f01 = (suppRight - supp); // P(y) - P(x,y)
// -1 * ((P(x) * log(Px)) + ((1 - P(x)) * log(1-p(x)))
double HX = -1 * ((suppLeft * MathUtils.logWithoutNaN(suppLeft)) + ((1 - suppLeft) * MathUtils.logWithoutNaN(1 - suppLeft)));
// -1 * ((P(y) * log(Py)) + ((1 - P(y)) * log(1-p(y)))
double HY = -1 * ((suppRight * MathUtils.logWithoutNaN(suppRight)) + ((1 - suppRight) * MathUtils.logWithoutNaN(1 - suppRight)));
double one = (supp * MathUtils.logWithoutNaN(supp)); // P(x,y) * log(P(x,y))
double two = (f10 * MathUtils.logWithoutNaN(f10));
double three = (f01 * MathUtils.logWithoutNaN(f01));
double four = (f00 * MathUtils.logWithoutNaN(f00));
double HXY = -1 * (one + two + three + four);
return (HX + HY - HXY) / (HX == 0 ? MathUtils.EPSILON : HX);
}
public class MathUtils {
public static final double EPSILON = 0.000001;
public static double logWithoutNaN(double value) {
if (value == 0) {
return Math.log(EPSILON);
} else if (value < 0) {
return 0;
}
return Math.log(value);
}
I have found the following to be fast, but I have not compared it against your method - only that provided in weka.
It works on the premise of re-arranging the MI equation so that it is possible to minimise the number of floating point operations:
We start by defining as count/frequency over number of samples/transactions. So, we define the number of items as n, the number of times x occurs as |x|, the number of times y occurs as |y| and the number of times they co-occur as |x,y|. We then get,
.
Now, we can re-arrange that by flipping the bottom of the inner divide, this gives us (n|x,y|)/(|x||y|). Also, compute use N = 1/n so we have one less divide operation. This gives us:
This gives us the following code:
/***
* Computes MI between variables t and a. Assumes that a.length == t.length.
* #param a candidate variable a
* #param avals number of values a can take (max(a) == avals)
* #param t target variable
* #param tvals number of values a can take (max(t) == tvals)
* #return
*/
static double computeMI(int[] a, int avals, int[] t, int tvals) {
double numinst = a.length;
double oneovernuminst = 1/numinst;
double sum = 0;
// longs are required here because of big multiples in calculation
long[][] crosscounts = new long[avals][tvals];
long[] tcounts = new long[tvals];
long[] acounts = new long[avals];
// Compute counts for the two variables
for (int i=0;i<a.length;i++) {
int av = a[i];
int tv = t[i];
acounts[av]++;
tcounts[tv]++;
crosscounts[av][tv]++;
}
for (int tv=0;tv<tvals;tv++) {
for (int av=0;av<avals;av++) {
if (crosscounts[av][tv] != 0) {
// Main fraction: (n|x,y|)/(|x||y|)
double sumtmp = (numinst*crosscounts[av][tv])/(acounts[av]*tcounts[tv]);
// Log bit (|x,y|/n) and update product
sum += oneovernuminst*crosscounts[av][tv]*Math.log(sumtmp)*log2;
}
}
}
return sum;
}
This code assumes that the values of a and t are not sparse (i.e. min(t)=0 and tvals=max(t)) for it to be efficient. Otherwise (as commented) large and unnecessary arrays are created.
I believe this approach improves further when computing MI between several variables at once (the count operations can be condensed - especially that of the target). The implementation I use is one that interfaces with WEKA.
Finally, it might be more efficient even to take the log out of the summations. But I am unsure whether log or power will take more computation within the loop. This is done by:
Apply a*log(b) = log(a^b)
Move the log to outside the summations, using log(a)+log(b) = log(ab)
and gives:
I am not mathematician but..
There are just a bunch of floating point calculations here. Some mathemagician might be able to reduce this to fewer calculation, try the Math SE.
Meanwhile, you should be able to use a static final double for Math.log(EPSILON)
Your problem might not be a single call but the volume of data for which this calculation has to be done. That problem is better solved by throwing more hardware at it.

Categories