Pedagang Saham Perjalanan Waktu


21

Kisah
Dahulu kala Bobby membuat dompet Bitcoin dengan 1 Satoshi (1e-8 BTC, unit mata uang terkecil) dan melupakannya. Seperti banyak orang lain, dia kemudian berkata, "Sialan, andai saja saya berinvestasi lebih banyak saat itu ...".
Tidak berhenti melamun, ia mendedikasikan seluruh waktu dan uangnya untuk membangun mesin waktu. Dia menghabiskan sebagian besar waktunya di garasinya, tidak menyadari urusan duniawi dan rumor yang beredar tentang dirinya. Dia menyelesaikan prototipe sehari sebelum listriknya akan dimatikan karena pembayaran tidak terjawab. Memandang ke atas dari meja kerjanya, dia melihat sebuah mobil polisi berhenti di rumahnya, sepertinya para tetangga yang usil mengira dia sedang menjalankan lab shabu di garasinya dan memanggil polisi.
Tanpa waktu untuk menjalankan tes, ia mengambil stik USB dengan data nilai tukar beberapa tahun terakhir, menghubungkan Flux Capacitor ke Quantum Discombobulator dan menemukan dirinya diangkut kembali ke hari ketika ia menciptakan dompetnya.

Tugas
Mengingat data nilai tukar, cari tahu berapa banyak uang yang dapat dihasilkan Bobby. Dia mengikuti aturan yang sangat sederhana: "Beli rendah - jual tinggi" dan karena ia mulai dengan modal yang sangat kecil, kami menganggap bahwa tindakannya tidak akan berdampak pada nilai tukar dari masa depan.

Input
Daftar float> 0, baik sebagai string yang dipisahkan oleh karakter tunggal (baris baru, tab, spasi, titik koma, apa pun yang Anda suka) dilewatkan sebagai argumen baris perintah ke program, dibaca dari file teks atau STDIN atau diteruskan sebagai parameter ke suatu fungsi. Anda dapat menggunakan tipe data numerik atau array bukan string karena pada dasarnya hanya string dengan tanda kurung.

Output
Faktor di mana modal Bobbys dikalikan pada akhir perdagangan.

Contoh

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

Nilai tukar: $ 0,48 / BTC, karena akan turun, kami menjual semua Bitcoin seharga 4,8 nanodollar. Faktor = 1 Nilai tukar: 0,4, tidak melakukan apa-apa
Nilai tukar: $ 0,24 / BTC dan naik: konversi semua $ ke 2 Satoshi. Faktor = 1 (nilai dolar masih tidak berubah)
Nilai tukar: 0.39 - 2.1 $ / BTC: jangan lakukan apa pun
Nilai tukar: 2.24 $ / BTC: jual semuanya sebelum jatuhkan. 44,8 nanodollar, faktor = 9,33
Nilai tukar: $ 2,07 / BTC: beli 2,164 Satoshi, faktor = 9,33
Nilai tukar: 2,41 $ / BTC: beli 52,15 nanodolar, faktor = 10,86

Output: 10.86

Detail Tambahan
Anda dapat mengabaikan kasus tepi aneh seperti input konstan, nilai nol atau negatif, hanya satu nomor input, dll.
Jangan ragu untuk membuat nomor acak Anda sendiri untuk pengujian atau menggunakan grafik saham aktual. Ini adalah input yang lebih panjang untuk pengujian (Output yang diharapkan sekitar 321903884.638)
Jelaskan secara singkat apa yang kode Anda lakukan
Grafik dihargai tetapi tidak perlu


Jika kita mengambil angka melalui argumen fungsi, apakah masih harus berupa string, atau bisakah kita langsung mengambil array?
Martin Ender

@ MartinBüttner Saya memikirkannya sebentar, apakah inputnya berupa string, array numerik, atau pilihan bebas, selalu ada beberapa bahasa yang mendapatkan keuntungan. Tampaknya tidak ada konsensus umum mengenai hal ini, dan menulis dua program, satu untuk numerik- dan satu untuk input string dan rata-rata kedua skor sepertinya berlebihan.
DenDenDo

Bagaimana dengan Drive Infinite Improbability? :)
Gagang Pintu

2
Kembali ke masalah, apakah kita perlu membulatkan nilai BTC dan / atau $ pada presisi yang diberikan, pada setiap iterasi? Misalnya, di dunia nyata dompet BTC seseorang harus dibulatkan ke Satoshi. Ini membuat perbedaan, karena pada contoh Anda, pada 2,07 Anda hanya dapat membeli 2s (bukan 2,164); kemudian pada 2.41 2s Anda membeli Anda 48,2 n $ (bukan 52,15) sehingga faktornya adalah 10,04 (bukan 10,86). Kecuali Anda menyimpan $ wallet terpisah dengan perubahan dan perlu menambahkannya kembali setiap kali. Bagaimana dengan dolar? Adakah yang sekarang bisa mengklaim memiliki nanodollar? Saya percaya jumlah terkecil yang dapat ditampung adalah 1 ¢.
Tobia

1
@CortAmmon: Anda mengatakan bahwa perdagangan BTC tidak kacau? ;-)
Steve Jessop

Jawaban:


10

APL, 16 karakter

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

Versi ini menggunakan @Frxstrem 's algoritma sederhana dan @xnor ' s max(r,1)ide.

Ini juga mengasumsikan bahwa seri meningkat secara keseluruhan, yaitu, nilai bitcoin pertama lebih kecil daripada yang terakhir. Ini konsisten dengan deskripsi masalah. Untuk mendapatkan formula yang lebih umum, pasangan tarif pertama harus dijatuhkan, dengan menambahkan 2 karakter:{×/1⌈÷/⊃1↓⍵,¨¯1⌽⍵}

Contoh:

    {×/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

Penjelasan:

Mulai dengan data nilai tukar:

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

Pasangkan setiap angka dengan yang sebelumnya (yang pertama akan dipasangkan dengan yang terakhir) dan masukkan ke dalam matriks:

    ⎕←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

Kurangi setiap baris dengan pembagian, pertahankan dengan rasio> 1, dan gabungkan rasio dengan penggandaan. Ini akan menghilangkan faktor berulang dalam serangkaian kenaikan berturut-turut, serta rasio palsu antara nilai tukar pertama dan terakhir:

    ×/1⌈÷/M
10.86634461

Asumsi Anda bahwa Anda harus selalu menjual pada posisi pertama membuat input yang lebih lama gagal dan mengembalikan angka kurang dari 1 (yang jelas tidak mungkin).
Frxstrem

@Frxstrem terima kasih, sudah diperbaiki. Sekarang hasilnya sama dengan skrip Anda. Akan lebih membantu jika OP memberi kami beberapa uji kasus dengan hasil!
Tobia

1
Saya suka solusi APL yang bagus karena, setiap kali saya melihatnya, mereka memicu filter "ini adalah file biner" dan saya mulai mencari ekstensi file untuk mencari cara membukanya.
Cort Ammon - Reinstate Monica

@CortAmmon yang sama sekali tidak berdasar: APL mempekerjakan banyak selusin operator grafis; di permukaan mereka dapat mengingatkan Anda tentang simbol dari set karakter DOS 8-bit. Ini juga merupakan bahasa yang sangat singkat, yang berarti bahwa garis APL memiliki entropi informasi yang sangat tinggi. Kedua fitur ini bergabung untuk memicu perasaan file biner yang dibuang ke jendela DOS. Tapi itu hanya berlangsung sampai Anda belajar untuk menghargai keindahan simbol dan sintaks APL.
Tobia

6

Python, 47

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

Contoh dijalankan pada test case .

Ambil daftar pelampung. Mengalikan faktor laba secara dua kali lipat dari dua elemen pertama hingga tersisa kurang dari dua elemen. Untuk kasus dasar, berikan Trueyang sama dengan 1.

Menggunakan popmemberi jumlah karakter yang sama.

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

Begitu juga dengan pergi dari akhir daftar.

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

Sebagai perbandingan, kode berulang saya di Python 2 adalah 49 karakter, 2 karakter lebih lama

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

Dimulai dengan c=-1adalah hack untuk membuat "langkah" imajiner pertama yang tidak pernah menunjukkan untung. Dengan memulai produk -1daripada 1membiarkan kami menetapkan kedua elemen bersama-sama, dan kami negatifkan kembali secara gratis sebelum mencetak.


Testcase yang lebih panjang melebihi batas rekursi default sebesar 1. f (x [: 999]) masih memberikan hasil yang benar. Untuk input yang lebih lama Anda dapat membaginya menjadi beberapa bagian ([n:(n+1)*500 + 1] for n in range(N_elem/500) )dan melipatgandakan faktor parsial
DenDenDo

Batas rekursi tergantung pada implementasi; Anda dapat menggunakan Stackless Python untuk menghindarinya.
xnor

Atau cukup gunakan sys.setrecursionlimit(dalam CPython)
user253751

3

Python, 79 81 76 77 byte

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

xadalah input yang dikodekan sebagai daftar. Fungsi mengembalikan faktor.


Mungkin ini hanya versi Python saya, tetapi saya harus menggunakan 1.alih-alih 1di akhir fungsi, jika tidak saya mendapatkan TypeError: deskriptor ' mul ' memerlukan objek 'float' tetapi menerima 'int'
Tobia

BTW, algoritma pintar!
Tobia

Anda tidak perlu f=bagian itu.
wizzwizz4

2

CJam, 33 byte

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

Ini bisa bermain golf lebih lanjut.

Mengambil input dari STDIN, seperti

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

dan menampilkan faktor ke STDOUT, seperti

10.866344605475046

Cobalah online di sini


1

Pyth , 18

u*GeS,1ceHhHC,QtQ1

Penjelasan:

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) ide terima kasih kepada @xnor


1

C #, 333 , 313

Upaya pertama saya. Mungkin bisa lebih mengoptimalkannya tetapi seperti saya katakan upaya pertama jadi akan terbiasa !.

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;}

Memasukkan

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

Keluaran

10.86

Sunting: Terima kasih kepada DenDenDo karena menyarankan untuk tidak menggunakan math.floor untuk membulatkan dan menggunakan int alih-alih bool untuk memotong karakter. Akan ingat itu untuk puzzle masa depan!


Heya, terima kasih atas tipsnya. Saya memperbarui seperti yang disarankan.
Darren Breen

Sepertinya Anda membulatkan ke dua digit Math.Floor(...)yang tidak diperlukan. Juga, saya tidak tahu apakah itu mungkin dalam C #, tetapi biasanya Anda dapat menggunakan 1 dan 0 untuk truedan false.
DenDenDo

Maaf, diperlukan pemikiran pembulatan ke 2 karena semua orang mencetak 10.86 dan saya mendapatkan 10.866 dan mengumpulkan. Anda bisa untuk bahasa c lain tetapi tidak untuk C #. Meskipun itu memberi saya ide, jadi saya sekarang menggunakan 1 dan 0 untuk cek boolean saya. Mengurangi sedikit lebih banyak. Terima kasih!
Darren Breen
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.