Misteri Kertas Toilet


36

Hari ini Anda perlu memecahkan masalah yang sangat praktis: Berapa banyak loop yang Anda butuhkan untuk memiliki sejumlah lembaran pada gulungan kertas toilet Anda? Mari kita lihat beberapa fakta:

  • Diameter silinder kertas toilet kosong adalah 3,8 cm
  • Panjang satu lembar kertas toilet adalah 10cm.
  • Ketebalan satu lembar kertas toilet adalah 1mm.

Sebelum Anda membungkus silinder pertama kali, ia memiliki keliling dalam cm 3,8 * pi. Setiap kali Anda membungkus selembar silinder di sekitar jari-jarinya meningkat sebesar 0,1, oleh karena itu kelilingnya meningkat sebesar 0,2 * PI. Gunakan informasi ini untuk mencari tahu berapa banyak loop yang diperlukan agar sesuai dengan n lembar kertas toilet. (Catatan: Gunakan perkiraan Pi yang setidaknya seakurat 3.14159).

Kasus uji :

n = 1 :

  • 10 / (3.8 * pi) = .838 loop

n = 2 :

  • (Berapa banyak loop penuh yang bisa kita buat?) 1 loop penuh = 3,8 * pi = 11,938.
  • (Berapa banyak yang tersisa setelah loop pertama?) 20 - 11.938 = 8.062
  • (Berapa banyak loop ke-2 yang dihasilkan oleh potongan yang tersisa?) 8.062 / (4 * pi) = .642 loop
  • Jawaban: 1,642 loop

n = 3 :

  • Loop penuh pertama = 3,8 * pi = 11,938, loop penuh kedua = 4 * pi = 12,566
  • 30 - 11.938 - 12.566 = 5.496
  • 5.496 / (4.2 * pi) = .417
  • Jawaban: 2.417 loop

n = 100 => 40.874


35
Fiuh! Tebal 1mm? Apakah Anda yakin menggunakan kertas toilet dan bukan kardus?
Trauma Digital

11
@DigitalTrauma Jelas Anda tidak tahu tentang triple-ply: p
geokavel

2
Di bawah asumsi bahwa kertas toilet tidak membuat langkah tetapi terus meningkatkan jari-jari, Anda bisa mendapatkan perkiraan bentuk tertutup untuk hasil yang diminta. Apakah ini cukup baik? nloops = sqrt(n+11.34)*0.0564189 - 0.19
flawr

2
Usulan uji kasus: 100->40.874
Dennis

1
Karton tiga lapis ?! Nah, itu tebal!
mbomb007

Jawaban:


13

Pyth, 27 23 byte

+fg0=-QJc*.n0+18T50)cQJ

Cobalah online. Suite uji.

Penjelasan

                            Q = input number (implicit)
 f                 )        increment T from 1, for each T:
             +18T             add 18 to T, get radius
         *.n0                 multiply by pi to, get half the circumference
        c        50           divide by 50, get circumference in sheets
       J                      save it to J
    =-Q                       decrement Q by it
  g0                          use this T if Q is now <= 0
+                           add
                     Q        Q (now <= 0)
                    c J       divided by J (the last circumference)
                            and print (implicit)

penjelasannya, tolong?
Conor O'Brien

@CᴏɴᴏʀO'Bʀɪᴇɴ Ditambahkan. Menjelaskan Pyth selalu sangat menyenangkan.
PurkkaKoodari

2
Penjelasan Anda terlihat seperti keluaran potensial untuk Surfin 'Word
geokavel

10

Haskell, 59 46 44 byte

Faktor skala 5 / pi diterapkan, sehingga silinder kertas memiliki keliling 19,20,21 ... cm dan selembar 50 / pi cm.

Disimpan 2 byte berkat xnor, dengan menggunakan fungsi yang tidak disebutkan namanya.

x!s|s>x=1+(x+1)!(s-x)|1>0=s/x
(19!).(50/pi*)

Metode yang cukup rekursif. Perhatikan bahwa fungsi yang tidak disebutkan namanya diizinkan bahkan ketika Anda memiliki baris lain (meskipun Haskell tidak mendukungnya), sehingga baris terakhir dapat pointfree sebagai (19!).(50/pi*).
xnor

Wow, hancurkan pendekatan saya keluar dari air!
CR Drost


5

Haskell, 97 byte

p&((m,x):(n,y):z)|y<p=p&((n,y):z)|1>0=m+(p-x)/(y-x)
t=(&zip[0..](scanl(+)0$map(*pi)[0.38,0.4..]))

Mungkin bisa golf lebih jauh dengan memindahkan filter dari &operator ke takeWhilepernyataan, tetapi mengingat bahwa itu bukan bahasa golf, ini tampaknya relatif kompetitif.

Penjelasan

Aliran panjang kertas toilet yang terdiri dari loop penuh pertama kali dihitung sebagai scanl (+) 0 (map (* pi) [0.38, 0.4 ..]]. Kami menutup ini dengan jumlah putaran penuh, yang juga akan mengambil jenis Doublesecara implisit. Kami meneruskan ini &dengan nomor saat ini yang ingin kami hitung, sebut saja p.

&memproses daftar (Double, Double)pasangan di sebelah kanannya dengan (a) melompati ke depan sampai snd . head . taillebih besar dari p, pada titik snd . headyang kurang darip .

Untuk mendapatkan proporsi dari baris ini yang diisi, ia kemudian menghitung (p - x)/(y - x),dan menambahkannya ke jumlah keseluruhan loop yang telah dibuat sejauh ini.


4

C ++, 72 byte

float f(float k,int d=19){auto c=d/15.9155;return k<c?k/c:1+f(k-c,d+1);}

Saya menggunakan C ++ di sini karena mendukung argumen fungsi default, diperlukan di sini untuk menginisialisasi jari-jari.

Rekursi tampaknya menghasilkan kode yang lebih pendek daripada menggunakan for-loop. Juga, autobukannya float- 1 byte lebih sedikit!


1
Anda hampir tertipu saya, menggunakan duntuk radius ...
Toby Speight

3

Lua, 82 byte

n=... l,c,p=10*n,11.938042,0 while l>c do l,c,p=l-c,c+.628318,p+1 end print(p+l/c)

Tidak buruk untuk bahasa tujuan umum, tetapi tidak terlalu kompetitif terhadap bahasa golf khusus. Konstanta ditakdirkan dengan pi, dengan presisi yang dinyatakan.


OP tidak spesifik tentang input apa yang harus diterima, jadi saya mengabaikan inisialisasi n, tetapi sisanya akan berjalan apa adanya (seperti apa adanya?). Bagaimanapun, sekarang dibutuhkan ndari baris perintah; misalnya untuk 3 lembar jalankan sebagai lua tp.lua 3.
Criptych berdiri bersama Monica

Ini bukan aturan pertanyaan ini, tetapi kebijakan umum. Kecuali jika pertanyaan mengatakan sebaliknya, hardcoding pada input menjadikan kiriman potongan, yang tidak diizinkan secara default . Informasi lebih lanjut tentang standar seluruh situs dapat ditemukan di wiki tag golf kode .
Dennis

Saya tahu tentang bagian "seluruh program atau fungsi" tetapi tidak tahu bahwa "hardcoding input membuat kiriman potongan". Terima kasih telah mengklarifikasi. Saya pikir ini sebenarnya akan lebih lama sebagai fungsi!
Criptych berdiri bersama Monica

3

JavaScript, 77 byte

function w(s,d,c){d=d||3.8;c=d*3.14159;return c>s*10?s*10/c:1+w(s-c/10,d+.2)}


3
Selamat datang di PPCG! Jika mau, Anda dapat menggunakan JavaScript ES6, dan membuatnya hingga 55 byte:w=(s,d=3.8,c=d*3.14159)=>c>s*10?s*10/c:1+w(s-c/10,d+.2)
Downgoat

3

C, 87 byte

float d(k){float f=31.831*k,n=round(sqrt(f+342.25)-19);return n+(f-n*(37+n))/(38+2*n);}

Menggunakan rumus eksplisit untuk jumlah keseluruhan loop:

floor(sqrt(100 * k / pi + (37/2)^2) - 37/2)

Saya digantikan 100 / pioleh 31.831, dan diganti floordengan round, mengubah nomor yang mengganggu -18.5menjadi bersih-19 .

Panjang loop ini adalah

pi * n * (3.7 + 0.1 * n)

Setelah mengurangi panjang ini dari panjang keseluruhan, kode membagi sisanya dengan keliling yang tepat.


Hanya untuk memperjelas - solusi ini memiliki kompleksitas O(1), tidak seperti banyak (semua?) Solusi lain. Jadi ini sedikit lebih lama dari satu loop atau rekursi.


2

C #, 113 byte

double s(int n){double c=0,s=0,t=3.8*3.14159;while(n*10>s+t){s+=t;c++;t=(3.8+c*.2)*3.14159;}return c+(n*10-s)/t;}

Tidak Disatukan:

double MysteryToiletPaper(int sheetNumber) 
    { 
        double fullLoops = 0, sum = 0, nextLoop = 3.8 * 3.14159; 

        while (sheetNumber * 10 > sum + nextLoop) 
        { 
            sum += nextLoop; 
            fullLoops++; 
            nextLoop = (3.8 + fullLoops * .2) * 3.14159; 
        } 

        return fullLoops + ((sheetNumber * 10 - sum) / nextLoop); 
    }

Hasil:

untuk 1 lembar

0,837658302760201

untuk 2 lembar

1,64155077524438

untuk 3 lembar

2,41650110749198

untuk 100 lembar

40,8737419532946


2

PHP, 101 byte

<?$p=pi();$r=3.8;$l=$argv[1]*10;$t=0;while($r*$p<$l){$t+=($l-=$r*$p)>0?1:0;$r+=.2;}echo$t+$l/($r*$p);

Tidak disatukan

<?
$pi = pi();
$radius = 3.8;
$length_left = $argv[1]*10;
$total_rounds = 0;
while ($radius * $pi < $length_left) {
    $total_rounds += ($length_left -= $radius * $pi) > 0 ? 1 : 0;
    $radius += .2;
}
echo $total_rounds + $length_left/( $radius * $pi );

Saya merasa ini bisa dilakukan sedikit lebih pendek, tetapi saya kehabisan ide.


2

Python 3, 114 109 99 byte

Fungsi ini melacak keliling setiap lapisan sampai jumlah keliling lebih besar dari panjang jumlah lembar. Setelah ini terjadi jawabannya adalah:

  • Satu kurang dari jumlah lapisan yang dihitung + panjang lembaran sisa / keliling lapisan terbaru

def f(n):
    l,s=0,[]
    while sum(s)<n:s+=[.062832*(l+19)];l+=1
    return len(s)-1+(n-sum(s[:-1]))/s[-1]

Memperbarui

  • -10 [16-05-09] Mengoptimalkan matematika saya
  • -5 [16-05-04] Jumlah baris yang diperkecil

1

JavaScript, 44 byte

w=(i,d=19,c=d/15.9155)=>i<c?i/c:1+w(i-c,d+1)

Saya menggunakan ide anatolyg dan menerjemahkan kodenya ke dalam JavaScript.


1

> <>, 46 44 byte

a*0"Gq",:&a9+*\
?\:{$-{1+{&:&+>:{:})
;>{$,+n

Mengharapkan jumlah lembar yang ada pada tumpukan saat program dimulai.

Ini menggunakan perkiraan pi 355/113 = 3.14159292..., menyimpan pi/5dalam register. Lingkaran iterasi saat ini tinggal di stack, danpi/5 ditambahkan pada setiap iterasi.

Sunting: Refactored untuk menyimpan keliling secara langsung - versi sebelumnya disimpan pi/10dan memulai diameter as 38, yang lebih panjang 2 byte.


0

PHP, 79 byte

function p($s,$d=3.8){$c=$d*pi();return $c>$s*10?$s*10/$c:1+p($s-$c/10,$d+.2);}

Jalankan kode di Sandbox

Saya cukup banyak hanya menerjemahkan jawaban Ross Bradbury untuk JavaScript ke dalam fungsi PHP, yang juga bersifat rekursif.


Tolong jangan hanya menyalin jawaban lain ke bahasa lain.
Rɪᴋᴇʀ
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.