Güvenli geçiş için trol ücretini hesapla


12

Esinlenen /puzzling//q/626


Maceralarınızda geçmeniz gereken 7 köprü dizisine varıyorsunuz. Her köprünün altında bir trol yaşıyor. Köprüden geçmek için önce trollere taşıdığınız keklerin yüzdesi olarak bir dizi kek vermelisiniz. Bunlar nazik troller olduğu için size belirli sayıda kek verecekler.

Her günün başında, yerel trol kralı her gezginin ödemesi gereken kek vergisi yüzdesini ve trol kek geri ödemesini - her trolün gezginlere geri vermesi gereken kek sayısını belirler.

İşiniz, o gün verilen koşullar için 7 trol köprüsünün tümünü geçmek için gereken minimum kek sayısını hesaplamaktır.

varsayalım:

  1. İki giriş parametresi: yüzde kek vergisi (0 ile 100 arasında tam sayı) ve kek geri ödeme.
  2. Hiç kimse, trol bile değil, kısmen başka bir trol tarafından yenen bir pasta istemez. Bir pastanın bir kısmı ile bırakılırsa, trol onu alır.
  3. Bir trol kek vergisini kabul eder, ancak daha sonra size tüm kekleri geri vermek zorunda kalırsa (eskisinden daha fazla veya daha az kek bırakılır), kızar ve sizi ve keklerinizi yiyecektir.
  4. Her trolde en az bir tam kek kalmalıdır.
  5. En fazla 100 kek taşıyabilirsiniz.
  6. Bulunduğunuz günü veya 7 köprünün diğer tarafındaki günü sonlandırmanız gerekir.

Meydan okuma:

Geçerli gün için seyahat etmek için minimum kek sayısını veya bugün güvenli bir şekilde seyahat etmek mümkün değilse, sıfır kek sayısını çıkarmak için tam bir program yazın - sayıların yarın ne olduğunu görmek için bekleyeceksiniz.

Giriş stdin, komut satırı bağımsız değişkenleri veya dosya girişi olarak geçirilmelidir.

En kısa kod (bayt sayısı) kazanır.

Misal:

% 25 kek vergisi, 2 trol pastası iadesi.


trol 1'den önce 19 kek ile başlayın : (19 * 0.75) =
trol 1'den sonra 14.25 : (14 + 2) = 16

trol 2'den önce: (16 * 0.75) = 12
trol 2'den sonra: (12 + 2) = 14

vb.

19 kek -> 16 -> 14 -> 12 -> 11 -> 10 -> 9 -> 8
18 kek -> 15 -> 13 -> 11 -> 10 -> 9 -> 8 -> 8 (kural 3)

18 kek için, son trol kek kalmayacaktı. Bu nedenle,% 25/2 gün için minimum kek sayısı 19'dur.

input: 25 2
output: 19

Örnek 2:

% 90 kek vergisi, 1 trol pastası iadesi

100 kek -> 11 -> 2 -> 1 (kural 4)

Üçüncü trol pastayı tutamadı. Bu nedenle, maksimum kek sayısından başlayarak bile% 90/1 günde seyahat etmek mümkün değildir.

input: 90 1
output: 0

Veri

Giriş ve çıkış değerlerinin hızlı bir grafiğini oluşturun. Bu "pürüzsüz" (bir çan eğrisi veya benzeri gibi) değildi şaşırdım; birkaç göze çarpan ada var.

veri grafiği

İlgilenenler için veriler. Sütunlar% 5 aralığa bölünür, satırlar 1 kek geri ödeme aralığının birimleridir (görüntüyü döndürülmüş excel). 28 kekden daha yüksek bir geri ödeme yapılamayacağını görebilirsiniz.

27, 17, 13, 14, 15, 18, 20, 24, 53, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
47, 27, 20, 19, 19, 19, 24, 39, 48, 68, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0
67, 37, 28, 24, 23, 28, 27, 29, 50, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
87, 47, 33, 29, 27, 28, 31, 44, 37, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 57, 40, 34, 31, 29, 34, 34, 62, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 67, 48, 39, 35, 38, 37, 49, 57, 76, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 77, 53, 44, 39, 38, 47, 39, 59, 78, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 87, 60, 49, 43, 39, 40, 54, 46, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 97, 68, 54, 47, 48, 44, 44, 71, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 73, 59, 51, 48, 47, 59, 73, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 80, 64, 55, 49, 51, 49, 68, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 88, 69, 59, 58, 54, 64, 70, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 93, 74, 63, 58, 57, 54, 57, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 100, 79, 67, 59, 67, 69, 82, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 84, 71, 68, 60, 59, 77, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 89, 75, 68, 64, 74, 79, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 94, 79, 69, 67, 64, 66, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 99, 83, 78, 71, 79, 91, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 87, 78, 74, 69, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 91, 79, 77, 84, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 95, 88, 87, 74, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 99, 88, 80, 89, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 89, 84, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 98, 87, 94, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 98, 91, 84, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 99, 94, 99, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 97, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

İyi bir nokta. Basitlik için eksiksiz bir program yapın. Girdi belirtilebilir ancak sabit kodlanmadığı sürece uygun görürsünüz (güncellenmiş zorluk).

Bu CJam kaba-kuvvet için iyi bir bulmaca. Bunu yarın yapacağım

bah, bu yüzden c # güzel şeylere sahip olamaz

Kural 2, bir kekin sadece bir kısmını alma şansını ortadan kaldırıyor gibi görünüyor ve bu da varsayım 4'ü gereksiz kılıyor. Yine de örnek 2'de üçüncü trolün sadece 0,8 kek alacağını söylüyorsunuz.
Dennis

Şartnamede çatışmalar var. In 25 211 pasta durumda, sen Troll 2.75 kek vermek ve 2 geri almak trol .75 tutar böylece (+. 25) ve hayatta. In 90 12 pasta durumda, sen trol 1.8 verip trol 0,8 tutar böylece geri 1 olsun (+. 2), ancak ölürsün.
TwiNight

Yanıtlar:


6

CJam, 46 43 41 39 38 36 33 bayt

100:H,{)_7{ea:i~H@m2$*H/+@;}*>}#)

ARGV üzerinden giriş.

Çevrimiçi bir tercüman var, ancak maalesef komut satırı argümanlarını desteklemiyor. Test için, bu sürümle STDIN'den taklit edebilirsiniz:

rr]:A;
100:H,{)_7{A:i~H@m2$*H/+@;}*>}#)

ARGV tabanlı sürümün açıklaması:

100:H                                  "Push a 100 and save it in H.";
     ,                                 "Create a range (as an array) from 0 to 99.";
      {                       }#       "Find the first index in [0,1,2,...,99] for which the
                                        block produces a truthy (non-zero) value.";
       )_                              "Increment and duplicate the current array element.";
         7{                }*          "Execute the block seven times.";
           ea:i                        "Push the command-line arguments as an array of strings
                                        and convert each element to an integer";
               ~                       "Unwrap the array.";
                H@                     "Push a 100 and rotate the stack to pull up
                                        the first command line argument.";
                  m                    "Subtract (from 100).";
                   2$                  "Copy the last iterations result.";
                     *H/               "Multiply and divide by 100, deducting tax.";
                        +              "Add the refund.";
                         @;            "Rotate top three stack elements, and discard the one that 
                                        has been pulled to the top. This always leaves the last 
                                        two results on the stack.";

                             >         "Make sure that the last result was less than the second 
                                        to last. Yields 0 or 1.";
                                )      "After the # search completes, we'll get -1 if no such 
                                        index exists, or one less than the desired number if it 
                                        does, so we can just increment.";

Yığının içeriği programın sonunda otomatik olarak yazdırılır.


Kodunuz 55 2( 0yerine 100) ve 56 5( 98yerine ) için yanlış sonuçlar üretir 94. Bunun nedeni ise 100_0.55*-ive 25_0.56*-isonbahar kurban kayan nokta belirsizlik için. Anlayabildiğim kadarıyla, çiftler 31 24, 31 25, 33 21, 33 22, 33 23, 35 10, 35 12, 35 15, 35 16, 35 27, 56 1, 57 4de yanlış sonuçlar veriyor.
Dennis

1
@Dennis sabit, teşekkürler!
Martin Ender

@Dennis Bu aslında bir bayt kurtardı. Keşke CJam'ın kapanışları olsaydı, başlangıçta vergi indirimi yapan bir blok tanımlayabilirim ve iki değişken kullanmak yerine bunu kullanabilirdim. Belki STDIN yerine ARGV kullanarak bir şeyler kaydedebilirim, bir bakayım.
Martin Ender

5

CJam, 44 40 38 37 35 bayt

l~U100:M),{{_M5$-*M/3$+_@<*}7*}=]W=

Veya komut satırı bağımsız değişkenleri ve {}#hile kullanırken 33 bayt :

100:M,{){_ea:i~M@-@*M/+_@<*}7*}#)

Bunu benim ana {}#yaklaşımım olarak koymamak, Martin'in cevabından ilham alıyor.

Örnek çalışma:

Giriş:

25 2

Çıktı:

19

Bir diğeri:

Giriş:

15 14

Çıktı:

100

Nasıl çalışır

l~                       "Read the two numbers, swap and convert tax to double";
  U100:M),               "Push 0 and [0, 1, ... 100] to stack, storing 100 in M";
          {  ...  }=     "Run this code for each element until top stack element is 1";
           {...}7*       "Run this code block 7 times";
_                        "Copy the array element";
  M5$                    "Push 100 and a copy tax % to stack";
     -*                  "Number = (100 - tax %) * Number";
       M/                "Integer divide the number by 100";          
         3$+             "Add refund";
            _@<*         "Convert to 0 if refunded number > before tax one";
                    ]W=  "Take the last element of the stack";

Buradan çevrimiçi deneyin


Ve şimdi geriye kalan Dennis'in gelip ikimizi de yenmesini beklemek. ;)
Martin Ender

CJam'de değil;) (umarım)
Doktor

Hünerden gerçekten hoşlanıyorum ]W=, ancak şimdiye kadar, onu kullanmaya çalıştığım her yol aynı karakter sayısına sahip.
Martin Ender

@ MartinBüttner - Evet, ben de.
Doktor

1
@Dennis - Şimdi çalışmalı, 2 bayt daha kısa kod eklenmiş bir avantajla: D
Optimizer

4

APL (39)

T R←⎕⋄⊃Z/⍨{⍵(⊢×>)R+⌊⍵×1-T÷M}⍣7¨Z←⍳M←100

Açıklama:

  • T R←⎕: klavyeden iki rakam okuyun ve T(vergi) ve R(iade) 'de saklayın .
  • Z←⍳M←100: Numarayı saklamak 100içinde Mve tüm numaraları 1için 100de Z.
  • {... }⍣7¨: içindeki her öğe Ziçin aşağıdaki işlevi 7 kez çalıştırın:
    • R+⌊1-T÷M: kaç kekin ödenmesi gerektiğini hesaplayın,
    • ⍵(⊢×>): trol başladığından daha fazla kekle sonuçlanırsa bu miktarı 1 ile veya değilse 0 ile çarpın.
  • ⊃Z/⍨: içindeki her öğe için Zbu işlevi verilen sayıyla çoğaltın. (Böylece işlevin döndürdüğü tüm sayılar 0kaybolur.) Ardından bu listeden ilk öğeyi seçin. Liste boşsa, bu sonuç verir 0.

3

C, 83 bayt

int cake(int perc_taken, int given_back)
{
    int startcake = floor(100.f/perc_taken*given_back+1);
    for(int i = 0; i < 6; i++)
    {
        startcake = ceil((startcake-given_back) * 100.f/(100 - perc_taken));
    }
    return startcake;
}

Çalışırsa, sadece 1'den 100'e kadar değil, tüm olası başlangıç ​​pastaları için çalışır.

EDIT: Çalışır. golfed:

n(int p,int g) {int s=100./p*g+1,i=0;for(;i++<6;){s=ceil((s-g)*100./(100-p));}return s;}

'Maksimum 100 kek' limiti ile:

n(int p,int g) {int s=100./p*g+1,i=0;for(;i++<6;){s=ceil((s-g)*100./(100-p));}return s>100?0:s;}

91 bayt.


Başlangıçta 100'den fazla keke ihtiyacınız varsa, özelliğin önemli bir parçası olduğunu düşünüyorum.
Martin Ender

2

CJam, 36 bayt

q~:R100:H*\d:T/i){R-H*HT-/m]}6*_H)<*

1

C ++ - 202 karakter

Her zamanki gibi, benim C ++ kötü yaptı:

#include<iostream>
int main(){double p,g,c=1,i,r,t;std::cin>>p>>g;for(;c<101;c++){r=c;for(i=0;i<7;i++){t=(int)(r*(1-(p/100))+g);if(t>=r){r=-1;break;}r=t;}if(r!=-1)break;}r!=-1?std::cout<<c:std::cout<<0;}

1

APL, 36

x y←⎕⋄101|1⍳⍨y<x×{y+⍵-⌈⍵×x}⍣6⍳x÷←100

açıklama

Bir "kek eşiği" olduğunu unutmayın. Vergi oranı xve geri ödeme yiçin kesinlikle daha fazlasına ihtiyacınız olacaky÷x sonraki köprüyü geçmek için keklerden .

x y←⎕girdi alın ve x(vergi) ve y(iade)
⍳x÷←100bölmesine atayınx 100'e ve sonra 1'den 100'e kadar bir dizi oluşturun

{y+⍵-⌈⍵×x}⍣6"geçiş köprüsü" işlevini 6 kez çağırın:
⌈⍵×xSahip olduğunuz kek sayısı, kez vergi oranı, yuvarlama (ödediğiniz miktar) Sahip
⍵-olduğunuz kek sayısından çıkarın
y+ iadesi ekle

Daha sonra, 1 ~ 100 kek ile başlarsanız 6 köprüyü geçtikten sonra kalan kek sayısını gösteren 100 elementlik bir dizi elde edersiniz. Son köprüyü geçip geçemeyeceğinizi görmek için eşiğin üzerinde olup olmadığınızı kontrol edin y÷x. Alternatif olarak:
diziyi çarpmax
y< kontrol den daha büyük isey

Son olarak, (true) '
1⍳⍨un ilk oluşumunun dizinini bulun, eğer bulunmazsa 1döndürür mod 101101
101|


1

C 128

Diğer C çözümüne oldukça benziyor ama bence bu kaçınılmaz. Ana hile, tamamlanıp tamamlanmamasına bağlı olarak farklı değerlerle iç döngüden ayrılıyor. Bu kullanmama izin veriyor mu?: Ara verdiğimde yapamadığımda;

t,r,j,k,l,p;main(i){for(scanf("%d%d",&t,&r),i=101;k=--i;){for(j=8;--j>0;)(p=r+k*(100-t)/100)<k?k=p:j=0;j?0:l=i;}printf("%d",l);} 

Ungolfed

int t,r,j,k,l,p;
main(int i)
{
    for(scanf("%d%d",&t,&r),i=101;k=--i;)
    {
        for(j=8;--j>0;)
        {
            if((p=r+k*(100-t)/100)<k)
                k=p;
            else
                j=0;
        }
        j?0:l=i;
    }
    printf("%d",l);
}

hangi derleyiciyi kullanıyorsun
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.