Stock Time Machine

35

Stock Time Machine

Obtuvo acceso a un conjunto de datos, tomorrowStocksque contiene los precios de las acciones de su negocio favorito en el NASDAQ. Este conjunto de datos es un contenedor indexado por minutos después de la apertura. Cada índice contiene el precio de la acción en ese momento.

// Assume the stock market opens at 9:30AM EDT
// tomorrowStocks[] contains the prices of your target stock.
// If the stock is $22 @ 10:30AM EDT
tomorrowStocks[60] == 22

Salida

Su tarea consiste en determinar el mejor resultado posible de 1 purchasey 1 salede la 1 stockdel conjunto de datos dado.

Gotchas

  • Debe comprar y vender exactamente 1 acción.
  • No puede comprar y vender en el mismo intervalo de tiempo.
  • Debe comprar antes de vender.

Datos de prueba

[1,2,3,4,5]    # 4
[1,99,2,105]   # 104
[99,1,99,100]  # 99
[99,1,1,2,1,3] # 2
[5,4,3,3,1]    # 0
[5,4,3,1]      # -1
[5,2,1]        # -1
[5,4,1]        # -1
[55,45,20,1]   # -10
[5,1]          # -4
[10,7,5,1]     # -2
[7]            # Invalid input -- assume size >= 2

Este es un ; ¡envía la respuesta más corta en tu idioma favorito!

MrDuk
fuente
11
Bienvenido a PPCG, buena primera pregunta! :)
FryAmTheEggman
¿Podemos suponer que la salida es determinista (es decir, siempre hay una solución que es definitivamente la mejor, y sin vínculos)
MayorMonty
1
Lástima que el intérprete para un lenguaje que estoy construyendo aún no haya terminado, ya que debería ser capaz de resolver esto en 4 bytes ... ¡Necesito terminarlo lo antes posible para no perderme tantas buenas preguntas!
Steven H.
1
@SpeedyNinja Esto está realmente en los casos de prueba. En caso de prueba [5,4,3,1]usted puede, pero para 5y se venden por 4o para comprar 4y vender para 3obtener el resultado óptimo de -1.
Martin Ender
1
@Fawful Puede agregar su respuesta como no competitiva más tarde. Definitivamente me interesaría verlo
CocoaBean

Respuestas:

14

05AB1E , 4 bytes

Usando el enfoque de FryAmTheEggman . Código:

¥ŒOà

Explicación:

¥     # Calculate the increments of the array.
 Œ    # Get all substring of the array.
  O   # Sum the arrays in the array.
   à  # Get the largest sum and implicitly print that.

Utiliza la codificación CP-1252 . Pruébalo en línea! .

Adnan
fuente
2
Maldición, probé 4 idiomas de golf y me olvidé de 05AB1E. Eso me aprenderá para la próxima vez: P
FryAmTheEggman
19

Python 2, 46 bytes

f=lambda x:-min(x.pop(0)-max(x),x[1:]and-f(x))

Pruébalo en Ideone .

Cómo funciona

Este es un enfoque recursivo que aprovecha las comparaciones de tipo mixto maravillosamente perversas de Python 2.

El mejor resultado posible es la diferencia del máximo de la lista con su primer elemento eliminado y ese primer elemento, u otra diferencia que no involucre al primer elemento.

Después de extraer el primer elemento con x.pop(0)(que lo elimina permanentemente de x ), calculamos x.pop(0)-max(x). Tenga en cuenta que esta diferencia tiene el signo "incorrecto".

Si la lista actualizada x todavía contiene al menos dos elementos, x[1:]genera una lista no vacía y la andreemplaza con el negativo de una llamada recursiva, calculada como -f(x). Una vez que hay muy pocos elementos para continuar, se x[1:]and-f(x)evalúa como una lista vacía.

To select the maximal outcome, we take the minimum of the difference and the negative of the recursive call (or []). Since all integers are strictly less than [], min will simply return its left argument if the right one is [].

Finally, the unary minus - corrects the sign of the computed outcome.

Dennis
fuente
This is strangely beautiful.
MrDuk
11

MATL, 7 bytes

2XN!dX>

Try it online! Or verify all test cases.

2XN  % Take input implicitly. Two-column 2D array with all combinations of 2 elements.
     % Each combination is a row. Elements in each row are in increasing order
!    % Transpose
d    % Difference of the two numbers in each column
X>   % Maximum value. Display implicitly
Luis Mendo
fuente
Turns out, this is the same idea as in Dennis' answer
Luis Mendo
1
Aww... Beat me to it!
DJMcMayhem
8

Jelly, 5 bytes

Œcḅ-Ṁ

Try it online! or verify all test cases.

How it works

Œcḅ-Ṁ  Main link. Argument: A (integer array)

Œc     Generate all combinations of two elements of A, in order.
  ḅ-   Convert each pair from base -1 to integer.
       This maps [a, b] to b - a.
    Ṁ  Take the maximum of all computed differences.
Dennis
fuente
IŒṡS€Ṁ Almost same length, it's too bad doing using before summing occasionally gives the wrong answer...
FryAmTheEggman
7

Pyth, 9

eSsM.:-Vt

Try it here or run a Test Suite.

Finds the consecutive differences between each element, then finds each substring of that array. Finally, sum the elements and return the maximal one.

Explanation:

eSsM.:-Vt
eSsM.:-VtQQ   ## Auto-fill variables
      -VtQQ   ## Splat subtraction on each element of zip(Q[1:], Q)
    .:        ## Get all substrings
  sM          ## Sum each list
eS            ## Take the largest number

It was mentioned to me that that this algorithm works isn't entirely intuitive. Hopefully this example will illustrate why this algorithm works:

[a, b, c, d]
difference between each element (reversed because of how Pyth does this)
[b-a, c-b, d-c]
"substrings" or each continuous slice
[b-a], [c-b], [d-c], [b-a, c-b], [c-b, d-c], [b-a, c-b, d-c]
sum each
[b-a], [c-b], [d-c], [b-a+c-b], [c-b+d-c], [b-a+c-b+d-c]
simplify
[b-a], [c-b], [d-c], [c-a], [d-b], [d-a]
FryAmTheEggman
fuente
5

Pyth, 9

_hS-M.cQ2

Yay pfns!

_hS-M.cQ2

     .cQ2 # generate all 2-elements combinations of Q (argument)
   -M     # map-splat with -: for each combination, substract the elements together
  S       # tort
 h        # take the first
_         # absolute value
Ven
fuente
I believe _hS-M.cQ2 is equivalent.
FryAmTheEggman
@FryAmTheEggman ah, thanks. Now trying to think how I could reverse -'s argument order... since I have to use _hS and can't use eS
Ven
4

PowerShell v2+, 58 bytes

param($n)($n|%{($n[++$i..$n.count]|sort)[-1]-$_}|sort)[-1]

Takes input $n, pipes each element into a loop |%{...}. Each iteration, we slice $n based on pre-incremented ++$i to the end of the input array, |sort that, and take the maximal [-1], then subtract the current element $_. We then |sort all of those differences, and again take the maximal [-1].

Tosses out a verbose array-index error, because we try to slice past the end of the array. But, since STDERR is ignored by default, we don't care.

AdmBorkBork
fuente
4

JavaScript (ES6), 57 54 bytes

a=>(m=Math.max)(...a.map((x,i)=>m(...a.slice(i+1))-x))

In JavaScript it's easier to take the max of the remainder of the array and subtract the current element. (In the case of the last element the result will still be -Infinity.) Edit: Saved 3 bytes thanks to @CharlieWynn.

Neil
fuente
I think (M=Math.max) and using M later will save you 3 bytes
Charlie Wynn
@CharlieWynn Thanks, I'd only tried with (which doesn't help in this case).
Neil
3

J, 21 bytes

[:>./@;i.@#<@{."_1-/~

Takes an array of values as an argument and returns the result.

Explanation

[:>./@;i.@#<@{."_1-/~  Input: p
                  -/~  Make a table of all differences between every pair
          #            Get the count of values in p
       i.@             Create a range [0, 1, ..., len(p)-1]
             {."_1     Take that many values from each row of the table
           <@          Box each row of selected values
[:    ;                Unbox and concatenate them
  >./@                 Reduce it by the max and return
miles
fuente
2

Java, 141 bytes

a->java.util.stream.IntStream.range(0,a.size()-1).map(i->a.subList(i+1,a.size()).stream().reduce(Math::max).get()-a.get(i)).max().getAsInt();

The lambda accepts an ArrayList and returns an Integer.

Ungolfed code with test cases:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.Function;
import java.util.stream.IntStream;

class Test {

    public static void main(String[] args) {
        Function<ArrayList<Integer>, Integer> f = a -> IntStream
            .range(0, a.size()-1)
            .map(i -> a.subList(i+1, a.size()).stream().reduce(Math::max).get() - a.get(i))
            .max()
            .getAsInt();

        System.out.println(f.apply(new ArrayList<>(Arrays.asList(1,2,3,4,5))));
        System.out.println(f.apply(new ArrayList<>(Arrays.asList(1,99,2,105))));
        System.out.println(f.apply(new ArrayList<>(Arrays.asList(99,1,99,100))));
        System.out.println(f.apply(new ArrayList<>(Arrays.asList(99,1,1,2,1,3))));
        System.out.println(f.apply(new ArrayList<>(Arrays.asList(5,4,3,3,1))));
        System.out.println(f.apply(new ArrayList<>(Arrays.asList(5,4,3,1))));
        System.out.println(f.apply(new ArrayList<>(Arrays.asList(5,2,1))));
        System.out.println(f.apply(new ArrayList<>(Arrays.asList(5,4,1))));
        System.out.println(f.apply(new ArrayList<>(Arrays.asList(55,45,20,1))));
        System.out.println(f.apply(new ArrayList<>(Arrays.asList(5,1))));
        System.out.println(f.apply(new ArrayList<>(Arrays.asList(10,7,5,1))));
    }
}

As far as I know, Java doesn't have a way to look forward in a stream, and manipulating the method from which the stream is generated produces strange results. So doing a.remove(0) inside a map horribly breaks the stream.


fuente
1

VBA, 154

Takes in the input in column A starting in A1, outputs in C1. Must be run with the last cell in A selected. Note that Excel auto-adds the spaces between terms in VBA, otherwise this could be golfed further.

Sub s
i = Selection.Row
r = "B1:B" + i-1
Range(r).FormulaArray = "MAX(A2:A$" + i + "-A1)"
Range(r).FillDown
Range("C1").Formula = "MAX(" + r + ")"
End Sub
Adam Martin
fuente
1

Java, 116

Another java solution, i used this one to prove that, streams might looks nice, but not always useful for golfing.

int a(int[]a){int t,d=a[1]-a[0],i,j,l=a.length;for(i=0;i<l;i++)for(j=i+1;j<l;j++){t=a[j]-a[i];d=d<t?t:d;}return d;}

there is lot of space for improvements in this solution

user902383
fuente
1

Clojure, 99 bytes

(fn[x](apply max(map #(-(apply max(% 1))(apply min(% 0)))(map #(split-at % x)(range 1(count x))))))

Splits input list at first position then second and so on, so we get a list which looks like this:

[[[n1][n2 ... nk]][[n1 n2][n3 ... nk]]...[[n1...n(k-1)][nk]]] then for each pair subtracts minimum of the first elements from max of the second element and then find max from them. Would be shorter if Clojure's min max were taking sequences rather than any number of arguments.

See it online: https://ideone.com/b2nllT

cliffroot
fuente
1

ruby, 52 bytes

->a{b=[];(x=a.pop;b+=a.map{|v|x-v})while a[0];b.max}

pops possible sell prices and look at all of the previous to find profit. Then gets max profit.

MegaTom
fuente
1

C, 101 99 Bytes

int i,j,m,h;int f(int*a){m=1<<31;for(;a[i];i++){for(j=i+1;a[j];h=a[j++]-a[i],m=h<m?m:h);}return m;}

Input: null terminated array. E.g. {1,2,3,4,5,0}
Output: returns the best outcome

You can save 8 bytes (93 91 total) if you never want to lose money:

int i,j,m,h;int f(int*a){for(;a[i];i++){for(j=i+1;a[j];h=a[j++]-a[i],m=h<m?m:h);}return m;}
Riley
fuente
1

R, 58 44 bytes

max(unlist(sapply(seq(y<-scan()),diff,x=y)))

ungolfed

y=scan()                #input
s=1:length(y)           #sequence of same length from 1
l = sapply(s,diff,x=y)  #applies the function diff to each 'lag' in sequence s
                        #and differencing on y
max(unlist(l))          #reforms as vector and finds maximum

EDIT: changed function. original below.

f=function(x)max(max(x[-1]-x[1]),if(length(x)-2)f(x[-1]))

or, if you're willing to put up with a bunch of warning messages, get rid of the -2 after length, for 56 bytes.

f=function(x)max(max(x[-1]-x[1]),if(length(x))f(x[-1]))

And if you feel like not trading and losing money when that's the only possibility, you can get down to 52

f=function(x)max(max(x-x[1]),if(length(x))f(x[-1]))
user5957401
fuente
f= isn't needed.
NoOneIsHere
@NoOneIsHere recursion won't work without it. I could use Recall, but it picks up more letters than I lose.
user5957401
Oh, sorry. I always miss recursion.
NoOneIsHere