Déterminez la version de votre langue

51

Votre défi consiste à écrire un polyglotte qui fonctionne dans différentes versions de votre langue. Lorsqu'il est exécuté, il affichera toujours la version linguistique.

Règles

  • Votre programme doit fonctionner dans au moins deux versions de votre langue.
  • La sortie de votre programme ne doit contenir que le numéro de version. Pas de données superflues.
  • Votre programme peut utiliser la méthode de votre choix pour déterminer le numéro de version. Cependant, la sortie doit suivre la règle 2; quelle que soit la manière dont vous déterminez le numéro de version, la sortie ne doit être que le numéro.
  • Votre programme n'a besoin que de sortir la version majeure de la langue. Par exemple, dans FooBar 12.3.456789-beta, votre programme n’aurait besoin que de produire 12.
  • Si votre langue place des mots ou des symboles avant ou après le numéro de version, vous n'avez pas besoin de les indiquer, mais uniquement le nombre. Par exemple, en C89, votre programme n'a besoin que d'imprimer 89et en C ++ 0x, il ne nécessite que d'imprimer 0.
  • Si vous choisissez d'imprimer le nom complet ou les numéros de version mineurs, par exemple C89 par opposition à C99, il ne doit qu'imprimer le nom. C89 build 32est valide, alors que error in C89 build 32: foo barnon.
  • Votre programme peut ne pas utiliser les indicateurs de compilateur intégré, de macro ou personnalisé pour déterminer la version du langage.

Notation

Votre score correspondra à la longueur du code divisé par le nombre de versions dans lesquelles il fonctionne. Le score le plus bas gagne, bonne chance!

MD XF
la source
4
Qu'est-ce qu'un numéro de version de langue? Qui le détermine?
Wheat Wizard
9
Je pense que l'inverse linéaire dans le nombre de version n'accueille pas les réponses avec un nombre élevé de versions.
user202729
6
@ user202729 Je suis d'accord. Polyvalent Integer Printer l' a bien fait - le score était (number of languages)^3 / (byte count).
Mego
6
Quelle est la version d'une langue ? Ne définissons-nous pas une langue comme ses interprètes / compilateurs ici? Disons qu'il existe une version de gcc qui a le bogue de produire, avec certains codes C89, un exécutable dont le comportement enfreint la spécification C89 et qui a été corrigée sur la version suivante de gcc. Cela devrait-il compter comme une solution valable si nous écrivons une partie du code sur ce comportement de bogue pour indiquer quelle version de gcc utilise? Il cible une version différente du compilateur , mais PAS une version différente du langage .
tsh
6
Je ne comprends pas ça. D'abord, vous dites: "La sortie de votre programme ne devrait être que le numéro de version." . Ensuite, vous dites "Si vous choisissez d'imprimer le nom complet ou les numéros de version mineurs, par exemple C89 par opposition à C99, il ne doit qu'imprimer le nom." Donc, la première règle n'est pas réellement une exigence?
pipe

Réponses:

16

Sérieusement et en fait , 3 octets, score de 1,5

'1u

Essayez-le en ligne: en fait , sérieusement

Explication:

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

uet Davoir des fonctionnalités sur les chaînes n'a été ajouté qu'à Actually (qui est Seriously v2).

Mego
la source
3
En fait, le fichier README.md indique qu’Actuellement est le successeur spirituel de Seriously. Cela ne semble pas être un simple changement de version pour moi.
Adám
7
@ Adám Si vous regardez les branches dans le référentiel, réside sérieusement dans la v1branche. Avant d'être sérieusement déconseillé, il résidait réellement dans la v2succursale. De plus, Sérieusement a utilisé les 1.xnuméros de version dans les versions , alors qu'Actuellement utilise 2.x(à la fois sur ce site et sur PyPI ).
Mego
115

Python 3.0 et Python 2, score 6

(12 octets, 2 versions)

print(3/2*2)

Essayez-le en ligne:

S'appuie sur le fait que Python 3+ utilise la division float par défaut, contrairement à Python 2, qui utilise la division de plancher.

fireflame241
la source
@MaltySen Your program should work in at least two versions of your language.Cela fonctionne dans au moins deux versions 2.7 et 3.0. J'ai choisi to print the full name or minor version numbers.
fireflame241
Oh je vois, mon mauvais.
Maltysen
4
OMG! Les développeurs de python pauvres
Regis Portalez
4
@ RegisPortalez from __future__ import division, problème résolu :)
Łukasz Rogalski
62

Java, 189 octets, 10 versions, score = 18.9

Versions prises en charge: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8et9

(Pour les partitions précédentes, consultez l'historique !)

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

Exécuter sur Java 8
Exécuter sur Java 9 ou version ultérieure

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

Veuillez noter que la partie de code return v<9?"1."+v:v;(précédemment return(v<9?"1.":"")+v;) doit être vérifiée par rapport à toute version comprise entre Java 1.0 et Java 1.3 incluse. Je ne dispose d'aucune installation Java 1.3 ou antérieure pour tester cette syntaxe.

introduction

Le versioning Java a un historique particulier. Toutes les versions ont été historiquement 1.xinclus 1.0. Mais ... à partir de Java 9 partir et le JEP223 , la version intrigante a changé d'utiliser 1.xpour x. C'est la version connue en interne. Nous avons donc le tableau suivant (mis en place avec le Javadoc et 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

Cette entrée de défi correspond à la colonne de version du tableau ci-dessus, qui est contenue dans la propriété système "java.version".

Explication

L'objectif est de vérifier à partir de quelle version une classe commence à exister, car Java déprécie le code mais ne le supprime jamais. Le code a été spécifiquement écrit en Java 1.0 pour être compatible avec toutes les versions, encore une fois, car le JDK est (principalement) compatible source à terme .

L'implémentation essaie de trouver les noms de classe les plus courts introduits par chaque version. Cependant, pour gagner des octets, il faut essayer de choisir un sous-paquet commun. Jusqu'ici, j'ai trouvé le paquet le plus efficace java.utilparce qu'il contient plusieurs classes très courtes portant des noms très courts, réparties dans toutes les versions de Java.

Maintenant, pour trouver le numéro de version actuel, les noms de classe sont triés par introduction. Ensuite, j'essaie d'instancier séquentiellement chaque classe et d'incrémenter l'index de tableau. Si la classe existe, on saute à la suivante, sinon on laissera l'exception être interceptée par le trybloc. Une fois cette opération effectuée, une autre exception est générée car il n’ya plus de classes dont nous devons vérifier l’existence.

Dans tous les cas, le fil laissera le try-block avec une exception. Cette exception n'est pas interceptée, mais simplement mise en attente grâce au finally-block, qui annule à son tour l'exception en attente en renvoyant une valeur qui est "1."+vvest l'index utilisé auparavant. Il arrive également que cet index corresponde au numéro de version mineur de Java.

Une partie importante du golf consistait à trouver le nouveau nom de classe le plus court dans le package java.util(ou dans un package pour enfants) pour chaque version. Voici le tableau que j'ai utilisé pour calculer ce coût.

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édits

  • 30 octets sauvés grâce à Kevin Cruijssen (même si je le faisais avant de lire son commentaire, je vous le promets!).
  • 26 octets supplémentaires sauvés grâce à Neil (non, je n'y pensais pas)
  • 12 octets grâce à Nevay et le beau hors-la -box pensée -Essayer-catch!
  • Encore 11 octets de Neil à nouveau et le joli finallytruc portable .
  • 2 octets supplémentaires grâce à Kevin Cruijssen en les remplaçant return(i<9?"1.":"")+i;par return i<9?"1."+i:i;(ceci doit être validé contre 1.0 ou au maximum 1.3 car aucune modification de la syntaxe n’est intervenue avant la version 1.4)

Avec construit

Si les constructions étaient autorisées:

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

54 octets pour 13 versions (de 1.0 à 12), le score serait donc de 4.1538.

Olivier Grégoire
la source
1
@KevinCruijssen J'ai ouvert le javadoc et organisé des cours avec des noms courts 1 sur 1. Mais ... j'ai été un peu aidé par cette page: docs.oracle.com/javase/8/docs/technotes/guides/lang/…
Olivier Grégoire
1
260 octets ou peut-être 1 de plus, je ne sais pas si return"...sans espace est possible dans toutes les versions tbh.)
Kevin Cruijssen
1
235 octets: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 octets: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
Ooh, je me demandais s'il était possible d'itérer un tableau et d'attraper une exception, mais vous pouvez en faire un meilleur avec finally{return"1."+i;}.
Neil
22

Python , 606 octets / 15 versions = score 40,4

-67 octets (lol) grâce à NoOneIsHere.

Les versions sont les suivantes: 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 et 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)

Tout le mérite de la réponse étonnante de Sp3000 . Le retour à la ligne est nécessaire.

Whee, c'était amusant de jouer au golf. Cela devrait fonctionner (oui, j'ai installé chacune de ces versions), mais j'ai peut-être accidentellement oublié quelque chose. Si quelqu'un trouve un bug, s'il vous plaît faites le moi savoir.

totalement humain
la source
... Oh, pas étonnant. Je me demandais pourquoi Sp3000 a mis des parenthèses dans chaque printappel ... Merci de me l'avoir fait savoir!
totalement humain
2
Vous pouvez enregistrer 68 octets en supprimant les types d’erreurs spécifiques (remplacez tous les excepts par except:).
NoOneIsHere
Cela fonctionnerait-il toujours si vous le x=<string inside eval>faisiez au lieu d'évaluer simplement le code manuellement?
Blue
@NoOneIsHere Je pensais, au début, que vous ne pouviez pas à cause de tous les 1/0, mais ensuite j'ai réalisé. Merci!
totalement humain
21

C ++ 11/14/17, score = 147/3 = 49

Pour faire la distinction entre C ++ 11 et C ++ 14/17, il utilise la modification de la valeur par défaut constdes constexprfonctions membres en C ++ 14 (en citant l'exemple de https://stackoverflow.com/questions/23980929/ que-changes-introduit-en-c14-peut-potentiellement-casser-un-programme-écrit-en-c1 ). Pour distinguer C ++ 14 de C ++ 17, il utilise le fait que C ++ 17 a désactivé les trigraphes.

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

(Testé avec Debian gcc 7.1.0 avec -std=c++{11,14,17}.)

Daniel Schepler
la source
1
Super première réponse! Notez que vous pouvez jouer au golf les espaces entre les includeet <dans les déclarations comprennent, par exemple #include<iostream>.
MD XF
1
Hmm ... si les règles ont été révisées pour interdire l'utilisation de différences de bibliothèque standard (qui dans ce cas utilise indirectement la __cplusplusmacro) - puis pour distinguer le C ++ 17 du C ++ 14, je préférerais utiliser le changement de plage pour la sémantique. Peut-être créez-vous des classes minimales d'itérateurs / sentinelles de manière à boost::integer_iteratorce que la conversion de sentinelle en itérateur ait un comportement "surprenant".
Daniel Schepler
4
return 0;est implicite pour mainque vous puissiez économiser 9 octets ici. Toujours selon wc -cvotre solution, utilisez 251 octets et non 252 (votre éditeur peut avoir inséré une nouvelle ligne à la fin).
nwp
1
Il est probablement plus court d'utiliser le manque de trigraphes pour séparer c ++ 17 de c ++ 14
Potato44
1
Cela fonctionnerait-il? return *=>return*
Zacharý
19

EcmaScript 3/5/2015/2016/2017 dans le navigateur, 59 octets / 5 versions = 11,8 points

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

NetScape 7 report 3 et Opera 12 report 5

Économisez 1 octet grâce à GOTO 0

tsh
la source
1
Ninjaed ! ;)
Shaggy
Netscape 7 uniquement pris en charge ES3? Wow, il est plus vieux que je ne le pensais ...
Neil
1
Vous pouvez enregistrer quelques octets en utilisant -!plutôt que +!!là où cela a du sens (et modifier les constantes numériques en conséquence).
GOTO 0
3
Peut-être une explication? :)
Derek 會 功夫
@Derek: voir ma solution (lien ci-dessus) pour une explication.
Shaggy
18

JavaScript (ES5 et ES6), 14 octets / 2 versions = 7

alert(5^"0o3")

0oles constantes octales de style sont nouvelles dans ES6; ES5 lance la chaîne NaNsans affecter le résultat du bit XOR.

Neil
la source
13

JavaScript (ES 2, 3 & 5 - 8 9), 59/6 = 9,833 75/7 = 10,714

Vous pouvez également soumettre la solution avec plusieurs versions, même si votre version est légèrement supérieure à celle de la solution à 2 versions.

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

Essayez-le en ligne

Vérifie la présence de diverses méthodes dans les prototypes Array, RegExp & String, les nie en donnant un booléen et soustrait ce booléen d'une valeur initiale de 9. La multiplication des ![].mapcomptes pour le fait que ES4 a été abandonné.

  • La dotAllpropriété (et l' sindicateur associé ) des expressions régulières a été introduite dans ES2018 (v9).
  • La padEndméthode String a été introduite dans ES2017 (v8).
  • La includesméthode Array a été introduite dans ES2016 (v7).
  • La keysméthode Array a été introduite dans ES2015 (v6).
  • La mapméthode Array a été introduite dans ES5.1 (v5).
  • La popméthode Array a été introduite dans ES3 (v3).
Hirsute
la source
ES 7 ou ES 8 est-il un numéro de version valide? Peut-être devrait-il s'appeler comme ES 201x?
tsh
1
@tsh: Oui, ils utilisent toujours les numéros de version. ils utilisent simplement des années pour les noms réels .
Shaggy
9

PHP 5/7, score 5.5

<?=7-"0x2";

3V4L c'est en ligne!

PHP 5.3.9 / 5.3.11, score 10

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

3V4L c'est en ligne!

La version en ligne est plus longue car les anciennes versions de PHP sur le bac à sable ne disposent pas de balises courtes activées.

Sisyphe
la source
9

Befunge: 15 11 octets / 2 versions = 5.5

4 octets supprimés par @ Pietu1998

"89",;5-;,@  

Essayez-le en ligne:
Befunge 93
Befunge 98
Utilise l’opérateur de point-virgule exclusif à Befunge 98 («passer au point-virgule suivant») pour différencier les versions. Les deux vont imprimer "9". Befunge 93 ignorera les points-virgules, soustrayera 5 de "8" (valeur laissée en haut de la pile), imprimera le "3" résultant et se terminera. Befunge 98, d’autre part, sautera, imprimera "8" et se terminera.

karhell
la source
"89",;5-;,@pour 11 octets
PurkkaKoodari
@ Pietu1998 Nice! Si vous souhaitez poster cela comme réponse, je voterai avec plaisir :)
karhell
Allez-y et prenez-le si vous voulez, vous avez compris la ;pièce.
PurkkaKoodari
@ Pietu1998 Edited in. Merci beaucoup!
Karhell
Pour info, j'ai réussi à le réduire à 7 octets, en adoptant une approche différente. Lien
James Holderness
7

Pyth 4/5 - 6 octets / 2 versions = 3

  5 ;4

En Pyth 5, un nombre égal d’espaces au début de la ligne n’est pas utilisé pour l’indentation, alors qu’en Pyth 4, il agit simplement comme un seul espace et empêche l’impression 5. En Pyth 4, les points-virgules viennent juste de terminer les instructions, ce qui permet de les 4imprimer, alors qu'en Pyth 5, un espace et un point-virgule font du reste de la ligne un commentaire.

Maltysen
la source
11
Qui savait que Pyth avait des versions?
Erik the Outgolfer
7

Python 3 et Python 2.0, 18 octets, score 18/2 = 9

print(3-round(.5))

Arrondi de banquier en Python 3, arrondi standard en Python 2.

Essayez-le en ligne - Python 3!

Essayez-le en ligne - Python 2!

Stephen
la source
wow j'ai toujours vu des gens différencier python 2 et 3 par division
phuclv
@ LưuVĩnhPhúc well division is golfier, c'est pourquoi: P
Stephen
7

Cubiquement, 4 octets, score 4 /

B3%0

Fonctionne dans toutes les versions de votre système dispose de suffisamment de mémoire pour fonctionner. Non compétitif parce que c'est nul. Valable par cette meta post .

Fondamentalement, B3 fait pivoter une rangée de la face gauche vers la face supérieure. F3 fonctionnerait aussi bien que F3 ou B₁3. Dans Cubically 3x3x3, une rangée est composée de trois cubelets par un, ce qui en fait trois 1dans la face supérieure, ce qui lui donne une somme de %0faces de 3 .

Dans Cubically 4x4x4, les lignes sont 4x1 cubies. Met 4 1 dans la face supérieure, ce qui donne une somme de 4.

MD XF
la source
9
Le score ne devrait-il pas être 4 /?
nwp
7

Code machine x86 16/32/64 bits: 11 octets, score = 3,66

Cette fonction renvoie le mode actuel (taille d'opérande par défaut) sous forme d'entier dans AL. Appelez-le de C avec signatureuint8_t modedetect(void);

Liste code source + code machine NASM (montrant comment cela fonctionne en mode 16 bits, puisqu’il BITS 16demande à NASM d’assembler la mnémonique source pour le mode 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

Justification :

Le code machine x86 n'a pas officiellement de numéro de version, mais je pense que cela répond à l'intention de la question en obligeant à produire des nombres spécifiques, plutôt que de choisir ce qui est le plus pratique (cela ne prend que 7 octets, voir ci-dessous).

Le processeur x86 d'origine, Intel 8086, ne supportait que le code machine 16 bits. 80386 a introduit le code machine 32 bits (utilisable en mode protégé 32 bits, et plus tard en mode compat sous un système d'exploitation 64 bits). AMD a introduit le code machine 64 bits, utilisable en mode long. Ce sont des versions du langage machine x86 au sens où Python2 et Python3 sont des versions de langage différentes. Ils sont pour la plupart compatibles, mais avec des changements intentionnels. Vous pouvez exécuter des exécutables 32 ou 64 bits directement sous un noyau de système d'exploitation 64 bits de la même manière que vous pouvez exécuter des programmes Python2 et Python3.

Comment ça fonctionne:

Commence avec al=64. Déplacez-le vers la droite de 1 (mode 32 bits) ou de 2 (mode 16 bits).

  • 16/32 vs 64 bits: Les codages sur 1 octet inc/ decsont des préfixes REX en 64 bits ( http://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix ). REX.W n’affecte pas du tout certaines instructions (par exemple un jmpou jcc), mais dans ce cas, obtenir 16/32/64, je voulais augmenter ou diminuer ecxplutôt que eax. Cela définit également REX.B, ce qui change le registre de destination. Mais heureusement, nous pouvons y arriver, mais il n’est pas nécessaire de changer de format 64 bits al.

    Les instructions qui ne fonctionnent qu'en mode 16 bits pourraient inclure un ret, mais je n'ai pas trouvé cela nécessaire ou utile. (Et rendrait impossible l'intégration en tant que fragment de code, au cas où vous voudriez le faire). Cela pourrait aussi être un jmpélément de la fonction.

  • 16 bits contre 32/64: les versions immédiates sont 16 bits au lieu de 32 bits. Le changement de mode peut changer la longueur d'une instruction. Par conséquent, les modes 32/64 bits décodent les deux octets suivants dans le cadre de l'instruction immédiate plutôt que séparément. J'ai simplifié les choses en utilisant ici une instruction de 2 octets, au lieu d'obtenir un décodage désynchronisé afin que le mode 16 bits décode à partir de limites d'instruction autres que 32/64.

    Connexes: le préfixe d'opérande-taille modifie la longueur de l'immédiat (sauf s'il s'agit d'un émetteur 8 bits immédiat), comme la différence entre les modes 16 bits et 32/64 bits. Cela rend difficile le décodage de longueur d’instruction en parallèle; Les processeurs Intel ont des déconnexions LCP .


La plupart des conventions d'appel (y compris les psABI System V de x86-32 et de x86-64) autorisent des valeurs de retour étroites à laisser des ordures dans les bits élevés du registre. Ils permettent également de graver CX / ECX / RCX (et R8 pour 64 bits). IDK si cela était courant dans les conventions d’appel 16 bits, mais c’est du code golf, donc je peux toujours dire que c’est de toute façon une convention d’appel personnalisée.

Démontage 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    

Démontage 64 bits ( essayez-le en ligne! ):

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    

Connexe: mon Q & A code machine polyglotte x86-32 / x86-64 sur SO.

Une autre différence entre 16 bits et 32/64 est que les modes d'adressage sont codés différemment. Par exemple lea eax, [rax+2]( 8D 40 02) décode comme lea ax, [bx+si+0x2]en mode 16 bits. Ceci est évidemment difficile à utiliser pour le golf de code, en particulier depuis e/rbxet e/rsiest préservée dans les conventions d'appel.

J'ai également envisagé d'utiliser le 10 octets mov r64, imm64, qui est REX + mov r32,imm32. Mais comme j'avais déjà une solution de 11 octets, ce serait au mieux égal (10 octets + 1 pour ret).


Code de test pour les modes 32 et 64 bits. (Je ne l'ai pas réellement exécuté en mode 16 bits, mais le désassemblage vous indique comment il va décoder. Je n'ai pas configuré d'émulateur 16 bits.)

; 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

Ce programme Linux se termine avec exit-status = modedetect(), exécutez-le ainsi ./a.out; echo $?. Assemblez-le et associez-le à un binaire statique, par exemple

$ 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 octets (score = 2,33) si je peux numéroter les versions 1, 2, 3

Il n'y a pas de numéro de version officiel pour différents modes x86. J'aime juste écrire asm réponses. Je pense que cela violerait l'intention de la question si je venais d'appeler les modes 1, 2, 3, ou 1, 2, parce que le but est de vous obliger à générer un nombre incommode. Mais si cela était permis:

 # 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

Qui décode en mode 32 bits en tant que

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

et 64 bits comme

00000000004000a0 <detect123>:
  4000a0:       b8 03 00 fe c8          mov    eax,0xc8fe0003
  4000a5:       48 c3                   rex.W ret 
Peter Cordes
la source
Je ne suis pas sûr que cela compte comme des versions différentes . Ne sont-ils pas simplement corrélés à différentes configurations de système?
Uriel
1
@Uriel: L'exécution d'un bloc de code machine avec la CPU en mode 16 bits, 32 bits ou 64 bits correspond à l'équivalent code-machine de l'exécution python2et des python3interpréteurs du même programme Python. Les nouveaux processeurs x86 incluent toujours un mode compatible avec les processeurs plus anciens (ceci est leur seule excuse pour utiliser un format de code machine aussi complexe et difficile à décoder!), Mais le mode protégé 326 de 386 et le mode long de x86-64 sont vraiment nouvelles versions du code machine x86. Le mode long a même supprimé certains opcodes, les rendant invalides.
Peter Cordes
5

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

2,1hw

Essayez-le en ligne! (Brachylog)

Essayez-le en ligne! (Brachylog v1)

Explication pour 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)

Explication pour 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 l'Outgolfeur
la source
Génial! En résumé, 2,1dans Brachylog v2 ne construit pas la liste [2,1]( 2;1serait), mais plutôt le nombre 21(ce qui ne change pas la façon dont vous vouliez que votre réponse fonctionne).
Fataliser
@Fatalize Ooh merci, j'ai confondu cela avec Jelly ...
Erik the Outgolfer
@Fatalize BTW 2;1n'aurait pas fonctionné dans Brachylog v1 comme ;moyen OU logique.
Erik the Outgolfer
5

C89 / C99, 25 octets, 2 versions, score = 12,5

#include <stdio.h>

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

// Les commentaires de style ne sont pas reconnus dans C89.

Version golfée:

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

Essayez-le en ligne: C89 , C99

Nwellnhof
la source
remplace int v()par main(), il est plus court et compilera comme un programme complet!
Andrea
@Andrea Merci. Autant que je sache, il est autorisé à poster des fonctions ou des programmes entiers.
nwellnhof
Vous avez raison.
Andrea
5

Perl 5 et Perl 6, 23 octets 19 octets, score de 9,5

print 6-grep '.',''

Perl 5 grepfirst op est toujours traité comme une regex, ce qui n’est pas le cas dans Perl 6.

Josué
la source
Le score est de 19/2 = 9,5
Daniel Vestøl
5

Bash, toutes les 4 versions, 72 71 32 octets ⇒ score = 8

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

Ce morceau de code utilise différentes interprétations des $'...'chaînes dans chaque version de Bash.
Affiche le numéro de version majeur - et c'est tout.

Doc trouvé ici .

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

Cette réponse est à moitié une conjecture; Je ne l'ai testé que dans les versions 4 et 3, mais cela devrait également fonctionner sur d'autres versions.

Faites-moi savoir si cela ne fonctionne pas, j'essaierai avec d'autres versions dès que je les aurai disponibles.

-1 car grâce à Jens.
-29 octets grâce à Digital Trauma (toute l' expridée)!

joH1
la source
La grammaire shell ne nécessite pas de ;;dans la dernière alternative. Utilisez ;pour supprimer un octet.
Jens
1
Je viens d'essayer cela sur bash-2.05a (compilé pour Cygwin), et il indique à tort "3", et non "2" :(
Jason Musgrove
1
la $'\xNfonctionnalité d' interprétation semble avoir été ajoutée à la version 2.01.1 ... Je vais devoir mettre à jour ma réponse. Travailler dessus
joH1
puis-je vous demander d'essayer cela? s="$'\ua\xa\n'";case ${#s} in 3)echo 4;;5)echo 3;;7)echo 2;;9)echo 1;esac
joH1
1
Vous pourriez être en mesure de jouer au golf à quelque chose comme s=$'\ua\xa\n';expr 5 - ${#s} / 2. Cela fonctionne sur v3 et v4. Je n'ai pas d'anciennes versions fonctionnelles à essayer pour le moment.
Trauma numérique
4

R, versions 2 et 3, score: 10,5 points

cat(exists("cite")+2)

Cette commande renvoie 2pour R 2.xx et 3pour R 3.xx. La fonction a citeété ajoutée dans la version R 3.0.0. Par conséquent, la commande exists("cite")retourne FALSEpour R 2.xx et TRUEpour R 3.xx

R, toutes les versions (1, 2 et 3), score: 12⅓ points

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

La fonction a eapplyété introduite dans R 2.0.0.

Sven Hohenstein
la source
R.version$major. 15 caractères. Je pas depuis quand il existe.
Rui Barradas
@RuiBarradas Permettez-moi de citer l'OP: " Votre programme ne peut pas utiliser d'indicateurs de compilateur intégré, de macro ou personnalisé pour déterminer la version du langage. "
Sven Hohenstein
Ok, désolé, j'ai raté cette partie. Dois-je supprimer le commentaire?
Rui Barradas
@RuiBarradas Pas de problème. Vous n'avez pas besoin de supprimer le commentaire.
Sven Hohenstein
Vous devez gérer l’impression du résultat. Actuellement, lorsqu'il est exécuté en tant que programme complet, cela n'imprime rien.
JAD
4

Python , 196 octets / 16 versions = note 12,25

Les versions sont 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 et 3.6
Malheureusement, j'ai dû laisser de côté 2.7 car il n'y a pas de modules dans pour autant que je sache, elles ne sont pas dans la version 2.6 mais dans la version 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.)

Nous parcourons un tas de modules introduits dans différentes versions de python et, à la première erreur, nous quittons et renvoyons la version. Les écarts entre les versions principales sont comblés par une importation répétée os. Le test pour python 1.5 repose sur le fait de string.splitne pas être présent avant le 1.6.

Merci à Olivier Grégoire pour son idée de tester en boucle de nouvelles classes / modules.

J'ai enfin enfin testé sur toutes les versions pertinentes de python ... ce qui nécessitait l'édition du code source 1.5 pour le compiler ...

g.rocket
la source
4

Fichier de commandes Windows , 35 octets / 2 versions = score 17.5

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

Imprime DOSsur MS-DOS (duh) et NTsur Windows NT. (duh)

Maintenant, pour quelques explications.

Windows a eu des scripts de commandes par lots depuis les temps MS-DOS et il n'a pas beaucoup changé depuis. Toutefois, lorsque Windows NT est venu, Microsoft a changé l'interpréteur par défaut pour les scripts de traitement par lots, à partir COMMAND.COMde cmd.exe(maintenant en permettant l'extension .cmdcomme une alternative à l'original.bat ).

Avec cela, ils ont également implémenté quelques modifications , telles que l' /iindicateur permettant d'ignorer la casse de chaîne sur les conditions. C’est-à-dire qu’il Z==zest faux, qu’il /i Z==zest vrai.

Nous exploitons le fait que DOS n’a pas insensible à la casse et comparons les majuscules Zaux minuscules z. En utilisant le /idrapeau, on se retrouve avec une Z==z(fausse) condition sous DOS etz==z (vrai) sous NT.

Maintenant, je me rends compte que le challenge spécifie qu'un numéro de version doit être imprimé. Mais, autant que je sache, il n’existe pas de «numéro de version» pour le traitement par lots, c’est donc le plus proche que je puisse obtenir.


Testé sur Windows 10, DOSBox et vDos:

Windows 10:

Windows 10

(courir avec cmd /kpour fermer la fenêtre exit)

DOSBox:

DOSBox

vDos:

vDos

Matheus Avellar
la source
Windows 7est plus court que Windows NT.
user202729
2
@ user202729 Je suppose, mais encore une fois, ce 7n'est pas vraiment une version linguistique, c'est la même chose sous Windows 'depuis 3.1. Donc, je ne pensais pas qu'il serait très juste d'appeler ça 7quand ça devrait peut-être même être3.1
Matheus Avellar
3

Wolfram Language / Mathematica 10/11, 37 octets / 2 versions = 18,5

Considérez (Length@DateRange[{1},{1}][[1]]+27)/3, à 37 octets et travaillant avec 2 versions, me donne une note 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

et

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

Je suis sûr qu'il existe un moyen plus efficace, mais la divergence entre la sortie DateRange m'a mordu à la fesses récemment, donc j'étais prêt à l'utiliser.

En guise de suivi, quelqu'un pourrait probablement tirer parti de l' Length@DateRange[{1}, {1}][[1]]évaluation 1dans les versions 1 à 8 de Mathematica, mais je n'ai pas eu le temps de l'intégrer.

utilisateur6014
la source
2
Assez sûr que votre réponse ne répond pas aux exigences de l'invite, à savoir la dernière règle en raison de votre utilisation $Version:Your program may not use a builtin, macro, or custom compiler flags to determine the language version.
Amndeep7
7
J'utilise seulement $Versionpour démontrer que le résultat correct $Versionest
affiché
Tout bon ami - le truc, c'est que vous utilisez quelque chose du genre $VersionNumber, mais vous l'appelez plutôt $Version. À mon sens, même si la Length@DateRangesubstance de votre programme est essentielle, cela ne fonctionnerait pas $Versionuniquement en fournissant les informations de version complètes que vous traitez ensuite, ce qui enfreint donc les règles.
Amndeep7
4
@ Amndeep7 La soumission est le code de 37 octets inséré dans le premier paragraphe. Les blocs de code ne sont que des démonstrations de sortie.
PurkkaKoodari
3
Explication: Utilisation d'un format d'heure différent selon les versions. Cela peut être joué plus à {1} Tr[1^#&@@%~DateRange~%]/3+9(31 octets), ou même 7+Length@Now(12 octets)
user202729
3

Ruby 1.x et 2.x, 20 octets, score de 10

p [].to_h&&2rescue 1

Basé sur la to_hméthode qui a été introduite sur la Arrayclasse dans Ruby 2.

Philipp Frank
la source
Belle première réponse. Je n'ai pas de test 1.x à tester, mais p [].to_h&&2rescue 1est un peu plus court.
manatwork
@manatwork Great, économise 3 octets et fonctionne à merveille
Philipp Frank
3

Erlang, 180 octets, 11 versions, score 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)]]).

Avec indentation et sauts de ligne:

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

Testé sur une version mineure de chaque version majeure depuis 10:

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

L'idée est que chaque version majeure a ajouté au moins un nouvel argument autorisé pour la fonction erlang:system_info. Essayons donc ceux de la liste, comptons le nombre de ceux qui échouent et soustrayons le nombre d'échecs de 20, qui est la version actuelle.

legoscia
la source
3

Julia 0.4, 0.5, 46 octets, score 22

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

Julia a modifié le nom de type des types de chaîne concrets et abstraits dans de nombreuses versions.

Ce code profite notamment de:

Julia 0.4 :

  • Le béton est ASCIIString,
  • Résumé est officiellement AbstractString,
  • Abstract a déconseillé d'utiliser un alias String.
  • Le concret est plus spécifique que l’abstrait et gagne donc l’envoi

Julia 0.5 :

  • Le béton est officiellement String,
  • Concrete a déconseillé le pseudonyme pour ASCIIString,
  • Le résumé est AbstractString(bien que cela ne soit pas important ici)
  • Comme deux méthodes ont été définies pour le type de chaîne en béton, la dernière remplace la première.

Voir aussi ma nouvelle solution plus efficace basée sur différents principes

Lyndon White
la source
3

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

'1r\S2

Test v1  |   Test v2

  • 2 octets économisés grâce à Oliver

Explication

Avant la v2, Japt utilisait une syntaxe RegEx personnalisée. Nous pouvons donc en tirer parti.

'1

Le nombre 1 sous forme de chaîne.

 r  2

Remplacez ( r) le ci-dessous par un 2.

\S

Japt 2 voit cela comme le RegEx /\S/g, qui correspond à la 1. Japt 1 ignore le \caractère d'échappement et voit juste la Squi est la constante de Japt pour un caractère d'espace et, évidemment, ne correspond pas à la 1.

Hirsute
la source
3

Befunge, score = 3.5

7 octets, 2 versions

"]"'b.@

Essayez-le en ligne dans Befunge-93
Essayez-le en ligne dans Befunge-98

"]"est un littéral de chaîne dans les deux versions, poussant 93 (la valeur ASCII de [) sur la pile. 'best un caractère littéral dans Befunge-98, poussant 98 (la valeur ASCII de b), mais il s’agit d’instructions non valides dans Befunge-93, elles sont donc simplement ignorées. On termine donc avec 93 au sommet de la pile dans Befunge-93 et ​​98 dans Befunge-98. .@écrit la valeur en haut de la pile puis quitte.

James Holderness
la source
]"[email protected]'ou ][email protected]'aussi travailler
MildlyMilquetoast
3

Ruby 1.x (<1.9) et 2.x, 10 8 octets, score = 4

$><<?2%7

Essayez le:

Cela fonctionne en exploitant les différents comportements de ?xRuby 1.x et 2.x. En Ruby 1.x, ?A(par exemple) renvoie 65(la valeur ASCII du caractèreA ), mais en Ruby 2.0, il renvoie la chaîne d'un caractère "A".

Le code ci-dessus est équivalent à ceci:

val = ?2
$> << val % 7

En Ruby 1.x (<1.9), la valeur de valis 50(la valeur ASCII du caractère 2), un Fixnum. Fixnum#%est l'opérateur modulo, donc50 % 7 renvoie1 .

En Ruby 2.x, valc'est la chaîne "2". String#%est une version infixe de sprintf, "2" % 7équivaut donc à sprintf("2", 7), où "2"est la chaîne de format. Comme la chaîne de format ne contient aucune séquence de format (par exemple%d ), les arguments suivants sont ignorés et "2"sont renvoyés.

Enfin, $>est un alias pour $stdout, donc $> << ...affiche le résultat.

Jordan
la source
1
Ooh bien! J'essayais de faire quelque chose comme ?A==66?1:2avant que je tombe sur votre réponse
Piccolo
3

Python 2 et Python 3 , 36 34 octets, score de 18 17

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

En Python 2 , le hachage de l'infini négatif est -271828 mais en Python 3, il s'agit de -314159. Edit: 2 octets enregistrés, 1 point de score, grâce à @ArBo.

Neil
la source
fouines Est - ce une chose e vs pi délibérée?
Jo King
@JoKing Oui; apparemment, quand a hashété corrigé pour la première fois pour travailler sur des infinis à virgule flottante, le développeur concerné a utilisé pi * 1e5 et e * -1e5 comme valeurs de hachage. À un moment donné dans Python 3, la valeur has de l'infini négatif a été changée pour devenir la négation de la valeur de hachage pour l'infini.
Neil
2

Python 3 , Python 2 , score 17,5

(35 octets, 2 versions)

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

Python 2 , 35 octets

Essayez-le en ligne!

Python 3 , 35 octets

Essayez-le en ligne!

5 octets sauvés grâce à ETHproductions

Pas une bonne réponse au golf, mais un changement énorme!

jferard
la source
Hmm, pouvez-vous mettre chaque déclaration sur la ligne précédente? Ietry:exec("print 2")\nexcept:print(3)
ETHproductions
@ETHproductions merci! Je ne m'attendais pas à gagner, donc j'étais un peu distrait. Je voulais principalement me concentrer sur le changement massif entre Python 2 et 3.
jferard