Selling electricity

-4

0

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.

McLinux

Posted 2018-02-10T21:46:23.037

Reputation: 295

Is this code golf? – Dennis – 2018-02-10T22:06:27.563

Yes, yes it is. – McLinux – 2018-02-10T22:22:32.930

Do we have to take the input exactly as described (N X on line 1, everything else on line 2) or can we use any reasonable format? – Dennis – 2018-02-10T22:45:44.487

You can use any reasonable format. – McLinux – 2018-02-10T22:49:17.793

1Please edit that clarification into your question. – Dennis – 2018-02-10T22:50:10.627

1By "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) – Jonathan Allan – 2018-02-10T22:58:48.347

What's the point of taking N as input if it's simply the length of the list of days? – Shaggy – 2018-02-10T23:05:33.467

Also, how does John buy at 8, sell at 14 and end up earning 17.5? Surely he's earned 6 there? – Shaggy – 2018-02-10T23:10:24.890

1@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) – Jonathan Allan – 2018-02-10T23:14:50.610

2If this is not your own problem please do provide its source. – Jonathan Allan – 2018-02-10T23:19:55.930

@JonathanAllan The price is never less than 1 because they're always integers. – McLinux – 2018-02-10T23:47:45.223

Yes, sorry for the imprecision! – McLinux – 2018-02-10T23:55:18.390

@JonathanAllan, It's all great! Thank you for your help and enthusiasm regarding this problem! – McLinux – 2018-02-11T00:09:58.093

1Can you give a reference implementation? I don't quite get the specs. – Rɪᴋᴇʀ – 2018-02-11T01:20:05.987

I suggest not accepting any answers. The +2 is not that important. – user202729 – 2018-02-20T04:16:25.120

Answers

1

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.

Mr. Xcoder

Posted 2018-02-10T21:46:23.037

Reputation: 39 774

5

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

Jonathan Allan

Posted 2018-02-10T21:46:23.037

Reputation: 67 804

2\ can be replaced by Ɲ. – Mr. Xcoder – 2018-02-11T14:33:53.303

Oh I forgot about that one, thanks! – Jonathan Allan – 2018-02-11T15:18:32.467

2

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

ovs

Posted 2018-02-10T21:46:23.037

Reputation: 21 408

46 bytes. – totallyhuman – 2018-02-11T13:49:29.503

@totallyhuman thanks a lot, I wasn't aware that the behaviour of map differs between Python 2 and 3. – ovs – 2018-02-11T14:06:19.950

2

Haskell, 41 bytes

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

Try it online!

totallyhuman

Posted 2018-02-10T21:46:23.037

Reputation: 15 378

1

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

Ton Hospel

Posted 2018-02-10T21:46:23.037

Reputation: 14 114

1

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

Emigna

Posted 2018-02-10T21:46:23.037

Reputation: 50 798

1

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)

benj2240

Posted 2018-02-10T21:46:23.037

Reputation: 801

0

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
}

benj2240

Posted 2018-02-10T21:46:23.037

Reputation: 801