47
\$\begingroup\$

Write a full program or a function that takes a positive integer N as input via STDIN/command line/ARGV or function arguments and prints an ASCII double knot corresponding to the N to STDOUT.

The ASCII double knot looks like this:

  __  __  __  __  __  __
 /  \/  \/  \/  \/  \/  \
| /\/ /\/ /\/ /\/ /\/ /\ |
| \/ /\/ /\/ /\/ /\/ /\/ |
 \ \/\ \/\ \/\ \/\ \/\ \/
 /\ \/\ \/\ \/\ \/\ \/\ \
| /\/ /\/ /\/ /\/ /\/ /\ |
| \/ /\/ /\/ /\/ /\/ /\/ |
 \__/\__/\__/\__/\__/\__/

The above is for N = 6

Here are a few more double knots for other values of N:

If N = 1, the output double knot looks like:

  __
 /  \
| /\ |
| \/ |
 \ \/
 /\ \
| /\ |
| \/ |
 \__/

For N = 2, its

  __  __ 
 /  \/  \
| /\/ /\ |
| \/ /\/ |
 \ \/\ \/
 /\ \/\ \
| /\/ /\ |
| \/ /\/ |
 \__/\__/

For N = 3, its

  __  __  __ 
 /  \/  \/  \
| /\/ /\/ /\ |
| \/ /\/ /\/ |
 \ \/\ \/\ \/
 /\ \/\ \/\ \
| /\/ /\/ /\ |
| \/ /\/ /\/ |
 \__/\__/\__/

and similarly, the pattern continues and any larger value of N.

Details:

  • The input is always a positive integer greater than 0.
  • Trailing newline is optional
  • There should either be no trailing spaces in each line, or enough trailing spaces such that each row's length is 4*N + 2.
  • There should never be any leading space that aren't part of the specified pattern.

This is , so shortest code in bytes wins.


Series Leaderboard

I am converting this into a series of ASCII art challenges and thus adding a leader board for the series (snippet by Martin). To make sure that your answers show up, please start every answer with a headline, using the following Markdown template:

# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

# Ruby, <s>104</s> <s>101</s> 96 bytes

/* Configuration */

var QUESTION_IDs = [50484, 50521, 50625, 51123, 51222]; // Obtain this from the url
// It will be like http://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!.FjwQBrX2KXuFkv6p2lChi_RjzM19";

/* App */

var answers = [], page = 1, currentQ = -1;

function answersUrl(index) {
  return "http://api.stackexchange.com/2.2/questions/" +  QUESTION_IDs.join(";") + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}


function getAnswers() {
  $.ajax({
    url: answersUrl(page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      if (data.has_more) getAnswers();
      else process();
    }
  });
}

getAnswers();

var SIZE_REG = /\d+(?=[^\d&]*(?:&lt;(?:s&gt;((?!&gt;).)*&lt;\/s&gt;|((?!&gt;).)+&gt;)[^\d&]*)*$)/;
var NUMBER_REG = /\d+/;
var LANGUAGE_REG = /^#*\s*([^\n,]+)(?=,)/;//

function shouldHaveHeading(a) {
  var pass = false;
  var lines = a.body_markdown.split("\n");
  try {
    pass |= /^#/.test(a.body_markdown);
    pass |= ["-", "="]
              .indexOf(lines[1][0]) > -1;
    pass &= LANGUAGE_REG.test(a.body_markdown);
  } catch (ex) {}
  return pass;
}

function shouldHaveScore(a) {
  var pass = false;
  try {
    pass |= SIZE_REG.test(a.body_markdown.split("\n")[0]);
  } catch (ex) {}
  if (!pass) console.log(a);
  return pass;
}

function getAuthorName(a) {
  return a.owner.display_name;
}

function getAuthorId(a) {
  return a.owner.user_id;
}

function process() {
  answers = answers.filter(shouldHaveScore)
                   .filter(shouldHaveHeading);
  answers.sort(function (a, b) {
    var aB = +(a.body_markdown.split("\n")[0].match(SIZE_REG) || [Infinity])[0],
        bB = +(b.body_markdown.split("\n")[0].match(SIZE_REG) || [Infinity])[0];
    return aB - bB
  });

  var users = {};
  answers.forEach(function (a) {
    var headline = a.body_markdown.split("\n")[0];
    var question = QUESTION_IDs.indexOf(a.question_id);
    var size = parseInt((headline.match(SIZE_REG)||[0])[0]);
    var language = headline.match(LANGUAGE_REG)[1];
    var user = getAuthorName(a);
    var userId = getAuthorId(a);
    if (!users[userId]) users[userId] = {name: user, nAnswer: 0, answers: []};
    if (!users[userId].answers[question]) {
      users[userId].answers[question] = {size: Infinity};
      users[userId].nAnswer++;
    }
    if (users[userId].answers[question].size > size) {
      users[userId].answers[question] = {size: size, link: a.share_link}
    }
  });
  
  
  var sortedUsers = [];
  for (var userId in users)
    if (users.hasOwnProperty(userId)) {
      var user = users[userId];
      user.score = 0;
      user.completedAll = true;
      for (var i = 0; i < QUESTION_IDs.length; ++i) {
        if (user.answers[i])
          user.score += user.answers[i].size;
        else
          user.completedAll = false;
      }
      sortedUsers.push(user);
    }  
  
  sortedUsers.sort(function (a, b) {
    if (a.nAnswer > b.nAnswer) return -1;
    if (b.nAnswer > a.nAnswer) return 1;
    return a.score - b.score;
  });
  
  var place = 1;
  for (var i = 0; i < sortedUsers.length; ++i) {
    var user = sortedUsers[i];
    var row = '<tr><td>'+ place++ +'.</td><td>'+user.name+'</td>';
    for (var j = 0; j < QUESTION_IDs.length; ++j) {
      var answer = user.answers[j];
      if (answer)
        row += '<td><a href="'+answer.link+'">'+answer.size+'</a></td>';
      else
        row += '<td class="missing"></td>';
    }
    row += '<td></td>';
    if (user.completedAll)
      row += '<td class="total">'+user.score+'</td>';
    else
      row += '<td class="total missing">'+user.score+'</td>';
    row += '</tr>';
    $("#users").append(row);
  }
}
body { text-align: left !important}

#leaderboard {
  width: 500px; 
}

#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}

#language-list {
  padding: 10px;
  width: 290px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}

td.total {
  font-weight: bold;
  text-align: right;
}

td.missing {
  background: #bbbbbb;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">
<div id="leaderboard">
  <h2>Leaderboard</h2>
  <p>
    Missing scores are shown as grey cells. A grey total indicates that the user has not participated in all challenges and is not eligible for the overall victory yet.
  </p>
  <table class="_user-list">
    <thead>
      <tr><td></td><td>User</td>
        <td><a href="https://codegolf.stackexchange.com/q/50484/31414">#1</a></td>
        <td><a href="https://codegolf.stackexchange.com/q/50521/31414">#2</a></td>
        <td><a href="https://codegolf.stackexchange.com/q/50625/31414">#3</a></td>
        <td><a href="https://codegolf.stackexchange.com/q/51123/31414">#4</a></td>
        <td><a href="https://codegolf.stackexchange.com/q/51222/31414">#5</a></td>
        <td></td><td>Total</td>
      </tr>
    </thead>
    <tbody id="users">

    </tbody>
  </table>
</div>
<table style="display: none">
  <tbody id="answer-template">
    <tr><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>
<table style="display: none">
  <tbody id="language-template">
    <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>


Series so far

1. Double Knot

2. Flow Snakes

3. Chinese Shrines

4. Zodiac Signs

5. Random Diamond Tilings

\$\endgroup\$
  • 1
    \$\begingroup\$ Why is the right edge different for N=3? \$\endgroup\$ – aditsu May 24 '15 at 9:17
  • \$\begingroup\$ @aditsu Haha. 4 days, 3K views, 11 answers and you are the first person to notice it :D . Fixed! \$\endgroup\$ – Optimizer May 24 '15 at 9:18

15 Answers 15

12
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ I'm not sure how long I tried to make the 1>W< shorter. Turns out that I only had to rotate the array before encoding it and use 2>... \$\endgroup\$ – Dennis Jun 4 '15 at 3:59
23
\$\begingroup\$

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.
\$\endgroup\$
12
\$\begingroup\$

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
`)
\$\endgroup\$
  • \$\begingroup\$ I think you can replace the string before .split(0) with ('__ 0 '+(r='\\/0/\\/ 0\\/ /0 ')+r+'0\\/ /0__/\\'). \$\endgroup\$ – flawr May 20 '15 at 17:45
  • \$\begingroup\$ @flawr I was able to condense it down even further using a similar method :) \$\endgroup\$ – nderscore May 20 '15 at 17:54
  • \$\begingroup\$ If you pass 0 on it, you will see an 8. \$\endgroup\$ – Ismael Miguel May 20 '15 at 18:30
  • \$\begingroup\$ What do those `` and the ${...} exactly do? \$\endgroup\$ – flawr May 20 '15 at 20:09
  • \$\begingroup\$ @flawr The backtick ` syntax declares a template string. Anything inside ${} is evaluated as a javascript expression. \$\endgroup\$ – nderscore May 20 '15 at 20:21
9
\$\begingroup\$

Perl, 134 129

print s/...\K.{4}/$&x~-"@ARGV"/er=~y!iolp!| /\\!r,$/for
map/i/?$_.oi:"o$_$_".o,o__o,loop,@x=(iolplolp,ioplolpl),popl,lpop,@x,p__l

Takes a command line parameter:

$ perl ~/knot.pl 3
  __  __  __  
 /  \/  \/  \ 
| /\/ /\/ /\ |
| \/ /\/ /\/ |
 \ \/\ \/\ \/ 
 /\ \/\ \/\ \ 
| /\/ /\/ /\ |
| \/ /\/ /\/ |
 \__/\__/\__/ 
\$\endgroup\$
8
\$\begingroup\$

JavaScript (ES6), 165 166

Knot elements:

  • 2 top rows, based on ' __' and '/ \' repeated
  • 2 outer rows, based on '/\/ ' repeated and enclosed in '| ... |'
  • 2 inner rows, based on '\/\ ' repeated and enclosed in '.../' and '/...\'
  • the same 2 outer rows above
  • 1 bottom row based on '\__/' repeated

Ungolfed

K=r=>
{
  R = x => x.repeat(r);
  S = d => R(elem).slice(d,d-2); // use global 'elem' that must be assigned before the call
  elem = '/\\/ '
  outer = '\n| ' + S(0) + ' |\n| ' + S(1) + ' |\n '
  elem = '\\ \\/'
  inner = '\\' + S(1) + '/\n /' + S(0) + '\\'
  return R('  __') + '\n ' + R('/  \\') + outer
  + inner + outer + R('\\__/')
}

Golfed

K=r=>(S=d=>(R=e=>e.repeat(r))(e).slice(d,d-2),o=`
| ${S(0,e='/\\/ ')} |
| ${S(1)} |
 `,R('  __')+`
 ${R('/  \\')+o}\\${S(1,e='\\ \\/')}/
 /${S(0)}\\${o}`+R('\\__/'))

// TEST

function go() {
  O.innerHTML=K(I.value)
}

go()
<input id=I value=5><button onclick='go()'>-></button><br>
<pre id=O></pre>

\$\endgroup\$
  • 2
    \$\begingroup\$ Try passing 0 to it and you will get a 4-legged spider. \$\endgroup\$ – Ismael Miguel May 20 '15 at 18:29
8
\$\begingroup\$

C++ , 1530 639 479

This looked like a fun challenge I deviated from the brief a little.

#include "stdafx.h"
#include <iostream>
#include <sstream>
using namespace std;
string a=" __ ",b="/  \\",c=" /\\",d="/\\/ ",f="\\ \\/",g="/\\\ \\",r="\\__/",o="",e=o,j="|";
string q(int n,string r,string x="",string m=" ",string t=" "){string z=o;for(int i=0;i<n;i++){z+=r;if(i!=n-1)z+=x;}return m+z+t+"\n";}
int main(){int x,y;cin>>x;cin>>y;e+=q(x,a)+q(x,b);for(int i=0;i<y;i++){e+=q(x,c,"/",j," |")+q(x-1,d,o,"| \\/ ",j);if(i!=y-1){e+=q(x,f)+q(x,g);}}e+=q(x,r);cout<<e;}

Im not sure how to measure bytes of the size of my application but I will try figure it out and update my answer.

My app could be smaller but it loops in both the x and y, and I kinda like that :D

\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to PPCG! Your score is the size of your source code, which is 1530 bytes as it is. You can start saving bytes by removing comments and whitespace, and shorten variable and function names. \$\endgroup\$ – Dennis May 21 '15 at 4:05
  • \$\begingroup\$ Wowzor thats bigger then the rest haha i will work on getting it down :D \$\endgroup\$ – Spaceman May 21 '15 at 4:19
6
\$\begingroup\$

Python 2, 156 151 147 141 139

edit 1: edited to use input() instead of a function.

edit 2: used str.join and added to var c to remove some redundant characters.

edit 3: removed some unnecessary string escape sequences.

edit 4: used ~-n instead of a=n-1

This was good fun to program, my first code golf!

n=input()
a='/\/ '*~-n
b='\ '+'\/\ '*~-n+'\\'
c='\n| '+a+'/\ |\n| \/ '+a+'|'
print'\n '.join(('  __'*n,'/  \\'*n+c,b+'/','/'+b+c,'\__/'*n))

save it in an external text editor as n.py in order to remove last newline character in order to reduce file size by 1 byte, run the module, and input your number.

\$\endgroup\$
  • \$\begingroup\$ If you allow for entering the number right after the programs execution statement, then I can further strip it down to 151 bytes \$\endgroup\$ – micsthepick May 20 '15 at 9:56
  • \$\begingroup\$ Usually input () is considered okay when reading from STDIN. \$\endgroup\$ – seequ May 20 '15 at 16:12
  • \$\begingroup\$ I see you've saved a=n-1 to save on writing *(n-1) twice, but you do *~-n. \$\endgroup\$ – xnor May 21 '15 at 6:06
  • \$\begingroup\$ still same amount of characters either way, because I use the value twice, but good tip. \$\endgroup\$ – micsthepick May 21 '15 at 6:37
  • \$\begingroup\$ You can save some bytes on the way python handles backslashes in strings, you don't always need to encode them. See stackoverflow.com/a/16973452/3351622 \$\endgroup\$ – Matty May 22 '15 at 9:31
5
\$\begingroup\$

Python 2, 139 133 129 bytes

n=input()
for i in range(9):w=' ?|'[i&2];s=' / /\/ /\_ /\ \/\__ \/\ \/_ \/ /\/ /'[i::9]*n;s=(s,' %s '%s[1:-1])[i%4>1];print w+s+w

This one just builds and prints line by line.

Here's the code in ungolfed form:

n=int(input())
# The list with all the knot pieces
l= [' __ ',
    '/  \\',
    ' /\/',
    '/\/ ',
    '\ \/',
    '/\ \\',
    ' /\/',
    '/\/ ',
    '\__/']
# The first and last columns
w = '  ||  || '
# Loop for each row
for i in range(9):
    # Exception for the first and last character in the knot (in some rows)
    s = l[i]*n
    if i % 4 > 1:
        s = ' ' + s[1:-1] + ' '
    # Print the knot for this row
    print(w[i] + s + w[i])

Edit: I changed the language to python 2, to be compatible with my answer for #3 (and it also saves 6 more bytes)

\$\endgroup\$
  • \$\begingroup\$ I believe w=(3*' ||')[i] -> w=' |'[i&2] and ' '+s[1:-1]+' ' -> ' %s '%s[1:-1] work (the first one is a string with two spaces then a pipe, but SE's acting up) \$\endgroup\$ – Sp3000 May 25 '15 at 6:45
  • \$\begingroup\$ @Sp3000 Thanks! That first one is pretty smart. I should have thought of ' ||'[i%4], but this is even shorter (also with two spaces). \$\endgroup\$ – Matty May 25 '15 at 11:13
3
\$\begingroup\$

C, 159 bytes

j,k;f(n){char*t="7>771I;M6CMI93;IIB;;MI1M;M6CMI93;IIB;>MI";for(n*=4;t[j/2];++k,k%=n+3,j+=k-n?k%n<3||k%4-2?1:-3:3)putchar("\n _|/\\"[(t[j/2]-48)/(j%2?1:6)%6]);}

With whitespace, and some other readability improvements:

#include <stdio.h>

int j, k;

void f(int n) {
    char *t = "7>771I;M6CMI93;IIB;;MI1M;M6CMI93;IIB;>MI", *m = "\n _|/\\";
    for (n *= 4; t[j / 2];
         ++k,
         k %= n + 3,
         j += k - n ? k % n < 3 || k % 4 - 2 ? 1 : -3 : 3)
        putchar(m[(t[j / 2] - 48) / (j % 2 ? 1 : 6 ) % 6]);
}

This is primarily template based. The template t contains all 9 possible columns of the output, meaning that it encodes 9 * 9 = 81 characters, or 80 without the trailing newline.

Since there are only 6 different characters in the pattern (including newline characters), I packaged pairs of them into one template character, which means that the template can be stored in 40 characters. There are then 6 * 6 = 36 possible pairs of characters, which are encoded as ASCII characters 48 to 73. The translation back to the original character is given by the small lookup table m.

The rest of the logic is mainly to repeat the pattern n times, which means jumping back 4 characters in the template, while emitting the start and end parts of each row correctly.

\$\endgroup\$
2
\$\begingroup\$

PHP 5.5.3, 488, 466

<?php 
function k($n){$r=array_fill(0,9,'');for($i=0;$i<$n;$i++){$r[0].=($i==0)?"  __ ":" __ ";$r[1].=($i==0)?" /  \\":"/  \\";$r[2].=($i==0)?"| /\\/":(($i==$n-1)?" /\\ |":" /\\/");$r[3].=($i==0)?"| \/ ":(($i==$n-1)?"/\/ |":"/\/ ");$r[4].=($i==0)?" \\ ":(($i==$n-1)?"\\/\\ \\/":"\\/\\ ");$r[5].=($i==0)?" /\\ ":(($i==$n-1)?"\\/\\ \\":"\\/\\ ");$r[6]=$r[2];$r[7]=$r[3];$r[8].=($i==0)? " \__/":"\__/";}foreach($r as $o){if(strlen($o)-2 !== 4*$n)$o.=" ";echo $o."\n";}}
\$\endgroup\$
  • \$\begingroup\$ You can save some chars by removing some unnecessary whitespace around operators, for example around the = and .= ones. \$\endgroup\$ – ProgramFOX May 21 '15 at 16:03
  • \$\begingroup\$ Thx I edited the answer \$\endgroup\$ – Med May 21 '15 at 16:12
2
\$\begingroup\$

Prolog (SWI), 285 bytes

a(N):-b(N,"  ||  || "," /  \\/  \\","_ /\\ \\/\\_","_ \\/\\ \\/_"," \\/ /\\/ /"," / /\\/ /\\"," \\  /\\  /"). b(N,[A|G],[B|H],[C|I],[D|J],[E|K],[F|L],[Y|Z]):-c(N,[Y,A],[E,F,C,D],T),writef([A,B,C,D|T]),nl,b(N,G,H,I,J,K,L,Z). c(1,L,_,L):-!. c(N,L,X,O):-M is N-1,c(M,L,X,T),append(X,T,O).

(With whitespace):

a(N):-
    b(N,
    "  ||  || ", 
    " /  \\/  \\", 
    "_ /\\ \\/\\_", 
    "_ \\/\\ \\/_", 
    " \\/ /\\/ /", 
    " / /\\/ /\\", 
    " \\  /\\  /").

b(N,[A|G],[B|H],[C|I],[D|J],[E|K],[F|L],[Y|Z]):-
    c(N,[Y,A],[E,F,C,D],T),
    writef([A,B,C,D|T]),
    nl,
    b(N,G,H,I,J,K,L,Z).

c(1,L,_,L):-!.
c(N,L,X,O):-
    M is N - 1,
    c(M,L,X,T),
    append(X,T,O).

I tried a few ways of chopping the strings, but none seemed to beat this naive columns method.

\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 158 154 148 137 bytes

n=>`    __
 /\\/ - \\/
 /\\/\\-__/`.replace(/-/g,` \\
| / /\\ |
|  /\\/ |
 \\/\\`).replace(/(..)(....)/g,(_,l,m)=>l+m.repeat(n).slice(2))

Edit: Saved 11 bytes thanks to @Bálint.

\$\endgroup\$
  • \$\begingroup\$ @Bálint But /(..)(.{4})/g is 13 bytes, the same as /(..)(....)/g... \$\endgroup\$ – Neil May 11 '16 at 21:17
  • \$\begingroup\$ @Bálint I actually realised that my previous 4-byte saving allowed me to do that, but I was away from the computer at the time. \$\endgroup\$ – Neil May 11 '16 at 21:19
  • \$\begingroup\$ @Bálint Nice! I had looked into avoiding the repeated \\/\\ segment but I hadn't thought to check for a longer repeated substring. \$\endgroup\$ – Neil May 12 '16 at 9:07
1
\$\begingroup\$

Java, 339 330 bytes

class D{int n,i;public static void main(String[]a){new D(new Integer(a[0]));}D(int k){n=k;r("  __");p("\n ");r("/  \\");c();r("\\ \\/");p("\n ");r("/\\ \\");c();r("\\__/");}void c(){p("\n|");--n;r(" /\\/");p(" /\\ |\n| \\/");r(" /\\/");++n;p(" |\n ");}void p(String s){System.out.print(s);}void r(String s){for(i=n;i>0;--i)p(s);}}

My first solution had so many "static" keywords in it that it was shorter to make the methods and attributes non-static and run the code in the constructor.

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 228 207 181 133 bytes

%{"  "+"__  "*$_;" "+"/  \"*$_;$b="|"+" /\/"*$_+"`b |";$b;$c="| "+"\/ /"*$_+"`b|";$c;" "+"\ \/"*$_;" "+"/\ \"*$_;$b;$c;" "+"\__/"*$_}

Reminder - PowerShell doesn't wait on stdin automatically. You have to pipe something in, e.g. 3|%{...}

\$\endgroup\$
0
\$\begingroup\$

SmileBASIC, 149 bytes

INPUT N?"  __"*N
A$="| / /\ |
B$="|  /\/ |
K" /\/  \
K A$K B$K" \/\ \/
K" /\/\ \
K A$K B$K" \/\__/
DEF K A?SUBST$(A,2,4,MID$(MID$(A,2,4)*N,2,N*9))END

Each string contains the pattern AACCBBDD which is expanded to form AABB(CCBB)*DD The CCBB part is repeated N times, then the first 2 characters are removed. (It was shorter to remove characters from the start than from the end)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.