7 gsub => tr

## Ruby (209204200200 198 bytes)

a=n.gsubtr(?|,' ').split$/ i=!p;t=a.map(&:chars).transpose.map(&:join).select{i^=a}.sort_by{|s|s[/[A-Z]/][0]} x=0;t.map{|t|y=0;u=p;t.chars{|c|u&&a[y][x,3]=?|*3;a[y][x+1]=c;y+=1;u|=c=='_'};x+=2} a.join$/

def sort_books(n)
a = n.gsubtr(?|,' ')  # pre-emptively remove all the '|'.
.split $/ # and split into an array of lines # ($/ is the INPUT_RECORD_SEPARATOR, typically "\n")
# we're going to write our answer into a later

i = !p # i = true; we'll use this as a flip-flop variable
# Kernel#p returns nil with no args

# we're now going to get a sorted array of book titles (t)
t = a.map(&:chars)  # break array into nested array of every character
.transpose     # and transpose the entire array
.map(&:join)   # this gives us an array of "horizontal" book titles with dividers

.select { i ^= a } # select every second line
# (i.e. just titles without dividers)
# i starts off true
# a is truish (it's our original array)
# ^= is the bitwise xor assignment,
#      it will alternate true/false on each execution

.sort_by { |s| s[/[A-Z]/][0] } # sort by the first alphabetical char

# use counters for less chars than each_with_index
# x and y are cartesian coordinates in the final array

x = 0 # start in the left-hand column

# go through each title
t.map { |t|
y = 0 # each book title starts on the top row

u = p # u is "have we reached the book's spine yet?" (or are we above it?)
# u starts off false and we'll set it true when we see the first '_'
# after which we'll start writing the book's edges

# go through each character of each title, including leading spaces and '_'s
# this will "descend" down the array writing each letter of the title
# along with the "edges"
t.chars { |c|

u &&                  # if we're on the spine
a[y][x,3] = ?|*3;   # write ||| in the next 3 columns
# the middle | will be overwriten by the title char

a[y][x+1] = c; # write the current title char into the second (x+1) column

y+=1; # descend to the next row

u |= c == '_' # Since '_' is the top and bottom of the book,
# this toggles whether we're on the spine
}
x += 2 # jump to the right 2 columns and start on the next title
}
a.join $/ # hopefully this is obvious end  ## Ruby (209204200 bytes) a=n.gsub(?|,' ').split$/
i=!p;t=a.map(&:chars).transpose.map(&:join).select{i^=a}.sort_by{|s|s[/[A-Z]/][0]}
x=0;t.map{|t|y=0;u=p;t.chars{|c|u&&a[y][x,3]=?|*3;a[y][x+1]=c;y+=1;u|=c=='_'};x+=2}
a.join$/  def sort_books(n) a = n.gsub(?|,' ') # pre-emptively remove all the '|'. .split$/         # and split into an array of lines
# ($/ is the INPUT_RECORD_SEPARATOR, typically "\n") # we're going to write our answer into a later i = !p # i = true; we'll use this as a flip-flop variable # Kernel#p returns nil with no args # we're now going to get a sorted array of book titles (t) t = a.map(&:chars) # break array into nested array of every character .transpose # and transpose the entire array .map(&:join) # this gives us an array of "horizontal" book titles with dividers .select { i ^= a } # select every second line # (i.e. just titles without dividers) # i starts off true # a is truish (it's our original array) # ^= is the bitwise xor assignment, # it will alternate true/false on each execution .sort_by { |s| s[/[A-Z]/][0] } # sort by the first alphabetical char # use counters for less chars than each_with_index # x and y are cartesian coordinates in the final array x = 0 # start in the left-hand column # go through each title t.map { |t| y = 0 # each book title starts on the top row u = p # u is "have we reached the book's spine yet?" (or are we above it?) # u starts off false and we'll set it true when we see the first '_' # after which we'll start writing the book's edges # go through each character of each title, including leading spaces and '_'s # this will "descend" down the array writing each letter of the title # along with the "edges" t.chars { |c| u && # if we're on the spine a[y][x,3] = ?|*3; # write ||| in the next 3 columns # the middle | will be overwriten by the title char a[y][x+1] = c; # write the current title char into the second (x+1) column y+=1; # descend to the next row u |= c == '_' # Since '_' is the top and bottom of the book, # this toggles whether we're on the spine } x += 2 # jump to the right 2 columns and start on the next title } a.join$/ # hopefully this is obvious
end


## Ruby (209204200 198 bytes)

a=n.tr(?|,' ').split$/ i=!p;t=a.map(&:chars).transpose.map(&:join).select{i^=a}.sort_by{|s|s[/[A-Z]/][0]} x=0;t.map{|t|y=0;u=p;t.chars{|c|u&&a[y][x,3]=?|*3;a[y][x+1]=c;y+=1;u|=c=='_'};x+=2} a.join$/

def sort_books(n)
a = n.tr(?|,' ')  # pre-emptively remove all the '|'.
.split $/ # and split into an array of lines # ($/ is the INPUT_RECORD_SEPARATOR, typically "\n")
# we're going to write our answer into a later

i = !p # i = true; we'll use this as a flip-flop variable
# Kernel#p returns nil with no args

# we're now going to get a sorted array of book titles (t)
t = a.map(&:chars)  # break array into nested array of every character
.transpose     # and transpose the entire array
.map(&:join)   # this gives us an array of "horizontal" book titles with dividers

.select { i ^= a } # select every second line
# (i.e. just titles without dividers)
# i starts off true
# a is truish (it's our original array)
# ^= is the bitwise xor assignment,
#      it will alternate true/false on each execution

.sort_by { |s| s[/[A-Z]/][0] } # sort by the first alphabetical char

# use counters for less chars than each_with_index
# x and y are cartesian coordinates in the final array

x = 0 # start in the left-hand column

# go through each title
t.map { |t|
y = 0 # each book title starts on the top row

u = p # u is "have we reached the book's spine yet?" (or are we above it?)
# u starts off false and we'll set it true when we see the first '_'
# after which we'll start writing the book's edges

# go through each character of each title, including leading spaces and '_'s
# this will "descend" down the array writing each letter of the title
# along with the "edges"
t.chars { |c|

u &&                  # if we're on the spine
a[y][x,3] = ?|*3;   # write ||| in the next 3 columns
# the middle | will be overwriten by the title char

a[y][x+1] = c; # write the current title char into the second (x+1) column

y+=1; # descend to the next row

u |= c == '_' # Since '_' is the top and bottom of the book,
# this toggles whether we're on the spine
}
x += 2 # jump to the right 2 columns and start on the next title
}
a.join $/ # hopefully this is obvious end  6 Fix comment regressions def sort_books(n) a = n.gsub(?|,' ') # pre-emptively remove all the '|'. .split$/         # and split into an array of lines
# ($/ is the INPUT_RECORD_SEPARATOR, typically "\n") # we're going to write our answer into a later i = !p # i = true; we'll use this isas a flip-flop variable # Kernel#p returns nil with no args # we're now going to get a sorted array of book titles (t) t = a.map(&:chars) # break array into nested array of every character .transpose # and transpose the entire array .map(&:join) # this gives us an array of "horizontal" book titles with dividers .select { i ^= a } # select every second line # (i.e. just titles without dividers) # i starts off true # a is truish (it's our original array) # ^= is the bitwise orxor assignment, # it will alternate true/false on each execution .sort_by { |s| s[/[A-Z]/][0] } # sort by the first alphabetical char # use counters for less chars than each_with_index # x and y are cartesian coordinates in the final array x = 0 # start in the left-hand column # go through each title t.map { |t| y = 0 # each book title starts on the top row u = p # u is "have we reached the book's spine yet?" (or are we above it?) # u starts off false and we'll set it true when we see the first '_' # after which we'll start writing the book's edges # go through each character of each title, including leading spaces and '_'s # this will "descend" down the array writing each letter of the title # along with the "edges" t.chars { |c| u && # if we're on the spine a[y][x,3] = ?|*3; # write ||| in the next 3 columns # the middle | will be overwriten by the title char a[y][x+1] = c; # write the current title char into the second (x+1) column y+=1; # descend to the next row u |= c == '_' # Since '_' is the top and bottom of the book, # this toggles whether we're on the spine } x += 2 # jump to the right 2 columns and start on the next title } a.join$/ # hopefully this is obvious
end

def sort_books(n)
a = n.gsub(?|,' ')  # pre-emptively remove all the '|'.
.split $/ # and split into an array of lines # ($/ is the INPUT_RECORD_SEPARATOR, typically "\n")
# we're going to write our answer into a later

i = !p # i = true; we'll use this is a flip-flop variable
# Kernel#p returns nil with no args

# we're now going to get a sorted array of book titles (t)
t = a.map(&:chars)  # break array into nested array of every character
.transpose     # and transpose the entire array
.map(&:join)   # this gives us an array of "horizontal" book titles with dividers

.select { i ^= a } # select every second line
# (i.e. just titles without dividers)
# i starts off true
# a is truish (it's our original array)
# ^= is the bitwise or assignment,
#      it will alternate true/false on each execution

.sort_by { |s| s[/[A-Z]/][0] } # sort by the first alphabetical char

# use counters for less chars than each_with_index
# x and y are cartesian coordinates in the final array

x = 0 # start in the left-hand column

# go through each title
t.map { |t|
y = 0 # each book title starts on the top row

u = p # u is "have we reached the book's spine yet?" (or are we above it?)
# u starts off false and we'll set it true when we see the first '_'
# after which we'll start writing the book's edges

# go through each character of each title, including leading spaces and '_'s
# this will "descend" down the array writing each letter of the title
# along with the "edges"
t.chars { |c|

u &&                  # if we're on the spine
a[y][x,3] = ?|*3;   # write ||| in the next 3 columns
# the middle | will be overwriten by the title char

a[y][x+1] = c; # write the current title char into the second (x+1) column

y+=1; # descend to the next row

u |= c == '_' # Since '_' is the top and bottom of the book,
# this toggles whether we're on the spine
}
x += 2 # jump to the right 2 columns and start on the next title
}
a.join $/ # hopefully this is obvious end  def sort_books(n) a = n.gsub(?|,' ') # pre-emptively remove all the '|'. .split$/         # and split into an array of lines
# ($/ is the INPUT_RECORD_SEPARATOR, typically "\n") # we're going to write our answer into a later i = !p # i = true; we'll use this as a flip-flop variable # Kernel#p returns nil with no args # we're now going to get a sorted array of book titles (t) t = a.map(&:chars) # break array into nested array of every character .transpose # and transpose the entire array .map(&:join) # this gives us an array of "horizontal" book titles with dividers .select { i ^= a } # select every second line # (i.e. just titles without dividers) # i starts off true # a is truish (it's our original array) # ^= is the bitwise xor assignment, # it will alternate true/false on each execution .sort_by { |s| s[/[A-Z]/][0] } # sort by the first alphabetical char # use counters for less chars than each_with_index # x and y are cartesian coordinates in the final array x = 0 # start in the left-hand column # go through each title t.map { |t| y = 0 # each book title starts on the top row u = p # u is "have we reached the book's spine yet?" (or are we above it?) # u starts off false and we'll set it true when we see the first '_' # after which we'll start writing the book's edges # go through each character of each title, including leading spaces and '_'s # this will "descend" down the array writing each letter of the title # along with the "edges" t.chars { |c| u && # if we're on the spine a[y][x,3] = ?|*3; # write ||| in the next 3 columns # the middle | will be overwriten by the title char a[y][x+1] = c; # write the current title char into the second (x+1) column y+=1; # descend to the next row u |= c == '_' # Since '_' is the top and bottom of the book, # this toggles whether we're on the spine } x += 2 # jump to the right 2 columns and start on the next title } a.join$/ # hopefully this is obvious
end

5 Updated char count

## Ruby (209204204 200 bytes)

a=n.gsub(?|,' ').split"\n"split$/ i=!p;t=a.map(&:chars).transpose.map(&:join).select{i^=a}.sort_by{|s|s[/[A-Z]/][0]} x=0;t.map{|t|y=0;u=p;t.chars{|c|u&&a[y][x,3]=?|*3;a[y][x+1]=c;y+=1;u|=c=='_'};x+=2} a.join"\n"join$/

def sort_books(n)
a = n.gsub(?|,' ')  # pre-emptively remove all the '|'.
.split"\n"split $/ # and split into an array of lines # ($/ is the INPUT_RECORD_SEPARATOR, typically "\n")
# we're going to write our answer into a later

i = !p # i = true; we'll use this asis a flip-flop variable
# Kernel#p returns nil with no args

# we're now going to get a sorted array of book titles (t)
t = a.map(&:chars)  # break array into nested array of every character
.transpose     # and transpose the entire array
.map(&:join)   # this gives us an array of "horizontal" book titles with dividers

.select { i ^= a } # select every second line
# (i.e. just titles without dividers)
# i starts off true
# a is truish (it's our original array)
# ^= is the bitwise xoror assignment,
#      it will alternate true/false on each execution

.sort_by { |s| s[/[A-Z]/][0] } # sort by the first alphabetical char

# use counters for less chars than each_with_index
# x and y are cartesian coordinates in the final array

x = 0 # start in the left-hand column

# go through each title
t.map { |t|
y = 0 # each book title starts on the top row

u = p # u is "have we reached the book's spine yet?" (or are we above it?)
# u starts off false and we'll set it true when we see the first '_'
# after which we'll start writing the book's edges

# go through each character of each title, including leading spaces and '_'s
# this will "descend" down the array writing each letter of the title
# along with the "edges"
t.chars { |c|

u &&                  # if we're on the spine
a[y][x,3] = ?|*3;   # write ||| in the next 3 columns
# the middle | will be overwriten by the title char

a[y][x+1] = c; # write the current title char into the second (x+1) column

y+=1; # descend to the next row

u |= c == '_' # Since '_' is the top and bottom of the book,
# this toggles whether we're on the spine
}
x += 2 # jump to the right 2 columns and start on the next title
}
a.join"\n"join $/ # hopefully this is obvious end  ## Ruby (209204 bytes) a=n.gsub(?|,' ').split"\n" i=!p;t=a.map(&:chars).transpose.map(&:join).select{i^=a}.sort_by{|s|s[/[A-Z]/][0]} x=0;t.map{|t|y=0;u=p;t.chars{|c|u&&a[y][x,3]=?|*3;a[y][x+1]=c;y+=1;u|=c=='_'};x+=2} a.join"\n"  def sort_books(n) a = n.gsub(?|,' ') # pre-emptively remove all the '|'. .split"\n" # and split into an array of lines # we're going to write our answer into a later i = !p # i = true; we'll use this as a flip-flop variable # Kernel#p returns nil with no args # we're now going to get a sorted array of book titles (t) t = a.map(&:chars) # break array into nested array of every character .transpose # and transpose the entire array .map(&:join) # this gives us an array of "horizontal" book titles with dividers .select { i ^= a } # select every second line # (i.e. just titles without dividers) # i starts off true # a is truish (it's our original array) # ^= is the bitwise xor assignment, # it will alternate true/false on each execution .sort_by { |s| s[/[A-Z]/][0] } # sort by the first alphabetical char # use counters for less chars than each_with_index # x and y are cartesian coordinates in the final array x = 0 # start in the left-hand column # go through each title t.map { |t| y = 0 # each book title starts on the top row u = p # u is "have we reached the book's spine yet?" (or are we above it?) # u starts off false and we'll set it true when we see the first '_' # after which we'll start writing the book's edges # go through each character of each title, including leading spaces and '_'s # this will "descend" down the array writing each letter of the title # along with the "edges" t.chars { |c| u && # if we're on the spine a[y][x,3] = ?|*3; # write ||| in the next 3 columns # the middle | will be overwriten by the title char a[y][x+1] = c; # write the current title char into the second (x+1) column y+=1; # descend to the next row u |= c == '_' # Since '_' is the top and bottom of the book, # this toggles whether we're on the spine } x += 2 # jump to the right 2 columns and start on the next title } a.join"\n" # hopefully this is obvious end  ## Ruby (209204 200 bytes) a=n.gsub(?|,' ').split$/
i=!p;t=a.map(&:chars).transpose.map(&:join).select{i^=a}.sort_by{|s|s[/[A-Z]/][0]}
x=0;t.map{|t|y=0;u=p;t.chars{|c|u&&a[y][x,3]=?|*3;a[y][x+1]=c;y+=1;u|=c=='_'};x+=2}
a.join$/  def sort_books(n) a = n.gsub(?|,' ') # pre-emptively remove all the '|'. .split$/         # and split into an array of lines
# ($/ is the INPUT_RECORD_SEPARATOR, typically "\n") # we're going to write our answer into a later i = !p # i = true; we'll use this is a flip-flop variable # Kernel#p returns nil with no args # we're now going to get a sorted array of book titles (t) t = a.map(&:chars) # break array into nested array of every character .transpose # and transpose the entire array .map(&:join) # this gives us an array of "horizontal" book titles with dividers .select { i ^= a } # select every second line # (i.e. just titles without dividers) # i starts off true # a is truish (it's our original array) # ^= is the bitwise or assignment, # it will alternate true/false on each execution .sort_by { |s| s[/[A-Z]/][0] } # sort by the first alphabetical char # use counters for less chars than each_with_index # x and y are cartesian coordinates in the final array x = 0 # start in the left-hand column # go through each title t.map { |t| y = 0 # each book title starts on the top row u = p # u is "have we reached the book's spine yet?" (or are we above it?) # u starts off false and we'll set it true when we see the first '_' # after which we'll start writing the book's edges # go through each character of each title, including leading spaces and '_'s # this will "descend" down the array writing each letter of the title # along with the "edges" t.chars { |c| u && # if we're on the spine a[y][x,3] = ?|*3; # write ||| in the next 3 columns # the middle | will be overwriten by the title char a[y][x+1] = c; # write the current title char into the second (x+1) column y+=1; # descend to the next row u |= c == '_' # Since '_' is the top and bottom of the book, # this toggles whether we're on the spine } x += 2 # jump to the right 2 columns and start on the next title } a.join$/ # hopefully this is obvious
end