トイレットペーパーの謎


36

今日、非常に実用的な問題を解決する必要があります。トイレットペーパーのロールに一定の枚数のシートを置くために、いくつのループが必要ですか。いくつかの事実を見てみましょう。

  • 裸のトイレットペーパーシリンダーの直径は3.8cmです
  • トイレットペーパー1枚の長さは10cmです。
  • 1枚のトイレットペーパーの厚さは1mmです。

シリンダーを最初に巻き付ける前のシリンダーの円周は3.8 * piです。シートを円柱に巻き付けるたびに、半径が.1ずつ増加するため、円周は.2 * PIずつ増加します。この情報を使用して、n枚のトイレットペーパーを収めるために必要なループの数を調べます。(注:少なくとも3.14159と同じ精度のPiの近似値を使用してください)。

テストケース

n = 1

  • 10 /(3.8 * pi)= .838ループ

n = 2

  • (完全なループをいくつ作成できますか?)1つの完全なループ= 3.8 * pi = 11.938。
  • (最初のループの後にどれくらい残っていますか?)20-11.938 = 8.062
  • (残りの部分はどのくらいの2番目のループを作成しますか?)8.062 /(4 * pi)= .642ループ
  • 回答:1.642ループ

n = 3

  • 1番目の完全ループ= 3.8 * pi = 11.938、2番目の完全ループ= 4 * pi = 12.566
  • 30-11.938-12.566 = 5.496
  • 5.496 /(4.2 * pi)= .417
  • 回答:2.417ループ

n = 100 => 40.874


35
ふう!厚さ1mm?段ボールではなくトイレットペーパーを使用しているのですか?
デジタル外傷

11
@DigitalTrauma明らかにトリプルプライについては知らない:p
geokavel

2
トイレットペーパーはステップを作らず、半径を連続的に増加させるという仮定の下で、要求された結果に対して閉じた形の近似を得ることができます。これで十分ですか?nloops = sqrt(n+11.34)*0.0564189 - 0.19
-flawr

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)

説明してください?
コナーオブライエン

@CᴏɴᴏʀO'Bʀɪᴇɴが追加されました。Pythの説明はいつもとても楽しいです。
-PurkkaKoodari

2
あなたの説明はSurfin 'Wordの
-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ドロス


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)するまで前方にスキップ()によって、その右側に対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ためr... adius
トビースパイツ

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は省略しましたが、残りはそのまま(as-was?)実行していました。いずれにせよ、今ではnコマンドラインから取得します。たとえば、3シートの場合はとして実行しますlua tp.lua 3
クリプティクはモニカと一緒に

これは正確にはこの質問のルールではなく、一般的なポリシーです。質問で特に断りのない限り、入力をハードコーディングすると送信がスニペットになりますが、これはデフォルトでは許可されいません。サイト全体のデフォルトについての詳細は、ゴルフタグwikiのコードを参照してください
デニス

「プログラムまたは関数全体」の部分については知っていましたが、「入力をハードコーディングすると送信がスニペットになる」ことを知りませんでした。明確にしてくれてありがとう。これは実際には関数としてより長くなると思います!
クリプティクはモニカと一緒に

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へようこそ!必要に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、および置き換え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バイト

この機能は、円周の合計がシート数の長さより大きくなるまで、各レイヤーの円周を追跡します。これが発生すると、答えは次のとおりです。

  • 計算された層の数+残りのシートの長さ/最新の層の円周より1つ少ない

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バイト長く保存され、開始されました。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.