Pyramides égyptiennes

15

La Grande Pyramide de Gizeh, la plus grande pyramide d'Egypte, est non seulement la plus ancienne des sept merveilles du monde antique, mais elle est également la seule à rester en grande partie intacte. Les pyramides égyptiennes peuvent prendre jusqu'à 20 ans à construire et sont si grandes qu'Al-Aziz Uthman, fils du grand Saladin qui a écrasé les croisés, a dû renoncer à démolir les grandes pyramides de Gizeh parce que cela était considéré comme une tâche trop lourde . Les pyramides égyptiennes ont été principalement construites en tant que tombes pour les pharaons du pays et leurs épouses pendant les périodes de l'Ancien et du Moyen Empire (c. 2686–1690 avant notre ère), et en 2008, 138 pyramides égyptiennes ont été découvertes.

La tâche consiste à créer un programme qui saisit une séquence de distances séparées par un espace et produit des pyramides de texte 10 × 10 séparées par ces distances. Une distance de 1 équivaut à deux caractères.

Une pyramide de texte ressemblera à ceci:

         /\
        /--\
       /----\
      /------\
     /--------\
    /----------\
   /------------\
  /--------------\
 /----------------\
/------------------\

Si l'entrée se compose uniquement d'un saut de ligne, alors une pyramide sera produite, comme ci-dessus . Pour chaque pyramide, les pyramides à gauche sont affichées comme si elles étaient devant.

Exemple I

Contribution:

4 3 1

Production:

         /\      /\    /\/\
        /--\    /--\  /--\-\
       /----\  /----\/----\-\
      /------\/------\-----\-\
     /--------\-------\-----\-\
    /----------\-------\-----\-\
   /------------\-------\-----\-\
  /--------------\-------\-----\-\
 /----------------\-------\-----\-\
/------------------\-------\-----\-\

Exemple II

Contribution:

0 9

Production:

         /\                /\
        /--\              /--\
       /----\            /----\
      /------\          /------\
     /--------\        /--------\
    /----------\      /----------\
   /------------\    /------------\
  /--------------\  /--------------\
 /----------------\/----------------\
/------------------\-----------------\

Exemple III

Contribution:

11

Production:

         /\                    /\
        /--\                  /--\
       /----\                /----\
      /------\              /------\
     /--------\            /--------\
    /----------\          /----------\
   /------------\        /------------\
  /--------------\      /--------------\
 /----------------\    /----------------\
/------------------\  /------------------\

La candidature pour remplir ces conditions avec le moins de caractères est gagnante.

Référence: Wikipedia.org

nharren
la source
Je suppose que des espaces supplémentaires à la fin de la ligne sont autorisés?
Peter Taylor
Cela dépend de qui vous demandez. Dans la lecture la plus stricte de la spécification, aucun espace ne suit la sortie. Mais étant donné que c'est pour le plaisir, je n'ai aucun problème avec ça.
nharren
Les arguments de ligne de commande pour prendre des entrées sont donc autorisés?
Joey
Tant qu'il répond aux exigences. Je vois maintenant que la solution de Whitledge n'est pas en mesure de gérer les sauts de ligne en entrée (je ne peux pas annuler mon vote positif), elle fonctionne simplement en produisant une pyramide s'il n'y a pas d'entrée. Mais si vous pouvez trouver une solution qui peut gérer les entrées de saut de ligne (\ r ou \ n c'est bien) comme arguments de ligne de commande, alors ça me convient.
nharren

Réponses:

4

Golfscript, 70 caractères

~]0-:|;10,{:§9\-" "*"/""-"§2**+"\\"+:&|{.§>{§-(2*" "*1$}{-2*&>}if}%n}%

Port direct de ma solution Ruby , donc je suis sûr qu'il est possible de raccourcir cela de quelques caractères.

Ventero
la source
5

Windows PowerShell, 122 132 133 139

$d=@(-split$input)-gt0
0..9|%{' '*(9-($x=$_))+($a="/$('--'*$_)\")+-join($d|%{'  '*(($_-$x-1)*($x-lt$_))
$a[(-2*$_)..-1]})}

Script de test .

L'entrée aléatoire donne également de belles images:

Pyramides aléatoires

Joey
la source
Cela fonctionne si j'ajoute $input=Read-Hosten haut, sinon il ne demande pas d'entrée. Comment cela devrait-il être exécuté?
nharren
@nharren: echo 0 3 4 1|powershell -noprofile -file pyramids.ps1Ou depuis PowerShell '0 1 4 3' | .\pyramids.ps1. C'est un problème fréquent avec le golf dans PowerShell, malheureusement, car vous ne pouvez accepter que l'entrée canalisée ou l' entrée interactive. PowerShell n'a pas vraiment la notion de stdin que d'autres langages et environnements ont et cela se voit parfois. Je préfère généralement une entrée canalisée, sauf si la tâche appelle explicitement à l'interactivité, comme Devinez le nombre .
Joey
Ah oui, maintenant ça marche. Ma purée de boutons n'a donné aucun résultat, et je n'ai pas pu comprendre pourquoi.
nharren
4

Haskell, 148 caractères

r=replicate
p d=map(\k->foldr(\n i->r(9-k)' '++'/':r(2*k)'-'++"\\"++drop(11+k)(r(2*n)' '++i))""$d++[0])[0..9]
main=interact$unlines.p.map read.words

Je suis assez insatisfait de ça! Cela semble trop long. Des idées?

MtnViewMark
la source
A l'intérieur du lambda, vous pouvez changer le gros tas de ++'s en une seule liste et utiliser concat aka >>=id. Je ne sais pas si ça va aider. Un autre point serait d'utiliser à la foldr1place de foldr.
FUZxxl
Merci pour les idées. Aucun des deux n'aide dans ce cas: la conversion de ++séquences ne vous permet d'économiser qu'un caractère par élément, et les frais généraux de la finale concatsont trop élevés ici. Le foldrne peut pas utiliser le foldr1formulaire car l'heure du résultat est Stringalors que le type de liste est [Int](les 1variantes foldexigent qu'ils soient les mêmes.)
MtnViewMark
4

Python, 123 caractères

N=[10]+map(int,raw_input().split())
for y in range(10):print''.join((2*n*' '+'/'+2*y*'-'+'\ ')[-2*n-1:-1]for n in N)[9-y:]
Keith Randall
la source
Par curiosité, est-ce python 2.5? Pour que cela fonctionne en python 3.2, j'ai encapsulé la fonction de carte dans une fonction de liste, changé raw_input () en input () et changé print en print ().
nharren
@nharren: fonctionne pour moi en 2.4.4 et 2.5.2.
Keith Randall
4

Ruby 1.9, 116 caractères

d=gets.split-[?0]
10.times{|i|puts [?\s*(9-i),l=?/+?-*2*i+?\\,d.map{|r|i<(r=r.to_i)??\s*2*(r+~i)+l :l[-2*r,99]}]*""}
Ventero
la source
2

Perl, 130 126 132 132 caractères

$_=<>;$s=" "x9;map{$k.="/\\"."  "x($_-1)if$_}split;$_="$s$k/\\$s\n";for$i(0..9){print;s%\\-%-\\%g;s%\\/%-\\%g;s%\\ %-\\%g;s% /%/-%g}

Version légèrement plus courte qui prend l'entrée comme arguments de ligne de commande plutôt que depuis stdin:

$s=" "x9;map{$k.="/\\"."  "x($_-1)if$_}@ARGV;$_="$s$k/\\$s\n";for$i(0..9){print;s%\\-%-\\%g;s%\\/%-\\%g;s%\\ %-\\%g;s% /%/-%g}

Je ne peux pas croire que personne n'ait encore fait de solution regex. Perl est loin d'être ma meilleure langue, donc cela peut perdre beaucoup plus. Je serais intéressé de voir une implémentation sed, si quelqu'un est prêt à relever le défi.

(Merci, @mbx, pour 4 caractères).

Peter Taylor
la source
foreach == pour -> enregistrer 4 caractères
mbx
avez-vous testé votre version avec les testcases données?!
mbx
@mbx, oui, ça marche pour moi. Perl 5.10.1, Ubuntu. Quel bug voyez-vous?
Peter Taylor
@Peter Taylor - sur mon ubuntu et win32, cela fonctionne aussi très bien. Je l'ai d'abord essayé sur ideone qui exécute perl 5.12.1.
mbx
2
»Si l'entrée se compose uniquement d'un saut de ligne« fait allusion à une entrée standard, en fait.
Joey
1

JavaScript, 396 octets

function p(a){for(u=0;u<10;u++){t[u+a][9-u]="/";for(k=9-u+1+a;k<10+u+a;k++)t[k][u]="-";
t[10+u+a][u]="\\"}}function _(a){t=[];for(i=0;i<50;i++){t[i]=[];for(j=0;j<10;j++)t[i][j]=" "
}var a=a.split(" "),b=a.reduce(function(a,b){return a-0+(b-0)})*2;for(i=a.length-1;i>=0;
i--)p(b),b-=a[i]*2-0;p(0);a="";for(j=0;j<10;j++){b="";for(i=0;i<50;i++)b+=t[i][j];
a+=b.replace(/\s+$/,"")+(j<9?"\n":"")}return a}

Je ne vais pas gagner avec JavaScript, mais il y a maintenant une entrée JavaScript :)

Utilisation: _("1 2 3")etc.

pimvdb
la source
1

Rubis (112)

Légèrement plus courte que la solution Ruby de Ventero, avec une approche différente. Je viens de commencer à apprendre Ruby, donc cela peut probablement être réduit un peu.

s=' '*9+r='/\\';gets.split.map{|i|s+=' '*2*(i.to_i-1)+r}
10.times{puts s;s.gsub!' /','/-';s.gsub!(/\\.?/,'-\\')}
migimaru
la source
1

Powershell, 105 98 octets, la lecture la plus stricte de la spécification

-7 octets de la réponse de migimaru .

($a=' '+-join(,5+$args-gt0|%{'  '*--$_+'/\'}))
1..9|%{($a=$a-replace' /','/-'-replace'\\.?','-\')}

Script de test:

$f = {

($a=' '+-join(,5+$args-gt0|%{'  '*--$_+'/\'}))
1..9|%{($a=$a-replace' /','/-'-replace'\\.?','-\')}

}

@(
,(@"
         /\
        /--\
       /----\
      /------\
     /--------\
    /----------\
   /------------\
  /--------------\
 /----------------\
/------------------\
"@)

,(@"
         /\      /\    /\/\
        /--\    /--\  /--\-\
       /----\  /----\/----\-\
      /------\/------\-----\-\
     /--------\-------\-----\-\
    /----------\-------\-----\-\
   /------------\-------\-----\-\
  /--------------\-------\-----\-\
 /----------------\-------\-----\-\
/------------------\-------\-----\-\
"@, 4,3,1)

,(@"
         /\                /\
        /--\              /--\
       /----\            /----\
      /------\          /------\
     /--------\        /--------\
    /----------\      /----------\
   /------------\    /------------\
  /--------------\  /--------------\
 /----------------\/----------------\
/------------------\-----------------\
"@, 0,9)

,(@"
         /\                    /\
        /--\                  /--\
       /----\                /----\
      /------\              /------\
     /--------\            /--------\
    /----------\          /----------\
   /------------\        /------------\
  /--------------\      /--------------\
 /----------------\    /----------------\
/------------------\  /------------------\
"@, 11)
) | % {
    $expected, $a = $_
    $result = &$f @a
    ($result-join"`n")-eq$expected
    $result 
}

Production:

True
         /\
        /--\
       /----\
      /------\
     /--------\
    /----------\
   /------------\
  /--------------\
 /----------------\
/------------------\
True
         /\      /\    /\/\
        /--\    /--\  /--\-\
       /----\  /----\/----\-\
      /------\/------\-----\-\
     /--------\-------\-----\-\
    /----------\-------\-----\-\
   /------------\-------\-----\-\
  /--------------\-------\-----\-\
 /----------------\-------\-----\-\
/------------------\-------\-----\-\
True
         /\                /\
        /--\              /--\
       /----\            /----\
      /------\          /------\
     /--------\        /--------\
    /----------\      /----------\
   /------------\    /------------\
  /--------------\  /--------------\
 /----------------\/----------------\
/------------------\-----------------\
True
         /\                    /\
        /--\                  /--\
       /----\                /----\
      /------\              /------\
     /--------\            /--------\
    /----------\          /----------\
   /------------\        /------------\
  /--------------\      /--------------\
 /----------------\    /----------------\
/------------------\  /------------------\

Powershell, 101 94, amusez-vous avec un espace blanc de premier plan

($a=-join(,6+$args-gt0|%{'  '*--$_+'/\'}))
1..9|%{($a=$a-replace' /','/-'-replace'\\.?','-\')}
mazzy
la source
0

Je n'ai pas pu obtenir la version C # 3 plus courte que cela. Je ne connais pas exactement le nombre de personnages, mais je soupçonne que j'ai perdu. :-(

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace PyramidRenderer
{
    /// <summary>
    /// Generates ASCII-art pyramids at user-specified horizontal locations to
    /// the standard output stream.
    /// </summary>
    public class Program
    {
        /// <summary>
        /// Generates one or more ASCII-art pyramids at the locations specified and 
        /// sends them to the standard output stream.
        /// </summary>
        /// <param name="args">The command-line arguments. These should be non-negative 
        /// integers that specify the horizontal distance of each additional pyramid from the 
        /// preceeding pyramid. Whether or not any distances are suppplied, a pyramid
        /// is rendered at the starting location.</param>
        public static void Main(string[] args)
        {
            try
            {
                AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

                int[] pyramidDistances = ParsePyramidLocationsFromCommandLine(args).ToArray();
                PyramidCollection pyramids = new PyramidCollection(pyramidDistances);
                pyramids.RenderToText(Console.Out);
            }
            catch (ArgumentException ex)
            {
                Console.Error.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// Handler for the unhandled exception. This just displays the error message to 
        /// the standard error stream.
        /// </summary>
        /// <param name="sender">Required but unnecessary sender object for the event handler.</param>
        /// <param name="e">The object that represents the exception.</param>
        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Debug.Assert(e.ExceptionObject != null);

            string exceptionText;
            Exception ex = e.ExceptionObject as Exception;
            if (ex == null)
                exceptionText = e.ExceptionObject.ToString();
            else
                exceptionText = ex.Message;
            Console.Error.WriteLine(exceptionText);
        }

        /// <summary>
        /// Takes the command-line arguments and converts them to a sequence of 
        /// non-negative integers.
        /// </summary>
        /// <param name="args">The command-line arguments as supplied to Main.</param>
        /// <returns>A sequence of integers that represent the user’s distance selections.</returns>
        /// <exception cref="ArgumentException">An invalid argument was supplied.</exception>
        private static IEnumerable<int> ParsePyramidLocationsFromCommandLine(string[] args)
        {
            Debug.Assert(args != null);

            foreach (string arg in args)
            {
                int result;
                if (int.TryParse(arg, out result))
                {
                    if (result < 0)
                        throw new ArgumentException(string.Format("Invalid distance specified: {0}", arg));

                    yield return result;
                }
                else
                {
                    throw new ArgumentException(string.Format("Invalid option: {0}", arg));
                }
            }
        }
    }

    /// <summary>
    /// Represents a single pyramid to be rendered.
    /// </summary>
    internal class Pyramid
    {
        /// <summary>
        /// The height of the pyramids in text rows. The width of each pyramid will be
        /// twice the height.
        /// </summary>
        internal const int Height = 10;

        /// <summary>
        /// The length in characters of the horizontal unit distance in which the user 
        /// specifies the pyramid distances.
        /// </summary>
        internal const int PyramidUnits = 2;

        /// <summary>
        /// The character to output as the background of the pyramids.
        /// </summary>
        private const char backgroundChar = ' ';

        /// <summary>
        /// The character to output as the left edge of the pyramids.
        /// </summary>
        private const char leftEdgeChar = '/';

        /// <summary>
        /// The character to output within each pyramid, between the edges.
        /// </summary>
        private const char brickChar = '-';

        /// <summary>
        /// The character to output as the right edge of the pyramids.
        /// </summary>
        private const char rightEdgeChar = '\\';

        /// <summary>
        /// The absolute horizonal location of the pyramid’s bottom left corner as 
        /// specified in PyramidUnits.
        /// </summary>
        private int position;

        /// <summary>
        /// Constructs a new pyramid object at the specified location.
        /// </summary>
        /// <param name="position">The absolute horizonal location of the pyramid’s bottom
        /// left corner in PyramidUnits.</param>
        internal Pyramid(int position)
        {
            Debug.Assert(position >= 0);

            this.position = position;
        }

        /// <summary>
        /// Renders a single row the pyramid to the supplied text stream starting at
        /// the indicated location.
        /// </summary>
        /// <param name="textWriter">The output stream to which the pyramid is to
        /// be rendered.</param>
        /// <param name="row">The row of the pyramid to render. Zero is the top row,
        /// and Height - 1 is the bottom row.</param>
        /// <param name="startingPosition">The text character position—indexed at zero—at 
        /// which the rendering is to begin. If non-zero, this identifies the column one 
        /// past the ending location of the previous pyramid.</param>
        /// <returns>The horizontal location (in characters) at which the next item 
        /// may be rendered.</returns>
        internal int RenderRow(TextWriter textWriter, int row, int startingPosition)
        {
            Debug.Assert(textWriter != null);
            Debug.Assert(row >= 0);
            Debug.Assert(startingPosition >= 0);

            int leftBoundary = Height - 1 - row + position * PyramidUnits;
            int rightBoundary = Height + row + position * PyramidUnits;

            startingPosition = RenderField(textWriter, backgroundChar, startingPosition, leftBoundary);
            startingPosition = RenderField(textWriter, leftEdgeChar, startingPosition, leftBoundary + 1);
            startingPosition = RenderField(textWriter, brickChar, startingPosition, rightBoundary);
            startingPosition = RenderField(textWriter, rightEdgeChar, startingPosition, rightBoundary + 1);
            return startingPosition;
        }

        /// <summary>
        /// Outputs a sequence of repeated characters from the indicated starting position to
        /// just before the ending position, unless the starting position is already equal to
        /// or greater than the ending position.
        /// </summary>
        /// <param name="textWriter">The output stream to which the field is to be rendered.</param>
        /// <param name="character">The character to be repeated in the output.</param>
        /// <param name="startingPosition">The location at which rendering may begin in 
        /// characters indexed at zero.</param>
        /// <param name="endingPosition">The location one past the location at which rendering
        /// is to end.</param>
        /// <returns>The position at which the next field may begin.</returns>
        private static int RenderField(TextWriter textWriter, char character, int startingPosition, int endingPosition)
        {
            Debug.Assert(textWriter != null);
            Debug.Assert(startingPosition >= 0);
            Debug.Assert(endingPosition >= 0);

            int charCount = endingPosition - startingPosition;
            if (charCount <= 0)
                return startingPosition;
            textWriter.Write(new string(character, charCount));
            return endingPosition;
        }
    }

    /// <summary>
    /// A collection of pyramids to be displayed.
    /// </summary>
    internal class PyramidCollection
    {
        /// <summary>
        /// A left-to-right ordered list of the pyramids that the user has 
        /// requested to be rendered.
        /// </summary>
        List<Pyramid> allPyramids = new List<Pyramid>();

        /// <summary>
        /// Constructs a new pyramid collection.
        /// </summary>
        /// <param name="distances">The distances of each non-leftmost pyramid (in PyramidUnits) after
        /// the previous pyramid. The total number of pyramids will be one greater than the length of
        /// the distances array.</param>
        internal PyramidCollection(int[] distances)
        {
            Debug.Assert(distances != null);

            int nextPosition = 0;
            allPyramids.Add(new Pyramid(nextPosition));
            foreach (int nextDistance in distances)
            {
                Debug.Assert(nextDistance >= 0);

                try
                {
                    checked
                    {
                        nextPosition += nextDistance;
                        int endLocation = nextPosition * Pyramid.PyramidUnits + Pyramid.Height * 2;
                    }
                }
                catch (OverflowException)
                {
                    // Ignore any pyramids specified beyond the integer maximum distance.
                    break;
                }
                allPyramids.Add(new Pyramid(nextPosition));
            }
        }

        /// <summary>
        /// Outputs ASCII-art images of the pyramids in this collection to the 
        /// provided output stream.
        /// </summary>
        /// <param name="textWriter">The output stream to which the pyramids
        /// are to be rendered.</param>
        internal void RenderToText(TextWriter textWriter)
        {
            Debug.Assert(textWriter != null);

            for (int row = 0; row < Pyramid.Height; row++)
            {
                int startingPosition = 0;
                foreach (Pyramid pyramid in allPyramids)
                {
                    startingPosition = pyramid.RenderRow(textWriter, row, startingPosition);
                }
                textWriter.WriteLine();
            }
        }
    }

}
Jeffrey L Whitledge
la source
3
Avez-vous confondu Code Bowling et Code Golf par hasard?
Joey
1
Faites au moins semblant d'essayer. Les gens ne tiendront pas un langage verbeux contre vous si vous le jouez .
dmckee --- chaton ex-modérateur
Je suppose que c'est votre version détaillée pour expliquer vos astuces astucieuses. Il semble que vous ayez oublié d'en publier la version golf.
mbx
@Joey, @dmckee - J'ai pensé à faire une version golf, mais je n'y suis pas parvenu. Je suis terrible à ce jeu de toute façon. Le code obscur va complètement à l'encontre de ma nature. Je devrais probablement rester loin des puzzles de golf! - @mbx - Malheureusement, il n'y a pas de trucs astucieux.
Jeffrey L Whitledge