Tajemnice papieru toaletowego

36

Dziś musisz rozwiązać bardzo praktyczny problem: ile pętli potrzebujesz, aby mieć określoną liczbę arkuszy na rolce papieru toaletowego? Spójrzmy na kilka faktów:

  • Średnica gołego cylindra z papieru toaletowego wynosi 3,8 cm
  • Długość jednego arkusza papieru toaletowego wynosi 10 cm.
  • Grubość jednego arkusza papieru toaletowego wynosi 1 mm.

Przed pierwszym owinięciem cylindra ma on obwód w cm 3,8 * pi. Za każdym razem, gdy owijasz arkusz wokół cylindra, jego promień zwiększa się o .1, a zatem jego obwód wzrasta o .2 * PI. Skorzystaj z tych informacji, aby dowiedzieć się, ile pętli pasuje do n arkuszy papieru toaletowego. (Uwaga: należy użyć przybliżenia Pi, które jest co najmniej tak dokładne jak 3.14159).

Przypadki testowe :

n = 1 :

  • 10 / (3,8 * pi) = .838 pętli

n = 2 :

  • (Ile pełnych pętli możemy wykonać?) 1 pełna pętla = 3,8 * pi = 11,938.
  • (Ile pozostało po pierwszej pętli?) 20 - 11,938 = 8,062
  • (Ile drugiej pętli tworzy pozostały element?) 8.062 / (4 * pi) = .642 pętli
  • Odpowiedź: 1.642 pętle

n = 3 :

  • 1. pełna pętla = 3,8 * pi = 11,938, druga pełna pętla = 4 * pi = 12.566
  • 30 - 11,938 - 12,566 = 5,496
  • 5,496 / (4,2 * pi) = .417
  • Odpowiedź: 2.417 pętli

n = 100 => 40,874

geokavel
źródło
35
Uff! 1 mm grubości? Czy na pewno używasz papieru toaletowego, a nie kartonu?
Cyfrowy uraz
11
@DigitalTrauma Najwyraźniej nie wiesz o triple-ply: p
geokavel
2
Zakładając, że papier toaletowy nie wykonuje kroków, ale stale zwiększa promień, można uzyskać przybliżone przybliżenie formularza do żądanego wyniku. Czy to wystarczy? nloops = sqrt(n+11.34)*0.0564189 - 0.19
flawr
2
Proponowany przypadek testowy: 100->40.874
Dennis
1
Karton trójwarstwowy ?! Teraz jest grubo!
mbomb007

Odpowiedzi:

13

Pyth, 27 23 bajtów

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

Wypróbuj online. Zestaw testowy.

Wyjaśnienie

                            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)
PurkkaKoodari
źródło
wyjaśnienie, proszę?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Dodano. Wyjaśnienie Pytha jest zawsze świetną zabawą.
PurkkaKoodari
2
Twoje wyjaśnienie wygląda jak potencjalny wynik dla Surfin 'Word
geokavel
10

Haskell, 59 46 44 bajtów

Zastosowano współczynnik skali 5 / pi, tak że walec papierowy ma obwód 19,20,21 ... cm, a arkusz ma 50 / pi cm.

Zaoszczędzono 2 bajty dzięki xnor, używając funkcji bez nazwy.

x!s|s>x=1+(x+1)!(s-x)|1>0=s/x
(19!).(50/pi*)
Damien
źródło
Dość rekurencyjna metoda. Zauważ, że funkcje bez nazwy są dozwolone, nawet jeśli masz inne linie (mimo że Haskell go nie obsługuje), więc ostatnia linia może być bezcelowa jak (19!).(50/pi*).
xnor
Wow, wydmuchuje moje podejście z wody!
CR Drost
5

Haskell, 97 bajtów

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

Może być w stanie zagrać w golfa dalej, przenosząc filtrowanie od &operatora dotakeWhile się pograć w golfa, oświadczenie, ale biorąc pod uwagę, że nie jest to język golfa, wydaje się to stosunkowo konkurencyjne.

Wyjaśnienie

Strumień długości papieru toaletowego zawierającego pełne pętle oblicza się najpierw jako scanl (+) 0 (map (* pi) [0.38, 0.4 ..]]. Spakowujemy je liczbą pełnych obrotów, które pośrednio podniosą ten typ Double. Przekazujemy to &bieżącemu numerowi, który chcemy obliczyć, nazywamy go p.

&przetwarza listę (Double, Double)par po prawej stronie przez (a) przeskakiwanie do przodu, aż snd . head . tailbędzie większa niż p, w którym momencie snd . headjest mniejsza niż p.

Aby uzyskać część tego wiersza, która jest wypełniona, następnie oblicza (p - x)/(y - x),i dodaje ją do ogólnej liczby wykonanych do tej pory pętli.

CR Drost
źródło
4

C ++, 72 bajty

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

Użyłem tutaj C ++, ponieważ obsługuje domyślne argumenty funkcji, potrzebne tutaj do zainicjowania promienia.

Wydaje się, że rekurencja generuje krótszy kod niż przy użyciu forpętli. Ponadto autozamiast float- 1 bajt mniej!

anatolig
źródło
1
Prawie mnie oszukać, używając ddo radius ...
Toby Speight
3

Lua, 82 bajty

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)

Nieźle jak na język ogólnego przeznaczenia, ale oczywiście niezbyt konkurencyjny w stosunku do dedykowanych języków golfowych. Stałe są wstępnie mnożone przez pi z określoną dokładnością.

cryptych stoi z Moniką
źródło
OP nie precyzowało, jakiego rodzaju dane wejściowe należy zaakceptować, więc pominąłem inicjalizację n, ale reszta działałaby w stanie, w jakim się znajduje (jak było?). W każdym razie teraz pobiera nz wiersza poleceń; np. dla 3 arkuszy uruchom jako lua tp.lua 3.
cryptych stoi z Monicą
Nie jest to reguła tego pytania, ale ogólna polityka. O ile pytanie nie mówi inaczej, kodowanie danych wejściowych powoduje, że przesyłanie jest fragmentem kodu, który domyślnie nie jest dozwolony . Więcej informacji na temat wartości domyślnych dla całej witryny można znaleźć w wiki wiki kodu golf tag .
Dennis
Wiedziałem o części „cały program lub funkcja”, ale nie wiedziałem, że „twarde kodowanie wejścia sprawia, że ​​przesłanie jest fragmentem”. Dzięki za wytłumaczenie. Myślę, że tak naprawdę byłoby to dłużej jako funkcja!
cryptych stoi z Monicą
3

JavaScript, 77 bajtów

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

Ross Bradbury
źródło
3
Witamy w PPCG! Jeśli chcesz, możesz użyć JavaScript ES6 i uzyskać to do 55 bajtów:w=(s,d=3.8,c=d*3.14159)=>c>s*10?s*10/c:1+w(s-c/10,d+.2)
Zejdź
3

C, 87 bajtów

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

Używa jawnej formuły dla liczby całych pętli:

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

Wymieniłem 100 / piprzez 31.831i zastąpione floorzround zwracając liczbę irytujących -18.5do czysta-19 .

Długość tych pętli wynosi

pi * n * (3.7 + 0.1 * n)

Po odjęciu tej długości od całej długości kod dzieli resztę przez odpowiedni obwód.


Żeby było jasne - to rozwiązanie ma złożoność O(1), w przeciwieństwie do wielu (wszystkich?) Innych rozwiązań. Jest to więc nieco dłużej niż pętla lub rekurencja.

anatolig
źródło
2

C #, 113 bajtów

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

Nie golfowany:

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

Wyniki:

za 1 arkusz

0,837658302760201

na 2 arkusze

1 64155077524438

na 3 arkusze

2 41650110749198

na 100 arkuszy

40,8737419532946

Ivaan
źródło
2

PHP, 101 bajtów

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

Bez golfa

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

Wydaje mi się, że można to zrobić trochę krócej, ale zabrakło mi pomysłów.

Samsquanch
źródło
2

Python 3, 114 109 99 bajtów

Ta funkcja śledzi obwód każdej warstwy, dopóki suma obwodów nie będzie większa niż długość liczby arkuszy. Gdy tak się stanie, odpowiedź brzmi:

  • O jeden mniej niż liczba obliczonych warstw + długość pozostałych arkuszy / obwód najnowszej warstwy

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]

Aktualizacja

  • -10 [16-05-09] Zoptymalizowałem moją matematykę
  • -5 [16-05-04] Zminimalizowana liczba linii
Nieliniowe Owoce
źródło
1

JavaScript, 44 bajty

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

Wykorzystałem pomysł anatolyga i przetłumaczyłem kod na JavaScript.

ericw31415
źródło
1

> <>, 46 44 bajtów

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

Oczekuje, że liczba arkuszy będzie obecna na stosie podczas uruchamiania programu.

Wykorzystuje to przybliżenie liczby pi 355/113 = 3.14159292..., zapisywanie pi/5w rejestrze. Obwód bieżącej iteracji trwa na stosie i pi/5jest dodawany przy każdej iteracji.

Edycja: Przeprojektowano w celu bezpośredniego przechowywania obwodu - poprzednia wersja zapisała pi/10i rozpoczęła średnicę jako 38, która była o 2 bajty dłuższa.

Sok
źródło
0

PHP, 79 bajtów

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

Uruchom kod w piaskownicy

Prawie przetłumaczyłem tylko odpowiedź Ross'a Bradbury'a na JavaScript na funkcję PHP, która również jest rekurencyjna.

Nacięcie
źródło
Nie kopiuj tylko innej odpowiedzi na inny język.
Rɪᴋᴇʀ