Визначте свою мову


51

Ваше завдання - написати поліглот, який працює в різних версіях вашої мови. Під час запуску він завжди виводить мовну версію.

Правила

  • Ваша програма повинна працювати щонайменше у двох версіях вашої мови.
  • Вихід програми повинен бути лише номером версії. Жодних сторонніх даних немає.
  • Ваша програма може використовувати будь-який спосіб, який ви хочете, щоб визначити номер версії. Однак вихід повинен відповідати правилу 2; однак ви визначаєте номер версії, вихід повинен бути лише числом.
  • Вашій програмі потрібно лише вивести основну версію мови. Наприклад, у FooBar 12.3.456789-beta, вашій програмі потрібно буде лише 12.
  • Якщо ваша мова ставить слова або символи до або після номера версії, вам не потрібно виводити ці, а лише число. Наприклад, у C89 вашій програмі потрібно друкувати лише друк 89, а в C ++ 0x - вашій програмі потрібно лише друкувати 0.
  • Якщо ви хочете надрукувати повне ім'я або молодший номер версії, наприклад , C89 , на відміну від C99, він повинен тільки друкувати ім'я. C89 build 32є дійсним, тоді error in C89 build 32: foo barяк ні.
  • Ваша програма може не використовувати вбудовані, макро або спеціальні прапори компілятора для визначення мовної версії.

Оцінка балів

Ваш результат буде кодовою довжиною, поділеною на кількість версій, в яких він працює. Найнижчий результат виграє, удачі!


4
Що таке номер версії мови? Хто це визначає?
Пшеничний майстер

9
Я думаю, що зворотна лінійна кількість версій не вітає відповідей з великою кількістю версій.
користувач202729

6
@ user202729 Я згоден. Універсальний принтер Integer це зробив добре - оцінка була (number of languages)^3 / (byte count).
Mego

6
Яка версія для мови ? Хіба ми тут не визначимо мову як її перекладачів / укладачів ? Скажімо, існує версія gcc, яка має помилку, яка з певними кодами C89 створює виконуваний файл, поведінка якого порушує специфікацію C89, і це було виправлено на наступній версії gcc. Чи слід вважати це правильним рішенням, якщо ми пишемо фрагмент кодової бази щодо цієї помилки, щоб сказати, яку версію gcc використовує? Він орієнтований на іншу версію компілятора , але НЕ іншу версію мови .
tsh

6
Я цього не розумію. По-перше, ви говорите "Вихід вашої програми має бути лише номером версії". . Тоді ви говорите: "Якщо ви вирішили надрукувати повне ім'я або незначні номери версій, наприклад, C89 на відміну від C99, він повинен надрукувати лише ім'я". Тож перше правило насправді не є вимогою?
труба

Відповіді:


16

Серйозно і насправді 3 байти, оцінка 1,5

'1u

Спробуйте в Інтернеті: насправді , серйозно

Пояснення:

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

uа Dфункціональність на рядках була додана лише в насправді (що серйозно v2).


3
Фактично README.md говорить, що насправді є духовним наступником Серйозно. Мені це не здається простою зміною версії.
Adám

7
@ Adám Якщо ви подивитеся на гілки в сховищі, він серйозно знаходиться у v1гілці. До того, як серйозно втратили силу, насправді проживали у v2філії. Крім того, серйозно використовуються 1.xномери версій у випусках , в той час як насправді використовується 2.x(і там, і на PyPI ).
Mego

115

Python 3.0 та Python 2, оцінка 6

(12 байт, 2 версії)

print(3/2*2)

Спробуйте в Інтернеті:

Покладається на те, що Python 3+ використовує поділ поплавця за замовчуванням, на відміну від Python 2, який використовує поділ підлоги.


@MaltySen Your program should work in at least two versions of your language.Працює як мінімум у двох версіях 2.7 та 3.0. Я вибрав to print the full name or minor version numbers.
fireflame241

Ой бачу, моє погано.
Мальтісен

4
О БОЖЕ МІЙ! Бідні розробники пітона
Regis Portalez

4
@RegisPortalez from __future__ import division, проблема вирішена :)
Łukasz Rogalski

62

Java, 189 байт, 10 версій, оцінка = 18,9

Підтримувані версії: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8і9

(Для попередніх оцінок перевірте історію !)

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

Запустити на Java 8
Запустити на Java 9 або новішої версії

Безумовно

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

Зверніть увагу, що частина коду return v<9?"1."+v:v;(раніше return(v<9?"1.":"")+v;) повинна бути перевірена на будь-яку версію між включеною Java 1.0 та Java 1.3. У мене немає жодної інсталяції Java 1.3 або попередньої версії, яка б фактично перевіряла цей синтаксис.

Вступ

Версія Java має особливу історію. Всі версії історично 1.xвключали 1.0. Але ... з Java 9 і JEP223 , схематизація версій змінилася з використання 1.xна x. Така версія є внутрішньо відомою. Отже, у нас є наступна таблиця (складена разом з Javadoc та Wikipedia ):

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

Цей запис виклику відповідає стовпцю версії в таблиці вище, що міститься у властивості системи "java.version".

Пояснення

Мета - перевірити, з якої версії починає існувати клас, оскільки Java знецінює код, але ніколи не видаляє його. Код був спеціально написаний на Java 1.0, щоб бути сумісним з усіма версіями, знову ж таки, тому що JDK є (здебільшого) сумісним джерелом вперед .

Реалізація намагається знайти найкоротші назви класів, які вводила кожна версія. Хоча для отримання байтів потрібно спробувати вибрати загальний підпакет. Поки що я знайшов найбільш ефективний пакет, java.utilтому що він містить кілька дійсно коротких назв класів, розповсюджених у всіх версіях Java.

Тепер, щоб знайти фактичний номер версії, назви класів сортуються за допомогою введення версії. Тоді я намагаюся інстанціювати кожен клас послідовно та збільшувати індекс масиву. Якщо клас існує, ми переходимо до наступного, інакше ми дозволяємо виняток перехопити try-block. Закінчивши, викидається ще один виняток, оскільки немає більше класів, існування яких нам потрібно перевірити.

У будь-якому випадку, нитка залишить try-block за винятком. Цей виняток не перехоплено, а просто поставити на утримання завдяки finallyБлоки, який , в свою чергу , перекриває виняток на утриманні насправді повертає значення , яке "1."+vде vзнаходиться індекс , який використовується раніше. Буває і так, що ми зробили, що цей індекс відповідає мінорному номеру версії Java.

Важливою частиною гольфу було знайти найкоротше нове найменування класу в пакеті java.util(або будь-якому дитячому пакеті) для кожної версії. Ось таблиця, яку я використав для обчислення цієї вартості.

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

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

Кредити

  • 30 байт збережено завдяки Кевіну Крейсейну (хоча я це робив ще до того, як прочитав його коментар, обіцяю!).
  • Ще 26 байт зберегли завдяки Нілу (ні, я не думав про це)
  • 12 байтів завдяки Nevay і приємно через оф -Box -постаратися прилов мислення!
  • Ще 11 байт Ніла знову і приємний портативний finallyтрюк.
  • Ще 2 байти завдяки Kevin Cruijssen замінивши return(i<9?"1.":"")+i;на return i<9?"1."+i:i;(це потрібно перевірити проти 1,0 або максимум 1,3, оскільки жодних змін синтаксису не відбулося до 1,4)

З вбудованими

Якщо вбудовані дозволили:

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

54 байти для 13 версій (від 1,0 до 12), тож оцінка склала б 4,1538.


1
@KevinCruijssen я відкрив javadoc і провів заняття з короткими іменами 1 на 1. Але ... мені трохи допомогла ця сторінка: docs.oracle.com/javase/8/docs/technotes/guides/lang/…
Олів'є Grégoire

1
260 байт. Або, можливо, ще 1, не знаю, чи return"...без місця можливий пробіл у всіх версіях.)
Кевін Круїйсен

1
235 байт:String v(){return "1."+(e("time.Year")+e("nio.file.Path")+e("io.Console")+e("util.UUID")+e("text.Bidi")+e("util.Timer")+e("sql.Ref")+e("lang.Void"));}int e(String c){try{Class.forName("java."+c);return 1;}catch(Exception e){return 0;}}
Ніл

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

1
Ой, мені було цікаво про ітерацію масиву та пошук винятку, але ви можете піти з одним кращим finally{return"1."+i;}.
Ніл

22

Python , 606 байт / 15 версій = оцінка 40,4

-67 байт (lol) завдяки NoOneIsHere.

Версії 0.9.1, 2 (.0), 2.2, 2.2.2, 2.5.0, 2,5.1, 3 (.0), 3.1, 3.1.3, 3.2.1, 3.3, 3.4, 3.5 aa 3.6 .

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

Вся заслуга дивовижної відповіді Sp3000 . Новий рядок необхідний.

Уі, це було весело гольфу. Це повинно працювати (так, я встановив кожну з цих версій), але, можливо, я випадково щось зламав. Якщо хтось знайде помилку, будь ласка, дайте мені знати.



... О, не дивно. Мені було цікаво, чому Sp3000 додає дужки в кожен printдзвінок ... Дякую, що повідомили мені!
повністюлюдський

2
Ви можете зберегти 68 байт, видаливши певні типи помилок (замініть всі excepts except:).
NoOneIsHere

Це все-таки спрацює, якби ви зробили це x=<string inside eval>замість того, щоб просто вручну вирівняти код?
Синій

@NoOneIsHere Спочатку я думав, що ти не можеш через все це 1/0, але потім я зрозумів. Дякую!
повністюлюдський

21

C ++ 14.11.17, оцінка = 147/3 = 49

Для того, щоб розрізняти C ++ 11 і С ++ 14/17, він використовує зміна за замовчуванням constності constexprфункцій членів в C ++ 14 (з кредитом наприклад на https://stackoverflow.com/questions/23980929/ що-зміни-введено-в-c14-може-потенційно-перерва-програму-написано-в-с1 ). Для розмежування C ++ 14 та C ++ 17 використовується той факт, що C ++ 17 відключив триграфи.

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

Безголівки:

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

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

(Тестовано за допомогою Debian gcc 7.1.0 за допомогою -std=c++{11,14,17}.)


1
Чудова перша відповідь! Зауважте, що, наприклад, ви можете розміщувати пробіли між вивісками includeта <включеннями у включених операторах #include<iostream>.
MD XF

1
Хм ... якщо правила були переглянуті, щоб заборонити використання стандартних відмінностей бібліотеки (яка в цьому випадку опосередковано використовує __cplusplusмакрос) - то для розрізнення C ++ 17 від C ++ 14 я б схилявся до використання зміни на основі діапазону для семантики. Можливо, створіть мінімальну кількість ітераторів / дозорних класів у boost::integer_iteratorтаких напрямках , що перетворення дозорного в ітератор має "дивовижну" поведінку.
Даніель Шеплер

4
return 0;неявна, mainтому ви можете зберегти там 9 байт. Також відповідно до wc -cвашого рішення використовується 251 байт, а не 252 (ваш редактор, можливо, вставив новий рядок в кінці).
nwp

1
Мабуть, коротше використовувати брак триграфів, щоб відокремити c ++ 17 від c ++ 14
Картопля44

1
Це би спрацювало? return *=>return*
Zacharý

19

EcmaScript 3/5/2015/2016/2017 у браузері, 59 байт / 5 версій = 11,8 бала

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

Звіт NetScape 7 3 і 5 звіту Opera 12

Збережіть 1 байт завдяки GOTO 0



Netscape 7 підтримує лише ES3? Нічого собі, він старший, ніж я думав ...
Ніл

1
Ви можете зберегти кілька байтів, використовуючи -!замість того, +!!де це має сенс (і відповідно змінити числові константи).
GOTO 0

3
Може, якесь пояснення? :)
Дерек 朕 會 功夫

@Derek: див. Моє рішення (пов'язане вище) для пояснення.
Shaggy

18

JavaScript (ES5 & ES6), 14 байт / 2 версії = 7

alert(5^"0o3")

0o- восьмі константи стилю - нові в ES6; ES5 відкидає рядок, NaNякий не впливає на результат побітового XOR.


13

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

Можна також подати рішення з більшою кількістю версій, навіть якщо воно набрало дещо вищий рівень, ніж 2-версійне рішення.

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

Спробуйте в Інтернеті

Перевіряє наявність різних методів у прототипах Array, RegExp & String, заперечує їх, надаючи логічне значення, і віднімає булеве значення від початкового значення 9. Множення ![].mapрахунків на те, що ES4 було залишено.

  • dotAllВласності (і пов'язаний з ними sпрапор) для регулярних виразів були введені в ES2018 (v9).
  • Метод padEndString був введений в ES2017 (v8).
  • Метод includesArray був введений в ES2016 (v7).
  • Метод keysArray був введений в ES2015 (v6).
  • Метод mapArray був введений в ES5.1 (v5).
  • Метод popArray був введений в ES3 (v3).

Є ES 7 або ES 8 дійсний номер версії? Може бути, це слід назвати як ES 201x?
tsh

1
@tsh: Так, вони все ще використовують номери версій; вони просто використовують роки для повторних імен .
Кудлатий


9

Befunge: 15 11 байт / 2 версії = 5,5

4 байти, поголений від @ Pietu1998

"89",;5-;,@  

Спробуйте в Інтернеті:
Befunge 93
Befunge 98
Використовує ексклюзивний оператор крапки з комою Befunge 98 ("перехід до наступної крапки з комою") для диференціації версій. Обидва надрукують "9". Befunge 93 проігнорує крапки з комою, відніме 5 з "8" (значення, залишене вгорі стека), надрукує отримане "3" і завершиться. З іншого боку, Befunge 98 пропустить, надрукує "8" та припиниться.


"89",;5-;,@для 11 байт
PurkkaKoodari

@ Pietu1998 Приємно! Якщо ви хочете опублікувати це як відповідь, я із задоволенням піднесу :)
karhell

Попередьте і візьміть його, якщо хочете, ви зрозуміли ;деталь.
PurkkaKoodari

@ Pietu1998 Відредаговано. Дякую!
karhell

FYI, мені вдалося зменшити його до 7 байт, застосувавши інший підхід. Посилання
Джеймс Холдернесс

7

Pyth 4/5 - 6 байт / 2 версії = 3

  5 ;4

У Pyth 5 рівна кількість пробілів на початку рядка ігнорується для використання в відступі, тоді як у Pyth 4 вона просто діє як єдиний пробіл і перешкоджає друку 5. У Pyth 4 крапки з комою просто закінчуються операторами, що дозволяє 4друкувати, а в Pyth 5 пробіл та крапка з комою робить решту рядка коментарем.


11
Хто знав, що Pyth мав версії?
Erik the Outgolfer

7

Python 3 та Python 2.0, 18 байт, оцінка 18/2 = 9

print(3-round(.5))

Округлення банкіра в Python 3, стандартне округлення в Python 2.

Спробуйте в Інтернеті - Python 3!

Спробуйте в Інтернеті - Python 2!


Уау Я завжди бачив людей, що розрізняють пітон 2 і 3 за поділом
phuclv

@ LưuVĩnhPhúc добре підрозділ є гравцем, тож чому: P
Стівен

7

Кубічно 4 байти, оцінка 4 / ∞

B3%0

Працює в кожній версії, у якій ваша система має достатньо пам'яті. Без конкуренції, бо це кульгавий. Дійсна для цього мета-повідомлення .

В основному, B3 обертається один ряд з лівого обличчя в верхню. F3 працював би так само, як і F₁3 або B₁3. Оскільки один рядок у кубічному форматі 3x3x3 - це три кубелі на один кубік, це додає три 1у верхню грань, надаючи йому номінальну суму 3. %0друкує цю верхню суму, друкуючи 3 для кубічно 3 x3x3.

У кубічно 4x4x4 рядки є кубиками 4x1. Вставляє 4 1 у верхню частину обличчя, отримуючи суму 4.


9
Чи не має бути оцінка 4 / ∞?
nwp

7

x86 16/32/64-бітний код машини: 11 байт, оцінка = 3,66

Ця функція повертає поточний режим (розмір операнду за замовчуванням) як ціле число в AL. Зателефонуйте з C з підписомuint8_t modedetect(void);

Машинний код NASM + список джерел (показує, як він працює в 16-бітному режимі, оскільки BITS 16говорить NASM зібрати мнемоніку джерела для 16-бітного режиму.)

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

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

Виправдання :

У машинному коді x86 офіційно немає номерів версій, але я думаю, що це задовольняє наміри питання за рахунок створення конкретних номерів, а не вибору того, що найзручніше (що займає лише 7 байт, див. нижче).

Оригінальний процесор x86, Intel 8086, підтримував лише 16-розрядний машинний код. 80386 ввів 32-розрядний машинний код (придатний для використання в 32-бітному захищеному режимі, а пізніше в режимі compat в 64-розрядної ОС). AMD представила 64-розрядний машинний код, який можна використовувати в тривалому режимі. Це версії машинної мови x86 в тому ж сенсі, що Python2 та Python3 - це різні мовні версії. Вони в основному сумісні, але з навмисними змінами. Ви можете запускати 32 або 64-бітні виконувані файли безпосередньо під 64-бітним ядром ОС так само, як ви могли запускати програми Python2 та Python3.

Як це працює:

Почніть з al=64. Перемістіть його вправо на 1 (32-бітний режим) або 2 (16-бітний режим).

  • 16/32 проти 64-бітових: 1-байт inc/ decкодування - це префікси REX у 64-бітовій версії ( http://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix ). REX.W взагалі не впливає на деякі вказівки (наприклад, a jmpабо jcc), але в цьому випадку отримати 16/32/64 я хотів ecxскоріше включити або зменшити eax. Це також встановлює REX.B, що змінює регістр призначення. Але, на щастя, ми можемо зробити це спрацьованим, але налаштування настільки настільки, що 64-розрядні не потрібно змінювати al.

    Інструкції, які виконуються лише в 16-бітному режимі, можуть включати в себе ret, але я не вважаю це необхідним чи корисним. (І зробило б неможливим вбудовувати його як фрагмент коду, якщо ви цього хочете зробити). Це також може бути jmpфункцією.

  • 16-бітний проти 32/64: безпосередні - 16-бітні, а не 32-бітні. Зміна режимів може змінити довжину інструкції, тому 32/64 бітові режими декодують наступні два байти як частину безпосередньої, а не окремої інструкції. Я просто спрощував речі, використовуючи 2-байтну інструкцію тут, замість того, щоб не декодувати синхронізацію, щоб 16-бітний режим декодувався з інших меж інструкцій, ніж 32/64.

    Пов’язано: Префікс розміру операнду змінює довжину безпосереднього (якщо тільки це 8-бітний негайний розширений знак), як і різниця між 16-бітним та 32/64-бітним режимами. Це ускладнює декодування довжини інструкцій паралельно; Процесори Intel мають стійку декодування LCP .


Більшість конвенцій, що викликають (включаючи системи x86-32 та x86-64 System V psABI), дозволяють вузьким значенням повернення містити сміття у високих бітах реєстру. Вони також дозволяють клобувати CX / ECX / RCX (і R8 для 64-розрядних). IDK, якби це було часто в 16-бітних конвенціях про дзвінки, але це код гольфу, тому я завжди можу просто сказати, що це звичайна конвенція про дзвінки.

32-розрядна розбирання :

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

64-розрядна розбирання ( спробуйте в Інтернеті! ):

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

Пов’язані дані: мій поліглот x86-32 / x86-64 код-код Q&A на ТАК.

Ще одна відмінність між 16-розрядною і 32/64 полягає в тому, що режими адресації кодуються по-різному. наприклад lea eax, [rax+2]( 8D 40 02) декодує, як lea ax, [bx+si+0x2]у 16-бітному режимі. Це, очевидно , важко використовувати для коду-гольфу, особливо з тих пір e/rbxі e/rsiякі називають збереженими в багатьох угодах про виклики.

Я також розглядав можливість використання 10-байтового mov r64, imm64, що є REX + mov r32,imm32. Але оскільки я вже мав рішення в 11 байт, це було б у кращому випадку рівним (10 байт + 1 за ret).


Тестовий код для 32 та 64-бітного режиму. (Я насправді не виконував його в 16-бітному режимі, але розбирання повідомляє вам, як він буде розшифровуватися. У мене немає 16-бітного емулятора.)

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

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

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

Ця програма для Linux виходить із статусом exit = status = modedetect(), тому запустіть її як ./a.out; echo $?. Зберіть і зв’яжіть його в статичний двійковий файл, наприклад

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

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

7 байт (бал = 2,33), якщо я можу пронумерувати версії 1, 2, 3

Офіційних номерів версій для різних режимів x86 немає. Мені просто подобається писати відповіді на Asm. Я думаю, що це порушило б намір питання, якби я просто назвав режими 1,2,3 або 0,1,2, оскільки справа в тому, щоб змусити вас генерувати незручне число. Але якщо це було дозволено:

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

Який декодується в 32-бітному режимі як

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

і 64-розрядні як

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

Я не впевнений, що це вважається різними версіями . Вони не просто співвідносяться з різними конфігураціями системи.
Уріель

1
@Uriel: Запуск блоку машинного коду з процесором у 16-бітному, 32-бітному або 64-бітному режимах є еквівалентом машинного коду роботи python2проти python3інтерпретаторів тієї ж програми Python. Нові процесори x86 завжди містять режим, сумісний із старими процесорами (це єдиний привід для використання такого складеного важко розшифрованого машино-кодового формату!), Але 32-бітний захищений режим 386 і довгий режим x86-64 насправді є нові версії машинного коду x86. Тривалий режим навіть видалив деякі коди, зробивши їх недійсними.
Пітер Кордес

5

Брахілог / Брахілог v1 , 5/2 = 2,5

2,1hw

Спробуйте в Інтернеті! (Брахілог)

Спробуйте в Інтернеті! (Брахілог v1)

Пояснення до Брахілог:

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

Пояснення для Brachylog v1:

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

Чудово! Як 2,1сторона, Brachylog v2 не будує список [2,1]( 2;1би), а скоріше число 21(яке не змінює те, як ви мали намір відповісти на роботу).
Фаталізувати

@ Fatalize Ooh дякую, що я переплутав це з Jelly ...
Ерік the Outgolfer

@Fatalize BTW 2;1не працював би в Brachylog v1, оскільки це ;означає логічний АБО там.
Erik the Outgolfer

5

C89 / C99, 25 байт, 2 версії, оцінка = 12,5

#include <stdio.h>

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

// коментарі стилю не розпізнаються в C89.

Версія для гольфу:

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

Спробуйте в Інтернеті: C89 , C99


замінити int v()на main(), він коротший і фактично складеться як повноцінна програма!
Андреа

@Andrea Дякую AFAIK, дозволено розміщувати або функції, або цілі програми.
nwellnhof

Ви маєте рацію.
Андреа

5

Perl 5 і Perl 6, 23 байти 19 байт, оцінка 9,5

print 6-grep '.',''

Perl 5 grepперший оп завжди розглядається як регулярний вираз, не так у Perl 6.


оцінка становить 19/2 = 9,5
Даніель Вестол

5

Bash, всі 4 версії, 72 71 32 байти ⇒ оцінка = 8

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

Цей фрагмент коду використовує різні інтерпретації $'...'рядків у кожній версії Bash.
Виводить основний номер версії - і все.

Тут знайдено документа .

Безголівки:

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

Ця відповідь наполовину здогадка; Я тестував його лише в bash 4 і 3, але він повинен працювати і на інших версіях.

Повідомте мене, чи це не так, я спробую використовувати інші версії, як тільки вони стануть доступними.

-1 чар завдяки Дженсу.
-29 байт завдяки Digital Trauma (вся exprідея)!


Граматика оболонки не вимагає ;;останньої альтернативи. Використовуйте ;для гоління байта.
Єнс

1
Я щойно спробував це на bash-2.05a (складений зараз для Cygwin), і він неправильно повідомляє "3", а не "2" :(
Джейсон Масгров

1
$'\xNначебто функція interpret- була додана в 2.01.1 ... мені доведеться оновити свою відповідь. Працюючи над цим
joH1

можна попросити спробувати це? s="$'\ua\xa\n'";case ${#s} in 3)echo 4;;5)echo 3;;7)echo 2;;9)echo 1;esac
joH1

1
Можливо, вам вдасться пограти в щось подібне s=$'\ua\xa\n';expr 5 - ${#s} / 2. Це працює на v3 та v4. Я не маю працюючих старих версій, щоб зараз спробувати.
Цифрова травма

4

R, версії 2 та 3, оцінка: 10,5 балів

cat(exists("cite")+2)

Ця команда повертається 2для R 2.xx та 3для R 3.xx Функція citeбула додана у версії R 3.0.0. Тому команда exists("cite")повертається FALSEдля R 2.xx і TRUEдля R 3.xx

R, всі версії (1, 2 і 3), оцінка: 12⅓ балів

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

Функція eapplyбула введена в R 2.0.0.


R.version$major. 15 символів. Я не з тих пір, коли він існує.
Rui Barradas

@RuiBarradas Дозвольте мені навести ЗП: " Ваша програма не може використовувати вбудовані, макро або спеціальні прапори компілятора для визначення мовної версії ".
Свен Хогенштайн

Добре, вибачте, я пропустив цю частину. Чи слід видалити коментар?
Rui Barradas

@RuiBarradas Немає проблем. Видаляти коментар не потрібно.
Свен Хогенштайн

Вам слід обробити результат друку. В даний час, коли запускається як повноцінна програма, це нічого не друкує.
JAD

4

Python , 196 байт / 16 версій = оцінка 12,25

Версії 1.5, 1.6, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5 та 3.6
На жаль, мені довелося залишити 2.7, оскільки в ньому немає жодних модулів це (наскільки я можу сказати), які не в 2.6, а в 3.0.

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

Ми перебираємо купу модулів, які були представлені в різних версіях python, і при першій помилці ми закриваємо і повертаємо версію. Прогалини між основними версіями заповнюються багаторазовим імпортом os. Тест на python 1.5 покладається на string.splitте, що він не присутній до 1.6.

Кредит відповідь Олів'є Грегуара за ідею тестування нових класів / модулів в циклі.

Зараз я нарешті перевірив усі відповідні версії python ... для редагування вихідного коду 1.5 для його компіляції ...


4

Пакетний файл Windows , 35 байт / 2 версії = оцінка 17.5

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

Друкується DOSна MS-DOS (duh) та NTна Windows NT. (да)

Тепер для деяких пояснень.

У Windows були створені пакетні сценарії з часів MS-DOS, і з тих пір він не сильно змінився. Однак, коли Windows NT з'явився, Microsoft змінила інтерпретатор за замовчуванням для пакетних сценаріїв з COMMAND.COMна cmd.exe(тепер також дозволяє розширення .cmdяк альтернативу оригіналу .bat).

З цим вони також здійснили кілька змін , наприклад /iпрапор ігнорування рядкового рядка на умовних умовах. Тобто, поки Z==zнеправда, /i Z==zправда.

Ми використовуємо, що у DOS не було чутливості регістру і порівнюємо великі Zрегістри з малими літерами z. Використовуючи /iпрапор, ми закінчуємо Z==z(false) умовно на DOS та z==z(true) на NT.

Тепер я розумію, що у виклику вказано, що номер версії повинен бути надрукований. Але, наскільки я знаю, немає "версії номера" для створення сценарію, тому це найближче, що я міг отримати.


Тестовано на Windows 10, DOSBox та vDos:

Windows 10:

Windows 10

(запустіть до того, cmd /kщоб вікно Prevend закрилося exit)

DOSBox:

DOSBox

vDos:

vDos


Windows 7коротше, ніж Windows NT.
користувач202729

2
@ user202729 Я думаю, але знову ж таки, 7це насправді не мовна версія, вона була однаковою для всіх Windows з 3.1. Тож я не думав, що це було б дуже справедливо, 7коли б це було можливо,3.1
Матей Авеллар,

3

Мова Wolfram / Mathematica 10/11, 37 байт / 2 версії = 18.5

Поміркуйте (Length@DateRange[{1},{1}][[1]]+27)/3, що в 37 байт і робота з 2 версіями дає мені оцінку 18,5.

In[1]:= $Version

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

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

Out[2]= 10

і

In[1]:= $Version

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

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

Out[2]= 11

Я впевнений, що існує більш ефективний спосіб, але невідповідність між результатами DateRange недавно мене покусала в зад, тому я був налаштований на використання цього.

У подальшому хтось, ймовірно, міг би скористатися Length@DateRange[{1}, {1}][[1]]оцінкою 1у версіях Mathematica 1- ~ 8, але я не встиг це включити.


2
Досить впевнений, що ваша відповідь не відповідає вимогам підказки, а саме останньому правилу, яке ви використовуєте $Version:Your program may not use a builtin, macro, or custom compiler flags to determine the language version.
Amndeep7

7
Я використовую лише $Versionдля того, щоб продемонструвати, що він дає правильний результат у правильній версії, $Versionне є частиною моєї відповіді ...
user6014

Всі добрі друже - справа в тому, що ви використовуєте щось на кшталт $VersionNumber, але натомість ви це називаєте $Version. На мій погляд, хоча м'ясо вашої програми - це Length@DateRangeречі, які не працюватимуть, не $Versionнадаючи лише повну інформацію про версію, яку ви потім обробляєте, що, таким чином, порушує правила.
Amndeep7

4
@ Amndeep7 Подання - це 37-байтний код, зазначений у першому абзаці. Кодові блоки є лише демонстрацією виводу.
PurkkaKoodari

3
Пояснення: Використання різного формату часу в різних версіях. Це може бути в гольф більше {1} Tr[1^#&@@%~DateRange~%]/3+9(31 байт) або навіть 7+Length@Now(12 байт)
user202729

3

Ruby 1.x і 2.x, 20 байт, оцінка 10

p [].to_h&&2rescue 1

На основі to_hметоду, який був представлений на Arrayуроці в Ruby 2.


Приємна перша відповідь. У мене немає 1.x зручного тестування, але p [].to_h&&2rescue 1він трохи коротший.
манатура

@manatwork Чудово, економить 3 байти і працює як шарм
Філіп Френк

3

Ерланг, 180 байт, 11 версій, оцінка 16,36

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

З відступом та розривами рядків:

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

Тестується на одному незначному випуску кожної основної версії з 10:

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

Ідея полягає в тому, що кожен головний випуск додав принаймні один новий допустимий аргумент для функції erlang:system_info, тому давайте спробуємо ті зі списку, порахуємо, скільки з них виходять з ладу, і віднімемо кількість відмов від 20, яка є поточною версією.


3

Джулія 0,4, 0,5, 46 байт, оцінка 22

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

У багатьох версіях Юлія змінила назву типу конкретного та абстрактного типів String.

Зокрема, цим кодом користуються:

Джулія 0,4 :

  • Бетон є ASCIIString,
  • Анотація офіційно AbstractString,
  • Анотація застаріла псевдонім до String.
  • Бетон найбільш специфічний, ніж абстрактний, тому він виграє відправлення

Джулія 0,5 :

  • Бетон офіційно String,
  • Бетон застарів псевдонім до ASCIIString,
  • Анотація є AbstractString(хоча це тут не має значення)
  • Оскільки два типи конкретних рядків були визначені двома методами, останній переписує перший.

Дивіться також моє нове більш ефективне рішення, засноване на різних принципах


3

Япт (1 і 2), 8 6/2 = 4 3

'1r\S2

Тест v1  |   Тест v2


Пояснення

До версії v2 Japt використовував індивідуальний синтаксис RegEx, тому ми можемо цим скористатися.

'1

Число 1 як рядок.

 r  2

Замініть ( r) наведене нижче на a 2.

\S

Japt 2 сприймає це як RegEx /\S/g, який відповідає 1. Japt 1 ігнорує \символ втечі і просто бачить S, що є константою Japt для символу пробілу і, очевидно, не відповідає 1.


3

Befunge, оцінка = 3,5

7 байт, 2 версії

"]"'b.@

Спробуйте в режимі он-лайн у Befunge-93
Спробуйте в режимі он-лайн у Befunge-98

"]"є рядковим літералом в обох версіях, виштовхуючи 93 (значення ASCII [) на стек. 'bє символом літералу в Befunge-98, натисканням 98 (значення ASCII b), але це недійсні інструкції в Befunge-93, тому їх просто ігнорують. Таким чином, ми закінчуємо 93 на вершині стека у Befunge-93 та 98 у Befunge-98. .@записує значення у верхній частині стека, а потім виходить.


]".@.b'або ]g.@.b'також працюйте
MildlyMilquetoast

3

Ruby 1.x (<1.9) і 2.x, 10 8 байт, оцінка = 4

$><<?2%7

Спробуй це:

Це працює, використовуючи різні способи поведінки ?xміж Ruby 1.x та 2.x. У Ruby 1.x ?A(наприклад) повертається 65(значення ASCII символу A), але в Ruby 2.0 повертає односимвольну рядок "A".

Код, наведений вище, еквівалентний цьому:

val = ?2
$> << val % 7

В Ruby 1.x (<1,9), значення valє 50(значення ASCII - символу 2), A Fixnum. Fixnum#%є оператором модуля, тому 50 % 7повертається 1.

У Ruby 2.x val- рядок "2". String#%є інфіксованою версією sprintf, тому "2" % 7еквівалентно sprintf("2", 7), де "2"знаходиться рядок формату. Оскільки рядок формату не містить послідовностей формату (наприклад %d), наступні аргументи відкидаються та "2"повертаються.

Нарешті, $>це псевдонім для $stdout, тому $> << ...друкується результат.


1
О, приємно! Я намагався зробити щось подібне ?A==66?1:2до того, як я натрапив на вашу відповідь
Пікколо

3

Python 2 та Python 3 , 36 34 байти, оцінка 18 17

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

У Python 2 хеш негативної нескінченності становить -271828, а в Python 3 -314159. Редагувати: Збережено 2 байти, 1 бал, завдяки @ArBo.


коситься Це цілеспрямована річ e vs pi?
Джо Кінг

@JoKing Так; Очевидно, коли hashвперше було зафіксовано роботу над нескінченностями з плаваючою комою, відповідний розробник використав pi * 1e5 та e * -1e5 як хеш-значень. У якийсь момент на Python 3 значення негативної нескінченності змінилося на заперечення хеш-значення для нескінченності.
Ніл

2

Python 3 , Python 2 , оцінка 17,5

(35 байт, 2 версії)

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

Python 2 , 35 байт

Спробуйте в Інтернеті!

Python 3 , 35 байт

Спробуйте в Інтернеті!

Збережено 5 байт завдяки ETHproductions

Не гарний відповідь коду на гольф, але масштабна зміна!


Хм, чи можете ви поставити кожне твердження в попередньому рядку? Тобтоtry:exec("print 2")\nexcept:print(3)
ETHproductions

@ETHproductions спасибі! Я не сподівався на перемогу, тому мене трохи відволікали. В основному я хотів би зосередитися на на масивне зміна між Python 2 і 3.
jferard
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.