每日ASCII艺术#1-双结


47

编写一个完整程序或一个函数,该程序或函数需要一个正整数N作为通过STDIN /命令行/ ARGV或函数参数的输入,并打印一个N与STDOUT 相对应的ASCII双结。

ASCII双结看起来像这样:

  __  __  __  __  __  __
 /  \/  \/  \/  \/  \/  \
| /\/ /\/ /\/ /\/ /\/ /\ |
| \/ /\/ /\/ /\/ /\/ /\/ |
 \ \/\ \/\ \/\ \/\ \/\ \/
 /\ \/\ \/\ \/\ \/\ \/\ \
| /\/ /\/ /\/ /\/ /\/ /\ |
| \/ /\/ /\/ /\/ /\/ /\/ |
 \__/\__/\__/\__/\__/\__/

以上是针对 N = 6

对于以下其他值,这还有一些其他问题N

如果为N = 1,则输出双结看起来像:

  __
 /  \
| /\ |
| \/ |
 \ \/
 /\ \
| /\ |
| \/ |
 \__/

对于N = 2

  __  __ 
 /  \/  \
| /\/ /\ |
| \/ /\/ |
 \ \/\ \/
 /\ \/\ \
| /\/ /\ |
| \/ /\/ |
 \__/\__/

对于N = 3

  __  __  __ 
 /  \/  \/  \
| /\/ /\/ /\ |
| \/ /\/ /\/ |
 \ \/\ \/\ \/
 /\ \/\ \/\ \
| /\/ /\/ /\ |
| \/ /\/ /\/ |
 \__/\__/\__/

并且类似地,模式继续,并且任何更大的值N

详细资料

  • 输入始终是大于的正整数0
  • 尾随换行符是可选的
  • 每行应该没有尾随空格,或者应该有足够的尾随空格以使每行的长度为4*N + 2
  • 绝不应该有任何不属于指定模式的前导空格。

这是,因此以字节为单位的最短代码获胜。


系列排行榜

我将其转换为一系列ASCII艺术挑战,因此增加了该系列的排行榜(Martin的片段)。为确保您的答案显示出来,请使用以下Markdown模板以标题开头每个答案:

# Language Name, N bytes

其中N是您提交的文件的大小。如果您提高了分数,则可以通过打败旧分数来保持标题。例如:

# Ruby, <s>104</s> <s>101</s> 96 bytes


到目前为止的系列

1.双结

2.流蛇

3.中国神社

4.黄道十二宫

5.随机的瓷砖


1
为什么对于N = 3,右边缘会有所不同?
aditsu

@aditsu哈哈 4天,3K观看,11个答案,您是第一个注意到它的人:D。固定!
Optimizer

Answers:


12

CJam,55个字节

我很讨厌这个书呆子……无论如何,我终于想出了55个字节的ISO 8859-1:

"²îå<63Åhbغ¢dräOä[æTZ"246b5b"|_ \/"f=9/4/~2/\ri*2>*zN*

或这种选择

"ô/Ht]õDz1M;í,D¯Tmä$:r"246b5b"_/\ |"f=9/2/~+ri*2>\++zN*

最初,我尝试以纯ASCII格式进行处理,但最终只减少到58个字节

"C]VA~`+-WIt*n_I?FanSEo*b"128b5b"_/|\ "f=9/4/~2/\ri*2>*zN*

再一次,一种选择

"1,*Ap7c?UvI$yQHqHqs~=}n"153b5b"_ /|\\"f=9/2/~+ri*2>\++zN*

说明:

这个想法是用一种方便的方式对独特的部分(左边缘,右边缘和中间模式)进行编码,根据需要重复中间部分,然后将它们放在一起。该代码最终在许多方面与Dennis的答案相似。我没有尝试复制他,但是我尝试了许多不同的方法(包括利用更多的对称性和重复性),这是最有效的方法。

我将左右边缘像这样放在一起:

    
 /\ 
|  |
|  |
 \/ 
 /\ 
|  |
|  |
 \/ 

中间的模式有4列,但它们重复N-0.5次,即将一个重复切成两半。为了方便起见,我使用了以下模式:

  __
\/  
/ /\
 /\/
/\ \
\/\ 
/ /\
 /\/
/\__

并删除了第一次重复的前半部分。

因此,我加入了这些部分并以转置形式对它们进行了编码,因为这样可以更轻松地使用它们。第一个和第三个程序对该字符串进行编码:

 \/ /\/ /
 / /\/ /\
_ /\ \/\_
_ \/\ \/_
  ||  || 
 /  \/  \
 \  /\  /
  ||  || 

(没有换行符),这是中间+边的转置。第二个程序和第四个程序(“替代”)对该字符串进行编码:

  ||  || 
 /  \/  \
 \  /\  /
  ||  || 
 \/ /\/ /
 / /\/ /\
_ /\ \/\_
_ \/\ \/_

同样,没有换行符,这是边线+中间线的换位。

这是代码的通用部分的工作方式:

"…"        encoded string (constructed via the reverse process,
           using a suitable base that gives valid characters)
246b       convert the string to an integer, treating each character as a digit
           in base 246 (or other bases in the ASCII versions)
5b         convert the number to base 5, obtaining 72 digits from 0 to 4,
           representing the 5 different characters we have
"|_ \/"f=  convert the digits to their corresponding characters
           (each program uses a different assignment order)
9/         split the resulting strings into 8 strings of 9 characters
           if viewed as lines, they look exactly like the 2 patterns shown above

此后,实现方式略有不同。在第一个和第三个程序中,我们有:

4/     split the lines into groups of 4 - the middle part and the edges
~      dump the two 4-line parts onto the stack
2/     split the second part (the edges) into 2 groups of 2 lines
       (left edge and right edge)
\      swap the edges with the middle part
ri*    read the input, convert to integer (N) and repeat the middle part N times
2>     remove the first 2 lines (first half of first repetition)
*      join the 2 edges using the repeated middle part as a separator
z      transpose the result back to the desired form
N*     join with newlines

在第二和第四(替代)程序中,我们具有:

2/     split the lines into groups of 2
       (left edge, right edge, middle first half, middle 2nd half)
~      dump all the groups onto the stack
+      join the two middle halves into a single middle group of 4 lines
ri*    read the input, convert to integer (N) and repeat the middle part N times
2>     remove the first 2 lines (first half of first repetition)
\      swap the repeated middle with the right edge
+      concatenate the middle with the right edge
+      concatenate the left edge with the rest
z      transpose the result back to the desired form
N*     join with newlines

我不确定我要1>W<缩短多长时间。原来,我只需要旋转数组就可以对其进行编码并使用2>...
Dennis

23

CJam,103 92 83 69 66 57字节

"O5àäªÞáKZò,_÷%SJ«Ò"248b5b"/ \_|"f=9/4/~ri*1>W<+2m<zN*

CJam解释器中在线尝试。

理念

一旦我们将行与列进行转置(在右边用空格填充),该模式将变得更加明显。

例如,对于输入3,它给出:

  ||  || 
 /  \/  \
_ /\ \/\_
_ \/\ \/_
 \/ /\/ /
 / /\/ /\
_ /\ \/\_
_ \/\ \/_
 \/ /\/ /
 / /\/ /\
_ /\ \/\_
_ \/\ \/_
 \  /\  /
  ||  || 

前两行和后两行是特殊的,但其他行一遍又一遍地重复相同的模式。

因此,对于输入N,我们要做的就是重复

 / /\/ /\
_ /\ \/\_
_ \/\ \/_
 \/ /\/ /

N次,将第一行替换为

  ||  || 
 /  \/  \

最后一行

 \  /\  /
  ||  || 

最后,将行与列进行转置。

"O5àäªÞáKZò,_÷%SJ«Ò"

248b  e# Convert the string (array of code points in base 248) to an integer.
5b    e# Convert the integer to the array of its digits in base 5.

      e# This pushes the following array:

      e# [ 1 2 1 1 0 2 1 1 0 1 1 4 4 1 1 4 4 1 1 1 4 4 1 1
      e#   4 4 1 1 0 1 1 2 0 1 1 2 1 0 1 0 2 0 1 0 2 3 1 0
      e#   2 1 2 0 2 3 3 1 2 0 2 1 2 0 3 1 2 0 1 0 2 0 1 0 ]

"/ \_"

f=    e# Retrieve the chars that correspond to the indexes in the array.

      e# This pushes the following string:

      e# " \  /\  /  ||  ||   ||  ||  /  \/  \ / /\/ /\_ /\ \/\__ \/\ \/_ \/ /\/ /"

9/4/~ e# Divide into groups of 4 strings of length 9.

      e# This pushes the following arrays:

      e# [ " \  /\  /"   "  ||  || "   "  ||  || "   " /  \/  \" ]
      e# [ " / /\/ /\"   "_ /\ \/\_"   "_ \/\ \/_"   " \/ /\/ /" ]

ri    e# Read an integer from STDIN.
*     e# Repeat the last array that many times.
1>W<  e# Remove the first and last string from the array.
+     e# Concatenate both arrays.
2m<   e# Rotate the concatenated arrays two elements to the left.
z     e# Zip the array of strings (transpose rows with columns).
N*    e# Join the strings of the array, separating by linefeeds.

12

使用Javascript(ES7草案),169个 163 160 158字节

编辑:-6通过使用模板字符串从模式字符串中消除一些重复。

编辑:-3通过重新排列模式字符串从切换slice(0,-2)slice(2)

编辑:-2通过循环b而不是aa字符串取模并减少为4。

F=N=>[(a='  ||'[i%4])+b[i]+`  __0\\/ ${c=' 0/ /\\0 /\\/0/\\'} \\0\\/\\${c}__`.split(0)[i].repeat(N).slice(2)+(b+b)[9-i]+a for(i in b=' /  \\/  \\')].join(`
`)
<input id="stdin" value="4" />
<button onclick="stdout.innerHTML=F(stdin.value)">Run</button><br />
<pre id="stdout"></pre>

评论:

F=N=>[ // define function F, start array comprehension to generate each line
    (a = '  ||'[i % 4]) + // first character of the line, store copy in a
    b[i] + // second character of each line
        `  __0\\/ ${c=' 0/ /\\0 /\\/0/\\'} \\0\\/\\${c}__`. 
        // list of patterns for each line delimited by 0's
        // results in string: '  __0\/  0/ /\0 /\/0/\ \0\/\ 0/ /\0 /\/0/\__'
        split(0)[i]. // split by 0, get index at i
        repeat(N). // repeat N times
        slice(2) + // chop off the first 2 characters
    (b + b)[9 - i] + // get opposite of second character, b+b to get a space at index 9
    a // repeat first character (a)
    for(i in b = ' /  \\/  \\') // runs for each index in character map b
].join(` // join resulting array with newlines
`)

我觉得你可以先更换串.split(0)('__ 0 '+(r='\\/0/\\/ 0\\/ /0 ')+r+'0\\/ /0__/\\')
flawr

@flawr我可以使用类似的方法将其压缩得更深:)
nderscore 2015年

如果您通过0它,您将看到一个8
伊斯梅尔·米格尔

这些是什么`` ${...}确切地是做什么的?
flawr

@flawr反引号`语法声明一个模板字符串。里面的任何内容${}都将作为javascript表达式求值。
nderscore 2015年

9

Perl中,134 129

print s/...\K.{4}/$&x~-"@ARGV"/er=~y!iolp!| /\\!r,$/for
map/i/?$_.oi:"o$_$_".o,o__o,loop,@x=(iolplolp,ioplolpl),popl,lpop,@x,p__l

采用命令行参数:

$ perl ~/knot.pl 3
  __  __  __  
 /  \/  \/  \ 
| /\/ /\/ /\ |
| \/ /\/ /\/ |
 \ \/\ \/\ \/ 
 /\ \/\ \/\ \ 
| /\/ /\/ /\ |
| \/ /\/ /\/ |
 \__/\__/\__/ 

8

JavaScript的(ES6),165 166

结元素:

  • 2顶行,基于重复的“ __”和“ / \”
  • 2个外部行,基于“ / \ /”重复并括在“ |”中 ... |'
  • 2个内部行,基于重复的'\ / \'并括在'... /'和'/ ... \'中
  • 上面相同的2个外部行
  • 重复基于'\ __ /'的1个底行

不打高尔夫球

K=r=>
{
  R = x => x.repeat(r);
  S = d => R(elem).slice(d,d-2); // use global 'elem' that must be assigned before the call
  elem = '/\\/ '
  outer = '\n| ' + S(0) + ' |\n| ' + S(1) + ' |\n '
  elem = '\\ \\/'
  inner = '\\' + S(1) + '/\n /' + S(0) + '\\'
  return R('  __') + '\n ' + R('/  \\') + outer
  + inner + outer + R('\\__/')
}

打高尔夫球

K=r=>(S=d=>(R=e=>e.repeat(r))(e).slice(d,d-2),o=`
| ${S(0,e='/\\/ ')} |
| ${S(1)} |
 `,R('  __')+`
 ${R('/  \\')+o}\\${S(1,e='\\ \\/')}/
 /${S(0)}\\${o}`+R('\\__/'))

// TEST

function go() {
  O.innerHTML=K(I.value)
}

go()
<input id=I value=5><button onclick='go()'>-></button><br>
<pre id=O></pre>


2
尝试传递0给它,您将得到一只四足蜘蛛。
伊斯梅尔·米格尔

8

C ++,1530 639 479

这看起来像是一个有趣的挑战,我与摘要略有不同。

#include "stdafx.h"
#include <iostream>
#include <sstream>
using namespace std;
string a=" __ ",b="/  \\",c=" /\\",d="/\\/ ",f="\\ \\/",g="/\\\ \\",r="\\__/",o="",e=o,j="|";
string q(int n,string r,string x="",string m=" ",string t=" "){string z=o;for(int i=0;i<n;i++){z+=r;if(i!=n-1)z+=x;}return m+z+t+"\n";}
int main(){int x,y;cin>>x;cin>>y;e+=q(x,a)+q(x,b);for(int i=0;i<y;i++){e+=q(x,c,"/",j," |")+q(x-1,d,o,"| \\/ ",j);if(i!=y-1){e+=q(x,f)+q(x,g);}}e+=q(x,r);cout<<e;}

我不确定如何测量应用程序大小的字节,但我会尝试找出答案并更新答案。

我的应用程序可能更小,但它同时在x和y中循环,我有点喜欢:D


1
欢迎来到PPCG!分数就是源代码的大小,即1530个字节。您可以通过删除注释和空格来开始保存字节,并缩短变量和函数名称。
丹尼斯

Wowzor那比其他人还大,哈哈,我将继续努力下去:D
太空人2015年

6

Python 2中,156 151 147 141 139

编辑1:编辑为使用input()代替函数。

编辑2:使用str.join并添加到var c中以删除一些多余的字符。

编辑3:删除了一些不必要的字符串转义序列。

编辑4:用〜-n代替a = n-1

这是编程的乐趣,这是我的第一个代码高尔夫球!

n=input()
a='/\/ '*~-n
b='\ '+'\/\ '*~-n+'\\'
c='\n| '+a+'/\ |\n| \/ '+a+'|'
print'\n '.join(('  __'*n,'/  \\'*n+c,b+'/','/'+b+c,'\__/'*n))

以n.py的形式将其保存在外部文本编辑器中,以删除最后一个换行符,以将文件大小减少1个字节,然后运行该模块并输入您的号码。


如果您允许在程序执行语句后立即输入数字,那么我可以将其进一步缩减为151个字节
-micsthepick

input ()从STDIN读取时通常认为还可以。
Seequ

我看到您a=n-1节省了*(n-1)两次写作的费用,但是您这样做了*~-n
xnor 2015年

两种方式的字符数仍然相同,因为我两次使用了该值,但提示不错。
micsthepick

您可以在python处理字符串中的反斜杠的方式上节省一些字节,而不必总是对其进行编码。请参阅stackoverflow.com/a/16973452/3351622
Matty 2015年

5

Python 2中,139个 133 129字节

n=input()
for i in range(9):w=' ?|'[i&2];s=' / /\/ /\_ /\ \/\__ \/\ \/_ \/ /\/ /'[i::9]*n;s=(s,' %s '%s[1:-1])[i%4>1];print w+s+w

这个只是逐行构建和打印。

这是非高尔夫球形式的代码:

n=int(input())
# The list with all the knot pieces
l= [' __ ',
    '/  \\',
    ' /\/',
    '/\/ ',
    '\ \/',
    '/\ \\',
    ' /\/',
    '/\/ ',
    '\__/']
# The first and last columns
w = '  ||  || '
# Loop for each row
for i in range(9):
    # Exception for the first and last character in the knot (in some rows)
    s = l[i]*n
    if i % 4 > 1:
        s = ' ' + s[1:-1] + ' '
    # Print the knot for this row
    print(w[i] + s + w[i])

编辑:我将语言更改为python 2,以与我对#3的回答兼容(并且它还节省了6个字节)


我相信w=(3*' ||')[i] -> w=' |'[i&2]' '+s[1:-1]+' ' -> ' %s '%s[1:-1]工作(第一个是带有两个空格的字符串,然后是管道,但是SE起作用了)
Sp3000,2015年

@ Sp3000谢谢!第一个很聪明。我应该想到的' ||'[i%4],但这甚至更短(也有两个空格)。
马蒂2015年

3

C,159字节

j,k;f(n){char*t="7>771I;M6CMI93;IIB;;MI1M;M6CMI93;IIB;>MI";for(n*=4;t[j/2];++k,k%=n+3,j+=k-n?k%n<3||k%4-2?1:-3:3)putchar("\n _|/\\"[(t[j/2]-48)/(j%2?1:6)%6]);}

有了空格,以及其他一些可读性方面的改进:

#include <stdio.h>

int j, k;

void f(int n) {
    char *t = "7>771I;M6CMI93;IIB;;MI1M;M6CMI93;IIB;>MI", *m = "\n _|/\\";
    for (n *= 4; t[j / 2];
         ++k,
         k %= n + 3,
         j += k - n ? k % n < 3 || k % 4 - 2 ? 1 : -3 : 3)
        putchar(m[(t[j / 2] - 48) / (j % 2 ? 1 : 6 ) % 6]);
}

这主要基于模板。该模板t包含输出的所有9个可能的列,这意味着它编码9 * 9 = 81个字符,即80个字符,不带尾随换行符。

由于模式中只有6个不同的字符(包括换行符),我将它们的对打包为一个模板字符,这意味着模板可以存储40个字符。这样,就有6 * 6 = 36个可能的字符对,它们被编码为ASCII字符48至73。通过小查询表可以将其转换回原始字符m

其余逻辑主要是重复模式n时间,这意味着跳回模板中的4个字符,同时正确发出每一行的开始和结束部分。


2

PHP 5.5.3,488,466

<?php 
function k($n){$r=array_fill(0,9,'');for($i=0;$i<$n;$i++){$r[0].=($i==0)?"  __ ":" __ ";$r[1].=($i==0)?" /  \\":"/  \\";$r[2].=($i==0)?"| /\\/":(($i==$n-1)?" /\\ |":" /\\/");$r[3].=($i==0)?"| \/ ":(($i==$n-1)?"/\/ |":"/\/ ");$r[4].=($i==0)?" \\ ":(($i==$n-1)?"\\/\\ \\/":"\\/\\ ");$r[5].=($i==0)?" /\\ ":(($i==$n-1)?"\\/\\ \\":"\\/\\ ");$r[6]=$r[2];$r[7]=$r[3];$r[8].=($i==0)? " \__/":"\__/";}foreach($r as $o){if(strlen($o)-2 !== 4*$n)$o.=" ";echo $o."\n";}}

您可以通过删除运算符周围不必要的空白来节省一些字符,例如,=和之间.=的空白。
ProgramFOX

THX我编辑了答案
地中海

2

Prolog(SWI),285个字节

a(N):-b(N,"  ||  || "," /  \\/  \\","_ /\\ \\/\\_","_ \\/\\ \\/_"," \\/ /\\/ /"," / /\\/ /\\"," \\  /\\  /"). b(N,[A|G],[B|H],[C|I],[D|J],[E|K],[F|L],[Y|Z]):-c(N,[Y,A],[E,F,C,D],T),writef([A,B,C,D|T]),nl,b(N,G,H,I,J,K,L,Z). c(1,L,_,L):-!. c(N,L,X,O):-M is N-1,c(M,L,X,T),append(X,T,O).

(带空格):

a(N):-
    b(N,
    "  ||  || ", 
    " /  \\/  \\", 
    "_ /\\ \\/\\_", 
    "_ \\/\\ \\/_", 
    " \\/ /\\/ /", 
    " / /\\/ /\\", 
    " \\  /\\  /").

b(N,[A|G],[B|H],[C|I],[D|J],[E|K],[F|L],[Y|Z]):-
    c(N,[Y,A],[E,F,C,D],T),
    writef([A,B,C,D|T]),
    nl,
    b(N,G,H,I,J,K,L,Z).

c(1,L,_,L):-!.
c(N,L,X,O):-
    M is N - 1,
    c(M,L,X,T),
    append(X,T,O).

我尝试了几种切碎字符串的方法,但似乎没有一个方法能击败这种幼稚的列方法。


2

的JavaScript(ES6),158个 154 148 137字节

n=>`    __
 /\\/ - \\/
 /\\/\\-__/`.replace(/-/g,` \\
| / /\\ |
|  /\\/ |
 \\/\\`).replace(/(..)(....)/g,(_,l,m)=>l+m.repeat(n).slice(2))

编辑:由于@Bálint,节省了11个字节。


@Bálint但是/(..)(.{4})/g是13个字节,与/(..)(....)/g... 相同
Neil

@Bálint我实际上意识到我以前的4字节保存允许我执行此操作,但是当时我不在电脑旁。
尼尔

@巴林特尼斯!我曾考虑避免重复的\\ / \\段,但是我没有想到要检查更长的重复子字符串。
尼尔

1

Java 339330字节

class D{int n,i;public static void main(String[]a){new D(new Integer(a[0]));}D(int k){n=k;r("  __");p("\n ");r("/  \\");c();r("\\ \\/");p("\n ");r("/\\ \\");c();r("\\__/");}void c(){p("\n|");--n;r(" /\\/");p(" /\\ |\n| \\/");r(" /\\/");++n;p(" |\n ");}void p(String s){System.out.print(s);}void r(String s){for(i=n;i>0;--i)p(s);}}

我的第一个解决方案中包含许多“静态”关键字,因此使方法和属性变为非静态并在构造函数中运行代码的时间要短一些。


1

PowerShell中,228个 207 181 133字节

%{"  "+"__  "*$_;" "+"/  \"*$_;$b="|"+" /\/"*$_+"`b |";$b;$c="| "+"\/ /"*$_+"`b|";$c;" "+"\ \/"*$_;" "+"/\ \"*$_;$b;$c;" "+"\__/"*$_}

提醒-PowerShell不会自动等待标准输入。您必须用管道输送一些东西,例如3|%{...}


0

SmileBASIC,149字节

INPUT N?"  __"*N
A$="| / /\ |
B$="|  /\/ |
K" /\/  \
K A$K B$K" \/\ \/
K" /\/\ \
K A$K B$K" \/\__/
DEF K A?SUBST$(A,2,4,MID$(MID$(A,2,4)*N,2,N*9))END

每个字符串都包含模式AACCBBDD,该模式被扩展为。AABB(CCBB)*DDCCBB部分重复N次,然后删除前2个字符。(从开头删除字符比从结尾删除字符要短)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.