Determina la versione della tua lingua


51

La tua sfida è scrivere un poliglotta che funzioni in diverse versioni della tua lingua. Quando eseguito, emetterà sempre la versione della lingua.

Regole

  • Il tuo programma dovrebbe funzionare in almeno due versioni della tua lingua.
  • L'output del tuo programma dovrebbe essere solo il numero di versione. Nessun dato estraneo.
  • Il tuo programma può utilizzare qualsiasi metodo ti piaccia per determinare il numero di versione. Tuttavia, l'output deve seguire la regola 2; tuttavia si determina il numero di versione, l'output deve essere solo il numero.
  • Il tuo programma deve solo produrre la versione principale della lingua. Ad esempio, in FooBar 12.3.456789-beta, il tuo programma dovrebbe solo produrre 12.
  • Se la tua lingua inserisce parole o simboli prima o dopo il numero di versione, non è necessario emetterli e solo il numero. Ad esempio, in C89, il tuo programma deve solo stampare 89e in C ++ 0x, il tuo programma deve solo stampare 0.
  • Se si sceglie di stampare il nome completo o i numeri di versione minori, ad es. C89 anziché C99, deve solo stampare il nome. C89 build 32è valido, mentre error in C89 build 32: foo barnon lo è.
  • Il programma non può utilizzare un flag di compilatore incorporato, macro o personalizzato per determinare la versione della lingua.

punteggio

Il tuo punteggio sarà la lunghezza del codice diviso per il numero di versioni in cui funziona. Il punteggio più basso vince, buona fortuna!


4
Che cos'è un numero di versione della lingua? Chi lo determina?
Mago del grano

9
Penso che l'inverso-lineare nel numero di versione non accetti le risposte con un alto numero di versioni.
user202729

6
@ user202729 Sono d'accordo. Versatile Integer Printer ha fatto bene - il punteggio è stato (number of languages)^3 / (byte count).
Mego

6
Qual è la versione per una lingua ? Non definiamo qui una lingua come suoi interpreti / compilatori ? Diciamo che esiste una versione di gcc che ha un bug che con alcuni codici C89 produce un eseguibile il cui comportamento viola la specifica C89 ed è stato corretto sulla prossima versione di gcc. Questo dovrebbe contare una soluzione valida se scriviamo un pezzo di codice su questo comportamento di bug per dire quale versione di gcc sta usando? Si rivolge a versioni diverse del compilatore , ma NON a versioni diverse del linguaggio .
TSH

6
Non capisco. Per prima cosa dici "L'output del tuo programma dovrebbe essere solo il numero di versione". . Quindi dici "Se scegli di stampare il nome completo o i numeri di versione minori, ad esempio C89 anziché C99, deve solo stampare il nome". Quindi la prima regola non è in realtà un requisito?
pipe

Risposte:


16

Seriamente e in realtà , 3 byte, punteggio 1,5

'1u

Provalo online: in realtà , sul serio

Spiegazione:

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

ue Davere funzionalità sulle stringhe è stato aggiunto solo in Actually (che è Seriamente v2).


3
README.md di Actually afferma che Actually è il successore spirituale di Seriously. Per me non sembra un semplice cambio di versione.
Adám,

7
@ Adám Se guardi i rami nel repository, risiede seriamente nel v1ramo. Prima di essere seriamente deprecato, risiedeva effettivamente nella v2filiale. Inoltre, 1.xnelle versioni ha usato seriamente i numeri di versione , mentre attualmente utilizza 2.x(sia lì che su PyPI ).
Mego

115

Python 3.0 e Python 2, punteggio 6

(12 byte, 2 versioni)

print(3/2*2)

Provalo online:

Si basa sul fatto che Python 3+ utilizza la divisione float per impostazione predefinita, a differenza di Python 2, che utilizza la divisione floor.


@MaltySen Your program should work in at least two versions of your language.Funziona nelle almeno due versioni 2.7 e 3.0. Ho scelto to print the full name or minor version numbers.
fireflame241

Oh capisco, mio ​​male.
Maltysen,

4
OH MIO DIO! Poveri sviluppatori di pitone
Regis Portalez,

4
@RegisPortalez from __future__ import division, problema risolto :)
Łukasz Rogalski

62

Java, 189 byte, 10 versioni, punteggio = 18,9

Le versioni supportate: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8e9

(Per i punteggi precedenti, controlla la cronologia !)

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

Eseguilo su Java 8
Eseguilo su Java 9 o versioni successive

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

Si noti che la parte di codice return v<9?"1."+v:v;(in precedenza return(v<9?"1.":"")+v;) deve essere verificata rispetto a qualsiasi versione tra Java 1.0 e Java 1.3 inclusa. Non ho alcuna installazione Java 1.3 o precedente a mia disposizione per testare effettivamente questa sintassi.

introduzione

Il versioning Java ha una storia speciale. Tutte le versioni sono state storicamente 1.xincluse 1.0. Ma ... da Java 9 in poi e JEP223 , lo schema della versione è cambiato dall'uso 1.xa x. Questa è la versione conosciuta internamente. Quindi abbiamo la seguente tabella (messa insieme a Javadoc e 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

Questa voce della sfida corrisponde alla colonna della versione nella tabella sopra, che è ciò che è contenuto nella proprietà di sistema "java.version".

Spiegazione

L'obiettivo è verificare da quale versione inizia a esistere una classe, poiché Java deprecava il codice ma non lo rimuove mai. Il codice è stato specificamente scritto in Java 1.0 per essere compatibile con tutte le versioni, anche perché JDK è (principalmente) compatibile con il forward della sorgente .

L'implementazione tenta di trovare i nomi di classe più brevi introdotti da ciascuna versione. Tuttavia, per guadagnare byte, è necessario provare a scegliere un pacchetto secondario comune. Finora ho scoperto che il pacchetto più efficiente è java.utilperché contiene diverse classi con nomi molto brevi sparsi su tutte le versioni di Java.

Ora, per trovare il numero di versione effettivo, i nomi delle classi vengono ordinati introducendo la versione. Quindi provo a istanziare sequenzialmente ogni classe e ad aumentare l'indice di array. Se la classe esiste, passiamo alla successiva, altrimenti lasciamo catturare l'eccezione dal tryblocco-. Al termine, viene generata un'altra eccezione perché non ci sono più classi di cui è necessario verificare l'esistenza.

In ogni caso, il thread lascerà il tryblocco con un'eccezione. finallyQuell'eccezione non viene colta, ma semplicemente messa in attesa grazie al blocco, che a sua volta sovrascrive l'eccezione in attesa restituendo effettivamente un valore che è "1."+vdove vè l'indice usato prima. Succede anche che questo indice corrisponda al numero di versione minore di Java.

Una parte importante del golf era trovare il nome della nuova classe più breve nel pacchetto java.util(o qualsiasi pacchetto per bambini) per ogni versione. Ecco la tabella che ho usato per calcolare quel costo.

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

Crediti

  • 30 byte salvati grazie a Kevin Cruijssen (anche se lo stavo facendo prima di leggere il suo commento, lo prometto!).
  • Altri 26 byte salvati grazie a Neil (no, non stavo pensando di farlo)
  • 12 byte grazie alla Nevay e la bella out-of-the -box pensare, provare catture!
  • Ancora 11 byte di Neil e il bel finallytrucco portatile .
  • 2 byte in più grazie a Kevin Cruijssen sostituendolo return(i<9?"1.":"")+i;con return i<9?"1."+i:i;(questo deve essere convalidato contro 1.0 o al massimo 1.3 poiché non si sono verificate modifiche alla sintassi prima di 1.4)

Con builtin

Se i builtin fossero consentiti:

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

54 byte per 13 versioni (da 1.0 a 12), quindi il punteggio sarebbe 4.1538.


1
@KevinCruijssen Ho aperto javadoc e ho tenuto lezioni con nomi brevi 1 per 1. Ma ... Sono stato aiutato un po 'da questa pagina: docs.oracle.com/javase/8/docs/technotes/guides/lang/…
Olivier Grégoire,

1
260 byte O forse 1 in più, non so se return"...è possibile senza spazio in tutte le versioni tbh.)
Kevin Cruijssen

1
235 byte: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 byte: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, mi sono meravigliato di iterare un array e catturare un'eccezione, ma puoi andare ancora meglio finally{return"1."+i;}.
Neil,

22

Python , 606 byte / 15 versioni = punteggio 40,4

-67 byte (lol) grazie a NoOneIsHere.

Le versioni sono 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)

Tutto il merito della straordinaria risposta di Sp3000 . La nuova riga finale è necessaria.

Whee, è stato divertente giocare a golf. Dovrebbe funzionare (sì, ho installato ognuna di queste versioni), ma potrei aver accidentalmente bloccato qualcosa. Se qualcuno trova un bug, per favore fatemelo sapere.



... Oh, non c'è da stupirsi. Mi chiedevo perché Sp3000 ha messo le parentesi in ogni printchiamata ... Grazie per avermelo fatto notare!
totalmente umano il

2
È possibile salvare 68 byte rimuovendo i tipi specifici di errori (sostituire tutti excepti messaggi con except:).
NoOneIsHere

x=<string inside eval>Funzionerebbe comunque se lo facessi invece di valutare manualmente il codice?
Blu,

@NoOneIsHere all'inizio ho pensato che non potevi farlo per via di tutto 1/0, ma poi ho capito. Grazie!
totalmente umano il

21

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

Per distinguere tra C ++ 11 e C ++ 14/17, utilizza la modifica nell'integrità constdelle constexprfunzioni membro in C ++ 14 (con credito all'esempio su https://stackoverflow.com/questions/23980929/ cosa-cambia-introdotto-in-c14-può-potenzialmente-rompere-un-programma-scritto-in-c1 ). Per distinguere tra C ++ 14 e C ++ 17, utilizza il fatto che C ++ 17 disabilita le trigrafi.

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

(Testato con Debian gcc 7.1.0 usando -std=c++{11,14,17}.)


1
Ottima prima risposta! Si noti che è possibile giocare a golf tra gli spazi tra includee le <istruzioni include, ad esempio #include<iostream>.
MD XF,

1
Hmm ... se le regole fossero state riviste per proibire l'uso delle differenze di libreria standard (che in questo caso usa indirettamente la __cplusplusmacro) - allora per distinguere C ++ 17 da C ++ 14 mi spingerei ad usare la modifica in base all'intervallo per la semantica. Forse creare classi di iteratore / sentinella minime seguendo le linee in modo boost::integer_iteratortale che la conversione di sentinella in iteratore abbia un comportamento "sorprendente".
Daniel Schepler,

4
return 0;è implicito per maincui è possibile salvare 9 byte lì. Inoltre, secondo la wc -ctua soluzione, stai usando 251 byte e non 252 (il tuo editor potrebbe aver inserito una nuova riga alla fine).
nwp,

1
Probabilmente è più breve usare la mancanza di trigrafi per separare c ++ 17 da c ++ 14
Potato44

1
Funzionerebbe? return *=>return*
Zacharý,

19

EcmaScript 3/5/2015/2016/2017 nel browser, 59 byte / 5 versioni = 11,8 punti

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

Rapporto 3 di NetScape 7 e rapporto di Opera 12 5

Risparmia 1 byte grazie a GOTO 0


1
Ninjaed ! ;)
Shaggy

Netscape 7 supportava solo ES3? Wow, è più vecchio di quanto pensassi ...
Neil,

1
È possibile salvare alcuni byte utilizzando -!invece di +!!dove ha senso (e modificare le costanti numeriche di conseguenza).
GOTO 0

3
Forse qualche spiegazione? :)
Derek 朕 會 功夫 il

@Derek: vedi la mia soluzione (linkato sopra) per una spiegazione.
Shaggy,

18

JavaScript (ES5 ed ES6), 14 byte / 2 versioni = 7

alert(5^"0o3")

0ole costanti ottali in stile sono nuove in ES6; ES5 lancia la stringa a NaNcui non influisce sul risultato dell'XOR bit a bit.


13

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

Può anche inviare la soluzione con più versioni, anche se ha un punteggio leggermente superiore rispetto alla soluzione a 2 versioni.

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

Provalo online

Verifica la presenza di vari metodi nei prototipi Array, RegExp e String, li annulla, fornendo un valore booleano e sottraendo valori booleani da un valore iniziale di 9. La moltiplicazione dei ![].mapconti per il fatto che ES4 è stato abbandonato.

  • La dotAllproprietà (e il relativo sflag) per le espressioni regolari è stata introdotta in ES2018 (v9).
  • Il padEndmetodo String è stato introdotto in ES2017 (v8).
  • Il includesmetodo Array è stato introdotto in ES2016 (v7).
  • Il keysmetodo Array è stato introdotto in ES2015 (v6).
  • Il mapmetodo Array è stato introdotto in ES5.1 (v5).
  • Il popmetodo Array è stato introdotto in ES3 (v3).

ES 7 o ES 8 è un numero di versione valido? Forse dovrebbe essere chiamato come ES 201x?
TSH

1
@tsh: Sì, usano ancora i numeri di versione; usano solo anni per nomi realesi .
Shaggy,

9

PHP 5/7, punteggio 5,5

<?=7-"0x2";

3V4L online!

PHP 5.3.9 / 5.3.11, punteggio 10

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

3V4L online!

La versione online è più lunga perché le vecchie versioni di PHP sulla sandbox non hanno tag brevi abilitati.


9

Befunge: 15 11 byte / 2 versioni = 5,5

4 byte eliminati da @ Pietu1998

"89",;5-;,@  

Provalo online:
Befunge 93
Befunge 98
Utilizza l'operatore punto e virgola esclusivo di Befunge 98 ("passa al punto e virgola successivo") per differenziare le versioni. Entrambi stamperanno "9". Befunge 93 ignorerà i punti e virgola, sottrarrà 5 da "8" (valore lasciato in cima alla pila), stamperà il risultante "3" e terminerà. Befunge 98 invece, salterà, stampa "8" e termina.


"89",;5-;,@per 11 byte
PurkkaKoodari il

@ Pietu1998 Nice! Se vuoi pubblicarlo come risposta, sarò lieto di votare :)
Karhell il

Vai avanti e prendilo se vuoi, hai capito la ;parte.
PurkkaKoodari,

@ Pietu1998 A cura di. Molte grazie!
karhell,

Cordiali saluti, sono riuscito a farlo scendere a 7 byte, adottando un approccio diverso. Link
James Holderness,

7

Pyth 4/5 - 6 byte / 2 versioni = 3

  5 ;4

In Pyth 5, una quantità uniforme di spazi all'inizio della riga viene ignorata per l'uso nel rientro, mentre in Pyth 4 agisce come un singolo spazio e impedisce di stampare il file 5. In Pyth 4, i punti e virgola terminano le istruzioni, il che consente 4di stamparli, mentre in Pyth 5, uno spazio e un punto e virgola rendono il resto della riga un commento.


11
Chi sapeva che Pyth aveva delle versioni?
Erik the Outgolfer


7

Cubicamente, 4 byte, punteggio 4 / ∞

B3%0

Funziona in ogni versione del tuo sistema ha memoria sufficiente per l'esecuzione. Non competitiva perché è zoppa. Valido per questo meta post .

Fondamentalmente, B3 ruota di una riga dalla faccia sinistra alla faccia superiore. F3 funzionerebbe altrettanto bene, così come F₁3 o B₁3. Dato che una riga in Cubically 3x3x3 è composta da tre cubelet per uno cubelet, questo ne mette tre 1nella faccia superiore, dandogli una somma di 3. %0facce che stampa la somma della faccia superiore, stampando 3 per Cubically 3 x3x3.

In Cubically 4x4x4, le righe sono cubi 4x1. Mette 4 1 nella faccia superiore, ottenendo una somma di 4.


9
Il punteggio non dovrebbe essere 4 / ∞?
nwp,

7

codice macchina x86 16/32/64-bit: 11 byte, punteggio = 3,66

Questa funzione restituisce la modalità corrente (dimensione dell'operando predefinita) come numero intero in AL. Chiamalo da C con firmauint8_t modedetect(void);

Codice macchina NASM + elenco dei sorgenti (che mostra come funziona in modalità a 16 bit, poiché BITS 16dice alla NASM di assemblare i mnemonici di origine per la modalità a 16 bit.)

 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

Giustificazione :

Il codice macchina x86 non ha ufficialmente numeri di versione, ma penso che questo soddisfi l'intento della domanda dovendo produrre numeri specifici, piuttosto che scegliere ciò che è più conveniente (che richiede solo 7 byte, vedi sotto).

La CPU x86 originale, Intel 8086, supportava solo il codice macchina a 16 bit. 80386 ha introdotto il codice macchina a 32 bit (utilizzabile in modalità protetta a 32 bit, e successivamente in modalità compatibile con un sistema operativo a 64 bit). AMD ha introdotto il codice macchina a 64 bit, utilizzabile in modalità lunga. Queste sono versioni del linguaggio macchina x86 nello stesso senso in cui Python2 e Python3 sono versioni linguistiche diverse. Sono per lo più compatibili, ma con cambiamenti intenzionali. È possibile eseguire eseguibili a 32 o 64 bit direttamente in un kernel del sistema operativo a 64 bit nello stesso modo in cui è possibile eseguire i programmi Python2 e Python3.

Come funziona:

Inizia con al=64. Spostalo a destra di 1 (modalità 32 bit) o ​​2 (modalità 16 bit).

  • 16/32 vs. 64 bit: I 1 byte inc/ deccodifiche sono prefissi REX in 64 bit ( http://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix ). REX.W non ha alcun effetto su alcune istruzioni (ad es. A jmpo jcc), ma in questo caso per ottenere il 16/32/64 volevo aumentare o diminuire ecxpiuttosto che eax. Anche questo imposta REX.B, che cambia il registro di destinazione. Ma per fortuna possiamo farlo funzionare ma impostando le cose in modo che 64-bit non debbano cambiare al.

    Le istruzioni che funzionano solo in modalità a 16 bit potrebbero includere a ret, ma non l'ho trovato necessario o utile. (E renderebbe impossibile inline come un frammento di codice, nel caso volessi farlo). Potrebbe anche essere un jmpall'interno della funzione.

  • 16 bit vs. 32/64: gli immediati sono 16 bit anziché 32 bit. La modifica delle modalità può modificare la lunghezza di un'istruzione, quindi le modalità a 32/64 bit decodificano i due byte successivi come parte dell'istruzione immediata, anziché come un'istruzione separata. Ho mantenuto le cose semplici usando un'istruzione a 2 byte qui, invece di ottenere la decodifica fuori sincrono in modo che la modalità a 16 bit decodificasse da limiti di istruzione diversi rispetto a 32/64.

    Correlati: il prefisso della dimensione dell'operando modifica la lunghezza dell'immediato (a meno che non sia un immediato esteso a 8 bit con segno), proprio come la differenza tra le modalità a 16 bit e 32/64-bit. Ciò rende difficile la decodifica in lunghezza delle istruzioni in parallelo; Le CPU Intel hanno stalle di decodifica LCP .


La maggior parte delle convenzioni di chiamata (inclusi gli psabi System V x86-32 e x86-64) consentono a valori di ritorno ristretti di avere immondizia nei bit alti del registro. Consentono inoltre di clobbering CX / ECX / RCX (e R8 per 64 bit). IDK se questo era comune nelle convenzioni di chiamata a 16 bit, ma questo è il golf del codice, quindi posso sempre solo dire che è comunque una convenzione di chiamata personalizzata.

Smontaggio a 32 bit :

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    

Smontaggio a 64 bit ( provalo 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    

Correlati: domande e risposte sul mio codice macchina poliglotta x86-32 / x86-64 su SO.

Un'altra differenza tra 16 bit e 32/64 è che le modalità di indirizzamento sono codificate in modo diverso. es. lea eax, [rax+2]( 8D 40 02) decodifica come lea ax, [bx+si+0x2]nella modalità a 16 bit. Questo è ovviamente difficile da usare per il code-golf, soprattutto perché e/rbxe e/rsisono conservati in molte convenzioni di chiamata.

Ho anche considerato l'utilizzo del 10 byte mov r64, imm64, che è REX + mov r32,imm32. Ma dal momento che avevo già una soluzione a 11 byte, questo sarebbe nella migliore delle ipotesi uguale (10 byte + 1 per ret).


Codice di test per modalità 32 e 64 bit. (In realtà non l'ho eseguito in modalità a 16 bit, ma lo smontaggio ti dice come verrà decodificato. Non ho un emulatore a 16 bit impostato.)

; 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

Questo programma Linux esce con exit-status = modedetect(), quindi eseguilo come ./a.out; echo $?. Montalo e collegalo in un binario statico, ad es

$ 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 byte (punteggio = 2,33) se posso numerare le versioni 1, 2, 3

Non ci sono numeri di versione ufficiali per diverse modalità x86. Mi piace solo scrivere risposte. Penso che violerebbe l'intento della domanda se avessi appena chiamato le modalità 1,2,3 o 0,1,2, perché il punto è costringerti a generare un numero scomodo. Ma se ciò fosse permesso:

 # 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

Che decodifica in modalità 32 bit come

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

e 64 bit come

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

Non sono sicuro che contano come versioni diverse . Non si limitano a correlare a diverse configurazioni di sistema?
Uriel,

1
@Uriel: l'esecuzione di un blocco di codice macchina con la CPU in modalità 16-bit, 32-bit o 64-bit è l'equivalente in codice macchina dell'esecuzione python2rispetto agli python3interpreti sullo stesso programma Python. Le nuove CPU x86 includono sempre una modalità compatibile con le CPU più vecchie (questa è la loro unica scusa per utilizzare un formato di codice macchina così difficile da decodificare!), Ma la modalità protetta a 32 bit a 386 e la modalità lunga di x86-64 lo sono davvero nuove versioni del codice macchina x86. La modalità lunga ha persino rimosso alcuni codici operativi, rendendoli non validi.
Peter Cordes,

5

Brachylog / Brachylog v1 , 5/2 = 2.5

2,1hw

Provalo online! (Brachylog)

Provalo online! (Brachylog v1)

Spiegazione per 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)

Spiegazione per 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)

Grande! Come sidenote, 2,1in Brachylog v2 non costruisce la lista [2,1]( 2;1sarebbe), ma piuttosto il numero 21(che non cambia il modo in cui intendevi che la risposta funzionasse).
Fatalizza il

@Fatalize Ooh grazie che l'ho confuso con Jelly ...
Erik the Outgolfer

@Fatalize BTW 2;1non avrebbe funzionato in Brachylog v1 come ;logico O lì.
Erik the Outgolfer,

5

C89 / C99, 25 byte, 2 versioni, punteggio = 12,5

#include <stdio.h>

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

// i commenti di stile non sono riconosciuti in C89.

Versione golfizzata:

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

Provalo online: C89 , C99


sostituirlo int v()con main(), è più corto e verrà compilato come un programma completo!
Andrea,

@Andrea Grazie. AFAIK, è consentito pubblicare funzioni o interi programmi.
nwellnhof,

Hai ragione.
Andrea,

5

Perl 5 e Perl 6, 23 byte 19 byte, punteggio 9.5

print 6-grep '.',''

La grepprima operazione di Perl 5 viene sempre considerata come regex, non così in Perl 6.


il punteggio è 19/2 = 9,5
Daniel Vestøl il

5

Bash, tutte e 4 le versioni, 72 71 32 byte ⇒ punteggio = 8

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

Questo pezzo di codice utilizza diverse interpretazioni delle $'...'stringhe in ogni versione di Bash.
Emette il numero di versione principale - e il gioco è fatto.

Doc trovato qui .

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

Questa risposta è per metà un'ipotesi; L'ho provato solo in bash 4 e 3, ma dovrebbe funzionare anche su altre versioni.

Fammi sapere se lo fa / no, proverò con altre versioni non appena le avrò disponibili.

-1 carattere grazie a Jens.
-29 byte grazie a Digital Trauma (l'intera expridea)!


La grammatica della shell non richiede una ;;nell'ultima alternativa. Utilizzare ;per radere via un byte.
Jens,

1
Ho appena provato questo su bash-2.05a (compilato proprio ora per Cygwin), e riporta erroneamente "3", non "2" :(
Jason Musgrove il

1
l'interpretazione $'\xNsembra essere stata aggiunta in 2.01.1 ... Dovrò aggiornare la mia risposta. Ci
sto lavorando

posso chiederti di provare questo? s="$'\ua\xa\n'";case ${#s} in 3)echo 4;;5)echo 3;;7)echo 2;;9)echo 1;esac
joH1

1
Potresti essere in grado di giocare a golf in qualcosa del genere s=$'\ua\xa\n';expr 5 - ${#s} / 2. Funziona su v3 e v4. Non ho versioni precedenti funzionanti da provare in questo momento.
Digital Trauma,

4

R, versioni 2 e 3, punteggio: 10,5 punti

cat(exists("cite")+2)

Questo comando restituisce 2per R 2.xx e 3per R 3.xx La funzione è citestata aggiunta in R versione 3.0.0. Pertanto, il comando exists("cite")restituisce FALSEper R 2.xx e TRUEper R 3.xx

R, tutte le versioni (1, 2 e 3), punteggio: 12⅓ punti

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

La funzione è eapplystata introdotta in R 2.0.0.


R.version$major. 15 caratteri. Non lo faccio da quando esiste.
Rui Barradas,

@RuiBarradas Lasciatemi citare il PO: " Il vostro programma non può usare un flag di compilatore incorporato, macro o personalizzato per determinare la versione della lingua "
Sven Hohenstein,

Ok, scusa, ho perso quella parte. Devo eliminare il commento?
Rui Barradas,

@RuiBarradas Nessun problema. Non è necessario eliminare il commento.
Sven Hohenstein,

Dovresti gestire la stampa del risultato. Attualmente, se eseguito come programma completo, questo non stampa nulla.
JAD,

4

Python , 196 byte / 16 versioni = punteggio 12,25

Le versioni sono 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
Sfortunatamente ho dovuto tralasciare 2.7 perché non ci sono moduli in (per quanto posso dire) che non sono in 2.6 ma sono in 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.)

Passiamo attraverso un mucchio di moduli che sono stati introdotti in diverse versioni di Python e al primo errore chiudiamo e restituiamo la versione. Gli spazi vuoti tra le versioni principali vengono colmati importando ripetutamente os. Il test per Python 1.5 si basa sul fatto di string.splitnon essere presente fino alla 1.6.

Ringraziamo la risposta di Olivier Grégoire per l'idea di testare nuove classi / moduli in un ciclo.

Ora ho finalmente testato su tutte le versioni rilevanti di Python ... che ha richiesto la modifica del codice sorgente 1.5 per farlo compilare ...


4

File batch di Windows , 35 byte / 2 versioni = punteggio 17.5

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

Stampa DOSsu MS-DOS (duh) e NTsu Windows NT. (duh)

Ora, per qualche spiegazione.

Windows ha avuto script in batch dai tempi di MS-DOS e da allora non è cambiato molto. Tuttavia, quando è arrivato Windows NT , Microsoft ha cambiato l'interprete predefinito per gli script batch, da COMMAND.COMa cmd.exe(ora consente anche l'estensione .cmdcome alternativa all'originale .bat).

Con ciò, hanno anche implementato alcune modifiche , come la /ibandiera per ignorare il caso di stringa sui condizionali. Cioè, mentre Z==zè falso, /i Z==zè vero.

Sfruttiamo che DOS non ha distinto tra maiuscole e minuscole e confrontiamo lettere maiuscole Zcon minuscole z. Usando il /iflag, finiamo con un Z==z(falso) condizionale su DOS e z==z(vero) su NT.

Ora, mi rendo conto che la sfida specifica che è necessario stampare un numero di versione. Ma, per quanto ne so, non esiste un "numero di versione" per gli script batch, quindi questo è il più vicino che potrei ottenere.


Testato su Windows 10, DOSBox e vDos:

Windows 10:

Windows 10

(corri con cmd /kper impedire la chiusura della finestra exit)

DOSBox:

DOSBox

VDOS:

VDOS


Windows 7è più corto di Windows NT.
user202729

2
@ user202729 Suppongo, ma poi di nuovo, 7non è davvero una versione linguistica, è stato lo stesso su tutti i Windows da 3.1. Quindi non pensavo che sarebbe stato giusto chiamarlo a 7quando forse dovrebbe anche essere3.1
Matheus Avellar

3

Wolfram Language / Mathematica 10/11, 37 byte / 2 versioni = 18.5

Considera (Length@DateRange[{1},{1}][[1]]+27)/3, a 37 byte e lavorando con 2 versioni, mi dà un punteggio di 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

Sono sicuro che esiste un modo più efficiente, ma la discrepanza tra l'output DateRange mi ha morso nel culo di recente, quindi ero pronto a usarlo.

Come follow-up, qualcuno potrebbe probabilmente trarre vantaggio dalla Length@DateRange[{1}, {1}][[1]]valutazione 1in Mathematica versioni 1- ~ 8, ma non ho avuto il tempo di incorporarlo.


2
Abbastanza sicuro che la tua risposta non soddisfi i requisiti del prompt, vale a dire l'ultima regola che devi usare $Version:Your program may not use a builtin, macro, or custom compiler flags to determine the language version.
Amndeep7

7
Sto solo usando $Versionper dimostrare che produce il risultato corretto nella versione corretta, $Versionnon fa parte della mia risposta ...
user6014

Tutti buoni amici - il fatto è che stai usando qualcosa di simile $VersionNumber, ma invece lo stai chiamando $Version. A mio avviso, mentre la carne del tuo programma è Length@DateRangeroba, che non funzionerebbe senza $Versionfornire solo le informazioni sulla versione completa che poi elabori, che quindi violano le regole.
Amndeep7,

4
@ Amndeep7 L'invio è il codice a 37 byte indicato nel primo paragrafo. I blocchi di codice sono solo dimostrazioni di output.
PurkkaKoodari,

3
Spiegazione: Utilizzo di diversi formati di tempo in diverse versioni. Che può essere giocato più a {1} Tr[1^#&@@%~DateRange~%]/3+9(31 byte), o anche 7+Length@Now(12 byte)
user202729

3

Ruby 1.xe 2.x, 20 byte, punteggio 10

p [].to_h&&2rescue 1

Basato sul to_hmetodo introdotto nella Arrayclasse in Ruby 2.


Bella prima risposta. Non ho 1.x utile da testare, ma p [].to_h&&2rescue 1è un po 'più corto.
arte

@manatwork Fantastico, salva 3 byte e funziona come un incantesimo
Philipp Frank,

3

Erlang, 180 byte, 11 versioni, punteggio 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)]]).

Con rientro e interruzioni di riga:

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

Testato su una versione minore di ogni versione principale dal 10:

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

L'idea è che ogni versione principale ha aggiunto almeno un nuovo argomento ammissibile per la funzione erlang:system_info, quindi proviamo quelli nella lista, contiamo quanti falliscono e sottraggiamo il numero di errori da 20, che è la versione corrente.


3

Julia 0.4, 0.5, 46 byte, punteggio 22

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

Julia ha cambiato il nome del tipo di stringhe concrete e astratte in molte versioni.

Questo codice in particolare sfrutta:

Julia 0.4 :

  • Il calcestruzzo è ASCIIString,
  • Abstract è ufficialmente AbstractString,
  • Abstract ha deprecato l'alias in String.
  • Il calcestruzzo è più specifico dell'astratto, quindi vince la spedizione

Julia 0.5 :

  • Il calcestruzzo è ufficialmente String,
  • Il calcestruzzo ha deprecato l'alias di ASCIIString,
  • L'estratto è AbstractString(anche se qui non importa)
  • Poiché sono stati definiti due metodi per il tipo di stringa di calcestruzzo, quest'ultimo sovrascrive il primo.

Vedi anche la mia nuova soluzione più efficace basata su principi diversi


3

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

'1r\S2

Test v1  |   Test v2

  • 2 byte salvati grazie a Oliver

Spiegazione

Prima della v2, Japt utilizzava una sintassi RegEx personalizzata, in modo che possiamo trarne vantaggio.

'1

Il numero 1 come stringa.

 r  2

Sostituisci ( r) il seguito con a 2.

\S

Japt 2 vede questo come RegEx /\S/g, che corrisponde a 1. Japt 1 ignora il \carattere di escape e vede solo la S, che è la costante di Japt per un personaggio spaziale e, ovviamente, non corrisponde a 1.


3

Befunge, punteggio = 3,5

7 byte, 2 versioni

"]"'b.@

Provalo online in Befunge-93
Provalo online in Befunge-98

"]"è una stringa letterale in entrambe le versioni, spingendo 93 (il valore ASCII di [) nello stack. 'bè un personaggio letterale in Befunge-98, spingendo 98 (il valore ASCII di b), ma quelle sono istruzioni non valide in Befunge-93, quindi vengono semplicemente ignorate. Finiamo così con 93 in cima allo stack in Befunge-93 e 98 in Befunge-98. .@scrive il valore nella parte superiore dello stack e quindi esce.


]".@.b'o ]g.@.b'anche lavorare
MildlyMilquetoast,

3

Ruby 1.x (<1.9) e 2.x, 10 8 byte, punteggio = 4

$><<?2%7

Provalo:

Questo funziona sfruttando i diversi comportamenti ?xtra Ruby 1.xe 2.x. In Ruby 1.x, ?A(ad esempio) restituisce 65(il valore ASCII del carattere A), ma in Ruby 2.0 restituisce la stringa di un carattere "A".

Il codice sopra è equivalente a questo:

val = ?2
$> << val % 7

In Ruby 1.x (<1.9), il valore di valè 50(il valore ASCII del carattere 2), un Fixnum. Fixnum#%è l'operatore modulo, quindi 50 % 7ritorna 1.

In Ruby 2.x valè la stringa "2". String#%è una versione infix di sprintf, quindi "2" % 7è equivalente a sprintf("2", 7), dove si "2"trova la stringa di formato. Poiché la stringa di formato non contiene sequenze di formati (ad es. %d), Gli argomenti successivi vengono scartati e "2"restituiti.

Infine, $>è un alias per $stdout, quindi $> << ...stampa il risultato.


1
Ooh bello! Stavo cercando di fare qualcosa di simile ?A==66?1:2prima di trovare la tua risposta
Piccolo

3

Python 2 e Python 3 , 36 34 byte, punteggio 18 17

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

In Python 2 , l'hash dell'infinito negativo è -271828 ma in Python 3 è -314159. Modifica: salvato 2 byte, 1 punto di punteggio, grazie a @ArBo.


squints Si tratta di una deliberata e vs cosa pi?
Jo King,

@JoKing Sì; apparentemente quando hashfu fissato per la prima volta a lavorare su infiniti a virgola mobile, lo sviluppatore interessato usò pi * 1e5 ed e * -1e5 come valori di hash. Ad un certo punto in Python 3 il valore ha per l'infinito negativo è stato cambiato in negazione del valore hash per l'infinito.
Neil,

2

Python 3 , Python 2 , punteggio 17.5

(35 byte, 2 versioni)

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

Python 2 , 35 byte

Provalo online!

Python 3 , 35 byte

Provalo online!

Risparmiato 5 byte grazie a ETHproductions

Non una buona risposta per il golf del codice, ma un grande cambiamento!


Hmm, puoi mettere ogni affermazione nella riga precedente? Vale a diretry:exec("print 2")\nexcept:print(3)
ETHproductions

@ETHproductions grazie! Non mi aspettavo di vincere, quindi ero un po 'distratto. Io principalmente volevo mettere a fuoco il massiccio cambiamento tra il Python 2 e 3.
jferard
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.