Dessinez une gamme de chaînes de montagnes

16

Inspiré par le carrelage domino de Fibonacci , ce problème concerne la génération de l'art ASCII représentant une autre séquence combinatoire célèbre.

Un diagramme de montagne en n étapes est un dessin d'une chaîne de montagnes, utilisant exactement n '/' et n '\' caractères, de sorte que les caractères dessinent une courbe continue qui ne plonge jamais en dessous de son "altitude" initiale. Par exemple,

   /\/\
/\/    \

et

   /\
/\/  \/\

sont tous deux des diagrammes de montagne en 4 étapes, mais

/\  /\/\
  \/

n'est pas.

Contribution

Le programme doit accepter un entier n de stdin ou comme paramètre d'une fonction.

Production

Imprimez tous les diagrammes de montagne à n étapes sur la sortie standard. Les diagrammes peuvent être dans n'importe quel ordre, mais doivent être séparés par une sorte d'espace blanc. Vous pouvez décider si différents diagrammes seront générés horizontalement, verticalement, etc.

Comme pour le problème de carrelage domino, vous pouvez utiliser les espaces que vous souhaitez. Cela inclut les retours à la ligne supplémentaires avant ou après la sortie imprimée.

Exemple

Quelques exemples de sorties valides pour n = 3:

Sortie valide A:

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

Sortie valide B:

   /\
/\/  \

 /\/\
/    \

/\/\/\   

  /\
 /  \
/    \

 /\
/  \/\

Sortie valide C:

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

C'est le golf de code; le programme le plus court (en octets) gagne.

Matt Noonan
la source
Lorsque vous dites "Vous pouvez décider si différents diagrammes seront affichés horizontalement, verticalement, etc.", les chaînes de montagnes elles-mêmes peuvent-elles être latérales?
xnor
Les chaînes de montagnes elles-mêmes ne devraient pas être latérales. Le ciel vide entre les pics ajoute au défi, je pense.
Matt Noonan
Certaines plages peuvent-elles apparaître plusieurs fois?
fier haskeller du
@MattNoonan Vous avez raison, l'impression horizontale des chaînes de montagnes était définitivement délicate.
xnor
@ proud-haskeller Cela devrait être une fois chacun.
Matt Noonan,

Réponses:

10

Python 2: 151 caractères

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, c'est un gâchis.

La première idée est d'utiliser les nombres 0 to 2**N-1pour encoder toutes les séquences de Nmouvements ascendants et descendants dans leurs bits. Nous lisons ces bits un par un en les répétant %2et en les répétant /2en execboucle.

Nous stockons la chaîne de montagnes en cours d'exécution dans une liste de chaînes transposée L . À chaque fois, nous générons une nouvelle ligne d'espaces et remplaçons une case de la nouvelle ligne par /ou \selon qu'un mouvement vers le haut ou vers le bas s'est produit.

L'index de cet espace est les cespaces de la fin, où cest la hauteur de course. Le faire de face mettrait les montagnes à l'envers. Nous le déplaçonsb alignant les mouvements vers le haut et vers le bas, en obtenant [b-c]. Commencer cà 1 plutôt qu'à 0 corrige une erreur de coupure.

Pour éliminer les cas où les cbaisses en dessous de la valeur de départ 1, lorsque cela se produit, nous nous mettons ià 0, ce qui provoque tous les mouvements ultérieurs vers le bas, ce qui cdevient plus négatif. Ensuite, lorsque nous vérifions s'il cs'est terminé à 1, nous vérifions également s'il est cjamais tombé en dessous. Nous seulementprint la chaîne de montagnes si cest 1.

Pour imprimer, nous faisons zip(*L) transposons la plage de la verticale à l'horizontale et imprimons chaque chaîne jointe. Beaucoup de problèmes dans cette réponse sont dus au fait que Python traite les chaînes comme immuables, nous avons donc travaillé avec elles comme des listes de caractères et les avons jointes uniquement en chaînes pour l'impression.

Merci à @flornquake pour son aide et ses améliorations.

xnor
la source
Vous devrez utiliser à la ' 'place de " "si vous voulez boucler en utilisant exec. :) Btw, vous n'avez pas besoin d'échapper à la barre oblique inverse.
flornquake du
@flornquake J'ai oublié d'écrire, j'ai utilisé ' 'et essayé de remplacer la chaîne par des guillemets avec une variable pour elle. Cela donnait toujours un indice hors de portée: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
Je voulais dire que vous devez écrire exec("b=i%2;c+=2*b-1;L+=[[' ']*N];L[-1][b-c]='\\/'[b];i=i//2*(c>0);"), c'est-à-dire que les guillemets intérieurs doivent être différents des guillemets extérieurs.
flornquake
@flornquake Wow, je me sens bête, j'ai changé une paire de citations mais pas l'autre. Merci!
xnor
7

APL (88)

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

Sortie pour n=3:

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

Explication:

  • (N/2)⊤⍳2*N←2×⍵: obtenir un champ de bits pour chaque nombre de 0à 2^⍵.
  • Z←↓⍉¯1+2×: multipliez par 2 et soustrayez 1, en donnant 1pour haut et -1pour bas. Stockez un vecteur de vecteurs, chaque vecteur contenant la représentation pour un nombre, dans Z.
  • {... }¨Z: pour chaque élément de Z:
    • ∧/0≤+\⍵: vérifiez que la somme cumulée ne descend jamais 0 (ne descend pas en dessous du niveau du sol),
    • (0=+/⍵): et que la somme totale est 0(se retrouve au niveau du sol).
  • {... }¨Z/⍨: sélectionnez ces éléments dansZ pour lesquels cela est vrai. Pour chacun d'eux:
    • K←(⍵≠1)++\⍵: recherchez la hauteur de chaque personnage et enregistrez-la K. Soulevez chacun \vers le haut, afin qu'ils s'alignent /correctement avec le s. Cela rend la hauteur du sol1 .
    • ¯1+2×K=⊂⌽⍳⌈/K: pour chaque colonne, faites une liste [1..max(K)]et marquez la position du caractère dans cette colonne avec 1et le reste comme -1. (La réplication par -1 remplit cette position avec un espace.)
    • '\/'[1+⍵=1]/⍨¨: recherchez le caractère correct pour chaque colonne et répliquez-le par la liste de cette colonne.
    • ⍉↑: transformez le résultat en matrice et mettez-le à l'endroit
marinus
la source
D'accord, une horizontale!
Matt Noonan,
2

Python, 261 241 236 caractères

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

Cela commence à prendre un certain n=5temps ...

$ 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
la source
2

JavaScript (ES6) 159 163

Tout comme ma réponse pour Fibonacci Domino Tiling, j'examine toutes les séquences de n + n bits, avec 1 marquant un '/' et 0 marquant un '\' (juste pour la sortie, '2' est ajouté plus tard pour marquer une nouvelle ligne) . Lors de la construction du modèle ascii, je vérifie l'équilibre - mêmes nombres de 0 et 1, et ne descendant jamais en dessous de la ligne de base de départ - et affiche ce qui obéit aux règles.

Sortie effectuée avec 'alert', qui est standard pour JS codegolf mais assez ennuyeux, et peut-être contraire aux règles. En utilisant console.log, le nombre de caractères passe à 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;
}

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

Testez dans la console FireFox / FireBug.

F(4)

Production

   /\
  /  \
 /    \
/      \ 

  /\/\
 /    \
/      \ 

    /\
 /\/  \
/      \ 

    /\
   /  \
/\/    \ 

  /\
 /  \/\
/      \ 

 /\/\/\
/      \ 

   /\/\
/\/    \ 

 /\  /\
/  \/  \ 

     /\
/\/\/  \ 

  /\
 /  \
/    \/\ 

 /\/\
/    \/\ 

   /\
/\/  \/\ 

 /\
/  \/\/\ 

/\/\/\/\ 
edc65
la source
Curieux de savoir s'il y a une raison particulière pour laquelle vous écrivez -b-bet -n-nau lieu de -2*b?
Steve Bennett
@SteveBennett aucune raison. Parfois, ce modèle est plus court, mais pas cette fois (par exemple: 2*b+1-> b-~b)
edc65
1

CJam, 84 octets

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

Notez que ce programme imprime les montagnes dans une boucle infinie afin que l'interprète en ligne ne vous aide pas; invoquer sur la ligne de commande en utilisant

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

ou pour essayer une utilisation en ligne

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

et appuyez simplement sur le bouton d'exécution plusieurs fois de suite et imaginez que la sortie est concaténée.

L'idée de base est que nous savons qu'une chaîne de montagnes de taille Q a Q de chaque transition vers le haut et vers le bas.

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

Ensuite, si elle est valide, nous l'imprimons, sinon nous la sortons de la pile pour qu'elle ne déborde pas.

Le routage d'impression construit essentiellement chaque colonne comme des espaces de hauteur Q, puis le symbole, puis suffisamment d'espaces pour atteindre Q + 1 au total, puis nous transposons et imprimons les lignes avec des retours à la ligne entre elles.

z{N\++}*o                                   #transpose, insert newlines, print
paradigmsort
la source
Pendant que j'y travaillais, la question a été clarifiée pour exiger que les montagnes soient imprimées une fois chacune. Cela nécessitera de repenser et probablement plus de personnages: /
paradigmsort
0

C, 179

excluant les espaces inutiles.

Une stratégie similaire à edc65. Je passe en n*2revue toutes les valeurs binaires -bit, en considérant /= 1 et \= 0.

Je nformate une chaîne unique contenant des sauts de ligne tous les n*3caractères. Comme écrit, la chaîne contient 1 000 caractères, donc il y a généralement beaucoup d'espaces imprimés après la montagne. (Cela peut être corrigé en ajoutant s[n*n*3]=0avant le puts.) Quoi qu'il en soit, cela me permet de sortir la montagne entière avec un seul putsaprès avoir vérifié qu'elle est conforme aux règles.

J'essaierai de le convertir en fonction et de le réduire à une seule forboucle plus tard.

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

Sortie (notez la quantité massive d'espaces à droite)

$ ./a
4

 /\
/  \/\/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

   /\
/\/  \/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

 /\/\
/    \/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

  /\
 /  \
/    \/\                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

     /\
/\/\/  \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

 /\  /\
/  \/  \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

   /\/\
/\/    \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

 /\/\/\
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

  /\
 /  \/\
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

    /\
   /  \
/\/    \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

    /\
 /\/  \
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

  /\/\
 /    \
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

   /\
  /  \
 /    \
/      \                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
Level River St
la source
0

Haskell, 140 octets

Après plusieurs tentatives infructueuses, je me suis retrouvé avec cette implémentation Haskell. Je suis content d'être juste dans un facteur 2 de la solution APL!

Solution golfée:

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

Non golfé et commenté:

Le programme construit récursivement l'ensemble des diagrammes de montagne à n étapes. Chaque diagramme est représenté par une liste de chaînes infiniment longues, représentant la montagne tracée latéralement, suivie d'espaces s'étendant à l'infini. Cela garantit que tous les diagrammes ont la même hauteur, ce qui facilite la récursivité. L'imprimante de montagne accepte un paramètre qui coupe la hauteur à une valeur finie.

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

Exemple d'utilisation:

$ 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
la source
0

GolfScript 103 ( démo )

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

Le programme prend un paramètre entier essaye de rendre en montagnes toutes les représentations binaires des nombres de 0 à 2 ^ (n-1). Il ne rend pas les combinaisons invalides (ex: celles qui vont en dessous du niveau 0).

Cristian Lupascu
la source