-3
\$\begingroup\$

Jack is a little businessman. He found out a way to earn money by buying electricity on days when it's cheap and selling it when it's much more expensive. He stores the electricity in a battery he made by himself.

Challenge

You are given N (if required), the number of days Jack knows the cost of electricity for, and X, the amount of money Jack has available to invest in electricity, and the value(buy/sell value) of the electricity for N days. Your job is to determine when Jack should buy and when he should sell electricity in order to earn as much money as possible and simply print the largest possible sum of money he could have afterwards.

The value of the electricity is always a positive integer but depending on the amount of money Jack has, the amount of electricity and money he has may be floating point numbers.

Examples

(I/O need not be exactly as shown):

1.

4 10
4 10 5 20

Output: 100
- because he buys electricity on the 1st day and the sells it on the 2nd and buys it on the 3rd and sells it on the 4th day.

2.

3 21  
10 8 3

Output: 21
- because it's better if he doesn't buy/sell any electricity.

3.

3 10
8 10 14

Output: 17.5
- because he buys electricity on the 1st day, but he sells it on the 3rd day.

4.

5 10
4 2 10 5 20

Output: 200
- much like example 1, but this time Jack waits for the price to drop to 2 before making a purchase.


The program with the shortest amount of code wins! This is a code golf problem. Note:You can shorten the input, as long as it still makes sense.

\$\endgroup\$
15
  • 1
    \$\begingroup\$ Please edit that clarification into your question. \$\endgroup\$
    – Dennis
    Commented Feb 10, 2018 at 22:50
  • 1
    \$\begingroup\$ By "earn" do you mean his final amount of money? (that is I think 4 10 and 4 10 5 20 only earns 90, not 100) \$\endgroup\$ Commented Feb 10, 2018 at 22:58
  • 1
    \$\begingroup\$ @Shaggy He spends his 10 buying at 8 storing 1.25 units which he sells at 14 for 17.5 (14*1.25). (He nets 7.5, but "earns" 17.5. See my comment above) \$\endgroup\$ Commented Feb 10, 2018 at 23:14
  • 2
    \$\begingroup\$ If this is not your own problem please do provide its source. \$\endgroup\$ Commented Feb 10, 2018 at 23:19
  • 1
    \$\begingroup\$ Can you give a reference implementation? I don't quite get the specs. \$\endgroup\$
    – Riker
    Commented Feb 11, 2018 at 1:20

8 Answers 8

5
\$\begingroup\$

Jelly,  8  7 bytes

-1 byte thanks to Mr. Xcoder (use the Ɲ quick which performs 2\)

÷@Ɲ»1P×

A dyadic link taking a list of the prices on the left and the initial capital on the right which returns the maximal capital.

Try it online! or see the test-suite.

How?

Jack can sell every day on which the preceding day had a lower price and buy on those days (even if it is one on which he sold). When he does so his capital increases by priceToday ÷ priceYesterday, such gains multiply his initial capital, while any time the price falls he may simply forego the loss and multiply his capital by 1 instead by not transacting.

÷@Ɲ»1P× - Link: list, prices; number, initial capital  e.g. [4,2,10,5,20], 10
  Ɲ     - pairwise overlapping reduce left (prices) by:
÷@      -   division with swapped arguments                 [0.5,5,0.5,4]
    1   - literal one                                       1
   »    - maximum (vectorises)                              [1,5,1,4]
     P  - product                                           20
      × - multiply by right (initial capital)               200
\$\endgroup\$
2
  • \$\begingroup\$ 2\ can be replaced by Ɲ. \$\endgroup\$
    – Mr. Xcoder
    Commented Feb 11, 2018 at 14:33
  • \$\begingroup\$ Oh I forgot about that one, thanks! \$\endgroup\$ Commented Feb 11, 2018 at 15:18
2
\$\begingroup\$

Haskell, 41 bytes

l#n=foldr((*).max 1)n$zipWith(/)(tail l)l

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Coconut, 51 45 bytes

thanks to @totallyhuman for -5 bytes

d->m->reduce((*),map(max$(1)..(/),d[1:],d))*m

Try it online!

Uses Jonathan Allan's algorithm.

Coconut extends Python with several functional programming constructs.

d->m->                      lambda function taking two arguments, money and prices, in currying syntax

    reduce((*),              product of...
           map(               map
               max$(1)..(/),   (x,y)->max(1, x/y)
                              over
               d[1:],d         consecutive pairs of prices
               )
          )*m                multiply with the initial money
\$\endgroup\$
2
  • \$\begingroup\$ 46 bytes. \$\endgroup\$ Commented Feb 11, 2018 at 13:49
  • \$\begingroup\$ @totallyhuman thanks a lot, I wasn't aware that the behaviour of map differs between Python 2 and 3. \$\endgroup\$
    – ovs
    Commented Feb 11, 2018 at 14:06
1
\$\begingroup\$

Husk, 7 bytes

Π:mY1Ẋ/

Try it online!

How?

Π:mY1Ẋ/ – Full program.
     Ẋ  – For each pair of adjacent elements from the input list...
      / – ... Divide the second by the first.
  m     – For each quotient...
   Y1   – ... Get the maximum between it and 1.
 :      – Append the second input.
Π       – Get the product of the resulting list.
\$\endgroup\$
1
\$\begingroup\$

Perl, 37 bytes

Includes +4 for -ap

On STDIN first give a line with the list of prices, then a line with the starting capital

electricity.pl:

#!/usr/bin/perl -ap
$\=<>;s%\d+%$\*=$&>$'||$'/$&%eg}{

You can then for example run it as:

(echo 4 2 10 5 20; echo 10) | electricity.pl; echo
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 9 bytes

Rü/εXM}P*

Try it online!

Uses the same method as in Jonathan Allan's Jelly answer

Explanation

R           # reverse input list of buy/sell values
 ü/         # pairwise division
   εXM}     # max of each element and 1
       P    # product
        *   # multiply by initial capital
\$\endgroup\$
1
\$\begingroup\$

Stax, 21 20 bytes

àq'4¢<╪╦ÉdεÖ!≤♠┬☻∟In

Run it

This is the ascii representation of the same program:

c|)s\Dc{|Mms{hm\{E:_m:**

I'm sure there is room for golfing here, but I wanted to give Stax a spin. Here's the breakdown.

                            Input stack: initial funds, array of prices
c                           Copy the array of prices
 |)                         Rotate the top copy one place right
   s                        Swap the two arrays on the main stack
    \                       Zip the arrays to get consecutive price pairs
     D                      Drop the first pair (don't need [price N, price 1])
      c                     Copy the result
       {|Mm                 Map max: Keep only the max of each pair (copy 1)
           s                Swap copy 1 and copy 2 on the main stack
            {hm             Map first: Keep only the first of each pair (copy 2)
               \            Zip copy 1 and copy 2
                {E:_m       Map explode, divide: Transform pairs with float division
                     :*     Array product: Multiply all resulting quotients
                       *    Multiply by other input (initial funds)
\$\endgroup\$
0
\$\begingroup\$

Ruby, 57 bytes

->a,x{x*a.each_cons(2).map{|t|t.max*1.0/t[0]}.reduce(:*)}

Try it online!

A lambda taking an array of prices a and the starting capital x. The most interesting thing I found here is that it's faster to treat the pairs of prices as a tuple t, whereas my first instinct was .map{|n,m|[m,n].max*1.0/m}.

->a,x{
  x *                       # Multiply the starting capital by...
  a.each_cons(2).map{ |t|   # For each consecutive pair of prices
    t.max*1.0 / t[0]        # The larger of that pair, divided by the first
  }.reduce(:*)              # All multiplied together
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.