Não posso ver a floresta para as árvores

29

Escreva um programa ou função que desenhe uma árvore de árvores, construindo assim uma floresta.

As árvores são desenhadas como empilhar uma pirâmide. A primeira linha (superior) contém 1árvore, a próxima linha contém 2(para um total de 3), a próxima contém 3(para um total de 6) e assim por diante. Se não houver árvores suficientes para completar uma linha completa, preencha-a à esquerda e deixe as manchas à direita vazias. Além disso, as árvores de nível inferior se sobrepõem levemente às árvores de nível superior devido à sua localização.

Esta é uma floresta de tamanho 1

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

Esta é uma floresta de tamanho 2

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

Esta é uma floresta de tamanho 3

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

Esta é uma floresta de tamanho 4

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

Esta é uma floresta de tamanho 5(observe que o topo da quinta árvore está cobrindo o tronco da primeira árvore)

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

(pule algumas)
Esta é uma floresta de tamanho 8(estendendo o padrão)

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

e assim por diante.

Entrada

Um número inteiro positivo único em qualquer formato conveniente , n > 0.

Saída

Uma representação da floresta em arte ASCII, seguindo as regras acima. Novas linhas à esquerda / à direita ou outro espaço em branco são opcionais, desde que todas as árvores se alinhem adequadamente.

Regras

  • Um programa completo ou uma função são aceitáveis. Se uma função, você pode retornar a saída em vez de imprimi-la.
  • As brechas padrão são proibidas.
  • Isso é portanto todas as regras usuais de golfe se aplicam e o código mais curto (em bytes) vence.
AdmBorkBork
fonte
Não sei ao certo qual é o padrão em relação à ordem em que as árvores são desenhadas. Ou seja, nquais são as posições das árvores?
Luis Mendo
@LuisMendo Pelo que entendi, eles são preenchidos em ordem de leitura. Portanto, cada linha é preenchida por sua vez e, se não houver árvores suficientes para toda a linha, o restante será colocado o mais à esquerda possível nessa linha.
Xnor
@LuisMendo xnor está certo. Se eu puder reformular isso para torná-lo mais claro, faça um ping no meu bate-papo.
AdmBorkBork
@xnor Graças, é totalmente claro para mim agora
Luis Mendo
@Adm Na verdade, foi escrito ali mesmo no desafio. Aparentemente eu não posso ler :-)
Luis Mendo

Respostas:

5

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

Ligue com w 5, por exemplo.

Aqui o código não compactado:

-- 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
Gerhard
fonte
Bem-vindo ao PPCG!
AdmBorkBork
4

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>

Editar: salvou 21 bytes graças a @KritixiLithos.

Neil
fonte
Para o primeiro repeat, você pode alterar blah.repeat(val)para blah[w="repeat"](val) e, em seguida, alterar as ocorrências subsequentes de repeatpara apenas [w](val)para salvar bytes
Kritixi Lithos
@KritixiLithos Não consigo fazer isso porque o primeiro repeatestá dentro do forloop e não será executado n=1, mas ainda assim pude salvar 21 bytes.
Neil
4

C ++ (no 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;}}

Ligue para:

int main()
{
    f(8);
}
Steadybox
fonte
0

C (no 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);}}

Semelhante à minha resposta em C ++, mas eu postei isso porque é um pouco menor em C.

Steadybox
fonte
@DLosc É C. #importé uma extensão (obsoleta) do GCC. Adequado para jogar golfe, no entanto.
Steadybox
Huh, interessante. Agora vejo que há uma dica para isso. Você pode mencionar isso na sua resposta.
11487 DLosc #
@DLosc Talvez, mas acho que é bastante utilizado no golfe, juntamente com outras extensões do GCC (embora não limitadas ao GCC), como omitir <stdio.h>e assumir automaticamente uma variável global como sendo intuma função a retornar int.
Steadybox
0

Javascript 418 377 bytes

Obrigado a @Kritixi Lithos por ajudar no golfe com 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):''}

Experimente Online

fəˈnɛtɪk
fonte
2
Para o primeiro repeat, você pode alterar blah.repeat(val)para blah[w="repeat"](val)e, em seguida, alterar as ocorrências subsequentes de repeatpara apenas [w](val)salvar os bytes
Kritixi Lithos