时间旅行股票交易者


21

故事
很久以前,鲍比(Bobby)用1个中本聪(1e-8 BTC,最小货币单位)创建了一个比特币钱包,却忘了它。像许多其他人一样,他后来也说“该死,如果我再投资更多……”。
他不停地做白日梦,他将所有的时间和金钱都献给了建造时光机。他将大部分时间都花在车库里,没有意识到世俗的事情和关于他的谣言。由于缺电,他将在即将关闭电源的前一天完成样机。从工作台上抬起头来,他看到一辆警车驶向他的房子,看上去像个爱管闲的邻居,以为他在自己的车库里经营一个冰毒实验室,并叫警察。
由于没有时间进行测试,他用过去几年的汇率数据获取USB记忆棒,将Flux电容器连接到Quantum Discombobulator,并发现自己回到了创建钱包的那一天

任务
根据汇率数据,找出鲍比能赚多少钱。他遵循一个非常简单的规则:“低买高卖”,并且由于他以无限小的资金开始,所以我们认为他的行为不会对未来的汇率产生影响。

输入
浮点数> 0的列表,可以是用单个字符(换行符,制表符,空格,分号,可以根据需要选择的任何字符)分隔的字符串,作为命令行参数传递给程序,从文本文件或STDIN中读取或作为参数传递功能。您可以使用数字数据类型或数组而不是字符串,因为它基本上只是带括号的字符串。

输出
Bobbys资本乘以交易结束所乘的因子。

Input:  0.48 0.4 0.24 0.39 0.74 1.31 1.71 2.1 2.24 2.07 2.41

汇率:0.48 $ / BTC,因为它即将下降,所以我们以4.8纳元的价格出售所有比特币。因子= 1汇率:0.4,不执行任何操作
汇率:0.24 $ / BTC并上涨:将所有$转换为2 Satoshis。因子= 1(美元价值仍然保持不变)
汇率:0.39-2.1 $ / BTC:不做任何事情
汇率:2.24 $ / BTC:在下跌之前卖出所有东西。44.8纳米美元,系数= 9.33
汇率:2.07美元/ BTC:买入2.164聪,系数= 9.33
汇率:2.41美元/ BTC:购买52.15纳米美元,系数= 10.86

Output: 10.86

其他详细信息
您可能会忽略一些奇怪的情况,例如恒定输入,零或负值,仅一个输入数字等。
请随意生成自己的随机数以进行测试或使用实际的股票图表。是用于测试的较长输入(预期输出约为321903884.638)
简要说明您的代码将执行哪些操作
图形值得赞赏,但不必要


如果我们通过函数参数获取数字,是否仍然必须是字符串,还是可以直接获取数组?
Martin Ender 2014年

@MartinBüttner我考虑了一段时间,无论输入是字符串,数字数组还是自由选择,总有一些语言会受益。在这方面似乎尚未达成共识,编写两个程序,一个用于数字输入,一个用于字符串输入,然后将两个分数取平均值似乎有点过头了。
DenDenDo 2014年

无限可能性驱动怎么样?:)
门把手

2
回到问题上,我们是否需要在每次迭代中以给定的精度舍入BTC和/或$值?例如,在现实世界中,必须将自己的BTC钱包四舍五入到中本聪。这会有所不同,因为在您的示例中,在2.07时,您只能购买2s(而不是2.164);因此,您只能购买2s。那么在2.41时,您的2买入您的收益为48.2 n $(而不是52.15),因此系数为10.04(不是10.86)。除非您为零钱保留一个单独的$钱包,并且每次都需要重新添加。那美元呢?今天有人可以声称自己拥有纳米金吗?我相信一个人可以持有的最小金额是1美分。
Tobia 2014年

1
@CortAmmon:您是说BTC交易混乱吗?;-)
史蒂夫·杰索普

Answers:


10

APL,16个字符

{×/1⌈÷/⊃⍵,¨¯1⌽⍵}

此版本使用@Frxstrem的简单算法和@xnormax(r,1)思想。

它还假设该系列总体上在上升,即第一个比特币值小于最后一个比特币。这与问题描述一致。要获得更通用的公式,必须删除前几个费率,添加2个字符:{×/1⌈÷/⊃1↓⍵,¨¯1⌽⍵}

例:

    {×/1⌈÷/⊃⍵,¨¯1⌽⍵}  0.48 0.4 0.24 0.39 0.74 1.31 1.71 2.1 2.24 2.07 2.41
10.86634461
    {×/1⌈÷/⊃⍵,¨¯1⌽⍵}  (the 1000 array from pastebin)
321903884.6

说明:

从汇率数据开始:

    A←0.48 0.4 0.24 0.39 0.74 1.31 1.71 2.1 2.24 2.07 2.41

将每个数字与前面的数字配对(第一个与最后一个配对),然后将它们放入矩阵中:

    ⎕←M←⊃A,¨¯1⌽A
0.48 2.41
0.4  0.48
0.24 0.4
0.39 0.24
0.74 0.39
1.31 0.74
1.71 1.31
2.1  1.71
2.24 2.1
2.07 2.24
2.41 2.07

通过除法减少每一行,使比率> 1的行保持不变,并通过乘法合并比率。这将消除连续不断上升的汇率中的任何重复因素,以及第一个和最后一个汇率之间的虚假比率:

    ×/1⌈÷/M
10.86634461

您始终应该在第一个头寸上卖出的假设使较长的输入失败并返回小于1的数字(这显然是不可能的)。
Frxstrem

@Frxstrem谢谢,已修复。现在,它给出与脚本相同的结果。如果OP给了我们一些带有结果的测试用例,那将会更有帮助!
Tobia 2014年

1
我喜欢好的APL解决方案,因为每当我看它们时,它们都会触发我的“这是二进制文件乱码”过滤器,并且我开始寻找文件扩展名以弄清楚如何打开它。
Cort Ammon-恢复莫妮卡2014年

@CortAmmon并非没有根据:APL雇用了许多图形操作员;从表面上看,它们可以使您想起8位DOS字符集中的符号。它也是一种非常简洁的语言,这意味着APL行具有很高的信息熵。这两个功能结合在一起,触发了将二进制文件转储到DOS窗口的感觉。但这只会持续到您学会欣赏APL的符号和语法之美。
Tobia'1

6

Python,47岁

f=lambda t:2>len(t)or max(t[1]/t[0],1)*f(t[1:])

示例在测试用例上运行

拿一个花车清单。递归乘以前两个元素的利润因子,直到剩下少于两个元素。对于基本情况,给出True等于1

使用pop给出相同数量的字符。

f=lambda t:2>len(t)or max(t[1]/t.pop(0),1)*f(t)

从列表末尾开始也是如此。

f=lambda t:2>len(t)or max(t.pop()/t[-1],1)*f(t)

为了进行比较,我在Python 2中的迭代代码为49个字符,长2个字符

p=c=-1
for x in input():p*=max(x/c,1);c=x
print-p

首先c=-1是使虚构的第一个“动作”永远不会获利的技巧。从而-1不是1让我们同时分配这两个元素开始产品,然后在打印之前免费将其否定。


较长的测试用例超出了默认递归限制1。尽管f(x [:999])仍然给出正确的结果。对于更长的输入,您可以将其拆分为多个块([n:(n+1)*500 + 1] for n in range(N_elem/500) )并乘以局部因子
DenDenDo 2014年

递归限制取决于实现;您可以使用Stackless Python避免这种情况。
xnor

或仅使用sys.setrecursionlimit(在CPython中)
user253751

3

Python,79 81 76 77字节

f=lambda x:reduce(float.__mul__,(a/b for a,b in zip(x[1:],x[:-1]) if a>b),1.)

x是编码为列表的输入。该函数返回因子。


也许这只是我的Python版本,但我不得不使用1.,而不是1在函数的末尾,否则我得到的类型错误:描述符“ MUL ”需要“浮动”对象,但获得了“廉政”
托比亚

顺便说一句,聪明的算法!
Tobia 2014年

您不需要那f=部分。
wizzwizz4

2

CJam,33个字节

q~{X1$3$-:X*0>{\;}*}*](g\2/{~//}/

这可以打得更远。

接受来自STDIN的输入,例如

[0.48 0.4 0.24 0.39 0.74 1.31 1.71 2.1 2.24 2.07 2.41]

并将其输出到STDOUT,例如

10.866344605475046

在这里在线尝试


1

珀斯 18岁

u*GeS,1ceHhHC,QtQ1

说明:

u                 reduce, G is accumulator, H iterates over sequence
 *G               multiply G by
   eS             max(               
     ,1               1,
       ceHhH            H[1]/H[0])
 C                H iterates over zip(
  ,QtQ                                Q,Q[1:])
 1                G is initialized to 1

max(H[1]/H[0],1) 感谢@xnor


1

C#,333,313

我的第一次尝试。可能可以对其进行更多优化,但是就像我说的那样,第一次尝试可以使它如虎添翼!

double a(double [] b){var c=0.0;var d=1;for(int i=0;i<b.Count();i++){c=(d==1)?(((i+1)<b.Count()&&b[i+1]<=b[i]&&d==1)?((c==0)?b[i]:b[i]*c):((i+1)>=b.Count()?(c*b[i])/b[0]:c)):((i+1)<b.Count()&&b[i+1]>b[i]&&d==0)?c/b[i]:c;d=((i+1)<b.Count()&&b[i+1]<b[i]&&d==1)?0:((i+1)<b.Count()&&b[i+1]>b[i]&&d==0)?1:d;}return c;}

输入项

0.48, 0.4, 0.24, 0.39, 0.74, 1.31, 1.71, 2.1, 2.24, 2.07, 2.41

输出量

10.86

编辑:感谢DenDenDo建议不要使用math.floor进行舍入并使用int而不是bool来削减字符。会为将来的难题记住这一点!


嘿,谢谢你的提示。我按照建议进行了更新。
达伦·布雷恩

看起来您四舍五入到两位数Math.Floor(...)是不需要的。另外,我不知道它是否可以在C#中使用,但通常您可以对true和使用1和0 false
DenDenDo'1

抱歉,认为需要四舍五入到2,因为每个人都打印10.86,而我得到10.866并四舍五入。您可以使用其他C语言,但不能使用C#。虽然那确实给了我一个主意,所以现在我在布尔检查中使用1和0。减少更多。谢谢!
达伦·布雷恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.