厕纸之谜


36

今天,您需要解决一个非常实际的问题:您的厕纸卷上需要多少循环才能容纳一定数量的纸张?让我们看一些事实:

  • 裸露卫生纸筒的直径为3.8厘米
  • 一张卫生纸的长度为10厘米。
  • 一张卫生纸的厚度为1mm。

第一次缠绕圆柱体之前,其周长为3.8 * pi(厘米)。每次在圆柱体上缠绕一张纸时,其半径都会增加.1,因此其周长会增加.2 * PI。使用此信息可以找出装入n张厕纸所需的循环次数。(注意:使用近似值Pi至少应与3.14159一样准确)。

测试用例

n = 1

  • 10 /(3.8 * pi)= .838循环

n = 2

  • (我们可以进行多少个完整循环?)1个完整循环= 3.8 * pi = 11.938。
  • (在第一个循环之后,我们还剩下多少?)20-11.938 = 8.062
  • (剩下的第二个循环产生多少?)8.062 /(4 * pi)= .642循环
  • 答案:1.642次循环

n = 3

  • 第一个完整循环= 3.8 * pi = 11.938,第二个完整循环= 4 * pi = 12.566
  • 30-11.938-12.566 = 5.496
  • 5.496 /(4.2 * pi)= .417
  • 答案:2.417次循环

n = 100 => 40.874


35
!1毫米厚?您确定使用卫生纸而不是硬纸板吗?
Digital Trauma

11
@DigitalTrauma显然,您不知道三层:p
geokavel

2
在卫生纸不走一步而是不断增大半径的假设下,您可以获得所需结果的近似闭合形式。这样够好吗?nloops = sqrt(n+11.34)*0.0564189 - 0.19
瑕疵的

2
建议的测试用例:100->40.874
丹尼斯(Dennis)

1
三层纸板?现在厚!
mbomb007 '16

Answers:


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)

请解释一下
科纳·奥布莱恩

@CᴏɴᴏʀO'Bʀɪᴇɴ添加了。解释Pyth总是很有趣。
PurkkaKoodari

2
你的解释看起来像一个潜在的输出的Surfin'字
geokavel

10

Haskell,59 46 44字节

比例因子为5 / pi,因此纸筒的周长为19,20,21 ... cm,纸张为50 / pi cm。

由于使用了xnor,使用未命名的函数节省了2个字节。

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
你几乎愚弄了我,用dradius ...
托比斯佩特

3

Lua,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,达到规定的精度。


OP并未具体说明要接受哪种输入,因此我省略了的初始化n,但其余的将按原样运行(原样?)。无论如何,现在都需要n从命令行获取;例如3张纸作为运行lua tp.lua 3
criptych与Monica站在

这不完全是这个问题的规则,而是一般政策。除非问题另行说明,否则对输入进行硬编码会使提交成为摘要,默认情况下不允许。有关站点范围默认值的更多信息,请参见代码golf tag wiki
丹尼斯

我知道“整个程序或函数”部分,但不知道“对输入进行硬编码会使提交成为摘要”。感谢您的澄清。我认为这实际上会更长一些!
criptych与Monica站在

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

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 / pi31.831,换成floorround,把恼人的数量-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

预计程序启动时将在堆栈中出现的纸张数量。

这使用pi的近似值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);}

在沙盒中运行代码

我几乎只将Ross Bradbury对于JavaScript的答案转换为PHP函数,这也是递归的。


请不要只将另一个答案复制到另一种语言。
Rɪᴋᴇʀ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.