Bangun segitiga tanpa segitiga


44

Sebagai anak kecil, saya sangat suka bermain dengan mainan ini:

masukkan deskripsi gambar di sini

Mereka mungkin bermaksud agar ini digunakan untuk seni, tetapi saya selalu menggunakannya untuk matematika! Fraktal, pola, dll. Suatu kali, saya diberi tantangan ini:

Bangun segitiga tanpa menggunakan ubin segitiga hijau.

Tantangan ini membuat saya bingung untuk waktu yang paling lama, sampai saya menemukan cara yang sangat indah dan sederhana untuk melakukannya hanya dengan 3 trapesium:

  /\  
 /_/\ 
/__\_\

Sekarang, ambil segitiga ini, dan putar:

______         
\ \__/         
 \/ /          
  \/ 

Dengan menggunakan dua segitiga ini, kita dapat membuat segitiga yang lebih besar darinya. Berikut adalah segitiga dengan ketinggian 2:

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

Dan berikut adalah segitiga dengan ketinggian 3-7:

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

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

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

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

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

Tantangan

Menulis sebuah program atau fungsi yang mengambil nomor n dan mencetak segitiga segitiga-kurang tinggi n . Ruang tambahan pada setiap baris dapat diterima, dan hingga satu trailing atau baris baru juga dapat diterima. IO dapat dalam format apa pun yang masuk akal. Masukan dijamin menjadi bilangan bulat positif, jadi Anda tidak perlu khawatir tentang angka negatif, desimal, bukan angka, dll.

Jawaban terpendek dalam byte menang!


Cobalah membuat lebih banyak trapesium dari trapesium. Panjang 2 dan 3 pasti dimungkinkan (dan dengan ekstensi, semua angka dari formulir 2 ^ a * 3 ^ b) (Bagaimana saya tahu? Dimainkan dengan jenis balok yang sama ketika saya masih kecil.)
CalculatorFeline

1
@CatsAreFluffy Nah, karena Anda dapat membuat trapesium dari segitiga, Anda dapat menyimpulkan bahwa Anda dapat membuat trapesium dari trapesium. Bahkan, jika Anda melihat segitiga dengan tinggi 3 dan 7, Anda bisa melihat pola yang sama diulang dengan trapesium besar.
DJMcMayhem

Tantangan ini sangat keren. Saya senang mencari tahu bagaimana melakukan ini di Retina.
mbomb007

@ mbomb007 Senang mendengar Anda menikmatinya! = D Itulah mengapa saya menulis tantangan.
DJMcMayhem

2
Tantangan ini sangat cocok di layar dengan aplikasi seluler. Apakah itu disengaja? :)
Doddy

Jawaban:


15

CJam, 47

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

Penjelasan:

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

Cobalah online


17

Ruby, 79

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

A. (-4 bytes, -1 +1) berubah dari 0-diindeks ( .times) menjadi 1-diindeks ( 1.upto)

B. (-5 byte) diubah dari array tiga string 6-char ke pemilihan substring 6-char dari string 18-char.

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

D. (-5 byte) mengurangi lima backslash ganda menjadi backslash tunggal (sebagian dimungkinkan oleh penataan ulang string yang diperlukan untuk titik A)

Ruby, 94

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

penjelasan

Unit dasar adalah berlian 3x6 sebagai berikut (karakter terakhir pada setiap baris diduplikasi untuk kejelasan :)

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

Yang perlu kita lakukan hanyalah menampilkan jendela yang sesuai dengan pola ini. Ruby ljustmemungkinkan Anda untuk menggunakan string apa pun, bukan hanya spasi. Biasanya ljustakan digunakan untuk membuat string karakter yang dapat dicetak dengan menambahkan spasi di bagian akhir, tetapi di sini kita menggunakannya secara terbalik: untuk membuat string spasi dengan menambahkan karakter yang dapat dicetak di bagian akhir.

ungolfed dalam program tes

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 Ini pertama kalinya saya mengalami keluhan itu. Sebagai seorang insinyur, saya sudah terbiasa untuk merevisi segala sesuatu. Ini adalah tantangan yang cukup sederhana dan perbaikannya cukup sepele, jadi saya sudah maju dan menghapus surat revisi. Saya pikir membiarkan kode asli baik atau setidaknya tidak ada ruginya, karena lebih mudah diikuti daripada versi saat ini.
Level River St

3
Ukuran kode biasanya secara unik mengidentifikasi revisi apa pun, tetapi riwayat revisi juga tersedia untuk siapa saja yang melihat riwayat edit.
mbomb007

9

Retina , 150 122 118 byte

Omong-omong, output dari tantangan ini tampak luar biasa!

Masukan dalam bentuk unary. Outputnya berisi linefeed baris tambahan. Kode ini menggunakan pengkodean ISO 8859-1. Perhatikan ruang trailing pada garis kedua dari belakang.

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

Cobalah online

Penjelasan

Jika Anda ingin penjelasan yang lebih mendalam, beri komentar atau pesan saya dalam obrolan.

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

Terima kasih kepada Martin untuk bermain golf dengan 32 byte.


6

Bahasa cetak ascii Tarmo, 46 ​​byte. (tidak bersaing)

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

Hanya dengan melihat ke bahasa pemrograman aneh seperti CJam, itu membuat saya sedikit pusing betapa rumit, tidak wajar dan samarnya bahasa itu, sehingga saya ingin "dengan berani pergi ke tempat yang belum pernah dikunjungi orang sebelumnya", dan menciptakan bahasa saya sendiri. Sebagai hasilnya saya membuat bahasa saya sendiri untuk pencetakan pola ascii.

Ide dasarnya adalah Anda dapat menetapkan pola pertama dan kemudian mencetak - menggunakan karakter yang sama '1' atau '2' atau nomor apa pun - Anda dapat menentukan pola cetak Anda sendiri.

Setelah pola didefinisikan (Mulai dari nomor hingga nomor berakhir) - nomor berikutnya akan menjalankan pencetakan pola.

Sebagai contoh

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

Output seperti ini:

  /\
 /_/\
/__\_\

Akan menentukan pola 1 dan kemudian mencetaknya segera. Pola didefinisikan semuanya dipisahkan dengan '|' karakter. 0 di akhir - bertindak seperti terminasi pola.

Karakter khusus seperti '$' dicadangkan sebagai umpan baris, dan '~' dicadangkan untuk penspasian - setengah - dari pola tertentu.

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

Akan menampilkan teks seperti ini:

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

Selanjutnya berlaku untuk-loop. Yang satu itu harus mudah terlihat - jadi saya mempertahankan kurung {} untuk for-loop, tetapi nama variabel bernama otomatis - jadi braket pertama akan menggunakan variabel 'a', kedua 'b' dan seterusnya. Iterasi akan selalu berubah dari 0 ke angka tertentu - dan angka itu ditentukan sebelum kurung {}.

'n' adalah variabel yang dipesan untuk input fungsi keseluruhan.

Jadi kode:

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

Akan menampilkan (Dengan n == 4):

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

Dan '#' adalah pengubah khusus untuk spasi putih timbal trim.

Dan akhirnya seluruh solusi:

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
}

Dengan argumen baris perintah seperti ini: -d "1 / \ | / _ / \ | / ___ \ 2 __ | / 0n {na-1 {½} 1a {2 # 1} $}" 3

Akan menampilkan ini:

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
Benar-benar hebat! Anda harus memasang itu di Github dan mendorong orang untuk menggunakannya!
DJMcMayhem

3
Selamat Datang di Programming Puzzles dan Code Golf! Sangat menyenangkan bahwa Anda menemukan bahasa pemrograman Anda sendiri, tetapi apakah versi terbaru yang dapat dijalankannya mendahului tantangan?
Adnan

Tidak sepenuhnya mengerti Anda, apa yang Anda katakan?
TarmoPikaro

Nah, jika bahasa itu sendiri lebih baru daripada tantangan, itu umum untuk menandainya sebagai non-bersaing (cukup logis;)). Ini mungkin posting yang relevan.
Adnan

Bahasa tergantung pada domain masalah, dan saya tidak tahu masalah seperti itu ada sebelum saya membacanya dari sini. Saya kira saya sudah bisa kode bahasa sebelumnya jika saya sudah menemukan masalah yang sama. :) Ngomong-ngomong, dengan memanen situs ini saya mengerti bahwa bahasa CJam cukup "normal" di sini. :)
TarmoPikaro

5

JavaScript (ES6), 119 byte

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

Dimana \nmewakili karakter baris baru literal. Jika garis depan dengan n*3spasi dan baris baru dapat diterima maka .slice(1)dapat dihapus untuk menghemat 9 byte.



2

Python 2, 142 byte

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

Prinsipnya sangat mirip dengan jawaban lain: ambil tiga string berulang dan kemudian lapis sedemikian rupa sehingga Anda hanya perlu memotong beberapa dari mereka untuk mendapatkan segitiga, kemudian pad mereka di sebelah kiri.


2

C ++, 395 Bytes

Golf kode waktu pertama dengan ukuran mulia 395 byte dalam C ++. Dalam kasus saya, rasanya seperti kontes untuk kebingungan: 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;}}}

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.