Zbuduj trójkąt bez żadnych trójkątów

44

Jako małe dziecko bardzo lubiłem bawić się tymi zabawkami:

wprowadź opis zdjęcia tutaj

Prawdopodobnie zamierzali je wykorzystać do sztuki, ale zawsze używałem ich do matematyki! Fraktale, wzory itp. Pewnego razu dostałem wyzwanie:

Zbuduj trójkąt bez użycia zielonych płytek trójkąta.

To wyzwanie zaskoczyło mnie najdłużej, dopóki nie natknąłem się na naprawdę piękny i prosty sposób na zrobienie tego za pomocą zaledwie 3 trapezoidów:

  /\  
 /_/\ 
/__\_\

Teraz weź ten trójkąt i obróć go:

______         
\ \__/         
 \/ /          
  \/ 

Za pomocą tych dwóch trójkątów możemy z nich zbudować większe trójkąty. Oto trójkąt o wysokości 2:

     /\           
    /_/\          
   /__\_\         
  /\ \__/\        
 /_/\/ /_/\       
/__\_\/__\_\    

A oto trójkąty o wysokości 3-7:

#3
        /\
       /_/\
      /__\_\
     /\ \__/\
    /_/\/ /_/\
   /__\_\/__\_\
  /\ \__/\ \__/\
 /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\

#4
           /\
          /_/\
         /__\_\
        /\ \__/\
       /_/\/ /_/\
      /__\_\/__\_\
     /\ \__/\ \__/\
    /_/\/ /_/\/ /_/\
   /__\_\/__\_\/__\_\
  /\ \__/\ \__/\ \__/\
 /_/\/ /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\/__\_\

#5
              /\
             /_/\
            /__\_\
           /\ \__/\
          /_/\/ /_/\
         /__\_\/__\_\
        /\ \__/\ \__/\
       /_/\/ /_/\/ /_/\
      /__\_\/__\_\/__\_\
     /\ \__/\ \__/\ \__/\
    /_/\/ /_/\/ /_/\/ /_/\
   /__\_\/__\_\/__\_\/__\_\
  /\ \__/\ \__/\ \__/\ \__/\
 /_/\/ /_/\/ /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\/__\_\/__\_\

#6
                 /\
                /_/\
               /__\_\
              /\ \__/\
             /_/\/ /_/\
            /__\_\/__\_\
           /\ \__/\ \__/\
          /_/\/ /_/\/ /_/\
         /__\_\/__\_\/__\_\
        /\ \__/\ \__/\ \__/\
       /_/\/ /_/\/ /_/\/ /_/\
      /__\_\/__\_\/__\_\/__\_\
     /\ \__/\ \__/\ \__/\ \__/\
    /_/\/ /_/\/ /_/\/ /_/\/ /_/\
   /__\_\/__\_\/__\_\/__\_\/__\_\
  /\ \__/\ \__/\ \__/\ \__/\ \__/\
 /_/\/ /_/\/ /_/\/ /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\/__\_\/__\_\/__\_\

#7
                    /\
                   /_/\
                  /__\_\
                 /\ \__/\
                /_/\/ /_/\
               /__\_\/__\_\
              /\ \__/\ \__/\
             /_/\/ /_/\/ /_/\
            /__\_\/__\_\/__\_\
           /\ \__/\ \__/\ \__/\
          /_/\/ /_/\/ /_/\/ /_/\
         /__\_\/__\_\/__\_\/__\_\
        /\ \__/\ \__/\ \__/\ \__/\
       /_/\/ /_/\/ /_/\/ /_/\/ /_/\
      /__\_\/__\_\/__\_\/__\_\/__\_\
     /\ \__/\ \__/\ \__/\ \__/\ \__/\
    /_/\/ /_/\/ /_/\/ /_/\/ /_/\/ /_/\
   /__\_\/__\_\/__\_\/__\_\/__\_\/__\_\
  /\ \__/\ \__/\ \__/\ \__/\ \__/\ \__/\
 /_/\/ /_/\/ /_/\/ /_/\/ /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\/__\_\/__\_\/__\_\/__\_\

Wyzwanie

Napisz program lub funkcję, która przyjmuje liczbę n i wypisuje trójkąt o wysokości n bez trójkątów . Końcowe spacje w każdej linii są dopuszczalne, a do jednej końcowej lub wiodącej nowej linii jest również dopuszczalne. IO może mieć dowolny rozsądny format. Dane wejściowe mają być dodatnimi liczbami całkowitymi, więc nie musisz się martwić o liczby ujemne, dziesiętne, nieliczbowe itp.

Najkrótsza odpowiedź w bajtach wygrywa!

DJMcMayhem
źródło
Spróbuj zrobić więcej trapezoidów z trapezoidów. Długości 2 i 3 są zdecydowanie możliwe (a przez to wszystkie liczby w formie 2 ^ a * 3 ^ b) (Skąd mam wiedzieć, że grałem z takimi samymi klockami, gdy byłem dzieckiem.)
CalculatorFeline
1
@CatsAreFluffy Cóż, ponieważ możesz zrobić trapez z trójkątów, możesz stwierdzić, że możesz zrobić trapezoidy z trapezoidów. W rzeczywistości, jeśli spojrzysz na trójkąty o wysokości 3 i 7, możesz zobaczyć ten sam wzór powtarzany z dużymi trapezoidami.
DJMcMayhem
To wyzwanie jest naprawdę fajne. Podobało mi się wymyślanie, jak to zrobić w siatkówce.
mbomb007
@ mbomb007 Cieszę się, że Ci się podobało! = D Właśnie dlatego piszę wyzwania.
DJMcMayhem
2
To wyzwanie idealnie pasuje do ekranu dzięki aplikacji mobilnej. Czy to było zamierzone? :)
Doddy

Odpowiedzi:

15

CJam, 47 lat

ri_"/__\_\/_/\/ /\ \__"6/f**eeW%{_S.*s\~,\-<N}/

Wyjaśnienie:

ri_       read the input, convert to integer and duplicate
"…"       push that string, containing the repeating pattern
           (3 lines in reverse order, concatenated)
6/        split into (3) lines of 6 characters
f*        multiply (repeat) each line n times
*         repeat the array of 3 lines n times
           at this point we have an array of 3*n strings with 6*n characters each
ee        enumerate the array (obtaining an array of [index string] pairs)
W%        reverse the array
           (so the lines are in correct order and indices in reverse order)
{…}/      for each [index string] pair
  _       duplicate the pair
  S.*     vectorized-multiply with " "
           this effectively replaces the index with a string of <index> spaces
  s       convert the pair to string, effectively concatenating the spaces
           with the string
  \       swap with the other copy of the [index string] pair
  ~,      dump the index and string on the stack and get the string length
  \-      subtract the index from it - this is the desired line length
  <       cut the concatenated string to that length
  N       add a newline

Wypróbuj online

aditsu
źródło
17

Ruby, 79

->n{1.upto(n*=3){|i|puts (' '*(n-i)).ljust(n+i,'/__\_\/\ \__/_/\/ '[i%3*6,6])}}

A. (-4 bajty -1 +1) zmieniono z 0-indeksowane ( .times) na 1-indeksowane ( 1.upto)

B. (-5 bajtów) zmieniono z tablicy trzech ciągów 6-znakowych na wybór podciągów 6-znakowych z ciągu 18-znakowego.

C. (-1 bajt) m=n*3->n*=3

D. (-5 bajtów) zredukował wszystkie pięć podwójnych odwrotnych ukośników do pojedynczych odwrotnych ukośników (częściowo możliwe dzięki zmianie kolejności ciągów wymaganych dla punktu A)

Ruby, 94

->n{(m=n*3).times{|i|puts (' '*(m-i-1)).ljust(m+i+1,[ '/\\ \\__','/_/\\/ ','/__\\_\\'][i%3])}}

wyjaśnienie

Podstawową jednostką jest diament 3x6 w następujący sposób (ostatni znak w każdym rzędzie powielony dla przejrzystości :)

    /\ \__/
   /_/\/ / 
  /__\_\/

Wszystko, co musimy zrobić, to wyświetlić odpowiednie okno tego wzoru. Ruby's ljustpozwala pad na dowolny ciąg, nie tylko spacje. Zwykle ljustbyłby używany do wypełniania ciągu znaków do wydrukowania przez dodanie spacji na końcu, ale tutaj używamy go w odwrotnej kolejności: do wypełniania ciągu spacji przez dodanie znaków do wydrukowania na końcu.

nie wziął udziału w programie testowym

f=->n{
  (m=n*3).times{|i|                  #for each line of the triangle
    puts (' '*(m-i-1)).              #print m-i-1 spaces, 
      ljust(m+i+1,[ '/\\ \\__',      #left justified and padded to total length m+i+1
                   '/_/\\/ ',        #by one of these three strings
                  '/__\\_\\'][i%3])
  }
}

f[gets.to_i]
Level River St
źródło
@ mbomb007 Po raz pierwszy mam tę skargę. Jako inżynier jestem przyzwyczajony do wprowadzania poprawek do wszystkiego. Jest to dość proste wyzwanie, a ulepszenia są dość trywialne, więc poszedłem naprzód i usunąłem litery wersji. Myślę, że pozostawienie oryginalnego kodu jest dobre, a przynajmniej nie szkodzi, ponieważ jest łatwiejszy do naśladowania niż obecna wersja.
Level River St
3
Rozmiar kodu zazwyczaj jednoznacznie identyfikuje każdą wersję, ale historia wersji jest również dostępna dla każdego, kto przegląda historię edycji.
mbomb007
9

Siatkówka , 150 122 118 bajtów

Nawiasem mówiąc, wyniki tego wyzwania wyglądają niesamowicie!

Dane wejściowe są jednostkowe. Dane wyjściowe zawierają końcowe podawanie wiersza. Kod wykorzystuje kodowanie ISO 8859-1. Zwróć uwagę na końcowe spacje na przedostatniej linii.

(?=_\\¶.*1)
_\/__\
(?=/_/\\¶.*1)
/_/\/ 
(^|__)(?=/\\¶.*1)
$1/\ \__
ms}`(.*1*)1
/\¶/_/\¶/__\_\¶$1
m`^(?=(.*¶)*.)
$#1$* 

Wypróbuj online

Wyjaśnienie

Jeśli chcesz uzyskać bardziej szczegółowe wyjaśnienia, skomentuj lub napisz do mnie na czacie.

(?=_\\¶.*1)                     # Matches the start of the 3rd line of every triangle
/__\_\                          #   and prepends another layer if needed
(?=/_/\\¶.*1)                   # 2nd line of each triangle
/_/\/ 
(^|__)(?=/\\¶.*1)               # 1st line of each triangle
$1/\ \__
ms}`(.*1*)1                 # This and above in a multi-single-line loop.
/\¶/_/\¶/__\_\¶$1               #   This stage adds a flattened triangle on top
m`^(?=(.*¶)*.)                  # Prepend a space for every line following -1
$#1$* 

Dzięki Martin za grę w golfa o 32 bajty.

mbomb007
źródło
6

Ascii język drukowania Tarmo, 46 ​​bajtów. (niekonkurujący)

1  /\| /_/\|/__\_\2 \__|/ 0n{n-a-1{~}1a{2#1}$}

Samo spojrzenie na takie dziwne języki programowania, jak CJam, wprawia mnie w zakłopotanie, jak skomplikowany, nienaturalny i tajemniczy może być język, że chciałem „odważnie iść tam, gdzie jeszcze nie było człowieka” i wymyślić mój własny język. W rezultacie stworzyłem własny język do drukowania wzorów ascii.

Podstawową ideą jest to, że możesz zdefiniować najpierw wzór, a następnie drukować - używając tego samego rodzaju znaku „1” lub „2” lub dowolnej liczby - możesz zdefiniować własny wzór wydruku.

Po zdefiniowaniu wzoru (zaczyna się od numeru do końca numeru) - kolejne numery wykonają drukowanie wzoru.

Na przykład

1  /\| /_/\|/__\_\01

Wyjścia takie jak to:

  /\
 /_/\
/__\_\

Zdefiniuje wzór 1, a następnie wydrukuje go od razu. Wzór jest zdefiniowany wszystko oddzielone za pomocą „|” postać. 0 na końcu - działa jak zakończenie wzoru.

Znaki specjalne, takie jak „$”, są zarezerwowane jako przesunięcie wiersza, a „~” jest zarezerwowane dla odstępów - połowy - określonego wzorca.

1  /\| /_/\|/__\_\01$~11$~1~11

Wysyła tekst w następujący sposób:

  /\
 /_/\
/__\_\
     /\
    /_/\
   /__\_\
        /\
       /_/\
      /__\_\

Dalej idzie do pętli. Ten musi być dobrze widoczny - więc zachowałem {} nawiasy kwadratowe dla pętli for, ale nazwy zmiennych są nazwane automatycznie - więc pierwszy nawias użyje „zmiennej”, drugiej „b” i tak dalej. Iteracja będzie zawsze wynosić od 0 do określonej liczby - a liczba ta jest definiowana przed nawiasami {}.

„n” jest zmienną zarezerwowaną dla danych wejściowych całej funkcji.

Więc kod:

1  /\| /_/\|/__\_\0n{1$}

Wyjdzie (przy n == 4):

  /\
 /_/\
/__\_\
  /\
 /_/\
/__\_\
  /\
 /_/\
/__\_\
  /\
 /_/\
/__\_\

A „#” to specjalny modyfikator do przycinania białego ołowiu.

I wreszcie całe rozwiązanie:

DrawPatterns.cs:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.CSharp;

class DrawPatterns
{
//Command line parameters - for example like this: "1  /\| /_/\|/__\_\2 \__|/ 0n{n-a-1{~}1a{2#1}$}" 3
    static Dictionary<char, String[]> patterns = new Dictionary<char,string[]>();

    static string Tabs(int n)
    {
        if( n < 0 ) n = 0;

        String r = "";

        for( int i = 0; i < n ; i++ )
            r += "    ";

        return r;
    }

    static int[] left = new int[10];
    static int top = Console.CursorTop;
    static int lastTop = Console.CursorTop;

    static public void DoPrint(char c, char modifier = ' ')
    {
        if (c == '$')
        {
            for (int i = 0; i < left.Length; i++)
                left[i] = 0;
            top = lastTop + 1;
            return;
        }

        if (!patterns.ContainsKey(c))
            return;

        if (modifier == '½' || modifier == '~')
        {
            int maxSize = patterns[c].Select(x => x.Length).Max();
            for( int i = 0; i < left.Length; i++ )
                left[i] += maxSize / 2;
            return;
        }

        int iLine = 0;
        foreach (var l in patterns[c])
        {
            Console.SetCursorPosition(left[iLine], top + iLine);
            if( top + iLine > lastTop ) 
                lastTop = top + iLine;

            String s = l;
            if (modifier == '#')
                s = s.TrimStart(' ');

            Console.WriteLine(s);
            left[iLine] += s.Length;
            iLine++;
        }
    }

    static void Main(string[] _args)
    {
        List<String> args = _args.ToList();
        String todo = "";
        String code = "";
        char nextVar = 'a';
        String lf = "\r\n";
        int align = 1;
        char lastModifier = ' ';
        int nextArg = 1;
        Dictionary<String, String> argValues = new Dictionary<string,string>();
        bool bDebug = false;

        if (args.Count != 0 && args[0].ToLower() == "-d")
        {
            bDebug = true;
            args.RemoveAt(0);
        }

        if (args.Count == 0)
        {
            Console.WriteLine("Usage: DrawPatterns.cs [options] \"script\" <arguments to script>");
            Console.WriteLine("[options] allowed:");
            Console.WriteLine("-d - debug");
            return;
        }

        String prog = args[0];

        for( int i = 0; i < prog.Length; i++ )
        {
            char c = prog[i];

            // Define pattern.
            if (c >= '0' && c <= '9' && !patterns.ContainsKey(c))
            {
                String p = Regex.Match(prog.Substring(i + 1), "[^0-9]*").Groups[0].Value;
                patterns[c] = p.Split('|');
                i += p.Length;
                if( prog[i + 1] == '0' ) i++;
                continue;
            }

            String procRemain = prog.Substring(i);
            // modifier specified, but pattern number is not provided - use first pattern.
            if( lastModifier != ' ' && ( c < '0' || c > '9' ) )
            {
                code += Tabs(align);
                code += "print('1' , '" + lastModifier + "');" + lf;
                lastModifier = ' ';
            }

            switch ( c )
            {
                case '{':
                    code += Tabs(align);
                    code += "for ( int " + nextVar + " = 0; " + nextVar + " < " + todo + " ; " + nextVar + "++ )" + lf;

                    //  Check for all variable names if they can be used in program.
                    foreach ( var m in Regex.Matches(todo, "[a-zA-Z_][a-zA-Z0-9_]*", RegexOptions.Singleline) )
                    {
                        String varName = m.ToString();

                        if( varName.Length == 1 && varName[0] <= nextVar )
                            // Already declared as a loop.
                            continue;

                        if( argValues.ContainsKey(varName ) )
                            continue;

                        if( nextArg >= args.Count )
                        {
                            Console.WriteLine("Insufficient parameters provided to script - argument '" + varName + "' value is needed");
                            return;
                        }

                        argValues[varName] = args[nextArg];
                        nextArg++;
                    }


                    code += Tabs(align);
                    code += "{" + lf;
                    nextVar++;
                    todo = "";
                    align++;
                    break;

                case '}':
                    align--;
                    code += Tabs(align);
                    code += "}" + lf;
                    break;

                default:
                    if (((c >= '0' && c <= '9') || c == '<' || c == '$') && todo == "")
                    {
                        code += Tabs(align);
                        code += "print('" + c + "' , '" + lastModifier + "');" + lf;
                        lastModifier = ' ';
                        continue;
                    }

                    if (c == '½' || c == '~' || c == '#')
                    {
                        lastModifier = c;
                        continue;
                    }

                    if( c == '\r' || c == '\n' )
                        continue;

                    todo += c;
                    break;
            }

        } //for

        String code2 = "";
        code2 += "using System;" + lf;
        code2 += "public class ExecClass { static void Exec( Action<char, char> print";

        object[] invokeArgs = new object[ argValues.Count+1];
        invokeArgs[0] = new Action<char, char>(DoPrint);
        int iValueIndex = 1;

        foreach ( var kv in argValues )
        {
            code2 += ",";
            code2 += "int " + kv.Key;
            invokeArgs[iValueIndex] = Int32.Parse(kv.Value);
            iValueIndex++;
        }

        code2 += ") {" + lf;
        code2 += code;
        code2 += "} };";

        if( bDebug )
        {
            int line = 1;
            String lineNumberedCode =Regex.Replace(code2, "^(.*)$", 
                delegate(Match m) { return (line++).ToString("d2") + ": " + m.Value; },
                RegexOptions.Multiline
            );
            Console.WriteLine(lineNumberedCode);
            Console.WriteLine();
            Console.WriteLine();
        }

        left[0] = Console.CursorLeft;
        for( int i = 1; i < left.Length; i++ )
            left[i] = left[0];
        top = Console.CursorTop;

        try
        {
            var compileResult = new CSharpCodeProvider().CompileAssemblyFromSource( new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = true }, code2);
            if (compileResult.Errors.HasErrors)
            {
                foreach (CompilerError ce in compileResult.Errors)
                {
                    if (ce.IsWarning) continue;
                    Console.WriteLine("{0}({1},{2}: error {3}: {4}", ce.FileName, ce.Line, ce.Column, ce.ErrorNumber, ce.ErrorText);
                }
                return;
            }

            var method = compileResult.CompiledAssembly.GetType("ExecClass").GetMethod("Exec", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
            method.Invoke(null, invokeArgs);

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

        Console.SetCursorPosition(1, lastTop);
        Console.WriteLine();
        Console.WriteLine();
    } //Main
}

Z takimi argumentami wiersza poleceń: -d "1 / \ | / _ / \ | / ___ \ 2 __ | / 0n {na-1 {½} 1a {2 # 1} $}" 3

Wyprowadzi to:

01: using System;
02: public class ExecClass { static void Exec( Action<char, char> print,int n) {
03:     for ( int a = 0; a < n ; a++ )
04:     {
05:         for ( int b = 0; b < n-a-1 ; b++ )
06:         {
07:             print('1' , '~');
08:         }
09:         print('1' , ' ');
10:         for ( int c = 0; c < a ; c++ )
11:         {
12:             print('2' , ' ');
13:             print('1' , '#');
14:         }
15:         print('$' , ' ');
16:     }
17: } };


        /\
       /_/\
      /__\_\
     /\ \__/\
    /_/\/ /_/\
   /__\_\/__\_\
  /\ \__/\ \__/\
 /_/\/ /_/\/ /_/\
/__\_\/__\_\/__\_\
TarmoPikaro
źródło
1
To naprawdę niesamowite! Powinieneś postawić to na Github i zachęcić ludzi do korzystania z niego!
DJMcMayhem
3
Witamy w Programowaniu zagadek i Code Golf! To bardzo miłe, że wymyśliłeś własny język programowania, ale czy najnowsza wersja, w której można go uruchomić, wyprzedza wyzwanie?
Adnan
Nie w pełni cię zrozumiałem, co mówisz?
TarmoPikaro
Cóż, jeśli sam język jest nowszy niż wyzwanie, często oznacza się go jako niekonkurencyjny (całkiem logiczne;)). To może być odpowiedni post.
Adnan
Język zależy od domeny problemu i nie wiedziałem, że taki problem istnieje, zanim go przeczytałem. Domyślam się, że mógłbym kodować język wcześniej, jeśli napotkam już podobny problem. :) W każdym razie, korzystając ze strony, zrozumiałem, że CJam jest tutaj dość „normalnym” językiem. :)
TarmoPikaro 17.04.16
5

JavaScript (ES6), 119 bajtów

n=>`,/\\ \\__,/_/\\/ ,/__\\_\\`[r=`repeat`](n).split`,`.map((s,i)=>` `[r](n*3-i)+s[r](n).slice(0,i*2)).slice(1).join`\n`

Gdzie \nreprezentuje dosłowny znak nowej linii. Jeśli dopuszczalna jest linia wiodąca ze n*3spacjami i znakiem nowej linii, .slice(1)można ją usunąć w celu zaoszczędzenia 9 bajtów.

Neil
źródło
2

Python 2, 142 bajty

def f(n,m):return f(n-1,m+3)+[' '*(m+x)+(y*n)[x*2:]for x,y in((2,' \\__/\\'),(1,'/ /_/\\'),(0,'/__\\_\\'))]if n else[]
print '\n'.join(f(n,0))

Zasada jest bardzo podobna do innych odpowiedzi: weź trzy powtarzające się struny, a następnie warstwuj je w taki sposób, że wystarczy przyciąć niektóre z nich, aby uzyskać trójkąt, a następnie wypełnić je po lewej stronie.

wvxvw
źródło
2

C ++, 395 bajtów

Pierwszy kod golfowy o wspaniałym rozmiarze 395 bajtów w C ++. W moim przypadku wygląda to trochę jak konkurs na zaciemnienie: D

#include <iostream>
#include <cstring>
#define A for (int k=0;k<((s-(i+1))*3+(2-j));k++) cout<<" ";
using namespace std; string t[3]={"/\\","/_/\\","/__\\_\\"};string r[2]={" \\__","/ "};int tr=3;int main(int,char**argv){int s=atoi(argv[1]);for(int i=0;i<s;i++){for(int j=0;j<tr;j++){A for(int l=1;l<=2*(i+1)-1;l++){if((l%2)==0&&(j<2)){cout<<r[j];}else if ((l%2)==1)cout<<t[j];}A cout<<endl;}}}
John HK
źródło