磁気彫刻


14

これは、グラフの構築に関する私の以前の課題の緩やかな継続です。

バックグラウンド

風変わりなアーティストが彼の彫刻の構造的完全性を推定するためにあなたを雇いました。彼は立方体の磁石の束を取り、それらを一つ一つ巨大な山に落とすことによって彼の芸術作品を作成します。彼の方法をよりよく分析するために、次の2次元モデルを使用します。空の床から始め#、任意の整数座標に磁石をドロップします0

       |
       v
       #
===============
       0

別の磁石をで落とすと0、前の磁石の上に配置されます:

       |
       v
       #
       #
===============
       0

次に、にもう1つ磁石をドロップし0、次に1つにドロップし1ます。

        |
       #v
       ##
       #
===============
       0

上記のように、落下する磁石は、通過する2番目の磁石に付着します(最初の磁石は単に減速させます)。2番目の磁石は最初の磁石のすぐ下にある必要はなく、両側の磁石は1つの磁石としてカウントされます。

      #   #
      ##|##
      # v #
      ### #
      #   #
===============
       0

アーティストは、最終的な彫刻の最大垂直ギャップ、つまり、同じ列の2つの磁石、または磁石とその下の地面の間の空きスペースの最大数を計算することを望んでいます。上の図では、この数は3(列2)です。

入力

アーティストが磁石を落とす座標を表す整数のリスト。左から右に読みます。座標が満たされ-1024 <= i < 1024、リストの長さが最大1024であると仮定することができます。

出力

最終的な彫刻の最大垂直ギャップ。-1私たちの彫刻家はダダイストであるため、空の彫刻にはギャップがあり、このケースを含める必要があります。

追加のルール

機能または完全なプログラムを提供できます。最短のバイトカウントが優先され、標準の抜け穴は許可されません。説明付きのコードが推奨されます。

テストケース

[] -> -1
[0,2,1] -> 0
[0,0,0,0,0,1,-1] -> 3
[0,0,0,0,0,1,1,1,2] -> 4
[1,1,2,2,2,2,2,2,1] -> 2
[1,1,2,2,2,2,2,2,1,0,1,0] -> 2
[1,2,1,2,1,2,1,2,2,2,2,1,0] -> 3
[-1,-1,-1,1,1,1,0] -> 1
[-1,-1,-1,-1,2,2,1,1,2,2,2,1,0] -> 2
[-2,-2,-2,-1,-1,-1,0,0,0,1,1,1,2,2,2,3,3,4,4,5,5,5,6] -> 6

回答:


1

Dyalog APL、73 70文字

{y←⍬⋄⌈/¯1,,¯1-2-/0,x⊢⌸{y,←⌈/(1+y/⍨0=⍵),Y⊃⍨2⊃⍒Y←1 1,∪y/⍨1=⍵}¨|x-¯1↓¨,\x←⍵}

{y←⍬⋄¯1⌈⌈/,¯1-2-/¯1,⍵⊢⌸{y,←⌈/(1+y/⍨0=⍵),⊃1↓{⍵[⍒⍵]}∪y/⍨1=⍵}¨|⍵-¯1↓¨,\⍵}

First statement:
       y←⍬  initialize semi-global variable y with an empty vector
Second statement, from right to left:
         ⍵  the vector of x coordinates
       ,\⍵  concat-scan: all prefixes of ⍵ of length 1, 2, ..., ≢⍵
   ¯1↓¨,\⍵  drop the last element of each prefix, lengths are 0, 1, ..., (≢⍵)-1
|⍵-¯1↓¨,\⍵  for each x: magnitudes of differences between x and its predecessors
 {...}¨...  execute the code in parens for each item of the argument
         ⍵  is now a single vector of differences from those described above
       1=⍵  boolean mask, where are our neighbouring xs?
    y/⍨1=⍵  select the ys corresponding to our neighbouring xs
   ∪y/⍨1=⍵  unique ys
   {⍵[⍒⍵]}  sort descending
       ⊃1↓  first of one-drop, i.e. get the second element if it exists, otherwise 0
       0=⍵  which previous xs are the same as our x?
  1+y/⍨0=⍵  select the corresponding ys and add 1 to them
        ⌈/  maximum of all the ys described so far
       y,←  append to the semi-global y
            the result from {} will be identical to y
  ⍵⊢⌸{...}  a matrix of ys, grouped in rows by x (which is now in ⍵) and zero-padded
       ¯1,  prepend ¯1 to the left of each row
       2-/  differences between consecutive horizontal elements, result is a matrix
       ¯1-  negative one minus each element of the matrix
         ,  ravel the matrix (linearize it to a vector)
        ⌈/  maximum; if the vector is empty, return ¯1.8e308, a very small number
     ¯1⌈⌈/  greater of ¯1 and the ⌈/  to avoid the very small number

注:これは、UTF-8を想定して、122バイトの長さです(チャレンジはバイト単位)。
MtnViewMark


私は非常に同情的です。私はゴルフをするHaskellでASCII以外の文字を使用していることにしばしばoftenされています。それ以来、Qが文字またはバイトによるカウントを指定している場合、私はかなり気をつけてきました。
MtnViewMark

@MtnViewMarkバイトによるスコアリングは、UTF-8バイトによるスコアリングを意味しません。APLでそうすることは、ASCIIを重要な標準として認識するには古すぎるためにそれを罰することです。APLの文字セットはシングルバイトコードページ内に簡単に収まり、そのコードページが存在します。したがって、そのコードページをエンコードとして使用すると、各文字 1バイトになります。一方、Haskellで非ASCII文字を使用する場合は、ASCII文字と非ASCII文字の両方を含むエンコードを使用する必要があります。通常はUTF-8です。
マーティンエンダー

@ngn-これに関するメタ投稿のほとんどを読んだことは、悲しいかな、まだ濁っているようです。ただし、チャレンジがバイト単位でスコアリングされる場合は、APLをバイト単位でスコアリングするのが最善ですが、使用されているエンコーディングのどこかに言及するのが最善でしょう。
MtnViewMark

4

ハスケル- 217 185 182のバイト

import Data.List
r g n m|m==n=max(head(g m)+1)((reverse.(0:).nub.sort$g(m-1)++g(m+1))!!1):g m|1<3=g m
j x=(-1)-minimum(0:(map(foldl r(\_->[0])x)[-1024..1024]>>=(tail>>=zipWith(-))))

使用法:

j [1,2,1,2,1,2,1,2,2,2,2,1,0]

この関数は、指定されたx位置の磁石のy位置のリストを返す別の関数を作成します。これにより、すべてのx位置-1024 .. 1024のギャップを計算し、最大値を取ります(編集:ギャップが負なので、最小値を取ります。数値が小さいほどギャップが大きくなります)。


賢いアプローチ!私が少しゴルフをやったことを気にしないでください。
MtnViewMark 14

@MtnViewMark:まったくありません。私は保存するためにさらに3つのバイトを見つけた:いない、負の数で行くと取ります。flip-minimum
nimi 14

私のリポジトリでは、このコード42997-Magnetic.hsを見つけることができます。これには、テストケース用のテストハーネスと、彫刻を表示するビジュアライザーも含まれています。
MtnViewMark

3

Javascript、201 193

F=P=>{m=[];for(p of P){s=2;c=m[p]=m[p]||[];for(i=1e4;~i&&s;i--){if((m[p-1]||[])[i]||(m[p+1]||[])[i])s--;if(c[i-1]) s=0}c[++i]=1}g=-1;m.map(c=>{ d=0;for(i in c){g=i-d>g?i-d:g;d=++i} });return g}

F([1,1,2,2,2,2,2,2,2,1])=== 2

または読み取り可能なバージョン

F=P=>{
  m=[];  // magnet positions
  for(p of P){ // every dropped magnet
    s=2; // initial speed
    c=m[p]=m[p]||[]; // column where magnet is dropping
    for(i=1e4;~i&&s;i--){ // continue until at floor or zero speed
      if((m[p-1]||[])[i]||(m[p+1]||[])[i])s--;  // magnet on either side, decrease speed
      if(c[i-1]) s=0; // magnet is directly below
    }
    c[++i]=1;
  }
  g=-1; // maximum gap
  m.map(c=>{ 
          d=0;for(i in c){g=i-d>g?i-d:g;d=++i;} 
       });
  return g;
};

2

Python 2.7、327

from itertools import * 
s=input()
if s:m=min(s);l=[[] for _ in range(max(s)-m+3)]
for t in s:
    i=t-m+1;r=l[i];c=[x or y for x,y in izip_longest(l[i-1],l[i+1])][::-1][1:];j=len(c)-c.index(1)-1-len(r) if any(c) else 0;l[i]=r+[0]*j+[1]
print -1 if not s else max([len(list(q)) if b==0 else 0 for k in l for b,q in groupby(k)])

ホワイトスペースゴルフの前は、次のようになっています。

from itertools import * 
s=input()
if s:
    m=min(s)
    l=[[] for _ in range(max(s)-m+3)]
for t in s:
    i=t-m+1;r=l[i]
    c=[x or y for x,y in izip_longest(l[i-1],l[i+1])][::-1][1:]
    j=len(c)-c.index(1)-1-len(r) if any(c) else 0
    l[i]=r+[0]*j+[1]
print -1 if not s else max([len(list(q)) if b==0 else 0 for k in l for b,q in groupby(k)])

主に私自身の利益のために、より複雑な行について説明します。

l=[[] for _ in range(max(s)-m+3)] 

これにより、長さがmax(drops)-min(drops)+1の空のリストの配列と、両側にプレースホルダーが構築されます。空のリストの配列を作成するために[[]] * Kを常に書きたいのですが、それは同じ空のリストへのKポインターを作成します。

c=[x or y for x,y in izip_longest(l[i-1],l[i+1])][::-1][1:] 

itertoolsの関数izip_longestはzipに似ていますが、リストを一緒に圧縮するために短いリストにNoneを埋めます。[::-1]をスライスすると、「または」比較の0と1のリストが逆になります。リストは、要素の最初のインスタンスを見つける次の行でインデックスメソッドを使用するために逆にされます。空ではない列の最後の要素は1でなければならないため、これは反転リストの最初の要素であり、スライス[1:]を介して無視されます。

j=len(c)-c.index(1)-1-len(r) if any(c) else 0 
l[i]=r+[0]*j+[1]

最初に、列iの長さと隣接する列の2番目の1の位置との差を計算します。差が正の場合、1を追加する前に列iにその数のゼロを追加します。正数でない[0]倍の数​​は空のリストです。

max([len(list(q)) if b==0 else 0 for k in l for b,q in groupby(k)])

itertoolsの関数groupbyは、リストを連続した要素のサブシーケンスに分割します。この行は、すべての列のゼロのすべてのサブシーケンスの長さの最大値を見つけます。groupbyは、自然にlenメソッドをサポートしないジェネレーター(すべてのitertools関数のような)を返すため、各サブシーケンスqをリストにキャストする必要があります。


1

Java-281バイト

かなり簡単です。

まず、彫刻を配列に構築します

次に、最大のギャップを見つけます。

int a(int[]b){
        int[][]d=new int[9999][9999];
        int g,r,t,y=-1;
        for(int c:b){
            c+=5000;
            g=0;
            for(r=9998;r>=0;r--){
                if(r==0||d[c][r-1]==1){d[c][r]=1;break;}
                if((d[c-1][r]==1||d[c+1][r]==1)&&++g==2){d[c][r]=1;break;}
            }
        }
        for(int[] k:d){
            t=0;
            for(int i:k){
                if(i==0)t++;
                else{if(t>y)y=t;t=0;}
            }
        }
        return y;
    }

小さい -

int a(int[]b){int[][]d=new int[9999][9999];int g,r,t,y=-1;for(int c:b){c+=5000;g=0;for(r=9998;r>=0;r--){if(r==0||d[c][r-1]==1){d[c][r]=1;break;}if((d[c-1][r]==1||d[c+1][r]==1)&&++g==2){d[c][r]=1;break;}}}for(int[] k:d){t=0;for(int i:k){if(i==0)t++;else{if(t>y)y=t;t=0;}}}return y;}

あなたは最初に置き換えることにより、バイトを保存することができ|||。また、y印刷する代わりに戻ると、9バイト節約されます。
Ypnypn 14

@Ypnypn、ありがとう!ところで、最初のステートメントはArrayIndexOutOfBounds例外(-1)をスローするようです。(私はビット演算子と多くの経験を持っていない)
ストレッチマニアック

これは、約1.5年となって、しかし、あなたはより多くのそれはいくつかのゴルフをすることができます:(272バイト): int a(int[]b){int z=9999,d[][]=new int[z][z],g,r,t,y=-1;for(int c:b){c+=z/2;g=0;for(r=z;--r>-2;){if(r==0||d[c][r-1]==1){d[c][r]=1;break;}if((d[c-1][r]==1|d[c+1][r]==1)&&++g==2){d[c][r]=1;break;}}}for(int[]k:d){t=0;for(int i:k){if(i==0)t++;else{if(t>y)y=t;t=0;}}}return y;}。変更の概要:z=9999追加および使用されました。intそして、int[][]フィールドの初期設定を1つに統合されました。2番目|||;に置き換えられます。for(r=9998;r>=0;r--)に変更されましたfor(r=z;--r>-2;)
ケビンCruijssen
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.