views:

159

answers:

5

Note: This is a general programming question, not specific to any language, but feel free to use the language of your choice in your answer to explain the logic.

I would like a method to take a string of text, say "Default(0-100)=20" and then extract out of that the default hourly wage would be 20 for hours 0 through 100. This could be then used for say "Default(101-245)=25" that the default hourly wage for hours 101 through 245 would be 25. Also allow it to define "Brian(0-29)=15" that the user "Brian" would have an non-default hourly wage of 15 for hours 0 through 29.

My first impression is to run the string through a regular expression says something like ^(\w*)\((\d*)-(\d*)\)$ where it could pickup the Text and the smaller and higher end of the range.

What would be the best way to store this information so it could be used later on? multidimensional array? hashes?

Once you do have the information stored, what would be the best way of actually using the information to good use?

How would you calculate the total wages earned if say we used "Default(0-100)=20" & "Default(101-245)=25" and the number of hours worked was 150.

+1  A: 

im not very experienced, but im trying to answer it for myself, maybe it can help you.

To the first part of your question, for a string like that id simply split the given string at the apropriate positions. most frameworks have classes to do this. in your case for example that would be ( ) - and =

result:

Default, (, 0, -, 100, ) , =, 20

  1. Default
  2. (
  3. 0
  4. -
  5. 100
  6. )
  7. =
  8. 20

youre values are always at the same index when you use a consistent stringformat. pick them, convert if needed and store in variables;

assuming youre talking about object orientated programming i would do something like this in your case:

create a class employee with name, and hourly-wages as instance variables. this class has also a method calculateWageForHours(int hours). the hourlywages could be stored in a dictionairy or sth simlilar - depending on your framework. You take the beginning-hour as key for the dict an the wagerate as value. you dont need the ending-hours since one rate consists until the next "stage" is reached.

the method to calculate the wage could look sth like this:(there sure is a better way depending on the concrete situation)

calculateWageForHours(int hours) {
for (int i = 0, i < dict.count - 1, i++) {
if (hours < dict[i + 1].key /* the int-value for the hour */ -1) {
float wage;
for (int j = 0, j < i, j++) {
wage += (dict[j + 1].key - 1) * dict[j].value;
}
wage += (hours - dict[i].key - 1) * dict[i].value;
return wage;
}
return calculateWageForHours(dict.lastkey - 1)
 + (hours - dict.lastkey) * dict.lastkey.value;

The default-part could be set anywhere in your programm where you instanciate the employee-class. just write a method which creates the default dictionairy for the employee. (could also be done in the object-initialisation and you hand in the nessesairy arguments from your controller-class)

Tobi
A: 

Very difficult to see the benefit of doing it this way over a traditional configuration in a database or something a little more explicit like an XML config file.

One problem would be ensuring that the expressions were valid individually and amongst themselves (consistent - i.e. what about "Default(0-40)=40,Default(38-100)=60")

Allowing a plain text representation allows some perceived flexibility, but you would still need to ensure that you can handle that in whatever representation you are parsing into. It could very well be a false economy to overbuild the engine to be able to "handle anything" (by becoming a compiler) compared to simply adding options and refactoring as the use cases expand.

If you want to allow expressions, it would seem to me that you could use real expressions - for instance some languages have an Eval function which can evaluate an expression. Or allow users to write scripts.

For expression evaluation, see: http://flee.codeplex.com/

Cade Roux
A: 

Although it is hard to tell from the information in your question, it seems like you are essentially trying to implement a Domain Specific Language (or DSL) to define some rules for your system.

Perhaps you should be looking at implementations of DSLs as a way to solve your problem.

Sam
A: 

I think type of storage and regular expressions would be the least of your concerns in modeling this. You are essentially writing a simple rule engine to compute the salary of an employee. Figuring out what those rules is the most important part of this problem. Ensuring that rules are complete, consistent, and deterministic is another important piece. By deterministic, I mean you cannot have two rules like:

Default(0-100)=20
Default(50-100)=25

as the system does not know how to compute the wages for hours 50-100 since there are two choices. By complete, I mean the rules should be able to compute the wages given any employee and the number of hours they worked. Take another example:

Default(0-100)=20
Default(125-150)=25

If an employee worked for 150 hours, the system does not know their earned wages for hours 101-125. So incompleteness is another problem.

Assuming the rules are complete and deterministic, we can proceed with modeling. If hours worked can be fractional, then the solution will need to proportionally split the hourly wage. It looks like there is a default salary and then salaries specific to an employee. Salaries specific to an employee always take precedence over the default salary. So in a simple if-else pseudo-code, it would look like:

get-wages (employee, hours-worked)
    total-wage = 0

    for each ith hour worked
        hourly-wage = get-hourly-wage (employee, ith-hour)
        fraction-of-hour-worked = get-fraction-of-hour-worked(ith-hour, hours-worked)
        total-wage += hourly-wage * fraction-of-hour-worked

    return total-wage
end

get-hourly-wage (employee, hour-number)
    if employee has specific wage for hour number
        return that
    else if there is default wage for hour number
        return that
    else
        throw error("no wage available for hour number [hour-number]")
end

get-fraction-of-hour-worked (hour-number, hours-worked)
    difference = hours-worked - hour-number
    if difference >= 1
        return 1
    else
        return difference
end

Checkout this article that gives one approach to writing a rule engine and interestingly it uses employees and wages as an example, so it might be helpful.

Some more interesting articles about rule engines that you might find useful:

Anurag
A: 

Why not drop everything not needed in the string, and use something like PHP's explode function (like @Tobi mentioned)?

So your strings would be "Brian,0,100,20" and "Brian,101,245,25"

function get_wages_array($the_string) {
    return explode(',', $the_string);
}

$wages = get_wages_array('Brian,0,40,14.75');

$wages now looks like this:

Array(
    [0] => 'Brian',
    [1] => '0',
    [2] => '40',
    [3] => '14.75'
)

I would store the results in a multidimensional array, then loop through them to get all of the times and wages.

Stephen