Determine your language's version

Python 3.0 and Python 2, score 6

(12 bytes, 2 versions)


Try it Online:

  • Python 2

  • Python 3

Relies on the fact that Python 3+ uses float division by default, unlike Python 2, which uses floor division.

Java, 189 bytes, 10 versions, score = 18.9

Supported versions: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8 and 9

(For previous scores, check the history!)

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

Run it on Java 8
Run it on Java 9 or later


Object v(){
  int v=0;
  try {
      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
  } 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

Please note that the code part return v<9?"1."+v:v; (previously return(v<9?"1.":"")+v;) needs to be checked against any version between Java 1.0 and Java 1.3 included. I don't have any Java 1.3 or earlier installation at my disposal to actually test this syntax.


The Java versioning has a special history. All versions have historically been 1.x including 1.0. But... from Java 9 onwards and the JEP223, the version scheming has changed from using 1.x to x. That is the version as internally known. So we have the following table (put together with the Javadoc and Wikipedia):

java.version property Release name Product name
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

This challenge entry matches the version column in the table above, which is what is contained in the system property "java.version".


The goal is to check from which version a class starts to exist, because Java deprecates code but never removes it. The code has been specifically written in Java 1.0 to be compatible with all the versions, again, because the JDK is (mostly) source forward compatible.

The implementation tries to find the shortest class names that each version introduced. Though, to gain bytes, it's needed to try and pick a common subpackage. So far I found the most efficient package is java.util because it contains several really short-named classes spread across all versions of Java.

Now, to find the actual version number, the class names are sorted by introducing version. Then I try to instanciate each class sequentially, and increment the array index. If the class exists, we skip to the next, otherwise we let the exception be caught by the try-block. When done, another exception is thrown because there are no more classes whose existence we need to check.

In any case, the thread will leave the try-block with an exception. That exception is not caught, but simply put on hold thanks to the finally-block, which in turn overrides the on-hold exception by actually returning a value which is "1."+v where v is the index used before. It also happens we made this index match the minor version number of Java.

An important part of the golf was to find the shortest new class name in the package java.util (or any children package) for each version. Here is the table I used to compute that cost.

Version Full name (cost in chars) Reduced name (cost in chars)
9 (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]
Full name (cost in chars) Reduced name (cost in chars)
Subtotal 144 chars 54 chars
Base 0 chars 10 chars (java.util.)
Total 144 chars 64 chars


  • 30 bytes saved thanks to Kevin Cruijssen (although I was doing it before I read his comment, I promise!).
  • 26 further bytes saved thanks to Neil (nope, I wasn't thinking about doing that)
  • 12 bytes thanks to Nevay and the nice out-of-the-box-try-catch thinking!
  • 11 more bytes by Neil again and the nice portable finally trick.
  • 2 more bytes thanks to Kevin Cruijssen by replacing return(i<9?"1.":"")+i; with return i<9?"1."+i:i; (this needs to be validated against 1.0 or at most 1.3 since no syntax changes happened before 1.4)

With builtins

If builtins were allowed:

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

54 bytes for 16 versions (from 1.0 to 15), so the score would be 3.375.

Python, 606 bytes / 15 versions = score 40.4

-67 bytes (lol) thanks to NoOneIsHere.

The versions are 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 aaand 3.6.

try:from email import _Parser;print(2.2);1/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:import enum

All credit to Sp3000's amazing answer. The trailing newline is necessary.

Whee, that was fun to golf. This should work (yes, I installed every one of these versions), but I might've accidentally borked something. If anybody finds a bug, please let me know.