Побудуйте трикутник без жодних трикутників


44

У дитинстві я дуже любив грати з цими іграшками:

введіть тут опис зображення

Вони, ймовірно, призначені для того, щоб вони були використані для мистецтва, але я завжди використовував їх для математики! Фрактали, візерунки тощо. Одного разу мені поставили цей виклик:

Побудуйте трикутник, не використовуючи жодної із плиток зеленого трикутника.

Цей виклик натякав мене найдовше, поки я не натрапив на дійсно красивий і простий спосіб зробити це за допомогою лише 3-х трапецій:

  /\  
 /_/\ 
/__\_\

Тепер візьміть цей трикутник і оберніть його:

______         
\ \__/         
 \/ /          
  \/ 

Використовуючи ці два трикутники, ми можемо побудувати з них більші трикутники. Ось трикутник висотою 2:

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

А ось трикутники висотою 3-7:

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

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

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

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

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

Змагання

Напишіть програму або функцію, яка займає число n і друкує трикутник, що не має трикутника, висотою n . Кінцеві пробіли на кожному рядку є прийнятними, і до однієї кінцевої або провідної нової лінії також є прийнятною. IO може бути в будь-якому розумному форматі. Вхід гарантується як додатне ціле число, тому вам не доведеться турбуватися про негативні числа, десяткові числа, не числа та ін.

Найкоротша відповідь у байтах виграє!


Спробуйте зробити більше трапецій із трапецій. Довжини 2 і 3, безумовно, можливі (і подовжуючи, всі числа форми 2 ^ a * 3 ^ b) (Як я знаю? Грали з однаковими блоками, коли я була дитиною.)
CalculatorFeline

1
@CatsAreFluffy Ну, оскільки ви можете зробити трапецію з трикутників, ви можете зробити висновок, що ви можете зробити трапеції з трапецій. Насправді, якщо подивитися на трикутники висотою 3 та 7, ви зможете побачити той самий малюнок, який повторюється з великими трапеціями.
DJMcMayhem

Цей виклик справді класний. Мені подобалося з'ясовувати, як це зробити на Сітці.
mbomb007

@ mbomb007 Радий почути, що вам сподобалось! = D Саме тому я пишу виклики.
DJMcMayhem

2
Це завдання ідеально підходить на екрані мобільного додатка. Це було навмисно? :)
Додді

Відповіді:


15

CJam, 47

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

Пояснення:

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

Спробуйте в Інтернеті


17

Рубі, 79

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

A. (-4 байти -1 +1) змінено з 0-індексованого ( .times) до 1-індексованого ( 1.upto)

B. (-5 байт) змінився з масиву трьох 6-знакових рядків до вибору 6-ти рядкових підрядків 18-знакових рядків.

C. (-1 байт) m=n*3->n*=3

D. (-5 байт) зменшив усі п’ять подвійних косої риски до одинарної косої риски (частково це стало можливим шляхом переупорядкування рядка, необхідного для точки A)

Рубі, 94

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

пояснення

Основна одиниця - діамант 3х6 таким чином (останній символ у кожному рядку, дублюється для наочності :)

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

Все, що нам потрібно зробити - це відобразити відповідне вікно цього шаблону. Ruby's ljustдозволяє прокладати будь-яку струну, а не лише пробіли. Зазвичай ljustвикористовується для прокладки рядка символів для друку, додаючи пробіли в кінці, але тут ми використовуємо його в зворотному порядку: для прокладки рядка пробілів, додаючи символи для друку в кінці.

unolfolf у тестовій програмі

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]

@ mbomb007 Вперше у мене була скарга. Як інженер, я звик вносити зміни до всього. Це досить просте завдання, і вдосконалення досить тривіальні, тому я пішов уперед і видалив листи про перегляд. Я думаю, що залишити вихідний код добре або принаймні не шкодить, оскільки це легше дотримуватися, ніж поточна версія.
Річка Рівня Св.

3
Розмір коду, як правило, однозначно ідентифікує будь-яку версію, але історія редагування також доступна для всіх, хто переглядає історію редагування.
mbomb007

9

Сітківка , 150 122 118 байт

До речі, результат цього виклику виглядає приголомшливо!

Введення не одинакове. Вихід містить зворотний канал. У коді використовується ISO 8859-1 кодування. Відзначте пробіл на передостанній лінії.

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

Спробуйте в Інтернеті

Пояснення

Якщо ви хочете більш поглибленого пояснення, коментуйте або повідомте мені у чаті.

(?=_\\¶.*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$* 

Дякую Мартіну за те, що він займався 32 байтами.


6

Мова друку Тармо, 46 байт. (неконкурентоспроможний)

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

Тільки дивлячись на такі дивні мови програмування, як CJam, мені стає запаморочено, наскільки складною, неприродною та виразною мовою може бути те, що я хотів "сміливо йти туди, де ще ніхто не їздив", і вигадати свою власну мову. В результаті я створив свою власну мову для друку шаблонів ascii.

Основна ідея полягає в тому, що ви можете визначити спочатку паттен, а потім друк - використовуючи той самий тип символів '1' або '2' або будь-яке число - ви можете визначити свій власний шаблон друку.

Після того, як шаблон буде визначений (починається від числа до кінця числа) - наступні номери виконуватимуть друк візерунків.

Наприклад

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

Такі результати:

  /\
 /_/\
/__\_\

Визначимо шаблон 1, а потім надрукуємо його відразу. Шаблон визначається всім розділеним знаком "|" характер. 0 в кінці - діє як припинення шаблону.

Спеціальні символи, такі як "$", зарезервовані як подача рядків, а "~" зарезервовано для проміжку - наполовину - певного шаблону.

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

Виводить текст таким чином:

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

Далі йде для-петлі. Це потрібно легко помітити - тому я зберігав {} дужки для for-циклів, але імена змінних автоматично іменуються - тому перша дужка буде використовувати змінну 'a', друга 'b' тощо. Ітерація завжди переходитиме від 0 до певного числа - і це число визначається до {} дужок.

'n' зарезервована змінна для введення всієї функції.

Отже, код:

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

Буде вихід (З n == 4):

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

І "#" - це спеціальний модифікатор для пробілу свинцевих пробілів.

І нарешті ціле рішення:

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
}

З такими аргументами командного рядка: -d "1 / \ | / _ / \ | / ___ \ 2 __ | / 0n {na-1 {½} 1a {2 # 1} $}" 3

Виводить це:

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


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

1
Це справді приголомшливо! Ви повинні поставити це на Github і заохотити людей використовувати його!
DJMcMayhem

3
Ласкаво просимо до головоломки програмування та коду для гольфу! Дуже приємно, що ви винайшли власну мову програмування, але чи остання версія, в якій її можна запустити, передує виклику?
Аднан

Не до кінця зрозумів тебе, що ти кажеш?
ТармоПікаро

Що ж, якщо мова сама новіша, ніж виклик, її прийнято позначати як неконкурентну (досить логічно правильно;)). Це може бути відповідна публікація.
Аднан

Мова залежить від проблемної області, і я не знав, що така проблема існувала, перш ніж я прочитав її звідси. Напевно, я міг би кодувати мову раніше, якщо вже потрапив у подібну проблему. :) У будь-якому разі, збираючи цей сайт, я зрозумів, що CJam - це "нормальна" мова тут. :)
ТармоПікаро

5

JavaScript (ES6), 119 байт

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

Де \nпредставляє буквальний символ нового рядка. Якщо n*3прийнятна провідна лінія з пробілами та новою лінією, то її .slice(1)можна видалити для економії 9 байт.



2

Python 2, 142 байти

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

Принцип дуже схожий на інші відповіді: візьміть три повторювані рядки, а потім розшаруйте їх таким чином, що вам потрібно лише обрізати деякі з них, щоб отримати трикутник, а потім прокладіть їх ліворуч.


2

C ++, 395 байт

Перший тайм-код гольфу зі славним розміром 395 байт у C ++. У моєму випадку це трохи схоже на змагання з притуплення: 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;}}}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.