确定您的语言版本


51

您面临的挑战是编写一个可以在您的语言的不同版本中使用的多语言。运行时,它将始终输出语言版本。

规则

  • 您的程序应至少在两种语言版本中运行。
  • 程序的输出应是版本号。无多余数据。
  • 您的程序可以使用任何您喜欢的方法来确定版本号。但是,输出必须遵循规则2。但是,如果您确定版本号,则输出只能是数字。
  • 您的程序仅需要输出语言的主要版本。例如,在FooBar 12.3.456789-beta中,您的程序仅需要输出12。
  • 如果您的语言在版本号之前或之后放置单词或符号,则无需输出这些单词或符号,只需输出编号。例如,在C89中,您的程序仅需要打印89,而在C ++ 0x中,您的程序仅需要打印0
  • 如果您选择打印全名或次要版本号,例如C89而不是C99,则只能打印名称。C89 build 32有效,而error in C89 build 32: foo bar无效。
  • 您的程序可能不使用内置的,宏的或自定义的编译器标志来确定语言版本。

计分

您的分数将是代码长度除以其工作版本的数量。分数最低者获胜,祝您好运!


4
什么是语言版本号?谁来决定?
小麦巫师

9
我认为版本数量成反线性不欢迎大量版本的答案。
user202729

6
@ user202729我同意。Versatile Integer Printer的得分很好(number of languages)^3 / (byte count)
Mego

6
语言的版本是什么?我们不是在这里将语言定义为其 解释器 / 编译器吗?可以说,有一个gcc版本存在一个错误,该错误使用某些C89代码生成了行为违反C89规范的可执行文件,并且已在下一版gcc上进行了修复。如果我们根据该错误行为编写一段代码来告诉您正在使用哪个gcc版本,那么这应该算是有效的解决方案吗?它针对不同版本的编译器,但不针对不同版本的语言
tsh

6
我不明白 首先,您说“您的程序的输出应仅是版本号。” 。然后,您说:“如果您选择打印全名或次要版本号,例如C89而不是C99,则只能打印名称。” 那么第一个规则实际上不是必要条件吗?
管道

Answers:


16

认真实际,3个字节,得分1.5

'1u

在线尝试:其实认真

说明:

'1u
'1   both versions: push "1"
  u  Actually: increment character to "2"; Seriously: NOP
     (both versions: implicit print)

u并且D仅在实际上(这是严重v2)中添加了具有字符串功能的功能。


3
实际上,README.md表示,实际上是“认真”的精神继承者。对我来说,听起来不只是一个版本更改。
亚当

7
@Adám如果查看存储库中的v1分支,则认真地驻留在分支中。在严重弃用之前,实际上已驻留在v2分支机构中。此外,1.xreleases中,认真使用的版本号,而实际上使用2.x(在PyPIPyPI上)。
Mego

115

Python 3.0和Python 2,得分6

(12个字节,2个版本)

print(3/2*2)

在线尝试:

依赖于Python 3+默认使用浮点除法的事实,与使用地板除法的Python 2不同。


@MaltySen Your program should work in at least two versions of your language.它可以在至少两个版本2.7和3.0中工作。我选择了to print the full name or minor version numbers
fireflame241

哦,我明白了,我的坏。
马蒂森(Maltysen)

4
我的天啊!可怜的python开发人员
Regis Portalez '17

4
@RegisPortalez from __future__ import division,问题就解决了:)
卢卡斯Rogalski

62

Java,189个字节,10个版本,得分= 18.9

支持的版本:1.01.11.21.31.41.51.61.71.89

(有关以前的分数,请查看历史记录!)

Object v(){int i=0;try{for(String[]s={"Locale","Map","Timer","Currency","UUID","Deque","Objects","Base64","zip.CRC32C"};;i++)Class.forName("java.util."+s[i]);}finally{return i<9?"1."+i:i;}}

在Java 8上
运行它在Java 9或更高版本上运行

不打高尔夫球

Object v(){
  int v=0;
  try {
    for(
      String[] s={
        "Locale",          // 1.1
        "Map",             // 1.2
        "Timer",           // 1.3
        "Currency",        // 1.4
        "UUID",            // 1.5
        "Deque",           // 1.6
        "Objects",         // 1.7
        "Base64",          // 1.8
        "zip.CRC32C"       // 9
      };;v++)
      Class.forName("java.util."+s[v]);
  } finally {
    // Swallowing ClassNotFoundException when the version is not the last one
    // Swallowing ArrayIndexOutOfBoundsException that occurs after reaching the last version.
    return v < 9 ? "1." + v : v; // Return either an int or a String
  }
}

请注意,需要对照Java 1.0和Java 1.3之间的任何版本检查代码部分return v<9?"1."+v:v;(以前是return(v<9?"1.":"")+v;)。我没有任何Java 1.3或更早版本的安装可用来实际测试此语法。

介绍

Java版本控制具有特殊的历史记录。历史上所有版本都1.x包含1.0。但是...从Java 9开始和JEP223,版本方案已从使用更改1.xx。这是内部已知的版本。因此,我们有了下表(将Javadoc和Wikipedia一起使用):

 java.version | Rel. name | Product name
   property   |           |
--------------+-----------+-----------------
          1.0 | JDK 1.0   | Java 1
          1.1 | JDK 1.1   |
          1.2 | J2SE 1.2  | Java 2
          1.3 | J2SE 1.3  |
          1.4 | J2SE 1.4  |
          1.5 | J2SE 5.0  | Java 5
          1.6 | Java SE 6 | Java 6
          1.7 | Java SE 7 | Java 7
          1.8 | Java SE 8 | Java 8
          9   | Java SE 9 | Java 9

该质询条目与上表中的version列匹配,这是system属性中包含的内容"java.version"

说明

目标是检查类从哪个版本开始存在,因为Java弃用了代码,但从不删除它。再次使用Java 1.0专门编写了代码,以便与所有版本兼容,因为JDK(主要是)源向前兼容

该实现尝试查找每个版本引入的最短的类名。但是,要获得字节,需要尝试选择一个通用子包。到目前为止,我发现最有效的软件包是java.util因为它包含几个跨所有Java版本分布的真正简称的类。

现在,为了找到实际的版本号,通过引入版本对类名进行排序。然后,我尝试依次实例化每个类,并增加数组索引。如果该类存在,则跳到下一个,否则让try-block 捕获异常。完成后,将抛出另一个异常,因为没有更多的类需要检查。

无论如何,线程都会使try-block带有异常。这个异常没有被捕获,而是简单地搁置感谢finally-块,这又覆盖上保持异常通过实际返回的值是"1."+v在那里v被之前使用的索引。碰巧我们使该索引与Java的次要版本号匹配。

高尔夫的重要部分是在java.util每个版本的包装(或任何儿童包装)中找到最短的新类别名称。这是我用来计算成本的表格。

Base cost: `java.util.` (10 chars)

 Version | Class name (cost in chars)     | Reduced name (cost in chars)
---------+--------------------------------+---------------------------
 9       | java.util.zip.CRC32C (20)      | zip.CRC32C (10)
 1.8     | java.util.Base64 (16)          | Base64 (6)
 1.7     | java.util.Objects (17)         | Objects (7)
 1.6     | java.util.Deque (15)           | Deque (5)
 1.5     | java.util.UUID (14)            | UUID (4)
 1.4     | java.util.Currency (18)        | Currency (8)
 1.3     | java.util.Timer (15)           | Timer (5)
 1.2     | java.util.Map (13)             | Map (3)
 1.1     | java.util.Locale (16)          | Locale (6)
 1.0     | <default>                      | <default>
---------+--------------------------------+---------------------------
Subtotal |                      144 chars |                  54 chars
    Base |                                |                  10 chars
   Total |                      144 chars |                  64 chars

学分

  • 感谢凯文·克鲁伊森(Kevin Cruijssen),节省了30个字节(尽管我在读他的评论之前就已经这样做了,但我保证!)
  • 多亏了尼尔,所以又节省了26个字节(不,我没有考虑这样做)
  • 多亏了12个Nevay和不错乱了-盒 -尝试-抓思想!
  • Neil再增加了11个字节,这是一个不错的可移植finally技巧。
  • 由于凯文Cruijssen 2个更多字节通过更换return(i<9?"1.":"")+i;return i<9?"1."+i:i;(这需要针对1.0或至多1.3进行验证,因为没有语法变化1.4之前发生)

与内置

如果允许内置函数:

String v(){return System.getProperty("java.version");}

13个版本(从1.0到12)为54个字节,因此得分为4.1538。


1
@KevinCruijssen我打开Javadoc和1。跑了短名称1类,但......我被扶了一下这个页面:docs.oracle.com/javase/8/docs/technotes/guides/lang/...
奥利维尔格雷戈尔

1
260个字节,或者可能还有1 个字节,不知道return"...所有版本tbh中是否都没有空间。)
Kevin Cruijssen

1
235个字节:String v(){return "1."+(e("time.Year")+e("nio.file.Path")+e("io.Console")+e("util.UUID")+e("text.Bidi")+e("util.Timer")+e("sql.Ref")+e("lang.Void"));}int e(String c){try{Class.forName("java."+c);return 1;}catch(Exception e){return 0;}}
尼尔(Neil)

3
216个字节:String v(){int i=0;try{for(String[]s={"lang.Void","sql.Ref","util.Timer","net.URI","util.UUID","net.IDN","nio.file.Path","time.Year","lang.Module"};;i++)Class.forName("java."+s[i]);}catch(Exception e){}return"1."+i;}
Nevay

1
噢,我确实想知道如何迭代数组并捕获异常,但是使用可以更好finally{return"1."+i;}
尼尔

22

Python,606字节/ 15个版本=得分40.4

-67字节(lol),这要归功于NoOneIsHere。

版本是0.9.1、2(.0),2.2、2.2.2、2.5.0、2.5.1、3(.0),3.1、3.1.3、3.2.1、3.3、3.4、3.5 aa和3.6 。

try:eval('1&2')
except:print('0.9.1');1/0
if`'\n'`<'\'\\n\'':print(2);1/0
try:from email import _Parser;print(2.2);1/0
except:0
try:eval('"go"in""')
except:print('2.2.2');1/0
try:int('2\x00',10);print(2.5);1/0
except:0
if pow(2,100)<1:print('2.5.1');1/0
if str(round(1,0))>'1':print(3);1/0
if format(complex(-0.0,2.0),'-')<'(-':print(3.1);1/0
if str(1.0/7)<repr(1.0/7):print('3.1.3');1/0
try:eval('u"abc"')
except:print('3.2.1');1/0
try:int(base=10);print(3.3);1/0
except:0
try:import enum
except:print('3.3.3');1/0
try:eval('[*[1]]')
except:print(3.4);1/0
try:eval('f""')
except:print(3.5);1/0
print(3.6)

所有这些都归功于Sp3000的惊人回答。尾随换行符是必需的。

Whee,打高尔夫球很有趣。这应该可以工作(是的,我安装了这些版本中的每个版本),但是我可能不小心弄断了某些东西。如果有人发现错误,请告诉我。



哦,难怪 我想知道为什么Sp3000在每个print通话中都加上括号...感谢您告诉我!
totallyhuman

2
您可以通过删除错误的具体类型来节省68个字节(将所有替换exceptexcept:)。
NoOneIsHere

如果您这样做x=<string inside eval>而不是仅仅手动逃避代码,这仍然会起作用吗?
蓝色

@NoOneIsHere首先,我认为您不能因为所有的原因1/0,但后来我意识到了。谢谢!
totallyhuman

21

C ++ 11/14/17,得分= 147/3 = 49

为了区分C ++ 11和C ++ 14/17,它使用C ++ 14 constconstexpr成员函数默认性的更改(此示例来自https://stackoverflow.com/questions/23980929/)在c14中引入的更改可能会破坏在c1中编写的程序)。为了区分C ++ 14和C ++ 17,它使用了C ++ 17禁用三字母组合的事实。

#include<iostream>
#define c constexpr int v
struct A{c(int){return 0;}c(float)const{return*"??="/10;}};int main(){const A a;std::cout<<11+a.v(0);}

取消高尔夫:

struct A {
    constexpr int v(int) { return 0; }
    constexpr int v(float) const {
        // with trigraphs, *"??=" == '#' == 35, v() returns 3
        // without trigraphs, *"??" == '?' == 63, v() returns 6
        return *("??=") / 10;
    }
};

int main() {
    const A a;
    std::cout << 11 + a.v(0);
}

(已使用Debian gcc 7.1.0进行了测试-std=c++{11,14,17}。)


1
很棒的第一答案!请注意,您可以在include语句中打入include和之间的空格<,例如#include<iostream>
MD XF

1
嗯...如果规则被修改为禁止使用标准库差异(在这种情况下间接使用__cplusplus宏)-则要区分C ++ 17和C ++ 14,我倾向于使用基于范围的更改用于语义。也许按照这样的方式创建最小的迭代器/前哨类,以boost::integer_iterator使将哨兵转换为迭代器具有“令人惊讶的”行为。
丹尼尔·谢普勒

4
return 0;是隐式的,main因此您可以在那里保存9个字节。同样根据wc -c您的解决方案,使用251个字节而不是252个字节(您的编辑器可能在末尾插入了换行符)。
nwp

1
使用缺少三字符组的方法将c ++ 17与c ++ 14分开可能会更短
Potato44

1
这行得通吗?return *=>return*
扎卡里

19

浏览器中的EcmaScript 3/5/2015/2016 / 2017,59字节/ 5个版本= 11.8点

alert(2017-2*![].map-2010*![].fill-![].includes-!"".padEnd)

NetScape 7报告3和Opera 12报告5

由于GOTO 0,节省了1个字节


1
忍者!;)
Shaggy

Netscape 7仅支持ES3?哇,它比我想像的还旧...
尼尔

1
您可以使用-!而不是+!!在有意义的位置保存一些字节(并相应地更改数字常量)。
GOTO

3
也许一些解释?:)
德里克·朕会功夫,

@Derek:请参阅我的解决方案(上面链接)以获取解释。
毛茸茸的

18

JavaScript(ES5&ES6),14个字节/ 2个版本= 7

alert(5^"0o3")

0o样式的八进制常量是ES6中的新增功能;ES5将字符串转换为NaN不影响按位XOR结果的字符串。


13

JavaScript(ES 2、3和5-8 9),59/6 = 9.833 75/7 = 10.714

即使分数确实比2版本的解决方案稍高,也可以提交具有更多版本的解决方案。

alert(9-(/./.dotAll!=0)-!"".padEnd-![].includes-![].keys-2*![].map-![].pop)

在线尝试

检查Array,RegExp和String原型中是否存在各种方法,将它们取反,给出一个布尔值,然后从初始值9中减去该布尔值。![].map帐户的乘法运算说明了ES4被放弃的事实。

  • ES2018(v9)中引入了正则表达式的dotAll属性(和相关s标志)。
  • padEnd字符串方法是在引入ES2017(V8)。
  • includes阵列的方法是在引入ES2016(V7)。
  • keys阵列的方法是在引入ES2015(V6)。
  • map阵列的方法是在引入ES5.1(V5)。
  • pop阵列的方法是在引入ES3(V3)。

ES 7或ES 8是有效的版本号吗?也许应该将其称为ES 201x?
tsh

1
@tsh:是的,他们仍然使用版本号;他们只用几年来表示真实名称
毛茸茸的


9

Befunge:15 11字节/ 2个版本= 5.5

@ Pietu1998删除了4个字节

"89",;5-;,@  

在线尝试:
Befunge 93
Befunge 98
使用Befunge 98专有的分号运算符(“跳至下一个分号”)来区分版本。两者都将打印“ 9”。Befunge 93将忽略分号,从“ 8”(堆栈顶部左侧的值)中减去5,打印结果“ 3”并终止。另一方面,Befunge 98将跳过,打印“ 8”并终止。


"89",;5-;,@11字节
PurkkaKoodari

@ Pietu1998不错!如果您想将其发布为答案,我会很乐意
赞成

继续进行下去,如果您愿意的话,您已经找到了;零件。
PurkkaKoodari

@ Pietu1998编辑。非常感谢!
karhell

仅供参考,我设法采用一种不同的方法将其减少到7个字节。链接
James Holderness

7

Pyth 4/5-6个字节/ 2个版本= 3

  5 ;4

在Pyth 5中,行首的偶数空格将被忽略以用于缩进,而在Pyth 4中,它的作用就像一个空格,并防止打印5。在Pyth 4中,分号仅完成语句,从而可以4打印;而在Pyth 5中,空格和分号使该行的其余部分成为注释。


11
谁知道Pyth有版本?
暴民埃里克(Erik the Outgolfer)'17年


7

大概是4个字节,得分4 /∞

B3%0

适用于您的系统具有足够内存来运行的每个版本。不竞争,因为它很la脚。根据此meta post有效。

基本上,B3从左面旋转一排到顶面。F3和F₁3或B₁3一样好。由于Cubically 3x3x3中的一行是三个Cubelet乘以一个Cubelet,因此将三个1'S'放到顶面中,使其正面总和为3。%0打印该顶面总和,为Cubically 3 x3x3 打印3 。

在立方体4x4x4中,行是4x1立方体。将4 1放入顶面,得出4的总和。


9
分数不应该是4 /∞吗?
nwp

7

x86 16/32/64位机器代码:11个字节,得分= 3.66

此函数以AL中的整数形式返回当前模式(默认操作数大小)。用签名从C调用uint8_t modedetect(void);

NASM机器码+源代码清单(显示16位模式下的工作方式,因为它BITS 16告诉NASM为16位模式组合源助记符。)

 1          machine      global modedetect
 2          code         modedetect:
 3 addr     hex          BITS 16

 5 00000000 B040             mov    al, 64
 6 00000002 B90000           mov    cx, 0       ; 3B in 16-bit.  5B in 32/64, consuming 2 more bytes as the immediate
 7 00000005 FEC1             inc    cl          ; always 2 bytes.  The 2B encoding of inc cx would work, too.
 8                       
 9                           ; want: 16-bit cl=1.   32-bit: cl=0
10 00000007 41               inc    cx       ; 64-bit: REX prefix
11 00000008 D2E8             shr    al, cl   ; 64-bit: shr r8b, cl doesn't affect AL at all.  32-bit cl=1.  16-bit cl=2
12 0000000A C3               ret
# end-of-function address is 0xB, length = 0xB = 11

理由

x86机器代码没有正式的版本号,但是我认为通过生成特定的编号而不是选择最方便的版本(仅占用7个字节,请参见下文),可以满足该问题的意图。

最初的x86 CPU(英特尔的8086)仅支持16位机器代码。80386引入了32位机器代码(在32位保护模式下可用,后来在64位OS下以兼容模式使用)。AMD推出了可在长时间模式下使用的64位机器代码。这些是x86机器语言的版本,其含义与Python2和Python3是不同的语言版本相同。它们大多兼容,但有意更改。您可以直接在64位OS内核下运行32或64位可执行文件,就像运行Python2和Python3程序一样。

这个怎么运作:

从开始al=64。向右移动1(32位模式)或2(16位模式)。

  • 16/32与64位:1字节inc/ dec编码是64位的REX前缀(http://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix)。REX.W根本不影响某些指令(例如a jmpjcc),但是在这种情况下要获得16/32/64,我想使用inc或dec ecx而不是eax。这也会设置REX.B,从而更改目标寄存器。但是幸运的是,我们可以做到这一点,但可以进行设置,因此不需要转换64位al

    仅在16位模式下运行的指令可以包含ret,但我认为没有必要或没有帮助。(如果您想这样做,则不可能内联为代码片段)。它也可以jmp在函数内。

  • 16位和32/64:立即数是16位而不是32位。更改模式可以改变指令的长度,因此32/64位模式将立即解码的后两个字节解码为立即数,而不是单独的指令。我通过在此处使用2字节指令使事情变得简单,而不是使解码不同步,因此16位模式将从不同于32/64的指令边界解码。

    相关:操作数大小前缀会更改立即数的长度(除非它是带符号扩展的8位立即数),就像16位模式和32/64位模式之间的差异一样。这使得指令长度解码很难并行进行。英特尔CPU具有LCP解码停顿


大多数调用约定(包括x86-32和x86-64 System V psABI)都允许狭窄的返回值在寄存器的高位中产生垃圾。它们还允许破坏CX / ECX / RCX(对于64位是R8)。IDK是否在16位调用约定中很常见,但这是代码高尔夫,所以我总是只能说这是自定义调用约定。

32位反汇编

08048070 <modedetect>:
 8048070:       b0 40                   mov    al,0x40
 8048072:       b9 00 00 fe c1          mov    ecx,0xc1fe0000   # fe c1 is the inc cl
 8048077:       41                      inc    ecx         # cl=1
 8048078:       d2 e8                   shr    al,cl
 804807a:       c3                      ret    

64位反汇编在线尝试!):

0000000000400090 <modedetect>:
  400090:       b0 40                   mov    al,0x40
  400092:       b9 00 00 fe c1          mov    ecx,0xc1fe0000
  400097:       41 d2 e8                shr    r8b,cl      # cl=0, and doesn't affect al anyway!
  40009a:       c3                      ret    

相关:我在SO上的x86-32 / x86-64多语言机器代码问答。

16位和32/64之间的另一个区别是寻址模式的编码方式不同。例如lea eax, [rax+2]8D 40 02)像lea ax, [bx+si+0x2]16位模式一样进行解码。显然,这对于代码高尔夫球来说很难使用,尤其是因为在许多调用约定中,e/rbx并且e/rsi它们都保留了调用。

我还考虑过使用10字节mov r64, imm64,即REX + mov r32,imm32。但是由于我已经有一个11字节的解决方案,所以这最多等于(10个字节+ 1个ret)。


32位和64位模式的测试代码。(我实际上并没有在16位模式下执行它,但是反汇编告诉您它将如何解码。我没有设置16位仿真器。)

; CPU p6   ;  YASM directive to make the ALIGN padding tidier
global _start
_start:
    call   modedetect
    movzx  ebx, al
    mov    eax, 1
    int    0x80        ; sys_exit(modedetect());

align 16
modedetect:
BITS 16
    mov    al, 64
    mov    cx, 0       ; 3B in 16-bit.  5B in 32/64, consuming 2 more bytes as the immediate
    inc    cl          ; always 2 bytes.  The 2B encoding of inc cx would work, too.

    ; want: 16-bit cl=1.   32-bit: cl=0
    inc    cx       ; 64-bit: REX prefix
    shr    al, cl   ; 64-bit: shr r8b, cl doesn't affect AL at all.  32-bit cl=1.  16-bit cl=2
    ret

该Linux程序以exit-status =退出modedetect(),因此以身份运行./a.out; echo $?。组装并将其链接到静态二进制文件中,例如

$ asm-link -m32 x86-modedetect-polyglot.asm && ./x86-modedetect-polyglot; echo $?
+ yasm -felf32 -Worphan-labels -gdwarf2 x86-modedetect-polyglot.asm
+ ld -melf_i386 -o x86-modedetect-polyglot x86-modedetect-polyglot.o
32
$ asm-link -m64 x86-modedetect-polyglot.asm && ./x86-modedetect-polyglot; echo $?
+ yasm -felf64 -Worphan-labels -gdwarf2 x86-modedetect-polyglot.asm
+ ld -o x86-modedetect-polyglot x86-modedetect-polyglot.o
64

## maybe test 16-bit with BOCHS somehow if you really want to.

如果可以为版本1、2、3编号,则为7个字节(分数= 2.33)

没有用于不同x86模式的正式版本号。我只是喜欢写asm答案。我认为,如果我只是调用模式1,2,3或0,1,2,这将违反问题的意图,因为这样做的目的是迫使您生成一个不方便的数字。但是如果允许的话:

 # 16-bit mode:
42                                  detect123:
43 00000020 B80300                      mov ax,3
44 00000023 FEC8                        dec al
45                                  
46 00000025 48                          dec ax
47 00000026 C3                          ret

其中以32位模式解码为

08048080 <detect123>:
 8048080:       b8 03 00 fe c8          mov    eax,0xc8fe0003
 8048085:       48                      dec    eax
 8048086:       c3                      ret    

和64位为

00000000004000a0 <detect123>:
  4000a0:       b8 03 00 fe c8          mov    eax,0xc8fe0003
  4000a5:       48 c3                   rex.W ret 

我不确定这些版本是否不同。它们不只是与不同的系统配置相关吗?
Uriel's

1
@Uriel:在CPU以16位模式,32位模式或64位模式运行一块机器代码时,等同于在同一Python程序上运行python2python3解释器的机器代码。新的x86 CPU始终包含与旧CPU兼容的模式(这是使用这种难以理解的复杂机器代码格式的唯一借口!),但是386的32位保护模式和x86-64的长模式确实是这样。 x86机器代码的新版本。长模式甚至删除了一些操作码,使它们无效。
彼得·科德斯

5

Brachylog / Brachylog v1,5 /2 = 2.5

2,1hw

在线尝试!(Brachylog)

在线尝试!(Brachylog v1)

Brachylog的说明:

?2,1hw.
?2      Unify ? (input) with 2 (no input so it succeeds)
  ,1    Append 1 (21)
    h   First element/head (2)
     w. Write to STDOUT and unify with output (not displayed)

Brachylog v1的说明:

?2,1hw.
?2      Unify ? (input) with 2 (no input so it succeeds)
  ,     Break implicit unification/logical AND
   1h   Take first element/head of 1 (1)
     w. Write to STDOUT and unify with output (not displayed)

大!附带说明一下,2,1在Brachylog v2中,不是构造列表[2,1]2;1将),而是构造数字21(这不会改变您希望答案起作用的方式)。
致命

@Fatalize Ooh,谢谢,我与Jelly混淆了...
Erik the Outgolfer

@Fatalize BTW 2;1不会在Brachylog v1中工作,因为这;意味着逻辑或。
暴民埃里克(Erik the Outgolfer)'17年

5

C89 / C99,25字节,2个版本,得分= 12.5

#include <stdio.h>

int main() {
    int v = 11 //**/ 11
            + 88;
    printf("C%d\n", v);
    return 0;
}

// C89无法识别样式注释。

高尔夫球版:

v(){return 20//**/2
+79;}

在线试用:C89C99


更换int v()main(),它的短,实际上将编译为一个完整的程序!
安德里亚(Andrea)

@安德里亚谢谢。AFAIK,允许发布函数或整个程序。
nwellnhof


5

Perl 5和Perl 6,23 字节,19个字节,得分9.5

print 6-grep '.',''

Perl 5 grepfirst op始终被视为正则表达式,而在Perl 6中则不是如此。


得分是19/2 = 9.5
DanielVestøl17年

5

Bash,所有4个版本,72 71 32字节⇒分数= 8

s=$'\ua\xa\n';expr 5 - ${#s} / 2

这段代码$'...'在每个Bash版本中使用了不同的字符串解释。
输出主要版本号,仅此而已。

Doc在这里找到。

取消高尔夫:

s=$'\ua\xa\n';
expr 5 - ${#s} / 2
# Bash v4 sees three linefeeds => length of 3 => 5 - 3 / 2 = 4
# Bash v3 sees the literal '\ua' + two linefeeds: 5 chars in length
#    => 5 - 5 / 2 = 3
# Bash v2 sees '\ua\xa' + linefeed, 7 chars: 5 - 7 / 2 = 2
# Bash v1 does not even interpret $'..' strings, and sees literally '$\ua\xa\n' of length 9 => 5 - 9 / 2 = 1

这个答案只是猜测。我仅在bash 4和3中对其进行了测试,但它也应该在其他版本上也可以使用。

让我知道它是否可以/不可以,我将在其他版本可用后立即尝试。

-1个字符,感谢Jens。
-29字节归功于Digital Trauma(整个expr构思)!


Shell语法;;在最后一个替代中不需要。使用;剃掉一个字节。
詹斯

1
我刚刚在bash-2.05a(刚刚为Cygwin编译)上进行了尝试,它错误地报告了“ 3”,而不是“ 2” :(
Jason Musgrove

1
解释$'\xN功能似乎已在2.01.1中添加...我将不得不更新我的答案。正在处理
joH1

我可以请你试试吗?s="$'\ua\xa\n'";case ${#s} in 3)echo 4;;5)echo 3;;7)echo 2;;9)echo 1;esac
joH1

1
您也许可以像这样打高尔夫球s=$'\ua\xa\n';expr 5 - ${#s} / 2。这适用于v3和v4。我现在没有较旧的版本可以尝试。
Digital Trauma

4

R,版本2和3,得分:10.5分

cat(exists("cite")+2)

2对于R 2.xx和3R 3.xx,此命令返回。该功能cite已在R版本3.0.0中添加。因此,该命令exists("cite")返回FALSER 2.xx和TRUER 3.xx

R,所有版本(1、2和3),得分:12分

e=exists;cat(e("cite")+e("eapply")+1)

该功能eapply在R 2.0.0中引入。


R.version$major。15个字符。从那时起我就不知道了。
瑞·巴拉达斯

@RuiBarradas让我引用OP:“ 您的程序可能不使用内置的,宏的或自定义的编译器标志来确定语言版本。
Sven Hohenstein

好的,对不起,我已经错过了那部分。我应该删除评论吗?
Rui Barradas

@RuiBarradas没问题。您无需删除评论。
Sven Hohenstein

您应该处理打印结果。当前,当以完整程序运行时,此操作不会打印任何内容。
JAD

4

Python,196字节/ 16个版本=得分12.25

版本是1.5、1.6、2.0、2.1、2.2、2.3、2.4、2.5、2.6、3.0、3.1、3.2、3.3、3.4、3.5和3.6
不幸的是我不得不省略2.7,因为其中没有任何模块(据我所知)不是在2.6中而是在3.0中。

i=15
try:
 for m in'os.atexit.os.os.os.warnings.cgitb.heapq.collections._ast.abc.queue.os.os.os.importlib.argparse.lzma.asyncio.zipapp.secrets.'.split('.'):__import__(m);i=i+1
except:print(i/10.)

我们遍历了在不同版本的python中引入的模块,在出现第一个错误时,我们退出并返回该版本。主要版本之间的空白可通过重复导入来填补os。python 1.5的测试依赖于string.split直到1.6才存在。

感谢奥利弗格雷的回答用于测试在一个循环中新的类/模块的想法。

我现在终于在所有相关版本的python上进行了测试...这需要编辑1.5源代码才能进行编译...


4

Windows的批处理文件,35个字节/ 2个版本=得分17.5

@if /i Z==z @echo NT&exit
@echo DOS

DOS在MS-DOS (duh)NTWindows NT上打印。(du)

现在,进行一些解释。

自MS-DOS时代以来,Windows就具有批处理脚本功能,自那时以来并没有太大变化。但是,当Windows NT出现时,Microsoft将批处理脚本的默认解释器从COMMAND.COM更改为cmd.exe(现在也允许扩展名.cmd作为原始的替代.bat)。

这样,他们还实现了一些更改,例如/i用于忽略条件字符串大小写的标志。也就是说,虽然Z==z为假,但/i Z==z为真。

我们利用DOS不区分大小写的方式,将大写Z与小写进行比较z。通过使用该/i标志,我们最终Z==z在DOS上为(false),z==z在NT上为(true)。

现在,我意识到挑战说明了应该打印版本号。但是,据我所知,批处理脚本没有“版本号”,所以这是我能得到的最接近的版本。


在Windows 10,DOSBox和vDos上进行了测试:

Windows 10:

Windows 10

cmd /k以阻止关闭的窗口运行exit

DOSBox:

DOS盒

vDos:

vDos


Windows 7比Windows短NT
user202729

2
@ user202729我想,但是话又说回来,7它不是真正的语言版本,从3.1开始在所有Windows上都是相同的。因此,我认为将其命名为“ 7何时”应该是不公平的3.1
Matheus Avellar

3

Wolfram语言/ Mathematica 10/11,37字节/ 2个版本= 18.5

考虑一下(Length@DateRange[{1},{1}][[1]]+27)/3,为37个字节并使用2个版本,我得到18.5的分数。

In[1]:= $Version

Out[1]= "10.4.1 for Microsoft Windows (64-bit) (April 11, 2016)"

In[2]:= (Length@DateRange[{1}, {1}][[1]] + 27)/3

Out[2]= 10

In[1]:= $Version

Out[1]= "11.1.1 for Microsoft Windows (64-bit) (April 18, 2017)"

In[2]:= (Length@DateRange[{1}, {1}][[1]] + 27)/3

Out[2]= 11

我敢肯定有一种更有效的方法,但是DateRange输出之间的差异最近使我陷入困境,所以我开始使用它。

作为后续,有人可能会利用对Mathematica 1-〜8版进行Length@DateRange[{1}, {1}][[1]]评估1,但是我没有时间将其纳入。


2
完全确定您的答案不符合提示的要求,即您使用的最后一条规则是$VersionYour program may not use a builtin, macro, or custom compiler flags to determine the language version.
Amndeep7

7
我只是$Version用来证明它以正确的版本输出了正确的结果,这$Version不是我的答案...
user6014

所有的好朋友-事情是,您使用的是$VersionNumber,但您却在使用它$Version。在我看来,尽管程序的Length@DateRange实质是内容,但如果不$Version提供您随后要处理的完整版本信息,那将是行不通的,因此违反了规则。
Amndeep7 '17

4
@ Amndeep7提交的内容是第一段中内联的37字节代码。代码块仅是输出演示。
PurkkaKoodari

3
说明:在不同版本中使用不同的时间格式。这可以打更多{1} Tr[1^#&@@%~DateRange~%]/3+9(31字节),甚至7+Length@Now(12字节)
user202729

3

Ruby 1.x和2.x,20个字节,得分10

p [].to_h&&2rescue 1

基于Ruby 2中to_hArray类介绍的方法。


不错的第一答案。我没有方便进行测试的1.x,但是p [].to_h&&2rescue 1有点短。
manatwork '17

@manatwork太好了,节省了3个字节,就像一个咒语一样工作
Philipp Frank

3

Erlang,180字节,11个版本,得分16.36

20-length([A||A<-[schedulers,c_compiler_used,cpu_topology,snifs,dynamic_trace,port_count,nif_version,end_time,max_heap_size,atom_count],{'EXIT',_}<-[catch erlang:system_info(A)]]).

有缩进和换行符:

20-length([A||A<-
                  [schedulers,
                   c_compiler_used,
                   cpu_topology,
                   snifs,
                   dynamic_trace,
                   port_count,
                   nif_version,
                   end_time,
                   max_heap_size,
                   atom_count],
              {'EXIT',_}<-[catch erlang:system_info(A)]]).

从10开始,对每个主要版本的一个次要版本进行了测试:

  • R10B-9
  • R11B-5
  • R12B-5
  • R13B04
  • R14B04
  • R15B03
  • R16B03
  • 17.5.6.2
  • 18.2.1
  • 19.2
  • 20.0

这个想法是,每个主要版本都为该函数添加了至少一个新的允许参数erlang:system_info,因此让我们尝试列表中的参数,计算其中有多少失败,然后从当前版本的20中减去失败的数量。


3

朱莉娅0.4,0.5,46字节,得分22

f(::ASCIIString)=.4
f(::String)=.5
f()=f("")

Julia已在许多版本中更改了具体的和抽象的String类型的类型名称。

该代码特别利用:

朱莉娅0.4

  • 具体是ASCIIString
  • 摘要是正式的AbstractString
  • 摘要已弃用的别名String
  • 具体比抽象更具体,因此可以赢得派遣

朱莉娅0.5

  • 具体是正式的String
  • 具体的别名已弃用ASCIIString
  • 摘要为AbstractString,(尽管在这里无关紧要)
  • 由于已经为具体的字符串类型定义了两种方法,因此后者将覆盖前者。

另请参阅我基于不同原理的更新更有效的解决方案


3

Japt(1&2),8 6/2 = 4 3

'1r\S2

测试v1  |   测试v2

  • 由于使用了Oliver,节省了2个字节

说明

在v2之前,Japt使用了自定义的RegEx语法,因此我们可以利用它。

'1

数字1作为字符串。

 r  2

r下面的()替换为2

\S

Japt 2将其视为RegEx /\S/g,与匹配1。Japt 1会忽略\转义字符,而只会看到S,这是空格字符的Japt常数,并且显然与匹配1


3

Befunge,得分= 3.5

7字节,2个版本

"]"'b.@

在Befunge-93中
在线尝试在Befunge-98中在线尝试

"]"是两个版本中的字符串文字,将93(的ASCII值[)压入堆栈。'b是Befunge-98中的字符文字,按98(的ASCII值b),但在Befunge-93中是无效指令,因此将其忽略。因此,在Befunge-93中以93结束堆栈顶部,在Befunge-98中以98结束堆栈顶部。.@将值写到堆栈的顶部,然后退出。


]".@.b'或者]g.@.b'也行
MildlyMilquetoast

3

Ruby 1.x(<1.9)和2.x,10 8个字节,score = 4

$><<?2%7

试试吧:

通过利用?xRuby 1.x和2.x之间的不同行为来工作。?A例如,在Ruby 1.x中,返回65(字符的ASCII值A),但是在Ruby 2.0中,它返回一个字符的字符串"A"

上面的代码等效于此:

val = ?2
$> << val % 7

在Ruby 1.x(<1.9)中,的值为valis 50(字符的ASCII值2),即Fixnum。Fixnum#%是模运算符,因此50 % 7返回1

在Ruby 2.x中,val字符串是"2"String#%是的中缀版本sprintf,因此"2" % 7等价于sprintf("2", 7),其中"2"是格式字符串。由于格式字符串不包含任何格式序列(例如%d),因此后续参数将被丢弃并"2"返回。

最后,$>是的别名$stdout,因此$> << ...输出结果。


1
哦,太好了!我试图做类似的事情,?A==66?1:2然后才找到您的答案
Piccolo

3

的Python 2Python 3中36 34个字节,得分18 17

print(str(hash(float('-inf')))[1])

Python 2中,负无穷大的哈​​希值为-271828,但在Python 3中为-314159。编辑:由于@ArBo,节省了2个字节,得分为1分。


斜视这是故意的e vs pi事情吗?
乔·金

@JoKing是的;显然,当hash最初固定为浮点无穷大时,相关的开发人员使用pi * 1e5和e * -1e5作为哈希值。在Python 3中的某个时刻,负无穷大的值已更改为哈希无穷大的值。
尼尔

2

Python 3Python 2,得分17.5

(35个字节,2个版本)

try:exec("print 2")
except:print(3)

Python 2,35个字节

在线尝试!

Python 3,35个字节

在线尝试!

ETHproductions节省了5个字节

高尔夫不是一个好的代码答案,而是一个巨大的改变!


嗯,您可以将每个语句放在前一行吗?即try:exec("print 2")\nexcept:print(3)
ETHproductions

@ETHproductions谢谢!我没想到会赢,所以我有点分心。我主要想关注Python 2和3之间巨大变化
。– jferard
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.