ASCII Art of the Day #1 - Double Knot
CJam, 103 92 83 69 66 57 bytes
"O5àäªÞáKZò,_÷%SJ«Ò"248b5b"/ \_|"f=9/4/~ri*1>W<+2m<zN*
Try it online in the CJam interpreter.
Idea
The pattern becomes a lot more obvious once we transpose rows with columns (padded to the right with spaces).
For input 3, for example, this gives:
|| ||
/ \/ \
_ /\ \/\_
_ \/\ \/_
\/ /\/ /
/ /\/ /\
_ /\ \/\_
_ \/\ \/_
\/ /\/ /
/ /\/ /\
_ /\ \/\_
_ \/\ \/_
\ /\ /
|| ||
The first two and last two rows are special, but the others repeat the same pattern over and over again.
Thus, for input N, all we have to do is repeat
/ /\/ /\
_ /\ \/\_
_ \/\ \/_
\/ /\/ /
N times, replace the first row with
|| ||
/ \/ \
the last row with
\ /\ /
|| ||
and, finally, transpose rows with columns.
Code
"O5àäªÞáKZò,_÷%SJ«Ò"
248b e# Convert the string (array of code points in base 248) to an integer.
5b e# Convert the integer to the array of its digits in base 5.
e# This pushes the following array:
e# [ 1 2 1 1 0 2 1 1 0 1 1 4 4 1 1 4 4 1 1 1 4 4 1 1
e# 4 4 1 1 0 1 1 2 0 1 1 2 1 0 1 0 2 0 1 0 2 3 1 0
e# 2 1 2 0 2 3 3 1 2 0 2 1 2 0 3 1 2 0 1 0 2 0 1 0 ]
"/ \_"
f= e# Retrieve the chars that correspond to the indexes in the array.
e# This pushes the following string:
e# " \ /\ / || || || || / \/ \ / /\/ /\_ /\ \/\__ \/\ \/_ \/ /\/ /"
9/4/~ e# Divide into groups of 4 strings of length 9.
e# This pushes the following arrays:
e# [ " \ /\ /" " || || " " || || " " / \/ \" ]
e# [ " / /\/ /\" "_ /\ \/\_" "_ \/\ \/_" " \/ /\/ /" ]
ri e# Read an integer from STDIN.
* e# Repeat the last array that many times.
1>W< e# Remove the first and last string from the array.
+ e# Concatenate both arrays.
2m< e# Rotate the concatenated arrays two elements to the left.
z e# Zip the array of strings (transpose rows with columns).
N* e# Join the strings of the array, separating by linefeeds.
Javascript (ES7 Draft), 169 163 160 158 bytes
Edit: -6 by using a template string to eliminate some repetition from the pattern string.
Edit: -3 by switching from slice(0,-2)
to slice(2)
by rearranging the pattern string.
Edit: -2 by looping through b
instead of a
and reducing the a
string to 4 with a modulo.
F=N=>[(a=' ||'[i%4])+b[i]+` __0\\/ ${c=' 0/ /\\0 /\\/0/\\'} \\0\\/\\${c}__`.split(0)[i].repeat(N).slice(2)+(b+b)[9-i]+a for(i in b=' / \\/ \\')].join(`
`)
<input id="stdin" value="4" />
<button onclick="stdout.innerHTML=F(stdin.value)">Run</button><br />
<pre id="stdout"></pre>
Commented:
F=N=>[ // define function F, start array comprehension to generate each line
(a = ' ||'[i % 4]) + // first character of the line, store copy in a
b[i] + // second character of each line
` __0\\/ ${c=' 0/ /\\0 /\\/0/\\'} \\0\\/\\${c}__`.
// list of patterns for each line delimited by 0's
// results in string: ' __0\/ 0/ /\0 /\/0/\ \0\/\ 0/ /\0 /\/0/\__'
split(0)[i]. // split by 0, get index at i
repeat(N). // repeat N times
slice(2) + // chop off the first 2 characters
(b + b)[9 - i] + // get opposite of second character, b+b to get a space at index 9
a // repeat first character (a)
for(i in b = ' / \\/ \\') // runs for each index in character map b
].join(` // join resulting array with newlines
`)
CJam, 55 bytes
I got nerd sniped pretty badly by this... anyway, I finally came up with 55 bytes of ISO 8859-1:
"²îå<63Åhbغ¢dräOä[æTZ"246b5b"|_ \/"f=9/4/~2/\ri*2>*zN*
or this alternative:
"ô/Ht]õDz1M;í,D¯Tmä$:r"246b5b"_/\ |"f=9/2/~+ri*2>\++zN*
Initially I tried to do it in plain ASCII, but only got it down to 58 bytes:
"C]VA~`+-WIt*n_I?FanSEo*b"128b5b"_/|\ "f=9/4/~2/\ri*2>*zN*
and again, an alternative:
"1,*Ap7c?UvI$yQHqHqs~=}n"153b5b"_ /|\\"f=9/2/~+ri*2>\++zN*
Explanation:
The idea is to encode the unique parts (left edge, right edge and middle pattern) in a convenient way, repeat the middle part as needed, and put them together. The code ended up being similar in many ways to Dennis's answer; I didn't try to copy him, but I tried many different approaches (including exploiting more symmetries and repetitions) and this is what worked best.
I put the left and right edges together like this:
/\
| |
| |
\/
/\
| |
| |
\/
The middle pattern has 4 columns, but they are repeated N-0.5 times, i.e. one repetition is cut in half. For convenience, I used this pattern:
__
\/
/ /\
/\/
/\ \
\/\
/ /\
/\/
/\__
and removed the first half of the first repetition.
So I joined the parts and encoded them in transposed form, as it's easier to work with them that way. The first and third program encode this string:
\/ /\/ /
/ /\/ /\
_ /\ \/\_
_ \/\ \/_
|| ||
/ \/ \
\ /\ /
|| ||
(without newlines), which is the transposition of the middle + edges. The second and fourth program (the "alternatives") encode this string:
|| ||
/ \/ \
\ /\ /
|| ||
\/ /\/ /
/ /\/ /\
_ /\ \/\_
_ \/\ \/_
again, without newlines, and this is the transposition of edges + middle.
Here's how this common part of the code works:
"…" encoded string (constructed via the reverse process,
using a suitable base that gives valid characters)
246b convert the string to an integer, treating each character as a digit
in base 246 (or other bases in the ASCII versions)
5b convert the number to base 5, obtaining 72 digits from 0 to 4,
representing the 5 different characters we have
"|_ \/"f= convert the digits to their corresponding characters
(each program uses a different assignment order)
9/ split the resulting strings into 8 strings of 9 characters
if viewed as lines, they look exactly like the 2 patterns shown above
After this, the implementation differs slightly. In the first and third program we have:
4/ split the lines into groups of 4 - the middle part and the edges
~ dump the two 4-line parts onto the stack
2/ split the second part (the edges) into 2 groups of 2 lines
(left edge and right edge)
\ swap the edges with the middle part
ri* read the input, convert to integer (N) and repeat the middle part N times
2> remove the first 2 lines (first half of first repetition)
* join the 2 edges using the repeated middle part as a separator
z transpose the result back to the desired form
N* join with newlines
In the second and fourth (alternative) programs, we have:
2/ split the lines into groups of 2
(left edge, right edge, middle first half, middle 2nd half)
~ dump all the groups onto the stack
+ join the two middle halves into a single middle group of 4 lines
ri* read the input, convert to integer (N) and repeat the middle part N times
2> remove the first 2 lines (first half of first repetition)
\ swap the repeated middle with the right edge
+ concatenate the middle with the right edge
+ concatenate the left edge with the rest
z transpose the result back to the desired form
N* join with newlines