我什至没有……我只是奇怪!


36

您的任务很简单:编写一个程序,接收一个整数作为输入,如果它是奇数,则将其输出,否则不做任何事情(不允许暂停)。挑战在于,您只能使用奇数字节。

您可以选择在输出末尾附加换行符。

这是代码高尔夫,最短的答案(奇数个字节)获胜。

禁止出现标准漏洞。此外,您不能使用比发布此挑战更新的语言版本。

输入>输出示例:

13 > 13

42 >


10
我否决了这个挑战,因为它是“不做Y的X”挑战。
Leaky Nun

4
到底是什么does nothing otherwise意思?在Haskell中,类型Int -> Int 为type的函数要么返回整数,要么不暂停或引发某些错误。如果输入均匀,则显然不应该返回该输入,那么在这种情况下停止或抛出错误是否可以接受?
Laikoni'7

2
如果您想知道是否可以使用源代码,请在浏览器控制台中尝试这些脚本。创建有效的字符集:alphabet=new Set(Array(256).fill(0).map((v,i)=>i).filter(v=>v%2).map(String.fromCharCode));。检查来源是否有效:[..."SOURCE CODE"].every(v=>alphabet.has(v))。请参阅源中的无效字符:[...new Set("SOURCE CODE")].filter(v=>!alphabet.has(v))。请记住不要使用引号,"=> \";)
kamoroso94

14
@LeakyNun“做X而不做Y”不是指一般的受限源挑战,而是指禁止您使用某种语言功能的挑战。这个挑战不是那样,它也没有任何问题使实际的“做X不做Y”挑战成为问题。
Martin Ender

1
@Laikoni因为已经有一些答案陷入无限循环,所以我可以说表现出这种行为是可以的。不返回可以解释为无所事事。
M.Herzkamp '17年

Answers:



67

语言645529908926937253684695788965635909332404360034079 9394157991500940492270727190763049448735 1174269748937617561533841898064735499551 2293382937520069758100171520285996319字节

大约等于2个十二亿字节。

该文件转换为以下brainfuck程序:

,[<<+>+>-]<[>>+<<-]+>>[-[->]<]<[<[<]>.<]

将输入作为ASCII码输入,最大值为256。使用换行。


@Okx我的错。但是,为什么不只使用,[<<+>+>-]<[>>+<<-]+>>[-[->]<]<[<[<]>.<]呢?
user202729

1
如何,[[>]++[-<]<+>>]>[<<<.<]只3452857532394791089951字节?
乔·金

实际上,由于允许无限循环,所以也可以,-[-->++<]>+.工作
Jo King

20

x86-64机器代码,8个字节

Bruce Forte解决方案的启发,但略低于标准杆。:-)

8D 07          lea      eax, [rdi]    ; put copy of input parameter in EAX
D1 EF          shr      edi, 1        ; shift LSB into CF
             InfiniteLoop:
F3 73 FD       rep jnc  InfiniteLoop  ; test CF; infinite loop back here if input was even
C3             ret                    ; return with original input in EAX if it was odd

EDI遵循系统V AMD64调用约定,在寄存器中采用单个整数参数。

最初将复制此值并将其放入,EAX以便在适当时可以将其返回。(因为我们需要一条奇数字节的指令,所以LEA使用它来代替普通MOV指令。)

然后,in的值EDI右移1,这会将移出的位放入进位标志(CF)。如果数字为偶数,则该位为0;如果为奇数,则为1。

然后,我们使用JNC指令测试CF,该指令仅在CF为0(即数字为偶数)时才跳转。这意味着我们将陷入偶数值的无限循环。对于奇数值,我们会掉线并EAX返回原始值(in )。

JNC但是,该指令有一个技巧—它有一个REP前缀!通常,REP前缀仅与字符串指令一起使用,但是由于Intel和AMD手册都同意REP忽略无关的/多余的/冗余的前缀,因此我们在此处的分支指令上添加一个前缀以使其长度为3个字节。这样,在跳转指令中编码的相对偏移量也是奇数。(当然,REP它本身也是一个奇数字节的前缀。)

谢天谢地,RET它使用奇数字节编码!

在线尝试!


如果您认为返回的值不为奇数而返回一个无限循环(以至于您永不返回)满足挑战的“输出”要求,或者您只是想得到更有趣的东西,则可以使用以下函数将值输出到串行端口(当然,只有在奇数的情况下)。

x86-64机器代码(输出到串行端口),17个字节

8D 07         lea   eax, [rdi]   ; put copy of input parameter (EDI) in EAX

B1 F7         mov   cl, 0xf7     ; put 0xF7 into low-order bits of CX
B5 03         mov   ch, 0x03     ; put 0x03 into high-order bits of CX
FE C1         inc   cl           ; increment low-order bits of CX to 0xF8 (so all together it's now 0x3F8)
0F B7 D1      movzx edx, cx      ; move CX to DX ("MOV DX, CX" would have a 16-bit prefix of 0x66)

D1 EF         shr   edi, 1       ; shift LSB of input parameter into CF
73 01         jnc   IsEven       ; test CF: branch if 0 (even), fall through if 1 (odd)
EF            out   dx, eax      ; output EAX (original input) to I/O port 0x3F8 (in DX)
            IsEven:
C3            ret                ; return

使代码更有趣的是,代码执行了更多操作,这意味着使用仅使用奇数字节编码的指令来完成所有操作更具挑战性。当然,这也意味着它在代码高尔夫上失败了,所以这是一种折衷—您是否想要有趣和具有挑战性,还是想做空?

无论如何,这使用x86 OUT指令写入I / O端口0x3F8,这是PC上的标准COM1串行端口。当然,有趣的部分是所有标准I / O端口(串行和并行)都具有偶数地址,因此不能简单地将它们编码为OUT指令的立即数或直接移入寄存器。您必须使用小于实际值的值进行初始化,然后递增寄存器中的值。您还限于使用某些寄存器进行操作,因为当用作操作数时,需要在指令中使用奇数字节编码的寄存器。

另外,我必须在循环的顶部初始化DX寄存器(通过CX寄存器),即使仅在值是奇数时才需要这样做,以确保JNC指令具有奇数偏移量。但是,由于我们要跳过的是OUT指令,因此这些代码所做的只是浪费周期和破坏暂存器。它实际上不会输出任何内容,因此不会违反规则。

最后,此函数将返回(将输出完成或未完成输出到串行端口之后),输入值保留在中EAX。但这实际上并没有违反任何规则。所有用汇编语言功能将与价值回报EAX-the问题就是它是一个显著值或垃圾值。这是由函数的文档确定的(本质上,它是返回值还是返回void),在这种情况下,我正在将其记录为未返回值。:-)

没有TIO链接,因为它没有实现到串行端口的输出。您将需要真正的铁力或想象力。


+1解释!为什么在第二行而不是第一行使用mov?
M.Herzkamp '17年

除了对这MOV条指令进行编码外,其操作数还必须在字节中进行编码。在这种情况下,它将是源寄存器和目标寄存器(尽管操作数也可以是立即数,就像常量一样)。不同的寄存器映射到不同的字节,其中一些字节是偶数。因此,例如,我要使用的是mov eax, edi,但是89 F8以字节为单位。见比你曾经想知道的编码在这里,“代码”部分下。@ M.Herzkamp
Cody Gray


9

05AB1E,3 个字节

Éi=

该代码对应于字节值C9,69,3D201,105,61全为奇数。

在线尝试!

说明

É     # input % 2 == 1
 i    # if true
  =   # print without popping

= # print without newline实际上是用换行符打印而不会弹出的
Erik the Outgolfer

@EriktheOutgolfer:是的。我会解决的原因。
Emigna '17

不幸的是,É×似乎没有用):
kalsowerus

@kalsowerus:是的,我也注意到了。D前面可以正常使用,但是长度均匀且较短。它不起作用的原因是重复的隐式输入被当作第二个参数。
Emigna

@Emigna但很奇怪的是,两次交换堆栈中的前两个值,使其也能正常工作……
kalsowerus

5

MATL,3个字节

o?G

MATL使用ASCII字符,所以o?G对应于字节(十进制)1116371

在线尝试!

说明

o     % Push (implicit) input modulo 2
?     % If nonzero
  G   %   Push input
      % End (implicit)
      % Display stack contents (implicit)

5

Haskell36 33字节

c[1]=1;c[m]=1+1+c[m-1-1];o	m=c[m]

在线尝试!

用法:o 7yiedls 7o 8进入无限循环。

实际的算法是

o 1 = 1
o m = 2 + o(m-2)

我面临的第一个问题是空间不足(,因为带有o参数的函数m通常定义为o m=...or o(m)=...。但是我发现内联注释也{- some comment -}可以用作标记定界符,因此o{--}m=...在给定规则下可以进行定义。编辑:ØrjanJohansen指出,可以使用制表符而不是空格,节省三个字节: o m=...

第二个问题是递归调用o(m-2)-2只是-1-1,但是这里的注释技巧无效,因为需要括号。我通过让功能工作单列表中包含了一些固定的:o[m-2]不过,因为这是不提供输入的一种标准的方式,我外包计算的辅助函数c,其在列表和调用工作co具有正确的格式。


您可以使用制表符代替空格。
与Orjan约翰森

我可以验证@ØrjanJohansen \t而不是{--}
硕果累累

@ØrjanJohansen谢谢,很高兴知道。
Laikoni'7

5

Python REPL,38个字节

使用将输入作为上一个表达式的值_。输出将是一个字符串(整数的字符串表示形式为奇数,或空字符串表示为偶数)。

'%s'%[['']+[_]][-1][[_%[1+1][-1]][-1]]

在线尝试

要在实际的shell中运行它,可以在此处尝试。输入输入,然后按Enter。粘贴代码,然后按Enter。

说明:

这花了一段时间才弄清楚。没有乘法,没有分支,没有切片,没有逗号,没有句点,没有导入,没有括号,no exec,no eval,no print和函数。我得到了一个使用stderr进行输出的解决方案,但是后来我意识到我们必须输出实际的整数,而不仅仅是真/假值。

我使用方括号代替括号[expression][-1]。通过简化,可以将上述代码转换为'%s'%(['']+[_])[_%(1+1)]

由于不能有逗号,因此我使用列表添加来创建['',_]。使用字符串格式,可以获得所需的结果。


荣誉 另外,它也适用于Ruby IRB :) Nitpick:可以为奇数返回字符串,可以为偶数返回空字符串吗?
艾里克·杜米尼尔

我认为什么都不做,打印或不返回任何东西都是相同的。从某种意义上说,空字符串什么都不是。
mbomb007'7

是的,我真的很挑剔。它仍然返回一个字符串而不是什么。在Python REPL中,我说那None会比更好''。无论如何,那仍然比我想出的任何东西都要好10000倍。
艾里克·杜米尼尔

@EricDuminil我可以回来FalseNone不过,您知道如何获得。
mbomb007'7

4

CJam,6个字节

q_iY%%

113 95 105 89 37 37

该程序采用输入的mod 2(称为r),并在输入字符串中打印第r个字符。如果输入数字为奇数,它将打印整个字符串,但是如果要求打印每第0个字符,则程序将引发错误。

在这里尝试


真好!我打算发帖qi_Y%]W%{}/M?,然后看到了。
硕果累累

4

Cubix23 19 17字节

;;u!I1)%/;O=!;;/;

试试吧!

@终止Cubix程序的是ascii 64,因此不幸的是,这实际上只是在测试了奇数之后才进入无限循环。没有TIO链接,因为它会超时。

= (ascii 61)在Cubix中为空操作。

这是对以前适用于负整数的算法(相同的字节数)的略微修改。

多维数据集版本:

    ; ;
    u !
I 1 ) % / ; O =
! ; ; / ; . . .
    . .
    . .

算法:

  • I (73) :以数字形式读入输入
  • 1 (49) :推1
  • ) (41) : 增量
  • % (37) :拿国防部
  • / (47) : 转左
  • ! (33) :如果奇数,则跳过下一条指令
    • 1;;/; ;(59):准备输出堆栈
    • O (79) :输出为数字。
    • 然后它重新输入算法,但是I读取0输入的结尾,因此我们保证进入偶数分支
  • u (117) :右转弯
  • ;;;!I :循环,实际上什么也没做。

@MickyT对于负输入失败,这就是为什么我避免使用?
Giuseppe

抱歉,我没有正确检查
-MickyT

3

木炭,9字节

¿﹪Iθ÷χ⁵→θ

在线尝试!

基本上,如果不是10/5的倍数,它会向右打印输入(²字符在“木炭代码”页中甚至是char )。使用的字符是:

  • ¿:代码BF
  • :代码A5
  • :代码C9
  • θ:代码F1
  • ÷:代码AF
  • χ:代码E3
  • :代码B5
  • :代码13

实际上,近端是多余的,但后来我看到答案的长度必须是奇数...

说明:

¿      if (
 ﹪      Modulo (
  Iθ      the input as number,
  ÷χ⁵      χ (predefined value: 10) divided by 5 = 2 ) [is 1])
 →θ      then print rightwards the input as string

您正在打印,然后向右移动;向右打印实际上是→θ
尼尔

@Neil糟糕,已修复。至少那并没有使我的答案无效... :-D
查理(Charlie)

3

x86_64机器码(Linux),12 11个字节

不幸的0x80是,它是偶数的,但仍然可行(假设“什么都不做”意味着不返回):

0000000000000000 <odd>:
   0:   8d 07                   lea  (%rdi), %eax
   2:   83 e7 01                and    $0x1, %edi
   5:   83 ff 01                cmp    $0x1, %edi
   8:   75 fb                   jne       5  <odd+0x5>
   a:   c3                      retq

-1个字节,谢谢@CodyGray!

在线尝试!


1
由于这是x86-64,因此当源是32位寄存器时,lea (%edi),%eax需要一个地址大小覆盖前缀(0x67)。您可以这样做消除这种情况lea (%rdi),%eax。这样可以节省一个字节,并且实际上会使代码效率更高(前缀会减慢解码速度并填充i缓存)。您还可以做一些其他事情来缩短这个时间,但这实际上构成了一个完整的重写,所以我将发布自己的答案。:-)当然,我也对此表示赞同!(哦,刚刚意识到您可能已经使用前缀使跳转偏移量为奇数了。嗯,您将需要更多魔术。)
Cody Gray

此外,TIO的解决方案非常聪明!我在大多数asm答案中都跳过了它,因为我不想在“页脚”中编写所有样板文件以在asm中打印输出。我终于崩溃了,有一天做到了,但是这是一个很大更好的主意,让您使用下一切。从现在开始,我会偷这个东西!:-)
Cody Gray

为您的意见打气,我在组装时是个菜鸟,但这似乎很简单!对您的解决方案感到好奇。哦,归功于@ceilingcat -我偷了它自己;)
ბიმო

我实际上并没有为您节省一个字节…… F6JNE指令现在具有偶数字节(),因为它具有偶数偏移量。这就是我在第一个注释中编辑的最后一个括号的意思。实际上,您需要该前缀来创建奇数对齐。或者,您必须以其他方式重写代码。我玩了一堆不同的变奏曲。我实际上是昨晚看的,并试图找出一种OUT用于输出奇数值的好方法,但是我没有真正找到好的解决方案。对我而言,这里的见解是为偶数值进入无限循环。
科迪·格雷

实际上,这是一个非常愚蠢的挑战,因为没有一种合理的解决方案可以起作用。它实际上只是测试您对x86指令集的晦涩之处的了解程度。我什至尝试了BT没有人使用过的指令系列(不幸的是,所有寄存器编码都是字节)。我认为写输出到串行端口的代码可能会更有趣,而不是仅仅返回一个值或其他值,但这确实会增加字节数(特别是因为十六进制的串行端口地址是偶数!),所以我放弃了。
科迪·格雷

3

Mathematica,20个字节

似乎是非高尔夫语言中的第一个解决方案。

a=1+1;g[i_/;!a\[Divides]i]=i

MacintoshChineseTraditional字符编码中。\[Divides]{161, 253}(2个字节)

备用版本(23字节)

\[CapitalAlpha]=1+1;\[CapitalGamma][\[CapitalChi]_/;\[CapitalAlpha]\[LeftFloor]\[CapitalChi]/\[CapitalAlpha]\[RightFloor]\[NotEqual]\[CapitalChi]]=\[CapitalChi]

或(以Unicode显示)

Α=1+1;Γ[Χ_/;Α⌊Χ/Α⌋≠Χ]=Χ

Symbol字符编码中。(仅使用1个字节的字符)

该解决方案定义了一个函数g(或Γ),当输入为奇数时对输入求值,而在输入为偶数时按字面意思“不执行任何操作”(不求值)。


;如果字节数必须为偶数,则为+1字节(末尾);否则为0。并且\[Divides]还有奇数的Unicode代码点。
user202729

您不需要I[1+1],您可以使用{1+1}。另外,您是否检查了地板托架的字节是否有效?如果是这样,您可以2从获得\[LeftFloor]E\[RightFloor]
Martin Ender

@MartinEnder只有Symbol使地有效,但它既没有E,也没有\[ExponentialE]
user202729

恐怕不允许您使用这些字符D; v; 也没有d,因为它们具有偶数字节值。.
::

1
@KevinCruijssen \[Divides]是Mathematica中的单个字符,由2个字节表示{161, 253}
user202729

3

Perl,54个字节

需要-E

我真的很喜欢这个挑战,我想我想尝试并改善这个答案,但是我认为这可能是我目前能做的最短的。我一直在反复使用这些答案几天,但是我对54字节的解决方案感到满意!

s//A_=Y[;A_=A_%O?A_W''/;y/#A-_/#-A/;s/[#-}]+/uc/ee;say

在线尝试!

说明

默认情况下,大多数Perl的字符串函数都在上运行$_,该字符串以空开头。

首先,s//A_=Y[;A_=A_%O?A_W''/代替在空字符串$_A_=Y[;A_=A_%O?A_W'',然后y/#A-_/#-A/替换根据以下列表上(以上炭变得低于字符)字符:

#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
#$%&'()*+,-./0123456789:;<=>?@A

更新$_包含$_=<>;$_=$_%2?$_:''。Next s/[#-}]+/uc/ee将所有字符替换[#-}]+uc。如果没有/eethis,那么它将只是字符串uc,但是会/ee两次评估字符串的内容。第一个计算结果返回的结果uc,是的大写版本,$_但由于不$_包含字母字符,因此仅返回整个字符串,然后第二个/e计算再次计算该字符串,该字符串设置$_$_(输入数字)还是''取决于还是不是数字是奇数还是偶数。

最后,由于$_现在包含了我们想要的内容,因此我们调用say(这是需要的,-E而不是-e),它先打印$_换行符。


备用Perl,93个字节

92字节代码+ 1 for -p,我认为这将使其不竞争。

s//_/g;s//uc/e;y/\x09-\x0b/_/;s/____/}[/;s/___/%C]/;s/_/{''H/;y/'{}1CDGH/'-)1-3+--/;s/[#-}]+/uc/ee

在中包含一个标签和一个垂直标签y///,分别以\x09和表示\x0b

在线尝试!


2

LOGO390 46 52 50字节

[ask    1   se[make]iseq    1-3 cos ?/ask   1[1/sum 1   179]?]

这是一个模板列表,如果输入为奇数,则返回输入,如果输入为偶数,则导致错误。

用法:

show invoke [ask ... (paste code here) ... ] 5

输出

5

因为5是奇数,并且

invoke [ask ... (paste code here) ... ] 6

将导致错误,因为6是偶数。



2

TI-BASIC,14个字节

Input Q
sinֿ¹(gcd(Q²,int(e
Q

这会在偶数上引发域错误(不向主屏幕打印任何内容)。

Input Q             Q is a variable with an odd code. We cannot use "Ans" as it's even.

            int(e   floor(e) = 2; "2" is even.
         Q²         Q may be negative, so we square it which preserves parity.
     gcd(Q²,int(e   1 if Q is odd; 2 if Q is even.
sinֿ¹(gcd(Q²,int(e   Error iff Q is even.

Q                   If there was no error, print Q.

1

Pyth14 11 10 9字节

I + Q_ + K / Q + 3_1KQ 
I!sIcQ + 3_1Q 
I!u + 1_GQ1Q
uu + 1_GQ1k

测试套件


那是一个聪明的方法,但是像这样的东西不应该I%Qy1Q工作吗?
雅库布

@Jakube我显然没有弄清楚y1...但是%,可惜,这是不允许的。
Leaky Nun

为什么不?%具有ascii值37,且为奇数。
雅库布

3
@Jakube,因为显然我信任此列表中提供的操作程序(这是错误的)
Leaky Nun

1

Japt,4个字节

u)çU

Japt使用ISO / IEC 8859-1,因此对应于(十进制)117 41 231 85

在线测试!

说明

Uu)çU   Implicit: U = input integer
Uu)     Return Python-style U % (missing argument = 2). This gives 1 if U is odd, 0 if even.
   çU   Implicitly convert U to a string and repeat it that many times.
        Implicit: output result of last expression

我首先尝试了使用的解决方案p,该解决方案基本上ç带有相反的参数。但是,p如果左参数为数字,则执行幂运算,因此我们需要将其显式转换为字符串。事实证明,该解决方案除了不包含任何奇数字节之外,实际上要短一个字节。


1

dc,21字节

[c]sa?kKKCI-1;1k%1!=a

小数: 91 99 93 115 97 63 107 75 75 67 73 45 49 59 49 107 37 49 33 61 97

按照 IO默认值,如果输入为奇数,则此程序将输入保留在主堆栈上,否则清空堆栈。可以通过f在程序末尾添加debug命令来确认,就像在TIO页面上一样。

在线尝试!

说明

[    # Begin macro definition.
 c   # Clear the main stack.
]sa  # End macro definition and push the macro into register "a".
?k   # Prompt for input and store it into precision parameter "k".
KK   # Push two copies of the input to the main stack.
CI-  # Push C-I = 12-10 = 2 to the main stack  
1;1  # Push the value stored in the first index of array "1" (0 by default) 
     # to the main stack. 
k    # Push 0 into parameter "k" to reset the precision (otherwise the modulus 
     # function will not work correctly).
%    # Push the input (mod 2) to the main stack.
1!=a # If the input (mod 2) does not equal 1, execute the macro in register "a".
f    # OPTIONAL: Output the contents of the main stack.

1

TI基本(18字节)

感谢lirtosiast,节省了2个字节

:Prompt Q
:While 5Q/ᴇ1-int(5Q/ᴇ1
:Q

以字节为单位(+2个换行符= 3F)

:Prompt Q
 DD     51
:While 5Q/ᴇ1-int(5Q/ᴇ1
 D1    35 3B B1  35 3B  
        51 31     51 31
         83 71     83
:Q
 51

参见http://tibasicdev.wikidot.com/one-byte-tokens


1
为什么不使用fPart(?
lirtosiast

根据@lirtosiast似乎是一个偶数字节(BA = 186)tibasicdev.wikidot.com/one-byte-tokens
冲电气

哦,我误读了哪些条目是行,哪些条目是列。
lirtosiast

1
我找到了Input Q[newline]sinֿ¹(gcd(Q²,int(e[newline]Q(14个字节)。我可以单独回答吗?
lirtosiast

@lirtosiast哇!对于单独的答案,绝对足够不同。喜欢它
冲木


0

Bash,31个字节

read a
[ $[a%2] = 0 ] ||echo $a

在线尝试!

说明:

read a                   reading the input and define it on the variable a
[ $[a%2] = 0 ]      outputs exit status 0 when a/2 is 0 and exit status 1 if not.
||                           evaluates only when the exit status left of it is 1
echo $a                displays the variable a

您似乎错过了这是一个受限的源挑战-您正在使用禁止的字节。(rd $20|h和换行。)
与Orjan约翰森

@ØrjanJohansen已修正,我猜是
ADDB

2
不。程序的长度没有限制,但是其中的每个字符都必须具有奇数字节值。
与Orjan约翰森
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.