29
\$\begingroup\$

Write a program or function that draws a tree of trees, thus constructing a forest.

The trees are drawn like stacking a pyramid. The first (top) row contains 1 tree, the next row down contains 2 (for a total of 3), the next contains 3 (for a total of 6), and so on. If there aren't enough trees to complete a full row, fill it to the left and leave the spots on the right empty. Additionally, lower-level trees slightly overlap upper-level trees due to their placement.

This is a forest of size 1

  /\
 //\\
///\\\
  ||
  ||

This is a forest of size 2

      /\
     //\\
  /\///\\\
 //\\ ||
///\\\||
  ||
  ||

This is a forest of size 3

      /\
     //\\
  /\///\\\/\
 //\\ || //\\
///\\\||///\\\
  ||      ||
  ||      ||

This is a forest of size 4

          /\
         //\\
      /\///\\\/\
     //\\ || //\\
  /\///\\\||///\\\
 //\\ ||      ||
///\\\||      ||
  ||
  ||

This is a forest of size 5 (note the top of the fifth tree is covering the trunk of the first tree)

          /\
         //\\
      /\///\\\/\
     //\\ || //\\
  /\///\\\/\///\\\
 //\\ || //\\ ||
///\\\||///\\\||
  ||      ||
  ||      ||

(skip a few)
This is a forest of size 8 (extending the pattern)

              /\
             //\\
          /\///\\\/\
         //\\ || //\\
      /\///\\\/\///\\\/\
     //\\ || //\\ || //\\
  /\///\\\/\///\\\||///\\\
 //\\ || //\\ ||      ||
///\\\||///\\\||      ||
  ||      ||
  ||      ||

and so on.

Input

A single positive integer in any convenient format, n > 0.

Output

An ASCII-art representation of the forest, following the above rules. Leading/trailing newlines or other whitespace are optional, provided that the trees all line up appropriately.

Rules

  • Either a full program or a function are acceptable. If a function, you can return the output rather than printing it.
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.
\$\endgroup\$
  • \$\begingroup\$ I'm not sure what the pattern is regarding the order in which the trees are drawn. That is, given n, what are the positions of the trees? \$\endgroup\$ – Luis Mendo Feb 10 '17 at 21:29
  • \$\begingroup\$ @LuisMendo As I understand, they are filled in reading order. So, each row is filled in turn, and if there's not enough trees for the whole row, the remainder are placed as far left as possible in that row. \$\endgroup\$ – xnor Feb 10 '17 at 21:34
  • \$\begingroup\$ @LuisMendo xnor has it right. If I can re-word that to make it more clear, please ping me in chat. \$\endgroup\$ – AdmBorkBork Feb 10 '17 at 21:35
  • \$\begingroup\$ @xnor Thanks, it's totally clear to me now \$\endgroup\$ – Luis Mendo Feb 10 '17 at 21:59
  • \$\begingroup\$ @Adm Actually it was written right there in the challenge. Apparently I can't read :-) \$\endgroup\$ – Luis Mendo Feb 10 '17 at 22:01
5
\$\begingroup\$

Haskell 310 bytes

w i=putStr$unlines$reverse$b i 0 0[][]
b 0 _ _ w r=e w r
b c l 0 w r=b c(l+1)l(e w r)[]
b c l p w r=b(c-1)l(p-1)w(n(++)["  ||    ","  ||    ","///\\\\\\  "," //\\\\   ","  /\\    "]r)
e w r=t++n(n d)(map(\t->"    "++t)w)c where(t,c)=splitAt 2 r
n f(a:c)(b:d)=f a b:n f c d
n _ a[]=a
n _ _ a=a
d d ' '=d
d _ d=d

Call it with w 5, for example.

Here the uncompressed code:

-- TreeTree
-- by Gerhard
-- 12 February 2017

module TreeTree (wood,test) where

type Tree = [String]

-- Test cases
test = do
 wood 0
 wood 1
 wood 2
 wood 3
 wood 4
 wood 5

-- build wood
wood :: Int -> IO ()
wood i = printTree $ buildWood i 0 0 [] []

-- Prints the trees
printTree :: Tree -> IO ()
printTree = putStr . unlines . reverse

-- build wood
buildWood :: Int -> Int -> Int -> Tree -> Tree -> Tree
buildWood 0 _ _ w r = concatTree w r 
buildWood c l 0 w r = buildWood c (l+1) l (concatTree w r) []
buildWood c l p w r = buildWood (c-1) l (p-1) w (addTree r)

-- indent definition
space :: String
space = "    "

-- tree definition
tree :: Tree
tree = reverse [
 "  /\\    ",
 " //\\\\   ",
 "///\\\\\\  ",
 "  ||    ",
 "  ||    "]

-- Add a Tree on the left side
addTree :: Tree -> Tree
addTree = match (++) tree

-- add tree row at the bottom of the wood
concatTree :: Tree -> Tree -> Tree
concatTree w r = trunk ++ matched
 where
  wood = grow w
  (trunk, crown) = splitAt 2 r 
  matched = matchTree wood crown

-- elnarge forrest on the left side to match next tree line
grow :: Tree -> Tree
grow = map (\t -> space ++ t)

-- match
match :: (a -> a -> a) -> [a] -> [a] -> [a]
match f (a:az) (b:bz) = f a b : match f az bz
match _ a [] = a
match _ _ a  = a

-- match trees
matchTree :: Tree -> Tree -> Tree
matchTree = match matchLine

-- match lines
matchLine :: String -> String -> String
matchLine = match matchChar

-- match chars
matchChar :: Char -> Char -> Char
matchChar c ' ' = c
matchChar _ c   = c

-- End
\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ – AdmBorkBork Feb 13 '17 at 13:17
4
\$\begingroup\$

JavaScript (ES6), 357 297 276 bytes

f=
n=>{a=`  /\\`;d=`///\\\\\\`;b=d+`/\\`;c=` //\\\\ ||`;d+=`||`;e=`
`;r=`repeat`;s=``;for(i=1;n>i;n-=i++)s=(s+a+b[r](i-1)+e+c[r](i)).replace(/^/gm,`    `)+e;return(s+a+b[r](n-1)+d[r](i-=n)+e+c[r](n)+(s=`      ||`[r](i))+e+d[r](n)+s+(s=e+`  ||    `[r](n))+s).replace(/\|.$/gm,``)}
<input type=number min=1 oninput=o.textContent=f(this.value)><pre id=o>

Edit: Saved 21 bytes thanks to @KritixiLithos.

\$\endgroup\$
  • \$\begingroup\$ For the first repeat, you can change blah.repeat(val) to blah[w="repeat"](val) and then you can change the subsequent occurences of repeat to just [w](val) instead to save bytes \$\endgroup\$ – Cows quack Feb 12 '17 at 7:46
  • \$\begingroup\$ @KritixiLithos I can't quite do that because the first repeat is inside the for loop and won't run for n=1, but I was still able to save 21 bytes. \$\endgroup\$ – Neil Feb 12 '17 at 10:53
4
\$\begingroup\$

C++ (on Windows), 330 312 308 304 303 bytes

#import<cstdio>
#import<windows.h>
#define P(x,y,s)SetConsoleCursorPosition(GetStdHandle(-11),{X+x,Y+y});puts(s);
int X,Y,R,r,c;t(){P(2,-2,"/\\")P(1,-1,"//\\\\")P(0,0,"///\\\\\\")P(2,1,"||")P(2,2,"||")}f(int n){for(c=R=r=1;c<n;c+=++R);for(;r;r++)for(c=0;++c<r+1;){X=(R-r-2)*4+c*8;Y=r*2;t();r=--n?r:-1;}}

Call with:

int main()
{
    f(8);
}
\$\endgroup\$
0
\$\begingroup\$

C (on Windows), 297 295 294 bytes

#import<windows.h>
#define P(x,y,s)C.X=X+x;C.Y=Y+y;SetConsoleCursorPosition(GetStdHandle(-11),C);puts(s);
COORD C;X,Y,R,r,c;t(){P(2,-2,"/\\")P(1,-1,"//\\\\")P(0,0,"///\\\\\\")P(2,1,"||")P(2,2,"||")}f(n){for(c=R=r=1;c<n;c+=++R);for(;r;r++)for(c=0;++c<r+1;){X=(R-r-2)*4+c*8;Y=r*2;t(r=--n?r:-1);}}

Similar to my C++ answer, but I posted this because it's somewhat shorter in C.

\$\endgroup\$
  • \$\begingroup\$ @DLosc It's C. #import is a (deprecated) GCC extension. Fit for golfing, though. \$\endgroup\$ – Steadybox Feb 11 '17 at 22:29
  • \$\begingroup\$ Huh, interesting. Now I see that there's a tip for that. You might mention that in your answer. \$\endgroup\$ – DLosc Feb 11 '17 at 22:33
  • \$\begingroup\$ @DLosc Perhaps, but I think it's quite widely used in golfing, along with some other GCC (though not limited to GCC) extensions like omitting <stdio.h> and automatically assuming a global variable to be int or a function to return int. \$\endgroup\$ – Steadybox Feb 11 '17 at 22:42
0
\$\begingroup\$

Javascript 418 377 bytes

Thanks to @Kritixi Lithos for helping golf off 39 bytes

x=>{s='';for(t=0;++t<x;x-=t);q='//\\\\';z="///\\\\\\";h="/\\";t--;for(i=0;i<t;i++){a=4*(t-i)+1;s+=" "[w="repeat"](a+1)+h+(z+h)[w](i)+`
`+" "[w](a)+q+(" || "+q)[w](i)+`
`}c=t-x+1>0?t-x+1:0;return x?s+"  "+(h+z)[w](--x)+h+(c?(z+"||")[w](c-1)+z:'')+`
 `+q+(" || "+q)[w](x)+" ||     "[w](c)+`
`+(z+"||")[w](x)+z+(c?"||"+"      ||"[w](c-1):'')+`
`+("  ||    "[w](x+1)+`
`)[w](2):''}

Try it Online

\$\endgroup\$
  • 2
    \$\begingroup\$ For the first repeat, you can change blah.repeat(val) to blah[w="repeat"](val) and then you can change the subsequent occurences of repeat to just [w](val) instead to save bytes \$\endgroup\$ – Cows quack Feb 11 '17 at 7:16

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.