绘制轮廓


25

给定高程的矩形矩阵,绘制其轮廓。

任务

如果,则两个元素xy处于同一轮廓线级别floor(x/10) == floor(y/10)。例如,5258处于相同的轮廓级别,但是5864不在同一轮廓级别。

绘制轮廓的行为定义如下:对于每个元素e,将其替换为如下选择的两个字符的字符串:

  • 第一个字符是" "下面的元素是否与下面的元素处于e相同的轮廓线级别,e或者下面没有任何元素e"_"否则
  • 第二个字符是," "如果右边的元素与该元素e处于相同的轮廓线级别,e或者右边没有元素e"|"否则

将行中的元素连接在一起,然后用换行符将这些行连接在一起。

假设输入为[[5,20],[3,6]],可视为

5 20
3 6

我们先来看一下5。由于3处于与相同的轮廓水平5,因此第一个字符为" "。由于20与的轮廓级别不同5,因此第二个字符是"|"

现在我们来看20。由于6轮廓线级别与相同20,因此第一个字符为"_"。由于的右边没有元素20,因此第二个字符是" "

现在我们来看3。由于下面没有元素3,因此第一个字符为" "。由于6与处于相同的轮廓水平3,第二个字符是" "

现在我们来看6。由于下面没有元素6,因此第一个字符为" "。由于的右边没有元素6,因此第二个字符是" "

基于这些两个字符的字符串,我们进行替换以获得[[" |","_ "],[" "," "]]。将这些结合在一起,我们得到的输出

 |_ 
    

规则

  • 输入矩阵将始终为矩形,并由正整数组成。
  • 尾随空格或换行符可以为任意数量(包括0),并且不必以任何方式保持一致。
  • 只要产生相同的结果,就不必遵循相同的算法。
  • 您的程序或函数可能会输出以换行符分隔的字符串,字符串列表或等效字符串。
  • 这是,因此以字节为单位的最短代码获胜。

测试用例

input
output

[[1,5,8,9],[3,11,13,8],[7,14,10,9],[4,8,7,6]]
  _ _  
 |   | 
 |_ _| 

[[0,10,20,30,40,50,60,70,80,90],[0,0,10,10,20,20,30,30,40,40],[0,0,0,10,10,10,20,20,20,30],[0,0,0,0,10,10,10,10,20,20],[0,0,0,0,0,10,10,10,10,10],[0,0,0,0,0,0,10,10,10,10],[0,0,0,0,0,0,0,10,10,10],[0,0,0,0,0,0,0,0,10,10],[0,0,0,0,0,0,0,0,0,10],[0,0,0,0,0,0,0,0,0,0]]
 |_|_|_|_|_|_|_|_|_
   |_  |_ _|_ _|_ _
     |_    |_ _  |_
       |_      |_ _
         |_        
           |_      
             |_    
               |_  
                 |_


[[5,5,5,5,5,5,5,5,5,5,5],[5,10,10,10,10,10,10,10,10,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,25,30,25,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,10,10,10,10,10,10,10,10,5],[5,5,5,5,5,5,5,5,5,5,5]]
  _ _ _ _ _ _ _ _ _  
 |                 | 
 |    _ _ _ _ _    | 
 |   |         |   | 
 |   |    _    |   | 
 |   |   |_|   |   | 
 |   |         |   | 
 |   |_ _ _ _ _|   | 
 |                 | 
 |_ _ _ _ _ _ _ _ _| 

[[35,32,29,26,25,25,25,26,29,32,35],[32,28,25,22,20,20,20,22,25,28,32],[29,25,21,18,15,15,15,18,21,25,29],[26,22,18,14,11,10,11,14,18,22,26],[25,20,15,11,7,5,7,11,15,20,25],[25,20,15,10,5,0,5,10,15,20,25],[25,20,15,11,7,5,7,11,15,20,25],[26,22,18,14,11,10,11,14,18,22,26],[29,25,21,18,15,15,15,18,21,25,29],[32,28,25,22,20,20,20,22,25,28,32],[35,32,29,26,25,25,25,26,29,32,35]]
  _|             |_  
_|    _ _ _ _ _    |_
    _|         |_    
   |    _ _ _    |   
   |   |     |   |   
   |   |     |   |   
   |   |_ _ _|   |   
   |_           _|   
_    |_ _ _ _ _|    _
 |_               _| 
   |             |  

1
在意识到这有多酷之前,我什至不开始阅读这篇文章
Christopher

Answers:


6

Perl 6,135个字节(131个字符)

{my$n="_";sub w{$^a.chop-$^b.chop??$n!!" "};my&q={|.[1..*],.tail};(($_ «[&w]».&q) ZZ~{$n="|";$_ «[&w]».map(*.&q)}()).map:{say |$_}}

在线尝试!

稍微松了一下:

{
    my $n = "_";
    sub w { $^a.chop - $^b.chop ?? $n !! " "};
    my &q = {|.[1..*],.tail};
    (
        ($_ «[&w]».&q)
        ZZ~
        {$n="|";$_ «[&w]».map(*.&q)}()
    ).map:{say |$_}
}

说明:首先,我们定义一个变量$n(第2行)和一个函数w(第3行)。如果其两个参数位于相同的“高程”,则此函数返回一个空格,否则返回变量的内容$n。而不是除以10和底数,我们滥用了int是Cool(可以像字符串一样对待)并用于chop删除最后一个字符(= digit)的事实。然后,我们从容地减去它们,再次将它们逼成数字:-)。

之后(第4行),我们组成一个函数q,该函数接受一个列表,并返回删除了第一个元素并复制了最后一个元素的列表。

在接下来的3行中,我们将从输入矩阵中再增加2个矩阵:第一行缺少第一行,而最后一行重复了(这就是.&q—使用.&,您可以在任何东西上调用一个函数,就像一个方法-点号前面的东西是第一个参数),另一个缺少第一列,而最后一列重复了(即.map(*.&q))。

首先(第4行),我们获取原始矩阵$_,将其与“移位的行”矩阵“重叠”,然后将该函数w用作[&w]匹配元素上的二进制运算符(即)。那就是将_匹配元素放在不同海拔的任何地方,否则放置一个。因此,我们得到结果的½(仅“第一个字符”)。

在第6行,我们做同样的事情,但是首先更改$n|,然后我们将原始矩阵与带有移位列的矩阵“重叠”。结果|在不同的高度和相同的高度。这些是“第二个字符”。

现在,我们将它们组合在一起。我们用带有concat的zip压缩数组(是的...),这将导致原始形状的矩阵,其每个元素都是串联的“半解”的2个匹配元素。最后,我们仅映射该矩阵(实际上是列表的列表)。这些列表中的每一个都被展平,然后say-ed(用换行符打印)。由于say可以接受任意数量的参数,并且无需分隔符即可打印所有参数,因此仅在最后换行,因此可以在stdout上获得所需的图片。(并且该块返回Trues 的列表(每个都say返回一个True),但谁在乎。)


+1 forbut who cares
HyperNeutrino

5

果冻 25 23  22 字节

-1字节归功于英里(向I量化)

:⁵I;€0ao⁶
Zç”_Zż"ç”|$Y

完整程序打印结果。作为单子链接,它获取数字列表,高程列表并返回列表列表,但是这些“行”由两个字符“成对”的列表组成-如果可以,则可以通过删除保存1个字节Y

在线尝试!

怎么样?

:⁵I;€0ao⁶ - Link 1, assignCharacters (row-wise): list of lists of numbers; character, c
 ⁵        - literal 10
:         - integer division (vectorises)
  I       - incremental differences (vectorises) (zero if the same else non-zero)
     0    - literal 0
   ;€     - concatenate for €ach (rightmost edge of a row has no contour mark)
      a   - logical and (vectorises) with c (replace non-zeros with the contour character)
        ⁶ - literal space character
       o  - logical or (vectorises) (replace the zeros with spaces)

Zç”_Zż"ç”|$Y - Main link: list of lists of numbers, contours
Z            - transpose the input (get the columns)
  ”_         - literal underscore character, '_'
 ç           - call the last link (1) as a dyad with '_'
    Z        - transpose the result
          $  - last two links as a monad:
        ”|   -   literal pipe character, '|'
       ç     -   call the last link (1) as a dyad with '|'
      "      - zip with the dyadic operation:
     ż       -   zip (interleave the column-wise characters with the row-wise ones)
           Y - join with newlines
             - implicit print

grr 3个字节。+1,但我会尽力让您失望;)
HyperNeutrino

独立解决方案-刚刚看到您的情况非常相似!为您省去
Jonathan Allan

您可以在助手中:⁵I;€0ao⁶而不是在主链接中使用每个字节保存一个字节Zç”_Zż"ç”|$Y
英里

@miles哇,行吗?谢谢!我想象I不会那样进行矢量化处理。
乔纳森·艾伦,

是的I向量化深度为1,并且两个ao矢量化在深度0
英里

3

Python 2中199个 186 157 155字节

lambda a:(lambda x:'\n'.join(''.join('_ '[x==z]+'| '[x==y]for x,y,z in zip(r,r[1:]+r[-1:],q))for r,q in zip(x,x[1:]+x[-1:])))([[v/10for v in r]for r in a])

在线尝试!


3

果冻,24字节

:⁵IṠ;€0
ZÇZị⁾_ +³Ç¤ị⁾| ¤

在线尝试!

说明

:⁵IṠ;€0           Helper Link; get contour data
:                 Floor division by
 ⁵                10
  I               Compute increments
   Ṡ              Sign; ±1 for different values and 0 for same values
    ;             Append
      0           Zero
     €            To each row
ZÇZị⁾_ +³Ç¤ị⁾| ¤  Main Link
Z                 Zip the input (for vertical contours _)
 Ç                Get the contour data
  Z               Zip the data (because it's zipped from the first Z)
   ị              Index into the string
    ⁾_            "_ "
       +          Add (vectorizing twice) to
        ³ ¤    ¤  Nilad starting from (input)
         Ç        Get contour data (horizontal contours |)
           ị      Index into the string
            ⁾|    "| "

-2个字节,感谢Jonathan Allan


您的解决方案实际上可以消除Y-它会返回字符列表的列表,我相信这是可以的(而我的在“行”中有成对的字符)。
乔纳森·艾伦

@JonathanAllan哦,是的,真的。谢谢!
HyperNeutrino

2

Python 2,226字节

l=[[j/10for j in i]for i in input()]
for i,j in enumerate(l[:-1]):print''.join('_ '[h==l[i+1][g]]+'| '[h==j[g+1]]for g,h in enumerate(j[:-1]))+'_ '[j[-1]==l[i+1][-1]]
print''.join(' '+'| '[i==j]for i,j in zip(l[-1],l[-1][1:]))

在线尝试!

哎呀,这很难确定逻辑。现在,我看到Hyper Neutrino忍者给了我一个较短的答案,但是我为此花了太多的工作,所以没有发布。:P

另外,我可以说,这是制作ASCII艺术的一种很棒的方法。打扰一下,请问我这些东西更多。


> ninja'd:花了45分钟
HyperNeutrino

是的,我没有看答案...:P
totallyhuman人类

您可以通过定义一个变量来节省4个字节,enumerate而不用两次使用全名。
乔纳森·弗雷希

删除第一个218个字节enumerate(ob,我必须删除一些输入才能在这里链接它)
Felipe Nardi Batista

2

J,58个字节

f=.{~0==/@]
[:(,/"2)2 2((' _'f{."1),' |'f{.);.3 1:+<.@%&10

在线尝试!

匿名函数,采用矩阵并输出轮廓。

Lotta有待改进的地方。我没有时间尝试所有的测试用例,所以让我知道是否有任何问题。会尝试打更多的高尔夫球,稍后再解释。

(快速)说明

辅助函数:根据2长度数组的第一个元素是否等于第二个元素,索引为2长度的字符串。如果相等,则索引到第零个元素;如果不相等,则索引到第一个元素。长度为1的数组始终索引到字符串的第零个元素。

f=.{~0==/@]

主功能

[:(,/"2)2 2((' _'f{."1),' |'f{.);.3 1:+<.@%&10

1:+<.@%&10 将每个元素除以10并加1(因此我们永远都不会得到0-这对于helper函数很重要)。

2 2((' _'f{."1),' |'f{.);.3如果可以的话,将矩阵切成2 x 2的段(否则将在边缘附近给出2 x 1、1 x 2或1 x 1的段),并应用f用于将左上方元素与顶部进行比较的函数右,左上角的元素到左下角。

(,/"2)将结果展平为所需的形状。我真的觉得我应该能够避免使用此方法(以及很多其他方法,但我离题了)。



2

的JavaScript(ES6),120个 118字节

a=>a.map(b=>b.map(c=>c/10|0)).map((b,i,a)=>b.map((c,j)=>((a[i+1]||0)[j]-c?'_':' ')+(b[j+1]-c?'|':' ')).join``).join`\n`

其中\n代表文字换行符。编辑:感谢@Bálint,节省了2个字节。

f=
a=>a.map(b=>b.map(c=>c/10|0)).map((b,i,a)=>b.map((c,j)=>((a[i+1]||0)[j]-c?'_':' ')+(b[j+1]-c?'|':' ')).join``).join`
`
;[
[[5,20],[3,6]]
,
[[1,5,8,9],[3,11,13,8],[7,14,10,9],[4,8,7,6]]
,
[[0,10,20,30,40,50,60,70,80,90],[0,0,10,10,20,20,30,30,40,40],[0,0,0,10,10,10,20,20,20,30],[0,0,0,0,10,10,10,10,20,20],[0,0,0,0,0,10,10,10,10,10],[0,0,0,0,0,0,10,10,10,10],[0,0,0,0,0,0,0,10,10,10],[0,0,0,0,0,0,0,0,10,10],[0,0,0,0,0,0,0,0,0,10],[0,0,0,0,0,0,0,0,0,0]]
,
[[5,5,5,5,5,5,5,5,5,5,5],[5,10,10,10,10,10,10,10,10,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,25,30,25,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,10,10,10,10,10,10,10,10,5],[5,5,5,5,5,5,5,5,5,5,5]]
,
[[35,32,29,26,25,25,25,26,29,32,35],[32,28,25,22,20,20,20,22,25,28,32],[29,25,21,18,15,15,15,18,21,25,29],[26,22,18,14,11,10,11,14,18,22,26],[25,20,15,11,7,5,7,11,15,20,25],[25,20,15,10,5,0,5,10,15,20,25],[25,20,15,11,7,5,7,11,15,20,25],[26,22,18,14,11,10,11,14,18,22,26],[29,25,21,18,15,15,15,18,21,25,29],[32,28,25,22,20,20,20,22,25,28,32],[35,32,29,26,25,25,25,26,29,32,35]]
].forEach(a=>document.write(['<pre>','</pre>'].join(f(a))));


您可以打开(a[i] || [])[j]构建以(a[i] || 0)[j]
巴林特

此外,在过去join`\n`,你可以删除\n一部分,并与实际的换行符替换
巴林特

114个字节:a=>a.map(b=>b.map(c=>c/10|0)).map((b,i,a)=>b.map((c,j)=>" _"[(a[i+1]||0)[j]-c&1]+" |"[b[j+1]-c&1]).join``).join`<new line here>`
巴林特

@BálintBah,我一直忘了做那\n部分;我在REPL中进行了测试,因此字面换行符会妨碍您的操作。
尼尔

@Bálint但是您对原始示例的最后一个建议失败了,我已将其添加到输出列表中。
尼尔

1

质子 202字节

R=(L=len)+range
k=[map((//)&10,r)for r:eval(input())]
d=(x,y,X,Y)=>X>=L(k)or Y>=L(k[X])or k[x][y]==k[X][Y]
print('\n'.join(map(''.join,[['_ '[d(x,y,x+1,y)]+'| '[d(x,y,x,y+1)]for y:R(k[x])]for x:R(k)])))

在线尝试!


通过切换到Proton而不是Python 2 ,Jonathan Frech减少了-2字节-15个字节


您可以通过更换节省两个字节lenL和定义L=len;
乔纳森·弗雷希

1

爪哇8,200个 170 169字节

a->{String r="";for(int l=a.length,i=0,j;i<l;i++,r+="\n")for(j=0;j<l;r+=(i>l-2||a[i][j]/10==a[i+1][j]/10?" ":"_")+(j++>l-2||a[i][j-1]/10==a[i][j]/10?" ":"|"));return r;}

说明:

在这里尝试。

请注意,Java中的整数除法会自动限制。

a->{                   // Method with 2D int-array as parameter and String return-type
  String r="";         //  Result-String
  for(int l=a.length,  //  Length of the input array
      i=0,j;           //  Index integers
      i<l;i++,         //  Loop (1) over the rows of the input array
          r+="\n")     //  and append a new-line to the result after every iteration
    for(j=0;j<l;       //   Inner loop (2) over the columns of a row
      r+=              //    Append the String with:
         (i>l-2        //      If it's the last row,
         ||a[i][j]/10==a[i+1][j]/10?
                       //      or the current and next rows are equal floored/10:
          " "          //       Use a space
         :             //      Else:
          "_")         //       Use a "_"
        +              //     Plus
         (j++>l-2      //      If it's the last column in the row,
         ||a[i][j-1]/10==a[i][j]/10?
                       //      or the current and next columns are equal floored/10:
          " "          //       Use a space
         :             //      Else:
          "|")         //       Use "|"
    );                 //   End of column loop (2)
                       //  End of row-loop (1) (implicit / single-line body)
  return r;            //  Return the result-String
}                      // End of method

1

R,159字节

f=function(m){M=m%/%10;a=cbind(0,t(apply(M,1,diff)));b=rbind(apply(M,2,diff),0);a[!!a]="|";b[!!b]="_";M[]=gsub("0"," ",paste0(a,b));write(t(M),"",ncol(m),,"")}

带有换行符和缩进:

f=function(m){
    M=m%/%10
    a=cbind(0,t(apply(M,1,diff))) #row-wise difference
    b=rbind(apply(M,2,diff),0) #column-wise difference
    a[!!a]="|"
    b[!!b]="_"
    M[]=gsub("0"," ",paste0(a,b)) # M[] is a trick to force the result to have the same structure as M
    write(t(M),"",ncol(m),,"")
    }

是否对矩阵进行整数除法,测量行和列的差异,当不为null时,替换为|_分别,然后粘贴两者(无痛,这要归功于R的矢量化)并输出。

测试用例:

> m=matrix(c(0,10,20,30,40,50,60,70,80,90,0,0,10,10,20,20,30,30,40,40,0,0,0,10,10,10,20,20,20,30,0,0,0,0,10,10,10,10,20,20,0,0,0,0,0,10,10,10,10,10,0,0,0,0,0,0,10,10,10,10,0,0,0,0,0,0,0,10,10,10,0,0,0,0,0,0,0,0,10,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0),byrow=T,ncol=10)
> f(m)
  |_|_|_|_|_|_|_|_|_
    |_  |_ _|_ _|_ _
      |_    |_ _  |_
        |_      |_ _
          |_        
            |_      
              |_    
                |_  
                  |_

> m=matrix(c(5,5,5,5,5,5,5,5,5,5,5,5,10,10,10,10,10,10,10,10,10,5,5,10,15,15,15,15,15,15,15,10,5,5,10,15,20,20,20,20,20,15,10,5,5,10,15,20,25,25,25,20,15,10,5,5,10,15,20,25,30,25,20,15,10,5,5,10,15,20,25,25,25,20,15,10,5,5,10,15,20,20,20,20,20,15,10,5,5,10,15,15,15,15,15,15,15,10,5,5,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,5,5),byrow=T,ncol=11)
> f(m)
   _ _ _ _ _ _ _ _ _  
  |                 | 
  |    _ _ _ _ _    | 
  |   |         |   | 
  |   |    _    |   | 
  |   |   |_|   |   | 
  |   |         |   | 
  |   |_ _ _ _ _|   | 
  |                 | 
  |_ _ _ _ _ _ _ _ _| 

0

Perl 5中130个 126字节

124个字节的代码+ 2个-ap标志

push@a,[map 0|$_/10,@F]}{map{say map{($a[$r+1][$c]-$_&&$r<$#a?'_':$").($a[$r][++$c]-$_&&$c<@{$a[0]}?'|':$")}@$_;$c=0;$r++}@a

在线尝试!

输入格式是2D网格,以空格分隔。

说明

这来自代码的先前迭代。

push@a,[map 0|$_/10,@F]     # read the input, divide it by 10, and store it in a 2-D array
}{                          # end the implicit while loop and start the final block
map{                        # repeat this for each line
  $_=($a[$r+1][$c]-$_&&$r<$#a?'_':$")       # set appropriate characters to output based
     .($a[$r][++$c]-$_&&$c<@{$a[0]}?'|':$") # on the given rules
  for@$_;                                   # repeat for each number on the line
  $c=0;$r++;                         # setup row and column counters for next iteration
  say@$_                             # output this line
}@a
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.