Nhà kinh doanh chứng khoán du hành thời gian


21

Câu chuyện
cách đây rất lâu, Bobby đã tạo ra một ví Bitcoin với 1 Satoshi (1e-8 BTC, đơn vị tiền tệ nhỏ nhất) và quên nó. Giống như nhiều người khác, sau này anh ta nói "Chết tiệt, nếu tôi đầu tư nhiều hơn thì ...".
Không dừng lại ở mơ mộng, anh dành toàn bộ thời gian và tiền bạc để xây dựng cỗ máy thời gian. Anh dành phần lớn thời gian trong nhà để xe của mình, không biết gì về những chuyện trần tục và những tin đồn xoay quanh anh. Anh ta hoàn thành nguyên mẫu một ngày trước khi điện của anh ta bị tắt do thanh toán bị bỏ lỡ. Nhìn lên từ bàn làm việc của anh ta, anh ta thấy một chiếc xe cảnh sát kéo đến nhà anh ta, có vẻ như những người hàng xóm tò mò nghĩ rằng anh ta đang điều hành một phòng thí nghiệm meth trong nhà để xe của mình và gọi cảnh sát.
Không có thời gian để chạy thử nghiệm, anh ta lấy một chiếc USB với dữ liệu tỷ giá hối đoái của những năm trước, kết nối Tụ thông lượng với Bộ giải mã lượng tử và thấy mình được vận chuyển trở lại vào ngày khi anh ta tạo ra ví của mình

Nhiệm vụ
Đưa ra dữ liệu tỷ giá hối đoái, tìm hiểu xem Bobby có thể kiếm được bao nhiêu tiền. Anh ấy tuân theo một quy tắc rất đơn giản: "Mua thấp - bán cao" và vì anh ấy bắt đầu với một số vốn cực kỳ nhỏ, chúng tôi cho rằng hành động của anh ấy sẽ không ảnh hưởng đến tỷ giá hối đoái trong tương lai.

Đầu vào
Một danh sách các float> 0, dưới dạng một chuỗi được phân tách bằng một ký tự đơn (dòng mới, tab, dấu cách, dấu chấm phẩy, bất cứ thứ gì bạn thích) được truyền dưới dạng đối số dòng lệnh cho chương trình, đọc từ tệp văn bản hoặc STDIN hoặc được truyền dưới dạng tham số đến một chức năng. Bạn có thể sử dụng kiểu dữ liệu số hoặc mảng thay vì chuỗi vì về cơ bản nó chỉ là một chuỗi có dấu ngoặc.

Đầu ra
Yếu tố mà vốn Bobbys nhân với khi kết thúc giao dịch.

Thí dụ

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

Tỷ giá hối đoái: 0,48 đô la / BTC, vì sắp giảm giá, chúng tôi bán tất cả Bitcoin với giá 4,8 nanodollar. Yếu tố = 1 Tỷ giá hối đoái: 0,4, không làm gì
Tỷ giá hối đoái: 0,24 $ / BTC và tăng: chuyển đổi tất cả $ thành 2 Satoshis. Yếu tố = 1 (giá trị đồng đô la vẫn không thay đổi)
Tỷ giá: 0,39 - 2,1 $ / BTC: không làm gì
Tỷ giá hối đoái: 2,24 $ / BTC: bán mọi thứ trước khi giảm. 44,8 nanodollar, hệ số = 9,33
Tỷ giá hối đoái: 2,07 $ / BTC: mua 2,164 Satoshis, hệ số = 9,33
Tỷ giá hối đoái: 2,41 $ / BTC: mua 52,15 nanodollar, hệ số = 10,86

Output: 10.86

Chi tiết bổ sung
Bạn có thể bỏ qua các trường hợp cạnh kỳ lạ như đầu vào không đổi, giá trị 0 hoặc âm, chỉ một số đầu vào, v.v.
Hãy thoải mái tạo số ngẫu nhiên của riêng bạn để kiểm tra hoặc sử dụng biểu đồ chứng khoán thực tế. Đây là một đầu vào dài hơn để thử nghiệm (Đầu ra dự kiến ​​khoảng 321903884.638)
Giải thích ngắn gọn những gì mã của bạn làm
Đồ thị được đánh giá cao nhưng không cần thiết


Nếu chúng ta lấy các số thông qua đối số hàm, nó vẫn phải là một chuỗi hay chúng ta có thể lấy trực tiếp một mảng không?
Martin Ender

@ MartinBüttner Tôi đã suy nghĩ về nó một thời gian, cho dù đầu vào là một chuỗi, một mảng số hay một sự lựa chọn miễn phí, luôn có một số ngôn ngữ có lợi thế. Dường như không có sự đồng thuận chung về điều này, và viết hai chương trình, một cho số - và một cho đầu vào chuỗi và tính trung bình cả hai điểm có vẻ như quá mức cần thiết.
DenDenDo

Điều gì về Ổ đĩa Khả năng Vô hạn? :)
Doorknob

2
Quay trở lại vấn đề, chúng ta có cần làm tròn các giá trị BTC và / hoặc $ với độ chính xác nhất định, trên mỗi lần lặp không? Ví dụ: trong thế giới thực, ví BTC phải được làm tròn thành Satoshi. Điều này tạo ra sự khác biệt, bởi vì trong ví dụ của bạn, tại 2.07, bạn chỉ có thể mua 2 giây (không phải 2.164); sau đó tại 2,41 số 2 của bạn mua cho bạn 48,2 n $ (không phải 52,15) nên hệ số là 10,04 (không phải 10,86). Trừ khi bạn giữ một ví $ riêng biệt với thay đổi và cần thêm lại mỗi lần. Còn đô la thì sao? Bất cứ ai ngày nay có thể tuyên bố có một nanodollar? Tôi tin rằng số tiền nhỏ nhất người ta có thể giữ là 1.
Tobia

1
@CortAmmon: bạn đang nói rằng giao dịch BTC không hỗn loạn? ;-)
Steve Jessop

Câu trả lời:


10

APL, 16 ký tự

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

Phiên bản này sử dụng @Frxstrem 's thuật toán đơn giản và @xnor ' s max(r,1)ý tưởng.

Nó cũng giả định rằng chuỗi này đang tăng tổng thể, nghĩa là giá trị bitcoin đầu tiên nhỏ hơn giá trị cuối cùng. Điều này phù hợp với mô tả vấn đề. Để có được một công thức tổng quát hơn, phải bỏ một vài tỷ lệ đầu tiên, thêm 2 ký tự:{×/1⌈÷/⊃1↓⍵,¨¯1⌽⍵}

Thí dụ:

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

Giải trình:

Bắt đầu với dữ liệu tỷ giá hối đoái:

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

Ghép từng số với số trước (số đầu tiên sẽ được ghép với số cuối) và đặt chúng vào ma trận:

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

Giảm từng hàng bằng cách chia, giữ những hàng có tỷ lệ> 1 và kết hợp các tỷ lệ bằng cách nhân. Điều này sẽ loại bỏ bất kỳ yếu tố lặp lại nào liên tiếp trong tỷ lệ tăng liên tiếp, cũng như tỷ lệ giả giữa tỷ giá hối đoái đầu tiên và cuối cùng:

    ×/1⌈÷/M
10.86634461

Giả định của bạn rằng bạn nên luôn luôn bán ở vị trí đầu tiên làm cho đầu vào dài hơn thất bại và trả về một số nhỏ hơn 1 (điều này rõ ràng là không thể).
Frxstrem

@Frxstrem cảm ơn, đã sửa. Bây giờ nó cho kết quả giống như kịch bản của bạn. Sẽ hữu ích hơn nếu OP đã cho chúng tôi một vài trường hợp thử nghiệm với kết quả!
Tobia

1
Tôi yêu các giải pháp APL tốt bởi vì, bất cứ khi nào tôi nhìn vào chúng, chúng sẽ kích hoạt bộ lọc "đây là tệp nhị phân" và tôi bắt đầu tìm kiếm một phần mở rộng tệp để tìm ra cách mở nó.
Cort Ammon - Phục hồi Monica

@CortAmmon hoàn toàn không có cơ sở: APL sử dụng nhiều tá toán tử đồ họa; trên bề mặt, chúng có thể nhắc nhở bạn về các ký hiệu từ các bộ ký tự DOS 8 bit. Nó cũng là một ngôn ngữ rất ngắn gọn, có nghĩa là một dòng APL có entropy thông tin rất cao. Hai tính năng này kết hợp để kích hoạt cảm giác của tệp nhị phân được đổ vào cửa sổ DOS. Nhưng nó chỉ tồn tại cho đến khi bạn học cách đánh giá cao vẻ đẹp của các biểu tượng và cú pháp của APL.
Tobia

6

Con trăn, 47

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

Ví dụ chạy trên trường hợp thử nghiệm .

Lấy một danh sách các phao. Nhân lên một cách đệ quy trên hệ số lợi nhuận từ hai yếu tố đầu tiên cho đến khi vẫn còn ít hơn hai yếu tố. Đối với trường hợp cơ sở, cho Truemà bằng 1.

Sử dụng popcho cùng một số ký tự.

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

Vì vậy, đi từ cuối danh sách.

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

Để so sánh, mã lặp của tôi trong Python 2 là 49 ký tự, dài hơn 2 ký tự

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

Bắt đầu với c=-1một hack để làm cho "di chuyển" tưởng tượng đầu tiên không bao giờ hiển thị lợi nhuận. Bắt đầu sản phẩm -1thay vì 1cho phép chúng tôi gán cả hai yếu tố lại với nhau và chúng tôi phủ định lại miễn phí trước khi in.


Testcase dài hơn vượt quá giới hạn đệ quy mặc định bởi 1. f (x [: 999]) vẫn cho kết quả chính xác. Để đầu vào dài hơn, bạn có thể chia nó thành nhiều phần ([n:(n+1)*500 + 1] for n in range(N_elem/500) )và nhân các yếu tố một phần
DenDenDo

Giới hạn đệ quy là phụ thuộc thực hiện; bạn có thể sử dụng Stackless Python để tránh nó.
xnor

Hoặc chỉ sử dụng sys.setrecursionlimit(trong 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.)

xlà đầu vào được mã hóa dưới dạng một danh sách. Hàm trả về thừa số.


Có thể đó chỉ là phiên bản Python của tôi, nhưng tôi phải sử dụng 1.thay vì 1ở cuối chức năng, nếu không, tôi nhận được TypeError: descriptor ' mul ' yêu cầu một đối tượng 'float' nhưng đã nhận được 'int'
Tobia

BTW, thuật toán thông minh!
Tobia

Bạn không cần f=phần đó .
wizzwizz4


1

Bình thường , 18

u*GeS,1ceHhHC,QtQ1

Giải trình:

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) ý tưởng nhờ @xnor


1

C #, 333 , 313

Nỗ lực đầu tiên của tôi. Có lẽ có thể tối ưu hóa nó nhiều hơn nhưng như tôi đã nói lần thử đầu tiên nên sẽ hiểu được!

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

Đầu vào

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

Đầu ra

10.86

Chỉnh sửa: Cảm ơn DenDenDo đã đề xuất không sử dụng math.floor để làm tròn và sử dụng int thay vì bool để cắt ký tự. Sẽ nhớ rằng cho các câu đố trong tương lai!


Heya, cảm ơn vì lời khuyên. Tôi cập nhật theo đề nghị.
Darren Breen

Có vẻ như bạn đang làm tròn đến hai chữ số Math.Floor(...)không bắt buộc. Ngoài ra, tôi không biết liệu nó có thể có trong C # hay không, nhưng thông thường bạn có thể sử dụng 1 và 0 cho truefalse.
DenDenDo

Xin lỗi, nghĩ làm tròn đến 2 là bắt buộc vì mọi người đều in 10,86 và tôi đã nhận được 10.866 và làm tròn số. Bạn có thể cho các ngôn ngữ c khác nhưng không cho C #. Mặc dù điều đó đã cho tôi một ý tưởng, vì vậy hiện đang sử dụng 1 và 0 cho các kiểm tra boolean của tôi. Giảm thêm một chút. Cảm ơn!
Darren Breen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.