Hitung tol troll untuk lulus dengan aman

12

Terinspirasi oleh /puzzling//q/626


Dalam petualangan Anda, Anda tiba di serangkaian 7 jembatan yang harus Anda lintasi. Di bawah setiap jembatan hidup troll. Untuk menyeberangi jembatan, Anda harus terlebih dahulu memberikan troll sejumlah kue sebagai persentase dari jumlah kue yang Anda bawa. Karena ini adalah troll yang baik, mereka akan memberikan sejumlah kue kepada Anda.

Pada awal setiap hari, raja troll lokal menetapkan pajak kue persen yang harus dibayar setiap pelancong, dan pengembalian kue troll - jumlah kue yang harus diberikan masing-masing troll kepada pelancong.

Tugas Anda adalah menghitung jumlah minimum kue yang diperlukan untuk melewati semua 7 jembatan troll untuk kondisi yang diberikan pada hari itu.

Menganggap:

  1. Dua parameter input: pajak kue persen (bilangan bulat dari 0 hingga 100), dan pengembalian dana kue troll.
  2. Tidak seorang pun, bahkan troll, menginginkan kue yang dimakan sebagian oleh troll lain. Jika Anda dibiarkan dengan sepotong kue, troll akan mendapatkannya.
  3. Jika troll menerima pajak kue, tetapi kemudian harus mengembalikan semua kue (dibiarkan dengan kue yang sama atau lebih sedikit dari sebelumnya), itu akan menjadi marah dan memakan Anda dan kue Anda.
  4. Setiap troll harus menyimpan setidaknya satu kue lengkap.
  5. Anda hanya dapat membawa maksimal 100 kue.
  6. Anda harus mengakhiri hari di mana Anda saat ini berada atau di sisi lain dari semua 7 jembatan.

Tantangan:

Tulis program lengkap untuk menampilkan jumlah kue minimum untuk bepergian hari ini atau nol jika hari ini tidak mungkin untuk bepergian dengan aman - Anda akan menunggu untuk melihat berapa angkanya besok.

Input harus diberikan sebagai stdin, argumen baris perintah atau input file.

Kode terpendek (jumlah byte) menang.

Contoh:

Pajak kue 25%, pengembalian 2 kue troll.

mulai dengan 19 kue
sebelum troll 1: (19 * 0,75) = 14,25
setelah troll 1: (14 + 2) = 16

sebelum troll 2: (16 * 0.75) = 12
setelah troll 2: (12 + 2) = 14

dll.

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

Untuk 18 kue, troll terakhir tidak akan bisa menyimpan kue. Oleh karena itu, jumlah minimum kue untuk 25% / 2 hari adalah 19.

input: 25 2
output: 19

Contoh 2:

Pajak kue 90%, pengembalian 1 kue troll

100 kue -> 11 -> 2 -> 1 (aturan 4)

Troll ketiga tidak bisa menyimpan kue apa pun. Oleh karena itu tidak mungkin untuk bepergian dengan 90% / 1 hari bahkan dimulai dengan jumlah kue maksimum.

input: 90 1
output: 0

Data

Gabungkan grafik input dan output dengan cepat. Saya terkejut ini bukan "halus" (seperti kurva lonceng atau serupa); ada beberapa pulau yang terlihat.

bagan data

Data untuk mereka yang tertarik. Kolom dibagi menjadi interval 5%, baris adalah unit interval pengembalian uang 1 kue (excel memutar gambar). Anda dapat melihat tidak ada pengembalian dana yang lebih tinggi dari 28 kue.

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
Komunitas
sumber
Poin yang bagus. Jadikan program yang lengkap untuk kesederhanaan. Input dapat ditentukan namun Anda inginkan selama itu bukan hard-coded (tantangan yang diperbarui).
Ini adalah teka-teki yang bagus untuk kekerasan di CJam. Saya akan melakukannya sekitar besok
bah, inilah sebabnya c # tidak bisa memiliki hal
Aturan 2 tampaknya mengecualikan kemungkinan troll hanya menerima sebagian kecil dari kue, yang seharusnya membuat asumsi 4 mubazir. Namun Anda mengatakan dalam contoh 2 bahwa troll ketiga hanya akan mendapatkan 0,8 kue.
Dennis
Ada konflik dalam spesifikasi. Dalam 25 211 kotak kue, Anda memberikan troll 2,75 kue dan kembali 2 sehingga troll itu tetap 0,75 (+. 25) dan Anda bertahan hidup. Dalam 90 1wadah 2 kue, Anda memberikan troll 1,8 dan mendapatkan kembali 1 sehingga troll tetap 0,8 (+. 2) tetapi Anda mati.
TwiNight

Jawaban:

6

CJam, 46 43 41 39 38 36 33 byte

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

Input melalui ARGV.

Ada penerjemah online, tetapi sayangnya tidak mendukung argumen baris perintah. Untuk pengujian, Anda dapat menirunya dari STDIN dengan versi ini:

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

Penjelasan versi berbasis ARGV:

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.";

Isi tumpukan secara otomatis dicetak di akhir program.

Martin Ender
sumber
Kode Anda menghasilkan hasil yang salah untuk 55 2( 0bukan 100) dan 56 5( 98bukan 94). Ini karena 100_0.55*-idan 25_0.56*-imenjadi korban ketidaktepatan floating point. Sejauh yang saya tahu, pasangan 31 24, 31 25, 33 21, 33 22, 33 23, 35 10, 35 12, 35 15, 35 16, 35 27, 56 1, 57 4memberikan hasil yang salah juga.
Dennis
1
@Dennis diperbaiki, terima kasih!
Martin Ender
@ Dennis Itu sebenarnya menyimpan satu byte. Saya berharap CJam memiliki penutupan, maka saya bisa mendefinisikan blok di awal yang melakukan pengurangan pajak, dan menggunakannya, daripada menggunakan dua variabel. Mungkin saya bisa menyimpan sesuatu menggunakan ARGV daripada STDIN, biarkan saya melihat.
Martin Ender
5

CJam, 44 40 38 37 35 byte

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

Atau saat menggunakan argumen dan {}#trik baris perintah , 33 byte :

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

Tidak menempatkan yang ini sebagai yang utama sebagai {}#pendekatan saya terinspirasi dari jawaban Martin.

Contoh dijalankan:

Memasukkan:

25 2

Keluaran:

19

Lain:

Memasukkan:

15 14

Keluaran:

100

Bagaimana itu bekerja

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

Cobalah online di sini

Pengoptimal
sumber
Dan sekarang yang tersisa adalah menunggu Dennis untuk datang dan mengalahkan kami berdua. ;)
Martin Ender
Tidak di CJam;) (semoga)
Pengoptimal
Saya sangat suka ]W=triknya, tetapi sejauh ini, setiap cara saya mencoba menggunakannya saya berakhir dengan jumlah karakter yang sama.
Martin Ender
@ MartinBüttner - Ya, saya juga.
Pengoptimal
1
@Dennis - Seharusnya berfungsi sekarang, dengan manfaat tambahan kode pendek 2 byte: D
Pengoptimal
4

APL (39)

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

Penjelasan:

  • T R←⎕: baca dua angka dari keyboard dan simpan di T(pajak) dan R(kembali).
  • Z←⍳M←100: Menyimpan nomor 100di M, dan semua nomor dari 1ke 100dalam Z.
  • {... }⍣7¨: untuk setiap elemen Z, jalankan fungsi berikut 7 kali:
    • R+⌊1-T÷M: hitung berapa banyak kue yang harus dibayar,
    • ⍵(⊢×>): kalikan jumlahnya dengan 1 jika troll berakhir dengan lebih banyak kue daripada yang dia mulai, atau dengan 0 jika tidak.
  • ⊃Z/⍨: untuk setiap elemen di dalam Z, gandakan dengan jumlah yang diberikan fungsi tersebut. (Jadi semua angka yang fungsinya dikembalikan 0menghilang.) Kemudian pilih item pertama dari daftar itu. Jika daftar berakhir kosong, ini memberi 0.
marinus
sumber
3

C, 83 byte

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

Jika berhasil, ini berfungsi untuk semua kemungkinan startcakes, tidak hanya dari 1 hingga 100.

EDIT: Berhasil. Golf:

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

Dengan batas 'maksimum 100 kue':

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 byte

Gerwin
sumber
Saya pikir ini adalah bagian penting dari spesifikasi bahwa solusi mengembalikan nol jika Anda memerlukan lebih dari 100 kue pada awalnya.
Martin Ender
2

CJam, 36 byte

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

C ++ - 202 karakter

Seperti biasa, C ++ saya melakukan yang terburuk:

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

sumber
1

APL, 36

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

Penjelasan

Perhatikan bahwa ada "ambang kue". Untuk tarif pajak xdan pengembalian uang y, Anda akan membutuhkan lebih dari sekadar y÷xkue untuk melewati jembatan berikutnya.

x y←⎕mengambil input dan menetapkan untuk x(pajak) dan y(kembali)
⍳x÷←100bagi x100, dan kemudian menghasilkan array 1 hingga 100

{y+⍵-⌈⍵×x}⍣6panggil fungsi "pass bridge" 6 kali:
⌈⍵×xJumlah kue yang Anda miliki, kali tarif pajak, jumlah (jumlah yang Anda bayarkan)
⍵-Kurangi dari jumlah kue yang Anda miliki
y+Tambahkan pengembalian dana

Kemudian Anda mendapatkan array 100 elemen yang menunjukkan jumlah kue yang tersisa setelah melewati 6 jembatan jika Anda mulai dengan 1 ~ 100 kue. Untuk melihat apakah Anda dapat menyeberangi jembatan terakhir, periksa apakah Anda berada di atas ambang batas y÷x. Atau:
gandakan array dengan x
y<memeriksa apakah lebih besar dariy

Akhirnya,
1⍳⍨cari indeks kemunculan pertama 1(benar), kembali 101jika tidak ditemukan
101|mod 101

TwiNight
sumber
1

C 128

Cukup mirip dengan solusi C lain tapi saya pikir itu tidak bisa dihindari. Trik utama adalah keluar dari loop dalam dengan nilai yang berbeda tergantung pada apakah itu selesai atau tidak. Ini memungkinkan saya untuk menggunakan?: Ketika saya tidak bisa jika saya menggunakan istirahat;

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

Tidak disatukan

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);
}
Ahli alkimia
sumber
kompiler apa yang Anda gunakan?