Таємниці туалетного паперу


36

Сьогодні вам потрібно вирішити дуже практичну проблему: Скільки петель потрібно мати певну кількість аркушів на вашому рулоні туалетного паперу? Давайте розглянемо деякі факти:

  • Діаметр голого циліндра туалетного паперу - 3,8см
  • Довжина одного аркуша туалетного паперу - 10см.
  • Товщина одного аркуша туалетного паперу - 1мм.

Перш ніж обернути циліндр вперше, він має окружність в см 3,8 * пі. Кожного разу, коли ви обмотуєте лист навколо циліндра, його радіус збільшується на .1, тому його окружність збільшується на .2 * PI. Використовуйте цю інформацію, щоб дізнатись, скільки петель потрібно, щоб вмістити n аркушів туалетного паперу. (Примітка. Використовуйте наближення Pi, що принаймні таке точне, як 3.14159).

Випробування :

n = 1 :

  • 10 / (3,8 * пі) = .838 петель

n = 2 :

  • (Скільки повних циклів ми можемо зробити?) 1 повний цикл = 3,8 * пі = 11,938.
  • (Скільки нам залишилось після 1-ї петлі?) 20 - 11,938 = 8,062
  • (Скільки 2-ї петлі робить залишився шматок?) 8.062 / (4 * pi) = .642 петлі
  • Відповідь: 1.642 петлі

n = 3 :

  • 1-й повний цикл = 3,8 * пі = 11,938, 2-й повний цикл = 4 * пі = 12,566
  • 30 - 11.938 - 12.566 = 5.496
  • 5.496 / (4.2 * пі) = .417
  • Відповідь: 2.417 петель

n = 100 => 40,874


35
Фу! 1 мм товщиною? Ви впевнені, що використовуєте туалетний папір, а не картон?
Цифрова травма

11
@DigitalTrauma Очевидно, що ви не знаєте про потрійний: p
geokavel

2
Зважаючи на те, що туалетний папір не робить кроків, але постійно збільшує радіус, можна отримати наближену форму закритого типу до потрібного результату. Це досить добре? nloops = sqrt(n+11.34)*0.0564189 - 0.19
недолік

2
Пропонований тестовий випадок: 100->40.874
Денніс

1
Тришаровий картон ?! Тепер це густо!
mbomb007

Відповіді:


13

Pyth, 27 23 байт

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

Спробуйте в Інтернеті. Тестовий набір.

Пояснення

                            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)

пояснення, будь ласка?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Додано. Пояснювати Pyth завжди так весело.
PurkkaKoodari

2
Твоє пояснення виглядає як потенційний результат для Surfin 'Word
geokavel

10

Haskell, 59 46 44 байт

Застосовується масштабний коефіцієнт 5 / пі, щоб паперовий циліндр мав окружність 19,20,21 ... см, а аркуш - 50 / пі см.

Збережено 2 байти завдяки xnor за допомогою неназваної функції.

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

Досить рекурсивний метод. Зауважте, що неназвані функції дозволені, навіть якщо у вас є інші рядки (незважаючи на те, що Haskell не підтримує її), тому останній рядок може бути точково як (19!).(50/pi*).
xnor

Ого, видуває мій підхід з води!
CR Drost


5

Haskell, 97 байт

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..]))

Можливо, можна додатково переграти його, перемістивши фільтрацію від &оператора в takeWhileзаяву, але враховуючи, що це не мова для гри в гольф, це здається відносно конкурентоспроможним.

Пояснення

Спочатку довжина туалетного паперу, що складається з повних петель, спочатку обчислюється як scanl (+) 0 (map (* pi) [0.38, 0.4 ..]]. Ми посилаємо їх на кількість повних оборотів, які також підбирають тип Doubleнеявно. Ми передаємо це &з поточним числом, яке ми хочемо обчислити, називаємо його p.

&обробляє список (Double, Double)пар праворуч (a), пропускаючи вперед, поки не snd . head . tailбуде більше, ніж p, у який момент snd . headменше, ніж p.

Щоб отримати пропорційну кількість цього ряду, який заповнюється, він обчислює (p - x)/(y - x),та додає його до загальної кількості петель, які були зроблені до цього часу.


4

C ++, 72 байти

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

Тут я використав C ++, оскільки він підтримує аргументи за замовчуванням, необхідні тут для ініціалізації радіусу.

Здається, рекурсія створює коротший код, ніж використання for-loop. Також autoзамість float- на 1 байт менше!


1
Ви ледь не обдурили мене, використовуючи dдля radius ...
Toby Speight

3

Луа, 82 байти

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)

Непогано для мови загального призначення, але не дуже конкурентоспроможною щодо видатних мов для гри в гольф, звичайно. Константи попередньо множать з pi, до заданої точності.


ОП не конкретно стосувався того, який вхід приймати, тому я ігнорував ініціалізацію n, але решта запустилася б як є (як було?). У будь-якому випадку, тепер це береться nз командного рядка; наприклад, для 3 аркушів виконайте це як lua tp.lua 3.
Кріптих стоїть з Монікою

Це не правило цього питання, а загальна політика. Якщо в питанні не сказано інакше, жорстке кодування введення робить фрагмент подання, який не дозволений за замовчуванням . Більш детальну інформацію про стандартні налаштування на сайті можна знайти у вікі-коді тегу гольфу .
Денніс

Я знав про частину "всієї програми чи функції", але не знав, що "жорстке кодування введення робить подання фрагментом". Дякуємо за уточнення. Я думаю, що це насправді буде довше як функція!
Кріптих стоїть разом з Монікою

3

JavaScript, 77 байт

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
Ласкаво просимо до PPCG! Якщо ви хочете, ви можете використовувати JavaScript ES6 і отримати це до 55 байт:w=(s,d=3.8,c=d*3.14159)=>c>s*10?s*10/c:1+w(s-c/10,d+.2)
Пуховик

3

C, 87 байт

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

Використовується явна формула для кількості цілих циклів:

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

Я замінив 100 / piна 31.831, і замінити floorз round, повертаючи прикре число -18.5до чистого -19.

Довжина цих петель становить

pi * n * (3.7 + 0.1 * n)

Віднявши цю довжину від усієї довжини, код ділиться залишком на правильну окружність.


Просто для того, щоб було зрозуміло - це рішення має складність O(1), на відміну від багатьох (усіх?) Інших рішень. Так що це трохи довше, ніж цикл чи рекурсія.


2

C #, 113 байт

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

Безголівки:

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

Результати:

за 1 аркуш

0,837658302760201

за 2 аркуші

1,64155077524438

за 3 аркуші

2,41650110749198

за 100 аркушів

40,8737419532946


2

PHP, 101 байт

<?$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);

Безумовно

<?
$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 );

Я відчуваю, що це можна зробити трохи коротше, але у мене вичерпалися ідеї.


2

Python 3, 114 109 99 байт

Ця функція відстежує окружність кожного шару до тих пір, поки сума окружності не перевищить довжину кількості аркушів. Як тільки це станеться, відповідь така:

  • На одну меншу кількість обчислених шарів + довжина залишків листів / окружність останнього шару

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]

Оновлення

  • -10 [16-05-09] Оптимізовано мою математику
  • -5 [16-05-04] Мінімізована кількість рядків

1

JavaScript, 44 байти

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

Я використав ідею anatolyg і переклав код у JavaScript.


1

> <>, 46 44 байти

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

Очікує кількість аркушів, які будуть присутні в стеці при запуску програми.

Для цього використовується наближення пі 355/113 = 3.14159292..., зберігання pi/5в реєстрі. Поточна окружність ітерації живе на стеку та pi/5додається до кожної ітерації.

Редагувати: Повторно налаштований для прямого зберігання окружності - попередня версія зберігалася pi/10і починала діаметр як 38, який був на 2 байти довше.


0

PHP, 79 байт

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

Запустити код у Sandbox

Я майже лише переклав відповідь Росса Бредбері за JavaScript на функцію PHP, яка також є рекурсивною.


Будь ласка, не просто копіюйте іншу відповідь на іншу мову.
Rɪᴋᴇʀ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.