วาดรูปหกเหลี่ยม ASCII ศูนย์กลาง


15

เขียนโปรแกรมสั้นที่สุดเท่าที่จะเป็นไปได้ในชุดของจำนวนเต็มบวกและเอาท์พุทการเรนเดอร์ ASCII แบบรวมศูนย์ hexagonsด้วยความยาวด้านเหล่านั้นทำจากสแลชขีดล่างช่องว่างและการขึ้นบรรทัดใหม่

โปรแกรมที่สั้นที่สุดในหน่วยไบต์จะถูกนับโดยhttps://mothereff.in/byte-counterชนะ

ตัวอย่าง

(ดูดีขึ้นโดยเว้นระยะบรรทัดน้อยลง)

หากอินพุตคือ1เอาต์พุตควรเป็นรูปหกเหลี่ยมที่มีความยาวด้าน 1:

 __ 
/  \
\__/

โปรดสังเกตว่าขีดล่างสองอันใช้สำหรับด้านบนและด้านล่างของรูปหกเหลี่ยมเพื่อให้มีสัดส่วนที่ดีกว่า

โดยทั่วไปขนาด N หกเหลี่ยมมี N slashes ในแต่ละมุมและ 2 * N ขีดล่างทั้งด้านบนและด้านล่าง

หากอินพุตคือ1 2ผลลัพธ์ควรเป็น hexagons ศูนย์กลางที่มีความยาวด้าน 1 และ 2:

  ____
 / __ \
/ /  \ \
\ \__/ /
 \____/

หากอินพุตเป็น1 3เอาต์พุตควรเป็น:

   ______
  /      \
 /   __   \
/   /  \   \
\   \__/   /
 \        /
  \______/

หากอินพุตเป็น1 3 2เอาต์พุตควรเป็น:

   ______
  / ____ \
 / / __ \ \
/ / /  \ \ \
\ \ \__/ / /
 \ \____/ /
  \______/

เป็นต้น

กฎ I / O

อินพุตต้องมาจากบรรทัดคำสั่งหรือ stdin แต่อาจอยู่ในรูปแบบใดก็ได้ที่สะดวกที่สุด

ตัวอย่างเช่นคุณอาจให้แต่ละหมายเลขเป็นอาร์กิวเมนต์บรรทัดคำสั่ง: > myprogram 1 3 2หรือคุณอาจแจ้งให้ผู้ใช้ป้อนหมายเลขเป็นรายการที่จัดรูปแบบล่วงหน้า:[1, 3, 2]หรือคุณอาจแจ้งให้ผู้ใช้สามารถป้อนข้อมูลตัวเลขที่เป็นรายการที่จัดรูปแบบ:

ผลลัพธ์จะต้องไปที่ stdout หรือภาษาที่ใกล้เคียงที่สุดของคุณ

กฎเพิ่มเติม

  • ข้อมูลที่ป้อนจะเป็นชุดของจำนวนเต็มบวกที่แตกต่างกันเสมอไม่จำเป็นต้องเรียงตามลำดับไม่จำเป็นต้องอยู่ในลำดับใด
  • ผลลัพธ์จะต้อง ...
    • ไม่มีอักขระใด ๆ นอกเหนือจากนี้ /\ _และขึ้นบรรทัดใหม่
    • ไม่มีช่องว่างต่อท้ายหรือช่องว่างนำหน้าที่ไม่จำเป็น
    • ไม่มีการขึ้นบรรทัดใหม่ที่ไม่เกี่ยวข้อง แต่อาจมีการขึ้นบรรทัดใหม่ที่ไม่จำเป็นหนึ่งบรรทัด
  • หากไม่มีการป้อนข้อมูลให้เอาท์พุทอะไรเลย (ยกเว้นอาจเป็นหนึ่งบรรทัดใหม่)
  • ถ้ามันจะช่วยให้คุณอาจคิดว่าจำนวนเต็มการป้อนข้อมูลที่มีน้อยกว่า 2 16

การ1อ้างถึงรูปหกเหลี่ยมด้านในสุดหรือด้านนอกสุด?
NinjaBearMonkey

@hsl The 1(หรือตัวเลขใด ๆ ) หมายถึงรูปหกเหลี่ยมที่มีความยาวด้าน 1 (ด้วยคำเตือนที่ 1 slash = 2 ขีดล่าง) ดังนั้น1จะอ้างถึงรูปหกเหลี่ยมด้านในสุด
งานอดิเรกของ Calvin

คำตอบ:


4

CJam, 148 116 109 109 ไบต์

สิ่งนี้ใช้เวลานานกว่าที่ฉันคาดไว้มาก เดิมทีฉันต้องการสร้างจตุภาคซ้ายบนซ้ำแล้วซ้ำอีกเหมือนในความท้าทายของเพชรและจากนั้นให้เหลือจากการสะท้อน แต่ฉันไม่ได้สังเกตว่าขีดเส้นใต้ไม่เชื่อฟังกระจกสมมาตรระหว่างครึ่งบนและล่าง ดังนั้นฉันต้องทำซ้ำส่วนใหญ่เพื่อสร้างครึ่งทางที่ถูกต้องซ้ำแล้วสะท้อนเพียงครั้งเดียว (ทางซ้าย)

S]2[l~]:(f#:+2bW%{_,2/~:T;{IT):T1<'\'/?S?S++}%__,2/=,2/I'_S?*_S+a@+\I'/S?S++a+}fI{)T)2*2$,-*1$W%"\/"_W%er@N}/

ทดสอบที่นี่

ตัวอย่าง Fibonacci-esque:

8 3 1 5 2
        ________________
       /                \
      /                  \
     /     __________     \
    /     /          \     \
   /     /   ______   \     \
  /     /   / ____ \   \     \
 /     /   / / __ \ \   \     \
/     /   / / /  \ \ \   \     \
\     \   \ \ \__/ / /   /     /
 \     \   \ \____/ /   /     /
  \     \   \______/   /     /
   \     \            /     /
    \     \__________/     /
     \                    /
      \                  /
       \________________/

คำอธิบาย:

ตามที่ระบุไว้ด้านบนฉันเริ่มต้นด้วยการสร้างครึ่งทางขวาซ้ำ ๆ นั่นคือตอนแรกฉันมีเพียงช่องว่างเดียวในกริดและจากนั้นสำหรับวงแหวนที่เป็นไปได้แต่ละอันฉันจะล้อมรอบกริดที่มีอยู่ในช่องว่างหรือกึ่งหกเหลี่ยมใหม่

เมื่อทำเสร็จแล้วฉันจะสะท้อนแต่ละบรรทัดไปทางซ้ายและวางด้วยช่องว่างนำหน้าเพื่อจัดแนวที่ถูกต้อง นี่คือรายละเอียดของรหัส:

"Prepare the input and the grid:";
S]2[l~]:(f#:+2bW%
S]                "Push string with a space and wrap it in an array. This is the grid.";
  2               "Push a 2 for future use.";
   [l~]           "Read and evaluate the input, wrap it in an array.";
       :(         "Decrement each number by 1.";
         f#       "Map each number i to 2^i.";
           :+     "Sum them all up.";
             2b   "Get the base two representation.";
               W% "Reverse the array.":
"At this point, the stack has the proto-grid at the bottom, and an array of 1s and
 0s on top, which indicates for each hexagon if it's present or not.";

"Next is a for loop, which runs the block for each of those 0s and 1s, storing the
 actual value in I. This block adds the next semi-hexagon or spaces.";
{ ... }fI

"First, append two characters to all existing lines:";
_,2/~:T;{IT):T1<'\'/?S?S++}%
_                            "Duplicate the previous grid.";
 ,2/                         "Get its length, integer-divide by 2.";
    ~:T;                     "Get the bitwise complement and store it in T. Discard it.";
        {                 }% "Map this block onto each line of the grid.";
         I                   "Push the current hexagon flag for future use.";
          T):T               "Push T, increment, store the new value.";
              1<'\'/?        "If T is less than 1, push \, else push /.";
                     S?      "If the current flag is 0, replace by a space.";
                       S++   "Append a space and add it to the current line.";

"So for hexagons this appends '\ ' to the top half and '/ ' to the bottom half.
 For empty rings, it appends '  ' to all lines.";

"Now add a new line to the top and the bottom:"    
__,2/=,2/I'_S?*_S+a@+\I'/S?S++a+
__                               "Get two copies of the grid.";
  ,2/                            "Get its length, integer-divide by 2.";
     =                           "Get that line - this is always the middle line.";
      ,2/                        "Get ITS length, integer'divide by 2.";
         I'_S?*                  "Get a string of that many _ or spaces depending on the 
                                  current flag.";
               _S+               "Duplicate and a space.";
                  a@+            "Wrap in an array, pull up the grid, and prepend the line.";
                     \           "Swap with the other copy.";
                      I'/S?      "Choose between / and a space depending on the flag.";
                           S++   "Append a space, and add both characters to the line.";
                              a+ "Wrap in an array, and append line to the grid.";

"This is all. Rinse and repeat for all rings. The result will look something like this:

_____ 
     \ 
___   \ 
__ \   \ 
_ \ \   \ 
 \ \ \   \ 
_/ / /   / 
__/ /   / 
___/   / 
      / 
_____/ 

Note that there are still trailing spaces.";

"Finish up all lines. These will not be joined together any more, but simply left
 on the stack in pieces to printed out back-to-back at the end of the program.
 The following runs the given block for each line:";
{ ... } /

"This generates the necessary indentation, then mirrors the lines and puts them
 in the right order:"
)T)2*2$,-*\_W%"\/"_W%er\N
)                         "Slice off that trailing space, but leave it on the stack.";
 T                        "Remember T? That still has something like the the size of
                           the grid from the last iteration. In fact it's N-1, where
                           N is the largest visible hexagon. We can use that to figure
                           out how many spaces we need.";
  )2*                     "Increment and double.";
     2$                   "Copy the current line.";
       ,-                 "Subtract its length from 2*N.";
         *                "Repeat the space that often. This is our indentation.";
          \_              "Swap with the line and duplicate.";
            W%            "Reverse the line.";
              "\/"_W%er   "Replace slashes with backslashes and vice versa.";
                       \  "Swap with the original line.";
                        N "Push a line break.";

5

Python - 251, 240, 239 228

l=input()+[0];m=max(l);A=abs;R=range
for j in R(2*m+1):print''.join([[' \\'[(A(j-i+m-1)/2.in l)*(2*m-i)/(j-m-.5)>1],'/'][(A(3*m-i-j)/2.in l)*(i-m-j+.5)/(j-.5-m)>0],'_'][(A(m-j)in l)*(A(2*m-i-.5)<A(m-j))]for i in R(4*m)).rstrip()

ทางเลือกวิธี (251):

l=input()+[0]
l.sort()
m=max(l)
M=2*m
s=[[' ']*m*4for j in' '*(M+1)]
for i in l:
 I=2*i;s[m-i][M-i:M+i]=s[m+i][M-i:M+i]='_'*I
 for k in range(i):K=k+1;s[m-k][M-I+k]=s[m+K][M+I-K]='/';s[m-k][M+I-K]=s[m+K][M-I+k]='\\'
for t in s:print''.join(t).rstrip()

3

APL (222 ไบต์ใน UTF-8)

(และ 133 ตัวอักษร)

เนื่องจากคำถามนี้ถามจำนวนไบต์ในการแทน UTF8 โดยเฉพาะฉันจึงต้องถอดออกเล็กน้อยเพื่อให้ยาวขึ้น แต่การแสดง UTF8 นั้นสั้นกว่า (โดยเฉพาะอย่างยิ่งอักขระของโอเปอเรเตอร์การเดินทางคือสามไบต์ในขณะที่()มีเพียงสองเท่านั้นดังนั้นการปรับให้เหมาะสมจะไม่ทำงานอีกต่อไปและยังทำให้การกำหนดมีราคาแพงมาก)

{⎕←(~⌽∧\⌽⍵=' ')/⍵}¨↓⊃{⍵{⍺=' ':⍵⋄⍺}¨K↑(-.5×(K←⍴⍵)+⍴⍺)↑⍺}/{Z⍪⌽⊖Z←↑(⊂(⍵/' '),(2×⍵)/'-'),⍵{((-⍵)↑'/'),((2 4-.×⍵⍺)/' '),'\'}¨⌽⍳⍵}¨N[⍋N←,⎕]

เวอร์ชันก่อนหน้านี้ซึ่งสั้นกว่าในตัวละคร (124) แต่ใช้ไบต์มากขึ้นเมื่อแสดงใน UTF-8 (230 ซึ่งจะใส่ไว้ในตำแหน่งที่สอง):

M←' '⋄{⎕←⍵/⍨~⌽∧\⌽⍵=M}¨↓⊃{⍵{⍺=M:⍵⋄⍺}¨K↑⍺↑⍨-.5×(K←⍴⍵)+⍴⍺}/{Z⍪⊖⌽Z←↑(⊂(⍵/M),'-'/⍨2×⍵),⍵{('/'↑⍨-⍵),'\',⍨M/⍨2 4-.×⍵⍺}¨⌽⍳⍵}¨N[⍋N←,⎕]

ทดสอบ:

      {⎕←(~⌽∧\⌽⍵=' ')/⍵}¨↓⊃{⍵{⍺=' ':⍵⋄⍺}¨K↑(-.5×(K←⍴⍵)+⍴⍺)↑⍺}/{Z⍪⌽⊖Z←↑(⊂(⍵/' '),(2×⍵)/'-'),⍵{((-⍵)↑'/'),((2 4-.×⍵⍺)/' '),'\'}¨⌽⍳⍵}¨N[⍋N←,⎕]
⎕:
      3 1 5 2
     ----------
    /          \
   /   ------   \
  /   / ---- \   \
 /   / / -- \ \   \
/   / / /  \ \ \   \
\   \ \ \  / / /   /
 \   \ \ -- / /   /
  \   \ ---- /   /
   \   ------   /
    \          /
     ----------

สิ่งนี้ดูเหมือนจะไม่ตรงตามข้อกำหนดสำหรับด้านบนและด้านล่าง (ควรเป็นขีดล่างไม่ใช่ยัติภังค์) และจึงถูกชดเชยด้วยบรรทัดเดียวสำหรับด้านล่าง
Martin Ender

1

Perl 5, 352 (349 ไบต์ + 3 สำหรับ anEธง)

นี่อาจเป็นเรื่องที่ต้องตีกอล์ฟมากขึ้น ..

@b=sort{$a>$b}@F;map{$_<$j||($j=$_)}@b;$k=++$j;for(;$j--;){$z=$"x$j;for($e=$k;--$e>$j;){$z.=$e~~@b?'/ ':'  '} $z.=($j~~@b?'_':$")x(2*$j);$z.=$_~~@b?' \\':'  'for($j+1..$k-1);say$z}for(0..$k-2){$z=$"x$_;for($e=$k;--$e>$_;){$z.=($e-$k+1?$":'').($e~~@b?'\\':$")}$z.=(($_+1)~~@b?'_':$")x(2*$_+2);$z.=($_~~@b?'/':$").($_-$k+1?$":'')for($_+1..$k-1);say$z}

Ungolfed:

# sort list of side lengths 
@b=sort{$a>$b}@F; 
# set $k and $j to max side length + 1
map{$_<$j||($j=$_)}@b;$k=++$j;
for(;$j--;){
  $z=$"x$j;
  for($e=$k;--$e>$j;){$z.=$e~~@b?'/ ':'  '}
  $z.=($j~~@b?'_':$")x(2*$j);
  $z.=$_~~@b?' \\':'  'for($j+1..$k-1);
  say$z
}
for(0..$k-2){
  $z=$"x$_;
  for($e=$k;--$e>$_;){$z.=($e-$k+1?$":'').($e~~@b?'\\':$")}
  $z.=(($_+1)~~@b?'_':$")x(2*$_+2);
  $z.=($_~~@b?'/':$").($_-$k+1?$":'')for($_+1..$k-1);
  say$z 
}

ตัวอย่าง ( 1 5 3 14):

              ____________________________
             /                            \
            /                              \
           /                                \
          /                                  \
         /                                    \
        /                                      \
       /                                        \
      /                                          \
     /                 __________                 \
    /                 /          \                 \
   /                 /   ______   \                 \
  /                 /   /      \   \                 \
 /                 /   /   __   \   \                 \
/                 /   /   /  \   \   \                 \
\                 \   \   \__/   /   /                 /
 \                 \   \        /   /                 /
  \                 \   \______/   /                 /
   \                 \            /                 /
    \                 \__________/                 /
     \                                            /
      \                                          /
       \                                        /
        \                                      /
         \                                    /
          \                                  /
           \                                /
            \                              /
             \____________________________/

1

C # - 388 316 ไบต์

แก้ไข: เปลี่ยนวิธีหลีกเลี่ยงการพิมพ์ช่องว่างต่อท้ายและโยนใน LINQ บางส่วน

โปรแกรมอย่างง่ายที่รับอาร์กิวเมนต์บรรทัดคำสั่ง มันวนซ้ำทุกอักขระที่เป็นไปได้ในแต่ละบรรทัดของสี่เหลี่ยมผืนผ้าที่กำหนดโดยมิติหกเหลี่ยมสูงสุดและต่อท้ายบรรทัดปัจจุบันก่อนที่จะตัดเส้นและพิมพ์ให้ต่อเนื่องกัน (มันจะสร้างบรรทัดใหม่ที่เป็นทางเลือก)

รหัส Golfed:

using System.Linq;class P{static void Main(string[]A){var I=A.Select(int.Parse);int m=I.Max(),i,j,y,x;for(j=m+1;j-->-m;){var r="";for(i=-2*m-1;++i<2*m-(y=j<0?-j-1:j);)r+="/\\_- "[(x=i<0?-i-1:i)>y&(x+=y)%2>0&x/2<m&&I.Contains(x/2+1)?(i^j)&1:x-y<(y=j<0?-j:j)&y<=m&I.Contains(y)?j<0?2:3:4];System.Console.WriteLine(r);}}}

รหัสไม่ได้รับการตอบกลับ:

using System.Linq; // all important

class P
{
    static void Main(string[]A)
    {
        var I=A.Select(int.Parse); // create int array

        for(int m=I.Max(),j=m+1,i,y,x;j-->-m;) // for each line...
        {
            var r=""; // current line

            for(i=-2*m-1;++i<2*m-(y=j<0?-j-1:j);) // for each char...
                r+="/\\_- "[// append something to the current line
                (x=i<0?-i-1:i)>y&(x+=y)%2>0&x/2<m&&I.Contains(x/2+1)?
                    (i^j)&1: // slashes as appropriate - I can't work out why this bit works, but it seems to
                x-y<(y=j<0?-j:j)&y<=m&I.Contains(y)?
                    j<0?2:3: // _ or - if required
                4]; // otherwise a space

            System.Console.WriteLine(r); // print current line
        }
    }
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.