井中的蜗牛


47

背景

有一个常见的谜语,像这样:

一只蜗牛在30英尺深的井底。蜗牛每天都能爬3英尺。晚上睡觉时,它们会向后滑动2英尺。蜗牛要离开井需要多少天?

直观的答案是

30天,因为蜗牛每天以1英尺的高度爬30天才能到达山顶,

但实际上答案是

28天,因为一旦蜗牛悬空了27英尺(27天之后),他们将在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我将把赏金授予最短的Gray Snail答案
musicman523

Answers:


21

Gray Snail,用于数字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-B到其中A

从开始的代码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-B并跳转到D何时A<=0。否则$分配A+CA并致电U

如果找不到解决方案,请挂起。

技巧:滥用“编译器”解释空字符串的能力。您可以剥离GOTO语句中的条件以进行无条件的跳转,同样的技巧也适用于POP

备注:我可以打更多3字节的高尔夫球,但是这样做,我和WheatWizard的答案将具有完全相同的逻辑。结果可能是最短的GraySnail解决方案,我正在尝试证明这一点。


你首先使它
ЕвгенийНовиков

嘿,我以为我会让你知道,我让我的时间比你的短。它只短了一个字节,并且从您的最新高尔夫中汲取了一些灵感。
小麦巫师

@WheatWizard根据您的旧答案,我有一个155字节的解决方案。但是对于体育精神,我不会将其视为答案。
科宇甘

@KeyuGan不,继续。我不在乎销售代表。我很高兴被打败。如果我的代码可以打高尔夫球,那是我没看到它的错。:)
小麦巫师

@WheatWizard我也没有。我敢肯定,这是我曾经有过PPCG的最好时光。
Keyu Gan'7

20

注意: Martin Ender在评论中质疑字节数。对于在C#答案中使用命名的递归lambda表达式该怎么办似乎没有明确的共识。所以我在Meta中了一个问题

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递归调用,则必须计算将函数分配给名称的代码。
Martin Ender

4
我不会用C#打高尔夫球,所以我不能完全确定共识是什么,但是我希望这需要一个完整的声明,f并带有一个声明和一个分号(如果命名的话)。我发现的第一件事是这个,但是这里没有明确的共识。
Martin Ender

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

我想我可以打一点。


恭喜你!
Keyu Gan'7

11

JavaScript(ES6),31 28 27字节

@Arnauld节省了几个字节

我还没有意识到我们可能会因异常而失败。可以肯定这是最佳选择:

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

使用例如分配给变量f=,然后调用like 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
显而易见:如果蜗牛进行的递归过多,则不可能进行爬升。:)
Tushar

1
也许27具有反向的curring语法?d=>u=>g=h=>h>u?1+g(h-u+d):1
Arnauld

@Arnauld谢谢,效果非常好……
ETHproductions '17

我是一个困惑的字节计数-在一个变量分配给函数t包括在内,另一个不?
显示名称

在最高版本中,@ Orangesandlemons位于g=中间,因为此变量存储递归调用所需的中间函数。较长的答案对进行递归调用f,该调用要求将该名称包括在字节数中。
musicman523

10

Excel,51 46字节

-1个字节感谢@ Scarabee

-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),所以我想你可以通过更换节省1个字节CEILING((A1-B1)/(B1-C1)+1,1)-FLOOR((B1-A1)/(B1-C1)+1,1)
Scarabee

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#解决方案的启发。

稍后(在完成我的Gray Snail回答后),我将更新扩展版本。


好东西!您能提供分析(非压缩)解决方案吗?
koita_pisw_sou

1
@koita_pisw_sou好的。
Keyu Gan'7

它根本不“返回”任何东西。您分配给局部参数,函数返回后其值就会消失。蜗牛被卡在永恒的边缘。
科迪·格雷

@CodyGray在GCC中使用稳定但未定义的行为。待会儿我可以给你链接。
Keyu Gan


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已经有一段时间了,但是高尔夫就是高尔夫,无论何时发生:-)
OlivierGrégoire18

我的想法正好。在某些情况下,当我看一些最初的答案时,我会打高尔夫球将原来的字节减半。;)
Kevin Cruijssen

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”换为“ __> 0”,将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=仅当lambda不起作用时才可以将其删除。
Xcoder先生17年

注意并解决。谢谢你让我知道。
Coty Johnathan Saxman '17

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
  • %/ 在列表的每个元素之间放置一个分隔符号,在我们的示例中,列表只有两个项目,因此它的意思是“ 27除以1”
  • >: 加1
  • >. 天花板

官方解决方案

这是将负数和无穷大转换为0的官方解决方案,这部分我无法找到令人满意的简洁解决方案:

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

蒂奥


If the snail cannot climb out of the well, you may return 0, return a falsy value, or throw an exception.为了编写测试用例,我只是选择None表明没有答案。您还会考虑添加说明和“在线试用”链接吗?
musicman523

@ musicman523已修复并完成。
约拿(Jonah)



2

Mathematica,47 40 39字节

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

@KeyuGan -7个字节


据我认为,您需要处理输入,69, 3, 8并且被算作3个字节。
Keyu Gan

全部固定!立即尝试
J42161217

您可以使用Maxreplace If语句。If[#<=#2,1,Max[⌈(#-#3)/(#2-#3)⌉,0]]&
Keyu Gan

2

红宝石49 47字节

->h,a,b{h-a<1?1:(1.0*(h-a)/[a-b,0].max+1).ceil}

如果蜗牛无法爬出则会抛出异常

在线尝试!


1
@Jonah解决了它
Alex

这个过程背后的原因是什么?h-a<1?1:(1.0*(h-a)/[a-b,0].max+1).ceil通过测试用例,并节省9个字节。
加伦

2

批次,66个字节

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

第二个最后一个测试用例什么也不打印,最后一个测试用例实际上崩溃了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;

打印NNone。用运行-r



2

Japt,12个字节

@UµV-W §W}aÄ

在线测试!

undefined在可能冻结浏览器一段时间之后,永远不会输出,因此请小心。

我不认为这是最佳选择。oWV-W l适用于除最后三种情况以外的所有情况...


通过更改输入的顺序来解决 11个字节的问题。
粗野的

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 '17

@Laikoni不知道可以做到这一点。谢谢你的提示。
小麦巫师

您可以b!c在列表理解中放下括号。
Zgarb

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)

在线尝试!(好的,不是真的:这是QBIC到在repl.it的QBasic环境中运行的QBasic代码的翻译)


2

Excel VBA,47字节

匿名VBE立即窗口功能,可[A1:C1]ActiveSheet对象输出到VBE立即窗口的范围内接受输入

这个主要基于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<s0<1,就像您在解释中已经隐含的那样,因为otherwise它只是的同义词True。2.您的元组版本中的递归调用仍处于咖喱状态。3.您可以将函数定义为,(d#c)s而不是f d c s再保存两个字节。
Laikoni '17

1
您还需要c<=s而不是c<s
Laikoni '17

1
重新排序和使用0而不是-1OP允许的数量为38个字节:在线尝试!
Laikoni '17

1
您可以使用中缀标识符来保存任何字节吗?
musicman523

我不知道,我是否应该发布经过编辑的分析服务,因为它是必不可少的@Laikoni的答案
Sergii Martynenko Jr




1

Python v2和v3,44字节

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

^无情况的无限递归(错误)。


您可以使用lambda。另外,这似乎与我的(Java)答案相似,因此请允许我提出以下公式的改进建议:(x-z-1)//(y-z)+1。我没有做太多的Python,所以我可能错了……
OlivierGrégoire17年

您可以f=从字节数中消除,在ifs和else周围删除一些空格,然后切换到Python 2,其中整数除法是单个的/
musicman523 '17

谢谢@ musicman523。我最终接受了您的所有建议。
veganaiZe

1
我意识到,当与其他输入(例如4、3、8)一起使用时,我的“干净”(无穷递归)代码存在很多极端情况。@ musicman523我想我已经开始看到您所说的“证据”。
veganaiZe'7

1

HP-15C可编程计算器,26字节

在运行程序之前,将这三个数字按顺序装入堆栈。下降高度输入为负数。如果蜗牛不能爬出井,则结果为负数或错误#0(零分错误)。

十六进制的操作码:

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'7

1

Common Lisp,49个字节

(defun f(a b c)(if(> a b)(1+(f(+(- a b)c)b c))1))

在线尝试!

递归函数,如果找不到解决方案,则堆栈溢出。


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.