31

# 对课本进行排序

### 例子

`````` _
| |  _
|F| | |
|o|_|P|
|o|B|P|
| |a|C|
| |r|G|
|_|_|_|
``````

``````   _
| |_
|F| |
_|o|P|
|B|o|P|
|a| |C|
|r| |G|
|_|_|_|
``````

### 输出量

`````` _
| |
| |
|F|
|o|
|o|
| |
| |
|B|
|a|
|r|
| |
| |
|_|
``````

``````"Foo  Bar"
``````

# 获奖

The_Basset_Hound 2015年

@BassetHound不，目前没有，但不必担心支持2 ^ 64-1高的书本。我最多将5120设定为“高”，这是您的程序需要处理的而不会失败
Downgoat 2015年

The_Basset_Hound 2015年

@ETHproductions是的，书名将只包含字母和空格
Downgoat 2015年

1

coredump

5

# CJam，60个字节

``````qN/:Kz1>2%{_{" _"-}#>}\$_{_'_#>,}%2,\*2ew{:e>('|*K,Se[}%.\zN*
``````

7

# Python 3，231个字节

``````def f(s):
*M,L=sorted(["".join(c).strip()for c in zip(*s.split("\n"))][1::2],key=lambda x:x[1:-1].strip()),;l=m=0
for r in L+[""]:n=len(r);M+="|"*~-max(n,l),r;m=max(n,m);l=n
for r in zip(*[x.rjust(m)for x in M]):print(*r,sep="")
``````

## 不打高尔夫球

``````def f(s):
new_cols = []

# Zip columns, removing the spaces above each book
# [1::2] is to skip columns of |s, keeping only the books
books = ["".join(c).strip() for c in zip(*s.split("\n"))][1::2]

# Sort based on title, [1:-1] to remove the top and bottom _s
books.sort(key=lambda x:x[1:-1].strip())

last = 0
max_height = 0

for book in (books + [""]):
height = len(book)

# Append |s as necessary for the left edge of the current book
# The +[""] above is for the right edge of the last book
new_cols.extend(["|"*(max(height, last) - 1), book])

max_height = max(height, max_height)
last = height

# Rezip columns, add back spaces as necessary and print
for col in zip(*[x.rjust(max_height) for x in new_cols]):
print("".join(col))
``````

Pureferret

1
@Pureferret添加了带有注释的非公开版本
Sp3000

6

## 红宝石（209204200 198个字节）

``````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\$/
``````

`transpose`此解决方案中的功能要求所有行的长度均相同，因此需要在输入处填充空白。

### 说明

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

`ruby`需要哪个版本？对于问题输入的样本，在2.1.2中，我得到“'转置'：元素大小不同（6应该为2）（IndexError）”。
manatwork

@manatwork抱歉，我应该指定该功能需要一个由空格填充的矩形。我将更新答案。
Daniel Fone

1

manatwork

5

# Python 2-399字节

``````import sys;a=str.strip;L=list(sys.stdin);b=len(L[-1])/2;s=['']*b
for l in L:
i=0
for c in l[1:-1:2]:s[i]+=c;i+=1
s=sorted([a(a(x),'_')for x in s],key=a);y=map(len,s);m=[y[0]]+[max(y[i],y[i+1])for i in range(b-1)]
for i in range(max(y)+1):
h=max(y)-i;l='';j=0
for x in s:l+='|'if h<m[j]else' ';l+='_' if h==len(x)else' 'if h>len(x)else x[-h-1];j+=1
print l+('|'if h<y[-1]else' ')
print'|_'*b+'|'
``````

5

# CJam，75 66 65字节

``````qN/z(;2%{_{" _"#W=}#>}\$es:P;_W>+{_'_#_Pe<)S*2\$,'|*.e<@@:P;}%);zN*
``````

``````qN/     Read input and split at newlines.
z       Transpose to turn columns into lines.
(;      Drop first line...
2%      ... and every second line after that, to keep only lines with titles.
{       Start block that maps lines for sort.
_       Copy.
{       Start block for matching first title letter.
" _"#   Search for character in " _".
}#      End match block. This gets position of first character not in " _".
>       Trim leading spaces and '_.
}\$      End of sort block. Lines are now sorted alphabetically by title.
es:P;   Store large number in P. P holds previous position of '_ in following loop.
_W>+    Repeat last title line, so that final separator line is generated.
{       Loop over title lines.
_'_#    Find position of '_.
_       Copy position. Will store it in P after the minimum has been determined.
P       Get position of '_ in previous line.
e<)     Take the smaller of the two '_ positions, and decrement.
S*      Generate leading spaces from the count.
2\$,     Get length of title line.
'|*     Generate full line length sequence of '|.
.e<     Overlap spaces with '| to give the final separator.
@@      Get '_ position to top, and stack in order for next loop iteration.
:P;     Store '_ position in P.
}%      End of loop over lines.
);      Remove last line, which was a repeat.
z       Transpose to turn lines into columns again.
N*      Join with newline characters.
``````

1

# Scala 359341字节

``(s:String)=>{def f(s:String)=(" "/:s)((r,c)=>if(r.last=='|'||c=='_')r+"|"else r+" ").init;val h=s.lines.toSeq.transpose.collect{case s if s.exists(_.isLetter)=>s.mkString}.sortBy(_.filter(!_.isWhitespace));((Seq(f(h(0)))/:h.sliding(2))((s,l)=>s:+l(0):+f(l.minBy(_.indexOf('_')))):+h.last:+f(h.last)).transpose.map(_.mkString).mkString("\n")}``

``````//anonymous method that takes the books ascii-art string
(s: String) => {

//method to convert the middle to a border
def f(s: String) =
//fold (starting from non empty string since we use `.last`)
(" "/:s)((r,c) =>
if(r.last=='|'||c=='_')r+"|"
else r+" "
).init.tail

//h is a sequence of strings of the middle of the books
val h =
//transpose lines of input string, and take only the lines the contains letters (middle of the books)
s.lines.toSeq.transpose.collect{
case s if s.exists(_.isLetter) =>
s.mkString
}.sortBy(_.filter(!_.isWhitespace)) //sort the books by title (actually by "_\$title" since we filter out just whitspaces)

//fold over pairs of books and add the last manually
(
(Seq(f(h(0)))/:h.sliding(2))((s,l) =>
s :+ l(0) :+ f(l.minBy(_.indexOf('_'))) //convert higher book to border and append to folded accumulator
) :+ h.last :+ f(h.last) //add last book manually
).transpose.map(_.mkString).mkString("\n") //transpose back and construct the output string
}
``````
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.