Dibuja un rango de cordilleras

16

Inspirado en el mosaico de dominó de Fibonacci , este problema se trata de generar arte ASCII que represente otra famosa secuencia combinatoria.

Un diagrama de montaña de n pasos es un dibujo de una cadena montañosa, que usa exactamente caracteres n '/' y n '\', de modo que los personajes dibujan una curva continua que nunca cae por debajo de su "altitud" inicial. Por ejemplo,

   /\/\
/\/    \

y

   /\
/\/  \/\

son diagramas de montaña de 4 pasos, pero

/\  /\/\
  \/

no es.

Entrada

El programa debe aceptar un número entero n desde stdin o como parámetro para una función.

Salida

Imprima todos los diagramas de montaña n -step en stdout. Los diagramas pueden estar en cualquier orden, pero deben estar separados por algún tipo de espacio en blanco. Puede decidir si se generarán diferentes diagramas horizontal, vertical, etc.

Como en el problema del mosaico de dominó, puede usar cualquier espacio en blanco que desee. Esto incluye nuevas líneas adicionales antes o después de la salida impresa.

Ejemplo

Algunas salidas válidas de muestra para n = 3:

Salida válida A:

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

Salida válida B:

   /\
/\/  \

 /\/\
/    \

/\/\/\   

  /\
 /  \
/    \

 /\
/  \/\

Salida válida C:

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

Este es el código de golf; el programa más corto (en bytes) gana.

Matt Noonan
fuente
Cuando dice "Puede decidir si se generarán diagramas diferentes horizontalmente, verticalmente, etc.", ¿pueden las cadenas montañosas mismas estar de lado?
xnor
Las sierras en sí mismas no deberían estar de lado. Creo que los cielos vacíos entre picos se suman al desafío.
Matt Noonan
¿Pueden aparecer algunos rangos más de una vez?
orgulloso Haskeller
@MattNoonan Tienes razón, imprimir las cadenas montañosas horizontalmente fue definitivamente complicado.
xnor
@ proud-haskeller Debería ser una vez cada uno.
Matt Noonan

Respuestas:

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:




  /\  
 /  \ 
/    \




 /\/\ 
/    \




   /\ 
/\/  \




 /\   
/  \/\





/\/\/\

Wow, esto es un desastre.

La primera idea es usar los números 0 to 2**N-1para codificar todas las secuencias de Nmovimientos ascendentes y descendentes en sus bits. Leemos estos bits uno por uno por repetidos %2e /2iterados en un execbucle.

Almacenamos la cordillera corriendo lateralmente en una lista transpuesta de cadenas L. Cada vez, generamos una nueva fila de espacios y reemplazamos un espacio en la nueva fila con /o \dependiendo de si ocurrió un movimiento hacia arriba o hacia abajo.

El índice de ese espacio es cespacios desde el final, donde cestá la altura de carrera. Hacerlo desde el frente pondría las montañas al revés. Lo cambiamos aún más bpara alinear movimientos hacia arriba y hacia abajo, obteniendo [b-c]. Comenzar cen 1 en lugar de 0 corrige un error fuera de uno.

Para eliminar los casos en los que las cinmersiones están por debajo del valor inicial 1, cuando esto sucede, establecemos ien 0, lo que hace que todos los movimientos adicionales sean hacia abajo, lo que hace que csea ​​más negativo. Luego, cuando verificamos si cterminó en 1, también verificamos si calguna vez cayó por debajo de él. Solo tenemos printla cordillera si ces así 1.

Para imprimir, hacemos la zip(*L)transposición del rango de vertical a horizontal, e imprimimos cada cadena unida. Muchos problemas en esta respuesta provienen de que Python trata las cadenas como inmutables, por lo que trabajamos con ellas como listas de caracteres y solo las unimos en cadenas para imprimirlas.

Gracias a @flornquake por su ayuda y mejoras.

xnor
fuente
Tendrá que usar en ' 'lugar de " "si desea usar el bucle exec. :) Por cierto, no necesitas escapar de la barra invertida.
flornquake
@flornquake Olvidé escribir, usé ' 'e intenté reemplazar la cadena con comillas con una variable. Esto todavía dio un índice fuera de rango: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
Quise decir que necesitas escribir exec("b=i%2;c+=2*b-1;L+=[[' ']*N];L[-1][b-c]='\\/'[b];i=i//2*(c>0);"), es decir, las citas internas deben ser diferentes de las externas.
flornquake
@flornquake Wow me siento tonto, cambié un par de citas pero no el otro. ¡Gracias!
xnor
7

APL (88)

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

Salida para n=3:

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

Explicación:

  • (N/2)⊤⍳2*N←2×⍵: obtener un campo de bits para cada número de 0a 2^⍵.
  • Z←↓⍉¯1+2×: multiplica por 2 y resta 1, dando 1por arriba y -1por abajo. Almacene un vector de vectores, cada vector que contiene la representación de un número, en Z.
  • {... }¨Z: para cada elemento de Z:
    • ∧/0≤+\⍵: compruebe que la suma acumulada nunca cae por debajo 0(no va por debajo del nivel del suelo),
    • (0=+/⍵): y que la suma total es 0(termina a nivel del suelo).
  • {... }¨Z/⍨: selecciona aquellos elementos Zpara los que eso es cierto. Para cada uno de ellos:
    • K←(⍵≠1)++\⍵: encuentra la altura de cada personaje y guárdalo K. Levante cada \una para que se alineen con la /s correctamente. Esto hace que la altura del suelo 1.
    • ¯1+2×K=⊂⌽⍳⌈/K: para cada columna, haga una lista [1..max(K)]y marque la posición del personaje en esa columna con 1y el resto como -1. (Replicar por -1 llena esa posición con un espacio).
    • '\/'[1+⍵=1]/⍨¨: encuentre el carácter correcto para cada columna y repítalo por la lista de esa columna.
    • ⍉↑: convierte el resultado en una matriz y lo coloca al revés
marinus
fuente
Muy bien, uno 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

Empieza a tardar un rato para n=5arriba ...

$ 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
fuente
2

JavaScript (ES6) 159 163

Al igual que mi respuesta para el mosaico de dominó de Fibonacci, examino todas las secuencias de n + n bits, con 1 marcando un '/' y 0 marcando un '\' (solo para la salida, luego se agrega '2' para marcar una nueva línea) . Mientras construyo el patrón ASCII, verifico el equilibrio, los mismos números de 0 y 1, y nunca voy por debajo de la línea base inicial, y obtengo lo que obedece las reglas.

Salida realizada con 'alerta', que es estándar para el codegolf JS pero bastante molesto, y tal vez en contra de las reglas. Usando console.log, el recuento de caracteres va a 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 golf

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]]||' '));
  }
}

Prueba en la consola FireFox / FireBug.

F(4)

Salida

   /\
  /  \
 /    \
/      \ 

  /\/\
 /    \
/      \ 

    /\
 /\/  \
/      \ 

    /\
   /  \
/\/    \ 

  /\
 /  \/\
/      \ 

 /\/\/\
/      \ 

   /\/\
/\/    \ 

 /\  /\
/  \/  \ 

     /\
/\/\/  \ 

  /\
 /  \
/    \/\ 

 /\/\
/    \/\ 

   /\
/\/  \/\ 

 /\
/  \/\/\ 

/\/\/\/\ 
edc65
fuente
¿Curioso si hay alguna razón en particular para escribir -b-by en -n-nlugar de -2*b?
Steve Bennett
@SteveBennett no hay razón. A veces este patrón es más corto, pero no esta vez (por ejemplo: 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

Tenga en cuenta que este programa imprime las montañas en un bucle infinito para que el intérprete en línea no lo ayude; invocar en la línea de comando usando

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

o para probar el uso en línea

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

y simplemente presione el botón de ejecución varias veces seguidas e imagine que la salida se concatena.

La idea básica es que sabemos que una cadena montañosa de tamaño Q tiene Q de cada transición hacia arriba y hacia abajo.

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

Luego, si es válido, lo imprimimos, si no, lo sacamos de la pila para que no se desborde.

La ruta de impresión básicamente construye cada columna como Q - espacios de altura, luego el símbolo, luego suficientes espacios para golpear Q + 1 caracteres en total, y luego transponemos e imprimimos las líneas con líneas nuevas entre ellos.

z{N\++}*o                                   #transpose, insert newlines, print
paradigma
fuente
Mientras trabajaba en esto, la pregunta se aclaró para exigir que las montañas se impriman una vez cada una. Eso requerirá un replanteamiento y probablemente más personajes: /
paradigmsort
0

C, 179

excluyendo espacios en blanco innecesarios.

Una estrategia similar a edc65. n*2Reviso todos los valores binarios de -bit, considerando /= 1 y \= 0.

Formateo una sola cadena que contiene nsaltos de línea cada n*3carácter. Tal como está escrita, la cadena contiene 1000 caracteres, por lo que generalmente se imprime mucho espacio en blanco después de la montaña. (Esto se puede solucionar agregando s[n*n*3]=0antes del puts.) De todos modos, esto me permite generar toda la montaña con un solo putsdespués de verificar que cumple con las reglas.

Intentaré convertirlo en una función y reducirlo a un solo forciclo más adelante.

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 
  }
}

Salida (observe la gran cantidad de espacios en blanco a la derecha)

$ ./a
4

 /\
/  \/\/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

   /\
/\/  \/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

 /\/\
/    \/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

  /\
 /  \
/    \/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

     /\
/\/\/  \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

 /\  /\
/  \/  \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

   /\/\
/\/    \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

 /\/\/\
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

  /\
 /  \/\
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

    /\
   /  \
/\/    \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

    /\
 /\/  \
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

  /\/\
 /    \
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

   /\
  /  \
 /    \
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
Level River St
fuente
0

Haskell, 140 bytes

Después de que varios intentos no pudieron ser muy golfables, terminé con esta implementación de Haskell. ¡Estoy feliz de estar dentro de un factor de 2 de la solución APL!

Solución de golf:

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 y comentó:

El programa construye el conjunto de diagramas de montaña n -step recursivamente. Cada diagrama está representado por una lista de cadenas infinitamente largas, que representan la montaña dibujada de lado seguido de espacios que se extienden hasta el infinito. Esto garantiza que todos los diagramas tengan la misma altura, lo que facilita la recursividad. La impresora de montaña acepta un parámetro que recorta la altura a un 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 de la muestra:

$ 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
fuente
0

GolfScript 103 ( demo )

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

El programa toma un parámetro entero que intenta representar como montañas todas las representaciones binarias de los números del 0 al 2 ^ (n-1). No representa combinaciones no válidas (por ejemplo, las que van por debajo del nivel 0).

Cristian Lupascu
fuente