L' escalier du diable est une fonction fractale liée à l'ensemble de Cantor.
Votre tâche consiste à reproduire cette fonction géniale - dans l’art ASCII!
Contribution
Un seul entier n >= 0
, indiquant la taille de la sortie. L'entrée peut être donnée via STDIN, un argument de fonction ou un argument de ligne de commande.
Sortie
L'interprétation ASCII-art de l'escalier du diable à la taille n
, soit renvoyée sous forme de chaîne, soit imprimée sur STDOUT. Les espaces de fin à la fin de chaque ligne sont corrects, mais pas les espaces de début. Vous pouvez éventuellement imprimer une nouvelle ligne de fin.
Pour la taille 0
, la sortie est simplement:
x
(Si vous le souhaitez, vous pouvez utiliser tout autre caractère ASCII imprimable autre que l'espace, à la place de x
.)
Pour la taille n > 0
, nous:
- Prendre la sortie de la taille
n-1
et étirer chaque ligne par un facteur de trois - Riffle entre les rangées de single
x
s - Déplacez les lignes vers la droite pour qu’il y en ait exactement une
x
dans chaque colonne et que la position de la premièrex
soit minimale tout en diminuant avec les lignes.
Par exemple, la sortie pour n = 1
est:
x
xxx
x
Pour obtenir le résultat n = 2
, nous étendons chaque ligne d'un facteur trois:
xxx
xxxxxxxxx
xxx
Riffle entre les rangées de single x
:
x
xxx
x
xxxxxxxxx
x
xxx
x
Décalage à droite:
x
xxx
x
xxxxxxxxx
x
xxx
x
Comme autre exemple, ici est n = 3
.
Notation
C'est du code-golf, donc la solution dans le moins d'octets gagne.
(,],~3^#@~.)@]
au lieu d'(1,[:,1,"0~3*])
enregistrer 1 octet. Et si vous êtes d'accord avec!
comme caractère de sortieu:32+
au lieu d'en' #'{~
sauvegarder un autre.#\
au lieu dei.@#
et vous dépassez APL! :)n-1
pas pourn
.Hexagonie , 217 octets
C'était extrêmement amusant. Merci d'avoir posté ce défi.
Divulgation complète: la langue (Hexagony) n'existait pas au moment où ce défi a été publié. Cependant, je ne l'ai pas inventé, et le langage n'a pas été conçu pour ce défi (ou tout autre défi spécifique).
Disposé en hexagone:
Le programme n'utilise pas réellement l'
#
instruction. J'ai donc utilisé ce caractère pour indiquer quelles cellules sont réellement inutilisées.Comment fonctionne ce programme? Ça dépend. Voulez-vous la version courte ou la version longue?
Courte explication
Pour illustrer ce que j'entends par «ligne» et «segment» dans l'explication suivante, considérons cette dissection de la sortie souhaitée:
Avec cela expliqué, le programme correspond au pseudocode suivant:
Longue explication
Veuillez vous référer à ce diagramme de chemin de code codé par couleur.
L'exécution commence dans le coin supérieur gauche. La séquence d'instructions
){2'"''3''"2}?)
est exécutée (plus quelques annulations redondantes, comme,"{
etc.) en suivant un chemin relativement compliqué. Nous commençons avec le pointeur d’instruction n ° 0, surligné en rouge. À mi-parcours, nous passons au n ° 1, en partant du coin supérieur droit et peints en vert forêt. Quand IP # 2 commence en bleu bleuet (au centre à droite), la disposition de la mémoire est la suivante:Tout au long du programme, les arêtes étiquetées 2a et 2b auront toujours la valeur
2
(nous les utilisons pour calculer 2ⁿ⁺¹ et pour diviser par 2, respectivement) et l'arête étiquetée 3 sera toujours3
(nous l'utilisons pour calculer 3).Nous entrons dans les affaires en entrant dans notre première boucle, surlignée en bleu bleuet. Cette boucle exécute les instructions
(}*{=&}{=
pour calculer la valeur 2ⁿ⁺¹. Lorsque la boucle se termine, le chemin brun de selle est emprunté, ce qui nous conduit au pointeur d’instruction n ° 3. Cette IP ne fait que barboter le long du bord inférieur à l’ouest en verge d’or jaune et passe rapidement sous le contrôle de l’IP # 4.Le chemin fuchsia indique comment l’IP n ° 4, en commençant par le coin inférieur gauche, procède rapidement pour décrémenter la ligne , régler ch sur
32
(le caractère espace) et seg sur la (nouvelle valeur de) ligne . C’est en raison de la décrémentation précoce que nous commençons réellement par 2ⁿ⁺¹ − 1 et finissons par subir une dernière itération avec la valeur 0. Nous entrons ensuite dans la première boucle imbriquée .Nous tournons notre attention vers l'indigo ramifié, où, après un bref décrément de seg , nous voyons que ch
x
n'est mis à jour que si seg est maintenant à zéro. Ensuite, n est réglé sur line-seg pour déterminer le numéro réel du segment dans lequel nous sommes. Immédiatement, nous entrons dans une autre boucle, cette fois dans la couleur claire de la tomate.Ici, nous calculons combien de fois n (le numéro de segment actuel) peut être divisé par 2. Tant que le modulo nous donne zéro, nous incrémentons i et divisons n par 2. Lorsque nous sommes satisfaits, n n'est plus divisible de la sorte , nous passons au gris ardoise, qui contient deux boucles: premièrement, il élève 3 à la puissance du i calculé, puis il émet ch le nombre de fois. Notez que la première de ces boucles contient un
[
instruction, qui bascule le contrôle sur IP # 3 - celui qui ne prenait que des pas le long du bord inférieur plus tôt. Le corps de la boucle (multipliant par 3 et décrémentant) est exécuté par un IP solitaire n ° 3, emprisonné dans un cercle vert olive sans fin le long du bord inférieur du code. De même, la seconde de ces boucles gris ardoise contient une]
instruction qui active l’IP n ° 5 pour la sortie des canaux et des décrémentations, représentée ici en rouge indien foncé. Dans les deux cas, les pointeurs d’instruction pris au piège de la servitude exécutent docilement une itération à la fois et cèdent le contrôle à l’IP 4, pour attendre que leur service soit de nouveau appelé. Le gris ardoise, quant à lui, rejoint ses frères fuchsia et indigo.Lorsque seg atteint inévitablement zéro, la boucle indigo se termine dans le chemin vert de la pelouse, qui ne fait que sortir le caractère de nouvelle ligne et se fond rapidement dans le fuchsia pour continuer la boucle de ligne . Au-delà de l'itération finale de la boucle de ligne , se trouve le court chemin ebon de la fin du programme.
la source
Python 2, 78
En commençant par la liste
L=[1]
, nous la dupliquons et insérons la prochaine puissance de 3 au milieu, ce qui donne[1, 3, 1]
. C'est répété plusieursn
fois pour nous donner les longueurs de rangées pour l'escalier du diable. Ensuite, nous imprimons chaque ligne avec des espaces.la source
APL, 38
Exemple:
Explication:
la source
GNU sed, 142
Pas la réponse la plus courte, mais c'est séduit !:
Parce que c'est sed (pas d'arithmétique native), je prends des libertés avec la règle "Un seul entier n> = 0, indiquant la taille de la sortie" . Dans ce cas, l'entier en entrée doit être une chaîne de
1
s, de longueur n. Je pense que cela "indique" la taille de la sortie, même si ce n'est pas un équivalent numérique direct à n. Ainsi pour n = 2, la chaîne en entrée sera11
:Cela semble compléter avec la complexité temporelle exponentielle de O (c n ), où c est environ 17. n = 8 a pris environ 45 minutes pour moi.
Alternativement, s'il est nécessaire que n soit entré numériquement exactement, alors nous pouvons le faire:
sed, 274 octets
Sortie:
la source
Python 2, 81
Version du programme (88)
Le nombre de x dans la
n
rangée 1 indexée est 3 à la puissance de (l'indice du premier bitn
entré, à partir du lsb).la source
Python 2, 74
Une approche récursive. L'escalier size- $ n $ devil est divisé en trois parties
n-1
, dont la longueur est3**n - 2**n
x
', de longueur3**n
n-1
, dont la longueur est3**n - 2**n
Notez que la longueur totale des trois parties est
3*(3**n) - 2*(2**n)
ou3**(n+1) - 2**(n+1)
, ce qui confirme l'induction.La variable facultative
s
stocke le décalage des pièces actuelles que nous imprimons. Nous recourrons d’abord vers la branche gauche avec un offset plus grand, puis nous imprimons la ligne centrale, puis nous faisons la branche de droite avec l’offset actuel.la source
CJam,
363533 octetsVoici une autre approche de CJam (je n'ai pas regardé le code d'Optimizer, donc je ne sais pas si c'est vraiment très différent):
Ceci utilise
0
pour la courbe. Alternativement, (en utilisant le truc de grc)qui utilise
x
.Testez-le ici.
Explication
L’idée de base est de commencer par former un tableau avec les lignes, comme
Et ensuite, parcourez cette liste en ajoutant le nombre d’espaces requis.
L'autre version fonctionne de manière similaire, mais crée un tableau de longueurs, comme
Et puis transforme cela en chaînes de
x
s dans la carte finale.la source
Dyalog APL, 34 caractères
En utilisant l'approche de grc. Dessine l'escalier avec des caractères
⌹
(domino) et prend les entrées de stdin. Cette solution suppose⎕IO←0
.⎕
- Prendre l’entrée de stdin.⌽⍳1+⎕
- la séquence des nombres allant⎕
de 0 à 0. (par exemple3 2 1 0
)3*⌽⍳1+⎕
- trois à la puissance de cela (par exemple27 9 3 1
)(⊢,,)/3*⌽⍳1+⎕
- le résultat précédent plié à droite par la fonction tacite⊢,,
qui est égale au dfn{⍵,⍺,⍵}
donnant les longueurs de marche de l'escalier du diable selon l'approche de la grc.{⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕
les longueurs d'étape converties en étapes.(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕
que l' auto-classés, comme dans ma solution J . Notez que⊖
le résultat est déjà retourné correctement.' ⌹'[(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕]
les numéros remplacés par des blancs et des dominos.la source
Ruby, 99
Une réponse différente à mon autre, inspirée de la réponse de FUZxxl
FUZxxl note que les nombres de x correspondent au nombre de facteurs de 2 de l'indice. Par exemple, pour n = 2, nous avons la factorisation suivante:
J'utilise un moyen plus simple d'extraire ces puissances de 2:
i=m&-m
ce qui donne la séquence,1 2 1 4 1 2 1
etc. Cela fonctionne comme suit:m-1
est le même quem
dans ses bits les plus significatifs, mais le bit le moins significatif devient un zéro et tous les zéros à droite deviennent des 1.Pour pouvoir utiliser AND avec l'original, nous devons retourner les bits. Il y a différentes façons de le faire. Une façon consiste à le soustraire
-1
.La formule globale est alors
m& (-1 -(m-1))
ce qui simplifie àm&(-m)
Exemple:
Voici le code: les nouvelles lignes sont comptées, les retraits sont inutiles et ne sont donc pas comptés, comme mon autre réponse. Il est légèrement plus long que mon autre réponse en raison de la conversion maladroite de la base 2:
1 2 1 4 1 2 1 etc
à la base 3:1 3 1 9 1 3 1 etc
(y a-t-il un moyen d'éviter celaMath::
?)la source
Rubis,
14099Mon deuxième code Ruby, et ma première utilisation non triviale de ce langage. Les suggestions sont les bienvenues. Le nombre d'octets exclut les espaces de début de ligne, mais inclut les nouvelles lignes (il semble que la plupart des nouvelles lignes ne puissent être supprimées que si elles sont remplacées par au moins une espace.)
La saisie se fait par appel de fonction. La sortie est un tableau de chaînes, que ruby vide facilement sur stdout en tant que liste séparée par une nouvelle ligne avec une seule
puts
.L'algorithme est simplement
new iteration
=previous iteration
+extra row of n**3 x's
+previous iteration
. Cependant , il y abeaucoupune quantité juste de code juste pour obtenir les espaces de premier plan dans le droit de sortie.Edit: Ruby, 97
Ceci utilise l'approche similaire mais différente de la construction d'une table numérique de tous les nombres de x nécessaires dans le tableau
a
de la manière décrite ci-dessus, mais en construisant ensuite une table de chaînes. La table de chaînes est construite à l’arrière dans un tableau enc
utilisant launshift
méthode assez étrange pour ajouter un préfixe au tableau existant.Actuellement, cette approche semble meilleure - mais seulement de 2 octets :-)
la source
for m in(0..n-1)do ... end
avecn.times{|m|...}
.n.times
et je m'en souviendrai certainement. Ça élimine unend
aussi! Cependant, à cette occasion, je me demandais s'ilfor m in (1..n)
serait peut-être préférable d'éviter les(m+1)
. Y a-t-il une façon plus courte d'écrire ça?for
est long principalement parce que vous êtes obligé d'utiliserend
(vous pouvez le remplacerdo
par un saut à la ligne ou par;
). Pour que1..n
vous puissiez utiliser1.upto(n){|m|...}
. J'aime le look de(1..n).each{|i|...}
mais c'est un peu plus long que d'utiliserupto
. Et notez que itérer en appelanteach
ouupto
non, c'est plus court, c'est aussi un Ruby plus idiomatique.1.upto(n)
c'est! Avec cela et quelques crochets inutiles disparus, je suis déjà tombé à 120. Je pense qu’en dessous de 100 est possible, je publierai le code révisé plus tard.Haskell, 99 caractères
La fonction est
d
:la source
q
et en faisantq x=x
la casse de liste vide. De plus, il semble que les parenthèsesiterate...[1]
sont inutiles.PHP - 137 octets
J'utilise ici le même truc que grc . Voici la version non-golfée:
la source
3**$i
-> se sent comme PHP 5.6. Vous devriez le spécifier. Ceci est incompatible avec presque toutes les installations de PHP. Pour vous sauver quelques octets, vous devriez commencer par$r=str_repeat;
et où vous avez cette fonction, vous pouvez remplacer avec$r
, en vous sauvant 2 octets. En outre,$r('x',$v)
peut être$r(x,$v)
et cela fonctionnera bien (notez que j'ai déjà remplacé le nom de la fonction par la variable). En outre, je crois que cela++$i<=$n
peut être réécrit pour$n>++$i
vous sauver un octet supplémentaire.function f($n){$r=str_repeat;$a=[1];while($n>++$i)$a=array_merge($a,[3**$i],$a);foreach($a as$v){$o=$r(' ',$s).$r(x,$v)."\r$o";$s+=$v;}echo$o;}
(au lieu d'avoir cette nouvelle ligne laide, j'ai ajouté la séquence d'échappement à l'\r
intérieur d'une chaîne entre guillemets, avec la variable à l'$o
intérieur. Ainsi,"\r$o"
le même nombre d'octets que celui-''.$o
ci, avec newline ommited sur le dernier et produit le même résultatwhile
doit être$n>$i++
pour que cette réduction fonctionne correctement.$r=str_repeat
tour. Je pensais uniquement à$r='str_repeat';
ce qui ne sauvegardait pas d'octet. La constante non définie est un bon truc aussi, bien joué;). Un saut de ligne est un octet plus petit que l'écriture\n
, je l'ai donc conservé, mais j'ai utilisé des guillemets pour éviter une concaténation$0
. Merci encore !3 ** $i
je dirais que vous avez une syntaxe terrible. Vous pouvez adresser cette correction. Je ne parle que de celui-ci et non pas[1]
parce que cela vient de PHP 5.4, qui est assez "vieux". Il y a 1 an, je vous demanderais de préciser cela. Aujourd'hui, je vous demande de spécifier simplement (dans une ligne très courte) que cela spécifie. En parlant de code, vous avez toujours le++$i<=$n
qui peut être remplacé par$n>$i++
. Je devais convertir tout votre code en PHP 5.3 pour le tester. Ce qui était douloureux. Mais je vois que vous avez mangé 7 octets jusqu'à présent.C, 165
Voici le même code non emballé et légèrement nettoyé:
Ceci est basé sur la même idée que la solution de FUZxxl au problème, consistant à utiliser une forme explicite plutôt que implicite pour les lignes. La déclaration de j la met à 2 ^ (n + 1) et la première boucle while calcule k = 3 ^ (n + 1); alors l = 3 ^ (n + 1) -2 ^ (n + 1) est la largeur totale de l'escalier (ce n'est pas trop difficile à prouver). Nous parcourons ensuite tous les nombres r de 1 à 2 ^ (n + 1) -1; pour chacun d'eux, si c'est divisible par (exactement) 2 ^ n, alors nous avons l'intention d'imprimer s = 3 ^ n 'X. l est ajusté pour nous assurer de partir du bon endroit: nous écrivons l espaces et s 'X's, puis une nouvelle ligne.
la source
(*p)()=putchar;
au début pour appeler enputchar
tant quep
. Je pense que ça devrait marcher.CJam,
46 43 41 39 3635 octetsMISE À JOUR en utilisant une approche différente maintenant.
Ancienne approche:
Assez naïf et long, mais quelque chose à commencer.
Ajoutera une explication une fois que je joue au golf.
Essayez-le en ligne ici
la source
Java,
271269 octetsUtilise la méthode de grc.
Dentelé:
Toutes les suggestions sont les bienvenues.
2 octets grâce à mbomb007
la source
b.size()>0
au lieu de!b.isEmpty()
, économiser 2 octets.Perl, 62
First calcule le résultat de manière itérative sans les espaces de début. Puis les ajoute avant chaque ligne en fonction du nombre de
x
caractères dans le reste de la chaîne.la source
JavaScript (ES6) 104
106 118Modifier Suppression de la fonction récursive, la liste des « * » pour chaque ligne , on obtient de manière itérative, de jouer avec les bits et les pouvoirs de 3 (comme dans beaucoup d' autres réponses)
dans la boucle, une chaîne de caractères multiligne est buuilt de haut en bas, en maintenant un compte courant des espaces de début à ajouter sur chaque ligne
First Try enlevé
La fonction R récursive construit un tableau avec le nombre de '*' pour chaque ligne. Par exemple, R (2) est
[1, 3, 1, 9, 1, 3, 1]
Ce tableau est analysé pour créer une chaîne multiligne de bas en haut, en conservant un nombre permanent d'espaces de début à ajouter à chaque ligne.
Testez dans la console Firefox / FireBug
Sortie
la source
R - 111 caractères
Mise en œuvre simple, en construisant le tableau de manière itérative et en le détruisant lentement.
Usage:
la source
n
argument de la ligne de commanden=scan()
.x
pour l'utiliser comme un curseur, ni vous avez besoinif(n)
. De plus, les sauts de ligne comptent comme un personnage, je pense.x
. Pas sûr deif(n)
cependant. J'ai ajouté cette partie pour traiter le casn=0
. Leif(n)
retourneF
et retourne donc un singlex
. Si je l'enlève,n=0
donne des résultats indésirables. Nouveau ici, donc je ne connaissais pas les sauts de ligne. Inclus maintenant!a=0
et démarrez la boucle à,x in 0:n
cela fonctionne également pour n = 0. Ensuite, vous pouvez omettre leif(n)
.