Determine a versão do seu idioma

51

Seu desafio é escrever um poliglota que funcione em diferentes versões do seu idioma. Quando executado, sempre gera a versão do idioma.

Regras

  • Seu programa deve funcionar em pelo menos duas versões do seu idioma.
  • A saída do seu programa deve ser apenas o número da versão. Sem dados estranhos.
  • Seu programa pode usar qualquer método que você desejar para determinar o número da versão. No entanto, a saída deve seguir a regra 2; no entanto, você determina o número da versão, a saída deve ser apenas o número.
  • Seu programa precisa apenas produzir a versão principal do idioma. Por exemplo, no FooBar 12.3.456789-beta, seu programa precisaria apenas produzir 12.
  • Se o seu idioma colocar palavras ou símbolos antes ou depois do número da versão, você não precisará apresentá-los, e apenas o número. Por exemplo, em C89, seu programa só precisa imprimir 89e, em C ++ 0x, seu programa só precisa imprimir 0.
  • Se você optar por imprimir o nome completo ou os números de versão secundários, por exemplo, C89 em vez de C99, ele deverá imprimir apenas o nome. C89 build 32é válido, enquanto error in C89 build 32: foo barnão é.
  • Seu programa não pode usar sinalizadores de compilador internos, macro ou personalizados para determinar a versão do idioma.

Pontuação

Sua pontuação será o tamanho do código dividido pelo número de versões em que funciona. A pontuação mais baixa vence, boa sorte!

MD XF
fonte
4
O que é um número de versão do idioma? Quem determina isso?
Assistente de trigo
9
Penso que inverso-linear no número de versões não aceita respostas com alto número de versões.
user202729
6
@ user202729 Eu concordo. Impressora Inteira Versátil fez bem - pontuação foi (number of languages)^3 / (byte count).
Mego
6
Qual é a versão para um idioma ? Não podemos definir uma linguagem como seus intérpretes / compiladores aqui? Digamos que existe uma versão do gcc que possui um bug que, com certos códigos C89, produz um executável cujo comportamento viola a especificação C89, e foi corrigido na próxima versão do gcc. Isso deve contar uma solução válida se escrevermos um trecho de código com base nesse comportamento de bug para saber qual versão do gcc está usando? É direcionado para uma versão diferente do compilador , mas NÃO para uma versão diferente da linguagem .
TSH
6
Eu não entendo isso. Primeiro você diz "A saída do seu programa deve ser apenas o número da versão". . Então você diz "Se você optar por imprimir o nome completo ou os números de versão secundários, por exemplo, C89 em vez de C99, ele deve apenas imprimir o nome". Então a primeira regra não é realmente um requisito?
pipe

Respostas:

16

Sério e Realmente , 3 bytes, pontuação 1.5

'1u

Experimente on-line: na verdade , sério

Explicação:

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

ue Dter funcionalidade nas strings foi adicionado apenas no Actually (que é seriamente v2).

Mego
fonte
3
O README.md da Actually diz que Na verdade é o sucessor espiritual de Seriamente. Não parece uma mera versão para mim.
Adám 18/08/19
7
@ Adám Se você observar as ramificações no repositório, reside seriamente na v1ramificação. Antes de ser seriamente reprovado, residia na v2filial. Além disso, os 1.xnúmeros de versão usados ​​seriamente nos lançamentos , enquanto o Na verdade usa 2.x(tanto lá quanto no PyPI ).
Mego
115

Python 3.0 e Python 2, pontuação 6

(12 bytes, 2 versões)

print(3/2*2)

Experimente on-line:

Confia no fato de que o Python 3+ usa a divisão de flutuação por padrão, diferente do Python 2, que usa a divisão de piso.

fireflame241
fonte
@ MaltySen Your program should work in at least two versions of your language.Funciona em pelo menos duas versões 2.7 e 3.0. Eu escolhi to print the full name or minor version numbers.
Fireflame241
Oh, entendo, meu mal.
Maltysen 16/08/19
4
AMD! Desenvolvedores de python pobres
Regis Portalez
4
@RegisPortalez from __future__ import division, problem resolve :)
Łukasz Rogalski
62

Java, 189 bytes, 10 versões, pontuação = 18,9

As versões suportadas: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8e9

(Para pontuações anteriores, verifique o histórico !)

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;}}

Execute-o no Java 8
Execute-o no Java 9 ou posterior

Ungolfed

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

Observe que a parte do código return v<9?"1."+v:v;(anteriormente return(v<9?"1.":"")+v;) precisa ser verificada em qualquer versão entre Java 1.0 e Java 1.3 incluído. Não tenho nenhuma instalação do Java 1.3 ou anterior à disposição para testar essa sintaxe.

Introdução

O controle de versão Java tem um histórico especial. Todas as versões foram historicamente 1.xincluídas 1.0. Mas ... a partir do Java 9 em diante e do JEP223 , o esquema da versão mudou de usado 1.xpara x. Essa é a versão como conhecida internamente. Portanto, temos a seguinte tabela (junto com o Javadoc e a 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

Esta entrada de desafio corresponde à coluna da versão na tabela acima, que é o que está contido na propriedade do sistema "java.version".

Explicação

O objetivo é verificar a partir de qual versão uma classe começa a existir, porque o Java reprova o código, mas nunca o remove. O código foi escrito especificamente em Java 1.0 para ser compatível com todas as versões, novamente, porque o JDK é (principalmente) compatível com o encaminhamento de origem .

A implementação tenta encontrar os nomes mais curtos de classe que cada versão introduzida. Porém, para obter bytes, é necessário tentar escolher um subpacote comum. Até agora, achei o pacote mais eficiente java.utilporque ele contém várias classes de nome curto, espalhadas por todas as versões do Java.

Agora, para encontrar o número da versão real, os nomes das classes são classificados introduzindo a versão. Em seguida, tento instanciar cada classe sequencialmente e incrementar o índice da matriz. Se a classe existir, pularemos para a próxima, caso contrário, deixamos a exceção ser capturada pelo trybloco. Quando concluído, outra exceção é lançada porque não há mais classes cuja existência precisamos verificar.

De qualquer forma, o encadeamento deixará o trybloco com uma exceção. Essa exceção não é capturada, mas simplesmente retida graças ao finallybloco, que, por sua vez, substitui a exceção retida na verdade, retornando um valor que é "1."+vonde vestá o índice usado anteriormente. Também acontece que fizemos esse índice corresponder ao número da versão secundária do Java.

Uma parte importante do golfe foi encontrar o novo nome de classe mais curto no pacote java.util(ou qualquer pacote filho) para cada versão. Aqui está a tabela que eu usei para calcular esse custo.

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

Créditos

  • 30 bytes salvos graças a Kevin Cruijssen (embora eu estivesse fazendo isso antes de ler seu comentário, prometo!).
  • 26 bytes adicionais salvos graças a Neil (não, eu não estava pensando em fazer isso)
  • 12 bytes graças a Nevay e agradável out-of-the -box pensamento -tentar-catch!
  • Mais 11 bytes de Neil e o belo finallytruque portátil .
  • Mais 2 bytes graças a Kevin Cruijssen, substituindo return(i<9?"1.":"")+i;por return i<9?"1."+i:i;(isso precisa ser validado com relação a 1,0 ou no máximo 1,3, pois nenhuma alteração de sintaxe ocorreu antes da versão 1.4)

With builtins

Se builtins fossem permitidos:

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

54 bytes para 13 versões (de 1,0 a 12), portanto a pontuação seria 4,1538.

Olivier Grégoire
fonte
11
@KevinCruijssen Abri o javadoc e executei classes com nomes abreviados 1 por 1. Mas ... fui ajudado um pouco por esta página: docs.oracle.com/javase/8/docs/technotes/guides/lang/…
Olivier Grégoire
11
260 bytes ou talvez 1 mais, não sei se return"...sem espaço é possível em todas as versões TBH).
Kevin Cruijssen
11
235 bytes: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 bytes: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
11
Ooh, eu me perguntei sobre a iteração de uma matriz e a captura de uma exceção, mas você pode ir melhor finally{return"1."+i;}.
Neil
22

Python , 606 bytes / 15 versões = pontuação 40.4

-67 bytes (lol) graças a NoOneIsHere.

As versões são 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 e 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)

Todo o crédito à incrível resposta do Sp3000 . A nova linha à direita é necessária.

Foi divertido jogar golfe. Isso deve funcionar (sim, eu instalei cada uma dessas versões), mas posso ter acidentalmente causado algo. Se alguém encontrar um bug, entre em contato.

totalmente humano
fonte
... Oh, não é de admirar. Fiquei me perguntando por que o Sp3000 colocou parênteses em todas as printchamadas ... Obrigado por me avisar!
totallyhuman
2
Você pode salvar 68 bytes removendo os tipos específicos de erros (substitua todos os excepts por except:).
NoOneIsHere
Isso ainda funcionaria se você o fizesse, em x=<string inside eval>vez de apenas avaliar o código manualmente?
Blue
@NoOneIsHere Pensei, a princípio, que você não podia por causa de todos 1/0, mas então percebi. Obrigado!
totallyhuman
21

C ++ 14/11/17, pontuação = 147/3 = 49

Para distinguir entre C ++ 11 e C ++ 14/17, ele usa a alteração no padrão constde constexprfunções-membro no C ++ 14 (com crédito para o exemplo em https://stackoverflow.com/questions/23980929/ o que muda-introduzido-em-c14-pode-potencialmente-quebrar-um-programa-escrito-em-c1 ). Para distinguir entre C ++ 14 e C ++ 17, ele usa o fato de que o C ++ 17 desativou os trigramas.

#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);}

Ungolfed:

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);
}

(Testado com o Debian gcc 7.1.0 usando -std=c++{11,14,17}.)

Daniel Schepler
fonte
11
Ótima primeira resposta! Observe que você pode jogar golfe nos espaços entre o includee o <nas instruções de inclusão, por exemplo #include<iostream>.
MD XF
11
Hmm ... se as regras fossem revisadas para proibir o uso de diferenças de biblioteca padrão (que neste caso usa indiretamente a __cplusplusmacro) - para distinguir C ++ 17 de C ++ 14, eu me inclinaria a usar a alteração no intervalo baseado em para semântica. Talvez crie classes mínimas de iterador / sentinela ao longo das linhas para boost::integer_iteratorque a conversão de sentinel em iterador tenha um comportamento "surpreendente".
precisa saber é o seguinte
4
return 0;está implícito para mainque você possa salvar 9 bytes lá. Também de acordo com a wc -csua solução, você está usando 251 bytes e não 252 (seu editor pode ter inserido uma nova linha no final).
nwp 17/08/19
11
É provavelmente mais curto para usar a falta de trigraphs para c separado ++ 17 de c ++ 14
Potato44
11
Isso funcionaria? return *=>return*
Zacharý
19

EcmaScript 3/5/2015 / 2016/2017 no navegador, 59 bytes / 5 versões = 11,8 pontos

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

Relatório 3 do NetScape 7 e relatório 5 do Opera 12

Economize 1 byte graças ao GOTO 0

tsh
fonte
11
Ninjaed ! ;)
Salsicha
O Netscape 7 suporta apenas o ES3? Uau, é mais velho do que eu pensava ...
Neil
11
Você pode salvar alguns bytes usando em -!vez de +!!onde faz sentido (e alterar as constantes numéricas de acordo).
GOTO 0
3
Talvez alguma explicação? :)
Derek朕會功夫
@ Derek: veja minha solução (link acima) para uma explicação.
Shaggy
18

JavaScript (ES5 e ES6), 14 bytes / 2 versões = 7

alert(5^"0o3")

0oconstantes octais de estilo são novas no ES6; O ES5 lança a sequência na NaNqual não afeta o resultado do XOR bit a bit.

Neil
fonte
13

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

Também pode enviar a solução com mais versões, mesmo que a pontuação seja ligeiramente superior à solução de 2 versões.

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

Experimente online

Verifica a presença de vários métodos nos protótipos Array, RegExp & String, os nega, fornecendo um booleano e subtrai esse booleano de um valor inicial de 9. A multiplicação de ![].mapcontas pelo fato de o ES4 ter sido abandonado.

  • A dotAllpropriedade (e o ssinalizador relacionado ) para Expressões regulares foi introduzida no ES2018 (v9).
  • O padEndmétodo String foi introduzido no ES2017 (v8).
  • O includesmétodo Array foi introduzido no ES2016 (v7).
  • O keysmétodo Array foi introduzido no ES2015 (v6).
  • O mapmétodo Array foi introduzido no ES5.1 (v5).
  • O popmétodo Array foi introduzido no ES3 (v3).
Shaggy
fonte
ES 7 ou ES 8 é um número de versão válido? Talvez deva ser chamado de ES 201x?
precisa saber é
11
@tsh: Sim, eles ainda usam números de versão; eles apenas usam anos para nomes realese .
Shaggy
9

PHP 5/7, pontuação 5,5

<?=7-"0x2";

3V4L-lo online!

PHP 5.3.9 / 5.3.11, pontuação 10

<?='5.3.'.(9-0x0+2);

3V4L-lo online!

A versão online é mais longa porque as versões antigas do PHP na caixa de areia não têm tags curtas ativadas.

Sísifo
fonte
9

Nota: 15 11 bytes / 2 versões = 5,5

4 bytes eliminados por @ Pietu1998

"89",;5-;,@  

Experimente on-line:
Befunge 93
Befunge 98
Usa o operador ponto-e-vírgula exclusivo do Befunge 98 ("pular para o próximo ponto-e-vírgula") para diferenciar versões. Ambos imprimirão "9". O Befunge 93 ignorará os pontos e vírgulas, subtrairá 5 de "8" (valor deixado no topo da pilha), imprimirá o "3" resultante e terminará. Por outro lado, o Befunge 98 irá pular, imprimir "8" e terminar.

karhell
fonte
"89",;5-;,@para 11 bytes
PurkkaKoodari
@ Pietu1998 Nice! Se você quiser postar isso como uma resposta, eu vou com prazer upvote :)
karhell
Vá em frente e pegue se quiser, você descobriu a ;parte.
PurkkaKoodari
@ Pietu1998 Editado. Muito obrigado!
karhell
Para sua informação, consegui reduzi-lo para 7 bytes, adotando uma abordagem diferente. Link
James Holderness
7

Pitão 4/5 - 6 bytes / 2 versões = 3

  5 ;4

No Pyth 5, uma quantidade uniforme de espaços no início da linha é ignorada para uso no recuo, enquanto no Pyth 4, ele age como um único espaço e impede a impressão do 5. No Pyth 4, ponto-e-vírgula apenas termina as instruções, o que permite 4que seja impresso, enquanto no Pyth 5, um espaço e ponto-e-vírgula fazem um comentário ao restante da linha.

Maltysen
fonte
11
Quem sabia que Pyth tinha versões?
Erik the Outgolfer
7

Python 3 e Python 2.0, 18 bytes, pontuação 18/2 = 9

print(3-round(.5))

Arredondamento de banqueiro em Python 3, arredondamento padrão em Python 2.

Experimente online - Python 3!

Experimente online - Python 2!

Stephen
fonte
pessoas wow Eu sempre vi diferenciadoras python 2 e 3 pela divisão
phuclv
@ L welluV isnhPhúc divisão de poço é mais golfista, então é por isso: P
Stephen
7

Cubicamente, 4 bytes, pontuação 4 / ∞

B3%0

Funciona em todas as versões em que seu sistema possui memória suficiente para executar. Não competir porque é coxo. Válido para esta meta postagem .

Basicamente, B3 gira uma linha da face esquerda para a face superior. F3 funcionaria tão bem quanto F3 ou B3. Como uma linha no Cubically 3x3x3 é três cubelets por um cubelet, isso coloca três 1na face superior, dando uma soma de 3. %0faces que imprime essa soma da face superior, imprimindo 3 para Cubically 3 x3x3.

No Cubically 4x4x4, as linhas são cubos 4x1. Coloca 4 1 na face superior, produzindo uma soma de 4.

MD XF
fonte
9
A pontuação não deve ser de 4 / ∞?
nwp 17/08/19
7

x86 código da máquina de 16/32/64 bits: 11 bytes, pontuação = 3,66

Esta função retorna o modo atual (tamanho padrão do operando) como um número inteiro em AL. Chame de C com assinaturauint8_t modedetect(void);

Código de máquina do NASM + listagem de fontes (mostrando como funciona no modo de 16 bits, pois BITS 16instrui o NASM a montar os mnemônicos de origem no modo de 16 bits.)

 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

Justificação :

O código de máquina x86 não possui oficialmente números de versão, mas acho que isso satisfaz a intenção da pergunta ao produzir números específicos, em vez de escolher o que é mais conveniente (que leva apenas 7 bytes, veja abaixo).

A CPU x86 original, 8086 da Intel, suportava apenas código de máquina de 16 bits. O 80386 introduziu o código da máquina de 32 bits (utilizável no modo protegido de 32 bits e, posteriormente, no modo compatível em um sistema operacional de 64 bits). A AMD introduziu o código da máquina de 64 bits, utilizável no modo longo. Essas são versões da linguagem de máquina x86 no mesmo sentido em que Python2 e Python3 são versões de linguagem diferentes. Eles são principalmente compatíveis, mas com alterações intencionais. Você pode executar executáveis ​​de 32 ou 64 bits diretamente em um kernel do sistema operacional de 64 bits da mesma maneira que poderia executar os programas Python2 e Python3.

Como funciona:

Comece com al=64. Desloque-o para a direita por 1 (modo de 32 bits) ou 2 (modo de 16 bits).

  • 16/32 vs. 64 bits: os códigos de 1 byte inc/ decsão prefixos REX em 64 bits ( http://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix ). O REX.W não afeta algumas instruções (por exemplo, a jmpou jcc), mas, neste caso, para obter 16/32/64, eu queria aumentar ou diminuir em ecxvez de eax. Isso também define REX.B, o que altera o registro de destino. Felizmente, porém, podemos fazer isso funcionar, mas configurar as coisas para que os 64 bits não precisem mudar al.

    As instruções que são executadas apenas no modo de 16 bits podem incluir a ret, mas não achei isso necessário ou útil. (E tornaria impossível alinhar como um fragmento de código, caso você queira fazer isso). Também poderia ser um jmpdentro da função.

  • 16 bits vs. 32/64: os imediatos são 16 bits em vez de 32 bits. A mudança de modos pode alterar o comprimento de uma instrução; portanto, os modos de 32/64 bits decodificam os próximos dois bytes como parte da instrução imediata, em vez de uma instrução separada. Eu mantive as coisas simples usando uma instrução de 2 bytes aqui, em vez de descodificar a sincronização para que o modo de 16 bits decodificasse a partir de limites de instruções diferentes de 32/64.

    Relacionado: O prefixo do tamanho do operando altera a duração do imediato (a menos que seja um imediato de 8 bits com extensão de sinal), assim como a diferença entre os modos de 16 e 32/64 bits. Isso dificulta a decodificação no comprimento das instruções em paralelo; As CPUs Intel têm barragens de decodificação LCP .


A maioria das convenções de chamada (incluindo os psABIs x86-32 e x86-64 System V) permite que valores de retorno limitados tenham lixo nos bits altos do registro. Eles também permitem derrotar CX / ECX / RCX (e R8 para 64 bits). IDK, se isso era comum em convenções de chamada de 16 bits, mas este é um código de golfe, então sempre posso dizer que é uma convenção de chamada personalizada de qualquer maneira.

Desmontagem de 32 bits :

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    

Desmontagem de 64 bits ( Experimente online! ):

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    

Relacionado: minhas perguntas e respostas sobre código de máquina poliglota x86-32 / x86-64 no SO.

Outra diferença entre 16 bits e 32/64 é que os modos de endereçamento são codificados de maneira diferente. por exemplo lea eax, [rax+2]( 8D 40 02) decodifica como lea ax, [bx+si+0x2]no modo de 16 bits. Esta é, obviamente, difícil de usar para o código-golf, especialmente desde e/rbxe e/rsisão, em muitos convenções de chamada preservado-call.

Também considerei o uso de 10 bytes mov r64, imm64, que é o REX + mov r32,imm32. Mas como eu já tinha uma solução de 11 bytes, isso seria no máximo igual (10 bytes + 1 para ret).


Código de teste para os modos 32 e 64 bits. (Na verdade, não o executei no modo de 16 bits, mas a desmontagem mostra como será decodificado. Não tenho um emulador de 16 bits configurado.)

; 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

Este programa Linux sai com exit-status = modedetect(), portanto, execute-o como ./a.out; echo $?. Monte e vincule-o a um binário estático, por exemplo

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

7 bytes (pontuação = 2,33) se eu puder numerar as versões 1, 2, 3

Não há números de versão oficiais para diferentes modos x86. Eu apenas gosto de escrever respostas asm. Eu acho que violaria a intenção da pergunta se eu chamasse os modos 1,2,3 ou 0,1,2, porque o objetivo é forçar você a gerar um número inconveniente. Mas se isso fosse permitido:

 # 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

Que decodifica no modo de 32 bits como

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

e 64 bits como

00000000004000a0 <detect123>:
  4000a0:       b8 03 00 fe c8          mov    eax,0xc8fe0003
  4000a5:       48 c3                   rex.W ret 
Peter Cordes
fonte
Não tenho certeza se isso conta como versões diferentes . Eles não se correlacionam apenas com diferentes configurações do sistema.
Uriel
11
@Uriel: Executar um bloco de código de máquina com a CPU no modo de 16 bits, modo de 32 bits ou 64 bits é o equivalente do código de máquina da execução python2vs. python3intérpretes no mesmo programa Python. As novas CPUs x86 sempre incluem um modo compatível com as CPUs mais antigas (essa é a única desculpa para usar um formato de código de máquina complicado e difícil de decodificar!), Mas o modo protegido de 32 bits de 386 e o ​​modo longo de x86-64 realmente são novas versões do código de máquina x86. O modo longo removeu alguns códigos de operação, tornando-os inválidos.
Peter Cordes
5

Brachylog / Brachylog v1 , 5/2 = 2,5

2,1hw

Experimente online! (Braquilog)

Experimente online! (Brachylog v1)

Explicação para 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)

Explicação para o 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)
Erik, o Outgolfer
fonte
Ótimo! Como nota de rodapé, 2,1no Brachylog v2 não constrói a lista [2,1]( 2;1faria), mas o número 21(que não muda a maneira como você pretendia que sua resposta funcionasse).
Fatalize 17/08/19
@Fatalize Ooh graças eu confuso que, com geléia ...
Erik o Outgolfer
O @Fatalize BTW 2;1não teria funcionado no Brachylog v1 como ;meio lógico OU lá.
Erik the Outgolfer
5

C89 / C99, 25 bytes, 2 versões, pontuação = 12,5

#include <stdio.h>

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

// comentários de estilo não são reconhecidos no C89.

Versão Golfed:

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

Experimente online: C89 , C99

Nwellnhof
fonte
substitua int v()por main(), é mais curto e compilará realmente como um programa completo!
Andrea
@ Andreia Obrigado. AFAIK, é permitido publicar funções ou programas inteiros.
Nwellnhof 17/08/19
Você está certo.
Andrea Andrea
5

Perl 5 e Perl 6, 23 bytes 19 bytes, pontuação 9,5

print 6-grep '.',''

O Perl 5 grepfirst op é sempre tratado como um regex, não no Perl 6.

Joshua
fonte
a pontuação é 19/2 = 9,5
Daniel Vestøl
5

Bash, todas as 4 versões, 72 71 32 bytes ⇒ score = 8

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

Este trecho de código utiliza diferentes interpretações de $'...'strings em cada versão do Bash.
Produz o número da versão principal - e é isso.

Doc encontrado aqui .

Ungolfed:

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

Essa resposta é apenas um palpite; Eu só testei no bash 4 e 3, mas deve funcionar em outras versões também.

Deixe-me saber se existe / não, tentarei com outras versões assim que as tiver disponíveis.

-1 char graças a Jens.
-29 bytes graças ao Digital Trauma (a expridéia toda )!

joH1
fonte
A gramática do shell não requer a ;;na última alternativa. Use ;para cortar um byte.
Jens
11
Eu apenas tentei isso em bash-2.05a (compilado apenas agora para Cygwin), e relata incorretamente "3", e não "2" :(
Jason Musgrove
11
o $'\xNrecurso de interpretação parece ter sido adicionado em 2.01.1 ... Vou ter que atualizar minha resposta. Trabalhando nisso
joH1
posso pedir para você tentar isso? s="$'\ua\xa\n'";case ${#s} in 3)echo 4;;5)echo 3;;7)echo 2;;9)echo 1;esac
joH1
11
Você pode jogar isso com algo parecido s=$'\ua\xa\n';expr 5 - ${#s} / 2. Isso funciona na v3 e v4. Não tenho versões antigas para testar agora.
Digital Trauma
4

R, versões 2 e 3, pontuação: 10,5 pontos

cat(exists("cite")+2)

Este comando retorna 2para R 2.xx e 3para R 3.xx A função citefoi adicionada no R versão 3.0.0. Portanto, o comando exists("cite")retorna FALSEpara R 2.xx e TRUEpara R 3.xx

R, todas as versões (1, 2 e 3), pontuação: 12⅓ pontos

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

A função eapplyfoi introduzida no R 2.0.0.

Sven Hohenstein
fonte
R.version$major. 15 caracteres. Não desde quando existe.
Rui Barradas
@RuiBarradas Deixe-me citar o OP: " Seu programa não pode usar um embutidas, macro ou opções de compilação personalizada para determinar a versão do idioma. "
Sven Hohenstein
Ok, desculpe, eu perdi essa parte. Devo excluir o comentário?
Rui Barradas
@RuiBarradas Sem problemas. Você não precisa excluir o comentário.
Sven Hohenstein
Você deve lidar com a impressão do resultado. Atualmente, quando executado como um programa completo, isso não imprime nada.
JAD
4

Python , 196 bytes / 16 versões = pontuação 12.25

As versões são 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 e 3.6
Infelizmente, tive que deixar de fora 2.7, porque não existem módulos no (até onde eu sei) que não está no 2.6, mas no 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.)

Percorremos vários módulos que foram introduzidos em diferentes versões do python e, no primeiro erro, encerramos e retornamos a versão. As lacunas entre as principais versões são preenchidas importando repetidamente os. O teste para o python 1.5 depende de string.splitnão estar presente até 1.6.

Agradecemos a resposta de Olivier Grégoire pela idéia de testar novas classes / módulos em um loop.

Agora finalmente testei em todas as versões relevantes do python ... que exigiam a edição do código-fonte 1.5 para compilá-lo ...

g.rocket
fonte
4

Arquivo em lote do Windows , 35 bytes / 2 versões = pontuação 17,5

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

Imprime DOSno MS-DOS (duh) e NTno Windows NT. (duh)

Agora, para alguma explicação.

O Windows possui scripts em lote desde os tempos do MS-DOS e não mudou muito desde então. No entanto, quando o Windows NT apareceu, a Microsoft alterou o intérprete padrão para scripts em lote, de COMMAND.COMpara cmd.exe(agora também permitindo a extensão .cmdcomo uma alternativa ao original .bat).

Com isso, eles também implementaram algumas alterações , como o /isinalizador para ignorar maiúsculas e minúsculas em condicionais. Ou seja, enquanto Z==zé falso, /i Z==zé verdade.

Exploramos que o DOS não tinha distinção entre maiúsculas e minúsculas e comparamos maiúsculas Zcom minúsculas z. Usando o /isinalizador, acabamos com um Z==z(falso) condicional no DOS e z==z(verdadeiro) no NT.

Agora, percebo que o desafio especifica que um número de versão deve ser impresso. Mas, até onde eu sei, não existe um 'número de versão' para o script em lote, portanto esse é o mais próximo que pude chegar.


Testado no Windows 10, DOSBox e vDos:

Windows 10:

Windows 10

(execute com cmd /kpara impedir o fechamento da janela exit)

DOSBox:

DOSBox

vDos:

vDos

Matheus Avellar
fonte
O Windows 7é mais curto que o Windows NT.
user202729
2
@ user202729 Suponho, mas, novamente, 7não é realmente uma versão do idioma, é a mesma em todos os Windows 'desde 3.1. Então eu não acho que seria muito justo chamá-lo de 7quando deveria talvez até mesmo ser3.1
Matheus Avellar
3

Wolfram Language / Mathematica 10/11, 37 bytes / 2 versões = 18,5

Considere (Length@DateRange[{1},{1}][[1]]+27)/3, com 37 bytes e trabalhando com 2 versões, me dá uma pontuação de 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

e

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

Tenho certeza de que existe uma maneira mais eficiente, mas a discrepância entre a saída DateRange me incomodou recentemente, então comecei a usá-la.

Como acompanhamento, alguém provavelmente poderia tirar proveito da Length@DateRange[{1}, {1}][[1]]avaliação 1nas versões 1 a 8 do Mathematica, mas não tive tempo para incorporar isso.

user6014
fonte
2
Quase a certeza de que a sua resposta não atender os requisitos da, ou seja, a última regra alerta devido a você usar $Version:Your program may not use a builtin, macro, or custom compiler flags to determine the language version.
Amndeep7
7
Eu só estou usando $Versionpara demonstrar que ela exiba o resultado correto na versão correta, $Versionnão faz parte da minha resposta ...
user6014
Tudo de bom amigo - o problema é que você está usando algo parecido $VersionNumber, mas está chamando $Version. Na minha opinião, embora a Length@DateRangeessência do seu programa seja o material, isso não funcionaria sem $Versionapenas fornecer as informações da versão completa que você processa, o que viola as regras.
precisa saber é o seguinte
4
@ Amndeep7 O envio é o código de 37 bytes descrito no primeiro parágrafo. Os blocos de código são apenas demonstrações de saída.
PurkkaKoodari
3
Explicação: Utilizando diferentes formatos de hora em diferentes versões. Que pode ser golfed mais para {1} Tr[1^#&@@%~DateRange~%]/3+9(31 bytes), ou mesmo 7+Length@Now(12 bytes)
user202729
3

Ruby 1.xe 2.x, 20 bytes, pontuação 10

p [].to_h&&2rescue 1

Com base no to_hmétodo que foi introduzido na Arrayclasse no Ruby 2.

Philipp Frank
fonte
Ótima primeira resposta. Não tenho o 1.x à mão para testar, mas p [].to_h&&2rescue 1é um pouco mais curto.
manatwork
@manatwork Ótimo, economiza 3 bytes e funciona como um encanto #
Philipp Frank
3

Erlang, 180 bytes, 11 versões, pontuação 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)]]).

Com recuo e quebras de linha:

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

Testado em uma versão menor de cada versão principal desde 10:

  • R10B-9
  • R11B-5
  • R12B-5
  • R13B04
  • R14B04
  • R15B03
  • R16B03
  • 17.5.6.2
  • 18.2.1
  • 19,2
  • 20,0

A ideia é que toda versão principal tenha adicionado pelo menos um novo argumento permitido para a função erlang:system_info, então vamos tentar os da lista, contar quantas delas falham e subtrair o número de falhas de 20, que é a versão atual.

legoscia
fonte
3

Julia 0.4, 0.5, 46 bytes, pontuação 22

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

Julia mudou o nome do tipo dos tipos String abstratos e concretos em várias versões.

Este código, em particular, tira proveito de:

Julia 0.4 :

  • Concreto é ASCIIString,
  • O resumo é oficialmente AbstractString,
  • O resumo substituiu o alias para String.
  • O concreto é mais específico do que abstrato, por isso ganha despacho

Julia 0.5 :

  • O concreto é oficialmente String,
  • O concreto substituiu o alias para ASCIIString,
  • O resumo é AbstractString(embora isso não importe aqui)
  • Como dois métodos foram definidos para o tipo de cadeia de concreto, o último substitui o primeiro.

Veja também minha nova solução mais eficaz, baseada em princípios diferentes

Lyndon White
fonte
3

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

'1r\S2

Teste v1  |   Teste v2

  • 2 bytes salvos graças a Oliver

Explicação

Antes da v2, o Japt usava uma sintaxe RegEx personalizada, para que pudéssemos tirar vantagem disso.

'1

O número 1 como uma sequência.

 r  2

Substitua ( r) a seguir por a 2.

\S

Japt 2 vê isso como o RegEx /\S/g, que corresponde ao 1. O Japt 1 ignora o \caractere de escape e apenas vê o S, que é a constante do Japt para um caractere de espaço e, obviamente, não corresponde ao 1.

Shaggy
fonte
3

Befunge, score = 3.5

7 bytes, 2 versões

"]"'b.@

Experimente online em Befunge-93
Experimente online em Befunge-98

"]"é uma string literal nas duas versões, pressionando 93 (o valor ASCII de [) na pilha. 'bé um literal de caractere no Befunge-98, pressionando 98 (o valor ASCII de b), mas essas são instruções inválidas no Befunge-93, portanto elas são simplesmente ignoradas. Assim, terminamos com 93 no topo da pilha em Befunge-93 e 98 em Befunge-98. .@grava o valor no topo da pilha e sai.

James Holderness
fonte
]"[email protected]'ou ][email protected]'também trabalham
MildlyMilquetoast
3

Ruby 1.x (<1.9) e 2.x, 10 8 bytes, pontuação = 4

$><<?2%7

Tente:

Isso funciona explorando os diferentes comportamentos ?xentre o Ruby 1.xe 2.x. No Ruby 1.x, ?A(por exemplo) retorna 65(o valor ASCII do caractere A), mas no Ruby 2.0 ele retorna a cadeia de um caractere "A".

O código acima é equivalente a isso:

val = ?2
$> << val % 7

No Ruby 1.x (<1.9), o valor de valé 50(o valor ASCII do caractere 2), um Fixnum. Fixnum#%é o operador módulo, então 50 % 7retorna 1.

No Ruby 2.x, valé a sequência "2". String#%é uma versão infix de sprintf, então "2" % 7é equivalente a sprintf("2", 7), onde "2"está a cadeia de formato. Como a sequência de formatação não contém nenhuma sequência de formato (por exemplo %d), os argumentos subsequentes são descartados e "2"retornados.

Finalmente, $>é um alias para $stdout, então $> << ...imprime o resultado.

Jordânia
fonte
11
Ooh legal! Eu estava tentando fazer algo assim ?A==66?1:2antes de eu me deparei com a sua resposta
Piccolo
3

Python 2 e Python 3 , 36 34 bytes, pontuação 18 17

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

No Python 2 , o hash do infinito negativo é -271828, mas no Python 3 é -314159. Editar: salvou 2 bytes, 1 ponto de pontuação, graças ao @ArBo.

Neil
fonte
squints Isso é uma coisa deliberada de e vs pi?
Jo King
@JoKing Sim; aparentemente, quando hashfoi corrigido pela primeira vez para trabalhar com infinitas de ponto flutuante, o desenvolvedor relevante usou pi * 1e5 e e * -1e5 como valores de hash. Em algum momento no Python 3, o valor has para infinito negativo foi alterado para ser a negação do valor hash para infinito.
Neil
2

Python 3 , Python 2 , pontuação 17,5

(35 bytes, 2 versões)

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

Python 2 , 35 bytes

Experimente online!

Python 3 , 35 bytes

Experimente online!

Economizou 5 bytes graças a ETHproductions

Não é uma boa resposta ao código de golfe, mas uma grande mudança!

jferard
fonte
Hmm, você pode colocar cada afirmação na linha anterior? Ou sejatry:exec("print 2")\nexcept:print(3)
ETHproductions
@ETHproductions obrigado! Eu não esperava vencer, então fiquei um pouco distraído. Eu queria principalmente para focar a mudança maciça entre Python 2 e 3.
jferard