g | x | w | all
Bytes Lang Time Link
047Google Sheets250820T093939Zdoubleun
046Swift 6250425T232000ZmacOSist
106Type the TS type system250423T205750ZGeneral
032Casio BASIC CASIO fx9750GIII250423T133417Zmadeforl
022Raku Perl 6 rakudo250417T192145Zxrs
043Tcl181002T134252Zsergiol
033><>240613T211216Zmbomb007
057Forth gforth181003T123928Zreffu
1097Scratch 3240613T142336Zlyxal
020Uiua SBCS240613T040922Zchunes
019PowerShell181003T082200Zmazzy
009Pip240118T231054ZDLosc
036Uiua240119T051758ZMaxim Kh
008Pip l181003T010941ZDLosc
032Awk240118T184529ZcamelCas
004Vyxal 3 Rj240113T094640Zpacman25
nanFig221012T211618Zemanresu
005Vyxal221012T054336ZDialFros
nan210322T083058Zemanresu
019Perl 5190821T183858ZXcali
011Pyth181003T125424ZElPedro
081C++190629T224755ZHatsuPoi
040PHP 7.1181003T042314ZTitus
018Vim190628T184458ZDJMcMayh
034ink190329T211815ZSara J
050SmileBASIC181124T133936Z12Me21
042Scala181104T134617Z6infinit
048Windows Batch181006T135539Zstevefes
046Python 3181003T180340ZGigaflop
1706Taxi181003T100348ZJosiahRy
048Z80Golf181004T230845Zuser3604
057JavaScript181008T034636Zguest271
044JavaScript Node.js181006T014243Zggorlen
033Ruby181007T201739ZTebogo
057Haskell181006T142249Zschueler
027Tidy181005T150807ZConor O&
065Crystal181005T140945ZDylan
062[C# .NET Core]181004T205858ZMeerkat
007Japt181002T132518ZLuis fel
056C clang181004T233226Zuser3604
045LUA181005T093202Zouflak
006MathGolf181003T062944Zmaxb
007Ohm v2181004T234451ZThePlasm
017Pyth181004T222919ZTryer
065Rust181004T213859Zchryslov
013V181003T121302ZEndenite
016sh + coreutils181004T161235Z2xsaiko
066F#181004T080122Zdumetrul
031Ruby181003T081337ZIdva
034APLNARS181003T071559Zuser5898
031Ruby181004T043948ZConor O&
024Attache181004T042842ZConor O&
017Retina181002T133637ZNeil
025Perl 5 5.12+181003T162355Zhobbs
065TSQL181003T160546ZBradC
059MBASIC181003T155751Zwooshiny
007Jelly181003T150644ZErik the
015K4181003T124549Zmkst
016PowerShell181002T211035ZAdmBorkB
028Ruby181003T084831Zmanatwor
051SimpleTemplate181003T101648ZIsmael M
176brainfuck181003T082712ZJo King
019Gol><>181003T084012ZGegell
121Whitespace181003T064327ZKevin Cr
016Bash + GNU utilities181003T030431ZDigital
051JavaScript ES6181003T043113ZDLosc
1092ORK181003T034745ZJosiahRy
031Bash181003T030536Zketone
055C GCC181003T015254ZAsleepac
031Haskell181003T004558ZKhuldrae
042Wolfram Language Mathematica181003T013651ZMisha La
032Kotlin181003T011616Zsnail_
039Python 2181002T235320Zxnor
006Stax181002T210054Zrecursiv
019R181002T135147Zngm
043JavaScript ES6181002T140215ZArnauld
044Red181002T134644ZGalen Iv
022Perl 6181002T133652ZJo King
067Java 10181002T134142ZKevin Cr
00605AB1E181002T133415ZEmigna
044Python 2181002T132339ZTFeld

Google Sheets, 47 bytes

=filter(row(1:100),iserror(find(2,row(1:100))))

Tried various tocol(sort(find()),2) constructions but couldn't find anything shorter.

Swift 6, 46 bytes

print((1...100).filter{!($0%10==2||$0/10==2)})

TypeScript (the TS type system), 106

If we don't care about errors whatsoever:

type D<R=[0,0],O="1",L=R["length"]>=101 extends L?O:C<[...R,0],`${L}`extends`${any}2${any}`?O:`${O}
${L}`>

If we do, then the score is 150.

type C<R extends any[]=[0,0],O extends string="1",L extends number=R["length"]>=101 extends L?O:C<[...R,0],`${L}`extends`${any}2${any}`?O:`${O}
${L}`>

In either case, to get the output, you can paste it into TS Playground or your IDE of choice, then mouse over the assigned type:

type A=C
type B=D

And it should print

"1\n3\n4\n5\n6\n7\n8\n9\n10\n11\n13\n14\n15\n16\n17\n18\n19\n30\n31\n33\n34\n35\n36\n37\n38\n39\n40\n41\n43\n44\n45\n46\n47\n48\n49\n50\n51\n53\n54\n55\n56\n57\n58\n59\n60\n61\n63\n64\n65\n66\n67\n68\n69\n70\n71\n73\n74\n75\n76\n77\n78\n79\n80\n81\n83\n84\n85\n86\n87\n88\n89\n90\n91\n93\n94\n95\n96\n97\n98\n99\n100"

The \ns are not literally those characters, but TS Playground outputs new lines that way.

Casio BASIC (CASIO fx-9750GIII), 36 32 bytes

For 1→N To ᴇ2
.1N
Frac Ans≠.2 And Int Ans≠2⟹N◢
Next

pretty awesome

Raku (Perl 6) (rakudo), 22 bytes

.say if !/2/for 1..100

Attempt This Online!

Feels like there should be a shorter way.

Tcl, 43 bytes

time {if ![regexp 2 [incr i]] puts\ $i} 100

Try it online!


# [Tcl], 47 bytes
time {if [incr i]%10!=2&$i/10!=2 {puts $i}} 100

Try it online!


# [Tcl], 48 bytes
time {if {2ni[split [incr i] ""]} {puts $i}} 100

Try it online!

><>, 40 33 bytes

0v
o>1+:::a%:2=@-a,2=+?!n:b9*)?;0

Try it online!

Or watch the execution in real time with this interpreter

All the numbers are output, with a NUL byte output instead of numbers with 2. The online interpreter shows spaces for these.

Explanation

Code is on the left, the stack after running that code is in the middle, and comments are on the right. The top of the stack is the right side of the stack.

0v               push zero (n=0) on the stack and go down
>                move right
1+  n n          increment n
::: n n n n      duplicate n thrice
a%  n n n o      push n % 10, represented by o (ones place)
:   n n n o o    duplicate o
2=  n n n o o=2  if o == 2
@   n n o=2 n o  rotate (put the top value down to the 3rd)
-   n n o=2 n-o  n-o, which is n-(n%10)
a,  n n o=2 t    t = (n-o)/10 = the tens place. ><> has float division, so this is needed instead
2=  n n o=2 t=2  
+   n n o=2|t=2  add (OR) them together
?!n n            print the number n if neither ones nor tens were 2
:   n n          duplicate n
b9* n n 99       push 11*9 = 99
)   n n>99       n > 99
?;  n            exit if (n > 99)
0   n 0          push zero (replace with "a" for newlines instead)
                 (loop back around)
o   n            output character with byte 0
                 (back to the ">" above)

Values containing 2 (and 100) are left on the stack, because garbage cleanup would cost additional bytes.

Forth (gforth), 58 57 bytes

: f 'e 1 do i 10 /mod 2 <> swap 2 <> * if i . then loop ;

Try it online!

Explanation

Loops from 1 to 100 (inclusive) and if both the ones and tens place of the index are not equal to 2, print it

Code explanation

: f                    \ start a new word definition
  'e 1 do             \ start a loop from 1 to 100 inclusive
    i 10 /mod          \ get the quotient and remainder of dividing i by 10
    2 <>               \ check if the the tens place is not equal to 2
    swap               \ move the result down the stack one
    2 <>               \ check that the ones place is not equal to 2
    *                  \ multiply results (cheaper AND)
    if i . then        \ if true, output i
  loop                 \ end counted loop
;                      \ end word definition

Scratch 3, 10 blocks / 97 bytes

enter image description here

Try it online!

ScratchBlocks Syntax

when GF clicked
set[n v]to(0
repeat(100
change[n v]by(1
if<not<(n)contains(2)>>then
add(n)to[o v

Very simple implementation, outputs to list o.

Uiua SBCS, 20 bytes

≡&p▽∵◇/↧⊸≠@2°⋕+1⇡100

Try it!

Explanation

≡&p▽∵◇/↧⊸≠@2°⋕+1⇡100­⁡​‎‎⁡⁠⁤⁣‏⁠‎⁡⁠⁤⁤‏⁠‎⁡⁠⁢⁡⁡‏⁠‎⁡⁠⁢⁡⁢‏⁠‎⁡⁠⁢⁡⁣‏⁠‎⁡⁠⁢⁡⁤‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁢‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁣⁡‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁤‏‏​⁡⁠⁡‌⁢⁣​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏⁠‎⁡⁠⁣‏‏​⁡⁠⁡‌­
              +1⇡100  # ‎⁡a list from one to a hundred
            °⋕        # ‎⁢convert each number to a string
         ≠@2          # ‎⁣list of masks of where digits are not two
        ⊸             # ‎⁤...preserving original list under masks
    ∵◇/↧              # ‎⁢⁡minimum of each (unboxed) mask
   ▽                  # ‎⁢⁢filter numbers
≡&p                   # ‎⁢⁣print each
💎

Created with the help of Luminespire.

PowerShell, 19 bytes

1..100-split'.*2.*'

This script show null-value instead 'numbers with 2 inside' and completely solves the task 'number 2 shouldn’t appear anywhere in the sequence'.

Output:

1


3
4
5
6
7
8
9
10
11


13
14
15
16
17
18
19




















30
31


33
34
35
36
37
38
39
40
41


43
44
45
46
47
48
49
50
51


53
54
55
56
57
58
59
60
61


63
64
65
66
67
68
69
70
71


73
74
75
76
77
78
79
80
81


83
84
85
86
87
88
89
90
91


93
94
95
96
97
98
99
100

PowerShell (output does not contain null-values), 24 bytes

1..100-split'.*2.*'-ne''

Pip, 10 9 bytes

LhUi~2|Pi

Attempt This Online!

Explanation

Flagless version, inspired by Xcali's Perl answer.

           i is preinitialized to 0
Lh         Loop 100 times:
  Ui        Increment i
    ~2      Find first match of 2 in (the new value of) i
      |     If no match was found, then
       Pi   Print i

Uiua, 36 bytes

Returns an array with numbers from 1 to 100 where the elements containing a two are removed.

▽×∩(≠2)⌊⊃÷◿10.+1⇡100

Try It

▽×∩(≠2)⌊⊃÷◿10.+1⇡100
              +1⇡100 # generate numbers 1..100
             . # duplicate the array for filtering
        ⊃÷◿10 # both divide by 10 and mod 10 each number
       ⌊ # floor the division result so that we have the 10s place
  ∩(≠2) # for both the mod and floored division (ones and tens places)
        # check that there is no 2
 × # use multiply as and
▽ # filter the array

Pip -l, 9 8 bytes

2N_FN\,h

Attempt This Online!

Explanation

       h  Preset variable: 100
     \,   1-based range: [1 2 3 ... 100]
   FN     Filter Negated on this function (i.e. keep falsey results):
2N_        Number of 2s iN the argument
          Print the resulting list (newline-separated thanks to -l flag)

Awk, 32 bytes

END{while(i++<100)print i~2?a:i}

Try it online!

To save space, I used Awk's behavior of assigning the null string to uninitialized variables to avoid initializing the counter and saving a byte with the null string literal.

Vyxal 3 Rj, 4 bytes

₅ᶻ2c

Try it Online!

rip -H flag

Fig, \$9\log_{256}(96)\approx\$ 7.408 bytes

Fa@2'r-2f

Try it online!

-1 or something thanks to Seggan

F         # Filter 
 a@2      # range(1, 100)
    '     # by...
      -2  # Subtracting 2 from
        f # each digit
     r    # Are all truthy?

Vyxal, 5 bytes

₁'2c¬

Try it Online!

Explained

₁'2c¬
₁     # push 100 to stack
 '    # filter lambda
  2c  # contains 2
    ¬ # logical NOT

Deadfish~

{iiiii}dc{dddd}ic{iiii}ic{dddd}dc{iiii}iic{dddd}ddc{iiii}iiic{dddd}dddc{iiii}iiiic{dddd}ddddc{iiii}iiiiic{dddd}dddddc{iiii}iiiiiic{dddd}ddddddc{iiiii}dddc{ddddd}iiic{iiii}dcdc{dddd}iic{iiii}dcc{dddd}ic{iiii}dciic{dddd}dc{iiii}dciiic{dddd}ddc{iiii}dciiiic{dddd}dddc{iiii}dciiiiic{dddd}ddddc{iiii}dciiiiiic{dddd}dddddc{iiii}dc{i}dddc{dddd}ddddddc{iiii}dc{i}ddc{ddddd}iiic{iiii}icdddc{dddd}iic{iiii}icddc{dddd}ic{iiii}icc{dddd}dc{iiii}icic{dddd}ddc{iiii}iciic{dddd}dddc{iiii}iciiic{dddd}ddddc{iiii}iciiiic{dddd}dddddc{iiii}iciiiiic{dddd}ddddddc{iiii}iciiiiiic{ddddd}iiic{iiii}iicddddc{dddd}iic{iiii}iicdddc{dddd}ic{iiii}iicdc{dddd}dc{iiii}iicc{dddd}ddc{iiii}iicic{dddd}dddc{iiii}iiciic{dddd}ddddc{iiii}iiciiic{dddd}dddddc{iiii}iiciiiic{dddd}ddddddc{iiii}iiciiiiic{ddddd}iiic{iiii}iiicdddddc{dddd}iic{iiii}iiicddddc{dddd}ic{iiii}iiicddc{dddd}dc{iiii}iiicdc{dddd}ddc{iiii}iiicc{dddd}dddc{iiii}iiicic{dddd}ddddc{iiii}iiiciic{dddd}dddddc{iiii}iiiciiic{dddd}ddddddc{iiii}iiiciiiic{ddddd}iiic{iiii}iiiicddddddc{dddd}iic{iiii}iiiicdddddc{dddd}ic{iiii}iiiicdddc{dddd}dc{iiii}iiiicddc{dddd}ddc{iiii}iiiicdc{dddd}dddc{iiii}iiiicc{dddd}ddddc{iiii}iiiicic{dddd}dddddc{iiii}iiiiciic{dddd}ddddddc{iiii}iiiiciiic{ddddd}iiic{iiii}iiiiic{d}iiic{dddd}iic{iiii}iiiiicddddddc{dddd}ic{iiii}iiiiicddddc{dddd}dc{iiii}iiiiicdddc{dddd}ddc{iiii}iiiiicddc{dddd}dddc{iiii}iiiiicdc{dddd}ddddc{iiii}iiiiicc{dddd}dddddc{iiii}iiiiicic{dddd}ddddddc{iiii}iiiiiciic{ddddd}iiic{iiii}iiiiiic{d}iic{dddd}iic{iiii}iiiiiic{d}iiic{dddd}ic{iiii}iiiiiicdddddc{dddd}dc{iiii}iiiiiicddddc{dddd}ddc{iiii}iiiiiicdddc{dddd}dddc{iiii}iiiiiicddc{dddd}ddddc{iiii}iiiiiicdc{dddd}dddddc{iiii}iiiiiicc{dddd}ddddddc{iiii}iiiiiicic{ddddd}iiic{iiiii}dddc{d}ic{dddd}iic{iiiii}dddc{d}iic{dddd}ic{iiiii}dddcddddddc{dddd}dc{iiiii}dddcdddddc{dddd}ddc{iiiii}dddcddddc{dddd}dddc{iiiii}dddcdddc{dddd}ddddc{iiiii}dddcddc{dddd}dddddc{iiiii}dddcdc{dddd}ddddddc{iiiii}dddcc{ddddd}iiic{iiii}dcdcc

Perl 5, 19 bytes

map{/2/||say}1..100

Try it online!

Pyth, 13 11 bytes

f!}`2`TS100

Try it online!

-2 with many thanks (nearly a year later!) to @ar4093

Original version:

VS*TTI!}\2`NN

Try it online!

I'm still a Pyth beginner so this could probably be improved on.

Explanation

for N in num_to_range(Psorted(times(T,T))):   # For N in range 1 to 10*10
 if Pnot(Pin("2",repr(N))):                   # If "2" is not in `N`
  imp_print(N)                                # Print N

C++, 84 81 bytes

-3 bytes thanks to ceilingcat

The function needs a void return value to compile with MSVC

#include<cstdio>
void f(){for(int i=0;++i<101;)i%10-2&&i/10-2&&printf("%d\n",i);}

The if read as "if the first digit isn't 2 and the second digit isn't 2"

PHP 7.1, 40 bytes

while($i++<100)strstr($i,50)||print$i._;

prints numbers separated by underscores. Run with -nr or try it online.

Vim, 18 bytes/keystrokes

100o0<esc>V{g<C-a>J:g/2/d<cr>

Try it online!

ink, 34 bytes

-(i){("{i}"!?"2"):{i}}
{i<100:->i}

Try it online!

Explanation

-(i)             // Labelled gather - keeps track of how many times it's been visited (in variable i)
{"{i}"!?"2":     // If "2" is not a substring of i...
{i}              // ...print i
}
{i<100:->i}      // If i is less than 100, go back to i.

SmileBASIC, 50 bytes

@L
N=N+1IF.>INSTR(STR$(N),"2")THEN?N
ON N>99GOTO@L

Explanation:

@LABEL
 N = N + 1
 IF 0 > INSTR(STR$(N), "2") THEN PRINT N
ON N>99 GOTO @LABEL

INSTR(STR$(N), "2") is -1 if N doesn't contain a 2.

ON ... GOTO takes a list of labels, and jumps to a label in that list corresponding to the value of an expression.
If N isn't greater than 99, N>99 returns 0 so it jumps to the 0th label, @LABEL.
Otherwise, N>99 is 1 so it tries to jump to label 1 in the list, but since the list isn't long enough, it doesn't jump and the program ends.

ON is meant to be used like switch/case, with a longer list of labels. But ON x GOTO @LABEL can be used as a shorter way of writing IF !(x) GOTO @LABEL:

IF N<=99GOTO@L
IF N<100GOTO@L
ON N>99GOTO@L

Scala, 56 48 47 45 42 bytes

1 to'd'filter(_+""forall(50!=))map println

Prints the elements separated by a line.

Here is a 38 bytes version that calls toString (technically allowed by the rules):

print(1 to'd'filter(_+""forall(50!=)))

Resulting in:

Vector(1, 3, 4, ..., 100)

Windows Batch, 49 48 bytes

@for /l %%G in (1,1,100)do @echo %%G|find /v "2"

Loops from 1 to 100, and for each number looped, only output those who does not contain any "2".

1 byte is saved by @Neil.

Python 3, 53 51 50 49 46 bytes

['2'in str(n)or print(n)for n in range(1,101)]

Try it online!

Not the strongest language for this task, but I'm new to golfing.

Thanks to the commenters for their tips!

Taxi, 2399 2391 2370 1783 1773 1706 bytes

-8 bytes for realizing that, instead of leaving a certain passenger at Sunny Side Park forever, it's more worth it to throw them off of Riverview Bridge. Ah, what a lovely town this is.

-21 bytes for taking out a comment I stupidly left in.

-587 bytes by simply changing the entire way I went about this (apparently a shorter way is by arithmetic; integer-dividing [17, 27, 37, 47,...] by 9 yields the sequence, but you gotta skip over the 20's yourself.)

-17 bytes for the realization that any quotes-encased string without a space doesn't need quotes after all (thanks Jo King!).

-67 bytes for the realization that linebreaks are optional.

17 is waiting at Starchild Numerology.Go to Starchild Numerology:w 1 l 2 r 1 l 1 l 2 l.Pickup a passenger going to Cyclone.Go to Cyclone:e 1 l 2 r.[B]Pickup a passenger going to Cyclone.Pickup a passenger going to Divide and Conquer.9 is waiting at Starchild Numerology.Go to Starchild Numerology:s 2 l 2 r.Pickup a passenger going to Divide and Conquer.Go to Divide and Conquer:e 1 l 2 r 3 r 2 r 1 r.Pickup a passenger going to Trunkers.Go to Trunkers:e 1 r 3 r 1 l.Pickup a passenger going to The Babelfishery.Go to The Babelfishery:e 1 r 1 r.Pickup a passenger going to Post Office.\n is waiting at Writer's Depot.Go to Writer's Depot:n 5 l 2 l.Pickup a passenger going to Post Office.Go to Post Office:n 1 r 2 r 1 l.Go to Cyclone:s 1 r 1 l 2 r.Pickup a passenger going to Addition Alley.Pickup a passenger going to Equal's Corner.177 is waiting at Starchild Numerology.Go to Starchild Numerology:s 2 l 2 r.Pickup a passenger going to Equal's Corner.Go to Equal's Corner:w 1 l.Switch to plan C if no one is waiting.Pickup a passenger going to Sunny Skies Park.100 is waiting at Starchild Numerology.Switch to plan D.[C]10 is waiting at Starchild Numerology.[D]Go to Starchild Numerology:n 1 r.Pickup a passenger going to Addition Alley.Go to Sunny Skies Park:w 1 r.Go to Addition Alley:n 1 r 1 r 1 r.Pickup a passenger going to Cyclone.Go to Cyclone:n 1 l 1 l.Pickup a passenger going to Cyclone.Pickup a passenger going to Equal's Corner.917 is waiting at Starchild Numerology.Go to Starchild Numerology:s 2 l 2 r.Pickup a passenger going to Equal's Corner.Go to Equal's Corner:w 1 l.Switch to plan E if no one is waiting.Switch to plan F.[E]Go to Go More:n 1 l.Go to Cyclone:w 1 r.Switch to plan B.[F]

Try it online!

This one isn't winning me any code golf competitions anytime soon, but I decided to try out the esolang Taxi.

Taxi is an esolang in which all programming is done by picking up and dropping off passengers at various stops in the fictional town of Townsburg. Of course, your taxicab will sometimes run out of gas, so you also need to visit gas stations every so often, and pay using the credits you receive as fare (in this case, I only need to stop for gas - at Go More - once per loop iteration!).

I used some tricks that reduce the filesize a bit, such as rephrasing directions like east 1st left, 2nd right as e 1 l 2 r, removing the word the where it is optional, and using the least complicated route towards all of my destinations (not necessarily the shortest path).

I hate this shorter solution more than the one I originally came up with. This solution down here is a more general way of accomplishing the task, which could start and end anywhere you want. Here it is, in its entirety.

2245 bytes (way more general)

1 is waiting at Starchild Numerology.Go to Starchild Numerology:w 1 l 2 r 1 l 1 l 2 l.Pickup a passenger going to Cyclone.Go to Cyclone:e 1 l 2 r.[B]Pickup a passenger going to Addition Alley.Pickup a passenger going to The Babelfishery.Go to The Babelfishery:n 2 r 2 r.Pickup a passenger going to Cyclone.Go to Cyclone:n 5 l 2 l.Pickup a passenger going to Chop Suey.Go to Zoom Zoom:n.0 is waiting at Writer's Depot.Go to Writer's Depot:w.Pickup a passenger going to Narrow Path Park.Go to Narrow Path Park:n 3 r 1 l 1 r.Go to Chop Suey:e 1 r 1 l 1 r.[C]Switch to plan E if no one is waiting.Pickup a passenger going to Crime Lab.2 is waiting at Writer's Depot.Go to Writer's Depot:n 1 l 3 l.Pickup a passenger going to Crime Lab.Go to Crime Lab:n 3 r 2 r.Switch to plan D if no one is waiting.Pickup a passenger going to KonKat's.Go to Narrow Path Park:n 5 l.Pickup a passenger going to KonKat's.Go to KonKat's:e 1 r.Pickup a passenger going to Narrow Path Park.Go to Narrow Path Park:n 2 l.Go to Chop Suey:e 1 r 1 l 1 r.Switch to plan C.[D]Go to Chop Suey:n 5 r 1 l.Switch to plan C.[E]Go to Narrow Path Park:n 1 l 1 r 1 l.Pickup a passenger going to Crime Lab.0 is waiting at Writer's Depot.Go to Writer's Depot:w 1 l 1 r 2 l.1 is waiting at Starchild Numerology.Pickup a passenger going to Crime Lab.Go to Crime Lab:n 3 r 2 r.Switch to plan F if no one is waiting.Pickup a passenger going to Riverview Bridge.Go to Cyclone:n 4 l 2 l.Pickup a passenger going to Post Office.Go to Riverview Bridge:n 2 r.\n is waiting at Writer's Depot.Go to Writer's Depot:w 2 l.Pickup a passenger going to Post Office.Go to Post Office:n 1 r 2 r 1 l.Go to Starchild Numerology:s 1 r 1 l 1 l 2 l.Switch to plan G.[F]Go to Cyclone:s 1 r 1 l 2 r.Pickup a passenger going to Riverview Bridge.Go to Riverview Bridge:n 2 r.Go to Starchild Numerology:w 2 l 3 l 2 r.[G]Pickup a passenger going to Addition Alley.Go to Addition Alley:e 1 l 2 r 3 r 1 r.Pickup a passenger going to Magic Eight.101 is waiting at Starchild Numerology.Go to Starchild Numerology:n 1 l 1 l 3 l 2 r.Pickup a passenger going to Magic Eight.Go to Magic Eight:w 1 r 2 r 1 r.Switch to plan H if no one is waiting.Pickup a passenger going to Cyclone.Go to Cyclone:n 1 l 2 r.Switch to plan B.[H]

Try it online!

And if mega-cheating is allowed, this one is way shorter than either of the last two.

456 bytes (totally cheating)

1\n3\n4\n5\n6\n7\n8\n9\n10\n11\n13\n14\n15\n16\n17\n18\n19\n30\n31\n33\n34\n35\n36\n37\n38\n39\n40\n41\n43\n44\n45\n46\n47\n48\n49\n50\n51\n53\n54\n55\n56\n57\n58\n59\n60\n61\n63\n64\n65\n66\n67\n68\n69\n70\n71\n73\n74\n75\n76\n77\n78\n79\n80\n81\n83\n84\n85\n86\n87\n88\n89\n90\n91\n93\n94\n95\n96\n97\n98\n99\n100 is waiting at Writer's Depot.Go to Writer's Depot:w 1 l 2 r 1 l 2 l.Pickup a passenger going to Post Office.Go to Post Office:n 1 r 2 r 1 l.

Try it online!

Z80Golf, 49 48 bytes

00000000: 1630 2e0a 5faf f57b fe02 2818 82ff f182  .0.._..{..(.....
00000010: ff92 3cf5 7dff f1bd 280a fe02 2803 f518  ..<.}...(...(...
00000020: e63c 18fa 7b3c bd20 db3e 31ff 3dff ff76  .<..{<. .>1.=..v

Try it online!

Assembly:

ld d, 30h			; ascii '0' character
ld l, 0Ah			; number 10 and ascii newline
tens:
	ld e,a			; store tens digit
	xor a			; reset ones digit to 0
	push af			; store initial ones digit 0
	ones:
		ld a,e		; get stored tens digit
		cp 2
		jr z,cont	; if tens digit==2(e.g.20-29),skip loop
		add d
		rst 38h 	; print tens digit
		pop af		; get stored ones digit
		add d
		rst 38h 	; print ones digit
		sub d
		inc a		; increment ones digit
		push af		; store ones digit
		ld a, l
		rst 38h 	; print newline
		pop af		; get stored ones digit again
		cp l
		jr z,cont	; if ones digit==10, break loop
		cp 2
		jr z,inc_again	; if ones digit==2, incr again
		repeat_loop:
		push af		; store ones digit again
		jr ones		; repeat print loop
		inc_again:
			inc a
			jr repeat_loop
		
	cont:
	ld a,e			; get stored tens digit
	inc a			; increment tens digit
	cp l
	jr nz, tens		; if tens place!=10, continue loop
ld a,31h
rst 38h				; print '1'
dec a
rst 38h				; print '0'
rst 38h				; print '0'
halt

Saved one byte with the repeat_loop jump

JavaScript, 57 bytes

_=>`${[...Array(101).keys()]}`.replace(/^0,|\d?2.?,/g,'')

Try it online!

JavaScript (Node.js), 45 44 bytes

-1 byte thanks to Neil

for(i=0;i++<100;)/2/.test(i)||console.log(i)

Try it online!

Ruby, 33 bytes

Solution:

puts (?1..'100').reject{|x|x[?2]}

Haskell, 57 Bytes

Solution

import Data.List
unlines.nub.map(filter(/='2').show).$[1..100]

or

import Data.List
nub.map(filter(/='2').show)$[1..100]

if you just want the list.

Output

Prelude Data.List> unlines.nub.map(filter(/='2').show)$[1..]
"1\n\n3\n4\n5\n6\n7\n8\n9\n10\n11\n13\n14\n15\n16\n17\n18\n19\n0\n30\n31\n33\n34\n35\n36\n37\n38\n39\n40\n41\n43\n44\n45\n46\n47\n48\n49\n50\n51\n53\n54\n55\n56\n57\n58\n59\n60\n61\n63\n64\n65\n66\n67\n68\n69\n70\n71\n73\n74\n75\n76\n77\n78\n79\n80\n81\n83\n84\n85\n86\n87\n88\n89\n90\n91\n93\n94\n95\n96\n97\n98\n99\n100

Explanation

Makes all numbers a string, removes their '2's and weeds out the duplicates.

Tidy, 27 bytes

{{x:"2"!in x.0}from[1,100]}

Try it online!

Function which returns the appropriate range. x.0 concatenates x and 0 as a string.

Crystal, 65 bytes

(1..100).each do |x|
    x.to_s().includes?('2') ? 0 : puts x
end

Try it online!

[C# (.NET Core)], 63 62 bytes

Thanks to milk for saving one byte in the for loop.

for(int i=0;++i<101;)if(i%10!=2&&i/10!=2)Console.WriteLine(i);

Try it online!

Ungolfed:

for (int i = 0; ++i < 101;)         // all integers from 1-100 (starts from zero, increments before code runs)
    if (i % 10 != 2                 // all numbers not ending with '2'
                    && i / 10 != 2) // all numbers not starting with '2'
        Console.WriteLine(i);       // write to console

Japt, 7 bytes

Lõs kø2

Lõs kø2     Full Program
Lõs         Range ["1"..."100"] (numbers are casted to string)
    k       Remove
     ø2     anything that contains "2"

Try it online!

C (clang), 56 bytes

f(i){for(i=0;i++<100;i%10^2&&i/10^2&&printf("%d\n",i));}

Try it online!

LUA, 113 68 47 45 bytes

Thanks to LUA's rather loose dynamic typing, can straight-up search the integer.

Thanks to @manatwork (twice)

Thanks to @Jo King

for x=1,100 do n=("").find(x,2)or print(x)end

Try it online!

MathGolf, 7 6 bytes

♀╒Ç{2╧

Try it online!

Explanation

♀╒       Push 100 and convert to 1-based range ([1,2,...,100])
  Č{     Inverse filter by block
    2╧   Does the number contain 2?

Ohm v2, 7 9 bytes

⁸#u⁇2εX

Explanation:

⁸#u⁇2εX
⁸        Push 100
 #       Push range 0..a
  u      Turn to string (vectorizes)
   ⁇     Filter only those that match conditional
    2εX  Match those that do not contain "2"

Try it online!

Pyth, 17 bytes

VS100I!}\2%"%s"NN

Try it online

My first code golf submission, also my first time using Pyth, this took way longer to put together than I expected.

Explanation

VS100 for loop from 1 to 100

I!}\2%"%s if the string "2" is in the string conversion of N

%"%sN convert N to a string. This is the only way I could figure out how to do this. If there is a shorter way to do int -> string conversion please let me know. I'm honestly just looking for a way to call str() or repr() on it with less chars.

N print n

EDIT: Looks like someone else beat me to it with Pyth. Turns out to convert N to a str I could do `N`, I'm going to leave mine the same because if I change it its almost the exact same solution.

Rust, 65 bytes

fn main(){for i in 1..101{if i%10!=2&&i/10!=2{println!("{}",i)}}}

Try it online!

Similar to the answers by Meerkat and dumetrulo, just iterate through and print only those whose ones digit and tens digit are not 2.

V, 14 13 bytes

Saved 1 byte thanks to @oktupol

á199ñÄj<C-a>ñç2/d

Try it online! <C-A> represents the start of heading character (0x01)

Explanation

á1            Insert a 1 on the first line
99ñ           Repeat 99 times:
 Ä             Duplicate the last line
 j<C-A>        Increment the last line by one
ñç2/          For every line containing a 2:
 d             Remove the line

sh + coreutils, 16 chars

seq 100|sed /2/d

Generates sequence from 1 to 100 (inclusive) and deletes any lines that have '2' in them.

F#, 66 bytes

Solution

Seq.filter(fun i->i%10<>2&&i/10<>2){1..100}|>Seq.iter(printfn"%d")

Explanation

Filters a sequence of numbers 1 to 100 by retaining those whose modulus of 10 is not 2, and which integer-divided by 10 do not result in 2, then prints the sequence with newlines between items.

This works for numbers up to and including 199. A more general solution is slightly longer (74 bytes):

Seq.filter(fun i->(string i).IndexOf '2'<0){1..100}|>Seq.iter(printfn"%d")

With proper spacing, and rearranged for readability, this looks as follows:

{1 .. 100}
|> Seq.filter (fun i -> (string i).IndexOf '2' < 0)
|> Seq.iter (printfn "%d")

Ruby, 35 31 bytes

100.times{|e|p e if/2/!~e.to_s}

Try it online!

Thanks to Conor O'Brien for -4 bytes

APL(NARS), 17 chars, 34 bytes

a/⍨∼'2'∊¨⍕¨a←⍳100

test

  a/⍨∼'2'∊¨⍕¨a←⍳100
1 3 4 5 6 7 8 9 10 11 13 14 15 16 17 18 19 30 31 33 
  34 35 36 37 38 39 40 41 43 44 45 46 47 48 49 50 
  51 53 54 55 56 57 58 59 60 61 63 64 65 66 67 68 
  69 70 71 73 74 75 76 77 78 79 80 81 83 84 85 86 
  87 88 89 90 91 93 94 95 96 97 98 99 100

Ruby, 31 bytes

p$.if"#{$.+=1}"!~/2/ until$.>99

Try it online!

A different, iterative approach than other ruby answers. This uses the not-match operator !~ as well as the implicitly-zero input line number variable $. as the iterator. The TIO link shows my golfing progress, from 48 bytes to 31 bytes.

Attache, 24 bytes

Output!2&`!in@List\1:100

Try it online!

Alternatively, Print=>2&`!in@List\1:100.

Filters (\) from 1:100 values whose digits (@List) do not contain (`!in) a 2 (2&), which is then Outputted.

Retina, 19 17 bytes


100*
.
$.>`¶
A`2

Try it online! Edit: Saved 2 bytes thanks to @ovs, although the last line now includes a newline. Explanation:


100*

Insert 100 characters.

.
$.>`¶

Replace each character with the number of characters up to and including that character, plus a newline.

A`2

Remove all entries that contain a 2.

Perl 5 (5.12+), 25 bytes

$,=$/;say grep!/2/,1..100

Try it online!

Pretty straightforward. The $,=$/ makes the following print put a newline between list elements, which is shorter than using join.

T-SQL, 65 bytes

DECLARE @ INT=1a:IF @ NOT LIKE'%2%'PRINT @;SET @+=1IF @<101GOTO a

I'm a bit annoyed that this variable loop is shorter than the best set-based SQL variant I could find (91 bytes):

SELECT DISTINCT number FROM spt_values WHERE number>0and number<101AND number NOT LIKE'%2%'

This one even has the additional restriction of needing to be run in the master database (since it uses an undocumented system table).

The best set-based solution I could find without that requirement was 94 bytes:

WITH t AS(SELECT 1n UNION ALL SELECT n+1FROM t WHERE n<100)SELECT*FROM t WHERE n NOT LIKE'%2%'

MBASIC, 59 bytes

1 FOR I=1 TO 100:IF INSTR(STR$(I),"2")=0 THEN PRINT I
2 NEXT

There's probably a mathematical way to do this, but this approach is what first came to mind.

Jelly, 7 bytes

³D2eṆƲƇ

Try it online!

K4, 15 bytes

Solution:

1_&~"2"in'$!101

Example:

q)k)1_&~"2"in'$!101
1 3 4 5 6 7 8 9 10 11 13 14 15 16 17 18 19 30 31 33 34 35 36 37 38 39 40 41 43 44 45 46 47 48 49 50 51 53 54 55 56 57 58 59 60 61 63 64 65 66 67 68 69 70 71 73 74 75 76 77 78 79 80 81 83 84 85 86 87 88 89 90 91 93 94 95 96 97 98 99 100

Explanation:

1_&~"2"in'$!101 / the solution
           !101 / range 0..100
          $     / string
    "2"in'      / is "2" in each?
   ~            / not
  &             / indices where true
1_              / drop the first

Extra:

TIO for 16 byte K (oK) answer: Try it online!

PowerShell, 22 16 bytes

1..100-notmatch2

Try it online!

-6 bytes thanks to mazzy

Generates the range 1 to 100, then pulls out those objects where they do -notmatch the number 2. Running the -notmatch against an array like this acts like a filter on the array. Each item is left on the pipeline, and output is implicit.

Ruby, 28 characters

puts [*?1..'100'].grep_v /2/

Thanks to:

Sample run:

bash-4.4$ ruby -e 'puts [*?1.."100"].grep_v /2/' | head -15
1
3
4
5
6
7
8
9
10
11
13
14
15
16
17

Try it online!

SimpleTemplate, 51 bytes

This was a fun challenge! And it is a challenge where my language can do well.

{@forfrom 1to100}{@if_ is notmatches"<2>"}{@echol_}

Cycles through all values from 1 to 100, outputting the ones that don't have 2, separated by a newline.

You can try it on http://sandbox.onlinephpfunctions.com/code/2c97a2b6954c29844f1079938da771d51e2e0d99

Ungolfed:

{@for i from 1 to 100}
    {@if i is not matches "<2>"}
        {@echo i, "\n"}
    {@/}
{@/}

The {@/} is used to close the {@for ...} and {@if ...}, but is optional.
When compiling to PHP, it adds the needed closing.


If you're curious, the golfed code results in this PHP code:

// {@forfrom 1to100}
// ~ optimization enabled ~ inlining the results
foreach(array(...) as $DATA['_']){

    // {@if_ is notmatches"<2>"}
    if(!(preg_match("<2>", (isset($DATA['_'])?$DATA['_']:null)))) {

        // {@echol_}
        echo implode('', $FN['array_flat']((isset($DATA['_'])?$DATA['_']:null)));echo PHP_EOL;


// AUTO-CLOSE
};};

Where $FN['array_flat'] is defined outside of this code.

brainfuck, 176 bytes

---------[[-<]-[>]>[>]-[-<]<++]-[>-<+++++++++]>--[>[->]<[<<<]>>[->]>-]<<,<-[-<]>[>]<[.[->+<]++++++++++.,<]>>[>]>>->-<<<<[>>>[<<[<]<.>>[>]>.[-<+>]++++++++++.,>]<<[<]<,<]>>>>.<..

Try it online!

Shorter is definitely possible. This generates the numbers 1,3,4,5,6,7,8,9 and 0,1,3,4,5,6,7,8,9. First it outputs each number in the first list, then it outputs every combination of the first and second list, then finally prints just 100.

Explanation:

---------   Push minus 9
[           Repeat 9 times
  [-<]-[>]    Add the negative of the number to the first list
  >[>]-[-<]<  Add the negative of the number to the second list
  ++          Increment the counter
]
Tape: 255 254 253 252 251 250 249 248 247 0' 0 246 247 248 249 250 251 252 253 254
-[>-<+++++++++]>--  Push 197
Tape: 255 254 253 252 251 250 249 248 247 0 197' 246 247 248 249 250 251 252 253 254
[
  >[->]<    Subtract 197 from every element in both lists to convert to digits
  [<<<]>>
  [->]>-
]
Tape: 58 57 56 55 54 53 52 51 49 0' 49 50 51 52 53 54 55 56 57
<<,<-[-<]>[>]<  Remove the 0 and the 2 from the first list
Tape: 58 57 56 55 54 53 52 51 0 0 0' 49 50 51 52 53 54 55 56 57
[  Loop over the first list
  .[->+<]        Print digit
  ++++++++++.,<  Print a newline
]
>>[>]>>->-   Remove the 2 from the second list
<<<<      
[  Loop over first list
  >>>
  [  Loop over second list
    <<[<]<.        Print first digit
    >>[>]>.        Print second digit
    [-<+>]         Move second digit over one
    ++++++++++.,>  Print a newline
  ]
  <<[<]<,<  Remove the digit from the first list and move to the next
]
>>>>.<..  Print 100 using the second list

Gol><>, 19 bytes

`dFLP:aSD2=$2=+ZN|;

Try it online!

Explanation:

`dFLP:aSD2=$2=+ZN|;

`d                  //Push 100 to the stack
  F                 //For loop from 0 to 99
   LP               //  Push the loopcounter+1 to the stack,achieving a range [1..100]
     :              //  Double for potential output later (saves 1 byte compared to pushing it again)
      aSD           //  Push division & modulus of current number by 10
         2=         //  Check if (num % 10) == 2 , pushes either 0 or 1
           $2=      //  Check if (num / 10) == 2 , "
              +     //  Add the results acting as a logical or for is zero question
               ZN   //  If neither the mod nor the div are equal to 2 output the number
                 |; //Exit after loop

Whitespace, 121 bytes

[S S S N
_Push_0][N
S S N
_Create_Label_LOOP][S S S T N
_Push_1][T  S S S _Add][S N
S _Duplicate][S S S T   T   S S T   S T N
_Push_101][T    S S T   _Subtract][N
T   S S N
_If_0_Jump_to_Label_EXIT][S N
S _Duplicate][S S S T   S T S N
_Push_10][T S T T   _Modulo][S S S T    S N
_Push_2][T  S S T   _Subtract][N
T   S N
_If_0_Jump_to_Label_LOOP][S N
S _Duplicate][S S S T   S T S N
_Push_10][T S T S _Integer_divide][S S S T  S N
_Push_2][T  S S T   _Subtract][N
T   S N
_If_0_Jump_to_Label_LOOP][S N
S _Duplicate][T N
S T _Print_integer_to_STDOUT][S S S T   S T S N
_Push_10][T N
S S _Print_character_to_STDOUT][N
S N
N
_Jump_to_Label_LOOP]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Try it online (with raw spaces, tabs and new-lines only).

Pseudo-code:

Integer i = 0
Label LOOP:
  i = i+1
  If(i == 101):
    Exit program
  If(i modulo-10 == 2):
    Go to next iteration of LOOP
  If(i integer-divided by 10 == 2):
    Go to next iteration of LOOP
  Print i to STDOUT
  Print a newline to STDOUT
  Go to next iteration of LOOP

Bash + GNU utilities, 16

seq 100|sed /2/d

Try it online!

JavaScript (ES6), 51 bytes

After reading Arnauld's answer, I wanted to try a non-recursive approach. Sure enough, it's longer, but it may be of some interest.

_=>[...Array(101).keys()].filter(n=>n*!/2/.test(n))

Try it online!

[...Array(101).keys()] creates a list of the numbers 0 through 100. We then filter to get rid of 0 and any number that contains a 2.

ORK, 1092 bytes

There is such a thing as a t
A t can w a number
A t can d a number
A t has a t which is a number

When a t is to w a number:
I have a mathematician called M
M's first operand is the number
M's second operand is 1
M is to add
The number is M's result
My t is 0
I have a number called n
n is the number
I am to d n
M's first operand is my t
M's second operand is 1
M is to compare
I have a scribe called W
If M says it's less then W is to write the number
If M says it's less then W is to write " "
M's first operand is the number
M's second operand is 100
M is to compare
If M says it's less then I am to loop

When a t is to d a number:
I have a mathematician called M
M's first operand is the number
M's second operand is 10
M is to modulo
I have a mathematician called N
N's first operand is M's result
N's second operand is 2
N is to compare
If N says it's equal then my t is 1
M is to divide
The number is M's result
M's first operand is the number
M's second operand is 0
M is to compare
If M says it's greater then I am to loop

When this program starts:
I have a t called T
T is to w 0

Try it online!

Objects R Kool. Output is a space-delimited list of numbers.

This translates (approximately) to the following pseudocode:

class t {
	int t;
	
	void w(number) {
		label T_W;
		mathematician M;
		M.first_operand = number;
		M.second_operand = 1;
		M.add();
		number = M.result;
		t = 0;
		int n = number;
		d(n);
		M.first_operand = t;
		M.second_operand = 1;
		M.compare();
		scribe W;
		if M.its_less { W.write(number); }
		if M.its_less { W.write(" "); }
		M.first_operand = number;
		M.second_operand = 100;
		M.compare();
		if M.its_less { goto T_W; }
	}
	
	void d(number) {
		label T_D;
		mathematician M;
		M.first_operand = number;
		M.second_operand = 10;
		M.modulo();
		mathematician N;
		N.first_operand = M.result;
		N.second_operand = 2;
		N.compare();
		if N.its_equal { t = 1; }
		M.divide();
		number = M.result;
		M.first_operand = number;
		M.second_operand = 0;
		M.compare();
		if M.its_greater { goto T_D; }
	}
}

void main() {
	t T;
	T.w(0);
}

As you can see, everything is done using objects, including basic math and IO functions (through the built-in mathematician and scribe classes). Only whole functions can loop, which explains the need for an object with two functions to do the work.

Bash, 31 bytes

printf %d\\n {1..100}|grep -v 2

Try it online!

Thanks to Digital Trauma for short loop.

C (GCC), 62 55 Bytes

• 7 Bytes thanks to Jonathan Frech

f(n){for(n=0;++n-101;n/10-2&&n%10-2&&printf("%d,",n));}

Loops from 1 to 100 and prints the number only if 2 is not in the ones or tens place.

Try it online!

Haskell, 48 33 31 bytes

Thanks @JonathanFrech for fifteen bytes saved, and @xnor for another two! I missed a big golf and didn't realize main=print$ can be omitted.

filter(all(/='2').show)[1..100]

Try it online!

Easily extended by changing the 100. Stringifies all the numbers and keeps only those without a '2'.

Wolfram Language (Mathematica), 42 bytes

Print@⌈Range[1,100,10/9]~Drop~{18,26}⌉

Try it online!

The arithmetic sequence 1, 19/9, 29/9, 39/9, ... grows at just the right rate that taking the ceiling skips all the numbers ending in 2. Then we get rid of 20 through 29 by Dropping the values at indices 18 through 26.

Kotlin, 32 bytes

{(1..100).filter{'2' !in ""+it}}

Try it online!

Python 2, 39 bytes

k=7
exec"k+=10;print(k>177)*10+k/9;"*81

Try it online!

Uses arithmetic operations only to generate numbers without 2's.

The value k follows the arithmetic progression 17, 27, 37, 47, ..., which when floor-divided by 9 gives 1,3,4,5,6,7,8,9,10,11,13,14,... which counts up numbers not ending in 2. To skip 20 through 29, outputs are increased by 10 past a certain threshold.

Stax, 6 bytes

Ç░τ╒╜h

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

AJ  10 squared
f   output each value in [1 .. n] satisfying the following filter
 E  get array of decimal digits in number
 2#     count the number of 2s
 !  logical not

Run this one

R, 19 bytes

grep(2,1:100,inv=T)

Try it online!

JavaScript (ES6), 43 bytes

Returns the sequence as a comma-separated string.

f=(n=98)=>n?f(n-=n-27?n%10?1:2:11)+[,n+3]:1

Try it online!

Why doing it this way?

We could iterate from \$1\$ to \$100\$ and test each number with /2/.test(n), which is a rather concise statement. But in this scenario, we'd have to handle empty entries with something like (/2/.test(n)?'':...), which adds a couple more bytes.

For example, this would work for 45 bytes:

f=(n=1)=>n>99?n:(/2/.test(n)?'':[n,,])+f(n+1)

Or this would work for 44 bytes, if a leading comma is acceptable:

f=(n=100)=>n?f(n-1)+(/2/.test(n)?'':[,n]):''

All in all (and until proven otherwise), it turns out to be shorter to skip right away all values of \$n\$ that contain a \$2\$.

Commented

f =                 // f is a recursive function taking:
(n = 98) =>         // n = counter, initialized to 98
  n ?               // if n is not equal to 0:
    f(              //   prepend the result of a recursive call:
      n -=          //     update n:
        n - 27 ?    //       if n is not equal to 27:
          n % 10 ?  //         if n is not a multiple of 10:
            1       //           subtract 1 from n
          :         //         else:
            2       //           subtract 2 from n
        :           //       else (n = 27):
          11        //         subtract 11 from n (--> 16)
    ) +             //   end of recursive call
    [, n + 3]       //   append a comma, followed by n + 3; notice that this is the value
                    //   of n *after* it was updated for the recursive call; at the first
                    //   iteration, we have: n = 98 -> updated to 97 -> n + 3 = 100
  :                 // else (n = 0):
    1               //   output the first term '1' and stop recursion

Red, 44 bytes

repeat n 100[unless find form n"2"[print n]]

Try it online!

Uses unless instead of if not, because why not? :)

Perl 6, 22 bytes

put grep {!/2/},1..100

Try it online!

There's probably a better way to do the code block, but I couldn't find a regex adverb to invert the match

Java 10, 67 bytes

v->{for(int i=0;++i<101;)if(i%10!=2&i/10!=2)System.out.println(i);}

Try it online.

Explanation:

v->{                           // Method with empty unused parameter and no return-type
  for(int i=0;++i<101;)        //  Loop `i` in the range (0, 101)
    if(i%10!=2                 //   If `i` modulo-10 is not 2
       &i/10!=2)               //   And `i` integer-divided by 10 is not 2 either
      System.out.println(i);}  //    Print `i` with a trailing newline

05AB1E, 6 bytes

тLʒ2å_

Try it online!

Explanation

тL       # push [1 ... 100]
  ʒ      # filter, keep only elements that
   2å_   # does not contain 2

Python 2, 44 bytes

print[n for n in range(1,101)if'2'not in`n`]

Try it online!