Someone has been hastily stacking the Christmas presents, and it's quite a mess:

           ========================
|                      |
========================
=============
|           |
|           |
|           |
|           |
|           |
|           |
=============
=======
|     |
|     |
|     |
=======
===================
|                 |
|                 |
|                 |
===================
=================
|               |
|               |
|               |
|               |
=================
=======
|     |
|     |
=======


Like, seriously, how does that top present even balance. It's probably a hammer. To prevent this tower of presents from crumbling, you're to reorder the presents so they stack nicely:

        =======
|     |
|     |
=======
=======
|     |
|     |
|     |
=======
=============
|           |
|           |
|           |
|           |
|           |
|           |
=============
=================
|               |
|               |
|               |
|               |
=================
===================
|                 |
|                 |
|                 |
===================
========================
|                      |
========================


## The Rules

• Each present consists of a top and bottom of = characters, and one or more middle rows, consisting of two | separated by spaces. The width of the present is the same in all its rows.
• There are no empty lines.
• Consecutive presents will overlap in at least one column.
• Presents are to be stacked in order of decreasing width. In the event of a tie, the taller present should go below the flatter present.
• Presents should be centred on the present beneath. If the present cannot be placed exactly in the centre (because the difference in widths is odd), you may choose either position that is half a character off the centre.
• You may or may not assume that the input has a single trailing newline, but please state your assumption.
• Your solution does not have to work for an empty input, but must be able to handle a single present.
• You may write a program or function, which takes input via STDIN or function argument and returns the result or prints it to STDOUT.
• This is code golf, so the shortest answer (in bytes) wins.

# CJam, 81 70 bytes

'"qN/{__Sm0=#>}%N*"=
="/"=\"\"="*'"++~]$_W='=/,f{1$'=/,m4/\N/\f{S*\N}}


So we have to stack the Christmas presents? This code does it like an actual person would do*.

First, we stack all the presents against a wall to easily move them up and down using this code:

'"qN/{__Sm0=#>}%N*


then, we identify each present as a separate item using this code:

"=
="/"=\"\"="*'"++~]


then, we sort the presents based on their heights and widths using this code:

 Till now, all the gifts have been stacked against a wall in order to have perfect alignment with each other. But as this is Christmas, we want to place the gifts aligned centered like a Christmas tree! This code does that: _W=Af{1Am4/\N/\f{S*\N}}


Here is a step by step output of the code for example in the question:

"Step 1 - Stack the presents against a wall";
========================
|                      |
========================
=============
|           |
|           |
|           |
|           |
|           |
|           |
=============
=======
|     |
|     |
|     |
=======
===================
|                 |
|                 |
|                 |
===================
=================
|               |
|               |
|               |
|               |
=================
=======
|     |
|     |
=======

"Step 2 - Identify the presents as a collection of presents";
["========================
|                      |
========================" "=============
|           |
|           |
|           |
|           |
|           |
|           |
=============" "=======
|     |
|     |
|     |
=======" "===================
|                 |
|                 |
|                 |
===================" "=================
|               |
|               |
|               |
|               |
=================" "=======
|     |
|     |
======="]

"Step 3 - Sort on height & width, with presents stacked against a wall to help sort them";
=======
|     |
|     |
=======
=======
|     |
|     |
|     |
=======
=============
|           |
|           |
|           |
|           |
|           |
|           |
=============
=================
|               |
|               |
|               |
|               |
=================
===================
|                 |
|                 |
|                 |
===================
========================
|                      |
========================

"Final step - stack them like a Christmas Tree";
=======
|     |
|     |
=======
=======
|     |
|     |
|     |
=======
=============
|           |
|           |
|           |
|           |
|           |
|           |
=============
=================
|               |
|               |
|               |
|               |
=================
===================
|                 |
|                 |
|                 |
===================
========================
|                      |
========================


Try it online here

* Might differ from person to person though :P

• That's awesome that the standard lexicographic order happens to fulfill the sorting requirements! Nice catch. – wchargin Dec 25 '14 at 0:59
• @WChargin yeah. Saved me a ton of bytes! – Optimizer Dec 25 '14 at 1:02

# Japt, 18 bytes

mx óÈíY b'=²Ãn c û


Try it online!

I use a sufficiently different strategy from the other Japt answer that I thought it was worth its own answer. Takes input and output as an array of lines

Explanation:

mx                    #Trim leading whitespace from each line
ó        Ã         #Split the array between lines where:
ÈíY               # The lines interleaved (e.g. "abc","def" => "adbecf")
b'=²          # starts with "=="
n        #Default sorting for "array of arrays of strings"
c      #Flatten to a single array of lines
û    #Pad each line so they are centered


I don't know precisely why "default sort" works like that, but I've tested that the taller box of the two with the same width is on the bottom regardless of which comes first in the input.

• Imagine that the shorter string gets right-padded with an imaginary character with code point -1 to the length of the longer one. – Erik the Outgolfer Dec 18 '18 at 17:12
• Replace "==" with '=² to save a byte. – Shaggy Dec 18 '18 at 17:22

# Ruby, 164

Neat challenge! Couldn't get it down much further.

f=->x{y=x.scan(/\s+=+[\s|]+\s+=+/).sort_by{|p|-p.count(?|)}.sort_by{|p|p.count ?=}
y.map{|p|p.gsub(/^\s+/,'').each_line{|l|puts l.strip.center(y[-1].count(?=)/2)}}}


### Explanation

The input String is chopped up into an Array where each present is an element. Then the array is sorted by the number of pipe characters and sorted again by the number of equal signs.

It then removes all leading whitespace and prints each line individually, centered by the width of the largest present.

It behaves the same with or without a trailing newline on the input.

f = lambda do |x|
y = x.scan(/\s+=+[\s|]+\s+=+/)
.sort_by { |p| -p.count("|") }
.sort_by { |p|  p.count("=") }

y.map do |p|
p.gsub(/^\s+/,'').each_line do |l|
puts l.strip.center(y.last.count("=") / 2 )
end
end
end


# 05AB1E, 23 20 bytes

|ðδÛ»…=
=…=0=:0¡{».c


-3 bytes thanks to @ErikTheOutgolfer.

Try it online.

Explanation:

|         # Take the input split by newlines
ðδÛ      # Remove leading spaces from each line
»     # And join everything back together again with a newline delimiter
…=
=         # Push string "=\n="
…=0=     # Push string "=0="
:    # Replace all "=\n=" with "=0="
0¡        # Now split on "0"
# (We now have our list of presents without any leading spaces)
{       # Sort this list (with default string-wise sorting)
»      # Join the list of presents by newlines
.c    # Left-focused centralize the string (and output implicitly)


Notes:

• Odd-width presents are left-focused centralized. This can be changed to right-focused by changing the trailing lowercase c to an uppercase C.
• The leading | can be dropped if we are allowed to take the input as a list of string-lines.
• Assumes the input contains no trailing spaces for any of the presents (similar as the input in the challenge description); trailing newlines are fine, since the | removes those anyway.
• 20 bytes. ðδÛ can be used instead of εðÛ} here, ¶'=.ø is the same as …=\n= (\n means newline), 0'=.ø is the same as …=0=. – Erik the Outgolfer Dec 18 '18 at 16:57
• @EriktheOutgolfer Ah, I'm an idiot for using .ø instead of the literal 3-char strings.. And thanks for ðδÛ. Actually never used δ before and had no idea it worked like that. – Kevin Cruijssen Dec 18 '18 at 17:18

# Attache, 91 bytes

Join&lf@{Center&#(_@-1@0)@>_}@{SortBy[&{#_'#__},Strip@>Lines=>Split[_,/"(?<==)\\s+(?==)"]]}


Try it online!

## Ungolfed

?? returns [length of first entry, number of entries]
revDim := &{#_'#__}

?? regex
SPLIT_ON_BARRIERS := /"(?<==)\\s+(?==)"

splitPresents[str] := (
chopped .= Split[str, SPLIT_ON_BARRIERS];;
normalized .= Strip @> Lines => chopped
)

orderPresents[presents] :=
SortBy[revDim, presents]

fixPresents[ordered] := (
?? number of columns of bottom-most present
?? center each line of each present
)

joinNewlines := Join&lf

stackPresents := joinNewlines@fixPresents@orderPresents@splitPresents


# Japt, 23 bytes

Very similar to Kevin's solution. I had a much shorter solution before spotting the tie-breaker for presents of the same width.

®x}R r"=
=""=l=" qÊn ·û


Try it

# Perl 5-n0, 123 bytes

sub k{pop=~y/=//}say s+^\s*+$"x((k($p[-1])- k$_)/4)+rmge for@p=sort{k($a)- k$b||$a=~y/|//-\$b=~y/|//}/\s*(=+[|
]+\s*\=+)/gs


Try it online!

# Python 2, 221 196 bytes

s,a,b,i=[c.strip()for c in input().split("\n")]+["="],[],[],0
exec"a+=[s[i].center(max(map(len,s)))]\nif s[i][0]==s[i+1][0]=='=':b+=[a];a=[]\ni+=1;"*(len(s)-1)
for c in sorted(b):print"\n".join(c)


Try it online!

Expects a quoted string without trailing newlines as input.

Not great, but it's the best I can do.