g | x | w | all
Bytes Lang Time Link
098AWK241127T170820Zxrs
064Dyalog APL241111T211120ZAaron
232Rust241009T093635ZDornteuf
677JavaScript ES6 77 Bytes241010T145629ZThePlane
021Vyxal241010T101118Zemanresu
021Thunno 2 N230816T082108ZThe Thon
021Japt R201029T162100ZShaggy
nan230222T193934ZThe Thon
025Husk201029T163741ZRazetime
106R190504T100525ZRobin Ry
062Perl 5 MListUtil=pairmap n190503T222332ZXcali
094Python 2160108T224741Zxnor
194C++11160108T235700ZAlexande
02205AB1E190118T212858ZWisław
020Jelly190117T191356ZJonathan
034APL Dyalog171120T234154ZUriel
073Perl 6170110T212037ZSean
114Javascript ES6160303T191210ZCharlie
083Ruby 2.3160108T152226Zmanatwor
141Lua160130T203730ZQuertyKe
105Brachylog160108T125444ZFatalize
051Bash + common utils160108T051617ZDigital
146JavaScript ES6160112T193340ZMwr247
042Japt160110T224828ZETHprodu
202Haskell160111T152741ZCapello
106PowerShell160110T152750Zbeatcrac
117Python 3160110T221833Zchtenb
147Scala160110T115004ZNitin Ni
155Python 3160110T110459ZTim Pede
333Java160109T233630ZBrett C.
282C160108T152051Zx13
116JavaScript160108T093252Zedc65
343C#160108T155839ZGoose
188JavaScript ES6160108T033438ZConor O&
296C#160108T170147ZTimwi
110Python 2160108T102253ZTFeld
105Mathematica160108T114113ZLegionMa
169Lua160108T062905ZNikolai9
132Julia160108T033510ZAlex A.
027Pyth160108T033459ZMaltysen

AWK, 98 bytes

{i=1;for(x=2;j++<$1-1;a[x++]=i++)for(;i~4||i==13;i++);for(;--x;)print(a[x-1]?a[x-1]:-1)"\t"a[x--]}

Try it online!

{i=1;for(x=2;j++<$1-1;    # count j number floors
a[x++]=i++)               # increment array and floor
for(;i~4||i==13;i++);     # no 4s or 13
for(;--x;)                # start from the top
print(a[x-1]?a[x-1]:-1)   # catch 0 -> -1
"\t"a[x--]}               # more print

Dyalog APL, 64 chars

{⊖(⍵÷2)2⍴{⍺←¯1 1⋄⍵=≢⍺:⍺⋄(⍺,{~(⍵=13)∨('4'∊⍕⍵):⍵⋄∇⍵+1}1+¯1↑⍺)∇⍵}⍵}

Explanation, slightly separated for clarity:

next←{~(⍵=13)∨('4'∊⍕⍵):⍵⋄∇⍵+1}    Finds the next number recursively, not picking 13 or a number with a four in it
      ~                           Not
       (⍵=13)                         input is 13
             ∨                        or
              ('4'∊  )                there's a four
                   ⍕⍵                     in the text representation of the number
                      :⍵          in which case, return ⍵
                         ∇⍵+1     Otherwise, call recursively with the next number

{⊖(⍵÷2)2⍴{⍺←¯1 1⋄⍵=≢⍺:⍺⋄(⍺,next 1+¯1↑⍺)∇⍵}⍵}
         {                              }       Find the list of numbers
          ⍺←¯1 1                                Start with -1,1
                 ⍵=≢⍺:⍺                         If the length of ⍺ is equal to the input, return ⍺, we're done 
                                      ∇⍵        Otherwise, recursively call this with the same right input (the length)
                       (             )          and the growing ⍺:
                        ⍺,                          append to ⍺
                                 ¯1↑⍺               the tail of ⍺
                               1+                   plus 1
                          next                      fed to the `next` function
  (⍵÷2)2⍴                                       Reshape the list to the height of half of the input and a width of 2
 ⊖                                              and flip it over

Rust, 232 237 bytes

fn main(){let(n,mut v,mut c)=(std::io::stdin().lines().next().unwrap().unwrap().parse().unwrap(),vec![-1],1);while v.len()<n{if c!=13&&!c.to_string().contains('4'){v.insert(0,c)}c+=1}for i in v.chunks(2){print!("{}	{}
",i[1],i[0])}}

Attempt This Online!

-5 bytes thanks to ceilingcat

JavaScript (ES6): 113 97 77 Bytes

-20 by emanresu

f=(n,v=-2,x=_=>/^13$|4|^0/.test(++v)?x():v,c=`
${x()}  `+x())=>n?f(n-2,v)+c:[]

Try it online!

Explanation:

f=(  // recursive function f
    n, // with input n
  v=-2, // counter = -2;
  x=_=> // recursive count-up function
    /^13$|4|^0/.test(++v) // is it a valid number?
    ?
        x() // otherwise, continue counting
    :
        v,  // if so, return
  c=`\n${x()}   `+x() // current line
)=>
    n? // are we done yet?
    f(n-2,v)+c // no? add current line
  :
    [] // yes? return

OLD (97 bytes):

f=(n,i=!(v=-2),x=_=>{while(/^13$|4|^0/.test(++v));},c=`
`+(x(),v)+` `+(x(),v))=>i<n?f(n,i+2)+c:[]

Try it online!

Explanation:

f=( // recursive function f with input n
    n,
  i=!(v=-2), // i=0, v=-2 (works for multiple uses)
             // technically i=false but false==0 for math op
  x=_=>{ // counter function (from Charlie Wynn's answer)
    while(/^13$|4|^0/.test(++v));
  },
  c=`\n`+(x(),v)+`\t`+(x(),v) // current line (x(),v) is the next value
)=>
    i<n? // if we are still going
    f(n,i+2)+c // next line + current line
  :
    [] // otherwise stop

Vyxal, 21 bytes

13≠n4c¬∧)ȯṪup2ẇ9CvjṘ⁋

Try it Online!

         ȯ            # Find the first n integers
--------)             # where
13≠                   # They're not 13
       ∧              # And
   n4c¬               # They don't contain a 4
          Ṫup         # Remove the last and prepend -1
             2ẇ       # Get pairs
                 vj   # join each by
               9C     # chr(9) - tab
                   Ṙ⁋ # Reverse and join by newlines

Thunno 2 N, 21 bytes

ḌĖ⁻0o13oæṘ4Ƈ}ɱ2ẇr9Cȷj

Try it online!

Explanation

ḌĖ⁻0o13oæṘ4Ƈ}ɱ2ẇr9Cȷj  # Implicit input
ḌĖ⁻                    # Push the range [-1 .. 2*input)
   0o13o               # Remove the 0 and the 13
        æṘ4Ƈ}          # Remove anything containing 4
             ɱ         # Take the first (input) items
              2ẇ       # Split into pairs
                9Cȷj   # Join each by ASCII 9 (tab)
                       # Join on newlines
                       # Implicit output

Japt -R, 23 22 21 bytes

È©DÀX«ìø4}jUJ ò Ômq9d

Try it

È©DÀX«ìø4}jUJ ò Ômq9d     :Implicit input of integer U
È                         :Function taking an integer X as argument
 ©                        :  Logical AND with
  D                       :    13
   ÀX                     :    Is not equal to X
     «                    :  Logical AND with logical NOT of
      ì                   :    Convert X to digit array
       ø4                 :    Contains 4?
         }                :End function
          jU              :Get the first U integers that return truthy
            J             :Starting with -1
              ò           :Partitions of length 2
                Ô         :Reverse
                 m        :Map
                  q       :  Join with
                   9d     :  Character at codepoint 9 (TAB)
                          :Implicit output joined with newlines

Thunno N, \$36\log_{256}(96)\approx\$ 29.63 bytes

1ns2*:gzt13Q&s4Aq!&kDLz0-Zy2Apre9Csj

Attempt This Online!

Port of Wisław's 05AB1E answer.

Explanation

1n        # Push -1
  s2*     # Swap and double the input
     :    # Push the range between -1 and 2*n
      g   # Filter this list by:
       zt #  Triplicate the integer       STACK:  i, i, i
13Q       #  Is it not equal to 13?       STACK:  i, i, i != 13
   &      #  Logical AND                  STACK:  i, (i and i != 13)
    s4Aq  #  Swap and check if it         STACK:  (i and i != 13), (4 in i)
          #  contains the digit 4
        ! #  Logical NOT                  STACK:  (i and i != 13), (4 not in i)
&         #  Logical AND                  STACK:  i and (i != 13) and (4 not in i)
 k        # End filter
  DL      # Duplicate and push the length
    z0-   # Subtract the input
       Zy # Remove this many elements from the back
2Ap       # Split into chunks of length 2
   r      # Reverse
    e     # Map over this list:
     9C   #  Push chr(9), a tab
       sj #  Join the list by a tab
          # N flag joins by newlines
          # Implicit output

Husk, 25 bytes

↔mJc9†sC2↑¹fȯ¬€4d-0-13…_1

Try it online!

R, 106 bytes

n=scan();x=-1:n^2;x=x[-grep(4,x)][-14][-2][n:1];cat(paste0(matrix(x,2,n/2)[2:1,],c("	","\n"),collapse=""))

Try it online!

Explanation: it starts with the vector of floors from \$-1\$ to \$n^2\$, which is more than enough in all my tests. Should that ever be insufficient, we could switch to \$n^3\$ or \$n^9\$. It then removes the unlucky floor numbers (as well as floor 0), converts to a 2-row matrix form and inverts the rows to get the numbers in correct order, then outputs in the desired format, recycling the vector c("\t","\n"). As suggested by Conor O'Brien, use a literal tab instead of \t for -1 byte.

n=scan();                                        # read number of floors n
x=-1:n^2;                                        # initial vector of numbers
x=x[-grep(4,x)]                                  # remove floors with a 4
               [-14]                             # remove floor 13
                    [-2]                         # remove floor 0
                        [n:1];                   # keep lowest n remaining floors, highest to lowest
cat(paste0( 
  matrix(x,2,n/2)                                # split vector of floors into 2 rows
                 [2:1,],                         # take row 2 then row 1
                        c("   ","\n"),           # separate integers with alternating tabs and newlines (uses recycling)
                                    collapse=""))

Perl 5 -MList::Util=pairmap -n, 62 bytes

pairmap{say"$b	$a"}reverse((-1,grep!/^13$|4/,1..121)[0..$_-1])

Try it online!

Python 2, 94 bytes

n=input();c=-1;s=''
while n:
 if('4'in`c`)==0!=c!=13:n-=1;s=(n%2*'%d	%%d\n'+s)%c
 c+=1
print s

Try it online!

There's a tab character in the string that SE doesn't render (thanks to Sp3000 for suggested to use it, saving a byte).

Tests floors c starting from floor -1 until the quota n of floors is reached. For each floor, tests that it doesn't contain a 4 nor equals 0 or 13. If so, prepends it to the elevator string s and decrements the quota n.

A trick with string formatting is used to get the two floors per column to appear in the proper order when prepended. Each new line is prepared as '%d\t%%d\n', so that when two floors are substituted in order, the first is on the left and the second is on the right. For example,

('%d\t%%d\n'%2)%3 == ('2\t%d\n')%3 == '2\t3\n'  

C++11, 259 258 203 202 195 194 bytes

Slashed off 1 byte, thanks to Conor O'Brien's idea to use literal tab instead of \t.

UPD 2: slashed off 55 bytes with improved logic and comma abuse.

UPD 3: another byte off thanks to ceilingcat.

UPD 4: 7 bytes off courtesy of ceilingcat.

UPD 5: and another byte off by ceilingcat.

Happy to have all includes in place AND still beat the C and C# solutions.

#include<iostream>
#include<string>
int main(){std::string o="-1    1",c,b;int n,i=2,s=2;for(std::cin>>n;s<n;o=i==14|~c.find(52)?o:(++s&1?b=c,"":b+'    '+c+'\n')+o)c=std::to_string(i++);std::cout<<o;}

Ungolfed:

#include <iostream>
#include <string>

int main()
{
    std::string o = "-1 1", c, b;
    int n, i = 2, s = 2;
    for (std::cin >> n;
         s < n;
         o = i == 14 | ~c.find(52) ? o : (++s & 1 ? b = c, "" : b + '   ' + c + '\n') + o
    )
        c = std::to_string(i++);
    std::cout << o;
}

05AB1E, 25 23 22 bytes

-1 byte thanks to @ASCII-only

·Ý<0K13Kʒ4å_}s£2ôR9çý»

Try it online!

Explanation

                           # Implicit input: integer n
·Ý<                        # Push list [-1,0,1,...,2n-1]
   0K                      # Remove 0 from [-1,0,1,...,2n-1]
     13K                   # Remove 13 from [-1,1,...,2n-1]
        ʒ4å_}              # Filter out every number containing a 4 from the list
             s£            # Pick out the n first element in the list
               2ôR         # Splice list into parts of length 2
                  9çý      # Join with tab character (ascii value 9)
                     »     # Join with newlines

Jelly, 20 bytes

ḟ13D_4Ȧµ#o-s2Ṛj€9Ọ¤Y

Try it online!

How?

ḟ13D_4Ȧµ#o-s2Ṛj€9Ọ¤Y - Main Link: no arguments
        #            - start at n=0 and collect the first INPUT values which are truthy under:
       µ             -   the monad (i.e. f(n)):        e.g.:    0      3      4      13     42        813
ḟ13                  -     filter out thirteens                 [0]    [3]    [4]    []     [42]      [813]
   D                 -     convert to decimal lists             [[0]]  [[3]]  [[4]]  []     [[4,2]]   [[8,1,3]]
    _4               -     subtract four (vectorises)           [[-4]] [[-1]] [[0]]  []     [[0,-2]]  [[4,-3,-1]
      Ȧ              -     any & all?                           1      1      0      0      0         1
         o-          - logical OR with -1 (replace floor 0 with floor -1)
           s2        - split into twos
             Ṛ       - reverse
                  ¤  - nilad followed by link(s) as a nilad:
                9    -   literal nine
                 Ọ   -   to character (a tab)
              j€     - join €ach
                   Y - join with newlines
                     - implicit print

APL (Dyalog), 34 bytes

{⊖(⍵÷2)2⍴o/⍨~'4'∊¨⍕¨o←13~⍨¯1,⍳⍵×⍵}

Try it online!

Perl 6, 73 bytes

{.join("    ").say for (-1,|grep {$_-13&!/4/},1..Inf)[^$_].rotor(2).reverse}

Assumes an even number of floors, since the problem statement seems to assume it as well and at least one other provided solution breaks for odd numbers of floors. Just add ,:partial as a second argument to rotor, for nine more bytes, to support odd numbers of floors.

Javascript ES6 114 bytes

n=>[...Array(n)].map(_=>{while(/^13$|4|^0/.test(++i));return i;},i=-2).join`    `.match(/-?\d+  \d+/g).reverse().join`\n`

Usage

f=n=>[...Array(n)].map(_=>{while(/^13$|4|^0/.test(++i));return i;},i=-2).join`  `.match(/-?\d+  \d+/g).reverse().join`\n`

f(100);

Ruby 2.3, 84 83 characters

(82 characters code + 1 characters command line option)

puts (["-1",*?1..?1+$_].grep_v(/^13$|4/)[0..$_.to_i]*?\t).scan(/\S+\t\d+/).reverse

Sample run:

bash-4.3$ ruby -ne 'puts (["-1",*?1..?1+$_].grep_v(/^13$|4/)[0..$_.to_i]*?\t).scan(/\S+\t\d+/).reverse' <<< '14'
15      16
11      12
9       10
7       8
5       6
2       3
-1      1

Ruby, 93 92 characters

(91 characters code + 1 character command line option)

puts ([-1,*1..2*n=$_.to_i].reject{|i|i==13||i.to_s[?4]}[0..n]*?\t).scan(/\S+\t\d+/).reverse

Sample run:

bash-4.3$ ruby -ne 'puts ([-1,*1..2*n=$_.to_i].reject{|i|i==13||i.to_s[?4]}[0..n]*?\t).scan(/\S+\t\d+/).reverse' <<< '14'
15      16
11      12
9       10
7       8
5       6
2       3
-1      1

Lua, 141 bytes

n,s=1,'-1 1'function g()repeat n=n+1 until s.find(n,4)==z and n~=13 return n end for i=4,io.read(),2 do s=g()..' '..g().."\n"..s end print(s)

Ungolfed

n,s = 1,'-1'1' --n is the current floor number, S is the string to be printed
function g() --This function raises n to the next valid floor
    repeat --Same as while loop except it runs the following block before checking the expression
        n = n + 1 --Self-explanatory, increases n by one
    until --Checks the expression, if it is true, it breaks out of the loop
        s.find(n,4) == z --[[Strings have a member :find(X) where it finds the position of
                             X in the string (X can also be a pattern). However, calling it 
                             by .find(S,X) executes find on S with argument X. I can't 
                             directly do n:find(4) because n is a number. This is a "hack" 
                             (sort of) to cut down some bytes. Also, if X is not a string,
                             lua tries to (in this case, succeeds) cast X to a
                             string and then look for it. I check if this is equal to z
                             because z is nil (because it is undefined), and find returns
                             nil if X is not found in S.
                             TL;DR: Checks if 4 is not the last digit.]]
        and n ~= 13 --Self-explanatory, checks if n is not 13
        return n --Self-explanatory, returns n
end
for i = 4, io.read(), 2 do --[[Start at floor 3 (shows 4 because we're going by target
                               floor, not by starting floor), continue until we reach
                               floor io.read() (io.read returns user input), increment by
                               2 floors per iteration)]]
    s = g() .. ' ' .. g() .. "\n" .. s --[[Prepend the next floor, a space, the next floor,
                               and a newline to s]]
end
print(s) --Self-explanatory, output the string

Try it online (you need to click 'execute' on the top and then click the terminal on the bottom before typing input; I'm looking for a better way to test lua online with stdin and stdout)

Brachylog, 105 bytes

,Ll?,Lbb:1{h_.|[L:I]hhH,I+1=J((13;J:Zm4),L:J:1&.;Lb:J:1&:[J]c.)}:[1:-1]c{_|hJ,?bhw,[9:J]:"~c~w
"w,?bb:2&}

Would have been a lot shorter with CLPFD support, here I have to iteratively try integers in the first sub-predicate.

The new line before "w,?bb:2&} is mandatory, this is the new line that is printed between every row.

Bash + common utils, 51

seq 9$1|sed 13d\;/4/d\;1i-1|rs 0 2|sed $[$1/2]q|tac

JavaScript (ES6), 151 146

alert([for(a of Array((n=+prompt(i=0))*2).keys())if((i+=t=/4/.test(a)||a==13,!t&&a<n+i))a].reduce((a,b,j,r)=>j%2-1?(b||-1)+`  ${r[j+1]}
`+a:a,''))

Did this before I realized edc65 had already made a shorter one. Oh well!

Japt, 42 bytes

JoU*2 k0 kD f@!Xs f4} ¯U ã f@Yv} w ®q'    } ·

The four spaces should be an actual tab char. Try it online!

How it works

          // Implicit: U = input integer, D = 13
JoU*2     // Create the range of integers [-1,U*2).
k0 kD     // Remove 0 and 13.
f@!Xs f4} // Filter out the items X where X.toString().match(/4/g) is not null, i.e. the numbers that contain a 4.
¯U ã      // Slice to the first U items, and generate all adjacent pairs of items.
f@Yv}     // Filter out the items where the index Y is odd. This discards every other pair.
w         // Reverse.
®q'\t}    // Join each item with tabs.
·         // Join the whole list with newlines.
          // Implicit: output last expression

Haskell 202 bytes

t=(-1):[x|x<-[1..],x/=13,all (/='4')(show x)]
by2 []=[[]]
by2 [a]=[[a]]
by2 [a,b]=[[a,b]]
by2 (a:b:xs)=[a,b]:(by2 xs)
main=do
 n<-getLine
 putStr$unlines$map unwords$by2$map show$reverse$take(read n) t

I’am haskell beginner…

PowerShell, 106 107 bytes

$c=,-1+$(while($i+1-lt"$args"){if(++$c-notmatch'^13$|4'){$c;++$i}})
while($c){$a,$b,$c=$c;$s="$a    $b
$s"}$s

Ungolfed

# Calculate floors:
$c=,-1 # Array with one element
  +
  $( # Result of subexpression
    while($i+1-lt"$args"){ # Uninitialized $i is 0, +1 ensures loop start from 1
      if(
        ++$c-match'^13$|4' # Expression increments uninitialized $c (i.e. start from 1)
                           # and matches resulting number to regex.
      ){
        $c;++$i # Return $c and increment $i counter 
      }
    }
  )

# Print floors:
while($c){ # Loop until no more elements in $c
  $a,$b,$c=$c # Use PS's multiple assignment feature
              # $a - first element of $c array
              # $b - second element of $c array
              # $c - the rest of elements of $c array
  $s="$a    $b
$s" # Create string with tabs and newlines,
    # literal characters are used
}
$s # Output resulting string

Example

PS > .\Elevator.ps1 14
15  16
11  12
9   10
7   8
5   6
2   3
-1  1

Python 3, 117 Bytes

n=int(input())
l=[-1]+[i for i in range(n*2)if(i!=13)*(not'4'in str(i))][1:n]
while l:x=l.pop();print(l.pop(),'\t',x)

Modified version of the python 2 post to fit the python 3 specification.

Scala 147

val n=io.StdIn.readInt;(-1 to 4*n).filter(i=>i!=0&&i!=13&&(!(i+"").contains(52))).take(n).reverse.grouped(2).toList.map{i=>println(i(1)+"\t"+i(0))}

Python 3, 155 bytes

I think listifying, reversing, and self-zipping the floor-number generator s() may have been too clever for its own good, but others have already done the alternative (popping two items at a time), not to mention using Python 2 which saves bytes on some key points.

def s(m,n=-1):
 while m:
  if not(n in(0,13)or'4'in str(n)):yield n;m-=1
  n+=1
*f,=s(int(input()))
g=iter(f[::-1])
h=zip(g,g)
for a,b in h:print(b,'\t',a)

The shorter, but already-done-better alternative takes 140 bytes.

def s(m,n=-1):
 while m:
  if not(n in(0,13)or'4'in str(n)):yield n;m-=1
  n+=1
*f,=s(int(input()))
while f:a=f.pop();print(f.pop(),'\t',a)

Java, 333 Bytes

import java.util.*;interface E{static void main(String[]a){byte i=-1;Stack<Byte>s=new Stack<>();while(s.size()<Byte.valueOf(a[0])){if(i==13|i==0|String.valueOf(i).contains("4")){i++;continue;}s.add(i);i++;}if(s.size()%2!=0){System.out.println(s.pop());}while(!s.isEmpty()){int r=s.pop();int l=s.pop();System.out.println(l+"\t"+r);}}}

Adds allowed floor numbers to a stack then pops them back off to print them.

I played around using an IntStream, but with all the imports this one ended up being smaller.

C, 282 Bytes

int main(int r,char*v[]){int c=atoi(v[1]),a[c],b,E=1E9,g,i,t,o=t=g=(E)-2;while(i++<c){while(t>0){r=t%10;t=t/10;if(r==4||g==(E)+13||g<=o||g==E)t=++g;}a[i-1]=o=t=g;}for(c-=3;c>=0;c-=2){printf("%d\t",a[c+1]-E);printf("%d\n",a[c+2]-E);}printf("%d\t",a[0]-E);if(i%2)printf("%d",a[1]-E);}

Formatted :

int main ( int r , char * v[] ) {
    int c = atoi ( v[ 1 ] ) , a[c] , b , E = 1E9 , g , i , t , o = t = g = ( E ) - 2;
    while ( i ++ < c ) {
        while ( t > 0 ) {
            r = t % 10;
            t = t / 10;
            if ( r == 4 || g == ( E ) + 13 || g <= o || g == E )t = ++ g;
        }
        a[ i - 1 ] = o = t = g;
    }
    for ( c -= 3 ; c >= 0 ; c -= 2 ) {
        printf ( "%d\t" , a[ c + 1 ] - E );
        printf ( "%d\n" , a[ c + 2 ] - E );
    }
    printf ( "%d\t" , a[ 0 ] - E );
    if ( i % 2 )printf ( "%d" , a[ 1 ] - E );
}

Features :

It can compute up to 2095984 floors, if each floor is 19.5m high (incl. ceiling) then this building is long enough to be wrapped around the equator! 2095984*19.5=40871688m=~40000km=one 'lap' around the planet.

JavaScript, 116 122

Edit Saved 6 bytes thx @Neil

Simple array solution - not even using ES6

Try with any browser

/* test */ console.log=function(x){ O.innerHTML+=x+'\n'; }

n=prompt();for(r=[-1],v=1;n;v++)v!=13&!/4/.test(v)&&--n&&r.push(v);for(;r[0];)console.log(a=r.pop(b=r.pop())+'\t'+b)
<pre id=O></pre>

C#, 277 343

using System;using System.Collections.Generic;static void f(int v){List<int>a=new List<int>();List<int>b=new List<int>();int s=1;for(int i=-1;i<v-1;i++){if(i==13||i.ToString().Contains("4")||i==0){ v++;continue;}if(s==1){s=2;a.Add(i);}else{s=1;b.Add(i);}}a.Reverse();b.Reverse();int l=0;foreach(int y in a){Console.WriteLine(y+" "+b[l]);l++;}}

This is as a function only. I'm new to C#. Increase was to make valid for 40-49, and for including usings

Ungolfed, as a complete running program:

using System;
using System.Collections.Generic;

class P {
    static void Main()
    {
        List<int> a = new List<int>();
        List<int> b = new List<int>();
        int v = Int32.Parse(Console.ReadLine());
        int s = 1;
        for (int i = -1; i < v - 1; i++)
        {
            if (i == 13 || i.ToString().Contains("4") || i == 0)
            {
                v++;
                continue;
            }
            if (s == 1)
            {
                s = 2;
                a.Add(i);
            }
            else {
                s = 1;
                b.Add(i);
            }
        }
        a.Reverse();
        b.Reverse();
        int l = 0;
        foreach (int y in a)
        {
            Console.WriteLine(y + " " + b[l]);
            l++;
        }
        Console.ReadLine();
    }
}

Explained

I create two lists, and alternate between pushing to them, reverse them, loop through one, and grab the other by index.

JavaScript ES6, 236 234 233 210 195 188 bytes

Saved a whole bunch 'a bytes thanks to usandfriends!

Uses the function* for generators. Probably a shorter way to do this, but it was fun. Way fun. I'll bet some golfing can be done. Those weird whitespace things are tabs.

z=prompt(i=x=0,l=[]);y=(function*(){while(i<z-x)yield(i?(/4/.test(i)||i==13?--x&&".":i):-1)+(0*++i)})();while(a=y.next().value)+a&&l.push(a);l.join`    `.match(/-?\d+  \d+/g).reverse().join`
`

C#, 296 bytes

namespace System.Collections.Generic{using Linq;class X{static void Main(){var a=new List<int>();var b=new List<int>();for(int i=int.Parse(Console.ReadLine()),j=-2;i>0;)if(++j!=13&&j!=0&&!(j+"").Contains("4"))(i--%2<1?a:b).Insert(0,j);Console.Write(string.Join("\n",a.Zip(b,(x,y)=>x+"\t"+y)));}}}

Ungolfed:

namespace System.Collections.Generic
{
    using Linq;
    class X
    {
        static void Main()
        {
            var a = new List<int>();
            var b = new List<int>();
            for (int i = int.Parse(Console.ReadLine()), j = -2; i > 0;)
                if (++j != 13 && j != 0 && !(j + "").Contains("4"))
                    (i-- % 2 < 1 ? a : b).Insert(0, j);
            Console.Write(string.Join("\n", a.Zip(b, (x, y) => x + "\t" + y)));
        }
    }
}

Golfing tricks used:

It is unfortunate that the using Linq; is necessary, since it is needed only for .Zip, but writing it as Linq.Enumerable.Zip() is longer.

Python 2, 120 110 bytes

N=input()
n=['-1']+[`i`for i in range(N*2)if i!=13and'4'not in`i`][1:N]
while n:x=n.pop();print n.pop()+'\t'+x

Mathematica, 105 bytes

StringRiffle[Reverse[Select[Range[2#]-2,#!=13&&#!=0&&DigitCount[#,10,4]<1&][[;;#]]~Partition~2],"
","\t"]&

Replace the \t with an actual tab character.

Lua, 169 Bytes

t={-1}i=1 repeat if(i..""):find("4")or i==13 then else table.insert(t,i)end i=i+1 until #t==arg[1] for i=#t%2==0 and#t-1 or#t,1,-2 do print(t[i],t[i+1]and t[i+1]or"")end

Fairly straight forward, we first assemble a table filled with all the button values. Then we iterate through it backwards, printing two values at a time, or nothing if the second value does not exist.

Julia, 134 132 bytes

x=[-1;filter(i->i!=13&&'4'∉"$i",1:2(n=parse(readline())))][1:n]
for i=2:2:endof(x) println(join((r=reverse)(r(x)[i-1:i]),"  "))end

That funny whitespace in there is a literal tab. As Conor O'Brien noted, this is a byte shorter than doing \t.

Ungolfed:

# Read an integer from STDIN
n = parse(readline())

# Generate all numbers from 1 to 2n, exclude 0, 13, and all numbers containing 4,
# prepend -1, then take the first n
x = [-1; filter(i -> i != 13 && '4' ∉ "$i", 1:2n)][1:n]

# Loop over pairs, print tab-separated
for i = 2:2:endof(x)
    println(join(reverse(reverse(x)[i-1:i]), "  "))
end

Pyth, 27 bytes

jjLC9_c+_1.f&!@\4`ZnZ13tQ)2

Try it online here.

Gets .first Q-1 numbers that match the filter !=13 and 4 isn't in the string representation of the number. Then it prepends -1 , chops in half, joins each by tabs(C9) and joins by newlines.