The Trader

Every day, Hugo the trader drives his cart past Emma's farm and buys crops. His prices change every day. When his cart is empty, he pays 2 coins more for each crop than the market. The next day, when it's half full, he pays 1 coin more. On the third day, it's full, and he pays only what the market pays. Then he takes everything to town, and it starts again: 2, 1, 0, 2, 1, 0…

Emma's rule is simple: if Hugo pays more than the market, she sells him everything in the barn. Otherwise, she keeps it, and at the end of the season, it goes to the market.

Hugo's days are a job for a coroutine, as in the lesson on coroutines: a function that runs a bit every day and pauses at coroutine.yield. coroutine.wrap turns it into a function that continues it: each call runs it until the next yield and returns the value given to yield. For example, what Rex the dog does all day:

local function rexScript()
    while true do
        coroutine.yield("guards the barn")
        coroutine.yield("sleeps by the well")
    end
end

local rex = coroutine.wrap(rexScript)
for day = 1, 3 do
    print("Day " .. day .. ": Rex " .. rex())
end

This prints:

Day 1: Rex guards the barn
Day 2: Rex sleeps by the well
Day 3: Rex guards the barn

The loop while true never ends, but that's fine here. At every yield, the coroutine pauses, and the program goes on. It runs again only when it's called, and it continues where it stopped, here in the middle of its loop. Hugo's script will be the same, only with a for loop from 2 down to 0 inside. Don't forget its step, -1. Without it, the for loop runs zero times, while true never reaches a yield, and the program runs until the site stops it after 5 seconds.

Hugo's script must run as a coroutine, through coroutine.wrap (or coroutine.create and coroutine.resume). If you call hugoScript() directly, it isn't a coroutine, and yield has nowhere to return to: attempt to yield from outside a coroutine (this time without a line number at the start). And create the coroutine only once, above the loop over the days. Created inside the loop, it would start from the beginning every day, and Hugo would always pay 2 coins more.

The function sell needs two more parameters: who buys (buyer) and how many coins more than the market he pays (extra). Give them default values, as in the lesson on functions: buyer = buyer or "Market" and extra = extra or 0. Then the call sell(barn) at the end of the season works as before.

sell must also empty the barn: barn[name] = nil removes a crop once it's sold. Without it, Hugo would buy the same wheat again on another day, the market once more at the end, and Emma would end the season with 390 coins. That's too good to be true. Removing the barn's keys inside the loop is fine, because the loop goes through the separate list from sortedNames.

On the first day, Hugo pays 2 coins more, but the barn is still empty, and sell would print Hugo: = 0. So let it print its line only when the total is greater than 0.

Instructions

Under sell, write a function hugoScript() with a loop while true that never ends. Inside it, a for loop goes from 2 down to 0 (with the step -1) and gives each number to coroutine.yield.

Change sell. Give it the parameters buyer and extra with the default values "Market" and 0, add extra to the price of each crop, start the line with buyer instead of Market, and remove each sold crop from the barn. Print the line only when the total is greater than 0. The output doesn't change yet.

In the main program, create Hugo's coroutine above the loop over the days: local hugo = coroutine.wrap(hugoScript). Every day, after the day's line, get Hugo's extra from hugo(). If it's greater than 0, sell him everything in the barn with sell(barn, "Hugo", extra), and add the coins. The season now looks like this:

Coins: 6
Day 1 (sunny): carrot 1/3, wheat 1/2, pumpkin 1/6
Day 2 (sunny): carrot 2/3, wheat 2/2, pumpkin 2/6
Hugo: wheat 6 x 4 = 24
Day 3 (rainy): carrot 3/3, wheat 2/2, pumpkin 4/6
Day 4 (cloudy): carrot 1/3, wheat 1/2, pumpkin 5/6
Hugo: carrot 4 x 7, wheat 6 x 5 = 58
Day 5 (sunny): carrot 2/3, wheat 2/2, pumpkin 6/6
Hugo: pumpkin 2 x 21, wheat 6 x 4 = 66
Day 6 (cloudy): carrot 3/3, wheat 1/2, pumpkin 1/6
Market: carrot 4 x 5 = 20
End of the season: 174 coins

If Hugo pays 2 coins more every day (wheat 6 x 5 on day 2), you create his coroutine inside the loop.

Start programming for free

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

6/7