루비 664671677 687701 (678 바이트)
_={│:[1,4],─:[2,8],┌:[4,8],┐:[4,2],└:[1,8],┘:[1,2],┼:[1,4,2,8]}
s=->a,l,b{l==[]&&a==[]?b:(l.product(l).any?{|q,r|q,r=q[0],r[0];(q[0]-r[0])**2+(q[1]-r[1])**2>a.size**2}?!0:(w,f=l.pop
w&&v=!a.size.times{|i|y=_[x=a[i]]
f&&y&[f]==[]||(k=l.select{|p,d|w!=p||y&[d]==[]}
(y-[f]).map{|d|z=[w[0]+(d<2?-1:(d&4)/4),w[1]+(d==2?-1:d>7?1:0)]
g=d<3?d*4:d/4
b[z]?_[b[z]]&[g]!=[]||v=0:k<<[z,g]}
v||r=s[a[0...i]+a[i+1..-1],k,b.merge({w=>x})]
return r if r)}))}
c=eval"[#{gets}]"
r=s[6.downto(0).map{|i|[_.keys[i]]*c[i]}.flatten,[[[0,0],nil]],{}]
h=j=k=l=0
r.map{|w,_|y,x=w
h>x&&h=x
j>y&&j=y
k<x&&k=x
l<y&&l=y}
s=(j..l).map{|_|' '*(k-h+1)}
r.map{|w,p|y,x=w
s[y-j][x-h]=p.to_s}
puts s
이것은 내가 얻을 수있는 가장 짧은 프로그램은 아니지만 실행 속도에 대한 간결함을 희생했습니다.
여기서 프로그램을 실험 해 볼 수 있습니다 . ideone의 실행 시간 제한이 있으므로 약 12 개 이상의 입력으로 구성된 입력의 경우 프로그램이 시간 초과 될 수 있습니다.
프로그램을위한 테스트 스위트 도 있습니다 . 위에서 언급 한 시간 제한으로 인해 마지막 두 테스트는 IDE에서 비활성화됩니다. 이러한 테스트를 활성화하려면 x_
해당 이름 에서 접두사를 삭제하십시오 .
프로그램은 깊이 우선 검색을 사용하여 솔루션을 찾습니다. 한 번에 하나씩 조각을 배치하고 느슨한 끝을 추적합니다. 더 이상 느슨한 (연결되지 않은) 끝이없고 모든 부품이 배치되면 검색이 중지됩니다.
이것은 ungolfed 프로그램입니다 :
N, W, S, E = 1, 2, 4, 8
# given a direction, find the opposite
def opposite (dir)
dir < 3 ? dir * 4 : dir / 4
end
# given a set of coordinates and a direction,
# find the neighbor cell in that direction
def goto(from, dir)
y, x = from
dx = case dir
when W then -1
when E then 1
else 0
end
dy = case dir
when N then -1
when S then 1
else 0
end
[y+dy, x+dx]
end
CONNECTIONS = {
?│ => [N, S],
?─ => [W, E],
?┌ => [S, E],
?┐ => [S, W],
?└ => [N, E],
?┘ => [N, W],
?┼ => [N, S, W, E],
}
BuildTrack =-> {
piece_types = CONNECTIONS.keys
piece_counts = gets.split(?,).map &:to_i
pieces = 6.downto(0).map{|i|piece_types[i]*piece_counts[i]}.join.chars
def solve (available_pieces, loose_ends=[[[0,0],nil]], board={})
return board if loose_ends==[] and available_pieces==[]
# optimization to avoid pursuing expensive paths
# which cannot yield a result.
# This prunes about 90% of the search space
c = loose_ends.map{ |c, _| c }
not_enough_pieces = c.product(c).any? { |q, r|
((q[0]-r[0])**2+(q[1]-r[1])**2) > available_pieces.size**2
}
return if not_enough_pieces
position, connect_from = loose_ends.pop
return unless position
available_pieces.size.times do |i|
piece = available_pieces[i]
remaining_pieces = available_pieces[0...i] + available_pieces[i+1..-1]
piece_not_connected_ok = connect_from && CONNECTIONS[piece] & [connect_from] == []
next if piece_not_connected_ok
new_loose_ends = loose_ends.select { |pos, dir|
# remove loose ends that may have been
# fixed, now that we placed this piece
position != pos || CONNECTIONS[piece] & [dir] == []
}
invalid_placement = false
(CONNECTIONS[piece]-[connect_from]).map do |dir|
new_pos = goto(position, dir)
new_dir = opposite(dir)
if board[new_pos]
if CONNECTIONS[board[new_pos]] & [new_dir] != []
# do nothing; already connected
else
# going towards an existing piece
# which has no suitable connection
invalid_placement = true
end
else
new_loose_ends << [new_pos, new_dir]
end
end
next if invalid_placement
new_board = board.merge({position => piece})
result = solve(remaining_pieces, new_loose_ends, new_board)
return result if result
end
nil
end
def print_board board
min_x = min_y = max_x = max_y = 0
board.each do |position, _|
y, x = position
min_x = [min_x, x].min
min_y = [min_y, y].min
max_x = [max_x, x].max
max_y = [max_y, y].max
end
str = (min_y..max_y).map{|_|
' ' * (max_x - min_x + 1)
}
board.each do |position, piece|
y, x = position
str[y-min_y][x-min_x] = piece
end
puts str
end
print_board(solve(pieces))
}