Określ wersję językową

51

Twoim wyzwaniem jest napisanie poliglota, który działa w różnych wersjach Twojego języka. Po uruchomieniu zawsze wyświetla wersję językową.

Zasady

  • Twój program powinien działać w co najmniej dwóch wersjach Twojego języka.
  • Wyjście twojego programu powinno być tylko numerem wersji. Brak obcych danych.
  • Twój program może użyć dowolnej metody w celu ustalenia numeru wersji. Jednak wynik musi być zgodny z regułą 2; niezależnie od tego, jaki numer wersji zostanie określony, wyjściem musi być tylko liczba.
  • Twój program musi tylko wypisać główną wersję języka. Na przykład, w FooBar 12.3.456789-beta, twój program będzie musiał tylko wypisać 12.
  • Jeśli Twój język umieszcza słowa lub symbole przed lub po numerze wersji, nie musisz ich wypisywać, a tylko numer. Na przykład w C89 twój program musi tylko drukować 89, aw C ++ 0x twój program musi tylko drukować 0.
  • Jeśli zdecydujesz się wydrukować pełną nazwę lub drobne numery wersji, np. C89 w przeciwieństwie do C99, musisz wydrukować tylko nazwę. C89 build 32jest ważny, a error in C89 build 32: foo barnie jest.
  • Twój program nie może używać wbudowanych, makr lub niestandardowych flag kompilatora do określania wersji językowej.

Punktacja

Twój wynik będzie równy długości kodu podzielonej przez liczbę wersji, w których działa. Najniższy wynik wygrywa, powodzenia!

MD XF
źródło
4
Co to jest numer wersji językowej? Kto to określa?
Wheat Wizard
9
Myślę, że odwrotnie-liniowy w liczbie wersji nie przyjmuje odpowiedzi z dużą liczbą wersji.
user202729,
6
@ user202729 Zgadzam się. Wszechstronna drukarka liczb całkowitych zrobiła to dobrze - wynik był (number of languages)^3 / (byte count).
Mego
6
Jaka jest wersja dla języka ? Czy nie definiujemy tutaj języka jako jego tłumaczy / kompilatorów ? Powiedzmy, że istnieje wersja gcc, która ma błąd, który z niektórymi kodami C89 tworzy plik wykonywalny, którego zachowanie narusza specyfikację C89, i została naprawiona w następnej wersji gcc. Czy to powinno policzyć prawidłowe rozwiązanie, jeśli napiszemy fragment kodu na podstawie tego błędu, aby stwierdzić, która wersja gcc używa? Jest skierowany na inną wersję kompilatora , ale NIE na inną wersję języka .
tsh
6
Nie rozumiem tego Najpierw powiesz „Wyjście twojego programu powinno być tylko numerem wersji”. . Następnie mówisz: „Jeśli zdecydujesz się wydrukować pełną nazwę lub drobne numery wersji, np. C89 w przeciwieństwie do C99, musisz tylko wydrukować nazwę”. Więc pierwsza zasada nie jest tak naprawdę wymogiem?
rura

Odpowiedzi:

16

Poważnie i faktycznie , 3 bajty, wynik 1,5

'1u

Wypróbuj online: Właściwie , poważnie

Wyjaśnienie:

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

ua Dfunkcjonalność na łańcuchach została dodana tylko w rzeczywistości (czyli Seriously v2).

Mego
źródło
3
W rzeczywistości README.md mówi, że w rzeczywistości jest duchowym następcą Seriously. Dla mnie to nie brzmi jak zwykła zmiana wersji.
Adám,
7
@ Adám Jeśli spojrzysz na gałęzie w repozytorium, Poważnie znajduje się w v1gałęzi. Przed poważnym zaniechaniem faktycznie mieszkał w v2oddziale. Dodatkowo, poważnie używane 1.xnumery wersji w wydaniach , podczas gdy faktycznie używa 2.x(zarówno tam, jak i na PyPI ).
Mego
115

Python 3.0 i Python 2, wynik 6

(12 bajtów, 2 wersje)

print(3/2*2)

Wypróbuj online:

Opiera się na tym, że Python 3+ domyślnie korzysta z podziału zmiennoprzecinkowego, w przeciwieństwie do Pythona 2, który używa podziału podłogowego.

fireflame241
źródło
@MaltySen Your program should work in at least two versions of your language.Działa w co najmniej dwóch wersjach 2.7 i 3.0. Wybrałam to print the full name or minor version numbers.
fireflame241
Och, rozumiem, moje złe.
Maltysen
4
O MÓJ BOŻE! Biedni programiści python
Regis Portalez
4
@RegisPortalez from __future__ import division, problem rozwiązany :)
Łukasz Rogalski
62

Java, 189 bajtów, 10 wersji, wynik = 18,9

Obsługiwane wersje: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8i9

(W przypadku poprzednich wyników sprawdź historię !)

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

Uruchom na Javie 8
Uruchom na Javie 9 lub nowszej

Bez golfa

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

Należy pamiętać, że część kodu return v<9?"1."+v:v;(wcześniej return(v<9?"1.":"")+v;) należy sprawdzić pod kątem dowolnej wersji zawartej między Java 1.0 a Java 1.3. Nie mam do dyspozycji żadnej instalacji Java 1.3 lub wcześniejszej, aby przetestować tę składnię.

Wprowadzenie

Wersja Java ma specjalną historię. Wszystkie wersje historycznie 1.xobejmowały 1.0. Ale ... począwszy od Java 9 i JEP223 , schematy wersji zmieniły się z używania 1.xna x. Jest to wersja znana wewnętrznie. Mamy więc następującą tabelę (razem z Javadoc i Wikipedią ):

 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

Ten wpis wyzwania pasuje do kolumny wersji w powyższej tabeli, która jest zawarta we właściwości systemu "java.version".

Wyjaśnienie

Celem jest sprawdzenie, z której wersji klasa zaczyna istnieć, ponieważ Java przestaje kodować, ale nigdy go nie usuwa. Kod został napisany specjalnie w Javie 1.0, aby był zgodny ze wszystkimi wersjami, ponieważ JDK jest (przeważnie) kompatybilny ze źródłowymi źródłami .

Implementacja próbuje znaleźć najkrótsze nazwy klas wprowadzone przez każdą wersję. Chociaż, aby uzyskać bajty, należy spróbować wybrać wspólny sub-pakiet. Jak dotąd znalazłem najbardziej wydajny pakiet, java.utilponieważ zawiera kilka naprawdę krótkich klas rozmieszczonych we wszystkich wersjach Javy.

Teraz, aby znaleźć rzeczywisty numer wersji, nazwy klas są sortowane według wprowadzenia wersji. Następnie próbuję po kolei zainicjować każdą klasę i zwiększyć indeks tablicy. Jeśli klasa istnieje, tryprzechodzimy do następnej, w przeciwnym razie pozwalamy na przechwycenie wyjątku przez -block. Po zakończeniu generowany jest kolejny wyjątek, ponieważ nie ma już klas, których istnienie musimy sprawdzić.

W każdym razie wątek opuści tryblok z wyjątkiem. Wyjątek ten nie zostanie złapany, ale po prostu zawieszone dzięki finally-blok, co z kolei nadpisuje wyjątek on-hold przez rzeczywiście powrocie wartość, która jest "1."+vtam gdzie vjest wskaźnik używany wcześniej. Zdarza się również, że dostosowaliśmy ten indeks do mniejszego numeru wersji Java.

Ważną częścią gry w golfa było znalezienie najkrótszej nowej nazwy klasy w pakiecie java.util(lub dowolnym pakiecie dla dzieci) dla każdej wersji. Oto tabela, której użyłem do obliczenia tego kosztu.

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

Kredyty

  • 30 bajtów zaoszczędzonych dzięki Kevinowi Cruijssenowi (chociaż robiłem to zanim przeczytałem jego komentarz, obiecuję!).
  • 26 kolejnych bajtów zaoszczędzonych dzięki Neilowi ​​(nie, nie myślałem o tym)
  • 12 bajtów dzięki Nevay i miła out-of-the -Box -try-catch myślenie!
  • Jeszcze 11 bajtów Neila i niezła przenośna finallysztuczka.
  • 2 dodatkowych bajtów dzięki Kevin Cruijssen zastępując return(i<9?"1.":"")+i;z return i<9?"1."+i:i;(powinno być aktualizowane na 1,0 lub co najwyżej 1,3, gdyż nie zmienia się składni przed 1.4)

Z wbudowanymi

Jeśli wbudowane były dozwolone:

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

54 bajty dla 13 wersji (od 1,0 do 12), więc wynik wyniósłby 4,1538.

Olivier Grégoire
źródło
1
@KevinCruijssen Otworzyłem javadoc i prowadziłem zajęcia z krótkimi nazwami 1 na 1. Ale ... Ta strona pomogła mi
Olivier Grégoire,
1
260 bajtów, a może jeszcze 1, nie wiem, czy return"...bez miejsca jest możliwe we wszystkich wersjach tbh.)
Kevin Cruijssen
1
235 bajtów: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 bajtów: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, zastanawiałem się nad iteracją tablicy i wyłapywaniem wyjątku, ale możesz zrobić to lepiej finally{return"1."+i;}.
Neil,
22

Python , 606 bajtów / 15 wersji = wynik 40,4

-67 bajtów (lol) dzięki NoOneIsHere.

Dostępne wersje to 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 oraz 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)

Wyrazy uznania dla niesamowitej odpowiedzi SP3000 jest . Końcowy znak nowej linii jest konieczny.

Whee, fajnie było grać w golfa. Powinno to działać (tak, zainstalowałem każdą z tych wersji), ale mogłem przypadkowo coś zepsuć. Jeśli ktoś znajdzie błąd, daj mi znać.

całkowicie ludzki
źródło
... Nic dziwnego. Zastanawiałem się, dlaczego Sp3000 umieścił nawiasy w każdym printpołączeniu ... Dziękuję za informację!
całkowicie ludzki,
2
Możesz zapisać 68 bajtów, usuwając określone rodzaje błędów (zamień wszystkie excepts na except:).
NoOneIsHere
Czy to nadal działałoby, gdybyś zrobił to x=<string inside eval>zamiast ręcznie sprawdzać kod?
Niebieski,
@NoOneIsThe początkowo myślałem, że nie możesz z powodu wszystkich 1/0, ale potem zdałem sobie sprawę. Dzięki!
całkowicie ludzki,
21

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

Aby rozróżnić C ++ 11 i C ++ 14/17, wykorzystuje zmianę domyślnej funkcji funkcji constskładowych constexprw C ++ 14 (dzięki przykładowi na https://stackoverflow.com/questions/23980929/ what-zmiany-wprowadzone-w-c14-może-potencjalnie-złamać-program-napisany w-c1 ). Aby odróżnić C ++ 14 od C ++ 17, wykorzystuje fakt, że C ++ 17 wyłączał trygrafy.

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

Nie golfowany:

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

(Testowane przy użyciu Debiana gcc 7.1.0 przy użyciu -std=c++{11,14,17}.)

Daniel Schepler
źródło
1
Świetna pierwsza odpowiedź! Pamiętaj, że możesz na przykład grać w golfa między znakami include<in” w instrukcjach dołączania #include<iostream>.
MD XF
1
Hmm ... jeśli reguły zostały zmienione, aby zabraniać używania standardowych różnic w bibliotece (które w tym przypadku pośrednio korzystają z __cplusplusmakra) - to w celu odróżnienia C ++ 17 od C ++ 14 skłaniam się ku zastosowaniu zmiany w zakresie dla semantyki. Może stwórz minimalne klasy iteratora / wartownika w boost::integer_iteratortaki sposób, aby konwersja wartownika na iterator miała „zaskakujące” zachowanie.
Daniel Schepler,
4
return 0;jest niejawny, mainwięc możesz tam zapisać 9 bajtów. Również według wc -ctwojego rozwiązania używa 251 bajtów, a nie 252 (twój edytor mógł wstawić nowy wiersz na końcu).
nwp
1
Prawdopodobnie krócej jest użyć braku trigrafów do oddzielenia c ++ 17 od c ++ 14
Potato44,
1
Czy to zadziała? return *=>return*
Zacharý
19

EcmaScript 3/5/2015/2016/2017 w przeglądarce, 59 bajtów / 5 wersji = 11,8 punktów

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

NetScape 7 raport 3, a Opera 12 raport 5

Zaoszczędź 1 bajt dzięki GOTO 0

tsh
źródło
1
Ninjaed ! ;)
Kudłaty
Netscape 7 obsługuje tylko ES3? Wow, jest starszy, niż myślałem ...
Neil
1
Możesz zapisać kilka bajtów, używając -!zamiast tego, +!!gdzie ma to sens (i odpowiednio zmienić stałe liczbowe).
GOTO 0
3
Może jakieś wyjaśnienie? :)
Derek 朕 會 功夫
@Derek: zobacz moje rozwiązanie (link powyżej), aby uzyskać wyjaśnienie.
Kudłaty
18

JavaScript (ES5 i ES6), 14 bajtów / 2 wersje = 7

alert(5^"0o3")

0o-stałe ósemkowe są nowe w ES6; ES5 rzutuje ciąg, na NaNktóry nie wpływa na wynik bitowego XOR.

Neil
źródło
13

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

Może również przesłać rozwiązanie z większą liczbą wersji, nawet jeśli jego wynik będzie nieco wyższy niż w przypadku rozwiązania 2-wersyjnego.

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

Wypróbuj online

Sprawdza obecność różnych metod w prototypach Array, RegExp i String, neguje je, dając wartość logiczną, i odejmuje tę wartość logiczną od wartości początkowej 9. Mnożenie ![].mapkont za fakt, że ES4 został porzucony.

  • dotAllNieruchomość (i związane z sflag) dla wyrażeń regularnych został wprowadzony w ES2018 (v9).
  • padEndSposób ciąg wprowadzono ES2017 (V8).
  • Metoda includesArray została wprowadzona w ES2016 (v7).
  • Metoda keysArray została wprowadzona w ES2015 (v6).
  • Metoda mapArray została wprowadzona w ES5.1 (v5).
  • Metoda popArray została wprowadzona w ES3 (v3).
Kudłaty
źródło
Czy ES 7 lub ES 8 jest prawidłowym numerem wersji? Może powinien być nazywany ES 201x?
tsh
1
@tsh: Tak, nadal używają numerów wersji; po prostu używają lat do realnych nazw .
Kudłaty
9

PHP 5/7, wynik 5,5

<?=7-"0x2";

3V4L to online!

PHP 5.3.9 / 5.3.11, wynik 10

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

3V4L to online!

Wersja online jest dłuższa, ponieważ stare wersje PHP w piaskownicy nie mają włączonych krótkich tagów.

Syzyf
źródło
9

Befunge: 15 11 bajtów / 2 wersje = 5.5

4 bajty wygolone przez @ Pietu1998

"89",;5-;,@  

Wypróbuj online:
Befunge 93
Befunge 98
Używa wyłącznego operatora średników Befunge 98 („przejdź do następnego średnika”) w celu rozróżnienia wersji. Oba wydrukują „9”. Befunge 93 zignoruje średniki, odejmie 5 od „8” (wartość pozostawiona na górze stosu), wydrukuje wynikowe „3” i zakończy. Z kolei Befunge 98 przeskoczy, wydrukuje „8” i zakończy działanie.

karhell
źródło
"89",;5-;,@dla 11 bajtów
PurkkaKoodari
@ Pietu1998 Nice! Jeśli chcesz opublikować to jako odpowiedź, chętnie poprę głos :)
karhell
Śmiało i weź to, jeśli chcesz, wymyśliłeś tę ;część.
PurkkaKoodari
@ Pietu1998 Edytowano w. Wielkie dzięki!
karhell
Do Twojej wiadomości udało mi się sprowadzić go do 7 bajtów, przyjmując inne podejście. Link
James Holderness
7

Pyth 4/5 - 6 bajtów / 2 wersje = 3

  5 ;4

W Pyth 5 parzysta ilość spacji na początku wiersza jest ignorowana do użycia przy wcięciach, podczas gdy w Pyth 4 działa tylko jak pojedyncza spacja i uniemożliwia wydrukowanie 5. W Pyth 4 średniki kończą instrukcje, co pozwala na 4wydrukowanie, podczas gdy w Pyth 5 spacja i średnik sprawiają, że reszta wiersza jest komentarzem.

Maltysen
źródło
11
Kto wiedział, że Pyth ma wersje?
Erik the Outgolfer,
7

Python 3 i Python 2.0, 18 bajtów, wynik 18/2 = 9

print(3-round(.5))

Zaokrąglanie bankiera w Pythonie 3, standardowe zaokrąglanie w Pythonie 2.

Wypróbuj online - Python 3!

Wypróbuj online - Python 2!

Stephen
źródło
wow, zawsze widziałem ludzi rozróżniających Python 2 i 3 według podziału
phuclv
@ LưuVĩnhPhúc podział jest golfistą, dlatego: P
Stephen
7

Sześciennie, 4 bajty, wynik 4 / ∞

B3%0

Działa w każdej wersji twojego systemu ma wystarczającą ilość pamięci do uruchomienia. Nie konkuruje, bo jest kiepski. Ważne dla tego posta .

Zasadniczo B3 obraca jeden rząd od lewej powierzchni do górnej powierzchni. F3 działałoby równie dobrze, jak F₁3 lub B₁3. Ponieważ jeden rząd w Cubical 3x3x3 ma trzy sześciany za jednym sześcianem, to umieszcza trzy 1z nich w górnej powierzchni, co daje mu sumę twarzy 3. %0drukuje sumę górnej powierzchni, drukując 3 dla Cubical 3 x3x3.

W Cubically 4x4x4 rzędy to 4x1 cubies. Umieszcza 4 1 w górnej powierzchni, dając sumę 4.

MD XF
źródło
9
Czy wynik nie powinien wynosić 4 / ∞?
nwp
7

x86 16/32/64-bitowy kod maszynowy: 11 bajtów, wynik = 3,66

Ta funkcja zwraca bieżący tryb (domyślny rozmiar argumentu) jako liczbę całkowitą w AL. Zadzwoń do niego z C z podpisemuint8_t modedetect(void);

Kod maszynowy NASM + lista źródeł (pokazująca, jak to działa w trybie 16-bitowym, ponieważ BITS 16mówi NASM, aby zebrał źródłowe mnemoniki dla trybu 16-bitowego).

 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

Uzasadnienie :

Kod maszynowy x86 oficjalnie nie ma numerów wersji, ale myślę, że to spełnia cel pytania, ponieważ trzeba wytwarzać określone liczby, zamiast wybierać to, co jest najwygodniejsze (zajmuje to tylko 7 bajtów, patrz poniżej).

Oryginalny procesor x86, Intel 8086, obsługiwał tylko 16-bitowy kod maszynowy. 80386 wprowadził 32-bitowy kod maszynowy (dostępny w 32-bitowym trybie chronionym, a później w trybie kompatybilności w 64-bitowym systemie operacyjnym). AMD wprowadziło 64-bitowy kod maszynowy, który można stosować w trybie długim. Są to wersje języka maszynowego x86 w tym samym sensie, co Python2 i Python3 to różne wersje językowe. Są w większości kompatybilne, ale z celowymi zmianami. Możesz uruchamiać 32-bitowe lub 64-bitowe pliki wykonywalne bezpośrednio w 64-bitowym jądrze systemu operacyjnego w taki sam sposób jak w programach Python2 i Python3.

Jak to działa:

Zacznij od al=64. Przesuń go w prawo o 1 (tryb 32-bitowy) lub 2 (tryb 16-bitowy).

  • 16/32 a 64-bitowe: 1-bajtowe inc/ deckodowanie to przedrostki REX w wersji 64-bitowej ( http://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix ). REX.W nie wpływa w ogóle na niektóre instrukcje (np. A jmplub jcc), ale w tym przypadku, aby uzyskać 16/32/64, chciałem ecxraczej dodać lub zdecydować eax. To także ustawia REX.B, co zmienia rejestr docelowy. Ale na szczęście możemy to zrobić, ale konfigurujemy tak, aby 64-bit nie musiał się zmieniać al.

    Instrukcje, które działają tylko w trybie 16-bitowym, mogą zawierać a ret, ale nie uważam tego za konieczne ani pomocne. (I uniemożliwiłoby wstawienie jako fragment kodu, na wypadek gdybyś chciał to zrobić). Może to być również jmpfunkcja.

  • 16-bit vs. 32/64: natychmiastowe są 16-bitowe zamiast 32-bitowe. Zmiana trybów może zmienić długość instrukcji, więc tryby 32/64 bit dekodują kolejne dwa bajty jako część instrukcji bezpośredniej, a nie oddzielnej instrukcji. Uprościłem to, używając tutaj instrukcji 2-bajtowej, zamiast zsynchronizować dekodowanie, aby tryb 16-bitowy dekodował z innych granic instrukcji niż 32/64.

    Powiązane: Prefiks wielkości operandu zmienia długość natychmiastowego (chyba że jest to 8-bitowe bezpośrednie rozszerzenie z rozszerzeniem znaku), podobnie jak różnica między trybami 16-bitowymi i 32/64-bitowymi. Utrudnia to równoległe dekodowanie długości instrukcji; Procesory Intel mają przeciągnięcia dekodujące LCP .


Większość konwencji wywoływania (w tym psABI x86-32 i x86-64 System V) pozwala na wąskie zwracane wartości, które zawierają śmieci w wysokich bitach rejestru. Pozwalają również na clobbering CX / ECX / RCX (i R8 dla wersji 64-bitowej). IDK, jeśli było to powszechne w 16-bitowych konwencjach wywoływania, ale jest to kod golfowy, więc zawsze mogę po prostu powiedzieć, że jest to zwyczajowa konwencja wywołań.

Demontaż 32-bitowy :

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    

Demontaż 64-bitowy ( wypróbuj 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    

Powiązane: mój kod maszynowy x86-32 / x86-64 poliglota - pytania i odpowiedzi dotyczące SO.

Kolejna różnica między 16-bitem a 32/64 polega na tym, że tryby adresowania są kodowane inaczej. np. lea eax, [rax+2]( 8D 40 02) dekoduje jak lea ax, [bx+si+0x2]w trybie 16-bitowym. Jest to oczywiście trudne do wykorzystania dla code-golf, zwłaszcza, że e/rbxi e/rsisą zadzwonić zachowane w wielu konwencjach telefonicznych.

Zastanawiałem się również nad użyciem 10-bajtowego mov r64, imm64, którym jest REX + mov r32,imm32. Ale ponieważ miałem już rozwiązanie 11-bajtowe, byłoby to w najlepszym razie równe (10 bajtów + 1 dla ret).


Kod testowy dla trybu 32 i 64-bitowego. (Właściwie nie wykonałem go w trybie 16-bitowym, ale deasemblacja mówi ci, jak będzie dekodować. Nie mam skonfigurowanego emulatora 16-bitowego).

; 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

Ten program Linux kończy działanie z kodem wyjścia = modedetect(), więc uruchom go jako ./a.out; echo $?. Złóż i połącz go w statyczny plik binarny, np

$ 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 bajtów (wynik = 2,33), jeśli mogę numerować wersje 1, 2, 3

Brak oficjalnych numerów wersji dla różnych trybów x86. Po prostu lubię pisać odpowiedzi na asm. Myślę, że naruszałoby to cel pytania, gdybym tylko wywołał tryby 1,2,3 lub 0,1,2, ponieważ chodzi o to, aby zmusić cię do wygenerowania niewygodnej liczby. Ale jeśli było to dozwolone:

 # 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

Który dekoduje w trybie 32-bitowym jako

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

i 64-bitowy jak

00000000004000a0 <detect123>:
  4000a0:       b8 03 00 fe c8          mov    eax,0xc8fe0003
  4000a5:       48 c3                   rex.W ret 
Peter Cordes
źródło
Nie jestem pewien, czy są to różne wersje . Czy nie korelują one tylko z różnymi konfiguracjami systemu?
Uriel
1
@Uriel: Uruchamianie bloku kodu maszynowego z procesorem w trybie 16-bitowym, 32-bitowym lub 64-bitowym to odpowiednik kodu maszynowego działania python2kontra python3interpretatory w tym samym programie Python. Nowe procesory x86 zawsze zawierają tryb kompatybilny ze starszymi procesorami (jest to ich jedyna wymówka dla użycia tak skomplikowanego, trudnego do odkodowania formatu kodu maszynowego!), Ale 326-bitowy tryb chroniony 386 i długi tryb x86-64 są naprawdę nowe wersje kodu maszynowego x86. Tryb długi nawet usunął niektóre kody, co czyni je nieważnymi.
Peter Cordes
5

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

2,1hw

Wypróbuj online! (Brachylog)

Wypróbuj online! (Brachylog v1)

Wyjaśnienie dotyczące 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)

Wyjaśnienie dotyczące 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 the Outgolfer
źródło
Wspaniały! Na marginesie, 2,1w Brachylog v2 nie konstruuje listy [2,1]( 2;1zrobiłby), ale raczej liczbę 21(która nie zmienia sposobu, w jaki chciałeś, aby twoja odpowiedź działała).
Fatalize
@Zatrzymaj dzięki Ooh, pomyliłem to z Jelly ...
Erik the Outgolfer
@Fatalize BTW 2;1nie działałby w Brachylog v1, co ;oznacza logiczne LUB tam.
Erik the Outgolfer,
5

C89 / C99, 25 bajtów, 2 wersje, wynik = 12,5

#include <stdio.h>

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

// komentarze do stylu nie są rozpoznawane w C89.

Wersja golfowa:

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

Wypróbuj online: C89 , C99

nwellnhof
źródło
wymienić int v()z main(), jest krótszy i będzie faktycznie skompilować jako kompletny program!
Andrea,
@Andrea Thanks. AFAIK, dozwolone jest publikowanie funkcji lub całych programów.
nwellnhof
Masz rację.
Andrea,
5

Perl 5 i Perl 6, 23 bajty 19 bajtów, wynik 9,5

print 6-grep '.',''

grepPierwsze działanie w Perlu 5 jest zawsze traktowane jako wyrażenie regularne, a nie w Perlu 6.

Jozuego
źródło
wynik to 19/2 = 9,5
Daniel Vestøl
5

Bash, wszystkie 4 wersje, 72 71 32 bajty ⇒ wynik = 8

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

Ten fragment kodu wykorzystuje różne interpretacje $'...'ciągów w każdej wersji Bash.
Wysyła główny numer wersji - i to wszystko.

Doc znaleźć tutaj .

Nie golfowany:

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

Ta odpowiedź jest w połowie domysłem; Testowałem go tylko w bash 4 i 3, ale powinien działać również na innych wersjach.

Daj mi znać, jeśli to robi / nie działa, spróbuję z innymi wersjami, jak tylko będę dostępny.

-1 char dzięki Jens.
-29 bajtów dzięki Digital Trauma (cały exprpomysł)!

joH1
źródło
Gramatyka powłoki nie wymaga ;;ostatniej alternatywy. Służy ;do golenia bajtu.
Jens,
1
Właśnie próbowałem tego na bash-2.05a (skompilowanym teraz dla Cygwina) i niepoprawnie zgłasza „3”, a nie „2” :(
Jason Musgrove
1
$'\xNwydaje się, że funkcja interpretacji została dodana w wersji 2.01.1 ... Będę musiał zaktualizować swoją odpowiedź. Pracuję nad tym
joH1
czy mogę prosić o wypróbowanie tego? s="$'\ua\xa\n'";case ${#s} in 3)echo 4;;5)echo 3;;7)echo 2;;9)echo 1;esac
joH1
1
Możesz być w stanie zagrać w golfa na coś takiego s=$'\ua\xa\n';expr 5 - ${#s} / 2. Działa to na wersjach v3 i v4. Nie mam teraz działających starszych wersji do wypróbowania.
Cyfrowa trauma
4

R, wersje 2 i 3, wynik: 10,5 punktu

cat(exists("cite")+2)

Ta komenda zwraca 2dla wersji R 2.xx i 3R 3.xx Funkcja citezostała dodana w wersji R 3.0.0. Dlatego polecenie exists("cite")zwraca FALSEdla R 2.xx i TRUER 3.xx

R, wszystkie wersje (1, 2 i 3), wynik: 12⅓ punktów

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

Funkcja eapplyzostała wprowadzona w wersji 2.0.0.

Sven Hohenstein
źródło
R.version$major. 15 znaków. Nie wiem od kiedy to istnieje.
Rui Barradas,
@RuiBarradas Pozwól, że zacytuję OP: „ Twój program nie może używać wbudowanych, makr lub niestandardowych flag kompilatora do określania wersji językowej.
Sven Hohenstein
Ok, przepraszam, tęskniłem za tą częścią. Czy powinienem usunąć komentarz?
Rui Barradas,
@RuiBarradas Nie ma problemu. Nie musisz usuwać komentarza.
Sven Hohenstein,
Powinieneś zająć się wydrukowaniem wyniku. Obecnie po uruchomieniu jako pełny program nic nie drukuje.
JAD
4

Python , 196 bajtów / 16 wersji = wynik 12,25

Wersje to 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 i 3.6
Niestety musiałem pominąć 2.7, ponieważ nie ma żadnych modułów (o ile wiem) nie ma ich w wersji 2.6, ale w wersji 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.)

Przechodzimy przez kilka modułów, które zostały wprowadzone w różnych wersjach Pythona, a przy pierwszym błędzie wychodzimy i zwracamy wersję. Luki między głównymi wersjami są uzupełniane przez wielokrotne importowanie os. Test dla Pythona 1.5 polega na string.splittym, że nie jest obecny do 1.6.

Kredyt na odpowiedź Olivier Gregoire jest dla idei testowania nowych Zajęcia / modułów w pętli.

W końcu przetestowałem wszystkie odpowiednie wersje Pythona ... które wymagały edycji kodu źródłowego 1.5, aby go skompilować ...

g. gniazdo
źródło
4

Plik wsadowy systemu Windows , 35 bajtów / 2 wersje = wynik 17,5

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

Drukuje DOSna MS-DOS (duh) i NTna Windows NT. (duh)

Teraz trochę wyjaśnienia.

System Windows ma skrypty wsadowe od czasów MS-DOS i od tego czasu niewiele się zmieniło. Jednak gdy pojawił się Windows NT , Microsoft zmienił domyślny interpreter skryptów wsadowych z COMMAND.COMna cmd.exe(teraz zezwala również na rozszerzenie .cmdjako alternatywę dla oryginału .bat).

Dzięki temu zaimplementowali także kilka zmian , takich jak /iflaga ignorująca wielkość liter w warunkach. To znaczy, choć Z==zjest fałszywe, /i Z==zjest prawdą.

Wykorzystujemy to, że DOS nie rozróżnia wielkości liter i porównujemy wielkie litery Zz małymi z. Używając /iflagi, otrzymujemy Z==z(fałsz) zależny od DOS i z==z(prawda) w NT.

Teraz zdaję sobie sprawę, że wyzwanie określa, że ​​należy wydrukować numer wersji. Ale, o ile mi wiadomo, nie ma „numeru wersji” do skryptowania wsadowego, więc jest to najbliższy możliwy sposób.


Testowane na Windows 10, DOSBox i vDos:

Windows 10:

Windows 10

(uruchom, cmd /kaby uniemożliwić zamknięcie okna exit)

DOSBox:

DOSBox

vDos:

vDos

Matheus Avellar
źródło
Windows 7jest krótszy niż Windows NT.
user202729,
2
@ user202729 Przypuszczam, ale z drugiej strony 7tak naprawdę nie jest wersją językową, jest taka sama we wszystkich systemach Windows od wersji 3.1. Więc nie sądziłem, że byłoby to sprawiedliwe nazwać to, 7kiedy powinno być3.1
Matheus Avellar
3

Wolfram Language / Mathematica 10/11, 37 bajtów / 2 wersje = 18,5

Zastanów się (Length@DateRange[{1},{1}][[1]]+27)/3, przy 37 bajtach i pracy z 2 wersjami, daje mi wynik 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

i

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

Jestem pewien, że istnieje bardziej skuteczny sposób, ale ostatnio rozbieżność między danymi wyjściowymi DateRange ugryzła mnie w tyłek, więc postanowiłem to wykorzystać.

Jako kontynuację, ktoś prawdopodobnie mógłby skorzystać z Length@DateRange[{1}, {1}][[1]]ewaluacji 1w wersjach Mathematica 1- ~ 8, ale nie miałem czasu, aby to uwzględnić.

użytkownik6014
źródło
2
Dość pewna, że ​​twoja odpowiedź nie spełnia wymagań podpowiedzi, a mianowicie ostatniej reguły z powodu użycia $Version:Your program may not use a builtin, macro, or custom compiler flags to determine the language version.
Amndeep7
7
Używam tylko $Versiondo wykazania, że ​​wyświetla prawidłowy wynik w poprawnej wersji, $Versionnie jest częścią mojej odpowiedzi ...
user6014
Cały dobry przyjaciel - chodzi o to, że używasz czegoś takiego $VersionNumber, ale zamiast tego nazywasz to $Version. Moim zdaniem, podczas gdy mięso twojego programu to Length@DateRangerzeczy, które nie działałyby bez $Versiondostarczenia pełnej informacji o wersji, którą następnie przetwarzasz, co narusza reguły.
Amndeep7,
4
@ Amndeep7 Przesłanie to 37-bajtowy kod wymieniony w pierwszym akapicie. Bloki kodu są tylko demonstracjami wyjściowymi.
PurkkaKoodari
3
Objaśnienie: Używanie innego formatu czasu w różnych wersjach. To może być golfowane bardziej do {1} Tr[1^#&@@%~DateRange~%]/3+9(31 bajtów), a nawet 7+Length@Now(12 bajtów)
user202729,
3

Ruby 1.x i 2.x, 20 bajtów, wynik 10

p [].to_h&&2rescue 1

Na podstawie to_hmetody wprowadzonej w Arrayklasie w Ruby 2.

Philipp Frank
źródło
Dobra pierwsza odpowiedź. Nie mam pod ręką 1.x do przetestowania, ale p [].to_h&&2rescue 1jest nieco krótszy.
manatwork
@manatwork Świetnie, oszczędza 3 bajty i działa jak urok
Philipp Frank
3

Erlang, 180 bajtów, 11 wersji, wynik 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)]]).

Z wcięciem i podziałami linii:

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

Testowane na jednym mniejszym wydaniu każdej głównej wersji od 10:

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

Chodzi o to, że każda ważna wersja dodawała co najmniej jeden nowy dopuszczalny argument dla funkcji erlang:system_info, więc spróbujmy tych z listy, policz, ile z nich uległo awarii, i odejmij liczbę awarii od 20, czyli bieżącej wersji.

legoscia
źródło
3

Julia 0,4, 0,5, 46 bajtów, wynik 22

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

Julia zmieniła nazwę typu konkretnych i abstrakcyjnych typów ciągów w wielu wersjach.

Ten kod w szczególności wykorzystuje:

Julia 0.4 :

  • Beton jest ASCIIString,
  • Streszczenie jest oficjalnie AbstractString,
  • Abstrakt zastąpił alias do String.
  • Beton jest bardziej konkretny niż abstrakcyjny, więc wygrywa w wysyłce

Julia 0.5 :

  • Beton jest oficjalnie String,
  • Beton zastąpił alias do ASCIIString,
  • Streszczenie jest AbstractString(choć nie ma to tutaj znaczenia)
  • Ponieważ zdefiniowano dwie metody dla konkretnego typu struny, ta druga zastępuje pierwszą.

Zobacz także moje nowsze, bardziej skuteczne rozwiązanie oparte na różnych zasadach

Lyndon White
źródło
3

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

'1r\S2

Test v1  |   Test v2


Wyjaśnienie

Przed wersją 2 Japt używał niestandardowej składni RegEx, dzięki czemu możemy to wykorzystać.

'1

Liczba 1 jako ciąg.

 r  2

Zamień ( r) poniżej na 2.

\S

Japt 2 widzi to jako RegEx /\S/g, który pasuje do 1. Japt 1 ignoruje \znak ucieczki i po prostu widzi S, która jest stałą Japt dla znaku spacji i, oczywiście, nie pasuje do 1.

Kudłaty
źródło
3

Befunge, wynik = 3,5

7 bajtów, 2 wersje

"]"'b.@

Wypróbuj online w Befunge-93
Wypróbuj online w Befunge-98

"]"jest literałem ciągu w obu wersjach, wypychając 93 (wartość ASCII z [) na stos. 'bjest dosłowną postacią w Befunge-98, wypychając 98 (wartość ASCII b), ale są to nieprawidłowe instrukcje w Befunge-93, więc są po prostu ignorowane. W ten sposób kończymy z 93 na górze stosu w Befunge-93 i 98 w Befunge-98. .@zapisuje wartość na górze stosu, a następnie kończy działanie.

James Holderness
źródło
]"[email protected]'lub ][email protected]'też praca
MildlyMilquetoast
3

Rubin 1.x (<1,9) i 2.x, 10 8 bajtów, wynik = 4

$><<?2%7

Spróbuj:

Działa to poprzez wykorzystanie różnych zachowań ?xmiędzy Ruby 1.xi 2.x. W Ruby 1.x ?A(na przykład) zwraca 65(wartość ASCII znaku A), ale w Ruby 2.0 zwraca łańcuch jednoznakowy "A".

Powyższy kod jest równoważny z tym:

val = ?2
$> << val % 7

W Ruby 1.x (<1.9) wartością valjest 50(wartość ASCII znaku 2), Fixnum. Fixnum#%jest operatorem modulo, więc 50 % 7zwraca 1.

W Ruby 2.x valjest ciągiem "2". String#%jest wersją przedrostkową sprintf, więc "2" % 7jest równoważne z sprintf("2", 7), gdzie "2"jest ciąg formatu. Ponieważ ciąg formatu nie zawiera żadnych sekwencji formatujących (np. %d), Kolejne argumenty są odrzucane i "2"zwracane.

Wreszcie $>jest pseudonimem $stdout, więc $> << ...drukuje wynik.

Jordania
źródło
1
OOH nieźle! Próbowałem zrobić coś takiego, ?A==66?1:2zanim natknąłem się na twoją odpowiedź
Piccolo,
3

Python 2 i Python 3 , 36 34 bajtów, wynik 18 17

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

W Pythonie 2 skrót ujemnej nieskończoności wynosi -271828, ale w Pythonie 3 jest to -314159. Edycja: Zapisano 2 bajty, 1 punkt wyniku, dzięki @ArBo.

Neil
źródło
mruży Czy to celowe działanie przeciwko pi?
Jo King
@JoKing Tak; najwyraźniej, kiedy po hashraz pierwszy naprawiono go do pracy na nieskończonościach zmiennoprzecinkowych, odpowiedni programista użył pi * 1e5 i e * -1e5 jako wartości skrótu. W pewnym momencie w Pythonie 3 wartość hash dla nieskończoności została zmieniona na negację wartości hash dla nieskończoności.
Neil
2

Python 3 , Python 2 , wynik 17,5

(35 bajtów, 2 wersje)

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

Python 2 , 35 bajtów

Wypróbuj online!

Python 3 , 35 bajtów

Wypróbuj online!

Zaoszczędzono 5 bajtów dzięki produktom ETH

Nie jest to dobra odpowiedź na golfa, ale ogromna zmiana!

Jferard
źródło
Hmm, czy możesz umieścić każde zdanie w poprzednim wierszu? To try:exec("print 2")\nexcept:print(3)
znaczy
@ETHproductions dzięki! Nie spodziewałem się wygranej, dlatego byłem trochę rozproszony. Chciałem głównie skupić się na ogromnej zmianie między Pythonem 2 i 3.
Jferard