Science and technology

Use Python to unravel a charity’s enterprise downside

In my first article on this sequence, I described an issue of dividing bulk provides into hampers of comparable worth to distribute to struggling neighbors in your neighborhood. I additionally wrote about how I get pleasure from fixing small issues like this with small applications in varied languages and evaluating how they do it.

In the primary article, I solved this downside with the Groovy programming language. Groovy is like Python in some ways, however syntactically it is extra like C and Java. Therefore, it ought to be fascinating and instructive to create the identical resolution in Python.

The Python resolution

In Java, I declare utility courses to carry tuples of information (the brand new report characteristic goes to be nice for that). In Groovy, I take advantage of the language help for maps, and I observe the identical method in Python.

Use a listing of dictionaries to carry the majority gadgets picked up from the wholesaler:

packs = [
        ,
        ,
        ,
        ,
        ,
        ,
        'merchandise':'UHT milk','model':'Atlantic','models':6,'value':4560,'amount':2,
        ,
        ,
        ,
        ,
        'merchandise':'Coffee','model':'Colombia Select','models':2,'value':4180,'amount':5,
        'merchandise':'Tofu','model':'Gourmet Choice','models':1,'value':1580,'amount':10,
        ,
        ]

There is one bulk pack of 10 baggage of rice and 10 bulk packs with one bag every of spaghetti. In the above, the variable packs is ready to a Python listing of dictionaries. This seems to be similar to the Groovy method. Just a few factors price noting in regards to the distinction between Groovy and Python:

  1. In Python, there isn’t any key phrase used to outline the variable packs; Python expects the primary use to set a price.
  2. Python dictionary keys (e.g., merchandise, model, models, value, amount) require quotes to point they’re strings; Groovy assumes these are strings, however accepts quotes as effectively.
  3. In Python, the notation signifies a dictionary declaration; Groovy makes use of the identical sq. brackets as a listing, however the construction in each circumstances should have key-value pairs.

And, sure, these costs aren’t in US .

Next, unpack the bulk packages. Unpacking the one bulk bundle of rice, for instance, will yield 10 models of rice; that’s, the whole variety of models yielded is models * amount. The Groovy script makes use of a helpful operate known as collectMany that can be utilized to flatten out lists of lists. As far as I do know, Python would not have something comparable, so use two listing comprehensions to provide the identical end result:

models = [['merchandise':pack['merchandise'],'model':pack['model'],
        'value':(pack['value'] / pack['models'])] *
        (pack['models'] * pack['amount']) for pack in packs]
models = [x for sublist in models for x in sublist]

The first listing comprehension (project to models) builds the listing of lists of dictionaries. The second “flattens” that into only a listing of dictionaries. Note that each Python and Groovy present an * operator that takes a listing on the left and a quantity N on the proper and replicates the listing N occasions.

The ultimate step is to repack the models into the baskets for distribution. As within the Groovy model, you might want to get a bit extra particular in regards to the splendid hamper worth, and also you would possibly as effectively not be overly restrictive if you get right down to only a few models left:

valueIdeal = 5000
valueMax = valueIdeal * 1.1

OK! Repack the baskets:

import random
hamperNumber = zero           # [1]
whereas len(models) > zero:      # [2]
    hamperNumber += 1
    hamper = []
    worth = zero
    canAdd = True              # [2.1]
    whereas canAdd:              # [2.2]
        u = random.randint(zero,len(models)-1)  # [2.2.1]
        canAdd = False                      # [2.2.2]
        o = zero                               # [2.2.3]
        whereas o < len(models):               # [2.2.4]
            uo = (u + o) % len(models)
            unit = models[uo]
            unitPrice = unit['value']          # [2.2.4.1]
            if len(models) < three or not (unit in hamper) and (worth + unitPrice) < valueMax:
                                               # [2.2.4.2]
                hamper.append(unit)
                worth += unitPrice
                models.pop(u)                   # [2.2.4.3]
                canAdd = len(models) > zero
                break                          # [2.2.4.4]
            o += 1                             # [2.2.4.5]
                                            # [2.2.5]
    print('')
    print('Hamper',hamperNumber,'worth',worth)
    for merchandise in hamper:
        print('%-25s%-25spercent7.2f' % (merchandise['merchandise'],merchandise['model'],merchandise['value'])) # [2.3]
    print('Remaining models',len(models))                                       # [2.4]

Some clarification, with numbers in brackets within the feedback above (e.g., [1]) akin to the clarifications under:

  • 1. Import Python’s random quantity generator services and initialize the hamper quantity.
  • 2. This whereas loop will redistribute models into hampers so long as there are extra out there:
    • 2.1 Increment the hamper quantity, get a brand new empty hamper (a listing of models), and set its worth to zero; begin off assuming you may add extra gadgets to the hamper.
    • 2.2 This whereas loop will add as many models to the hamper as doable (the Groovy code used a for loop, however Python’s for loops count on to iterate over one thing, whereas Groovy has the extra conventional C type of for loop):
      • 2.2.1 Get a random quantity between zero and the variety of remaining models minus 1.
      • 2.2.2 Assume you may’t discover extra models so as to add.
      • 2.2.three Create a variable for use for the offset from the place to begin the place you are on the lookout for gadgets to place within the hamper.
      • 2.2.four Starting on the randomly chosen index, this whereas loop will attempt to discover a unit that may be added to the hamper (as soon as once more, notice that the Python for loop in all probability is not appropriate right here because the size of the listing will change throughout processing).
        • 2.2.four.1. Figure out which unit to have a look at (random place to begin + offset) and get its value.
        • 2.2.four.2 You can add this unit to the hamper if there are just a few left or if the worth of the hamper is not too excessive as soon as the unit is added.
        • 2.2.four.three Add the unit to the hamper, increment the hamper worth by the unit value, take away the unit from the out there models listing.
        • 2.2.four.four As lengthy as there are models left, you may add extra, so get away of this loop to maintain trying.
        • 2.2.four.5 Increment the offset.
      • 2.2.5 On exit from this whereas loop, should you inspected each remaining unit and couldn’t discover one so as to add to the hamper, the hamper is full; in any other case, you discovered one and may proceed on the lookout for extra.
    • 2.three Print out the contents of the hamper.
    • 2.four Print out the remaining models data.

When you run this code, the output seems to be fairly much like the output from the Groovy program:

Hamper 1 worth 5304.zero
UHT milk                 Atlantic                  760.00
Tomato sauce             Best Family               190.00
Rice                     Best Family               565.00
Coffee                   Colombia Select          2090.00
Sugar                    Good Price                565.00
Vegetable oil            Crafco                    835.00
Soap                     Sunny Day                 299.00
Remaining models 148

Hamper 2 worth 5428.zero
Tea                      Superior                  544.00
Lentils                  Southern Style           1189.00
Flour                    Neighbor Mills            520.00
Tofu                     Gourmet Choice           1580.00
Vegetable oil            Crafco                    835.00
UHT milk                 Atlantic                  760.00
Remaining models 142

Hamper three worth 5424.zero
Soap                     Sunny Day                 299.00
Chickpeas                Southern Style           1300.00
Sardines                 Fresh Caught              909.00
Rice                     Best Family               565.00
Vegetable oil            Crafco                    835.00
Spaghetti                Best Family               327.00
Lentils                  Southern Style           1189.00
Remaining models 135

Hamper 21 worth 5145.zero
Tomato sauce             Best Family               190.00
Tea                      Superior                  544.00
Chickpeas                Southern Style           1300.00
Spaghetti                Best Family               327.00
UHT milk                 Atlantic                  760.00
Vegetable oil            Crafco                    835.00
Lentils                  Southern Style           1189.00
Remaining models four

Hamper 22 worth 2874.zero
Sardines                 Fresh Caught              909.00
Vegetable oil            Crafco                    835.00
Rice                     Best Family               565.00
Rice                     Best Family               565.00
Remaining models zero

The final hamper is abbreviated in contents and worth.

Closing ideas

At a look, there is not a complete lot of distinction between the Python and Groovy variations of this program. Both have the same set of constructs that make dealing with lists and dictionaries very simple. Neither requires a whole lot of “boilerplate code” or different “ceremonial” actions.

Also, as within the Groovy instance, there’s some fiddly enterprise about having the ability to add models to the hamper. Basically, you choose a random place within the listing of models and, beginning at that place, iterate via the listing till you both discover a unit whose value permits it to be included or till you exhaust the listing. Also, when there are just a few gadgets left, you simply toss them into the final hamper.

Another concern price mentioning: This is not a very environment friendly method. Removing components from lists, being careless about repeated expressions, and some different issues make this much less appropriate for an enormous redistribution downside. Still, it runs in a blink on my outdated machine.

If you’re shuddering at my use of whereas loops and mutating the information on this code, you in all probability want I made it extra purposeful. I could not consider a means to make use of map and scale back options in Python along side a random choice of models for repackaging. Can you?

In the subsequent article, I will re-do this in Java simply to see how a lot much less effort Groovy and Python are, and future articles will cowl Julia and Go.

Most Popular

To Top