井戸のカタツムリ


47

バックグラウンド

次のような一般的な謎があります。

カタツムリは30フィートの井戸の底にあります。毎日カタツムリは3フィートを登ることができます。彼らが眠る夜、彼らは2フィート下にスライドします。カタツムリが井戸から出るのに何日かかりますか?

直感的な答えは

30日。カタツムリは1日に1フィートで30日間登り、頂上に到達するため

しかし、実際には答えは

28日。カタツムリが空中に27フィート(27日後)になると、残りの3フィートを28日目に単純に登ります。

チャレンジ

この挑戦はこの謎を一般化します。合計の高さ、上昇高さ、および下降高さを表す3つの正の整数を入力として指定すると、井戸から上昇するまでにかかる日数を返します。

カタツムリが井戸から登れない場合は、0を返すか、偽の値を返すか、例外をスローします。ソリューションが存在する場合にのみ停止するコードを記述することもできます。

必要に応じて、落下高さを負の整数として取得できます。

テストケース

(30、3、2)-> 28
(84、17、15)-> 35
(79、15、9)-> 12
(29、17、4)-> 2
(13、18、8)-> 1
(5、5、10)-> 1
(7、7、7)-> 1
(69、3、8)->なし
(81、14、14)->なし

得点

これはであるため、各言語で最も短い回答が優先されます。



8
誰かが灰色のカタツムリで答えた場合、おそらく賞金を授与します。Esolangsページはちょうど空のスタブですが、そこにあるいくつかの情報と利用可能なオンラインコンパイラだけでなく、ビールの問題の99本のボトル用サンプルプログラムは
musicman523

4
これは単純な式だと思いましたが、ケースワークは驚くほど興味深いものです。
XNOR

あなたはまだ「何時間....」を持っています。答えは27 * 24 + 12です(12時間の「日」を想定)。
フランシスデイビー

2
私は最短グレーカタツムリの答えに懸賞金授与されます@WheatWizard
musicman523

回答:


21

灰色のカタツムリ、数値I / Oの場合は1206バイト、単項I / Oの場合は149バイト

楽しみのために。最初のプログラムの構成:

  • 451バイト、数値をドットに変換
  • 121バイト、コア機能(個別のバージョンを以下に記載)
  • 634バイト、ドットを数値に変換

数値の入力と出力を受け取ります。入力があるABCそれぞれ。他の(ほぼ)O(1)答えと比較すると、コードはの複雑さを持っていますO(n)。しかし、多くの場合、最初に記憶を使い果たす可能性があります。

解決策が見つからない場合はハングします。

INPUT p
POP Z r .!
f
POP Z o .
q
POP Z p [p]
GOTO [Z]
0
POP Z n .
GOTO w
1
POP Z n ..
GOTO w
2
POP Z n ...
GOTO w
3
POP Z n ....
GOTO w
4
POP Z n .....
GOTO w
5
POP Z n ......
GOTO w
6
POP Z n .......
GOTO w
7
POP Z n ........
GOTO w
8
POP Z n .........
GOTO w
9
POP Z n ..........
GOTO w
w
POP Z o .[o][o][o][o][o][o][o][o][o][o][n]
GOTO [r] [p] 
GOTO q
!
POP Z A .[o]
INPUT p
POP Z r .@
GOTO f
@
POP Z B .[o]
INPUT p
POP Z r .#
GOTO f
#
POP Z C .[o]
POP H N .[B]
U
POP Z A [A]
POP Z B [B]
GOTO D [A] 
GOTO $ [B] 
GOTO U
$
POP Z A .[A][C]
POP Z H ..[H]
POP Z B .[N]
GOTO U
D
POP Z r .
POP Z M .
POP Z N ...........
POP Z z .[N]
POP Z V .[H]
+
GOTO l[V] [H] 
POP Z H [H]
POP Z z [z]
GOTO ( [z] 
GOTO +
(
GOTO ) [H] 
POP Z z .[N]
POP Z M ..[M]
POP Z V .[H]
GOTO +
)
POP Z r .0[r]
POP Z M ..[M]
POP Z H .[M]
POP Z M .
POP Z V .[H]
POP Z z .[N]
GOTO +
l
POP Z r .0[r]
GOTO -
l.
POP Z r .1[r]
GOTO -
l..
POP Z r .2[r]
GOTO -
l...
POP Z r .3[r]
GOTO -
l....
POP Z r .4[r]
GOTO -
l.....
POP Z r .5[r]
GOTO -
l......
POP Z r .6[r]
GOTO -
l.......
POP Z r .7[r]
GOTO -
l........
POP Z r .8[r]
GOTO -
l.........
POP Z r .9[r]
GOTO -
-
GOTO / [M] 
POP Z H .[M]
POP Z M .
POP Z V .[H]
POP Z z .[N]
GOTO +
/
OUTPUT [r]

f整数をドットに変換する(おそらく)再帰関数です。引数はに保存され[p]、出力され[o]ます。

U機能検査でS1>=S2のパラメータを格納し、B, A保存中A-BA

から始まるコードDは、ドットを数字に変換するスタブです。

基本的な原理は、私のCの答えと同じです(不可能な解決策のために偽の出力をはぎ取る)。

スタンドアロンバージョン、149 156 157 167 170 230 バイト、単項I / Oのみをサポート

入力は、例えば、ドットにする必要がある..........ため10

INPUT A
INPUT B
INPUT C
POP N H .
GOTO U
$
POP N A .[A][C]
POP Z H ..[H]
U
POP Z A [A]
POP Z N ..[N]
GOTO D [A] 
GOTO $ .[B] [N]
GOTO U
D
OUTPUT .[H]

U計算しA=A-BDいつにジャンプしA<=0ます。それ以外の場合は、に$割り当てA+CA呼び出しますU

解決策が見つからない場合はハングします。

トリック:空の文字列を解釈する「コンパイラ」の機能を悪用します。GOTOステートメントの条件をリッピングして、無条件ジャンプを行うことができますPOP

注釈: 3バイト以上ゴルフをするかもしれませんが、そうすることで、私とWheatWizardの答えはまったく同じロジックになります。結果はおそらく最短のGraySnailソリューションであり、私はそれを証明しようとしています。


あなたは、まずそれを作った
ЕвгенийНовиков

ねえ、私はあなたのものよりも短いものにしたことをあなたに知らせると思っただけです。1バイト短く、最新のゴルフからインスピレーションを得ています。
小麦ウィザード

@WheatWizard私はあなたの古い答えに基づいて155バイトのソリューションを持っています。しかし、スポーツマンシップについては、私はそれを私の答えとは見なしません。
キーガン

@KeyuGanいいえ、どうぞ。私は担当者がゲームについてすべて気にしません。beatられてうれしいです。私のコードをゴルフできるなら、それを見ないのが私のせいです。:)
小麦ウィザード

@WheatWizard私もです。私は今までPPCGで最高の時間だと確信しています。
キーガン

20

注:バイトカウントはコメントでMartin Enderによって質問されています。C#回答の名前付き再帰再帰ラムダ式をどう処理するかについて、明確なコンセンサスがないようです。だから私はそれについてメタで質問をしました。

C#(.NET Core)32 31バイト

f=(a,b,c)=>a>b?1+f(a-b+c,b,c):1

オンラインでお試しください!

再帰的アプローチ。カタツムリが脱出できない場合、次のメッセージで終了します。Process is terminating due to StackOverflowException.

  • LiefdeWenのおかげで1バイト節約されました!

1
あなたは、変更、バイトのバイトを保存することができますa<=ba>b、次の部品を交換する
LiefdeWen

3
ES6でまったく同じコードの作品f=(a,b,c)=>a<=b?1:1+f(a-b+c,b,c)
Tushar

f再帰呼び出しの名前に依存している場合、名前に関数を割り当てるコードをカウントする必要があります。
マーティンエンダー

4
私はC#でゴルフをしませんので、コンセンサスが何であるかは完全にはわかりませんが、f名前が付けられている場合は、セミコロンと宣言を含む完全なステートメントが必要になると予想していました。私が最初に見つけたのはこれですが、ここには明確なコンセンサスはありません。
マーティンエンダー

2
@MartinEnderカルロスがここでやったように、私は通常やるだけです。宣言はf=...、セミコロンを最後に追加するかどうかがわからないだけだからです。
TheLethalCoder

13

GRAY SNAIL、219 206 169 167 159 156 146バイト(単項IO)

INPUT a
INPUT u
INPUT d
POP U c 
GOTO 1
3
POP f a [a][d]
POP U c ..[c]
1
GOTO 2 [a] 
GOTO 3 [U] [u]
POP f U ..[U]
POP f a [a]
GOTO 1
2
OUTPUT [c].

これを少しだけゴルフできると思います。


おめでとうございます!
キーガン

11

JavaScript(ES6)、31 28 27バイト

@Arnauldのおかげで数バイト節約

例外で失敗する可能性があるとは思いもしませんでした。これが最適であることを確認してください:

u=>d=>g=h=>h>u?1+g(h-u+d):1

たとえばf=、変数に代入し、次のように呼び出しますf(climb)(fall)(height)InternalError: too much recursion登ることが不可能な場合にスローされます。


JavaScript(ES6)、38バイト

f=(h,u,d=0)=>h>u?u>0?1+f(h-u,u-d):+f:1

日数を返す、またはNaN決して返さない再帰関数。

テストケース


2
それは明らかです。カタツムリがあまりにも多くの再帰を行う場合、登ることは不可能です。:)
トゥーシャー

1
おそらくカレー構文を逆にした27ですか?d=>u=>g=h=>h>u?1+g(h-u+d):1
アーナルド

驚くほどうまく機能@Arnauldおかげで、...
ETHproductions

私はそれがバイトカウントに混乱している-関数に割り当てられた変数に含まれているtは含まれていますか?
表示名

上のバージョンの@Orangesandlemonsでは、g=この変数が再帰呼び出しに必要な中間関数を格納しているため、中間にあります。より長い答えはf、名前をバイトカウントに含めることを義務付けるの再帰呼び出しを行います。
musicman523

10

Excel、51 46バイト

@ Scarabeeのおかげで-1バイト。

-4 INT(x)= FLOOR(x、1)のため

=IF(B1<A1,IF(C1<B1,-INT((B1-A1)/(B1-C1)-1)),1)

セルA1、B1、およびC1からそれぞれ取得した入力。FALSE無効なシナリオを返します。


ceiling(x)は常に等しいため-floor(-x)、で置き換えることCEILING((A1-B1)/(B1-C1)+1,1)で1バイト節約できると思います-FLOOR((B1-A1)/(B1-C1)+1,1)
スカラビー

7

C(gcc)、39 43 44 46 47 58 60 バイト

32ビットGCCのみで、すべての最適化がオフになりました。

f(a,b,c){a=a>b?b>c?1+f(a-b+c,b,c):0:1;}

解決できない場合は0を返します。元の再帰的ソリューションの修正バージョン。

@Jonah Jソリューションと@CarlosAlejo C#ソリューションに触発されました。

グレーのカタツムリの答えを終えた後、拡張バージョンを更新します。


良いですね!分析(非圧縮)ソリューションを含めることができますか?
koita_pisw_sou

1
@koita_pisw_souもちろん。
キーガン

何も「戻りません」。関数が戻ると値が蒸発するローカルパラメータに割り当てます。カタツムリは永遠の縁で立ち往生しています。
コーディグレー

@CodyGrayは、GCCで安定しているが未定義の動作を使用します。後でリンクを表示できます。
キーガン


7

Java(OpenJDK 8)、35バイト

(a,b,c)->b<a?c<b?(a+~c)/(b-c)+1:0:1

オンラインでお試しください!

数学が勝つ!

クレジット


1
それはしばらくして、しかしですa-c-1a+~c
ケビンクルーイッセン

1
ありがとう@KevinCruijssen久しぶりですが、ゴルフはいつでも起こります:
オリビエグレゴワール

私の考えは正確に。いくつかの機会に、最初の回答のいくつかを見たときに、元のバイトを半分にすることについてゴルフをしました。;)
ケビンクルーイッセン

5

Python 2、37バイト

f=lambda x,y,z:x-y<1or 1+f(x-y+z,y,z)

オンラインでお試しください!

最後に、再帰バージョンを標準の計算よりも低くしました(関数を呼び出す前にカウントを追加する代わりにカウントを関数に渡していました)。

Pythonの2、4346 バイト

#43 bytes
lambda x,y,z:y/x>0 or[1-(x-y)/(z-y),0][z/y]
#46 bytes
lambda x,y,z:y/x and 1or[1-(x-y)/(z-y),0][z/y]

オンラインでお試しください!

「__> 1」を「__ and 1」と交換して、3バイト削りました。

ブールトリックを使用して、基本的に次を実行します。

if floor(y/x) > 0:
    return True # == 1
elif floor(z/y) == 1:
    return 0
elif floor(z/y) == 0:
    return 1-floor((x-y)/(z-y))
    # Python 2 implicitly treats integer division as floor division
    # equivalent: 1 + math.ceil((y-x)/(z-y))
    # because: -floor(-x) == ceil(x)

2
f=コードの前に置く必要があり(最初の解決策)、バイトカウントは37になります。これは再帰的であるため、匿名のままにできないためです。f=ラムダの場合は、不快ではない場合にのみドロップできます。
氏Xcoder

注目され対処された。知らせてくれてありがとうございます。
コティジョナサンサックスマン

4

R、43バイト

他の答えから借りる:

g=function(a,b,c)`if`(b<a,1+g(a-b+c,b,c),1)

解決策がない場合はエラーになります。


素敵な答え。PPCGへようこそ!
musicman523

3

J、25バイト

「正の整数の結果以外のもの」が「なし」に等しいと仮定しているため、最初の素晴らしい解決策はチートです。

>.>:%/2-/\

説明

  • 2-/\3つの項目入力で長さ2のウィンドウを使用し、入力ごとにマイナス記号を配置し30 3 2ます。27 1
  • %/ リストの各要素の間に分割記号を配置します。この場合、リストには2つの項目しかないため、「27で1で分割」を意味します
  • >: 1ずつ増加
  • >. 天井を取る

公式ソリューション

以下は、負と無限大を0に変換する公式の解決策です。

0:`[@.(>&0*<&_)>.>:%/2-/\

TIO


If the snail cannot climb out of the well, you may return 0, return a falsy value, or throw an exception.テストケースを書くためNoneに、答えがなかったことを示すことにしました。説明とオンラインで試すリンクを追加することも検討しますか?
musicman523

@ musicman523修正および完了。
ジョナ



2

Mathematica、47 40 39バイト

If[#==#2,1,⌈(#-#3)/(#2-#3)⌉~Max~0]&

@KeyuGanから-7バイト


あなたは、などの入力に対処する必要がある69, 3, 8限り私が思うよう3バイトとしてカウントされます。
Keyuガン

すべて修正済み!今それを試してみてください
J42161217

ステートメントMaxを置き換えるために使用できますIfIf[#<=#2,1,Max[⌈(#-#3)/(#2-#3)⌉,0]]&
キーガン


2

バッチ、66バイト

@set/an=%4+1,a=%1-%2+%3
@if %1 gtr %2 %0 %a% %2 %3 %n%
@echo %n%

最後から2番目のテストケースでは何も印刷されず、最後のテストケースは実際にクラッシュしましたCMD.EXE...


2

05AB1E、19バイト

0[¼²+D¹<›i¾q}³-D1‹#

説明:

0                   Initialise stack with 0
 [                  while(true)
  ¼                   increment the counter variable
   ²+                 add the second input to the top of the stack
     D¹<›i            if it is greater than or equal to the first input
          ¾             push the counter variable
           q            terminate the program
             }        end if
              ³-      subtract the third input from the top of the stack
                D     duplicate top of stack
                 1‹   if it is less than 1
                   #  break the loop

無効な値の場合、これは1未満の任意の値を返すことがあります。ただし、05AB1Eでは、1のみが真実であるため、無効な値の出力は偽であるという要件を満たしています。

オンラインでお試しください!


2

PHP、60バイト

[,$h,$v,$d]=$argv;echo$h>$v?$v>$d?ceil(($h-$d)/($v-$d)):N:1;

印刷物NのためNone。で実行し-rます。




2

Haskell30 29バイト

(b!c)a=1+sum[(b!c)$a+c-b|a>b]

オンラインでお試しください!

既存のHaskellの回答よりも短い。おそらく他の誰かが私を打ち負かすことができます。

これは、再帰的アプローチを使用して問題を解決します。各再帰は本質的にカタツムリの動きの日です。最後まで残った距離がまだ必要な距離よりも短い場合、再帰を終了します。


中置表記法で1バイトを保存します(b#c)a=1+sum[(b#c)$a+c-b|a>b]
ライコニ

@Laikoniそれができるとは知らなかった。ヒントをありがとう。
小麦ウィザード

b!cリストの理解度に括弧をドロップできます。
ズガルブ

2

QBIC31 23バイト

要件が変更されたことに注意してください。このバージョンでは、カタツムリが井戸の最上部に到達するかどうかはチェックされません。

≈:-:>0|q=q+1┘a=a-b+:]?q

以下の説明では、ソリューションが存在するかどうかを確認する元のバージョンについて、このコードのすべての関連部分もカバーしています。


元の31バイトの回答:

~:>:|≈:-a>0|q=q+1┘c=c-a+b]?q\?0

説明

~           IF
 :          cmd line arg 'a'  (the increment of our snail)
  >         is greater than
   :        cmd line arg 'b'  (the decrement, or daily drop)
    |       THEN
≈           WHILE
 :          cmd line arg 'c'  (the height of the well)
  -a        minus the increment (we count down the hieght-to-go)
    >0|     is greater than 0 (ie while we haven't reached the top yet)
q=q+1       Add a day to q (day counter, starts at 1)
┘           (syntactic linebreak)
c=c-a+b     Do the raise-and-drop on the height-to-go
]           WEND
?q          PRINT q (the number of days)
\?0         ELSE (incrementer <= decrementer) print 0 (no solution)

オンラインでお試しください!(実際、そうではありません:これは、repl.itの(やや欠けている)QBasic環境で実行されるQBICからQBasicコードへの変換です)


2

Excel VBA、47バイト

オブジェクト出力からVBEイミディエイトウィンドウまでの範囲[A1:C1]から入力を受け取る匿名VBEイミディエイトウィンドウ関数ActiveSheet

この主にExcelの数式ベースのソリューションは、私が思いつくことができる純粋なVBAソリューションよりも小さいようです:(

?[If(B1>C1,-Int((B1-A1)/(B1-C1)-1),Int(A1=B1))]

1

Haskell、47 55バイト(タプルが必要な場合は48)

f d c s|d<=c=1|c<s= -1|d>c||c<s=1+(f(d-c+s)c s)

タプルのバリエーション

f(d,c,s)|d<=c=1|c<s= -1|d>c||c<s=1+(f(d-c+s)c s)

説明

f d c s       function that does all the heavy lifting =)
              d - depth
              c - climb per day
              s - slide per night

 |d<=c=1             recursion terminator. 1 day of climbing 
 |c<s= -1            possibility check. top can't be reached
 |otherwise=1+(f(d-c+s)c s)  1 day plus the rest of the distance

1
1. 説明ですでに暗黙的に行っているように、d>c||c<sだけで置き換えることができます。0<1これotherwiseはの同義語であるためですTrue。2.タプルバージョンの再帰呼び出しはまだカリー化されています。3. さらに2バイトを節約する(d#c)s代わりに、関数を定義できf d c sます。
ライコニ

1
c<=s代わりにも必要ですc<s
ライコニ

1
OPで許可されている0代わりに並べ替えて使用すると-1、38バイトになります。オンラインで試してみてください。
ライコニ

1
中置識別子を使用してバイトを保存できますか?
musicman523

それはLaikoniの答え@ esentialyあるので、私が編集したANSERを投稿する必要がある場合、私は、知らない
セルギMartynenkoジュニア




1

Python v2およびv3、44バイト

f=lambda x,y,z:1+f(x-(y-z),y,z)if x>y else 1

^なしの場合の無限再帰(エラー)。


ラムダを使用できます。また、これは私の(Java)の回答に似ているように見えるので、式の改善を提案できるようにします(x-z-1)//(y-z)+1。私は間違っているかもしれないので、私は、あまりのPythonをしない...
オリヴィエ・グレゴワール

あなたは排除することができf=、バイトカウントからIFSとよその周りにいくつかのスペースを削除して、整数の除算が単一であるPythonの2のスイッチ/
musicman523

ありがとう@ musicman523。私はあなたのアドバイスをすべて受けてしまいました。
ベガナイズ

1
私の "クリーン"(無限再帰なし)コードは、他の入力(4、3、8など)で使用すると、多くのコーナーケースの問題があることに気付きました。@ musicman523あなたの言う「証明」を見始めていると思います。
ベガナイズ

1

HP-15C Programmable Calculator、26バイト

3つの数字は、プログラムを実行する前に順番にスタックにロードされます。落下高さは負の数として入力されます。カタツムリが井戸から抜け出せない場合、結果は負の数またはエラー#0(ゼロ除算エラー)になります。

16進数の命令コード:

C5 C1 B4 C5 FB 74 1A C4 FA B4 C5 FD C1 C1 A3 70 C6 F0 B4 FA EB F1 FA B2 0A F1

命令の意味:

x↔y 
ENTER
g R⬆
x↔y 
− 
g TEST x≤0 
GTO A
R⬇
+ 
g R⬆
x↔y 
÷ 
ENTER
ENTER
f FRAC
TEST x≠0 
EEX 
0 
g R⬆
+ 
g INT 
1 
+ 
g RTN 
f LBL A
1

このHP-15Cシミュレーターでプログラムを試すことができます。


これはすごい!PPCGへようこそ:)
musicman523


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