Desenhe uma série de cadeias de montanhas

16

Inspirado pelo ladrilho de dominó de Fibonacci , esse problema é sobre a geração de arte ASCII representando outra famosa seqüência combinatória.

Um diagrama de montanha em n etapas é um desenho de uma cadeia de montanhas, usando exatamente n '/' e n '\', de modo que os caracteres desenhem uma curva contínua que nunca cai abaixo de sua "altitude" inicial. Por exemplo,

   /\/\
/\/    \

e

   /\
/\/  \/\

são ambos diagramas de montanha em quatro etapas, mas

/\  /\/\
  \/

não é.

Entrada

O programa deve aceitar um número inteiro n de stdin ou como parâmetro para uma função.

Resultado

Imprima todos os diagramas de montanha n- step para stdout. Os diagramas podem estar em qualquer ordem, mas devem ser separados por algum tipo de espaço em branco. Você pode decidir se diferentes diagramas serão exibidos horizontalmente, verticalmente etc.

Como no problema de dominó, você pode usar qualquer espaço em branco que desejar. Isso inclui novas linhas extras antes ou depois da saída impressa.

Exemplo

Algumas amostras de saídas válidas para n = 3:

Saída válida A:

                                        /\
         /\             /\             /  \    /\/\
/\/\/\  /  \/\       /\/  \           /    \  /    \

Saída B válida:

   /\
/\/  \

 /\/\
/    \

/\/\/\   

  /\
 /  \
/    \

 /\
/  \/\

Saída válida C:

  /\
 /  \       /\
/    \   /\/  \
                  /\/\
 /\              /    \
/  \/\   /\/\/\

Isso é código de golfe; o programa mais curto (em bytes) vence.

Matt Noonan
fonte
Quando você diz "Você pode decidir se diferentes diagramas serão exibidos horizontalmente, verticalmente etc.", as cadeias de montanhas podem estar de lado?
xnor
As cadeias de montanhas em si não devem ficar de lado. Os céus vazios entre os picos aumentam o desafio, eu acho.
precisa saber é o seguinte
Alguns intervalos podem aparecer mais de uma vez?
proud haskeller
@MattNoonan Você está certo, imprimir as montanhas horizontalmente foi definitivamente complicado.
xnor
@ proud-haskeller Deve ser uma vez cada.
Matt Noonan

Respostas:

10

Python 2: 151 caracteres

N=2*input()
for i in range(2**N):
 L=[];c=1;exec"b=i%2;c+=2*b-1;L+=[[' ']*N];L[-1][b-c]='\/'[b];i=i/2*(c>0);"*N
 for x in(c==1)*zip(*L):print"".join(x)

#Output for n=3:




  /\  
 /  \ 
/    \




 /\/\ 
/    \




   /\ 
/\/  \




 /\   
/  \/\





/\/\/\

Uau, isso é uma bagunça.

A primeira idéia é usar os números 0 to 2**N-1para codificar todas as sequências de Nmovimentos para cima e para baixo em seus bits. Lemos esses bits um por um repetidos %2e /2iterados em um execloop.

Armazenamos a cadeia de montanhas lateralmente em uma lista de cordas transposta L. Cada vez que geramos uma nova linha de espaços, substituímos um espaço na nova linha por /ou \dependendo de uma movimentação para cima ou para baixo.

O índice desse espaço são cespaços do final, onde cestá a altura de execução. Fazer isso de frente faria as montanhas de cabeça para baixo. Nós o deslocamos ainda mais bpara alinhar movimentos para cima e para baixo, obtendo [b-c]. Começar ccom 1 em vez de 0 corrige um erro de um por um.

Para eliminar os casos em que ccaem abaixo do valor inicial 1, quando isso acontece, definimos icomo 0, o que faz com que todos os outros movimentos sejam descendentes, tornando- cse mais negativos. Então, quando verificamos se cterminou em 1, também verificamos se calguma vez caiu abaixo dela. Nós apenas printa cordilheira se cé 1.

Para imprimir, é zip(*L)necessário transpor o intervalo da vertical para a horizontal e imprimir cada sequência de caracteres unida. Muitos problemas nesta resposta vieram das seqüências de caracteres do Python como imutáveis, por isso trabalhamos com elas como listas de caracteres e as juntamos apenas em strings para impressão.

Obrigado a @flornquake pela ajuda e melhorias.

xnor
fonte
Você precisará usar em ' 'vez de " "se desejar fazer um loop usando exec. :) Btw, você não precisa escapar da barra invertida.
Flornquake 18/09/14
@flornquake eu esqueci de escrever, eu usei ' 'e tentei substituir a string por aspas por uma variável. Isso ainda deu o índice fora do intervalo:for _ in[0]*N:exec("b=i%2;c+=2*b-1;L+=[[" "]*N];L[-1][b-c]='\\/'[b];i=i//2*(c>0);")
xnor
Eu quis dizer que você precisa escrever exec("b=i%2;c+=2*b-1;L+=[[' ']*N];L[-1][b-c]='\\/'[b];i=i//2*(c>0);"), ou seja, as aspas internas devem ser diferentes das exteriores.
Flornquake 18/09/14
@flornquake Uau, eu me sinto boba, mudei um par de citações, mas não o outro. Obrigado!
Xnor
7

APL (88)

{{⍉↑'\/'[1+⍵=1]/⍨¨¯1+2×K=⊂⌽⍳⌈/K←(⍵≠1)++\⍵}¨Z/⍨{(0=+/⍵)∧∧/0≤+\⍵}¨Z←↓⍉¯1+2×(N/2)⊤⍳2*N←2×⍵}

Saída para n=3:

      {{⍉↑'\/'[1+⍵=1]/⍨¨¯1+2×K=⊂⌽⍳⌈/K←(⍵≠1)++\⍵}¨Z/⍨{(0=+/⍵)∧∧/0≤+\⍵}¨Z←↓⍉¯1+2×(N/2)⊤⍳2*N←2×⍵}3
 /\/\/\     /\    /\      /\/\     /\   
         /\/  \  /  \/\  /    \   /  \  
                                 /    \ 

Explicação:

  • (N/2)⊤⍳2*N←2×⍵: obtenha um campo de bits para cada número de 0a 2^⍵.
  • Z←↓⍉¯1+2×: multiplique por 2 e subtraia 1, dando 1para cima e -1para baixo. Armazenar um vector de vectores, cada um vector que contém a representação de um número, em Z.
  • {... }¨Z: para cada elemento de Z:
    • ∧/0≤+\⍵: verifique se a soma atual nunca cai abaixo 0(não fica abaixo do nível do solo),
    • (0=+/⍵): e que a soma total é 0(termina no nível do solo).
  • {... }¨Z/⍨: selecione os elementos Zpara os quais isso é verdade. Para cada um deles:
    • K←(⍵≠1)++\⍵: encontre a altura de cada personagem e armazene-a K. Levante cada \uma delas, para que elas se alinhem com os /s corretamente. Isso torna a altura do solo 1.
    • ¯1+2×K=⊂⌽⍳⌈/K: para cada coluna, faça uma lista [1..max(K)]e marque a posição do caractere nessa coluna com 1e o restante como -1. A replicação em -1 preenche essa posição com um espaço.
    • '\/'[1+⍵=1]/⍨¨: encontre o caractere correto para cada coluna e replique-o pela lista dessa coluna.
    • ⍉↑: transforme o resultado em uma matriz e coloque-o com o lado direito para cima
marinus
fonte
Tudo bem, uma horizontal!
Matt Noonan
2

Python, 261 241 236 caracteres

import itertools as I
n=input()
S={}
for q in I.permutations((-1,1)*n):
 s=0;B=[[' ']*n*2 for _ in range(n+2)];o=0
 for i in q:
    B[n-s+(i==-1)][o]=' /\\'[i];s+=i;o+=1
    if s<0:break
 else:
    for l in (B,[])[q in S]:print''.join(l)
 S[q]=1

Começa a demorar um pouco para n=5subir ...

$ echo 1 | py mountrange.py

/\



Laxori@Laxori-PC /cygdrive/c/Programmin
$ echo 2 | py mountrange.py


/\/\



 /\
/  \



Laxori@Laxori-PC /cygdrive/c/Programmin
$ echo 3 | py mountrange.py



/\/\/\




   /\
/\/  \




 /\
/  \/\




 /\/\
/    \



  /\
 /  \
/    \



Laxori@Laxori-PC /cygdrive/c/Programmin
$ echo 4 | py mountrange.py




/\/\/\/\





     /\
/\/\/  \





   /\
/\/  \/\





   /\/\
/\/    \




    /\
   /  \
/\/    \





 /\
/  \/\/\





 /\  /\
/  \/  \





 /\/\
/    \/\





 /\/\/\
/      \




    /\
 /\/  \
/      \




  /\
 /  \
/    \/\




  /\
 /  \/\
/      \




  /\/\
 /    \
/      \



   /\
  /  \
 /    \
/      \
Claudiu
fonte
2

JavaScript (ES6) 159 163

Assim como minha resposta para Fibonacci Domino Tiling, eu examino todas as seqüências de n + n bits, com 1 marcando um '/' e 0 marcando um '\' (apenas para a saída, '2' é adicionado posteriormente para marcar uma nova linha) . Ao construir esse padrão ASCII, verifico o saldo - os mesmos números de 0 e 1 e nunca abaixo da linha de base - e mostro o que obedece às regras.

Saída feita com 'alert', que é padrão para o codegolf JS, mas bastante irritante e talvez contra as regras. Usando console.log, a contagem de caracteres vai para 165.

F=n=>{
  for(i=0;++i<1<<n+n;l||alert((o+'').replace(/,\d?/g,r=>'\\/\n '[r[1]||3])))
    for(p=l=o=[],j=i;l+1&&p++-n-n;j/=2)
      b=j&1,
      l-=1-b-b,
      (o[k=b+n-l]=o[k]||[2])[p]=b;
}

Menos golfe

F=n=>{
  m = n+n
  outer:
  for (i=1; i < 1<<m; i+=2)
  {
    o=[]
    l=0;
    p=1;
    for (j = 1; j <1<<m; j+=j,p++)
    {
      if (i&j)
      {
        q=o[n-l]||[]
        q[p]=1;
        o[n-l]=q
        ++l;
      }
      else
      {
        --l;
        if (l<0) continue outer;
        q=o[n-l]||[]
        q[p]=0;
        o[n-l]=q
      }
    }
    if (l==0) console.log(o.join('\n').replace(/,\d?/g,r=>'\\/'[r[1]]||' '));
  }
}

Teste no console do FireFox / FireBug.

F(4)

Resultado

   /\
  /  \
 /    \
/      \ 

  /\/\
 /    \
/      \ 

    /\
 /\/  \
/      \ 

    /\
   /  \
/\/    \ 

  /\
 /  \/\
/      \ 

 /\/\/\
/      \ 

   /\/\
/\/    \ 

 /\  /\
/  \/  \ 

     /\
/\/\/  \ 

  /\
 /  \
/    \/\ 

 /\/\
/    \/\ 

   /\
/\/  \/\ 

 /\
/  \/\/\ 

/\/\/\/\ 
edc65
fonte
Curioso se houver algum motivo específico para você escrever -b-be -n-nnão -2*b?
Steve Bennett
@SteveBennett sem motivo. Às vezes, esse padrão é mais curto, mas não desta vez (por exemplo: 2*b+1->b-~b )
edc65
1

CJam, 84 bytes

q~:Q{Q[XW]*mr1\{\_@+}%_{*}*{(\{_Q\-)S*@2$m0<" /""\\"?+QS*+Q)<\}%);z{N\++}*o}{;}?1}g

Observe que este programa imprime as montanhas em um loop infinito para que o intérprete online não o ajude; chamar na linha de comando usando

java -jar cjam-0.6.2.jar mountain.cjam <<< 5

ou para tentar usar on-line

q~:Q{Q[XW]*mr1\{\_@+}%_{*}*{(\{_Q\-)S*@2$m0<" /""\\"?+QS*+Q)<\}%);z{N\++}*o}{;}?}fZ

e basta pressionar o botão executar várias vezes seguidas e imaginar que a saída é concatenada.

A idéia básica é que sabemos que uma cadeia de montanhas de tamanho Q tem Q de cada transição para cima e para baixo.

 Q[XW]*mr                                   #shuffled list of Q 1s and -1s
1        {\_@+}%                            #height map after each transition
                _{*}*                       #if it passes through 0 it's invalid

Então, se for válido, imprimi-lo, caso contrário, o retiramos da pilha para que não transborde.

O roteamento de impressão basicamente constrói cada coluna como espaços Q - altura, depois o símbolo, mais espaços suficientes para atingir Q + 1 total de caracteres e, em seguida, transpomos e imprimimos as linhas com novas linhas entre eles.

z{N\++}*o                                   #transpose, insert newlines, print
paradigmsort
fonte
Enquanto eu trabalhava nisso, a questão foi esclarecida para exigir que as montanhas fossem impressas uma vez cada. Isso exigirá repensar e provavelmente mais caracteres: /
paradigmsort
0

C, 179

excluindo espaços em branco desnecessários.

Uma estratégia semelhante ao edc65. Eu corro todos os n*2valores binários de -bit, considerando /= 1 e\ = 0.

Eu formato uma única string contendo nquebras de linha todos os n*3caracteres. Como foi escrita, a string contém 1000 caracteres; portanto, geralmente há muito espaço em branco impresso após a montanha. (Isso pode ser corrigido adicionando s[n*n*3]=0antes do puts.) De qualquer forma, isso me permite gerar toda a montanha com um únicoputs depois de verificar se ela está em conformidade com as regras.

Vou tentar convertê-lo em uma função e reduzir para um único forloop mais tarde.

i,n,x,y,q,r;
main(){
  scanf("%d",&n);
  for(i=1<<n*2;i--;){                              //run though all n*2-digit binary numbers
    char s[]={[0 ...999]=32};                      //fill an array with spaces. This syntax is allowed by GCC
    y=n;                                           //start y one square below the grid (note: r is initialised to 0 by default.)
    for(x=n*2;x--;)                                //for each digit of i
      q=i>>x&1,
      y+=q+r-1,                                    //move up if the current and last digit are 0, down if they are 1, and stay on the same line if they are different.
      y<n?s[y*n*3]=10,s[y*n*3+x+1]=92-45*q:(x=0),  //if y is within the grid, put a newline (ASCII 10)at the beginning of the row and write \ or / (ASCII 92 or 47) to the correct square. Otherwise abort the x loop.
      r=q;                                         //store the current bit of i to r as it will be needed on the next iteration 
    n-1-y||puts(s);                                //if y is on the bottom row of the grid, output the mountain 
  }
}

Saída (observe a enorme quantidade de espaço em branco à direita)

$ ./a
4

 /\
/  \/\/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

   /\
/\/  \/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

 /\/\
/    \/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

  /\
 /  \
/    \/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

     /\
/\/\/  \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

 /\  /\
/  \/  \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

   /\/\
/\/    \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

 /\/\/\
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

  /\
 /  \/\
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

    /\
   /  \
/\/    \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

    /\
 /\/  \
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

  /\/\
 /    \
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

   /\
  /  \
 /    \
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
Level River St
fonte
0

Haskell, 140 bytes

Depois que várias tentativas falharam em ser muito jogáveis, acabei com essa implementação do Haskell. Estou feliz por estar dentro de um fator de 2 da solução APL!

Solução Golfed:

e=' ':e
m=[[]]:[[('/':e):map(' ':)x++('\\':e):y|k<-[0..n],x<-m!!(n-k),y<-m!!k]|n<-[0..]]
f n=putStr$unlines[map(!!(n-k))a|a<-m!!n,k<-[1..n]]

Ungolfed e comentou:

O programa constrói o conjunto de diagramas de montanha n- step recursivamente. Cada diagrama é representado por uma lista de cadeias infinitamente longas, representando a montanha desenhada de lado, seguida por espaços que se estendem até o infinito. Isso garante que todos os diagramas tenham a mesma altura, o que facilita a recursão. A impressora de montanha aceita um parâmetro que fixa a altura a um valor finito.

import Data.List (transpose)

-- Elementary picture slices, extending to infinity.
empty = ' ' : empty
up    = '/' : empty
down  = '\\': empty

-- A function which draws a mountain picture to stdout, clipping
-- its height to n.
printMtn n = putStr . unlines . reverse . take n . transpose 

{-- Combine mountain pictures x and y by

              x
 x # y  ==   / \y

--}
x # y = up : raised x ++ down : y
    where raised = map (' ':)

-- Given two sets X,Y of mountain pictures, compute the set X <> Y of all
-- combined pictures x#y for x in X, y in Y.
xs <> ys = [ x # y | x <- xs, y <- ys ]

-- Compute the (++,<>)-convolution of a list with itself, e.g.:
--   autoConvolve [x0,x1,x2] == (x2 <> x0) ++ (x1 <> x1) ++ (x0 <> x2)
autoConvolve xs = concat $ zipWith (<>) (reverse xs) xs

{--
    mtns is a list whose nth entry is the list of all n-step mountain diagrams.
    It is defined recursively by:
        --  The only 0-step mountain diagram is empty.
        --  Each (n+1)-step diagram can be uniquely drawn as x#y for
            some k-step diagram x and (n-k)-step diagram y.
--}
mtns = [[]] : [autoConvolve (prefix n) | n <- [1..]]
    where prefix n = take n mtns

-- The driver function: apply the height n mountain printer to each
-- n-step mountain diagram.  Whitespace is guaranteed by the order
-- in which the diagrams appear.
test n = mapM_ (printMtn n) $ mtns!!n

Uso da amostra:

$ ghci mtn3.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( mtn3.hs, interpreted )
Ok, modules loaded: Main.
λ> f 3
  /\  
 /  \ 
/    \

 /\/\ 
/    \

 /\   
/  \/\

   /\ 
/\/  \


/\/\/\
λ> 
Matt Noonan
fonte
0

GolfScript 103 ( demo )

2*:§2\?,{2base.,§\-[0]*\+:a 1\{.2*@(.@+@@+}%:l$)\;),-1%{a,,{.l=2$=\a=1$+*' \\/'= }%\;n+}%\1=*l$(\;0>*}/

O programa usa um parâmetro inteiro tenta renderizar como montanhas todas as representações binárias dos números de 0 a 2 ^ (n-1). Não gera combinações inválidas (por exemplo, as que ficam abaixo do nível 0).

Cristian Lupascu
fonte