Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I was asked in an interview to implement a business rule
Requirements change. They always do:
assess a 20% fee for any amount below $100,000.
assess a 10% fee for any amount between $100,000 and $500,000.
assess a 5% fee for any amount above $500,000
Calculate the fee for an arbitrary amount x.
Example: Given a $600,000 invoice the fee should be $65,000.
Given a $50,000 invoice the fee should be $10,000.
Given a $200,000 invoice the fee should be $30,000.
I used CofR but the interviewer then asked what if their is more than 3 conditions like n of them would i create n-classes to handle each request.
Is their a better approach to the question asides writing a very long recursive function checking for each of the conditions.
CoR is helpful when the members of the chain have substantially different rules, but in this case, all of the rules are basically the same (charge a certain percent if the amount is over X). Instead of independent classes, just have one struct-like class that holds the minimum amount and percentage, and another one that looks up the appropriate fee:
class FeeSchedule {
static class Entry implements Comparable<Entry> {
int threshold;
int percentage;
int compareTo(Entry other) {
// sort by percentage, descending
}
SortedSet<Entry> feeTable;
int calculateFee(int invoiceAmount) {
for(Entry e : feeTable)
if(invoiceAmount > e.threshold)
return (invoiceAmount * e.percentage);
// error condition; return 0?
}
}
I would guess that the interviewer was implying that something like the chain-of-responsibility pattern would be a little over-engineered for a problem like this. There's also an argument that your implementing classes would actually have the same responsibility, in that they'd all be computing an amount based on a given input, just with different parameters.
I would probably do this with two simple classes. One would compute the percentage fee rate based on the input value and one would use this rate to return the fee amount.
If you need to add a fourth condition, you just add it to the class containing the rate computation. I don't see why it needs to be any more complicated than this for such a simple problem.
EDIT:
I was thinking along the same lines as #chrylis in that there'd be a class to perform the calculation by processing an ordered list of rates.
class Rate {
int rangeSize;
double commission;
Rate(int rangeSize, double commission){
this.rangeSize = rangeSize;
this.commission = commission;
}
int computeForAmount(int amount) {
if (amount <= 0) {
return 0;
}
return (int) (Math.min(amount, this.rangeSize) * this.commission);
}
}
class FeeCalculator {
List<Rate> rates = Arrays.asList(
new Rate(100, 0.2),
new Rate(400, 0.1),
new Rate(500, 0.05));
int calculateCommission(int startingAmount) {
int commission = 0;
int remainingAmount = startingAmount;
for (Rate rate : this.rates) {
commission += rate.computeForAmount(remainingAmount);
remainingAmount -= rate.rangeSize;
}
return commission;
}
}
I admit that I'm not entirely happy about breaking the encapsulation by calling rate.rangeSize but it does demonstrate the design I was trying to articulate.
I think a simple strategy pattern should be enough in this case. Something like:
interface FeeAssessor {
public double assessFee(double invoice);
}
FeeAssessor feeAssessor = new FeeAssessor() {
// logic goes here
};
double calculateFee(double invoice) {
return feeAssessor.assessFee(invoice);
}
For a simple business logic that you presented, I think it would be simpler to implement it all inside one assessFee() function. You can implement different (simple) ones and swap out the "strategy" object as needed. If the fee assessment algorithm depends on multiple varying factors that are independent of each other, then you can further split them up into multiple strategy methods.
Related
Assume that you are in exam and you have 120 minutes but you can't solve the questions because you have a limited time. For example, the points and time to be needed to complete the question is below.
enter image description here
So we need to design the most efficient algorithm using dynamic programming approach for calculating highest point you will take in available time.
Here is my code below;
static int maxPoints(int points[], int time[],int n) {
if(n<=0) {
return 0;
}
else {
return Math.max(points[n-1]+maxPoints(points,time,(n-2)),
time[n - 1] + maxPoints(points, time, (n - 1)));
}
}
public static void main(String[] args) {
int n=10;
int points[]= {4,9,5,12,14,6,12,20,7,10};
int time[]= {1,15,2,3,20,120};
System.out.println();
}
But i couldn't find the correct algorithm, can you help me with this problem?
In your question, each question has a weight (the amount of time it needs) and a value (the points it awards). There is a constraint on the total time (or weight) and you need to maximise the points (or value).
This becomes analogous to the 0-1 Knapsack Problem, which can easily be solved using dynamic programming.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
The code doesn't work right the program runs both if statements and the total never comes out right. I can't figure out whats wrong. what changes do i need to make for this to work? the directions are below.
The cost to become a member of a fitness center is as follows: (a) the Senior
citizens discount is 30%; (b) if the membership is bought and paid for 12 or
more months in advance, the discount is 15%; or (c) if more than 5 personal
training sessions are purchased, the discount on each session is 20%.
Write a menu driven program that determines the cost of a new membership.
Your program must contain a method that displays the general information about
the fitness center and its charges, a method to get all the necessary information
to determine the membership cost, and a method to determine the membership
cost. Use appropriate parameters to pass information in and out of a method.
what methods should i use?
double grossdiscount1,grossdiscount2,grossdiscount3;
double grossprice1,grossprice2,grossprice3;
//end result of box calculation
double answerbox1,answerbox2,answerbox3;
double answerbox1b,answerbox2b,answerbox3b;
//Jtext inputs
double box1,box2,box3;
double discount1 = 0.30 ;
double discount2 = 0.20 ;
double discount3 = 0.15 ;
// prices PT=personal training MT=montly price
double pricePT =50.00;
double priceMT =100.00;
box1 = Double.parseDouble(jTextField1.getText());
box2 = Double.parseDouble(jTextField2.getText());
box3 = Double.parseDouble(jTextField3.getText());
// i brought these out of the if statement because the program won't run without
// them being stated
answerbox1b=box1*100;
grossdiscount1=(box1*priceMT)*discount3;// the amount saved
grossprice1=(box1*priceMT);
answerbox1=(grossprice1-grossdiscount1);
answerbox2b=(box2*pricePT);
grossdiscount2=(box2*pricePT)*discount2;// the amount saved
grossprice2=(box2*pricePT);
answerbox2=(grossprice2-grossdiscount2);
double total = answerbox1+answerbox2+answerbox1b+answerbox2b;
grossdiscount3=(total*discount3);// the amount saved
grossprice3=total;
answerbox3=(grossprice3-grossdiscount3);
if(box1<11 )
{
answerbox1b=box1*100;
}
else if(box1>12)
{
grossdiscount1=(box1*priceMT)*discount3;// the amount saved
grossprice1=(box1*priceMT);
answerbox1=(grossprice1-grossdiscount1);
}
if(box2<5 )
{
answerbox2b=(box2*pricePT);
}
else if(box2>=5)
{
grossdiscount2=(box2*pricePT)*discount2;// the amount saved
grossprice2=(box2*pricePT);
answerbox2=(grossprice2-grossdiscount2);
}
if(box3==1 )
{
grossdiscount3=(total*discount3);// the amount saved
grossprice3=total;
answerbox3=(grossprice3-grossdiscount3);
}
else if(box3==0);
{
}
jTextField4.setText(String.valueOf(total));
The else if statements are not written correctly. Remove the ; for a correct flow.
And I also recommend you to check any of the threads related to comparing doubles in Java
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I am working on a discount requirement, where the user should be given discount based on his order amount.
For example,
Order 1000 to 5000 items - give 10% discount
Order 5000 to 10000 items - give 15% discount
Order 10000 to 15000 items - give 20% discount
These are the details I have in my database.
What is the best way to find the discount percent based on my order amount. I have tried setting these in a List of object and iterate them and find in what range it belongs and then get that percent.
But this seems to be a long approach. Please let me know if there is any better approach than this.
This is my Java solution. Totally agree if you want to do it direct with SQL. But either way, here's some codez! :)
I would use a LinkedHashMap of key "Amounts" with value "Discounts". It's Linked so that it maintains order when you iterate over it, from highest to lowest. If your value is >= the iterated key Amount, apply the value Discount and break out of the loop.
Map<Integer,Integer> map = new LinkedHashMap<>();
public void discount() {
map.put(10000,20);
map.put(5000,15);
map.put(1000,10);
System.out.println(discount(11000));
System.out.println(discount(5100));
System.out.println(discount(1100));
System.out.println(discount(100));
}
private int discount(int value) {
for (Map.Entry<Integer,Integer> entrySet : map.entrySet()) {
if (value >= entrySet.getKey()) {
return entrySet.getValue();
}
}
return 0;
}
Results… (it assumes that anything above 10000 is 20%)
20
15
10
0
Use the database. Assuming it's SQL:
Table DISCOUNTS
MIN MAX REDUCTION
--- --- -------
1000 5000 10
5001 10000 15
10001 150000 25
SQL Query
select reduction
from discounts
where #amount between MIN and MAX
Is this a business app, you are going to write or just an example app?
In case, it is just an example app:
Why not implementing a fallthrough method:
int getDiscount(int amount){
if (amount >= 10000 && amount <= 15000) return 20;
if (amount >= 5000) return 15;
if (amount >= 1000) return 10;
return 0;
}
Pro:
it's easy to implement
if there is a change in the group, it is easy adaptable
Con:
it has too many magical numbers
First refactoring:
int getDiscount(int amount){
if (isDiscountGroupA) return 20;
if (isDiscountGroupB) return 15;
if (isDiscountGroupC) return 10;
return 0;
}
bool isDiscountGroupA(int amount){
if (amount >= 10000 && amount <= 15000) return true;
}
bool isDiscountGroupB(int amount){
if (amount>5000) return true;
}
bool isDiscountGroupC(int amount){
if (amount>1000) return true;
}
Pro:
better readable
Con:
still has magic numbers in it.
Second refactoring:
public enum DiscountRanges {
DISCOUNTGROUPAUPPERBOUND(15000),
DISCOUNTGROUPALOWERBOUND(10000),
DISCOUNTGROUPBLOWERBOUND(5000),
DISCOUNTGROUPCLOWERBOUND(1000);
private final int boundary;
DiscountRanges(int boundary) { this.boundary=boundary; }
public int getValue() {return boundary;};
}
So DiscountRanges.GROUPCLOWERBOUND.getValue() gives you the value for group C.
Pro:
Magic numbers are encapsulated in an enum.
Con:
none so far
A JAVA8 solution:
public class DiscountCalculator {
Map<Predicate<Integer>, Integer> rules=new LinkedHashMap<Predicate<Integer>, Integer>();
Integer getDiscount(int amount){
Optional<Integer> o= rules
.entrySet()
.stream()
.filter(x->x.getKey().test(amount))
.map(x->x.getValue())
.findFirst();
return (o.isPresent())?o.get():0;
}
public DiscountCalculator() {
rules.put(x -> x >= 10000 && x < 15000, 20);
rules.put(x -> x >= 5000, 15);
rules.put(x -> x >= 1000, 10);
}
}
Pro:
since these are lambdas you are free to design complex predicate, not only checking bounds; e.g. you could include modulo-arithmetic to create more complex scales. Perhaps much nicer to code than to design a complex query.
Con:
But if these ranges are already in the DB, there is no need to hardcode them at all.
If you already have the conditions (in an easy queryable way) in the database, #Dave's answer suits your needs best: simply select it rom the DB.
I have a task to sort search results not only by relevance of string fields of indexed documents, but also by distance from a given geographical point to a point associated with each document being indexed. It should be mentioned that only top-ten or so matched documents should be included into a result set. Also it's not important to sort by precise distance, only kind of "distance levels" from the given point are important.
Technically I have successfully implemented the task. The geographical part of the task was implemented as a CustomScoreQuery-derived class:
private static class DistanceQuery extends CustomScoreQuery {
public DistanceQuery(final Query _subQuery, final SpatialStrategy _strategy, final Point _bp) {
super(_subQuery, new FunctionQuery(_strategy.makeDistanceValueSource(_bp)));
}
#Override
protected CustomScoreProvider getCustomScoreProvider(AtomicReaderContext _context) throws IOException {
return new CustomScoreProvider(_context) {
#Override
public float customScore(int _doc, float _subQueryScore, float _valSrcScore) throws IOException {
// the spatial strategies makeDistanceValueSource creates a ValueSource which score varies from almost 0 for nearby points to 2.7-2.8 for distant points
// so I voluntarily chosen 2 as the normalization factor and increase subQueryScore for that factor at max;
logger.debug("customScore for document {}: [subQuery={}, valScore={}", this.context.reader().document(_doc).getField(IndexedField.id.name()).numericValue().toString(), _subQueryScore, _valSrcScore);
return (_valSrcScore > 2 || _valSrcScore < 0) ? _subQueryScore : _subQueryScore + (2 - _valSrcScore);
}
};
}
}
and wrap a given "textual" query with this geospatial "enhancement".
Generally speaking the chosen strategy gives me pretty reasonable results. As one may see, the final score just slightly exceeds the initial query score (by 2 at max). And with typical results scores of a dozen and more, this geospatial addition works just as a way to "post-sort" otherwise similar documents.
With few hundreds or thousands test documents in the index, performance of the wrapped query was also good enough. It's about 10-50 milliseconds per search and this is just 2-5 times slower than an unwrapped query.
But when I switched from a test to a real-world DB and the number of documents in the index raised from a thousand to approximately 10 millions and is going to increase even more (with an estimation of a hundred millions in a near future), then the situation have changed dramatically. Actually I can't get any search results anymore because JVM goes out of memory and processor. Currently it can't finish the search in JVM with -Xmx6g and more.
Certainly I could buy a better hardware for the task, but the problem is likely to be solved by choosing a more appropriate sorting strategy.
One solution is to completely avoid geo-sorting provided by Lucene and manually sort top N items of the result set if items relevance scores are similar. And I'm going to choose this way if nothing else helps.
But my question is whether more adequate solutions exist. Maybe I can somehow split result items by classes of equivalence (with same or similar enough scores) and apply geo-spatial sorting only to first few classes? Please suggest.
Look at how elasticsearch implements this in the function_score query. You can probably reuse a few things from what they do. If I remember correctly, they can optionally use faster but less accurate distance calculation algorithms as well. You probably want to do something similar.
I'm using another CustomScoreProvider for DistanceQuery:
public class DistanceQueryScoreProvider extends CustomScoreProvider {
private double x;
private double y;
public DistanceQueryScoreProvider(LeafReaderContext context, double x, double y) {
super(context);
this.x = x;
this.y = y;
}
#Override
public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
Document d = context.reader().document(doc);
double geomX = d.getField(Consts.GEOM_X_FIELD).numericValue().doubleValue();
double geomY = d.getField(Consts.GEOM_Y_FIELD).numericValue().doubleValue();
double deglen = 110.25;
double deltaX = geomY - y;
double deltaY = (geomX - x) * Math.cos(y);
return -Double.valueOf(deglen * Math.sqrt(deltaX * deltaX + deltaY * deltaY)).floatValue();
}
}
Elasticsearch implementation of plane distance function from Sorting by Distance was slower, than above code function customScore. This function was implemented based on article Geographic distance can be simple and fast
user3159253, maybe you have your answer for this thread?
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
For those people already read my last post, I do have a different solution for this. Please don't just walk away.
This is an assignment question from school (Sorry for the long story, I already tried shorten it)
I tend to order food based on how much money I have on me. I like to tip at least 15% regardless of service (I do enough evaluating performance in any given week already) and I hate the whole process of giving my money, waiting for the waitress to come back with the change the trying to find the correct change to make a proper tip. What I do is examine the menu for the combination of foods that best matches the money I have on me. When I say best matches, I mean closest to 15% without going under, and I only pick each food item once. As you can imagine it takes me a bit of time to compute all of this so I want you to make a method that I can use.
The method only has to work for the following menu:
Bandera Pizza Bread 6.49
Boston's Pizza Bread 5.35
Garlic Twist Bread 7.49
Single Order 5.35
Sun-Dried Tomato Bruschetta 6.99
Three Cheese Toast 6.35
Double Order wings 16.49
Starter Size wings 8.99
Cactus Nachos 10.29
Baked Ravioli Bites 8.49
Southwest Quesadilla 9.25
Create a method called selectFood that takes the amount of money I have as a parameter, outputs the selections on the screen and returns the percentage tip I will be leaving rounded to one decimal place. Don't worry if there is more food than two people can eat, I often go out with larger groups.
Some example output:
Best order for $10.00 is:Baked Ravioli Bites
The tip is 17.79%
Best order for $20.00 is:Sun-Dried Tomato Bruschetta, Cactus Nachos
The tip is 15.74%
Best order for $60.00 is:Bandera Pizza Bread, Boston's Pizza Bread, Three Cheese Toast, Double Order wings, Starter Size wings, Baked Ravioli Bites
The tip is 15.03%
Best order for $190.00 is:Bandera Pizza Bread, Boston's Pizza Bread, Garlic Twist Bread, Single Order, Sun-Dried Tomato Bruschetta, Three Cheese Toast, Double Order wings, Starter Size wings, Cactus Nachos, Baked Ravioli Bites, Southwest Quesadilla
The tip is 107.58%
My teacher has a restriction - we are not allowed to use an arraylist.
Here's my newest try:
import java.util.*;
class MethodAssign7{
public static void main(String[]args){
boolean[] took = {false,false,false,false,false,false,false,false,false,false,false};
double money = 70.0;
//System.out.println(selectFood(money/1.15,took));
selectFood(money,took);
System.out.println(closest/money*100+15);
}
static double closest = 10000.0;
static void selectFood(double money, boolean[] took){
String[] food = {"Bandera Pizza Bread","Boston's Pizza Bread","Garlic Twist Bread","Single Order","Sun-Dried Tomato Bruschetta","Three Cheese Toast","Double Order wings","Starter Size wings","Cactus Nachos","Baked Ravioli Bites","Southwest Quesadilla"};
double[] costs = {6.49,5.35,7.49,5.35,6.99,6.35,16.49,8.99,10.29,8.49,9.25};
if(money<5.35){
if(money<closest){
closest = money;
}
}
else{
for(double d: costs){
if(money-d*1.15>0){
//System.out.println(money-d);
selectFood(money-d*1.15,took);
}
}
}
}
/*static void printSelections(double money, boolean[] took){
String[] food = {"Bandera Pizza Bread","Boston's Pizza Bread","Garlic Twist Bread","Single Order","Sun-Dried Tomato Bruschetta","Three Cheese Toast","Double Order wings","Starter Size wings","Cactus Nachos","Baked Ravioli Bites","Southwest Quesadilla"};
double[] costs = {6.49,5.35,7.49,5.35,6.99,6.35,16.49,8.99,10.29,8.49,9.25};
if(money<5.35){
if(money==closest){
print the choices by using took
}
}
else{
for(int i=0;i<costs.length;i++){
if(money-costs[i]*1.15>0 && took[i]!=true){
took[i]=true;
//System.out.println(money-d);
selectFood(money-costs[i]*1.15,took);
}
}
}
}*/
}
I'm trying to solve the percentage part of the question first with dynamic programming, I can get the percentage answer with my program, but it takes too long for money input above 60. I tried to addin the boolean list "took" to indicate which ones are already picked but it did not work at all and got me confused :(
All the parts that's commented out are for the output of selections of food. And I know my selectFood method is only void right now and won't return value, but I think that's easier to fix. All I care right now is how do I get this percentage part working.
Thank you for your time reading my question, if you can help me I would appreciate it very much or if you don't get what I'm asking please leave a comment to tell me.
The simple version of this is that you start with an amount of money, x. At least a certain amount of this will be required as a tip, which we will call t. That effectively means that you want to spend as much money as you can, without going over (x - t).
What you want to do then, is define your targets:
double totalMoney = 190.0;
double minimumTip = totalMoney/115*15;
double targetMoney = totalMoney - minimumTip;
I'll assume that you have the required data structures, like so:
MenuItem[] items = new MenuItem[]
{
new MenuItem("Bandera Pizza Bread", 6.49),
new MenuItem("Boston's Pizza Bread", 5.35),
[...]
};
Now we want to search recursively for the best possible combination of these items, such that the total cost of the selected items is maximized while always remaining less than targetMoney.
Each branch of the recursive tree will represent one combination of products that I could purchase. This is the key difference between my solution and yours. At the first branch of the tree, I will evaluate two possibilities - either I will purchase "Bandera Pizza Bread", or I will not. At the second level of branches, I will evaluate whether I should purchase "Boston's Pizza Bread", or not. At each recursive call, I only need to know whether I still have any money left to spend (at which point I look at the next item down the list) or whether this order has 'overspent', at which point I give up on this combination (since buying anything else will just make it even more expensive!).
To reduce the number of arrays I need to create/discard, I'm using an integer "selected" as a bit field specifying which items I have decided to purchase on this branch. If a bit is 1, then I have chosen to purchase this item. If a bit is 0, then I have chosen not to purchase this item. You could get the same effect using arrays of booleans, but there would be a lot of array manipulation getting in the way of the actual algorithm I'm demonstrating.
I've also created class variables for the best case:
int bestPurchaseSet = 0;
double bestCost = 0;
You don't have to do this, you can pass your results around with parameters and return types, but it makes the code less heavy this way.
So then, the recursive function looks a bit like this:
public void search(MenuItem[] items,
int selected,
int depth,
double currentCost,
double maxCost)
{
if(currentCost > maxCost)
{
// too expensive
return;
}
if(currentCost > bestCost)
{
// New best combination! Save it.
bestCost = currentCost;
bestPurchaseSet = selected;
}
if(depth >= items.length)
{
// run out of food types
return;
}
// if we do choose this item, then we mark it as selected and increase the cost of this order.
search(items, selected | (0x1 << depth), depth + 1, currentCost + items[depth].cost, maxCost);
// if we don't choose this item
search(items, selected, depth + 1, currentCost, maxCost);
}
This should run quite efficiently, because each food item only adds one additional level of recursion - and many of the recursive branches are chopped off early (as soon as the purchase becomes too expensive).
Finally, it's a matter of printing out the results:
System.out.print("Best order for $" + totalMoney + " is: ");
for(int i=0; i<items.length; i++)
{
if((bestPurchaseSet & (0x1 << i)) != 0)
{
System.out.print(items[i].name + ", ");
}
}
System.out.println("The tip is " + (totalMoney - bestCost)/bestCost * 100 + "%");