# Question
Title: Print A-Z and their alphabet index without using 1,2,4,6
You need to print A-Z like this:

```
1. A
2. B
3. C
4. D
5. E
6. F
7. G
8. H
9. I
10. J
11. K
12. L
13. M
14. N
15. O
16. P
17. Q
18. R
19. S
20. T
21. U
22. V
23. W
24. X
25. Y
26. Z

```

But your source code cannot use `1,2,4,6`.

Trailing newlines in output allowed,, but leading ones not allowed.

Standard loopholes apply, shortest code wins.

# Answer
> 6 votes
# Python 2, 44 bytes

```
i=8*8
while i<90:i=-~i;print`i-8*8`+'. %c'%i

```

Try it online!

**46 bytes**

```
i=0
while i<33-7:i=-~i;print'%d. %c'%(i,i+8*8)

```

Try it online!

The loop condition can also be `while-~i/9-3:` or `while~-i/5-5` or `while-i/5-~5:` or `while~-i-5*5:` or `while~-033>i`.

**46 bytes**

```
i=0
exec 78/3*"i=-~i;print'%d. %c'%(i,i+8*8);"

```

Try it online!

**46 bytes**

```
i=8*8
while i<90:i=-~i;print'%d. %c'%(i-8*8,i)

```

Try it online!

**46 bytes**

```
i=0
while~i-5*5:i=~-i;print'%d. %c'%(-i,8*8-i)

```

Try it online!

**46 bytes**

```
i=8*8
while i<90:i=-~i;print'%d. %c'%(i&799,i)

```

Try it online!

**47 bytes**

```
for i in range(33-7):print"%d. %c"%(-~i,8*8-~i)

```

Try it online!

# Answer
> 6 votes
# Zsh, 27 bytes

```
eval ';echo $[++i]. '{A..Z}

```

Try it online!

# Answer
> 6 votes
# JavaScript (Node.js), 48 bytes

```
f=(n=033)=>--n?f(n)+n+`. ${Buffer([8*8|n])}
`:''

```

Try it online!

# Answer
> 5 votes
# APL (Dyalog Extended), 19 bytes (SBCS)

```
↑(⍳∘≢,⍥⍕¨'. '∘,¨)⎕A

```

Try it online!

`⎕A` the uppercase **A**lphabet

`(``)` apply the following tacit function:

`'. '∘,¨` prepend ". " to each letter.

`,⍥⍕¨` concatenate the string representation of each to the string representation of:

`⍳∘≢` the **ɩ**ndices of the length of the alphabet

"mix" the list of strings into a character matrix

# Answer
> 5 votes
# PHP, ~~45~~ ~~40~~ ~~39~~ 38 bytes

```
for($c=A;$c<>AA;$c++)echo++$i,". $c
";

```

Try it online!

-1 thanks to Kaddath

# Answer
> 3 votes
# 05AB1E, 9 bytes

```
Auā'.«sø»

```

Try it online!

```
A          # push the lowercase alphabet
 u         # convert to uppercase
  ā        # push the range [1 .. len(alphabet)]
   '.«    '# append '.' to each number
      s    # swap to the alphabet
       ø   # zip both lists => [['1.', 'A'], ..., ['26.', 'Z']]
        »  # join each inner list by spaces and the outer list by newlines

```

# Answer
> 3 votes
# Charcoal, 9 bytes

```
Ｅα⁺⁺⊕κ. ι

```

Try it online! Link is to verbose version of code. Explanation:

```
 α          Predefined variable uppercase alphabet
Ｅ           Map over characters
     κ      Current index (0-indexed)
    ⊕       Incremented
      .     Literal string `. `
        ι   Current character
  ⁺⁺        All concatenated
            Implicitly print on separate lines

```

# Answer
> 3 votes
# Perl 5.10, 22 bytes

```
say++$..". $_"for A..Z

```

Try it online!

# Answer
> 3 votes
# , 33 bytes

```
write.table(LETTERS,,,F,". ",c=F)

```

Try it online!

# Answer
> 2 votes
# Canvas, 8 bytes

```
Ｚ｛²Ｏ. ｏｏ

```

Try it here!, alternate version

The only reason this is shorter than charcoal is because it's got a 1-indexed iteration count.

## Explanation

```
Z{²O. oo
Z{       loop over the alphabet
  ²O     output the iteration number
    . o  output ". "
       o output the current letter

```

# Answer
> 2 votes
# Retina 0.8.2, ~~49~~ ~~29~~ 28 bytes

```
T`@L`_o
}`$
Z
.
$.`. $&¶
A`@

```

Try it online! Explanation:

```
T`@L`_o
}`$
Z

```

Generate the uppercase alphabet prefixed by `@`. This works by feeding in `Z`s and transliterating a step backwards each time until the transformation becomes idempotent.

```
.
$.`. $&¶

```

Prefix each character with its 0-based index and `.` , and split each character on to its own line.

```
A`@

```

Delete the `@` entry.

# Answer
> 2 votes
# PowerShell, 25 bytes

```
'A'..'Z'|%{++$i;"$i. $_"}

```

Try it online!

# Answer
> 2 votes
# BASIC, 41 bytes

```
for i=!0 to 33-7:?i,". ",chr$(8*8+i):next

```

Try it online!

# Answer
> 1 votes
# PowerShell, 41 bytes

```
(8-7)..(33-7)|%{"$($_). "+[char]($_+8*8)}

```

Try it online!

# Answer
> 1 votes
# Python 3, ~~52~~ 50 bytes

```
for x in range(8-7,33-6):print(f"{x}.",chr(x+8*8))

```

Try it online!

# Answer
> 1 votes
# Javascript (Browser console), 58 bytes

```
for(i=0;i<35-9;)alert(++i+". "+String.fromCharCode(i+8*8))

```

-2 bytes thanks to @expressjs123 -3 bytes thanks to @tsh

# Answer
> 1 votes
# Vyxal, `j`, 10 bytes

```
αɾkAZƛı. j

```

Try it Online!

# Answer
> 1 votes
# Retina, 27 bytes

```

3*9*@
Y`@`L_
L$`.
$.>`. $&

```

Try it online! Explanation:

```

3*9*@

```

Insert 27 `@`s. (Best I can do since I can't use `2` or `6`.)

```
Y`@`L_

```

Replace each `@` with subsequent uppercase letters, but delete the last one.

```
L$`.

```

Match each letter.

```
$.>`. $&

```

For each letter, output its 1-indexed index, `.` , then the letter.

# Answer
> 1 votes
# Jelly, ~~10~~ 9 bytes

```
ØAĖj€⁾. Y

```

Try it online!

## How it works

```
ØAĖj€⁾. Y - Main link. Takes no arguments
ØA        - Yield the uppercase alphabet and set as the left and right arguments
  Ė       - Enumerate
   j€⁾.   - Join each pair with ". "
        Y - Join with newlines and output

```

# Answer
> 1 votes
# Japt, 12 bytes

```
;B£[YÄLSXR]q

```

Try it online!

Straightforward, though I feel like there's still room for improvement.

Explanation:

```
;B£[YÄLSXR]q    #
;               # Store the uppercase alphabet in B
 B£             # Replace each character in B with the following:
   [      ]     #  Make an array containing:
    YÄ          #   The 0-based index of the character + 1 (i.e. 1-based index)
      L         #   Period
       S        #   Space
        X       #   The original character
         R      #   A newline
           q    #  Join the array into a string with no separator
                # Implicitly output the resulting string

```

# Answer
> 1 votes
# Rust, 56 bytes

```
||for(i,x)in(9..).zip('A'..'['){print!("{}. {}
",i-8,x)}

```

# Answer
> 1 votes
# Java, 62 bytes

```
$->{for(char c='@';++c<'[';)System.out.println(c-'@'+". "+c);}

```

Try it online!

# Java, 95 bytes

```
$->java.util.stream.IntStream.range('A','[').forEach(i->System.out.println(i-'@'+". "+(char)i))

```

Try it online!

# Answer
> 1 votes
# Lua (55 bytes)

```
for i=7%3,33-7 do print(i..". "..(8*8+i..""):char())end

```

# Answer
> 1 votes
# Bash, 41 bytes

```
echo {A..Z}|tr ' ' '
'|nl -s". " -w$[8-7]

```

Try it online!

# Answer
> 1 votes
# Julia 1.0, ~~37~~ 35 bytes

```
'A':'Z'.|>i->print("$(i-'@'). $i
")

```

Try it online!

# Answer
> 1 votes
# Japt `-R`, 11 bytes

```
;B¬ËiSiLiEÄ

```

Test it

# Answer
> 0 votes
# C

```
main() { for(int i='A',j=0;i<='Z';j++,printf("%d. %c\n",j,i),i++);}

```

If for some, this wouldn't work:

```
#include <stdio.h>
void main() { for(int i='A',j=0;i<='Z';j++,printf("%d. %c\n",j,i),i++);}

```

# Answer
> 0 votes
# C (gcc), 50 bytes

```
f(i){for(i=0;++i<033;)printf("%d. %c\n",i,i+'@');}

```

Try it online!

# Answer
> 0 votes
# C (gcc), 50 bytes

```
main(i){for(;i<3*9;printf("%d. %c\n",i++,i+8*8));}

```

Try it online!

```
f(i){for(i=0;++i<3*9;printf("%d. %c\n",i,i+8*8));}

```

Try it online!

# Answer
> 0 votes
# Stax, ~~9~~ 8 bytes

```
τ┌Z*µ╝╘Q

```

Run and debug it

# Answer
> 0 votes
# Pyth, 15 bytes

```
j.e+++hk\.dbrG1

```

Try it online!

---

Python 3 translation:

```
G = "abcdefghijklmnopqrstuvwzyz"

print("\n".join(map(lambda(k,b):str(k+1)+"."+" "+b,enumerate(G.upper()))))

```

# Answer
> 0 votes
# APL (Dyalog Unicode), 27 bytes

```
⎕∘←¨⎕a,⍨¨{'. ',⍨⍕⍵}¨⍳⎕a⍳'Z'

```

Try it online!

# Answer
> 0 votes
# Knight, 38 bytes

```
;=a 0W>+*5 5TaO+++''=a++0Ta'. 'A+*8 8a

```

Try It Online!

# Answer
> 0 votes
# Uiua 0.3.1, 23 bytes

```
∵(&p$"_. _":+@@.)⊝⊚⇡ⁿ.3

```

See it in action

---
Tags: code-golf, kolmogorov-complexity, restricted-source
---


# Question
Title: Convert real numbers between factoradic and positive integer bases
This prompt asked you to convert back and forth to factoradic, but is very limited in scope (only decimal integers from 0 to 10!-1). Your task in this challenge is to reach just a bit further and fully implement conversion between factoradic and any other integer base.

The factoradic system is extended to the reals by using reciprocals of factorials:

```
43210.001234 (max value at each position, ==DEC119.991666666... and ==DEC14399/120)
= 4      3      2      1      0   .  0        0        1        2        3        4
= 4*4! + 3*3! + 2*2! + 1*1! + 0*0! + 0*1/0! + 0*1/1! + 1*1/2! + 2*1/3! + 3*1/4! + 4*1/5!
= 96   + 18   + 4    + 1    + 0    + 0      + 0      + 1/2    + 1/3    + 1/8    + 1/30
= 119+119/120 (last two here lines are in decimal; but same idea for any other base)

```

Because of how this is defined, any real factoradic number has at most \[denominator+1\] digits past the decimal. As you can see from the above example, which has significantly less than 121 digits after the decimal, the number of digits required is much less for numbers with lots of factors. To convert in the other direction, a real numer a/b -\> factoradic, requires a bit more effort. There may be an easier way to do this, but I couldn't find anyone who has done this before so I had to work out the formula myself. If you come up with an easier formula feel free to add it. Since we're working in multiple bases here, clarification may be needed: a number prefixed by a 3-letter abbreviation is being represented in the base which that prefix corresponds to, I am using the notation of `baseN(#)` to mean `convert number # to base N`, and unspecified numbers are in decimal for convenience.

```
14399/120 = 119 + 119/120

whole number portion:
119  / 4! = 4 r 23
23   / 3! = 3 r 5
5    / 2! = 2 r 1
1    / 1! = 1 r 0
0    / 0! = 0 r 0

fraction portion:
119/120 = 119/5!
base5(DEC119) = 434 (43 4)
base4(QUI43)  = 113 (11 3)
base3(QUA11)  = 12   (1 2)
base2(TRI1)   = 1    (0 1)
base1(BIN0)   = 0    (0 0)
base0(UNA0)   = 0    (0 0)

factorial:
43210.001234

bigger example:
123454321/11 = 11223120 + 1/11

whole number portion:
11223120 / 10! = 3 r 336720
336720   / 9!  = 0 r 336720
336720   / 8!  = 8 r 14160
14160    / 7!  = 2 r 4080
4080     / 6!  = 5 r 480
480      / 5!  = 4 r 0
0        / 4!  = 0 r 0
0        / 3!  = 0 r 0
0        / 2!  = 0 r 0
0        / 1!  = 0 r 0
0        / 0!  = 0 r 0

fraction portion:
1/11 = (1*(11-1)!)/11! = 3628800/11!

base11(DEC3628800) = 205940A (205940 A)
base10(ELE205940)  = 329890   (32989 0)
base9(DEC32989)    = 50224     (5022 4)
base8(NON5022)     = 7121       (712 1)
base7(OCT712)      = 1223       (122 3)
base6(SEP112)      = 145         (14 5)
base5(SEX14)       = 20           (2 0)
base4(QUI2)        = 2            (0 2)
base3(QUA0)        = 0            (0 0)
base2(TRI0)        = 0            (0 0)
base1(BIN0)        = 0            (0 0)
base0(UNA0)        = 0            (0 0)

factorial number:
30825400000.00002053140A

converting number n0 from base b1 to b2:
n0/b2 = n1 r d1     ( this only works )
n1/b2 = n2 r d2     ( if you actually )
n2/b2 = n3 r d3     ( do all the work )
..until n<b2...     ( in the 1st base )
n0 in b1 is n:...:d3:d2:d1 in b2, where
a colon represents separation of digits

if you can't do operations in other bases, first convert to base 10:
digit1 * b1^(#digits) + digit2 * b1^(#digits-1) + ... + digitn * b1^0 = number_in_base10

```

In words:
For the whole number part you take the floor of the number, and divide it by the largest factorial less than it, using the floor of that answer as the next digit and the remainder as the next argument.
For the fraction part, you multiply top and bottom until the denominator is a factorial n!, and convert the numerator to base n. Then remove the last digit and convert to the next lower base, using the full sequence of removed digits as the decimal.

You may notice that the three middle digits (...0.00...) are always 0. You may either include or exclude them, but state in your answer which you are going to do, and be consistent (ie, either your input and output both always use the abbreviated form like !1.1=DEC3/2 or they both always use the complete form like !10.001=DEC3/2).

Your code should take as input an input & output base, along with a real number represented in the input base, and then output that same real number in the output base. (depricated req) Note that at some point you will need to select a sub-base to represent the digits of numbers in bases larger than you can represent with one character. The higher you can get without falling back onto a sub-base the happier you will make me personally.

You may assume exactly one of either 'input' or 'output' must be in factoradic. Your output must take the same format as your input, ie your code should be able to back-convert anything it outputs. Numbers should be output in their simplest form (ie no leading/trailing 0's; no #/1's, 0/#'s, or #/0's; no -0; no #/-# or -#/-#; 6/4 -\> 3/2; etc). (depricated req) In the spirit of flexible I/O you may use the default representation of higher-number bases for your language. Please state in your answer what format your numbers will use.

You may define the format for specifying 'input and output bases' in any way you like, as long as it can represent any integer base \>= 2 and specifies whether the input will be going into or out of factoradic.
You may represent the non-factoradic number as either a/b (recommended) or as a real number n; if you use real number n as your input and output format you have to come up with a way to represent repeated digits like in DEC1/3, DEC1/7, or DEC1/28 (eg, digits after some delimiter repeat or something).
The factoradic part must be one number, you may not separately convert the numerator and denominator and return a fraction.

Examples:

```
radix: decimal-in
number: 14399/120
output: 43210.001234

radix: decimal-out
number: -43210.001234
output: -14399/120

radix: decimal-in
number: 123454321/11
output: 30825400000.00002053140A

radix: octal-in
number: -11656
output: -6543200

radix: hex-out
number: 42130100.001004
output: 4FD06/F

radix: 100-in
number(sub-base is hex): 1c|3|2f|62|35|5a|3/1|1e|4c|4a|24|50|0
output: 3110.0002223571381ccd

radix: binary-in
number: 0
output: 0

```

so shortest code in each language wins. You may assume input always follows your specified format, and it will always be a valid output as if your code had been given its own output and told to convert the other way. The logic of your code should work for any real number, converting between any positive integer base \>=2 and factoradic in either direction. If your language has a built-in factoradic conversion function, you may include a secondary answer to show it off, but your first answer should not use it. Other integer base -\> integer base conversion functions are fine.

# Answer
> 1 votes
# Jelly, ~~94~~ 93 bytes

```
⁹1!ḍ@¥1#ḢR;!:¥ɗU×1¦%Ḣd¥\FḊU
:1!>¥1#Ḣ’!€Ɗ;ƲUṪd¥\FḊ,ç
ḅç/
ẈḶ!U×¥:@ƭ€FṀ$©$ḋ⁸S;®:g/$b
A⁵ŀ⁹×1¦ṠFḢɗ

```

Try it online!

Test suite

A full program taking three arguments. The first argument is a list of two lists of integers. This will be base digits for the numerator and denominator if converting to the factoradic representation. If converting from factoradic representation, it will be the factoradic digits before and after the point. The second argument will be an integer representing the base and the third will be the integer `3` for conversion to factoradic representation and `4` for conversion from factoradic representation. The program prints a list of lists of integers representing the results of the conversion. When converting from factoradic, the result will always be a fraction in its simplest form, with a denominator of 1 for integers. When converting to factoradic, a zero whole number portion is represented as an empty list, while after the point there will always be the two fixed zeros (even if there are no other digits).

The TIO link runs a series of five variants of the test cases from the question, first converting to factoradic and then back again.

Integer maths is used throughout, so should handle any size of input.

## Explanation

```
⁹1!ḍ@¥1#ḢR;!:¥ɗU×1¦%Ḣd¥\FḊU  # Helper link 1: takes numerator as left argument and denominator as right argument and returns the portion of the factoriadic representation after the point
⁹                            # Right argument (denominator)
 1!ḍ@¥1#Ḣ                    # Starting at 1, find the first integer where the factorial is divisible by the denominator (referred to as z below)
              ɗ              # Following as a dyad with the original denominator as the right argument
         R                   # - Range (1 to z)
          ;  ¥               # - Concatenated to:
           !:                #   - The result
                             # of dividing the factorial of z by the original denominator
               U             # Reverse the order of the list
                ×1¦%         # Multiply the first number (z!/denominator) by the result of numerator mod denominator
                    Ḣd¥\     # Reduce by popping the head and then taking divmod the next member of the list, collecting up intermediate results
                        F    # Flatten
                         Ḋ   # Remove the original starting point for the reduction
                          U  # Reverse the order of the list

:1!>¥1#Ḣ’!€Ɗ;ƲUṪd¥\FḊ,ç      # Helper link 2: takes numerator as left argument and denominator as right argument and returns the factoriadic representation
:                            # Integer divide numerator by denominator
             Ʋ               # Following as a monad:
 1!>¥1#Ḣ                     # - Starting with one, find the first integer that has a factorial greater than this
           Ɗ                 # - Following as a monad:
        ’                    #   - Decrease by 1
         !€                  #   - Factorial of each integer from 1 to this
            ;                # - Concatenate to floor(numerator/denominator)
              U              # Reverse order of the list
               Ṫd¥\          # Reduce by popping the tail and then taking divmod the next member of the list, collecting up intermediate results
                   F         # Flatten
                    Ḋ        # Remove the original starting point for the reduction
                     ,ç      # Pair to the result of calling helper link 1 with the original arguments to this link

ḅç/                          # Helper link 3: takes the numerator
                             # and denominator as base digits as the left argument and a base as the right. Converts from that base, then calls helper link 2 with the numerator as the left argument and denominator as the right

ẈḶ!U×¥:@ƭ€FṀ$©$ḋ⁸S;®:g/$b   # Helper link 4: takes a factoradic representation as the left argument and a base as the right. Returns the base digits of the numerator and denominator after converting from factoradic
Ẉ                           # Lengths of list
 Ḷ                          # Range from
                            # 0..each of these lengths -1
  !                         # Factorial (vectorised)
              $             # Following as a monad:
        ƭ€FṀ$©              # Use the following,  first chain for the first argument, second for the second, in both cases using the max of the flattened list as the right argument (and also preserving this max in the register)
   U×¥                      # - For the first argument, reverse the order and multiply by the max of the flattened list
      :@                    # - For the second, divide the max of the flattened list by this
               ḋ⁸           # Dot product with the original left argument
                 S          # Sum
                  ;®        # Append the register
                    :g/$    # Divide by the GCD of these (simplifying the fraction)
                        b   # Convert to the requested base

A⁵ŀ⁹×1¦ṠFḢɗ                  # Main link
A                            # Absolute
 ⁵ŀ⁹                         # Call the helper link indicated by argument 3
    ×1¦   ɗ                  # Multiply the first part of the result by:
       ṠFḢ                   # The first sign of the original first argument, flattened

```

Created with the help of Luminespire.

---
Tags: code-golf, math, number, base-conversion, factorial
---


title: Determine your language's version

text:
# Question
Title: Determine your language's version
Your challenge is to write a polyglot that works in different versions of your language. When run, it will always output the language version.

# Rules

* Your program should work in at least two versions of your language.
* Your program's output should *only* be the version number. No extraneous data.
* Your program may use whatever method you like to determine the version number. However, the output must follow rule 2; however you determine the version number, the output must only be the number.
* Your program only needs to output the major version of the language. For example, in FooBar 12.3.456789-beta, your program would only need to output 12.
* If your language puts words or symbols before or after the version number, you do not need to output those, and only the number. For example, in C89, your program only needs to print `89`, and in C++0x, your program only needs to print `0`.
* If you choose to print the full name or minor version numbers, e.g. C89 as opposed to C99, it must *only* print the name. `C89 build 32` is valid, while `error in C89 build 32: foo bar` is not.
* Your program may not use a builtin, macro, or custom compiler flags to determine the language version.

# Scoring

Your score will be the code length divided by the number of versions it works in. Lowest score wins, good luck!

# Answer
# Seriously and Actually, 3 bytes, score 1.5

```
'1u

```

Try it online: Actually, Seriously

Explanation:

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

```

`u` and `D` having functionality on strings was only added in Actually (which is Seriously v2).
> 20 votes

# Answer
# Python 3.0 and Python 2, score 6

(12 bytes, 2 versions)

```
print(3/2*2)

```

Try it Online:

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

# Answer
# Java, 400 bytes, 17 versions, score = 23,52

Supported versions: `1.0`, `1.1`, `1.2`, `1.3`, `1.4`, `1.5`, `1.6`, `1.7`, `1.8`, `9`, `11`, `12`, `14`, `15`, `16`, `17` and `18`. Unsupported vesions: `10` and `13` since they have no new classes at all.

(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","Map","java.security.interfaces.XECKey","java.lang.Enum$EnumDesc","Map","java.io.Serial","java.security.spec.EdECPoint","java.lang.Record","HexFormat","java.net.spi.InetAddressResolver"};;i++)Class.forName(s[i].charAt(0)=='j'?s[i]:"java.util."+s[i]);}finally{return i<9?"1."+i:i;}}
```

Attempt This Online!

### 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
        "Map",             // 10 is unsupported so use the smallest name possible.
        "java.security.interfaces.XECKey",   // 11
        "Enum$EnumDesc",                     // 12
        "Map",             // 13 is unsupported so use the smallest name possible.
        "java.io.Serial",  // 14
        "java.security.spec.EdECPoint",      // 15
        "java.lang.Record",                  // 16
        "HexFormat",                         // 17
        "java.net.spi.InetAddressResolver"   // 18
      };;v++)
      Class.forName(
        s[i].charAt(0)=='j'     // If the package name is referenced,
          ? s[i]                // Use it
          : "java.util."+s[i]); // Else, prepend "java.util".
  } 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.

### Introduction

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 |
| ... | ... | ... |
| 18 | Java SE 18 | Java 18 |

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

### Explanation

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.

Note: what is below needs to be updated.

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 | `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\] |

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

### Credits

* 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 19 versions (from 1.0 to 18), so the score would be 2,84.
> 70 votes

# Answer
# 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: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)

```

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.
> 30 votes

# Answer
# EcmaScript 3 / 5 / 2015 / 2016 / 2017 in Browser, 59 bytes / 5 versions = 11.8 points

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

Save 1 byte thanks to GOTO 0
> 22 votes

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

To distinguish between C++11 and C++14/17, it uses the change in the default `const`ness of `constexpr` member functions in C++14 (with credit to the example at https://stackoverflow.com/questions/23980929/what-changes-introduced-in-c14-can-potentially-break-a-program-written-in-c1). To distinguish between C++14 and C++17, it uses the fact that C++17 disabled trigraphs.

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

```

(Tested with Debian gcc 7.1.0 using `-std=c++{11,14,17}`.)
> 21 votes

# Answer
## JavaScript (ES5 & ES6), 14 bytes / 2 versions = 7

```
alert(5^"0o3")

```

`0o`-style octal constants are new in ES6; ES5 casts the string to `NaN` which doesn't affect the result of the bitwise XOR.
> 19 votes

# Answer
# JavaScript (ES 2, 3 & 5 - ~~8 9~~ 11), ~~59 / 6 = 9.833 75 / 7 = 10.714~~ 98 / 9 = 10.889

May as well submit the solution with more versions, even if it does score slightly higher than the 2-version solution.

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

```

Try it online

Checks for the presence of various methods in the Array, RegExp & String prototypes, negates them, giving a boolean, and subtracts that boolean from an initial value of 11. The multiplication of `![].map` accounts for the fact that ES4 was abandoned.

* The `matchAll` String method was introduced in ES2019 (v11).
* The `flat` Array method was introduced in ES2020 (v10).
* The `dotAll` property (and related `s` flag) for Regular Expressions was introduced in ES2018 (v9).
* The `padEnd` String method was introduced in ES2017 (v8).
* The `includes` Array method was introduced in ES2016 (v7).
* The `keys` Array method was introduced in ES2015 (v6).
* The `map` Array method was introduced in ES5.1 (v5).
* The `pop` Array method was introduced in ES3 (v3).
> 13 votes

# Answer
# PHP 5/7, score 5.5

```
<?=7-"0x2";

```

3V4L it online!

# PHP 5.3.9/5.3.11, score 10

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

```

3V4L it online!

The online version is longer because old PHP versions on the sandbox don't have short tags enabled.
> 10 votes

# Answer
# x86 16/32/64-bit machine code: 11 bytes, score= 3.66

This function returns the current mode (default address-size) as an integer in AL. Call it from C with signature `uint8_t modedetect(void);`. (Or more realistically, from machine code that's going to branch on the result using instruction encodings that decode the same in all modes.)

NASM machine-code + source listing (showing how it works in 16-bit mode, since `BITS 16` tells NASM to assemble the source mnemonics for 16-bit mode.)

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

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

```

**Justification**:

x86 machine code doesn't officially have version numbers, but I think this satisfies the intent of the question by having to produce specific numbers, rather than choosing what's most convenient (that only takes 7 bytes, see below).

Another interesting way to interpret the question would be to write 16-bit code to detect 8086 vs. 186 vs. 286 vs. 386, etc, as in this example, based on FLAGS and other behaviour, because each new "version" added new features (including instruction opcodes). But that's not what this answer does.

The original x86 CPU, Intel's 8086, only supported 16-bit machine code. 80386 introduced 32-bit machine code (usable in 32-bit protected mode, and later in compat mode under a 64-bit OS). AMD introduced 64-bit machine code, usable in long mode. These are versions of x86 machine language in the same sense that Python2 and Python3 are different language versions. They're mostly compatible, but with intentional changes. You can run 32 or 64-bit executables directly under a 64-bit OS kernel the same way you could run Python2 and Python3 programs.

### How it works:

Start with `al=64`. Shift it right by 1 (32-bit mode) or 2 (16-bit mode).

* 16/32 vs. 64-bit: The 1-byte `inc`/`dec` encodings are REX prefixes in 64-bit (http://wiki.osdev.org/X86-64\_Instruction\_Encoding#REX\_prefix). REX.W doesn't affect some instructions at all (e.g. a `jmp` or `jcc`), but in this case to get 16/32/64 I wanted to inc or dec `ecx` rather than `eax`. That also sets `REX.B`, which changes the destination register. But fortunately we can make that work but setting things up so 64-bit doesn't need to shift `al`.

The instruction(s) that run only in 16-bit mode could include a `ret`, but I didn't find that necessary or helpful. (And would make it impossible to inline as a code-fragment, in case you wanted to do that). It could also be a `jmp` within the function.
* 16-bit vs. 32/64: immediates are 16-bit instead of 32-bit. Changing modes can change the length of an instruction, so 32/64 bit modes decode the next two bytes as part of the immediate, rather than a separate instruction. I kept things simple by using a 2-byte instruction here, instead of getting decode out of sync so 16-bit mode would decode from different instruction boundaries than 32/64.

Related: The operand-size prefix changes the length of the immediate (unless it's a sign-extended 8-bit immediate), just like the difference between 16-bit and 32/64-bit modes. This makes instruction-length decoding difficult to do in parallel; Intel CPUs have LCP decoding stalls.

---

Most calling conventions (including the i386 and x86-64 System V ABIs) allow narrow return values to have garbage in the high bits of the register. They also allow clobbering CX/ECX/RCX (and R8 for 64-bit). IDK if that was common in 16-bit calling conventions, but this is code golf so I can always just say it's a custom calling convention anyway.

**32-bit disassembly**:

```
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-bit disassembly** (Try it 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

```

Related: my x86-32 / x86-64 polyglot machine-code Q&A on SO.

Another difference between 16-bit and 32/64 is that addressing modes are encoded differently. e.g. `lea eax, [rax+2]` (`8D 40 02`) decodes as `lea ax, [bx+si+0x2]` in 16-bit mode. This is obviously difficult to use for code-golf, especially since `e/rbx` and `e/rsi` are call-preserved in many calling conventions.

I also considered using the 10-byte `mov r64, imm64`, which is REX + `mov r32,imm32`. But since I already had an 11 byte solution, this would be at best equal (10 bytes + 1 for `ret`).

---

Test code for 32 and 64-bit mode. (I haven't actually executed it in 16-bit mode, but the disassembly tells you how it will decode. I don't have a 16-bit emulator set up.)

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

```

This Linux program exits with exit-status = `modedetect()`, so run it as `./a.out; echo $?`. Assemble and link it into a static binary, e.g.

```
$ 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, e.g. in a bootloader, if you want.

```

---

# 7 bytes (score=2.33) if I can number the versions 1, 2, 3

There are no official version numbers for different x86 modes. I just like writing asm answers. I think it would violate the question's intent if I just called the modes 1,2,3, or 0,1,2, because the point is to force you to generate an inconvenient number. But if that was allowed:

```
 # 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

```

Which decodes in 32-bit mode as

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

```

and 64-bit as

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

```
> 10 votes

# Answer
# Pyth 4/5 - 6 bytes/2 versions = 3

```
  5 ;4

```

In Pyth 5, an even amount of spaces at the start of the line is ignored for use in indenting, while in Pyth 4, it just acts like a single space and prevents printing the `5`. In Pyth 4, semicolons just finish statements, which allows the `4` to be printed, while in Pyth 5, a space and semicolon makes the rest of the line a comment.
> 9 votes

# Answer
# Befunge : ~~15~~ 11 bytes / 2 versions = 5.5

4 bytes shaved off by @Pietu1998

```
"89",;5-;,@

```

Try it online :
Befunge 93
Befunge 98
Uses the Befunge 98-exclusive semicolon operator ("skip to next semicolon") to differentiate versions. Both will print "9". Befunge 93 will ignore the semicolons, subtract 5 from "8" (value left on top of the stack), print the resulting "3" and terminate. Befunge 98 on the other hand, will skip over, print "8" and terminate.
> 9 votes

# Answer
# Cubically, 4 bytes, score 4/∞

```
B3%0

```

Works in every version your system has enough memory to run. **Non-competing because it's lame.** Valid per this meta post.

Basically, B3 rotates one row from the left face into the top face. F3 would work just as well, as would F₁3 or B₁3. As one row in Cubically 3x3x3 is three cubelets by one cubelet, this puts three `1`'s into the top face, giving it a face sum of 3. `%0` prints that top face sum, printing 3 for Cubically **3**x3x3.

In Cubically 4x4x4, rows are 4x1 cubies. Puts 4 1's into the top face, yielding a sum of 4.
> 9 votes

# Answer
# Python, 196 bytes / 16 versions = score 12.25

The versions are 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, and 3.6
Unfortunately I had to leave out 2.7 because there aren't any modules in it (as far as I can tell) that aren't in 2.6 but are 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.)

```

We loop through a bunch of modules that were introduced in different versions of python, and at the first error we quit and return the version. The gaps between major versions are filled in by repeatedly importing `os`. The test for python 1.5 relies on `string.split` not being present until 1.6.

Credit to Olivier Grégoire's answer for the idea of testing for new classes/modules in a loop.

I've now finally tested on all relevant versions of python...which required editing the 1.5 source code to get it to compile...
> 9 votes

# Answer
# Brachylog / Brachylog v1, 5 / 2 = 2.5

```
2,1hw

```

Try it online! (Brachylog)

Try it online! (Brachylog v1)

Explanation for 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)

```

Explanation for 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)

```
> 7 votes

# Answer
# Python 3 and Python 2.0, 18 bytes, score 18 / 2 = 9

```
print(3-round(.5))

```

Banker's rounding in Python 3, standard rounding in Python 2.

Try it online - Python 3!

Try it online - Python 2!
> 7 votes

# Answer
# Python 1,2,3, score 10.6667

```
print(len("a a\x20a".split()))

```

This only works if you feed it in as a command line argument instead of putting it in a file, as older versions of python won't default to utf-8 in a file but will in a command line argument.

Basically, the string consists of an 'a', an ogham space (3 bytes), an 'a', an escaped space character, and another 'a', and we just split it on whitespace, count how many strings we got, and print that.

* Python 3 correctly recognises the ogham space and the escaped space as whitespace, and so the string has 3 words.
* Python 2 incorrectly assumes all unicode characters are not whitespace, so it only counts the escaped space and gets 2 words.
* Python 1 fails to parse the escaped whitespace, I think because of the a after it, so it sees no spaces and gets 1 word.
> 7 votes

# Answer
## Perl 5 and Perl 6, 23 bytes 19 bytes, score 9.5

```
print 6-grep '.',''

```

Perl 5 `grep` first op is always treated as a regex, not so in Perl 6.
> 6 votes

# Answer
## Bash, all 4 versions, ~~72~~ ~~71~~ 32 bytes ⇒ score = 8

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

```

This piece of code makes use of different interpretations of `$'...'` strings in each version of Bash.
Outputs the major version number -- and that's it.

Doc found here.

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

```

This answer is halfly a guess; I only tested it in bash 4 and 3, but it should work on other versions too.

Let me know if it does / does not, I will try with other versions as soon as I have them available.

-1 char thanks to Jens.
-29 bytes thanks to Digital Trauma (the whole `expr` idea)!
> 6 votes

# Answer
# C89/C99, 25 bytes, 2 versions, score = 12.5

```
#include <stdio.h>

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

```

`//` style comments aren't recognized in C89.

Golfed version:

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

```

Try it online: C89, C99
> 6 votes

# Answer
## R, versions 2 and 3, score: 10.5 points

```
cat(exists("cite")+2)

```

This command returns `2` for R 2.x.x and `3` for R 3.x.x. The function `cite` was added in R version 3.0.0. Therefore, the command `exists("cite")` returns `FALSE` for R 2.x.x and `TRUE` for R 3.x.x.

## R, all versions (1, 2, and 3), score: 12⅓ points

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

```

The function `eapply` was introduced in R 2.0.0.
> 4 votes

# Answer
# Julia 0.4, 0.5, 46 bytes, score 22

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

```

Julia has changed the type name of the concrete and abstract String types in many versions.

This code in particular take advantage of:

**Julia 0.4**:

* Concrete is `ASCIIString`,
* Abstract is officially `AbstractString`,
* Abstract has deprecated alias to `String`.
* Concrete is most specific than abstract so it wins dispatch

**Julia 0.5**:

* Concrete is officially `String`,
* Concrete has deprecated alias to `ASCIIString`,
* Abstract is `AbstractString`, (though that doesn't matter here)
* As two methods have been defined for the concrete string type, the latter over-writes the former.

See also my newer more effective solution based on different principles
> 4 votes

# Answer
# Erlang, 180 bytes, 11 versions, score 16.36

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

```

With indentation and line breaks:

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

```

Tested on one minor release of each major version since 10:

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

The idea is that every major release has added at least one new allowable argument for the function `erlang:system_info`, so let's try the ones in the list, count how many of them fail, and subtract the number of failures from 20, which is the current version.
> 4 votes

# Answer
# Windows' Batch File, 35 bytes / 2 versions = score 17.5

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

```

Prints `DOS` on MS-DOS <sup>(duh)</sup> and `NT` on Windows NT. <sup>(duh)</sup>

Now, for some explanation.

Windows has had batch scripting since MS-DOS times and it hasn't changed much since then. However, when Windows NT came along, Microsoft changed the default interpreter for batch scripts, from `COMMAND.COM` to `cmd.exe` (now also allowing the extension `.cmd` as an alternative to the original `.bat`).

With that, they also implemented a few changes, such as the `/i` flag for ignoring string case on conditionals. That is, while `Z==z` is false, `/i Z==z` is true.

We exploit that DOS didn't have case insensitivy and compare uppercase `Z` with lowercase `z`. By using the `/i` flag, we end up with a `Z==z` (false) conditional on DOS and `z==z` (true) on NT.

Now, I realize that the challenge specifies that a version number should be printed. But, as far as I know, there is no 'version number' to batch scripting, so this is the closest I could get.

---

Tested on Windows 10, DOSBox and vDos:

**Windows 10:**

(run with `cmd /k` to prevend window closing on `exit`)

**DOSBox:**

**vDos:**
> 4 votes

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

```
'1r\S2

```

Test v1 **|** Test v2

* 2 bytes saved thanks to Oliver

---

## Explanation

Prior to v2, Japt used a customised RegEx syntax, so we can take advantage of that.

```
'1

```

The number 1 as a string.

```
 r  2

```

Replace (`r`) the below with a `2`.

```
\S

```

Japt 2 sees this as the RegEx `/\S/g`, which matches the `1`. Japt 1 ignores the `\` escape character and just sees the `S`, which is the Japt constant for a space character and, obviously, doesn't match the `1`.
> 4 votes

# Answer
# One and Two Star Programmer, 3 bytes/2, score 1.5

```
0 1

```

In One Star Programmer, the left most cell will point to cell 1,

in Two Star Programmer, it will point to cell 2
> 4 votes

# Answer
# Wolfram Language/Mathematica 10/11, 37 bytes / 2 versions = 18.5

Consider `(Length@DateRange[{1},{1}][[1]]+27)/3`, at 37 bytes and working with 2 versions, gives me a score of 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

```

and

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

```

I'm sure there is a more efficient way, but the discrepancy between the DateRange output bit me in the butt recently, so I was set on using that.

As a follow up, someone could probably take advantage of `Length@DateRange[{1}, {1}][[1]]` evaluating to `1` in Mathematica versions 1-~8, but I didn't have time to incorporate that.
> 3 votes

# Answer
# Ruby 1.x and 2.x, 20 bytes, score 10

```
p [].to_h&&2rescue 1

```

Based on the `to_h` method which was introduced on the `Array` class in Ruby 2.
> 3 votes

# Answer
# APL (Dyalog), score 7.3 or 3

### 51 bytes for 7 versions or 6 bytes for 2 versions

For the lowest score, distinguish versions 12 and 13 with:

```
12+≡⍳0

```

Twelve plus the depth of the first zero integers. Until version 12, `⍳0` (wrongly) returned the index origin as a scalar, i.e. depth 0. In version 13 and up, `⍳0` returns an empty list, i.e. depth 1.

---

Much more interesting is the following anonymous function which distinguishes all major versions 10 through 16 (the current). It needs a dummy argument (which is ignored) to run.

```
{2::10⋄⌷2::11⋄_←⎕XML⋄0::+/12⎕ML,≡⍳0⋄≡,/⍬::15⋄16@~0}

```

`{``}` an anonymous function which allows setting error guards `::` with a numeric error code (determining which type of error to catch) on the left, and on the right, the result to be returned in case of error.

`2::10` if SYNTAX ERROR, return 10

`⌷2::11` materialise (introduced in version 11) 2 (SYNTAX ERROR) which if happens, yields 11

`⋄_←⎕XML` try: assign XML system function (introduced in version 12) to a dummy name

`0::` if any error happens;

`⍳0` first zero integers (gives 1 until version 12 and empty list from version 13)

depth of that (0 until 12, 1 from 13)

`12⎕ML,` prepend 12 and the **M**igration **L**evel (0 until 13, 1 from 14)

`+/` sum (12 until 12, 13 in 13, 14 from 14)

`≡,/⍬::15` try: concatenate the elements of an empty list (introduced in version 15) and get its depth, 2 (SYNTAX ERROR) which if happens, yields 15

`⋄16@~0` try: amend with a 16 at (introduced in version 16) positions where logical NOT yields truth, applied to 0

Try it on TryAPL (slightly modified to pass security) and Try it Online!
> 3 votes

# Answer
# Julia 0.2-0.7, bytes = 59, versions = 6, score = 9.833

```
f()=[4,0,3,0,5,2,6,7][endof(subtypes(AbstractArray))-16]/10

```

Turns out each version of julia has had a different number of abstract array subtypes. So we use the number of subtypes to index into an array that contains the version number. The current nightly (0.7), currently has 25, but it is the fallback case anyway.

Julia 0.1 also has a different number of AbstractArray subtypes I would guess. However, julia 0.1 does not have the `subtypes` function. So I can't trivially retrieve them.

A significant improvement over my previous answer.

(Thanks @one-minute-more for almost halving the bytecount)
> 3 votes

# Answer
# Befunge, score = 3.5

7 bytes, 2 versions

```
"]"'b.@

```

Try it online in Befunge-93
Try it online in Befunge-98

`"]"` is a string literal in both versions, pushing 93 (the ASCII value of `[`) onto the stack. `'b` is a character literal in Befunge-98, pushing 98 (the ASCII value of `b`), but those are invalid instructions in Befunge-93, so they are simply ignored. We thus end with 93 on the top of the stack in Befunge-93 and 98 in Befunge-98. `.@` writes out the value at the top of the stack and then exits.
> 3 votes

# Answer
# Ruby 1.x (\<1.9) and 2.x, ~~10~~ 8 bytes, score = 4

```
$><<?2%7

```

Try it:

This works by exploiting the different behaviors of `?x` between Ruby 1.x and 2.x. In Ruby 1.x, `?A` (for example) returns `65` (the ASCII value of the character `A`), but in Ruby 2.0 it returns the one-character string `"A"`.

The code above is equivalent to this:

```
val = ?2
$> << val % 7

```

In Ruby 1.x (\<1.9), the value of `val` is `50` (the ASCII value of the character `2`), a Fixnum. `Fixnum#%` is the modulo operator, so `50 % 7` returns `1`.

In Ruby 2.x, `val` is the string `"2"`. `String#%` is an infix version of `sprintf`, so `"2" % 7` is equivalent to `sprintf("2", 7)`, where `"2"` is the format string. Since the format string doesn't contain any format sequences (e.g. `%d`), subsequent arguments are discarded and `"2"` is returned.

Finally, `$>` is an alias for `$stdout`, so `$> << ...` prints the result.
> 3 votes

# Answer
# Python 2 and Python 3, ~~36~~ 34 bytes, score ~~18~~ 17

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

```

In Python 2, the hash of negative infinity is -271828 but in Python 3 it's -314159. Edit: Saved 2 bytes, 1 point of score, thanks to @ArBo.
> 3 votes

# Answer
# 05AB1E/05AB1E (legacy)/2sable, score ~~9~~ 8⅔ (26 bytes with 3 versions)

```
•äƵí•hR®di’ÿ (»Š)’ë’2sˆ¢’r

```

Try it online in 2sable
Try it online in 05AB1E (legacy)
Try it online in 05AB1E

**Explanation:**

Let's start with a bit of history of these three versions. The development of 05AB1E started at the start of 2016 (or actually, the very first git-commit was on December 21st, 2015). This new codegolf language was being built in Python as backend. Mid 2016 2sable was branched of that current 05AB1E version (July 7th, 2016 to be exact), and the strength of 2sable in comparison to that old 05AB1E version was added: implicit inputs. Later on implicit input was also added to 05AB1E, and 2sable became obsolete and basically a forgotten version right after it was created on that day July 7th, 2016.
Then in mid-2018, a new 05AB1E version was being started, this time completely rewritten in Elixir instead of Python, with loads of new builtins added and some builtins changed or even removed.

So, let's go over the code and see what it does in each of the three versions:

```
•äƵí•              # Legacy 05AB1E / new 05AB1E: push compressed integer 14793296
                   # 2sable: no-op (compressed integers didn't exist yet,
                   #         so nothing is pushed to the stack)
     h             # Convert this from an integer to a hexadecimal string: "E1BA50"
      R            # Reverse this string: "05AB1E"
                   # (2sable: the stack remains empty for `h` and `R`)
       ®           # Push -1
        d          # 2sable: check if -1 only consist of digits (falsey)
                   # 05AB1E (legacy): check if -1 is an integer (truthy)
                   # New 05AB1E: check if -1 is a non-negative (≥0) integer (falsey)
         i         # If it is truthy:
          ’ÿ (»Š)’ #  Push dictionary string "ÿ (legacy)",
                   #  where the `ÿ` is automatically filled with the top of the stack
         ë         # Else:
          ’2sˆ¢’   #  Push dictionary string "2sable"
                r  #  And reverse the stack
                   #  (05AB1E: stack changes from "05AB1E","2sable" to "2sable","05AB1E"
                   #   2sable: stack stays the same "2sable")
                   # (after which the top of the stack is output implicitly as result)

```

See this 05AB1E tip of mine (sections *How to use the dictionary?* and *How to compress large integers?*) to understand why `’ÿ (»Š)’` is `"ÿ (legacy)"`, `’2sˆ¢’` is `"2sable"`, and `•äƵí•` is `14793296`.
> 3 votes

# Answer
# Scratch (Squeak 1.x, 2.0, and 3.0) (scratchblocks3 syntax), 92 bytes, score 30.666...

```
when gf clicked
if<<[cos v]of(90)>=(0
say[3
else
add<not<>>to[l v
if<(l)=(1
say[1
else
say[2

```

Ungolfed, with explanation:

```
when gf clicked
if<<[cos v] of (90)> = (0) // cos 90 is 0 in Scratch 3, and some nonsense number in other versions
    say [3]
else
    add<not <> > to [list v] // "add <true> to a list" - this adds "1" to the list in 1.x, and the string "true" to the list in later versions
if<(list) = (1)> // all versions of Scratch automatically typecast everything to everything, including lists to strings, allowing for comparisons like this to be done seamlessly
    say[1]
else
    say[2]
end
end

```
> 3 votes

# Answer
# Python 3, Python 2, score 17.5

(35 bytes, 2 versions)

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

```

## Python 2, 35 bytes

Try it online!

## Python 3, 35 bytes

Try it online!

*Saved 5 bytes thanks to ETHproductions*

Not a good code golf answer, but a massive change!
> 2 votes

# Answer
## PHP 4, 5, & 7: 59 bytes, score 19.67

```
<?list($a[],$a[])=array(5-strrpos('112','11'),7);echo$a[1];

```

It's way long but it does 3 versions!

`list()` assigns in backwards order in PHP 4 & 5, `strrpos()` only searches for a single character in PHP 4.
> 2 votes

# Answer
## C++11 and C++14, 96 bytes, score 48

```
#include<iostream>
#define M(x,...)__VA_ARGS__
int main(){std::cout<<(int[]){M(1'2,1'4,11)}[0];}

```

The code is based on the digit separator proposal which has very similar example code at the end.

online version
> 2 votes

# Answer
# Braingolf, 4 bytes, 2 versions, score = 2

```
0n6+

```

Try it online!

`n` (negate) was added in braingolf v0.7, meaning this will output `7` in v0.7 and newer, and `6` in v0.6 and older

In v0.7, `n` "negates" the 0 to a 1, then adds it to 6 to make 7, but in v0.6, the `n` does nothing, and so 0 is added to 6, resulting in 6. Both versions have implicit output.

This is technically the minor version, however there is only 1 major version of Braingolf, as Braingolf v1.0 isn't a thing yet, so this is about as major as the version numbers get.
> 2 votes

# Answer
# Idea of the solution

Each version hava added a new syntax features, so code vith them will cause a syntax error in smaller versions of the language.

* **ES5:** Octal constants `03` are disallowd in strict mode (unused in actual solutions)
* **ES6:** Octal constants `0o6` are introduced
* **ES7:** Pow operator is introduced: `7**1`
* **ES8:** Trailing comma in function call is allowed: `f(8,)`
* **ES9:** Tagging of invalid strings is allowed: `f`\u9``

So evaluating

```
eval('9;'+s)

```

on one of the examples will either return the the value, or throw a SyntaxError. But what value would it return? For all ES6-ES8 snippets the last calculated value will be the version. In ES9 snippet the 9 from `9;` is return. So if we place a minimal supported version into catch block like

```
eval(`try{eval('9;'+s)}catch(e){6}`)

```

we'll get the behaviour we want.

# Ecmascript 5+ (for 5, 6, 7, 8, 9); 124 / 5 = 24.8 points

```
alert(Math.max.apply(0,'0o6~7**1~f(8,)~f`\\u9`'.split('~').map(function f(s){return eval("try{eval('9;'+s)}catch(e){5}")})))
```

Tested in:

* IE8: Error (Object doesn't support property or method 'map')
* IE 11: 5
* Edge 14: 8
* Chrome 60: 8
* Firefox 55: 9

---

# Ecmascript 6+ (for 6, 7, 8, 9); 96 / 4 = 24 points

```
alert(Math.max(...'7**1~f(8,)~f`\\u9`'.split`~`.map(f=s=>eval(`try{eval('9;'+s)}catch(e){6}`))))
```

Tested in:

* Edge 14: 8
* Chrome 60: 8
* Firefox 55: 9
> 2 votes

# Answer
# Lua 5.3.3 / 5.2.4, 32 bytes / 2 = 16 points

```
print(54-#("a"):gsub("a?$","a"))

```

This actually abuses a bug in Lua 5.2's `string.gsub` function: In Lua 5.2, `"a?$"` would first match `"a{endOfString}"` and then `"{endOfString}"` a second time, which is obviously incorrect, because `gsub` may only match each character/anchor in the string once. This results in `"a"` being substituted into the string twice, giving a final string length of 2.

In Lua 5.3, the bug is fixed, so `"a?$"` only matches `"a{endOfString}"`, thus matching the end of the string only once, which is the correct behavior. Therefore, `"a"` is substituted into the string just once, resulting in a string length of 1.

The difference between the string length and 54 then gives the major/minor version number of the Lua interpreter, which is printed as follows:

Lua 5.2.4: `52`
Lua 5.3.3: `53`

(I could only test on these two specific versions, but it should work on more)
> 2 votes

# Answer
# Japt, 4 bytes / 2 versions = 2

```
J\+2

```

**Japt** **|** **Japt 2.0**

Alternative:

```
2\/2

```

**Japt** **|** **Japt 2.0**
> 2 votes

# Answer
# Wolfram Language (Mathematica), 30 bytes (5\<= Score \<=10)

```
Floor[.8+Length@Names@"*"/615]

```

I tested this on Mathematica 10.2, which has 5683 named symbols and 11.3, which has 6280 names symbols. I used cloud.wolfram.com to test it on Mathematica 12.0 which has 6914 named symbols. With possibly some slight tweaking to the numbers, this could work for as many as 6 versions (see the graph at https://blog.wolfram.com/2018/06/21/weve-come-a-long-way-in-30-years-but-you-havent-seen-anything-yet/) which shows that the function count has grown pretty much linearly since v6.)

Try it online!
> 2 votes

# Answer
## Python 1, 2, and 3, ~~43~~ 33 bytes, score ~~14.333~~ 11

-10 bytes by using `and` and `or` instead of an if/else statement

```
print(1and str(1<2)=="1"or 3/2*2)

```

Yes, there are already submissions for Python, but this one also differentiates Python 1 and 2.

The difference between Python 3 and 2 are pretty well known, but with Python 1? It's very similar to Python 2.

But I found something.

In Python 1, a true statement evaluates to 1. In Python 2 and 3, it evaluates to True. By turning a true statement into a string, you can differentiate Python 1 and the later versions.
> 2 votes

# Answer
# Whispers, 35 bytes / 3 versions = 11.66

```
>> R2
>> -1
> 3
> 2
> 1
>> Output 3

```

Try it online! (Whispers v1)

Try it online! (Whispers v2)

Unfortunately, Whispers v3 isn't currently on TIO, so you'll have to download it from the repo to try it.

## How they work

This relies on the feature in Whispers which removes lines that contain (among other things) invalid instructions from the code before numbering the lines for execution.

All three programs work by calling line **3** and outputting the number on that line. However, by removing lines that contain invalid instructions, we change which line line **3** actually is. As they all just output line **3**'s result, I'll focus the explanations on which line is line **3** and why.

### v1

In version 1, neither of the first two lines are valid instructions. Therefore, the code passes to the executor is

```
> 3
> 2
> 1
>> Output 3

```

and line **3** simply returns \\$1\\$

### v2

In version 2, the first line `>> R2` is now a valid instruction: it takes a vector and outputs its polar form (i.e. magnitude and angle). However, the second line `>> -1` is not yet valid, so the interpreter sees

```
>> R2
> 3
> 2
> 1
>> Output 3

```

The first line shifts line **3** to refer to `> 2`, which just returns \\$2\\$.

### v3

The entire program is valid in the latest version Whispers, which includes a massive expansion of builtins, but the shortest new addition is the negate command: `>> -1`, which does not return \\$-1\\$, rather it takes in an argument and negates in. Therefore, the interpreter sees

```
>> R2
>> -1
> 3
> 2
> 1
>> Output 3

```

Meaning that line **3** is now `> 3`, which, you guessed it, returns \\$3\\$.
> 2 votes

# Answer
# Nim, 28 bytes / 2 versions = score 14

```
echo int compiles uint64.low

```

Try it online! (TIO only supports one version)

In version 1.0, `uint64` was made a proper ordinal type, so it's now possible to determine its lower bound. The program simply checks if the expression `uint64.low` compiles and converts the bool to an integer.
> 2 votes

# Answer
# Vyxal 3 `G`, 4 bytes, 2 versions = Score 2

```
2#[3

```

Vyxal 3

Vyxal 2

Lists in Vyxal 3 start with #\[ which is commented out in Vyxal 2.
> 2 votes

# Answer
# VBA, 51 Bytes / 2 Codes = 25.5

Anonymous VBE immediate window function that outputs the VBA program version - works only in Excel 2011 and later. Outputs Version 7 for windows and Version 6 for Mac, as mac has yet to get version 7 of VBA

Uses conditional compilation constant `Mac` to determine the VBA language version

```
Sub a()
o=7
#If Mac Then
o=6
#End If
Debug.?o
End Sub

```
> 1 votes

# Answer
# Lua 5.0, 5.1, 5.2, 5.3, score: 17.75

```
print("5."..(table.getn or load'return #...'){math.fmod,_ENV,math.ult})

```

`math.fmod` was `math.mod` before 5.1
`_ENV` was introduced in 5.2 for new environment system
`math.ult` was introduced in 5.3

There was a problem: lua 5.0 don't know `#` for tables, but lua \>= 5.2 don't have function `table.getn`, so I keep `#` isolated in string for lua 5.0, and loads in instead of `table.getn` for lua \>= 5.2.
> 1 votes

# Answer
## /Kona, 6 bytes, 2 versions - score 3

```
-4+@,0

```

Version 3 defaults to long numeric types, whereas 2 defaults to integer numerics. We enlist (`,`) to get a positively typed number (atoms are negative), we get its type (`@`), and we add that to -4.
> 1 votes

# Answer
# RProgN 1/, 4 bytes / 2 versions. Score = 2

```
1 1+

```

RProgN1 requires commands to be split into words, where as RProgN2 reads byte by byte by default. As such, RProgN1 can't do anything with `1+`, so it just outputs `1`, but RProgN2 can execute it, so it adds `1` to the `1`, giving `2`.

Try RProgN1

Try RProgn2
> 1 votes

# Answer
# T-SQL, 41 bytes / 11 versions = 3.7 score

```
SELECT MAX(cmptlevel)/10FROM sysdatabases

```

Note that this does *not* use a SQL "builtin, macro, or custom compiler flag"; that would be something like `SELECT @@VERSION` or `SELECT SERVERPROPERTY('productversion')`.

Instead, this looks up the *highest "compatibility level" for all databases on the server*. Existing databases on a server might have older compatibility levels, but the system database `tempdb` is recreated each time the server is restarted, so will always have the compatibility level of the actual current version. (Using `MAX` is shorter than including `WHERE name='tempdb'`).

I divide by 10 so it returns the actual SQL version number.

I've successfully tested this on all versions between SQL 2005 and 2017, but I believe this will ultimately work in 11 distinct versions:

```
Version Number    Release Name
6                 SQL Server 6.0
6.5               SQL Server 6.5
7                 SQL Server 7.0
8                 SQL Server 2000
9                 SQL Server 2005
10                SQL Server 2008 (or SQL Server 2008 R2)
11                SQL Server 2012
12                SQL Server 2014
13                SQL Server 2016
14                SQL Server 2017
15                SQL Server 2019 (Pre-release)

```

Let me know if anyone has SQL 2000 or older still running to see if this works as expected.

Note that my code uses a deprecated system table for widest compatibility, I'd normally use the newer `sys.databases` system view introduced in SQL 2005.
> 1 votes

# Answer
# SmileBASIC (2 and 3), 4.5 bytes

Thank you 12Me21 for helping out.

```
?3+CANCEL

```

In SB, variable declaration rules are lazy by default; if a variable name is not declared or assigned anywhere in scope, it is assumed to be 0. There's also a handful of reserved system variables and constants which varies between version and platform.

In SB v2, `CANCEL` was a reserved variable that represented -1; this was intended for use with `RESULT` to check the state of a dialog box or other action. In SB v3, this variable is not present.

Thus, when this program is run on a standard SB v2 environment it prints 2, and on a v3 environment it prints 3.
> 1 votes

# Answer
# Whitespace, 43 bytes, 2 versions, score 21.5

Version 0.3 of Whitespace added the `copy` and `slide` instructions. Of those two, `slide` is exploited here. Slide removes the top *n* elements of the stack, keeping the top element. The code for version 0.3 slides 2 and version 0.2 ignores the slide and keeps the 2.

```
SS
T
STSSSTT
SSSTS
SSSTSTTTS
ST
ST
T
SST
ST

```

Written as more readable Whitespace assembly:

```
push 0   # Push 0 to the stack
printi   # Print 0 as an integer
push 3   # Push 3 to the stack
push 2   # Push 2 to the stack
push '.' # Push 46 ('.') to the stack
slide 1  # Pop 2 if version 0.3 or skip instruction
printc   # Print 46 as character '.'
printi   # Print 2 or 3 as integer

```
> 1 votes

# Answer
## PHP (42 chars, 4 versions) - score 10.5

```
echo max('$',0)?@(date(c)==c?4:7-"0x2"):8;

```

With the `@` error control operator you shouldn't see the “*Use of undefined constant*” notice.

## PHP (59 chars, 4 versions)

This 15 chars per version attempt is based on fdiv, ereg and idate existence.
The line must be runnable through the codes from the years 2000 to 2022.

```
$a='is_callable';echo$a('fdiv')+6-2*$a('ereg')+$a('idate');

```

Both write a single character to stdout among 4,5,7 and 8, checked with 3v4l.org.

**Interesting** change between 7 and 8 :

```
echo max('$', 0) === max(0, '$') ? 8 : 7 ; // custom version detector

```
> 1 votes

# Answer
## PostScript, 36 bytes/3 versions = score of 12

```
00000000: 92aa 9238 283c 3c29 9260 7b28 7368 6669  ...8(<<).`{(shfi
00000010: 6c6c 2992 607b 337d 7b32 7d92 557d 7b31  ll).`{3}{2}.U}{1
00000020: 7d92 553d                                }.U=

```

Un-tokenized:

```
systemdict dup(<<)known{(shfill)known{3}{2}ifelse}{1}ifelse =

```

Tests for operators introduced in PostScript Levels 2 and 3.

`<<` was introduced in PS level 2. If this isn't present, it's PS level 1.

`shfill` was introduced in PS level 3. If this isn't present, it's PS level 2. (xpost currently prints `2`, as `shfill` isn't implemented: Try it online!)

Ghostscript prints `3`.
> 1 votes

# Answer
# Julia: 21 bytes, score: 10.5

```
(length([1:2])+V)/10   # where V takes value critical version minus 1

```

I cannot *quite* remember *which* version of julia this changed in (stuff gets deprecated *very* often), but there was some point in the language where this:

```
julia> [1:2]
2-element Array{Int64,1}:
 1
 2

```

became this:

```
julia> [1:2]
1-element Array{UnitRange{Int64},1}:
 1:2

```

from one version\* to the next. I think it was probably from v0.3 to v0.4? (in which case `V = 2`)

---

<sub>* julia is still in major version 0</sub>
> 0 votes

# Answer
## Mathematica 10/11 20 Bytes, Score=10

Since Echo was introduced in version 11

```
10+Echo@1/.Echo@1->0

```

Can extend to version 9 as well (since AbsArg was intro'd in V10) with

```
10-Last@AbsArg@1+Echo@1/.Echo@1:>0

```

but the score goes up to 34/3 or 11.33
> 0 votes

# Answer
# Python 2/3 REPL, ~~36~~ 33 bytes, ~~36~~ 33/2=~~38~~ 16.5 score

```
[3,2]['cmp' in dir(__builtins__)]

```

Try it in a Python shell. It (ab)uses removed builtins in Python 3. `cmp` was a builtin in Python 2, but was removed in Python 3, and it would result a truthy value in Python 2 and falsey in Python 3, and use it to index the `[3,2]` list, if it is 0, then it would output `3` and for `1` it would output `2`.

To make this solution, first I took the bulitins list from Python 2, made it a set, and subtracted set of Python 3 builtins from it

```
s={'ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip'}-(set(dir(__builtins__)))

```

Which is

```
{'reduce', 'cmp', 'basestring', 'reload', 'file', 'unicode', 'buffer', 'execfile', 'apply', 'raw_input', 'unichr', 'coerce', 'StandardError', 'xrange', 'intern', 'long'}

```

And for good sort from smallest to largest

```
sorted(s,key=lambda x:len(x))

```

So we could use these builtins, amongst them, `cmp` is the shortest:

```
'cmp', 'file', 'long', 'apply', 'reduce', 'reload', 'buffer', 'unichr', 'coerce', 'xrange', 'intern', 'unicode', 'execfile', 'raw_input', 'basestring', 'StandardError'

```
> 0 votes

# Answer
# , 4 bytes / 13 major versions: score 0.3077

```
.z.K

```

Built-in: https://code.kx.com/q/ref/dotz/#zk-version

Same for k4.
> -1 votes

---
Tags: code-golf, code-challenge, polyglot
---


title: Limited letter renderer: BIOPD

text:
# Question
Title: Limited letter renderer: BIOPD
There have of course been challenges to render ASCII art fonts here and there. This challenge doesn't add anything to those. In contrary, it subtracts from them for a good reason. If you allow all characters,

1. it's a lot of boring work
2. the task is mainly about clever compression of the font and short extraction

This one shall be different, because it is restricted to only five letters to be rendered: `BDIOP`

```
####   #   ###   ####   ####
#   #  #  #   #  #   #  #   #
####   #  #   #  ####   #   #
#   #  #  #   #  #      #   #
####   #   ###   #      ####

```

Those are obviously chosen for a reason, they share some symmetry, some common elements, but not all of them:

* They are vertically symmetrical, except for the `P`
* The start with a vertical bar, except for the `O`
* The second line is the same, except for the `I`

I think these subtile differences open the field for a lot of possible golfing improvements.

**The input** is a sequence of up to 13 uppercase characters out of those five (put as extended regex `[BDIOP]{,13}`) in a form that fits your language.

**The output** is the ASCII art output of the string with the given 5\*x variable width font, using a whitespace for the background and a character of your choice for the letters, with two whitespaces between the letters. Trailing whitespaces on the lines are allowed, as well as one trailing newline.

**The shortest code** for each language wins.

# Answer
> 22 votes
# JavaScript (ES6), 110 bytes

Expects an array of ASCII codes.

```
a=>[759,4,55,5,757].map(p=>a.map(c=>"#   ##     ### #### ".substr((p>>c%31%9&3)*5,4>>c-9^5)).join`  `).join`
`

```

Try it online!

Or **102 bytes** if we can output an array of strings.

### Method

Only 4 distinct patterns are needed to build all letters. We store them into a single lookup string.

```
0: #...#      #...##.....###.####.
1: #....      \___/\___/\___/\___/
2: .###.        0    1    2    3
3: ####.

```

The letters are encoded per row, using 2 bits per pattern. By converting from base 4 to base 10, we eventually get the array `[759, 4, 55, 5, 757]`.

```
2: .###. | 3: ####. | 3: ####. | 1: #.... | 3: ####. -> 23313 -> **759**
0: #...# | 0: #...# | 0: #...# | 1: #.... | 0: #...# -> 00010 -> **4**
0: #...# | 0: #...# | 3: ####. | 1: #.... | 3: ####. -> 00313 -> **55**
0: #...# | 0: #...# | 0: #...# | 1: #.... | 1: #.... -> 00011 -> **5**
2: .###. | 3: ####. | 3: ####. | 1: #.... | 1: #.... -> 23311 -> **757**
```

By reducing each ASCII code modulo \\$31\\$ and modulo \\$9\\$, we get the shift amount that must be applied to extract the relevant bits from the above values. (This formula is the reason why the letters are encoded in the order `ODBIP`.)

| Letter | ASCII code | modulo 31 | modulo 9 |
| --- | --- | --- | --- |
| **O** | 79 | 17 | **8** |
| **D** | 68 | 6 | **6** |
| **B** | 66 | 4 | **4** |
| **I** | 73 | 11 | **2** |
| **P** | 80 | 18 | **0** |

Finally, we have to adjust to the correct character width. The expression `4 >> c - 9 ^ 5` used as the 2nd parameter of `substr()` gives \\$1\\$ for `I` and \\$5\\$ for all other letters. (The simpler `c - 73 ? 5 : 1` is just as long ... but not as cool. ^^)

# Answer
> 4 votes
# Charcoal, ~~41~~ ~~39~~ ~~36~~ ~~35~~ 33 bytes

```
↑ＥＳ⟦⪪§⪪”{∨'Ｎ4Ｔ≕⊞｜"³üＵr⁸mＩ”²⁴⊖Σ℅ι⁵

```

Try it online! Link is to verbose version of code. Explanation: Mainly clever compression of the font and short extraction.

```
  Ｓ                 Input string
 Ｅ                  Map over letters
       ”...”        Compressed rotated font
      ⪪     ²⁴      Split into letters
     §              Indexed by
                 ι  Current character
                ℅   Ordinal
               Σ    Digital sum
              ⊖     Decremented
    ⪪             ⁵ Split into columns
   ⟦                Doubly nest the list
↑                   Output rotated

```

The mapping of the characters to the font index is as follows (note that the modulo 5 is automatic due to the use of cyclic indexing):

| Character | Ordinal | Digital Sum | Decremented | Modulo 5 |
| --- | --- | --- | --- | --- |
| O | 79 | 16 | 15 | 0 |
| B | 66 | 12 | 11 | 1 |
| P | 80 | 8 | 7 | 2 |
| D | 68 | 14 | 13 | 3 |
| I | 73 | 10 | 9 | 4 |

The nested map would normally result in a list of lists so the extra list wrapper makes a doubly nested list which results in the desired output spacing.

# Answer
> 4 votes
# 05AB1E, 37 bytes

```
•1b§…£U(γ°xāxK²•„# Åв5ô5ôIÇH<è€øJøð«»

```

Try it online.

Just uses `#` and spaces like the challenge description, and has a single trailing column of spaces. Using a different character (`0`) would be the same byte-count, by replacing `„# Åв` with `b1ð:S`:
try it online.

**Explanation:**

```
•1b§…£U(γ°xāxK²• # Push compressed integer 22122550664723003622970748254752
 „#              # Push string "# "
    Åв           # Convert the large integer to a base-2 list, and index it into "# "
5ô               # Split the list of characters into parts of size 5
  5ô             # Split the list of quintuplets into parts of (up to) size 5 as well
    I            # Push the input-string
     Ç           # Convert it to a list of codepoint-integers
      H          # Convert them from hexadecimal to base-10
       <         # Decrease each by 1
        è        # Modular 0-based index each into the earlier list of matrices
€                # Map over each matrix:
 ø               #  Zip/transpose; swapping rows/columns
  J              # Join each inner list together to a string
   ø             # Zip/transpose; swapping rows/columns
    ð«           # Append a space to each line
      »          # Join each inner list by a space, and then each string by newlines
                 # (after which the result is output implicitly)

```

| letter | `Ç` | `H` | `<` | modular 0-based index |
| --- | --- | --- | --- | --- |
| B | 66 | 102 | 101 | 1 |
| D | 68 | 104 | 103 | 3 |
| I | 73 | 115 | 114 | 4 |
| O | 79 | 121 | 120 | 0 |
| P | 80 | 128 | 127 | 2 |

See this 05AB1E tip of mine (section *How to compress large integers?*) to understand why `•1b§…£U(γ°xāxK²•` is `22122550664723003622970748254752`.
This number has been generated by the program in this ASCII-art tip using the transposed flattened rendered letters as input-string.

# Answer
> 4 votes
# Jelly, 34 bytes

```
OD§ị“¡x%ẸȥpFẠẊẓ~ọØ¢’Bs5$⁺¤jØ1z1a⁶Y

```

Try it online!

A full program taking a string argument and printing the desired output, using 0 and space to make up the letters. In the end, a simple binary encoding of the five letters was most the shortest I could come up with.

## Explanation

```
O                                   # Convert to codepoints
 D                                  # Convert to decimal digits
  §                                 # Sum inner lists
   ị                     ¤          # (Modular) index into the following:
    “¡x%ẸȥpFẠẊẓ~ọØ¢’                # - Base-250 integer 22122550664723003622970748254752
                    B               # - Convert to binary
                     s5$⁺           # - Split into lists of length 5 twice (last one will only have length 1 - corresponds to I)
                          jØ0       # Join with two ones between each list of lists
                              z1    # Zip, filling with ones
                                a⁶  # And with a space (replaces 1 with space)
                                  Y # Join with newlines

```

# Jelly, previous version, 35 bytes

```
“¢ḄẸẏßŻ¦ṠAi;$ƈƬ’Bs5s5⁽æ£,ḥⱮjØ0z0o⁶Y

```

Try it online!

A full program taking a string argument and printing the desired output, using 1 and space to make up the letters.

## Explanation

```
“¢ḄẸẏßŻ¦ṠAi;$ƈƬ’Bs5s5⁽æ£,ḥⱮjØ0z0o⁶Y
“¢ḄẸẏßŻ¦ṠAi;$ƈƬ’                     # Base-250 integer 40155886737228810123461877351903
                B                    # Convert to binary
                 s5                  # Split into lists of length 5
                   s5                # Split into lists of length 5 (last one will only have length 1 - corresponds to I)
                     ⁽æ£,            # Pair 6503 with this
                         ḥⱮ          # Use 6503 as the salt for the Jelly hash function for each of the input letters (will return  the first list of lists for B, the second for P, the third for O, the fourth for D and the fifth for I)
                           jØ0       # Join with two zeros between each list of lists
                              z0     # Zip, filling with zeros
                                o⁶   # Or with a space (replaces 0 with space)
                                  Y  # Join with newlines

```

Created with the help of Luminespire

# Answer
> 2 votes
# GNU sed `-E`, 218 bytes

There are only four or five different lines to compose the characters, but seems expensive to use this knowledge in `sed`, so I a column-based approach. First, replace each character by a lower letter representing the type of column, from `a` for `a`ll set to `z` for `z`ero set. The I build row after row, inheriting the type of column. Simple for `a` and `z`, slightly more complicated for `e`very `o`ther row set and really long logical chains for others.

```
s/./a&zz/g
s/^/xy:kl:ghia:zzoe \
fglmnzaawxyzeo#\n_/
s/I//g
s/B/eeo/g
s/P/wwx/g
s/D/ffk/g
s/aO/kffk/g
G
:1
s/_([ #]*\n)(.*)/\1_\2\n/
s/((.)([a-z])\S*(.)\n.*_[ #]*)\2(.*)/\1\4\5\3/
#x;p;x
/.*#\n((.*\n){5})_.*/!b1
s//\1/

```

Who can beat that one with `sed` with a different approach?

Try it online!

And easily scalable

# Answer
> 2 votes
# Vyxal 3, ~~45~~ 37 bytes

```
OṠv"ᵇVOᶠ4ZG%|∵₁ιf†“b5Ẇ5Ẇ$ið5Y2YjTð∧Ṅṅ

```

Try it Online!

This is a translation of my Jelly answer to Vyxal 3, mainly as an exercise in learning an alternative language. It’s ~~11~~ 3 bytes longer, partly reflecting my inexperience with the language.

The lost bytes reflect two bytes to manually output as ASCII art rather than a representation of lists, 0-indexing (so one byte for decrementing the index).

*Thanks to @lyxal for saving eight bytes, including by fixing some bugs in the language!*

# Answer
> 1 votes
# APL+WIN, 80 bytes

Prompts for character string. Can be any length:

```
' #'[(5⍴2)⊤∊(¯9+(⊂⎕av)⍳¨('xnnnc' 'xjjjg' 'x' 'gjjjg' 'hmmma')['BDIOP'⍳⎕]),¨⊂0 0]

```

Try it online! Thanks to Dyalog Classic

# Answer
> 1 votes
# Python, 118 bytes

```
s=input()
*z,=b"|b|b||bbb|\\bbb\``|b|"
for z[:0]in[[6]]*5:print(*(bin(z[ord(c)%9//2*5])[3:].replace(*'0 ')for c in s))

```

Attempt This Online!

Uses spaces and `1`s for output.

Encodes the font in binary. Lookup uses `%9//2` which maps the code points to `0...4`, in particular, sending `I` to `0` which allows us to abuse the simple structure of `I`.

# Answer
> 1 votes
# Uiua 0.3.1, 62 bytes

```
/⊐≡(⊂⊂:"  ")⊐≡(+@ ×3⋯)⊏:[±.⍜↘±3.⍜⊙⊡-.2.⊃+∘+14×3¬.⋯17]⊗:"IPBDO"

```

## Explanation

```
Rndr ← (                        # Define a function
  ⊗:"IPBDO"                     # Convert letters to indices
  [±.⍜↘±3.⍜⊙⊡-.2.⊃+∘+14×3¬.⋯17] # Encode bit masks for letters as integer arrays
  ⊏:                            # Convert indices to masks
  ≡(□+@ ×3⋯)                    # Render each row as a letter,
                                #   box them to accommodate for different width
  /⊐≡(⊂⊂:"  ")                  # Join letters together, add spaces between them
  # ≡&p # Uncomment to print to stdout
)
Rndr "IDBIPOPD"                 # Call the function on a value

```

Try it out!

---
Tags: code-golf, ascii-art
---