Zaman Yolculuğu Borsa Yatırımcısı


21

Hikaye
Uzun zaman önce Bobby, 1 Satoshi (1e-8 BTC, en küçük para birimi) ile bir Bitcoin cüzdanı yarattı ve unuttu. Diğerleri gibi daha sonra "Kahretsin, sadece daha sonra yatırım yaparsam ..." demiştir.
Hayal kurmayı bırakmamak, tüm zamanını ve parasını bir zaman makinesi kurmaya adamıştır. Zamanının çoğunu garajında ​​geçiriyor, dünyevi olaylardan habersiz ve onunla ilgili dolaştığı söylentileri. Prototipi, eksik ödemeler nedeniyle elektriğinin kesilmesinden bir gün önce tamamlar. Çalışma masasından bakarken, evine giden bir polis minibüsü görüyor, meraklı komşular garajında ​​bir laboratuar çalıştığını ve polis çağırdığını sanıyor.
Testler yapması için zaman kaybetmeden geçmiş yılların döviz kurundaki bir USB çubuğunu kaptı, Akı Kapasitörünü Kuantum Discombobulator'a bağladı ve cüzdanını yarattığı güne kadar taşınıyor

Görev
Döviz kuru verileri göz önüne alındığında, Bobby'nin ne kadar para kazanabileceğini öğrenin. Çok basit bir kurala uyuyor: "Düşük al - sat yüksek" ve çok küçük bir sermaye ile başladığından, eylemlerinin gelecekteki döviz kurlarını etkilemeyeceğini varsayıyoruz.

Giriş
Programa komut satırı argümanı olarak iletilen, bir metin dosyasından veya STDIN'den okunan veya bir parametre olarak iletilen, tek bir karakterle ayrılmış bir dize (yeni satır, sekme, boşluk, noktalı virgül, ne istersen) olan bir kayanlar listesi bir işleve. Dize yerine sayısal veri türleri veya diziler kullanabilirsiniz, çünkü temelde yalnızca köşeli ayraçlar içeren bir dizedir.

Çıktı
Bobbys'in sermayesinin işlem sonu ile çarptığı faktör.

Örnek

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

Döviz kuru: 0.48 $ / BTC, düşmek üzere olduğu için tüm Bitcoin'leri 4.8 nanodollar'a satıyoruz. Faktör = 1 Döviz kuru: 0.4, hiçbir şey yapmayın
Döviz kuru: 0.24 $ / BTC ve yükselen: 2 $ 'ı 2 Satoshis'e dönüştürün. Faktör = 1 (dolar değeri hala değişmedi)
Döviz kuru: 0,39 - 2,1 ABD Doları / BTC: hiçbir şey yapmaz
Döviz Kuru: 2,24 ABD Doları / BTC: her şey düşmeden önce satar. 44.8 nanodollar, faktör = 9.33
Döviz kuru: 2.07 $ / BTC: 2.164 Satoshis al, faktör = 9.33
Döviz kuru: 2.41 $ / BTC: 52.15 nanodollar al, faktör = 10.86

Output: 10.86

Ek Detaylar
Sabit giriş, sıfır veya negatif değerler, yalnızca bir giriş numarası vb. Gibi garip kenar durumlarını göz ardı edebilirsiniz
. Gerçek stok çizelgelerini test etmek veya kullanmak için kendi rastgele numaralarınızı oluşturmaktan çekinmeyin. İşte test etmek için daha uzun bir girdidir (yaklaşık Beklenen çıktı. 321.903.884,638)
kısaca kod ne anlatmak
Grafikler takdir fakat gerekli değildir


Sayıları fonksiyon argümanı ile alırsak, hala bir dize olmak zorunda mı yoksa doğrudan bir dizi mi alabiliriz?
Martin Ender

@ MartinBüttner Bir süre bunun hakkında düşündüm; giriş bir dize, sayısal bir dizi ya da serbest bir seçim olsun, her zaman avantaj sağlayan bazı diller vardır. Bu konuda genel bir fikir birliğine varılmış gibi görünmüyor ve iki program yazıyor, biri sayısal, diğeri de girdi girişi ve her iki puanın ortalaması da fazladan görünüyor.
DenDenDo

Sonsuz Olanaksızlık Süreci ne olacak? :)
Doorknob

2
Soruna geri dönersek, BTC ve / veya $ değerlerini her bir kesinlikte belirli bir hassasiyette yuvarlamamız gerekir mi? Örneğin, gerçek dünyada BTC cüzdanı Satoshi'ye yuvarlatılmalıdır. Bu fark yaratır, çünkü örneğinizde, 2.07'de sadece 2s satın alabilirsiniz (2.164'ü değil); o zaman 2.41'de, 2'leriniz size 48.2 n $ (52.15 değil) alır, yani faktör 10.04 (10.86 değil) olur. Değişikliği olan ayrı bir $ cüzdanınız olmadığı sürece ve her seferinde geri eklemeniz gerekir. Peki ya dolar? Bugün herhangi biri nanodollar olduğunu iddia edebilir mi? İnsanın alabileceği en küçük miktarın 1 ¢ olduğuna inanıyorum.
Tobia

1
@CortAmmon: BTC ticaretinin kaotik olmadığını mı söylüyorsunuz ? ;-)
Steve Jessop

Yanıtlar:


10

APL, 16 karakter

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

Bu sürüm kullanan @Frxstrem 'ın daha basit bir algoritma ve @xnor ' ın max(r,1)fikrini.

Ayrıca, serinin genel olarak yükseldiğini, yani ilk bitcoin değerinin sonuncusundan daha küçük olduğunu varsayar. Bu, sorun açıklamasıyla tutarlıdır. Daha genel bir formül elde etmek için, ilk iki oran düşürülmeli ve 2 karakter eklenmeli:{×/1⌈÷/⊃1↓⍵,¨¯1⌽⍵}

Örnek:

    {×/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çıklama:

Döviz kuru verileriyle başlayın:

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

Her sayıyı bir öncekiyle eşleştirin (ilki en sonuncuyla eşleştirilir) ve bunları bir matrise koyun:

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

Her satırı bölmeye göre azaltın, oranı> 1 olanlarda tutun ve oranları çarpma ile birleştirin. Bu, art arda yükselen oranlar sırasındaki yinelenen faktörleri ve ayrıca ilk ve son döviz kurları arasındaki sahte oranı ortadan kaldıracaktır:

    ×/1⌈÷/M
10.86634461

Her zaman birinci konumda satmanız gerektiği varsayımınız daha uzun girişin başarısız olmasına neden olur ve 1'den küçük bir sayı döndürür (bu kesinlikle mümkün değildir).
Frxstrem

@ Frxstrem teşekkürler, düzeltildi. Şimdi betiğinizle aynı sonucu veriyor. OP bize sonuçlarla birkaç test davası vermiş olsaydı daha yararlı olurdu!
Tobia

1
İyi APL çözümlerini seviyorum, çünkü ne zaman onlara baksam, "bu ikili dosya anlamsız" süzgecimi tetikliyorlar ve nasıl açılacağını bulmak için bir dosya uzantısı aramaya başlıyorum.
Cort Ammon - Monica,

Asla temelsiz olmayan @CortAmmon: APL birçok düzine grafik operatörünü kullanıyor; yüzeyde size 8 bitlik DOS karakter kümelerindeki simgeleri hatırlatabilirler. Aynı zamanda çok özlü bir dildir, yani bir APL hattı çok yüksek bilgi entropisine sahiptir. Bu iki özellik bir DOS penceresine atılan ikili bir dosya hissini tetiklemek için birleştirir. Ancak APL'nin sembollerinin ve sözdiziminin güzelliğini takdir etmeyi öğrenene kadar sürer.
Tobia,

6

Python, 47

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

Test senaryosundaki örnek çalışma .

Yüzenlerin bir listesini alın. İlk iki unsurdan iki unsurdan daha az kalana kadar kar faktörü üzerinde tekrar tekrar çoğalır. Temel durum için, Truehangi eşittir verir 1.

Kullanmak popaynı sayıda karakter verir.

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

Yani listenin sonundan gidiyor.

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

Karşılaştırma için, Python 2'deki yinelemeli kodum 49 karakter, 2 karakter daha uzun

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

Başlamak c=-1, hayali ilk "hamleyi" asla kar göstermemesi için bir kesmek. Ürünü, her iki öğeyi birlikte atamamıza izin vermek -1yerine başlatmak ve 1yazdırmadan önce ücretsiz olarak geri göndermek istiyoruz.


Uzun test çantası varsayılan özyineleme sınırını 1 değerini aşıyor. F (x [: 999]) yine de doğru sonucu veriyor. Daha uzun girdiler için parçalara bölebilir ([n:(n+1)*500 + 1] for n in range(N_elem/500) )ve kısmi faktörleri çoğaltabilirsiniz
DenDenDo

Özyineleme sınırı uygulamaya bağlıdır; önlemek için Stackless Python kullanabilirsiniz .
xnor

Veya sadece kullanın sys.setrecursionlimit(
CPython'da

3

Python, 79 81 76 77 bayt

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

xliste halinde kodlanmış bir giriştir. İşlev faktörü döndürür.


Belki de sadece benim Python sürümü, ama kullanmak zorunda 1.yerine 1, işlevi sonunda aksi takdirde olsun TypeError: açıklayıcısı ' mul ' bir float nesneyi gerektirir ama bir 'int' Alınan
Tobia

Btw, akıllı algoritma!
Tobia,

O f=kısma ihtiyacın yok .
wizzwizz4

2

CJam, 33 bayt

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

Bu daha fazla golf oynayabilir.

Gibi, STDIN girdi alır

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

ve faktörü STDOUT gibi çıktılar

10.866344605475046

Burada çevrimiçi deneyin


1

Pyth , 18

u*GeS,1ceHhHC,QtQ1

Açıklama:

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 sayesinde fikir


1

C #, 333 , 313

İlk denemem. Muhtemelen daha fazla optimize etmek mümkün olabilir ama dediğim gibi ilk denemem bu yüzden onu asmak!

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

Giriş

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

Çıktı

10.86

Düzenleme: math.floor'u yuvarlamak için kullanmamanızı ve karakterleri kesmek için bool yerine int kullanmasını önerdiğiniz için DenDenDo'ya teşekkürler. Bunu gelecek bulmacalar için hatırlayacağım!


Heya, ipuçları için teşekkürler. Önerildiği gibi güncellendi.
Darren Breen

Math.Floor(...)Zorunlu olmayan iki rakama yuvarlanıyor gibisiniz . Ayrıca, C # olası olmadığını bilmiyorum, ama genelde sizin için 1 ve 0 kullanabilir trueve false.
DenDenDo

Üzgünüm, düşünce 2'ye yuvarlama gerekliydi çünkü herkes 10.86'yı basıyordu ve ben 10.866'yı topluyordum. Diğer c dilleri için yapabilirsiniz, ancak C # için değil. Bu bana bir fikir vermiş olsa da şimdi boolean çeklerim için 1 ve 0 kullanıyorum. Biraz daha azaltılmış. Teşekkürler!
Darren Breen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.