# Draw a Random ASCII Art Quilt

For this challenge, an ASCII art quilt will be a block of text 24 characters wide and 18 lines tall, containing the characters =-<>/\ in a quilt-like pattern that is horizontally and vertically symmetrical.

Example quilt:

========================
------------------------
//\\//\\\//\/\\///\\//\\
<<><<>>>>><<>><<<<<>><>>
/\\/\\\\/\/\/\/\////\//\
------------------------
/\/////\\///\\\//\\\\\/\
\///\/\/\\\\////\/\/\\\/
\///\/\/\\\\////\/\/\\\/
/\\\/\/\////\\\\/\/\///\
/\\\/\/\////\\\\/\/\///\
\/\\\\\//\\\///\\/////\/
------------------------
\//\////\/\/\/\/\\\\/\\/
<<><<>>>>><<>><<<<<>><>>
\\//\\///\\/\//\\\//\\//
------------------------
========================


All quilts have the same form:

• They are always 24 by 18.
• The top line (line 1) and bottom line (line 18) are = all the way across.
• Lines 2, 6, 13 and 17 are - all the way across.
• Lines 4 and 15 are the same random horizontally symmetric pattern of < and >.
• All other lines (3, 5, 7, 8, 9, 10, 11, 12, 14, 16) are filled with / and \ in a completely random way such that the entire quilt remains horizontally and vertically symmetric.

Notice that when folding the quilt exactly in half, either vertically or horizontally, the shapes of the characters exactly match up. Don't get this confused with the characters themselves matching up. e.g. line 3 and line 16 are not identical, they are vertical mirror images.

# Challenge

Write a program or function that will print or return a random ASCII art quilt.

Due to the many hardcoded lines and the symmetry, the only real randomness comes from the first 12 characters on lines 3, 4, 5, 7, 8, 9:

• The first 12 characters on line 4 should be able to be any length 12 string of the characters < and >.
• The first 12 characters on lines 3, 5, 7, 8, 9 should be able to be any length 12 string of the characters / and \ (independent of each other).
• These random strings are then mirrored accordingly to make the entire quilt.

The shortest answer in bytes wins. Tiebreaker is earlier post.

You may use pseudorandom number generators. (No, you don't need to prove that all 12 char string of <> or /\ can be generated with you language's PRNG.)

The output may optionally contain a trailing newline, but no trailing spaces or other characters besides what's necessary for the quilt.

• can we take input as a random seed? Jan 18, 2017 at 0:10

# CJam, 616058555452 51 bytes

Shortened a bit with some help from Sp3000 and Optimizer.

"=-/</-///"{C*1{"<\/>"%1$W%\_W%er}:F~+mrC<1FN}%s3F(  Test it here. ## Explanation As usual with these symmetric ASCII art challenges, I'm generating one quadrant and then expand it to the full thing by two appropriate mirroring operations. For this explanation I should start with the function F, which I'm defining somewhere along the way, because it's used in three places for three different things: {"<\/>"%1$W%\_W%er}:F


This expects an integer on the top of the stack, and a string beneath that. Its purpose is to reverse the string and also swap some characters, to get the mirroring right. The integer is either 1 or 3 and indicates whether (1) both brackets and slashes should be swapped or (3) only brackets should be swapped. Here is how it works:

"<\/>"            "Push a string with all four relevant characters.";
%           "% applied to a string and an integer N (in any order) selects every
Nth character, starting from the first. So with N = 1 this just
leaves the string unchanged, but with N = 3 it returns a string
containing only < and >.";
1$"Copy the string we want to mirror."; W% "% also takes negative arguments. Giving it -1 reverses the string."; \_ "Swap the two strings and duplicate the <\/> or <> string."; W% "Reverse that one. Due to the symmetry of this string, we'll now have the characters to be swapped at corresponding indices."; er "Perform element-wise transliteration on the reversed input string to complete the mirroring operation.";  Now for the rest of the code: "=-/</-///" "This string encodes the 9 different line types. Note that for the /\ and <> lines we only use one of the characters. This idea is due to Sp3000. Thanks! :)"; { }% "Map this block onto the characters."; C* "Repeat the character 12 times, turning it into a string."; 1{...}:F~ "Define and call F on the resulting string. The reversal doesn't do anything, but the character swapping creates strings containing both \/ and <>."; +mr "Add the two halves together and shuffle them."; C< "Truncate to 12 characters. We've now got our random half-lines."; 1F "Call F again to mirror the half-line."; N "Push a newline."; s "Join all those separate strings together by converting the array to a string."; 3F "Perform one more mirroring operation on the half-quilt, but this time only swap < and >. This yields the correct full quilt, except there are two newlines in the centre."; ( "This slices the leading newline off the second half and pushes it onto the stack.";  The two halves and that single newline are then printed automatically at the end of the program. # Python 3, 257229192185176149 143 bytes from random import* k,*L=80703, while k:s=eval("''"+".join(sample('--==<>\/'[k%4*2:][:2],2))"*12);L=[s]+L+[s[::(-1)**k]];k//=4 *_,=map(print,L)  With help from @xnor, we've finally caught up with JS! Sample output: ======================== ------------------------ ///////////\/\\\\\\\\\\\ >><<<>><<<><><>>><<>>><< /\/\\/\/\\/\/\//\/\//\/\ ------------------------ //\\////\\/\/\//\\\\//\\ /////\\\/\/\/\/\///\\\\\ /\\//\\/////\\\\\//\\//\ \//\\//\\\\\/////\\//\\/ \\\\\///\/\/\/\/\\\///// \\//\\\\//\/\/\\////\\// ------------------------ \/\//\/\//\/\/\\/\/\\/\/ >><<<>><<<><><>>><<>>><< \\\\\\\\\\\/\/////////// ------------------------ ========================  ## Explanation (Slightly outdated, will update later) "444046402" encodes the rows, with each digit referring to the starting index of the relevant 2-char substring of '--==\/<>'. Each individual row is built inside-out via repeated shuffling of the two chars (using sample(...,2), since random.shuffle is unfortunately in-place) and string joining. A simplified example of what the expansion might look like for the fourth row is: ''.join(['<','>']).join(['>','<']).join(['>','<']).join(['<','>']).join(['>','<'])  which would yield ><>><><<><:  '' <> .join(['<','>']) > < .join(['>','<']) > < .join(['>','<']) < > .join(['<','>']) > < .join(['>','<'])  The overall quilt is also built inside-out, as construction begins with the 9th/10th rows, working outward. To do this we start with an empty list L, which we add rows to the front and back of as we go via L=[s]+L+[[s,s[::-1]][n<"5"]]  The n<"5" condition is to check whether we have a row consisting of ><, in which case we append an identical row to the back, otherwise its reverse. Finally, *_,= is to force the evaluation of map so printing occurs, and is just a shorter way to do print("\n".join(L)). For a long time I had the function g=lambda s:s.translate({60:62,62:60,92:47,47:92})  which takes a string and converts /\>< to \/<> respectively, but I've finally managed to get rid of it :) • The spec says as long as it can generate all the possible carpets, it's fine. – user34736 Apr 17, 2015 at 14:36 # Python 2, 300 bytes This program uses join, lambda, replace, sample, import and other verbose functions, so it will not be winning any golf awards. from random import* f=lambda a,b,t:t.replace(a,'*').replace(b,a).replace('*',b) k=lambda a:''.join(sample(a*12,12)) c='-'*24 e=k('<>') h=e+f('<','>',e[::-1]) j=[d+f('/','\\',d[::-1])for d in[k('\\/')for i in'quilt']] g=['='*24,c,j,h,j,c]+j[2:] print'\n'.join(g+[f('/','\\',d)for d in g[::-1]])  The code before the auto-golfer got hold of it: from random import * change = lambda a,b,t: t.replace(a,'*').replace(b,a).replace('*',b) pick = lambda a: ''.join(sample(a*12, 12)) innerline = '-' * 24 line4h = pick('<>') line4 = line4h + change('<', '>', line4h[::-1]) diag = [d + change('/', '\\', d[::-1]) for d in [pick('\\/') for i in 'quilt']] quilt = ['='*24, innerline, diag, line4, diag, innerline] + diag[2:] print '\n'.join(quilt + [change('/', '\\', d) for d in quilt[::-1]])  A sample output: ======================== ------------------------ \\\\/\////\\//\\\\/\//// <><<>>>><><><><><<<<>><> /\\\\////\\\///\\\\////\ ------------------------ \\\\//\///\\//\\\/\\//// //\//\\\\/\/\/\////\\/\\ \/\\\\/\//\/\/\\/\////\/ /\////\/\\/\/\//\/\\\\/\ \\/\\////\/\/\/\\\\//\// ////\\/\\\//\\///\//\\\\ ------------------------ \////\\\\///\\\////\\\\/ <><<>>>><><><><><<<<>><> ////\/\\\\//\\////\/\\\\ ------------------------ ========================  • Not the shortest, but hey, with 7 more bytes you've got a program worthy of your name :D Apr 17, 2015 at 8:00 • I see what you did there. Apr 17, 2015 at 9:24 • Auto-golfer? Aint nobody got time for golfing by hand? Apr 17, 2015 at 12:11 • You know us hackers. If I have to do a 3 minute task more than once, I will spend 10 hours writing a program to automate it. I am all about efficiency ;-) Apr 18, 2015 at 3:01 # APL (53 58) It's not quite as symmetrical as I thought it was, unfortunately. Fix cost me 5 characters and now I'm out of the running. L←+,3-⌽⋄'==--/\<><'[↑(732451451260688⊤⍨18/8)+L{L?12⍴2}¨⍳9]  Explanation: • L←+,3-⌽: L is a function that returns its argument followed by 3 - the reverse of its argument • L{L?12⍴2}¨⍳9: generate 9 lines of 12 random values from [1,2] plus their reverse, then the reverse of those 9 lines • 732451451260688⊤⍨18/8: generate the list 0 2 4 6 4 2 4 4 4 4 4 4 2 4 _7_ 4 2 0 (that's where the damn asymmetricality is) • +: for each line, add the corresponding number to each value • ↑: format as matrix • '==--/\<><'[...]: for each of the numbers in the matrix, select the character from the string at that position Output: ======================== ------------------------ ///////\\///\\\//\\\\\\\ <<><<><><<<<>>>><><>><>> \\\\\//\/\\\///\/\\///// ------------------------ /\///\\/\/\/\/\/\//\\\/\ \////////\//\\/\\\\\\\\/ \\/\\\//\///\\\/\\///\// //\///\\/\\\///\//\\\/\\ /\\\\\\\\/\\//\////////\ \/\\\//\/\/\/\/\/\\///\/ ------------------------ /////\\/\///\\\/\//\\\\\ <<><<><><<<<>>>><><>><>> \\\\\\\//\\\///\\/////// ------------------------ ========================  • I had +1ed because the algorithm you posted was interesting and original, but I've just noticed that your <> lines are not vertically symmetrical as you use your swap table when making the vertical mirror as well. (Thanks for posting the output btw, makes figuring out if APL works much easier ;p ) Apr 17, 2015 at 23:15 • @FryAmTheEggman: shit, didn't notice that. I'll probably have to scrap the whole algorithm now, since there's one line that's not like the others. Well, thanks for telling me rather than just downvoting. Apr 17, 2015 at 23:23 • @FryAmTheEggman: well, it's fixed (by adding another < to the end of the string, and incrementing the second line once more, thereby swapping it twice). Didn't even have to scrap the whole thing, though it won't win anymore now. (Perhaps next time I should't post the output :P) Apr 17, 2015 at 23:37 • That solution is quite clever, you can keep the +1 :) Apr 18, 2015 at 1:22 • @Calvin'sHobbies: fix one thing, break another. Now it's really fixed. Apr 18, 2015 at 3:10 # PHP, 408, 407, 402, 387, 379 bytes I am not a good golfer, but this problem sounded fun so I gave it a try. <?$a=str_replace;$b=str_repeat;function a($l,$a,$b){while(strlen($s)<$l){$s.=rand(0,1)?$a:$b;}return$s;}$c=[$b('=',12),$b('-',12),a(12,'/','\\'),a(12,'<','>'),a(12,'/','\\'),$b('-',12)];while(count($c)<9){$c[]=a(12,'/','\\');}for($d=9;$d--;){$c[$d].=strrev($a(['/','<','\\','>',1,2],[1,2,'/','<','\\','>'],$c[$d]));$c[]=$a(['/','\\',1],[1,'/','\\'],$c[$d]);}echo implode(" ",$c);


Ungolfed code

<?php

function randomString($length,$a, $b) {$string = '';
while(strlen($string) <$length) {
$string .= rand(0, 1) ?$a : $b; } return$string;
}

if(isset($argv)) { srand(intval($argv));
}

$lines = [ str_repeat('=', 12), str_repeat('-', 12), randomString(12, '/', '\\'), randomString(12, '<', '>'), randomString(12, '/', '\\'), str_repeat('-', 12) ]; while(count($lines) < 9) {
$lines[] = randomString(12, '/', '\\'); } for($index = count($lines);$index--;) {
$lines[$index] .= strrev(str_replace(['/', '<', '\\', '>', 1, 2], [1, 2, '/', '<', '\\', '>'], $lines[$index]));
$lines[] = str_replace(['/', '\\', 1], [1, '/', '\\'],$lines[$index]); } echo implode("\n",$lines) . "\n";

?>


The ungolfed version has a little bonus: You can pass it an integer to seed rand() and get the same quilt each time for a seed:

php quilt.php 48937


This results, for example, in this beautiful, hand woven quilt:

========================
------------------------
/\\\////\\\/\///\\\\///\
><>><>><<<><><>>><<><<><
/\\\///\//\/\/\\/\\\///\
------------------------
/\\/\\\/\\/\/\//\///\//\
/\\\\/\//\\/\//\\/\////\
\/\\/\/\////\\\\/\/\//\/
/\//\/\/\\\\////\/\/\\/\
\////\/\\//\/\\//\/\\\\/
\//\///\//\/\/\\/\\\/\\/
------------------------
\///\\\/\\/\/\//\///\\\/
><>><>><<<><><>>><<><<><
\///\\\\///\/\\\////\\\/
------------------------
========================


Edit: Turns out my first version did not return a correct quilt. So I fixed it. Funny enough, the fix is even shorter.

• You can do many things to golf this: ['/','<','\\','>','a','b'] can be replaced with ['/','<','\\','>',a,b] (notice the missing quotes around a and b), @$s can be replaced with $s, you can store str_repeat('-',12) and str_repeat('=',12) in global variables/constants, for($b=8;$b>=0;$b--) can be replaced with for($b=9;$b--;), str_repeat and repeated functions can be shortened by giving their name to a global variable (e.g.: global$R,$V;$R=str_repeat;$V=strrev;$V($R('=',12))) and newlines (\n) may be replaced by a multi-line string. Apr 17, 2015 at 18:54 • Here is a shorter version: pastebin.com/2TabUqbA (373 bytes). I've changed a few tips: removed the global variables, lets strrev unchanged, removed 1 space and a few small changes. Apr 17, 2015 at 19:06 • I think you need line 4 and line 15 (the <>><>< lines) to be the same. Apr 18, 2015 at 2:59 • Sorry, here's a 357-bytes long solution: pastebin.com/TugNDjjL I forgot to reduce some things. Apr 18, 2015 at 20:40 • @IsmaelMiguel Thanks for your help. I took some of your advice, but some of it results in a notice getting thrown. Apr 20, 2015 at 8:06 # JavaScript (ES6) 169 195 201 Edit 6 bytes saved thx @nderscore. Beware, the newline inside backquotes is significant and counted. Edit2 simplified row building, no need of reverse and concat F=(o='')=>[...z='/\\/-/<\\-='].map((c,i,_,y=[z,'\\/\\-\\>/-='],q=[for(_ of-z+z)Math.random(Q=k=>q.map(v=>r=y[v^!k][i]+r+y[v^k][i],r='')&&r+ )*2])=>o=Q()+o+Q(i!=5))&&o  Run snippet to test (in Firefox) F=(o='')=>[...z='/\\/-/<\\-='].map((c,i,_,y=[z,'\\/\\-\\>/-='],q=[for(_ of-z+z)Math.random(Q=k=>q.map(v=>r=y[v^!k][i]+r+y[v^k][i],r='')&&r+ )*2])=>o=Q()+o+Q(i!=5))&&o Q.innerHTML=F() <pre id=Q style='font-size:9px;line-height:9px'> • -6 bytes: Remove parenthesis around definition of z. Move definition of Q inside of the Math.random call. Replace '\n' with template string of newline. |0 integer casting is not needed, as the values will be xor-ed later on. Apr 17, 2015 at 21:27 • What does this for(_ of-z+z) mean? Apr 19, 2015 at 19:43 • @Derek I need to iterate 12 times and the best I have is a 9 char string. z is not numeric so -z is NaN (not a number) NaN converted to string is "NaN" and 3 chars + 9 chars are 12. Apr 19, 2015 at 19:48 # Ruby, 162 155 I like this one because it made me learn to abuse backslashes in both string literals and String#tr. The code isn't terribly clever otherwise, just compact. a='/\\' b='\\\/' t=Array.new(9){x='' 12.times{x+=a[rand(2)]} x+x.reverse.tr(a,b)} t=?=*24 t=t=?-*24 t.tr!a,'<>' puts t,((t.reverse*' ').tr a,b)  • Welcome to Programming Puzzles & Code Golf Stack Exchange! Here are a couple of Ruby-specific tips: I don't think you need to escape the / in a and b. The first tr can probably also do without parentheses. Single-character strings like '=' can be written ?=. And .join can be replaced by *. Apr 18, 2015 at 19:33 • @MartinBüttner Thanks for the welcome and the tips! The character literals and join synonym save me 6 bytes. I can't remove the parentheses in x+x.reverse.tr(a,b) because + takes precedence over , though. I'm also not actually escaping the slashes in my strings - I'm failing to escape one backslash in each. A second \ is necessary in b because of the way tr works, though I now realize the first \ in a is superfluous, so there's another byte. Apr 19, 2015 at 3:30 # Pyth, 57 59 61 J"\<>/"K"\/"L+b_mXdK_Kbjbym+d_XdJ_JmsmOk12[\=\-K-JKK\-KKK J"\<>/"K"\/"jbu++HGXHK_Km+d_XdJ_JmsmOk12[KKK\-K-JKK\-\=)Y  Thanks a lot to @Jakube for coming up with these 57 byte versions. Algorithm very similar to Martin's. (Revised) Explanation to come. Try it online Explanation: =G"\<>/" : Set G to be the string "\<>/" K"\/" : Set K to be the string "\/" Jm+d_XdG_GmsmOk12[\=\-K"<>"K\-KKK; : Set J to be the top half of the carpet [\=\-K"<>"K\-KKK; : Make a list of possible chars for each row msmOk12 : for each element of that list, : make a list of 12 randomly chosen characters : from it, then join them Jm+d_XdG_G : for each element of that list, : make a new list with the old element, : and its horizontal reflection jb+J_mXdK_KJ : Print the whole carpet mXdK_KJ : For each element of J make its vertical reflection  • Very nice. Shouldn't have thrown in the towel. 1 char save by replacing "<>" with -GK Apr 17, 2015 at 19:24 • And another one by either using lambda J"\<>/"K"\/"L+b_mXdK_Kbjbym+d_XdJ_JmsmOk12[\=\-K-JKK\-KKK or reduce J"\<>/"K"\/"jbu++HGXHK_Km+d_XdJ_JmsmOk12[KKK\-K-JKK\-\=)Y Apr 17, 2015 at 19:41 • @Jakube Thanks! Both of those are quite clever optimizations. I really like how the lambda lets you put the list at the end. Apr 17, 2015 at 22:17 # J, 56 54 bytes '=/\<>--></\'{~(-,|.)0,(3(2})8$5,3#1)+(,1-|.)"1?8 12$2  Usage:  '=/\<>--></\'{~(-,|.)0,(3(2})8$5,3#1)+(,1-|.)"1?8 12$2 ======================== ------------------------ ///\\\\/\///\\\/\////\\\ ><<><><>><>><<><<><><>>< \\/\//\\/\//\\/\//\\/\// ------------------------ \/\/\//////\/\\\\\\/\/\/ /\/\\//\//\\//\\/\\//\/\ //\\\\/////\/\\\\\////\\ \\////\\\\\/\/////\\\\// \/\//\\/\\//\\//\//\\/\/ /\/\/\\\\\\/\//////\/\/\ ------------------------ //\/\\//\/\\//\/\\//\/\\ ><<><><>><>><<><<><><>>< \\\////\/\\\///\/\\\\/// ------------------------ ========================  1 byte thanks to @FUZxxl. Explanation coming soon. Try it online here. • Save one character: Replace 5 1 3 1 5 1 1 1 with (3(2})8$5,3#1). Apr 18, 2015 at 12:13
• @FUZxxl Great! I tried a ton of alternatives but haven't found this. (CJam got away in score overnight so J will not reach them. :P) Apr 18, 2015 at 18:21

# Python 295287 227 bytes

Not that great but I'll post it anyway:

from random import*
m,d=[],dict(zip("\/<>=-","/\><=-"))
v=lambda w:[d[x]for x in w]
for e in '=-/>/-///':f=[choice([e,d[e]])for x in*12];t=''.join(f+v(f[::-1]));print t;m+=''.join(e=='/'and v(t)or t),
print'\n'.join(m[::-1])


If you want an explanation just ask me.

• @Sp3000 Thanks for pointing it out, I fixed it. A shame it came if even longer though...
– Def
Apr 19, 2015 at 12:09
• Here's a bunch of golfs which are too long to fit in a comment. You might be able to get it down even more if you put = and - in d. Apr 19, 2015 at 13:54
• @Sp3000 Thanks a lot for all the advice. A lot of it was pretty obvious (spaces, removing reversed) as I'm not the greatest golfer (both code and irl), but I learned some new python too (so again thanks). Removing the if statement by including = and - in the dict turned out to be a very good idea. P.S. would you mind explaining how a recursive quilt is made in so few code (decrypting translate sucks)
– Def
Apr 19, 2015 at 15:29

# Javascript (ES7 Draft) 174168 146

Some inspiration taken from @edc65

Edit: Thanks to edc65 for some ideas to optimize building of rows.

F=(o='')=>[for(i of'555357531')(z=[for(_ of c='==--/\\<>golf')Math.random(r=x=>z.reduce((s,y)=>c[w=i^y^x]+s+c[w^1],'')+
)*2],o=r()+o+r(i<7))]&&o


Demonstration: (Firefox only)

F=(o='')=>[for(i of'555357531')(z=[for(_ of c='==--/\\<>golf')Math.random(r=x=>z.reduce((s,y)=>c[w=i^y^x]+s+c[w^1],'')+
)*2],o=r()+o+r(i<7))]&&o

document.write('<pre>' + F() + '</pre>');

Commented:

// define function, initialize output to ''
F = (o = '') =>
// loop through character indexes of first 9 lines
[
for (i of '555357531')(
// build array of 12 random 0/1's, initialize character list
z = [
for (_ of c = '==--/\\<>golf')
Math.random(
// define function for generating lines
// if x is true, opposite line is generated
r = x =>
z.reduce(
(s, y) =>
c[w = i ^ y ^ x] + s + c[w ^ 1],
''
) + \n
) * 2
],
// build new lines and wrap output in them
// x true in the second line for indexes < 7 (not character '>')
o = r() + o + r(i < 7)
)
]
// return output
&& o

• See my edit, it's good for your solution too Apr 18, 2015 at 8:52
• @edc65 nice idea! I've implemented something similar now. Apr 18, 2015 at 14:42

## Pharo 4, 236

|s i f v h|s:='====----/\/\/<><<>'.f:=[:c|s at:(s indexOf:c)+i].v:=#(),'=-/</-///'collect:[:c|h:=(String new:12)collect:[:x|i:=2atRandom.f value:c].i:=1.h,(h reverse collect:f)].i:=3.String cr join:v,(v reverse collect:[:k|k collect:f])


or formatted normally:

|s i f v h|
s:='====----/\/\/<><<>'.
f:=[:c|s at:(s indexOf:c)+i].
v:=#() , '=-/</-///'
collect:[:c|
h:=(String new:12)collect:[:x|i:=2atRandom.f value:c].
i:=1.
h,(h reverse collect:f)].
i:=3.
String cr join:v,(v reverse collect:[:k|k collect:f])


Explanation:

The string s:='====----/\/\/<><<>' together with the block f:=[:c|s at:(s indexOf:c)+i] are here both for tossing the characters and for reversing the patterns...

• For i=1, it performs horizontal reversion (/ <-> \ , < <-> > ).

• For i=3, it performs vertical reversion (/ <-> \)

• For i=1 or 2 atRandom, it toss among / or \, < or >

'=-/</-///' encodes the character type c that will feed the block f for the 9 first lines.

#() , '=-/</-///' is a concatenation trick for transforming the String into an Array and thus collecting into an Array.

The rest is simple concatenation after applying the horizontal/vertical symetry.

========================
------------------------
\\/\/\\\\/\/\/\////\/\//
>>>><><><>><><<><><><<<<
\/\/\//\///\/\\\/\\/\/\/
------------------------
/\//\/\/////\\\\\/\/\\/\
\\//\//\\\/\/\///\\/\\//
////\\/\/\//\\/\/\//\\\\
\\\\//\/\/\\//\/\/\\////
//\\/\\///\/\/\\\//\//\\
\/\\/\/\\\\\/////\/\//\/
------------------------
/\/\/\\/\\\/\///\//\/\/\
>>>><><><>><><<><><><<<<
//\/\////\/\/\/\\\\/\/\\
------------------------
========================


## Squeak 4.X, 247

|r s h m n p|s:='==--/\<>'.r:=(1<<108)atRandom.h:=''.m:=0.(16to:0by:-2),(0to:16by:2)do:[:i|n:=3bitAnd:28266>>i.p:=0.(11to:0by:-1),(0to:11)do:[:j|h:=h,(s at:n*2+1+(r-1>>(6*i+j)+(101>>(3-n*4+m+p))bitAnd:1)).j=0and:[p:=1]].i=0and:[m:=2].h:=h,#].h


Or formatted:

|r s h m n p|
s:='==--/\<>'.
r:=(1<<108)atRandom.
h:=''.
m:=0.
(16to:0by:-2),(0to:16by:2) do:[:i|
n:=3 bitAnd: 28266>>i.
p:=0.
(11to:0 by:-1),(0to:11) do:[:j|
"h:=h,(s at:n*2+1+((r-1bitAt:6*i+j+1)bitXor:(101bitAt:3-n*4+m+p))). <- originally"
h:=h,(s at:n*2+1+(r-1>>(6*i+j)+(101>>(3-n*4+m+p))bitAnd:1)).
j=0and:[p:=1]].
i=0and:[m:=2].
h:=h,#].
h


Explanations:

s:='==--/\<>'. obviously encodes the four posible pairs.

r:=(1<<108)atRandom. toss 108 bits (in a LargeInteger) for 9 rows*12 columns (we toss the == and -- unecessarily but performance is not our problem).

h:=''is the string where we will concatenate (Schlemiel painter because a Stream would be too costly in characters).

(16to:0by:-2),(0to:16by:2)do:[:i| is iterating on the rows (*2)

(11to:0by:-1),(0to:11) do:[:j| is iterating on the columns

28266 is a magic number encoding the pair to be used on first 9 lines.
It is the bit pattern 00 01 10 11 10 01 10 10 10, where 00 encodes '==', 01 '--', 10 '/\' and 11 '<>'.

101 is a magic number encoding the horizontal and vertical reversion.
It is the bit pattern 0000 0000 0110 1010, encoding when to reverse (1) or not (0) the first (0) or second (1) character of each pair '==' '--' '/\' and '<>', for the vertical symetry and horizontal symetry.

n:=3 bitAnd: 28266>>i gives the encoding of character pair for row i/2 (0 for '==', 1 for '--', 2 for '/\' and 3 for '<>').

(r-1 bitAt: 6*i+j+1) pick the random bit for row i/2 column j (1 is the rank of lowest bit thus we have a +1, k atRandom toss in interval [1,k] thus we have a -1).

(101 bitAt: 3-n*4+m+p) pick the reversal bit: (3-n)*4 is the offset for the group of 4 bits corresponding to the pair code n, m is the vertical reversion offset (0 for first 9, 2 for last 9 rows), p is the horizontal reversion offset (0 for first 12, 1 for last 12 columns)+1 because low bit rank is 1.

bitXor: performs the reversion (it answer an offset 0 or 1), and s at:2*n+1+bitXor_offset pick the right character in s.

But (A>>a)+(B>>b) bitAnd: 1 costs less bytes than (A bitAt:a+1)bitXor:(B bitAt:b+1)thus the bitXor was rewritten and offset +1 on p is gone...

h,# is an ugly squeakism, we can concatenate a String with a ByteArray (containing code for carriage return).

========================
------------------------
/\/\\\/\//\/\/\\/\///\/\
><>><<>>>><<>><<<<>><<><
////\\////\\//\\\\//\\\\
------------------------
/\\\/\\/\\//\\//\//\///\
\/\\/\//////\\\\\\/\//\/
\\\//\\\////\\\\///\\///
///\\///\\\\////\\\//\\\
/\//\/\\\\\\//////\/\\/\
\///\//\//\\//\\/\\/\\\/
------------------------
\\\\//\\\\//\\////\\////
><>><<>>>><<>><<<<>><<><
\/\///\/\\/\/\//\/\\\/\/
------------------------
========================