# ASCII-Art Venn Diagram

Given two lists that contain no duplicate elements a and b, find the crossover between the two lists and output an ASCII-Art Venn Diagram. The Venn Diagram will use a squarified version of the traditional circles for simplicity.

# Example

Given:

a = [1, 11, 'Fox', 'Bear', 333, 'Bee']
b = ['1', 333, 'Bee', 'SchwiftyFive', 4]


Output (Order is 100% arbitrary, as long as the Venn Diagram is correct):

+-----+----+-------------+
|11   |333 |SchwiftyFive |
|Fox  |Bee |4            |
|Bear |1   |             |
+-----+----+-------------+


The program may either consider '1' == 1 or '1' != 1, up to your implementation. You may also choose to just handle everything as strings, and only accept string input.

Given:

a=[]
b=[1,2,3]


Output (Notice how the two empty parts still have the right-pad space):

+-+-+--+
| | |1 |
| | |2 |
| | |3 |
+-+-+--+


Given:

a=[1]
b=[1]


Output:

+-+--+-+
| |1 | |
+-+--+-+


# Rules

• Elements of the Venn Diagram are left-aligned and padded to the max length entry plus 1.
• The ordering of the elements within sub-sections of the Venn-Diagram are arbitrary.
• Corners of the Venn Diagram (where | meets -) must be represented by a +.
• You are garuanteed that a.join(b).length() > 0, if both are empty, you may do whatever.
• You may even print a picture of Abe Lincoln, don't care.
• This is , and .

# Bonus

Charcoal renders boxes like this naturally, but the whole set theory part... Don't know how well it does that. +100 bounty for the shortest charcoal submission before I am able to add a bounty to the question (2 days from being asked).

• Personally, I feel that being able to support '1' == 1 is a bit too much of a stretch – Kritixi Lithos May 11 '17 at 19:07
• @KritixiLithos fair enough, updated the challenge spec so that it doesn't hurt those who have started. It is now your choice on how you want string to integer comparison to work, both choices being equally valid submissions. – Magic Octopus Urn May 11 '17 at 19:09
• Can we assume that the input will only contain strings? – Rod May 11 '17 at 19:10
• Related. – Martin Ender May 11 '17 at 19:12
• @L3viathan one mobile edit and your post is over. – Magic Octopus Urn May 11 '17 at 22:13

# Python 2, 221210 212 bytes

m=map
A,B=m(set,input())
d=A-B,B&A,B-A
e=[max(m(len,s))+1for s in d]
p,i,n='+|\n'
o=b=p+p.join(m('-'.__mul__,e))+p+n
while sum(m(len,d)):o+=i+i.join(m(str.ljust,[len(s)and s.pop()or''for s in d],e))+i+n
print o+b


Try it online!

• Slightly wrong, you're missing the one space char right-pad. – Magic Octopus Urn May 11 '17 at 20:40
• @carusocomputing fixed – Rod May 11 '17 at 21:41

# PHP>=7.1, 287 Bytes

<?for([$a,$b]=$_GET,$x=max(($m=array_map)(count,$r=[($d=array_diff)($a,$b),array_intersect($a,$b),$d($b,$a)]));$n<3;$n++)for(sort($r[+$n]),$i=-1;$i<=$x;$i++){$o[$i].="|+"[$b=$i<0||$i==$x].str_pad($b?"":$r[+$n][$i],max($m(strlen,$r[+$n]))+1," -"[$b]).("|+"[$b][$n<2]);}echo join("
",$o);  Online Version Expanded for([$a,$b]=$_GET, # store input arrays in shorter variables
$x=max(($m=array_map)(count,   # get maximum of
$r=[($d=array_diff)($a,$b),array_intersect($a,$b),$d($b,$a)])); #the set array$n<3;$n++) for(sort($r[+$n]),$i=-1;$i<=$x;$i++){ # sort array to remove keys$o[$i].="|+"[$b=$i<0||$i==$x]. # concat line$b boolean for first and last line beginning char
str_pad($b?"":$r[+$n][$i]   # string of item in array if not first or last line
,max($m(strlen,$r[+$n]))+1 # fill till maximum length of items in array ," -"[$b]) # with char depends on first/last line or item line
.("|+"[$b][$n<2]); # make end of string if last array is reach
}
echo join("
",\$o); #Output


# Charcoal, 10689 87 bytes:

Ａ⟦⟧ςＡ⟦⟧λＡ⟦⟧ρＡ⟦⟧τＷＳ⊞ςιＷＳ⊞⎇№ςιτριＦς⊞⎇№τι⟦⟧λιＦ⟦λτρ⟧«Ｆι«↓Ｐκ»ＭＬι↑←Ａ⁺⌈ＥιＬκ³ζＵＲζ⁺⌈⟦ＬλＬτＬρ⟧²Ｍζ→


Try it online! Note that link is to verbose code for explanatory purposes, with the -sl option that shows the equivalent native Charcoal code. Takes input as newline-separated strings with a blank line after each set.

Edit: Saved 11 bytes thanks to @ASCII-only. Previous version actually had a bug when the last word in the first set was not in the second set and also the first column was the tallest, which manifested as an apparently inability to optimise away a temporary. Saved 2 bytes by optimising two Move commands (the deverbosifier now does this automatically but the resulting code was always valid so the answer is still competing).

Edit: I don't think Multiprint used to work with multiline output but it does currently and making use of that would save 6 bytes, plus a further 4 bytes because current Charcoal preinitialises the u variable to the empty list: Try it online!

• Oh, if you want to print without moving the cursor, use Multiprint (Ｐ) – ASCII-only May 11 '17 at 22:45
• Okay, 95 bytes, remember to remove commas/semicolons to remove delimiter in non-verbose form (will fix later), also Map exists (sorry, will document asap) – ASCII-only May 11 '17 at 23:29
• @ASCII-only Huh, well, I'm sure I tried Multiprint at some point, so I don't know why I wasn't able to get it to work. Also, thanks for Map, it helped me optimise the answer a bit more. Finally, I think Charcoal sometimes lets you use ← without an Ｍ which would save a byte here, or is that a bug? – Neil May 12 '17 at 0:10
• Directions without an Ｍ are intentional (but always remember a direction with a variable after is a directional print) – ASCII-only May 12 '17 at 0:14
• Okay, done, now all we need to do is wait for Dennis to pull for the better Move deverbosifying (it also now removes more unneeded separators so you'll be able to add the commas back in if you want) – ASCII-only May 12 '17 at 0:43