タイムトラベリングストックトレーダー


21

ストーリー
かなり前に、ボビーは1サトシ(1e-8 BTC、最小通貨単位)でビットコインウォレットを作成し、それを忘れていました。他の多くの人と同じように、彼は後に「くそー、もし私がもっともっと投資すれば...」。
空想にとどまらず、彼は時間とお金のすべてをタイムマシンの構築に捧げます。彼は自分の時間の大部分をガレージで過ごし、世間の出来事や彼についての噂を知らない。彼は、支払いを逃し、電気が切れようとする1日前にプロトタイプを完成させました。ワークベンチから見上げると、彼は警察のバンが彼の家に引っ張っているのを見ます。
テストを実行する時間がないため、彼は過去数年間の為替レートのデータをUSBスティックで取得し、Flux CapacitorをQuantum Discombobulatorに接続して、自分がウォレットを作成した日に戻されていることに気付きました。

タスク
為替レートデータが与えられたら、ボビーが稼ぐことができる金額を調べます。彼は非常に単純なルールに従います:「低価格で購入-高価格で販売」そして彼は無限に小さな資本でスタートするので、彼の行動は将来の為替レートに影響を与えないと仮定します。

入力
プログラムにコマンドライン引数として渡される、テキストファイルまたはSTDINから読み取られる、またはパラメーターとして渡される、単一の文字(改行、タブ、スペース、セミコロン、任意の文字)で区切られた文字列としての0以上のfloatのリスト関数に。文字列の代わりに数値データ型または数値配列を使用できます。これは、基本的に角括弧付きの文字列だからです。

アウトプット
ボビーズの資本に取引の終了を掛けた係数。

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 Satoshisを購入、ファクター= 9.33
為替レート:2.41 $ / BTC:52.15ナノドルを購入、ファクター= 10.86

Output: 10.86

追加の詳細
一定の入力、ゼロまたは負の値、1つの入力番号など、奇妙なエッジケースは無視でき
ます。実際の株価チャートをテストまたは使用するために、独自の乱数を生成してください。ここでテストするための長い入力された(約予想される出力は。321903884.638)
簡単に言うが、あなたのコードが何をするかを説明し
たグラフは感謝必ずしも必要ではないされています


関数の引数を使用して数値を取得する場合、文字列である必要がありますか、それとも配列を直接取得できますか?
マーティンエンダー14

@MartinBüttner入力については文字列、数値配列、または自由選択のいずれであっても、しばらくの間それについて熟考しました。これに関する一般的なコンセンサスはないようで、2つのプログラムを作成します。1つは数値入力用、もう1つは文字列入力用で、両方のスコアを平均化することはやり過ぎのようです。
DenDenDo

Infinite Improbability Driveはどうですか?:)
ドアノブ

2
問題に戻って、繰り返しごとにBTCや$値を特定の精度で丸める必要がありますか?たとえば、現実世界では、BTCウォレットはSatoshiに丸められなければなりません。これは違いを生みます。この例では、2.07で2枚しか購入できない(2.164ではない)ためです。その後、2.41で2が48.2 n $(52.15ではない)を購入するため、係数は10.04(10.86ではない)になります。変更時に別の$ウォレットを保持し、そのたびに追加する必要がある場合を除きます。ドルはどうですか?今日誰かがナノドルを持っていると主張できますか?私が保持できる最小量は1¢だと思います。
トビア14

1
@CortAmmon:BTCの取引混tradingではないと言っているのですか?;-)
スティーブジェソップ14

回答:


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が結果を含むいくつかのテストケースを提供してくれた場合、もっと役に立ちました。
トビア14

1
良いAPLソリューションが大好きです。なぜなら、それらを見るたびに「this is binary file gibberish」フィルターがトリガーされ、それを開く方法を見つけるためにファイル拡張子を探し始めるからです。
コートアンモン-復帰モニカ14

@CortAmmonはまったく根拠がないわけではありません。APLは多数のグラフィック演算子を使用しています。表面上では、8ビットDOS文字セットの記号を思い出させることができます。また、非常に簡潔な言語です。つまり、APLの行には非常に高い情報エントロピーがあります。これら2つの機能を組み合わせて、DOSウィンドウにダンプされたバイナリファイルの感覚をトリガーします。しかし、APLのシンボルと構文の美しさを理解するまで、それは続きます。
トビア

6

Python、47

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

テストケースで実行する例

フロートのリストを取得します。最初の2つの要素からの利益係数を、2つ未満の要素が残るまで再帰的に乗算します。基本ケースでは、Truewhichがに等しくなり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

再帰制限は実装に依存します。Stackless Pythonを使用して回避できます。
xnor 14

それとも使用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、関数の最後にそれ以外の場合はI GET例外TypeError:ディスクリプタが「MULは」「フロート」オブジェクトが必要ですが、「INT」を受け取った
トビア

ところで、スマートアルゴリズム!
トビア14

そのf=部分は必要ありません。
wizzwizz4


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

編集:math.floorを使用して丸めず、boolの代わりにintを使用してcharをカットすることを提案してくれたDenDenDoに感謝します。将来のパズルのためにそれを覚えているでしょう!


へや、ヒントをありがとう。提案どおりに更新しました。
ダレンブリーン

Math.Floor(...)必要のない2桁に丸めているようです。また、私はC#でその可能かどうかわからないが、通常、あなたがのために1と0を使用することができるtruefalse
-DenDenDo

申し訳ありませんが、誰もが10.86を印刷しており、10.866を取得して切り上げていたため、2に丸める必要があると考えました。他のc言語では可能ですが、C#ではできません。それは私にアイディアを与えたので、今では私のブールチェックに1と0を使用しています。それをもう少し減らしました。ありがとう!
ダレンブリーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.