輪郭を描く


25

標高の長方形のマトリックスを指定して、その輪郭を描きます。

仕事

の場合、2つの要素xyは同じ輪郭レベルにありますfloor(x/10) == floor(y/10)。たとえば、5258は同じ等高線レベルにありますが58、そうで64はありません。

輪郭を描く動作は次のように定義されます。すべての要素についてe、次のように選択した2文字の文字列に置き換えます。

  • 最初の文字は" "、下の要素eが同じ輪郭レベルにあるeか、下の要素がないかe"_"そうでない場合
  • 2番目の文字は" "、右側の要素がe同じ輪郭レベルにあるeか、右側の要素がない場合、eまたは"|"そうでない場合

行内の要素が結合され、次に行が改行で結合されます。

入力が[[5,20],[3,6]]、次のように視覚化されているとしましょう

5 20
3 6

最初に見てください5。以来、3同じ等高線レベルであり5、最初の文字です" "20はと等高線レベルにないため5、2番目の文字は"|"です。

今、私たちは見てください206はと等高線レベルにないため20、最初の文字は"_"です。の右側に要素がないため20、2番目の文字は" "です。

今、私たちは見てください3。下3に要素がないので、最初の文字は" "です。以来、6同じ等高線レベルにあり3、第二の文字があります" "

今、私たちは見てください6。下6に要素がないので、最初の文字は" "です。の右側に要素がないため6、2番目の文字は" "です。

これらの2文字の文字列に基づいて、getを置き換える[[" |","_ "],[" "," "]]。これらを結合すると、次の出力が得られます

 |_ 
    

ルール

  • 入力行列は常に長方形で、正の整数で構成されます。
  • 末尾のスペースまたは改行は任意の量(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
これがいかにクールであるかを理解する前に、私はこれを読みさえしません
クリストファー

回答:


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行目)を定義します。この関数は、2つの引数が同じ「高度」にある場合はスペースを返し、$nそうでない場合は変数の内容を返します。10で割ってフローリングする代わりに、intがCool文字列のように扱うことができるという事実を悪用しchop、最後の文字(=数字)を削除するために使用します。その後、それらを静かに減算し、それらを再び数値に強制します:—)。

その後(行4)q、リストを取り、最初の要素が削除され、最後の要素が複製されたリストを返す関数を作成します。

次の3行では、入力マトリックスからさらに2つのマトリックスを作成します。最初のマトリックスでは、最初の行が欠落しており、最後の行が複製されています(それだけです.&q—を使用して.&、メソッド—ドットの前にあるものが最初の引数です)、もう1つには最初の列がなく、最後の列が複製されています(つまり.map(*.&q))。

最初(4行目)に、元の行列を取得し、$_それを「シフトされた行」行列で「オーバーレイ」し、一致する要素でw二項演算子(つまりそれ[&w])として関数を使用します。それは_、一致する要素が異なる標高にある場合はどこでも、それ以外の場合は1つを置きます。したがって、結果の半分が得られます(「最初の文字」のみ)。

6行目でも同じことを行いますが、最初にに変更$n|、元のマトリックスをシフトされた列を持つマトリックスで「オーバーレイ」します。結果は|異なる高度で同じ高度になります。これらは「2番目の文字」です。

今、それらを一緒に結合します。連結を含むzipを使用して配列を圧縮します(ええ...)。これにより、元の形状のマトリックスが作成され、各要素は「ハーフソリューション」の2つの一致する要素が連結されます。最後に、このマトリックス(実際にはリストのリスト)にマップします。これらの各リストはフラット化sayされてから-ed(改行で印刷)されます。以来say任意の数の引数を取り、それだけで終わりに改行を作り、セパレータなしでそれらをすべて印刷しすることができ、我々は標準出力に所望の画像を取得します。(そして、ブロックはTruesのリストをsay返します(それぞれが1を返しますTrue)が、誰が気にします。)


+1but who cares
HyperNeutrino

5

ゼリー 25 23  22 バイト

マイルのおかげで-1バイト(Iベクトル化)

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

結果を印刷する完全なプログラム。モナドリンクとして、数値のリストのリスト、標高を取得し、リストリストを返しますが、これらの「行」は2文字の「ペア」のリストで構成されます。これで問題ない場合は、削除して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

独立したソリューション-あなたが見たものは非常に似ています!...あなたは1つの直線オフを節約
ジョナサン・アラン

:⁵I;€0ao⁶メインリンクではなくヘルパーの結合でそれぞれを使用して1バイトを保存できますZç”_Zż"ç”|$Y
マイル

@milesああすごい、それはうまくいく?ありがとう!私Iはそのようにベクトル化しないと想像しました。
ジョナサンアラン

うんI深さ1、および両方でベクトル化aし、o深さ0のベクトル化
マイル


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バイト


あなたの解決策は実際になくすことができますY-文字のリストのリストを返します。
ジョナサンアラン

@JonathanAllanそうそう...ありがとう!
ハイパーニュートリノ

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

オンラインでお試しください!

ふう、それは論理をうまくやるにはうんざりした。私は今、ハイパーニュートリノ忍者が短い答えで私を誘ったのを見ますが、私はこれを投稿しないようにこれに多くの仕事を費やしました。:P

また、これはASCIIアートを作成する素晴らしい方法です。これらをもっとボートに乗せている間、すみません。


> ninja'd:おい、それは45分となっています
HyperNeutrino

ええ、私は...答えを見ていない:P
totallyhuman

enumerateフルネームを2回使用する代わりに、変数を定義することで4バイトを節約できます。
ジョナサンフレッチ

最初を削除して218バイトenumerate(obs、ここにリンクするにはいくつかの入力を削除する必要がありました)
フェリペナルディバティスタ

2

J、58バイト

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

オンラインでお試しください!

行列を取り、輪郭を出力する無名関数。

ここに改善の余地があります。すべてのテストケースを試す時間はなかったので、問題がある場合はお知らせください。もっとゴルフして、後で説明しようとします。

(クイック)説明

ヘルパー関数:長さ2の配列の最初の要素が2番目の要素と等しいかどうかに基づいて、長さ2の文字列にインデックスを付けます。等しい場合は0番目の要素にインデックスを付け、等しくない場合は最初の要素にインデックスを付けます。長さ1の配列は、常に文字列の0番目の要素にインデックスを付けます。

f=.{~0==/@]

主な機能

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

1:+<.@%&10 各要素を10で割って1を追加します(したがって0は取得されません-これはヘルパー関数にとって重要です)。

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`

where \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)])))

オンラインでお試しください!

Jonathan Frechのおかげで-2バイト
Python 2ではなくProtonに切り替えて-15バイト


で置き換えlenL定義すると、2バイト節約できますL=len;
ジョナサンフレッチ

1

Java 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

パール5130の 126バイト

124バイトのコード+ -apフラグ用に2

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

オンラインでお試しください!

入力形式は、スペースで区切られた数字の2次元グリッドです。

説明

これは、コードの以前の反復からのものです。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.