[Question]
  [
Duolingo, the language learning app, has a lot of things going for it, but there is one major issue that drives me crazy. It tells me how many days in a row I've used the app with a message like **You're on a 7 day streak!** Setting aside hyphenation and whether the number should be spelled out, this works fine for most numbers, but is indisputably wrong when it says **You're on a 8 day streak!** I'm not using it to learn English but this is still unfortunate behavior for a language app.
You're going to help out the Duolingo team by writing a complete program or function that figures out whether a given number should be preceded by *a* or *an*. A number is preceded by *a* if its pronunciation in spoken English begins with a [consonant or semivowel sound](https://en.wiktionary.org/wiki/Wiktionary:IPA_pronunciation_key), and preceded by *an* if its pronunciation begins with a vowel sound. Thus the only numbers preceded by *an* are those whose pronunciation begins with *eight*, *eleven*, *eighteen*, or *eighty*.
Presumably the Duolingo dev team left this bug in because they ran out of space for more source code in the app, so you need to make this code as short as possible in the hopes they can squeeze it in.
Your code must take an integer from 0 to 2,147,483,647 and output `a` or `an`. A trailing newline is optional. For the purposes of this challenge, 1863 is read as *one thousand eight hundred and sixty-three*, not *eighteen hundred and sixty-three*.
**Test cases:**
```
0 → a
8 → an
11 → an
18 → an
84 → an
110 → a
843 → an
1111 → a
1863 → a
8192 → an
11000 → an
18000 → an
110000 → a
180000 → a
1141592 → a
1897932 → a
11234567 → an
18675309 → an
```
  
[Answer]
## Python 2, 60 bytes
```
lambda n:'a'+'n'[:`n`[0]=='8'or`n`[:2]in len(`n`)%3/2*'118']
```
An anonymous function. Adds an `n` if either:
* The first digit is 8
* The first two digits are 11 or 18, and the length is 2 modulo 3.
[Answer]
# Pyth, 23 bytes
```
<>n\8hz}hjsz^T3,hT18"an
```
This selects how many letters to slice off the end of `"an"` by checking whether the first letter is not an `8` and that the first digit of the number when considered in base 1000 is neither 11 nor 18. The resulting boolean is the number of characters to slice of the end.
[Answer]
# GNU Sed, 32
Score includes +1 for `-E` option to sed.
```
s/^8.*|^1[18](...)*$/an/
t
ca
:
```
[Try it online.](https://ideone.com/GgYmyZ)
* Remove groups of 3 digits from the end of each number until there is only 1 to 3 digits left
* Match any number starting with 8 or exactly 11 or 18 and change to `an`
* Change all other numbers to `a`
Thanks to @MartinBüttner for [his retina approach](http://chat.stackexchange.com/transcript/message/26246140#26246140) that saved 10 bytes.
[Answer]
# Shell + bsd-games, 30
```
number -l|sed '/^e/{can
q};ca'
```
Input read from STDIN.
`number` converts a decimal string into words. It is then a simple matter to decide whether or not the result begins with `e`.
[Answer]
## [Retina](https://github.com/mbuettner/retina), 27 bytes
This isn't very different from DigitalTrauma's Retina answer, but they insisted I post this myself.
```
^8.*|^1[18](...)*$
an
\d+
a
```
[Try it online.](http://retina.tryitonline.net/#code=bWBeOC4qfF4xWzE4XSguLi4pKiQKYW4KXGQrCmE&input=MAo4CjExCjE4Cjg0CjExMAo4NDMKMTExMQoxODYzCjgxOTIKMTEwMDAKMTgwMDAKMTEwMDAwCjE4MDAwMAoxMTQxNTkyCjE4OTc5MzIKMTEyMzQ1NjcKMTg2NzUzMDk)
The first regex replaces all relevant numbers with `an`, and the second replaces all remaining numbers with `a`. This works for the same bytes:
```
^8.*|^1[18](...)*$
n
^\d*
a
```
[Answer]
# C++, 101
This is my challenge, so this isn't meant to be a competitive answer. Just wanted to see how short I could get it in C++. String operations are just too verbose so this is done with math. I feel like there must be a way to get that condition smaller but I can't quite figure it out.
```
const char*f(int i){int n=0,d=0;for(;i;(!(d++%3)&(i==18|i==11))|i==8?n=1:0,i/=10);return n?"an":"a";}
```
[Answer]
## Mathematica, 53 bytes
```
If[#~IntegerName~"Words"~StringStartsQ~"e","an","a"]&
```
A solution using string processing would actually end up being longer.
[Answer]
## PostScript, ~~119~~ 113 characters
```
10 string cvs dup 0 get 56 eq exch dup length 3 mod 2 eq{0 2 getinterval dup(11)eq exch(18)eq or or}{pop}ifelse
```
With test code:
```
/An
{
    10 string cvs dup 0 get 56 eq exch dup length 3 mod 2 eq{0 2 getinterval dup(11)eq exch(18)eq or or}{pop}ifelse
} def
/ShouldBeFalse [ 0 110 1111 1863 110000 180000 1141592 1897932 ] def
/ShouldBeTrue [ 8 11 18 84 843 8192 11000 18000 11234567 18675309 ] def
() = (ShouldBeFalse) = ShouldBeFalse {An =} forall
() = (ShouldBeTrue)  = ShouldBeTrue  {An =} forall
```
[Answer]
## JavaScript (ES6) ~~70~~ ~~61~~ ~~46~~ 38 bytes
```
n=>/^8|^1[18](...)*$/.test(n)?'an':'a'
```
Community wiki because the current solution is so different than my original. Thanks everyone!
Demo: <http://www.es6fiddle.net/iio40yep/>
[Answer]
## Seriously, ~~43~~ 40 bytes
```
9⌐9τk,;;$l3@\3*╤@\(íub)$#p'8=)XkΣ'n*'a+
```
The strategy here is to only look at the 1, 2, or 3 most significant digits, by integer-dividing the input by the largest value `10^(3n)` that is less than the input.
[Try it online](http://seriouslylang.herokuapp.com/link/code=39a939e76b2c3b3b246c33405c332ad1405c28a175622924237027383d29586be4276e2a27612b&input=843)
Explanation:
```
9⌐9τk,;;$l3@\3*╤@\(íub)$#p'8=)XkΣ'n*'a+
9⌐9τk                                    push [11, 18]
     ,;;                                 push 3 copies of input (n)
        $l                               get length of n as string (effectively floor(log(n,10)))
          3@\3*╤                         get largest 10^(3n) less than the length
                @\                       get most significant digits of n (x)
                  (í                     bring list from back, push the index of x in the list or -1 if not in list
                    ub)                  increment by 1, convert to boolean, shove to bottom
                       $#p               push first digit from n (as string)
                          '8=            push 1 if "8" else 0
                             )X          shove to bottom of stack, discard remaining digits
                               kΣ'n*     push sum of stack, push a string containing that many "n"s
                                    'a+  push "a", concatenate
```
[Answer]
# [Retina](https://github.com/mbuettner/retina), 34
Direct translation of [my sed answer](https://codegolf.stackexchange.com/a/66842/11259):
```
+`(.)...$
$1
^8.*|^1[18]$
an
\d+
a
```
[Try it online.](http://retina.tryitonline.net/#code=K2AoLikuLi4kCiQxCl44Lip8XjFbMThdJAphbgpcZCsKYQ&input=MTg2NzUzMDk&args=&debug=on)
One byte saved thanks to @Timwi.
[Answer]
# [Perl 6](http://perl6.org), ~~31~~ 30 bytes
```
{'a'~'n'x?/^8|^1<[18]>[...]*$/} # 31 bytes
```
```
{<a an>[?/^8|^1<[18]>[...]*$/]} # 31 bytes
```
```
{<a an>[?/^8|^[11|18][...]*$/]} # 31 bytes
```
```
{'a'~'n'x?/^8|^1[1|8][...]*$/} # 30 bytes
```
```
{<a an>[?/^8|^1[1|8][...]*$/]} # 30 bytes
```
( Perl 6 uses `[ ]` in regexes for non-capturing `( )`, and uses `<[ ]>` for character sets )
Usage:
```
# store it in a lexical code variable for ease of use
my &code = {...}
my @a  = <0 110 1111 1863 110000 180000 1141592 1897932>;
my @an = <8 11 18 843 8192 11000 18000 11234567 18675309>;
say @a.map: &code;
say @an.map: &code;
```
```
(a a a a a a a a)
(an an an an an an an an an)
```
[Answer]
## PostScript, 109 bytes
```
(a)exch 10 string cvs dup[exch length 3 mod 2 eq{(11)(18)}if(8)]{anchorsearch{pop pop(an)exch}if}forall pop =
```
The code verifies if the number starts with certain prefixes. The prefix `8` is always checked (*eight*, *eighty-something*, *eight-hundreds-and*), but `11` and `18` (*eleven* and *eighteen*) are checked only when the number of digits is a multiple of 3 plus 2.
We start with a tentative result of `a` and when a prefix is found the result gets replaced with `an`. `anchorsearch` is used to avoid extracting a prefix from the string. Even if a match is found we continue verifying the rest of the prefixes – why waste 5 bytes for the `exit`? –, but because the original string gets replaced with `a` we are sure not to get any false positives.
To return the `a`-or-`an` result on the operand stack instead of printing it, remove the trailing `=` (resulting length: 107 bytes).
Test code:
```
/DO {
    ... the code above ...
} def
(Should be "a"s:)  = {0 110 1111 1863 110000 180000 1141592 1897932}     { DO } forall
(Should be "an"s:) = {8 11 18 84 843 8192 11000 18000 11234567 18675309} { DO } forall
flush
```
[Answer]
## PostScript (with binary tokens), 63 bytes
```
(a)’>10’¥’1’8[’>’b3’j2’={(11)(18)}if(8)]{’${’u’u(an)’>}if}’I’u=
```
The `’` are bytes with the value 146 (decimal), `¥` is a 165 and `$` is a 3. All others are printable 7-bit ASCII characters.
This is the same as my PostScript [pure ASCII] version, but uses binary tokens where this helps reduce the total length. I post it separately for 3 reasons:
* In the general case, an implementation that minimizes the ASCII code is not necessarily the same as the one minimizing the binary version. Some longer piece of ASCII PostScript code could compress better than another and its corresponding binary version be shorter.
* Binary code is not suitable everywhere, so a pure ASCII answer may be preferred even if longer.
* It wouldn’t be fair to compare the length of a pure ASCII PostScript answer with one using binary encodings.
[Answer]
# Pyth, ~~29~~ 31
```
?:_ec_z3"(^18$|^11$|^8)"0"an"\a
```
Reverses the string, splits it into sections of three, reverses it again, then chooses the appropriate ending.
[Answer]
# Python 3, ~~110~~ ~~93~~ ~~91~~ ~~76~~ ~~74~~ ~~70~~ ~~65~~ 64 bytes
Here is a long one, but a simple one.
**Edit:** Corrected with thanks to [isaacg](https://codegolf.stackexchange.com/users/20080/isaacg). Saved some whitespace after the comparisons. Many bytes saved thanks to [Timwi](https://codegolf.stackexchange.com/users/668/timwi), [Mego](https://codegolf.stackexchange.com/users/45941/mego), [benpop](https://codegolf.stackexchange.com/users/43573/benpop) and [Alissa](https://codegolf.stackexchange.com/users/8550/alissa).
```
n=input();print("a"+"n"*(len(n)%3>1and n[:2]in"118"or"8"==n[0]))
```
or for the same number of bytes.
```
n=input();print("a"+"n"[:len(n)%3>1and n[:2]in"118"or"8"==n[0]])
```
Ungolfed:
```
def a():
    n=input()
    if "8"==n[:1]:
        a = "n"
    elif len(n)%3 == 2 and (n[:2] in ["11", "18"]):
        a = "n"
    else:
        a = ""
    return "a"+a
```
[Answer]
# Java 10, 102 bytes
```
n->{var N=n+"";return(n>9&&"118".contains(N.substring(0,2))&N.length()%3>1)|N.charAt(0)==56?"an":"a";}
```
[Try it online.](https://tio.run/##jVNBbsIwELz3FStLjWy1GEwISRqFqg9oLj2iHoxJITQsKHaQKsrbU5eg3spi2Qd7RzOzY3ujD3qwWX52ptbWwquu8HgHUKErmw9tSih@twBvrqlwBYb7CqDI/OHJLz@t064yUABCDh0OZseDbqDI8YGxrCld2yDHWRoETKmESbND50UsL6RtF/ZMy0ePYyGCQtYlrtyai/twpsR3Ic1aNy@Oj0SeR9NnppE9Mc2yU5f12vt2UXvti4XDrlrC1pPz3u38HbTo7Q@HoPs@vqwrt3LXOrn3GFd7c9J4hXNL/9aVohFKUZBkGtI6fpA8t4DUREXpmKRK4zS8hrpU/lLEa3QJaYr0QwCSCQmgMk4UHYu68RZInnE4iaYx/TDiKByl4vKvTt0P)
**Explanation:**
```
n->{                  // Method with integer parameter and String return-type
  var N=n+"";         //  Input integer as String
  return(n>9&&        //  If the input has at least two digits,
    "118".contains(N.substring(0,2))
                      //  and the first two digits are "11" or "18",
    &N.length()%3>1)  //  and the length modulo-3 is 2
   |N.charAt(0)==56?  //  Or if the first digit is an '8':
     "an"             //   Return "an"
   :                  //  Else:
     "a";}            //   Return "a"
```
[Answer]
# [Japt](https://github.com/ETHproductions/japt), ~~28~~ 27 bytes
```
'a+'npUì v ¥8ª[B18]d¥UìA³ v
```
[Try it online!](https://ethproductions.github.io/japt/?v=2.0a0&code=J2ErJ25wVewgdiClOKpbQjE4XWSlVexBsyB2&input=LW0gWwowLCAvL2EKOCwgLy9hbgoxMSwgLy9hbgoxOCwgLy9hbgo4NCwgLy9hbgoxMTAsIC8vYQo4NDMsIC8vYW4KMTExMSwgLy9hCjE4NjMsIC8vYQo4MTkyLCAvL2FuCjExMDAwLCAvL2FuCjE4MDAwLCAvL2FuCjExMDAwMCwgLy9hCjE4MDAwMCwgLy9hCjExNDE1OTIsIC8vYQoxODk3OTMyLCAvL2EKMTEyMzQ1NjcsIC8vYW4KMTg2NzUzMDkgIC8vYW4KXQ==)
### Unpacked & How it works
```
'a+'npUì v ==8||[B18]d==UìAp3  v
'a+'np  "a" + "n".repeat(...)
Uì v ==8    First digit in decimal == 8
||          or...
[B18]d      [11,18].some(...)
==UìAp3  v  == First digit in base 10**3
```
[Answer]
# GNU `sed -r` + BSD `number`, 34 bytes
```
s/(e?).*/number &/e
s//a\1/
y/e/n/
```
First we convert to English number. Then delete everything except a possible initial `e`, and prefix with `a`. Then convert the `e` (if present) to `n`. The only golfing trick is to match the optional `e` in the first substitution, so we can reuse the pattern in the following line.
## Demo
```
for i in 0 8 11 18 84 110 843 1111 1863 8192 \
    11000 18000 110000 180000 1141592 1897932 11234567 18675309
do printf "%'10d → %s\n" $i $(./66841.sed <<<$i)
done
```
```
         0 → a
         8 → an
        11 → an
        18 → an
        84 → an
       110 → a
       843 → an
     1,111 → a
     1,863 → a
     8,192 → an
    11,000 → an
    18,000 → an
   110,000 → a
   180,000 → a
 1,141,592 → a
 1,897,932 → a
11,234,567 → an
18,675,309 → an
```
[Answer]
# [Perl 5](https://www.perl.org/) `-p`, 26 bytes
```
$_=a.n x/^8|^1[18](...)*$/
```
[Try it online!](https://tio.run/##K0gtyjH9/18l3jZRL0@hQj/OoibOMNrQIlZDT09PU0tF//9/QwtLc0tjo3/5BSWZ@XnF/3ULAA "Perl 5 – Try It Online")
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), ~~26~~ 21 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
₄внŽ4$2ôQàI8Å?+>„ans∍
```
[Try it online](https://tio.run/##ATMAzP9vc2FiaWX//@KChNCy0L3FvTQkMsO0UcOgSTjDhT8rPuKAnmFuc@KIjf//MTEyMzQ1Njc) or [verify all test cases](https://tio.run/##yy9OTMpM/V9Waa@k8KhtkoKSfeX/R00tFzZd2Ht0r4mK0eEtgYcXVFocbrXXtnvUMC8xr/hRR@9/nf/RBjoKhoZgwtAQSFqYGYMFgADEg9KGJoamlkYgAUtzS2MgwwIkCOIDmSYgDNRlYQhWYojQCuIZGZuYmpmDTTY3NTawjAUA).
**Explanation:**
```
₄в          # Convert the (implicit) input-integer to base-1000 as list
  н         # Pop and push the first integer in this list
            #  i.e. 11234567 → [11,234,567] → 11
            #  i.e. 110000 → [110,0] → 110
            #  i.e. 8192 → [8,192] → 8
   Ž4$      # Push compressed integer 1118
      2ô    # Split it into parts of size 2: [11,18]
        Q   # Check for each if it's equal to the integer
         à  # Pop and push the maximum to check if either is truthy
            #  11 → [1,0] → 1
            #  110 → [0,0] → 0
            #  8 → [0,0] → 0
I           # Push the input-integer again
 8Å?        # Check if it starts with an 8
            #  11234567 → 0
            #  110000 → 0
            #  8192 → 1
+           # Add the two checks together
 >          # Increase it by 1
            #  1+0 → 1 → 2
            #  0+0 → 0 → 1
            #  0+1 → 1 → 2
  „an       # Push string "an"
     s∍     # And shorten it to a length equal to the integer
            #  2 → "an"
            #  1 → "a"
            #  2 → "an"
            # (after which the result is output implicitly)
```
[See this 05AB1E tip of mine (section *How to compress large integers?*)](https://codegolf.stackexchange.com/a/166851/52210) to understand why `Ž4$` is `1118`.
[Answer]
## [TeaScript](https://esolangs.org/wiki/TeaScript), 35 bytes
```
[18,11,8,80]I(+xh(x.n%3¶3©?'an':'a'
```
[Try it here.](http://vihanserver.tk/p/TeaScript/#?code=%22%5B18,11,8,80%5DI%28%2Bxh%28x.n%253%C2%B63%C2%A9%3F'an':'a'%22&inputs=%5B%2218675309%22%5D&opts=%7B%22int%22:false,%22ar%22:false,%22debug%22:false,%22chars%22:false,%22html%22:false%7D)
### Explanation
```
               xh(x.n%3¶3           get the relevant digits from the input
                                    xh compiles to x.head which returns the
                                    first n chars of x (implicit input)
                                    ¶ ('\xb6') compiles to ||
              +                     cast the result to an integer since
                                    .includes does a strict comparison
                         ©          ('\xa9') compiles to ))
[18,11,8,80]                        array of the special cases
            I(                      I( is an alias for .includes( which
                                    returns true if the array contains the
                                    argument
                          ?'an':'a' finally, return 'an' if the array
                                    contains the number, 'a' otherwise
```
[Answer]
## Python 2.7, 66
```
s=`input()`
print['a','an'][s[:1]=='8'or s[:2]in len(s)%3/2*'118']
```
Obviously not as short as the `lambda` one.
[Answer]
# [QuadS](https://github.com/abrudz/QuadRS), 32 bytes
```
'a',⍵
^8.*|^1[18](...)*$
⊃⍵L/'n'
```
[Try it online!](https://tio.run/##KyxNTCn@/189UV3nUe9WrjgLPa2aOMNoQ4tYDT09PU0tFa5HXc1AGR999Tz1//8NDQ0MDAA "QuadS – Try It Online")
[Answer]
# [Stax](https://github.com/tomtheisen/stax), 25 [bytes](https://github.com/tomtheisen/stax/blob/master/docs/packed.md#packed-stax)
```
â-x▬♪°∞▄'δL|÷æ╪║>₧4¢ÿ·7åR
```
[Run and debug it](https://staxlang.xyz/#p=832d78160df8ecdc27eb4c7cf691d8ba3e9e349b98fa378652&i=0%0A8%0A11%0A18%0A84%0A110%0A843%0A1111%0A1863%0A8192%0A11000%0A18000%0A110000%0A180000%0A1141592%0A1897932%0A11234567%0A18675309&a=1&m=2)
Unpacked, ungolfed, and commented, it looks like this.
```
Vk|Eh       get the first "digit" after converting to base 1000
AJ|Eh       get the first "digit" after converting to base 100
c20>9*^/    if the result is greater than 20, divide it by 10 again
"AMj"!#     is the result one of [8, 11, 18]?
^           increment by 1
.an(        keep that many characters of the string "an"
```
[Run this one](https://staxlang.xyz/#c=Vk%7CEh+++%09get+the+first+%22digit%22+after+converting+to+base+1000%0AAJ%7CEh+++%09get+the+first+%22digit%22+after+converting+to+base+100%0Ac20%3E9*%5E%2F%09if+the+result+is+greater+than+20,+divide+it+by+10+again%0A%22AMj%22%21%23+%09is+the+result+one+of+[8,+11,+18]%3F%0A%5E+++++++%09increment+by+1%0A.an%28++++%09keep+that+many+characters+of+the+string+%22an%22&i=0%0A8%0A11%0A18%0A84%0A110%0A843%0A1111%0A1863%0A8192%0A11000%0A18000%0A110000%0A180000%0A1141592%0A1897932%0A11234567%0A18675309&a=1&m=2)
[Answer]
# [Whitespace](https://web.archive.org/web/20150618184706/http://compsoc.dur.ac.uk/whitespace/tutorial.php), 243 bytes
```
[S S S T    T   S S S S T   N
_Push_97_a][T   N
S S _Print_as_character][S S S T    N
_Push_1][S N
S _Duplicate_1][S N
S _Duplicate_1][T   N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve_input][N
S S S T N
_Create_Label_LOOP][S N
T   _Swap_top_two][S S S T  N
_Push_1][T  S S S _Add][S N
T   _Swap_top_two][S N
S _Duplicate][S S S T   T   S S T   S S N
_Push_100][T    S S T   _Subtract][N
T   T   T   N
_If_negative_jump_to_Label_TWO_DIGITS][S S S T  S ST    S N
_Push_10][T S T S _Integer_division][N
S N
S T N
_Jump_to_Label_LOOP][N
S S T   N
_Create_Label_TWO_DIGITS][S N
S _Duplicate][S S S T   S S S N
_Push_8][T  S S T   _Subtract][N
T   S S S N
_If_zero_jump_to_Label_PRINT_n][S N
S _Duplicate][S S S T   S T T   N
_Push_11][T S S T   _Subtract][N
T   S S N
_If_0_jump_to_Label_2_MOD_3][S N
S _Duplicate][S S S T   S S T   S N
_Push_18][T S S T   _Subtract][N
T   S S N
_If_0_jump_to_Label_2_MOD_3][S S S T    S ST    S N
_Push_10][T S T S _Integer_division][S N
S _Duplicate][N
T   S N
_If_0_jump_to_Label_EXIT][N
S N
T   N
_Jump_to_Label_TWO_DIGITS][N
S S S N
_Create_Label_2_MOD_3][S N
T   _Swap_top_two][S S S T  T   N
_Push_3][T  S T T   _Modulo][S S S T    S M
_Push_2][T  S S T   _Subtract][N
T   T   N
_If_negative_jump_to_Label_EXIT][N
S S S S N
_Create_Label_PRINT_n][S S S T  T   S T T   T   S N
_Push_110_n][T  N
S S _Print_as_character][N
S S N
_Create_Label_EXIT]
```
Letters `S` (space), `T` (tab), and `N` (new-line) added as highlighting only.  
`[..._some_action]` added as explanation only.
[Try it online](https://tio.run/##TY9dCoAwDIOf21PkCIr4dxwRQd8EBY8/l9SpG4Qu/Rq6a93O5dineUkJgBmobo4okAunweOPZcGQyCqUg6ZnwELzdYkivOSJLCirYpq95gcafuYvFFrEqYxG2YukvvEORj@m2WND34KnVA9d3zbVeAM) (with raw spaces, tabs and new-lines only).  
Program stops with an error: No exit found.
**Explanation in pseudo-code:**
```
Print "a"
Integer input = STDIN as integer
Integer counter = 1
Start LOOP:
  counter = counter + 1
  If(input < 100)
    Jump to function TWO_DIGITS
  input = input integer-divided by 10
  Go to next iteration of LOOP
function TWO_DIGITS:
  If(input == 8)
    Jump to function PRINT_n
  If(input == 11 or input == 18)
    Jump to function 2_MOD_3
  input = input integer-divided by 10
  If(input == 0)
    Exit program
  Recursive call to TWO_DIGITS
function 2_MOD_3:
  If(counter modulo-3 != 2)
    Exit program
  Jump to function PRINT_n
function PRINT_n:
  Print "n"
  Exit program
```
[Answer]
# C++, ~~80~~ 79 bytes
```
[](int i){for(;i>999;i/=1e3);return i-11&&i-18&&i/100-8&&i/10-8&&i-8?"a":"an";}
```
It turned out 4 bytes shorter to explicitly test against 8xx and 8x than to have another `/=10` loop, like this:
```
[](int i){for(;i>999;i/=1e3);for(i==11|i==18?i=8:0;i>9;i/=10);return i-8?"a":"an";}
```
## Demo
```
#include <locale>
#include <cstdio>
int main(int argc, char**argv)
{
    auto const f =
        [](int i){for(;i>999;i/=1e3);return i-11&&i-18&&i/100-8&&i/10-8&&i-8?"a":"an";}
    ;
    std::locale::global(std::locale{""});
    for (int i = 1;  i < argc;  ++i) {
        auto const n = std::stoi(argv[i]);
        printf("%'10d → %s\n", n, f(n));
    }
}
```
```
         0 → a
         8 → an
        11 → an
        18 → an
        84 → an
       110 → a
       843 → an
     1,111 → a
     1,863 → a
     8,192 → an
    11,000 → an
    18,000 → an
   110,000 → a
   180,000 → a
 1,141,592 → a
 1,897,932 → a
11,234,567 → an
18,675,309 → an
```
[Answer]
# Perl, ~~71~~ ~~55~~ 49 bytes
```
$_=<>;$_=/^8/||/^1[18]/&&length%3==1?'an':'a';say
```
I knew the ternary operator would help one day...
Let me break this down.
* `$_=<>` accepts a number as input.
* The big `$_=...` block will set the value of `$_` after it's used.
	+ `...?...:...` is the ternary operator. If the condition (first argument) is true, it returns the second argument. Otherwise, it returns the third.
	+ `/^8/||(/^1[18]/&&length%3==2)` checks to see if the number starts with 8 or begins with 11 or 18 (`1[18]` accepts either) and has a length mod 3 of 2.
	+ If that's true, `$_` is set to `an`. Otherwise, it's set to `a`.
* It then prints out the contents of `$_` (either `a` or `an`) with `say`.
**Changes**
* Saved 16 bytes thanks to msh210.
* Saved 6 bytes by removing parens and using defaults.
]