Toilet Paper Mysteries

36

4

Today you need to solve a very practical problem: How many loops do you need to have a certain number of sheets on your toilet paper roll? Let's look at some facts:

  • The diameter of a bare toilet paper cylinder is 3.8cm
  • The length of one sheet of toilet paper is 10cm.
  • The thickness of one sheet of toilet paper is 1mm.

Before you wrap around the cylinder the first time, it has a circumference in cm of 3.8*pi. Every time you wrap a sheet around the cylinder its radius increases by .1, therefore its circumference increases by .2*PI. Use this information to find out how many loops it takes to fit n sheets of toilet paper. (Note: Use an approximation of Pi that is at least as accurate as 3.14159).

Test Cases:

n=1:

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

n=2:

  • (How many full loops can we make?) 1 full loop = 3.8*pi = 11.938.
  • (How much do we have left after the 1st loop?) 20 - 11.938 = 8.062
  • (How much of a 2nd loop does the remaining piece make?) 8.062/(4*pi) = .642 loops
  • Answer: 1.642 loops

n=3:

  • 1st full loop = 3.8*pi = 11.938, 2nd full loop = 4*pi = 12.566
  • 30 - 11.938 - 12.566 = 5.496
  • 5.496/(4.2*pi) = .417
  • Answer: 2.417 loops

n=100 => 40.874

geokavel

Posted 2016-01-13T18:34:27.500

Reputation: 6 352

@FlagAsSpam Because in the first bullet point, I calculate the length of all the full loops. – geokavel – 2016-01-13T18:38:27.190

Also, your calculations are only correct if the bare roll is 3.7cm in diameter. Only then the mean diameter of the first layer is 3.8cm. – Rainer P. – 2016-01-13T18:47:38.627

@RainerP. o.k. I changed the language a bit. It should agree with what you're saying. – geokavel – 2016-01-13T19:01:24.593

35Phew! 1mm thick? Are you sure you're using toilet paper and not cardboard? – Digital Trauma – 2016-01-13T19:01:45.363

I'm getting 2.416499187… for n = 3. That doesn't round to 2.417. Is my calculation off somewhere? – PurkkaKoodari – 2016-01-13T19:14:17.863

@Pietu1998 It's because when doing it by hand I rounded to 3 decimal places. – geokavel – 2016-01-13T19:16:47.590

So our programs do not have to round? – Conor O'Brien – 2016-01-13T19:35:45.223

@CᴏɴᴏʀO'Bʀɪᴇɴ Nope, less rounding is better. – geokavel – 2016-01-13T19:36:36.307

11@DigitalTrauma Clearly you don't know about triple-ply :p – geokavel – 2016-01-13T19:40:36.900

2Under the assumption that the toilet paper does not make steps but continuously increases the radius, you can get a closed form approximation to requested result. Is this good enough? nloops = sqrt(n+11.34)*0.0564189 - 0.19 – flawr – 2016-01-13T20:01:33.203

@flawr Sorry, no. – geokavel – 2016-01-13T20:04:14.793

Aside from the golfing aspect, I find this question incredibly amusing and even useful, lol. I wouldn't be surprised if this became a programming homework question and we see SO littered with this question!

– MonkeyZeus – 2016-01-13T21:13:20.357

2Proposed test case: 100 -> 40.874 – Dennis – 2016-01-13T22:45:16.783

1Triple-ply cardboard?! Now that's thick! – mbomb007 – 2016-01-13T22:59:05.767

1I'm not going to lie, I came here because I was expecting something else when I saw "toilet paper mysteries"... – Ashwin Gupta – 2016-01-15T03:20:01.330

@Ashwin Yeah, that was part off the idea :p – geokavel – 2016-01-15T03:21:44.933

1I can't get this shit to work. I think I need to try something different. :) – mathreadler – 2016-01-15T09:20:16.347

They see me rolling, they be knockin'. – mathreadler – 2016-01-15T09:28:32.230

It is literally a shit challenge. – sergiol – 2017-07-31T01:06:51.147

Answers

13

Pyth, 27 23 bytes

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

Try it online. Test suite.

Explanation

                            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

Posted 2016-01-13T18:34:27.500

Reputation: 16 699

explanation, please? – Conor O'Brien – 2016-01-13T19:52:39.820

@CᴏɴᴏʀO'Bʀɪᴇɴ Added. Explaining Pyth is always so much fun. – PurkkaKoodari – 2016-01-13T20:11:52.850

2

Your explanation looks like a potential output for Surfin' Word

– geokavel – 2016-01-13T21:24:35.263

10

Haskell, 59 46 44 bytes

A scale factor of 5/pi is applied, so that a paper cylinder has a circumference of 19,20,21... cm and a sheet is 50/pi cm.

Saved 2 bytes thanks to xnor, by using an unnamed function.

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

Damien

Posted 2016-01-13T18:34:27.500

Reputation: 2 407

A pretty recursive method. Note that unnamed functions are allowed even when you have other lines (despite Haskell not supporting it), so the last line can be pointfree as (19!).(50/pi*).

– xnor – 2016-01-14T00:23:29.627

Wow, blows my approach out of the water! – CR Drost – 2016-01-14T02:32:22.193

7

Jelly, 29 27 26 bytes

R+18×3.6°µ0;+\³_÷µḞi0©ị+®’

Try it online!

Dennis

Posted 2016-01-13T18:34:27.500

Reputation: 196 637

5

Haskell, 97 bytes

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

Might be able to golf it further by moving the filtering from the & operator into a takeWhile statement, but given that it's not a golfing language this seems relatively competitive.

Explanation

The stream of lengths of toilet paper that comprise full loops are first calculated as scanl (+) 0 (map (* pi) [0.38, 0.4 ..]]. We zip these with the number of full revolutions, which will also pick up the type Double implicitly. We pass this to & with the current number that we want to calculate, call it p.

& processes the list of (Double, Double) pairs on its right by (a) skipping forward until snd . head . tail is greater than p, at which point snd . head is less than p.

To get the proportion of this row that is filled, it then computes (p - x)/(y - x), and adds it to the overall amount of loops that have been made so far.

CR Drost

Posted 2016-01-13T18:34:27.500

Reputation: 949

4

C++, 72 bytes

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

I used C++ here because it supports default function arguments, needed here to initialize the radius.

Recursion seems to produce shorter code than using a for-loop. Also, auto instead of float - 1 byte less!

anatolyg

Posted 2016-01-13T18:34:27.500

Reputation: 10 719

1You almost fooled me, using d for the radius... – Toby Speight – 2016-01-15T12:24:46.617

3

Lua, 82 bytes

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)

Not bad for a general-purpose language, but not very competitive against dedicated golfing languages of course. The constants are premultiplied with pi, to the stated precision.

criptych stands with Monica

Posted 2016-01-13T18:34:27.500

Reputation: 181

OP wasn't specific about what kind of input to accept, so I left out the initialization of n, but the rest would've run as-is (as-was?). In any case, now it takes n from the command line; e.g. for 3 sheets run it as lua tp.lua 3. – criptych stands with Monica – 2016-01-14T14:01:28.317

It's not precisely a rule of this question, but a general policy. Unless the question says otherwise, hardcoding the input makes the submission a snippet, which are not allowed by default. More information about site-wide defaults can be found in the code golf tag wiki.

– Dennis – 2016-01-14T14:47:16.767

I knew about the "whole program or function" part but didn't know that "hardcoding the input makes the submission a snippet". Thanks for clarifying. I think this would actually be longer as a function! – criptych stands with Monica – 2016-01-14T18:15:37.847

3

C, 87 bytes

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

Uses an explicit formula for the number of whole loops:

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

I replaced 100 / pi by 31.831, and replaced floor with round, turning the annoying number -18.5 to a clean -19.

The length of these loops is

pi * n * (3.7 + 0.1 * n)

After subtracting this length from the whole length, the code divides the remainder by the proper circumference.


Just to make it clear - this solution has complexity O(1), unlike many (all?) other solutions. So it's a bit longer than a loop or recursion.

anatolyg

Posted 2016-01-13T18:34:27.500

Reputation: 10 719

3

JavaScript, 77 bytes

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

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

function wraps(sheets, diameter, circumference) {
    // Default the value of diameter
    diameter = diameter || 3.8;
    circumference = diameter * 3.14159;
    if (circumference > sheets * 10)
        return sheets * 10 / circumference;
    return 1 + wraps(sheets - circumference / 10, diameter + .2);
}

document.getElementById('text').innerHTML = "0 => " + w(0)
+ "\n1 => " + w(1)
+ "\n2 => " + w(2)
+ "\n3 => " + w(3)
+ "\n100 => " + w(100)

+ "\n\n0 => " + wraps(0)
+ "\n1 => " + wraps(1)
+ "\n2 => " + wraps(2)
+ "\n3 => " + wraps(3)
+ "\n100 => " + wraps(100);
<pre id="text"></pre>

Ross Bradbury

Posted 2016-01-13T18:34:27.500

Reputation: 131

3Welcome to PPCG! If you'd like, you can use JavaScript ES6, and get this to 55 bytes: w=(s,d=3.8,c=d*3.14159)=>c>s*10?s*10/c:1+w(s-c/10,d+.2) – Downgoat – 2016-01-15T04:22:20.930

2

C#, 113 bytes

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

Ungolfed:

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

Results:

for 1 sheet

0,837658302760201

for 2 sheets

1,64155077524438

for 3 sheets

2,41650110749198

for 100 sheets

40,8737419532946

ivaan

Posted 2016-01-13T18:34:27.500

Reputation: 191

2

PHP, 101 bytes

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

Ungolfed

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

I feel like this could be done a little shorter, but I ran out of ideas.

Samsquanch

Posted 2016-01-13T18:34:27.500

Reputation: 271

2

Python 3, 114 109 99 bytes

This function tracks the circumference of each layer until the sum of the circumferences is greater than the length of the number of sheets. Once this happens the answer is:

  • One less than the number of calculated layers + length of leftover sheets / circumference of most recent layer

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]

Update

  • -10 [16-05-09] Optimized my math-ing
  • -5 [16-05-04] Minimized number of lines

NonlinearFruit

Posted 2016-01-13T18:34:27.500

Reputation: 5 334

1

JavaScript, 44 bytes

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

I used anatolyg's idea and translated the code into JavaScript.

ericw31415

Posted 2016-01-13T18:34:27.500

Reputation: 2 229

1

><>, 46 44 bytes

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

Expects the number of sheets to be present on the stack at program start.

This uses an approximation of pi of 355/113 = 3.14159292..., storing pi/5 in the register. The current iteration's circumference lives on the stack, and pi/5 is added on each iteration.

Edit: Refactored to store the circumference directly - previous version stored pi/10 and started the diameter as 38, which was 2 bytes longer.

Sok

Posted 2016-01-13T18:34:27.500

Reputation: 5 592

0

PHP, 79 bytes

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

Run code in Sandbox

I have pretty much only translated Ross Bradbury's answer for JavaScript into a PHP function, which is also recursive.

Nick

Posted 2016-01-13T18:34:27.500

Reputation: 101

Please don't just copy another answer into another language. – Rɪᴋᴇʀ – 2016-05-10T20:37:40.587