Piramidy egipskie

15

Wielka Piramida w Gizie, największa piramida w Egipcie, jest nie tylko najstarszym z Siedmiu Cudów Starożytnego Świata, ale także jedynym, który pozostaje w dużej mierze nienaruszony. Budowa egipskich piramid może zająć do 20 lat i jest tak duża, że ​​Al-Aziz Uthman, syn wielkiego Saladyna, który zmiażdżył krzyżowców, musiał zrezygnować z rozbiórki wielkich piramid w Gizie, ponieważ uznano to za zbyt wielkie zadanie . Egipskie piramidy budowano głównie jako grobowce dla faraonów i ich małżonków w czasach Starego i Średniego Królestwa (ok. 2686–1690 pne), a od 2008 r. Odkryto 138 egipskich piramid.

Zadanie polega na utworzeniu programu, który wprowadza sekwencję odległości oddzielonych spacją i produkuje piramidy tekstowe 10 × 10 oddzielone tymi odległościami. Odległość 1 jest równa dwóm postaciom.

Piramida tekstowa będzie wyglądać następująco:

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

Jeżeli wejście składa się tylko z podziału linii, powstanie jedna piramida, jak wyżej . Dla każdej piramidy piramidy po lewej stronie są wyświetlane tak, jakby były z przodu.

Przykład I

Wejście:

4 3 1

Wynik:

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

Przykład II

Wejście:

0 9

Wynik:

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

Przykład III

Wejście:

11

Wynik:

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

Zwycięzcą jest aplikacja spełniająca te wymagania w jak najmniejszej liczbie znaków.

Odniesienie: Wikipedia.org

Nharren
źródło
Zakładam, że dozwolone są dodatkowe białe znaki na końcu linii?
Peter Taylor
Zależy, kogo zapytasz. W najściślejszym odczycie specyfikacji nie ma białych znaków po danych wyjściowych. Ale biorąc pod uwagę, że jest to dla zabawy, nie mam z tym problemu.
nharren
Czy dozwolone są zatem argumenty wiersza poleceń dotyczące wprowadzania danych?
Joey
O ile spełnia wymagania. Widzę teraz, że rozwiązanie Whitledge'a faktycznie nie jest w stanie obsłużyć przełamań linii jako danych wejściowych (nie mogę cofnąć mojego poparcia), po prostu działa wokół niego, tworząc piramidę, jeśli nie ma danych wejściowych. Ale jeśli możesz znaleźć rozwiązanie, które poradzi sobie z wejściami do łamania linii (\ r lub \ n jest w porządku) jako argumenty linii poleceń, to jest dla mnie w porządku.
nharren

Odpowiedzi:

4

Golfscript, 70 znaków

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

Bezpośredni port mojego rozwiązania Ruby , więc jestem pewien, że można to skrócić o kilka znaków.

Ventero
źródło
5

Windows PowerShell, 122 132 133 139 139

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

Skrypt testowy .

Losowe wprowadzanie również tworzy ładne obrazy:

Losowe piramidy

Joey
źródło
Działa, jeśli dodam $input=Read-Hostu góry, w przeciwnym razie nie prosi o dane wejściowe. Jak należy to uruchomić?
nharren
@nharren: echo 0 3 4 1|powershell -noprofile -file pyramids.ps1Lub z PowerShell '0 1 4 3' | .\pyramids.ps1. Jest to częsty problem z golfa w PowerShell, niestety, jak można akceptować tylko bądź rurami w wejście lub wejścia interaktywnego. PowerShell tak naprawdę nie ma pojęcia stdin w innych językach i środowiskach, co czasem się pojawia. Zwykle wybieram dane wejściowe, chyba że zadanie wyraźnie wymaga interakcji, na przykład Zgadnij numer .
Joey
Ach tak, teraz to działa. Moje zacieranie przycisków nie przynosiło żadnych rezultatów i nie mogłem zrozumieć, dlaczego.
nharren
4

Haskell, 148 znaków

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

Jestem z tego całkiem niezadowolony! To po prostu wydaje się zbyt długie. Pomysły?

MtnViewMark
źródło
Wewnątrz lambda możesz zmienić duży stos ++na pojedynczą listę i użyć concat aka >>=id. Nie wiem czy to pomoże. Innym punktem byłoby użycie foldr1zamiast foldr.
FUZxxl
Dzięki za pomysły. W tym przypadku również nie pomaga: konwersja ++sekwencji oszczędza tylko jedną postać na przedmiot, a koszt końcowy concatjest tutaj zbyt wysoki. Nie foldrmożna użyć foldr1formularza, ponieważ wynikiem jest czas, Stringpodczas gdy typ listy to [Int]( 1warianty foldwymagają, aby były takie same.)
MtnViewMark
4

Python, 123 znaki

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
źródło
Z ciekawości, czy to python 2.5? Aby to działało w Pythonie 3.2, otoczyłem funkcję map funkcją listy, zmieniłem raw_input () na input () i zmieniłem print na print ().
nharren
@nharren: działa dla mnie zarówno w wersji 2.4.4, jak i 2.5.2.
Keith Randall,
4

Ruby 1.9, 116 znaków

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
źródło
2

Perl, 130 126 132 znaków

$_=<>;$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}

Nieco krótsza wersja, która pobiera dane wejściowe jako argumenty wiersza poleceń zamiast ze standardowego wejścia:

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

Nie mogę uwierzyć, że nikt nie zrobił jeszcze wyrażenia regularnego. Perl jest daleki od bycia moim najlepszym językiem, więc to może prawdopodobnie stracić znacznie więcej. Byłbym zainteresowany zobaczeniem implementacji sed, jeśli ktoś jest gotowy na wyzwanie.

(Dzięki, @mbx, za 4 znaki).

Peter Taylor
źródło
foreach == for -> zapisz 4 znaki
mbx
przetestowałeś swoją wersję z podanymi testami ?!
mbx
@mbx, tak, działa dla mnie. Perl 5.10.1, Ubuntu. Jaki błąd widzisz?
Peter Taylor
@Peter Taylor - na moim ubuntu i win32 działa również dobrze. Najpierw wypróbowałem to na ideone, który działa w Perlu 5.12.1.
mbx
2
»Jeśli dane wejściowe składają się tylko z łamania linii«, w rzeczywistości są to standardowe wskazówki.
Joey
1

JavaScript, 396 bajtów

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}

Nie wygram z JavaScriptem, ale teraz jest wpis JavaScript :)

Zastosowanie: _("1 2 3")itp.

pimvdb
źródło
1

Rubin (112)

Nieco krótszy niż rozwiązanie Ruby firmy Ventero, z innym podejściem. Właśnie zacząłem uczyć się języka Ruby, więc prawdopodobnie można to nieco zmniejszyć.

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

PowerShell, 105 98 bajtów, najściślejszy odczyt specyfikacji

-7 bajtów od odpowiedzi migimaru .

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

Skrypt testowy:

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

Wynik:

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

PowerShell, 101 94, zabawa z jednym wiodącym białym znakiem

($a=-join(,6+$args-gt0|%{'  '*--$_+'/\'}))
1..9|%{($a=$a-replace' /','/-'-replace'\\.?','-\')}
mazzy
źródło
0

Nie mogłem uzyskać wersji C # 3 krótszej niż ta. Nie wiem dokładnie, ile postaci się liczy, ale podejrzewam, że przegrałem. :-(

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
źródło
3
Czy przypadkiem pomyliłeś Code Bowling i Code Golf?
Joey,
1
Przynajmniej udawaj, że próbujesz. Jeśli nie grasz w golfa, ludzie nie będą mieli przeciwko tobie pełnego języka .
dmckee --- były moderator kociąt
Sądzę, że to twoja pełna wersja wyjaśniająca twoje sprytne sztuczki. Wygląda na to, że zapomniałeś opublikować wersję golfową.
mbx,
@Joey, @dmckee - Myślałem o zrobieniu wersji golfa, ale nie udało mi się. W każdym razie jestem okropny w tej grze. Niewyraźny kod jest całkowicie sprzeczny z moją naturą. Prawdopodobnie powinienem trzymać się z dala od zagadek golfowych! - @mbx - Niestety, nie ma fajnych sztuczek.
Jeffrey L Whitledge