dc,47个字节
dc,48个字节
还有Bash + Unix实用程序,29字节
直流电(47字节):
1sb[_1sb]s zz?sdlb*sc[pld+lnx]sl[dlb*lcr<l]dsnx
在线尝试!
请注意,负数必须用下划线而不是负号输入,因为这是dc接受数字输入的方式。因此,例如,写_5而不是-5。
dc无法读取输入到变量中的字符或字符串并对其进行处理(下面有更详细的说明),但是我发现了解决此问题的两种方法:
在47个字节的DC解决方案适用于具有参数1和参数2逆转,用空格作为分隔符输入。因此,从1到(但不包括)10的步长为3的计数将输入为:
< 1 10 3
如果不能改变参数的顺序,我还提供了一个48字节的dc解决方案,该解决方案保留了参数的原始顺序。这zz
用作参数之间的分隔符。因此,以3的步数从1向上计数(但不包括10)将再次使用以下输入行:
1zz<zz10zz3
最后,相同的想法产生了一个29字节的bash解决方案。
有关dc缺少字符串处理以及该程序如何处理的详细信息:
在dc中处理此问题非常棘手,因为dc不像大多数语言那样接受字符串或char输入。dc读取输入字符串时,它将立即作为dc程序(宏)运行该字符串,然后丢弃该字符串。您不能将字符串的字符存储在内存中,以后再以其他任何方式对其进行处理。这会干扰输入中必须包含“ <”或“>”的要求。
我将展示两种解决方法。在上述解决方案(47字节)中,我们切换了前两个输入的顺序。输入定界符是空格字符。例如,要以3的步长从1到(但不包括)10进行计数,您需要输入
< 1 10 3
这是此解决方案背后的想法:
dc中的宏存储在寄存器中,并且寄存器具有单字符名称。我将宏存储在寄存器中,其名称只是一个空格字符。
该程序通过在获取输入之前在堆栈上压入0和1来工作。然后,当输入作为dc程序运行时(这是dc在输入行中所做的事情),'<'或'>'字符作为命令执行,这是名称为“ <”或“>”之后的下一个字符。具体来说,将弹出堆栈中的前两项。如果弹出的第一项是<(分别是>)第二个弹出的项,则执行指示的宏。下一个字符(在'<'或'>'之后)是一个空格,因此,如果条件成立,我们存储在名称为空格char的寄存器中的宏就是要执行的宏。但是我们将0和1压入堆栈,所以弹出的第一项是1,弹出的第二项是0。结果,仅当条件测试为>而不是<时,才执行宏。这使我们可以区分输入中的“ <”和“>”。
该行中的其余项目只是数字,而dc只会将这些数字依次推入堆栈。
这是详细说明。大多数情况下,计数变量(问题语句伪代码中的i)存储在堆栈的顶部。
1sb Store 1 in register b. (b will end up being 1 for '<', and -1 for '>').
[_1sb]s Note that there is a space after the second s. So the space char is the name of a macro which stores -1 in b.
z Push 0 on the stack.
z Push 1 on the stack.
? Accept input in the format above. This will:
- Store 1 or -1 in b, depending on whether you've typed "<" or ">"
- Push each of the three numbers in turn on the stack.
sd Save the increment in register d.
lb*sc Save either limit or -limit in register c, depending on whether the input started with "<" or ">".
[pld+lnx]sl Define a macro called l which is the body of our loop:
- Prints the top of the stack
- Adds the increment to the top of the stack.
- Calls macro n (the loop test).
[dlb*lcr<l]dsn Define a macro called n which is the test of the loop:
It checks to see if i (at the top of the stack) times b is less than c; if so, it calls macro l (looping back).
x Execute the loop test macro initially (a while loop needs to have a test at the top before entering the loop the first time).
另一方面,《任择议定书》指出:
Input can be in one-line using any format "a/b/c/d" or "a,b,c,d" etc.
因此,在输入中的a之前切换顺序并要求b是不合法的。
这是一种将a,b,c和d保持原始顺序的替代方法。我们可以使用任何定界符;我将使用zz作为分隔符。因此,从1到(但不包括)10以3的步长计数将输入为:
1zz<zz10zz3
具有zz分隔输入的新程序是
直流电(48字节):
1sb[_1sb]sz?sdiilb*sci[pld+lnx]sl[dlb*lcr<l]dsnx
这比47字节的第一个解决方案长一个字节。
在线尝试zz分隔版本!
我个人认为,不同顺序的< 1 10 3
格式1zz<zz10zz3
更符合问题的实质,但也许可以更好地满足实际的技术规范。
如果在不同的输入参数之间允许使用不同的分隔符,则可能会得到更短的解决方案,但是我认为这并不是问题的实质。
Bash + Unix实用程序,29字节
您可以将上面的基本思想变成一个bash程序(称为dc)。这避免了使用“ <”和“>”带来的所有麻烦,并且还简化了各种数字参数的处理,因此它只有29个字节长,与@zeppelin的bash + bc答案相同。
bash版本(29字节):
dc -e[p$4+d$3r$2l]sl$1d$3r$2l
在线尝试bash版本!
这是bash程序中dc程序工作方式的描述:
i的值大多数时候都存储在堆栈的顶部。
[ Start of macro (i is at the top of the stack). This macro will be called l.
p Print i
$4+ i += (4th argument)
d Duplicate i at the top of the stack.
$3 Push the 3rd argument onto the stack.
r Swap the top two items on the stack, so i is at the top and arg3 is second
$2l $2 is "<" or ">", causing the top two items to be popped from the stack, and macro l is then called (effectively looping back) if i < arg3 or i > arg3, respectively.
]sl End of macro definition; store macro in register l.
$1 Push argument 1 onto the stack (i = 1st argument).
d$3r$2l Just as above, call macro l if i < arg3, or i > arg3, depending on whether arg2 is "<" or ">"