我反转了源代码,您否定了输入!


36

公然敲竹杠一个的敲竹杠。去投票那些!

您的任务(如果希望接受)是编写一个程序/函数,该程序输出/返回其整数输入/参数。棘手的部分是,如果我反转源代码,则输出必须是取反的原始整数。

例子

假设您的源代码为ABC,其输入为4。如果我CBA改为编写并运行它,则输出必须为-4

假设您的源代码为ABC,其输入为-2。如果我CBA改为编写并运行它,则输出必须为2

输入的0可能为0-0,但是,如果您确实支持带符号的零,-0则应为0


5
为什么我们需要相同问题的副本?
基督徒

5
@Christian一个人输出一个常数(及其取反),而这个人必须接受输入并返回/取反它。用多种语言进行的工作非常不同。
亚当

5
是的,现在我看到了区别。人们需要非常仔细地阅读
Christian

如果使用C#这样的结构化语言,您只是在换行吗?
PerpetualJ

@PerpetualJ不,请像字符列表一样查看源代码,其中有些是换行符。
亚当

Answers:





11

x86机器码,3个字节

C3 D8 F7

上面的代码字节定义了一个无操作的函数:它只是将控制权返回给调用者。该函数后跟两个将不执行的垃圾字节,因为它们是在返回之后出现的,它们位于“无人区”。在汇编助记符中:

ret                     ; C3    
fdiv  st(0), st(7)      ; D8 F7

好的,现在有一些巨魔来了,并反转了字节的顺序:

F7 D8 C3

现在,这些字节定义了一个函数,该函数在EAX寄存器中使用一个整数参数,将其取反,然后将控制权返回给调用方。在汇编助记符中:

neg  eax     ; F7 D8
ret          ; C3

所以...很简单。:-)

注意,我们可以使“取反”指令成为我们想要的任何东西,因为它永远不会以“正向”方向执行,而只会以“反向”方向执行。因此,我们可以遵循相同的模式来任意处理更复杂的东西。例如,这里我们在另一个寄存器中采用一个整数参数(例如,EDI遵循* nix系统上常用的System V调用约定),将其取反,然后在常规EAX寄存器中返回它:

C3      ret
D8 F7   fdiv  st(0), st(7)      ;  \ garbage bytes that
F8      clc                     ;  | never get executed,
89      .byte 0x89              ;  / so nobody cares

  ↓↓

89 F8   mov  eax, edi
F7 D8   neg  eax
C3      ret



6

空格,48个字节

S S S N
S N
S T N
T   T   T   T   T   T   N
S T N
N
N
T   S N
T   N
S S T   N
T   T   S S T   T   T   T   T   N
T   S N
S N
S S S 

字母S(空格),T(制表符)和N(换行符)仅作为突出显示而添加。

我的空白答案进行细微修改,以便我反转源代码,您否定输出!挑战

在线尝试在线尝试反向(仅使用空格,制表符和换行符)。

说明:

利用内置的退出程序是一个短回文NNN
常规程序将:

SSSN   # Push 0 to the stack
SNS    # Duplicate it
TNTT   # Read STDIN as integer, and store it at heap address 0
TTT    # Retrieve the input from heap address 0, and push it to the stack
TNST   # Pop and print the top of the stack as number
NNN    # Exit the program, making everything after it no-ops

反向程序将:

SSSN   # Push 0 to the stack
SNS    # Duplicate it
TNTT   # Read STDIN as integer, and store it at heap address 0
TTT    # Retrieve the input from heap address 0, and push it to the stack
SSTTN  # Push -1 to the stack
TSSN   # Multiply the top two values on the stack together
TNST   # Pop and print the top of the stack as number
NNN    # Exit the program, making everything after it no-ops

小推数字的其他说明:

  • 首先S:启用堆栈操作
  • 第二S:将数字推入堆栈
  • ST:分别为正/负
  • 一些S/ T后跟一个N:二进制数字,其中S=0T=1

SSTTSTSN-10。对于0我们,我们不需要显式的S=0,因此简单SSSNSSTN足够。




5

Brain-Flak,7个字节

#)]}{[(

在线尝试!

反转:

([{}])#

在线尝试!

注意:仅在支持注释的解释器中有效(例如,在Rain-Flak中有效,但在BrainHack中不适用)


如果我们也交换开/关括号而不仅仅是反转字节,那么我们可以在8个字节中完成此操作而无需使用注释:

({}[{}])

在线尝试!
尝试反向!


这是不确定的行为滥用吗?我认为Brain-Flak规范不允许这样的括号。
高度放射性的

@TwilightSparkle The #开始注释,因此原始版本中的括号将被忽略。
莱利

哦,是的,我忘了!但这仅适用于Rain-Flak(不过是官方解释器)。您可能需要提一下?
高度放射性的

@TwilightSparkle添加了注释以进行澄清。谢谢。
莱利

有趣的小挑战:如果您也交换开/关括号而不是仅仅反转,是否可以不加注释地执行此操作?
DJMcMayhem




4

R,23个字节

我决定不加评论就放弃。

向前

`+`=scan;""+-0;nacs=`+`

在线尝试!

相反

`+`=scan;0-+"";nacs=`+`

在线尝试!

在向前版本+中,代理是二进制运算符,并且-是一元运算符。

相反,+变成一元,而变成-二进制。因此,scan函数采用以下参数:file=""这意味着stdin和what=0,它们也是默认值。所以当+参数为一元时,第一个参数在右边,当参数为二元时,第一个参数在左边。

;nacs=`+`

代码的一部分并没有真正有用的功能,因此从某种意义上说,我的代码并没有比使用注释技巧更有效。


1
这非常聪明(+1)。我们经常将R运算符重新定义为golf字节,但是我认为这是我第一次看到+将其重新定义为一元和二进制形式。我花了一分钟的时间来理解它是如何解析的……没有其他操作员姓名可以完成这项工作。
罗宾·赖德


4

Perl 5(-p),7 6字节

-1感谢@primo

$_*=$#

蒂奥

评论不会改变输入

#1-=*_$

取反输入

$_*=-1#

蒂奥


-1:$_*=$# TIO。请注意#必须是程序的最后一个字节,否则它将被解释为变量$#,而不是名称为<empty>的数组的最后一个索引。
普里莫

1
但是我不明白它是如何工作的,因为尝试打印$#会给出错误(如果#不是最后一个字符)或什么都不显示
Nahuel Fouilleul

似乎只能使用-p-n。我怀疑样板与它有关…
primo

2
@primo它起作用,因为在代码后-p/-n添加了一个;。这$#实际上意味着$#;:数组的大小@;。如果@;更改大小,则结果不再正确(TIO)。无论如何,这非常聪明,做得好!:)
达达

可以用来解释perl -MO=Deparse -p <(echo -n '$_*=$#'),因为它似乎perl -MO=Deparse -pe '$_*=$#'增加了换行符
Nahuel Fouilleul

4

盖亚 2字节

_@

在线尝试!

_	| implicit push input and negate
 @	| push next input OR push last input (when all inputs have been pushed)
	| implicit print TOS

反转:

@	| push input
 _	| negate
	| implicit print TOS

4

反手6 5个字节

I@-Ov

在线尝试! 尝试加倍!

由于“反手”中指针的性质,使其有点复杂。我认为不可能再缩短哈哈了,事实证明我错了。这不会重复任何指令,并且会在两个程序之间重用输入,输出和终止命令。现在,我认为这是最佳选择,因为您需要所有IO-@命令才能工作,并且在4字节程序中,您只能执行其中两个命令。

说明:

反手中的指针在三个单元格处移动一个刻度,并从该单元格的边界反弹,这意味着常规逻辑是重叠的。但是,您可以使用v^命令。

原始程序执行指令IO-@,即输入为数字,输出为数字,减去,终止。显然,减法是多余的。在代码中,这些是:

I@-Ov
^  ^    Reflect
  ^     Reflect again
 ^

反向程序执行v-I-vO-@。的v降低之间的蜱的指针的步骤,和-从堆栈的底部,这是隐式零中减去。额外的-命令什么都不做。程序执行像

vO-@I
v       Reduce pointer speed to 2
  -     Subtract zero from zero
    I   Get input as number and reflect off boundary
  -     Subtract input from zero
v       Reduce pointer speed to 1
 O      Output as number
  -     Subtract zero from zero
   @    Terminate







2

APL(Dyalog Unicode)13个 3字节

-∘0

在线尝试!

琐碎的答案。返回arg¯arg

不笨,节省了10个字节(感谢Adám)。

将生成的3-byter更改为更合适的功能。


哇,这可以用三个字节来完成!
亚当

有趣的是,您已经嵌入了一个3字节的答案作为其子字符串。
亚当

@Adám是的,我知道那里有一个简单的答案。谢谢。
J.Sallé

2

图灵机语言,39字节

积极的

1 r - _ 0
0 l * * 0
0 - _ l 0
0 _ _ r 0

负面的

0 r _ _ 0
0 l _ - 0
0 * * l 0
0 _ - r 1

这比我想象的要棘手,主要是因为我必须克服偏向于使代码运行“编译”错误的偏见。


2

> <>5 4字节

n-r0

使用带有-v选项的堆栈初始化,将输入变量放在此处。

在线尝试!

或尝试逆转

说明

n       Prints whatever is on the stack as a number
 -      Subtract the top 2 elements on the stack.
        There aren't 2 elements, so it crashes.
  r0    Never gets executed

or reversed:

0       Push a 0 onto the stack
 r      reverse the stack (now 0, -v)
  -     Subtract top 2 elements and push result (0-v, ie negated)
   n    Print as number
        The code wraps around and executes again. 
        It crashes on the - as there is only one
        item on the stack: 0.

2

堆猫 -mn,2个字节

-X

在线尝试!

尝试反向!

说明

事实证明,这实际上比Stack Cats中的上一个挑战要容易得多。完整的程序(申请后-m)是-X-X用于交换磁带头左右的堆栈,即它根本不影响初始堆栈,因此我们可以忽略它。但是然后程序实际上只是--(两次使栈顶取反),什么也不做。

对于逆向程序,应用-m给出X-X。再说一次,X什么也不做,所以程序实际上就是just -,它否定了栈的顶部。

唯一的其他2字节解决方案是-=,但实际上是相同的。唯一的区别是仅=交换相邻堆栈的顶部,而不交换整个堆栈。

但是再次,使用-m感觉有点像作弊,因此下面是使用完全镜像程序的解决方案。


叠猫 -n,7字节

:I<->I:

在线尝试!

尝试反向!

说明

先前答案的注意事项仍然适用:任何有效的解决方案都需要使用成对的字符和I。六个可能的解决方案(包含在TIO链接中)几乎都是相同的。-_在此程序中是等效的,:可以用|或代替T(对于非零输入,它们的作用相同,同时对于零输入也适用)。我刚刚选择这一个来解释,因为它是最简单的。

因此请记住,初始堆栈将输入保持在a的顶部-1(在无限多个零的顶部),而磁带上的所有其他堆栈仅保持零。Stack Cats还具有以下特性:任何偶数长度的程序都不会执行任何操作(前提是它终止了,但是无论如何我们都不能使用循环来进行此挑战)。那么对于任何奇数长度的程序,其中心字符什么都不做,显然也是如此……让我们来看一下:

:    Swap the input with the -1 below.
I    Move the -1 one stack to the left and turn it into +1.
<    Move another stack left (without taking the value).
-    Negate the zero on top of that stack (i.e. do nothing).

因此,程序的后半部分恰好撤消了前半部分,因此我们最终将输入重新放在了顶部-1

逆程序是:I>-<I:。让我们看看它如何改变事物:

:    Swap the input with the -1 below.
I    Move the -1 one stack to the left and turn it into +1.
>    Move one stack right, i.e. back onto the initial stack which still holds the input.
-    Negate the input.
<    Move back to the left where we've parked the 1.
I    Move that 1 back onto the initial stack and turn it back into a -1.
:    Swap the -1 below the negated input to act as an EOF marker.

2

批次,34个字节

@ECHO.%1 2>MER@
@REM>2 1%=-aa/TES@

回显(ECHO.)输入(%1)。从技术上讲,第一行的其余部分将重定向STDERR到名为的文件MER@,但这不会产生影响。
第二行被注释掉(REM...)。

倒转

@SET/aa-=%1 2>MER@
@REM>2 1%.OHCE@

使用set命令(SET /a)的算术模式从未定义的变量()中减去(-=)输入(%1),该变量a等于0 - input。同样,第一行的其余部分在技术上都重定向STDERR到名为的文件MER@,但这没有影响。
第二行被注释掉(REM...)。


这看起来很有趣。介意解释吗?
亚当

@Adám添加了一个解释,并且还意识到我有向后的程序。
Οurous

2

Brachylog,2个字节

&ṅ

Brachylog从左边隐式输入,从右边隐式输出。
&忽略左侧的任何内容,并将输入向右传递给函数。
将其每一面都限制为彼此取反的形式。

在线尝试


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.