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\$
5
  • \$\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
    Commented Feb 10, 2017 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
    Commented Feb 10, 2017 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\$ Commented Feb 10, 2017 at 21:35
  • \$\begingroup\$ @xnor Thanks, it's totally clear to me now \$\endgroup\$
    – Luis Mendo
    Commented Feb 10, 2017 at 21:59
  • \$\begingroup\$ @Adm Actually it was written right there in the challenge. Apparently I can't read :-) \$\endgroup\$
    – Luis Mendo
    Commented Feb 10, 2017 at 22:01

5 Answers 5

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\$
1
  • \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ Commented Feb 13, 2017 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\$
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\$
    – user41805
    Commented Feb 12, 2017 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
    Commented Feb 12, 2017 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\$
1
\$\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\$
1
  • 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\$
    – user41805
    Commented Feb 11, 2017 at 7:16
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\$
3
  • \$\begingroup\$ @DLosc It's C. #import is a (deprecated) GCC extension. Fit for golfing, though. \$\endgroup\$
    – Steadybox
    Commented Feb 11, 2017 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
    Commented Feb 11, 2017 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
    Commented Feb 11, 2017 at 22:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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