Nether Portal Tespiti


53

Video oyunu Minecraft , sanal dünyayı oluşturan 3B tamsayı kafesine farklı tipte blokları yerleştirmek ve çıkarmakla ilgilidir . Her kafes noktası tam olarak bir blok içerebilir veya boş olabilir ( resmen bir " hava " bloğu). Bu mücadelede, sadece 3D dünyasının dikey bir 2D düzlemi ve bir blok tipi olan obsidiyen ile ilgileneceğiz .

Obsidiyen dikey bir düzlemde boş bir dikdörtgenin dış hatlarını oluşturduğunda, nether portalı oluşturulabilir. Boş dikdörtgen, 2 birim genişliğinde 3 birim yüksekliğinde, 22 birim genişliğinde 22 birim yüksekliğinde herhangi bir boyutta olabilir. Dikdörtgenin köşelerinin sadece kenarlardan oluşan obsidiyenin kenarlarında olması gerekmez.

Örneğin, varsayalım Xki obsidiyen ve .boşluk: (Sayılar sadece tanımlama amaçlı ve boş.)

...................................
..XXXX....XXXX....XXXXXXXXX........
..X..X...X....X..X.........X..XXXX.
..X.1X...X.2..X..X...3...X.X..X....
..X..X...X....XXXX.........X..X.6X.
..XXXX....XXXX...XXXXXXXXXXX..X..X.
.............X.4.X....X.5.X...XXXX.
.............X...X....X...X........
..............XXX......XXX.........
...................................

Bu ızgara 3 geçerli portal içeriyor:

  • Portal 1 2'ye 3 birim, tamamen boş ve obsidiyenin sınırında. Bu nedenle geçerli.
  • Portal 2 4'e 3, tamamen boş ve obsidiyenin sınırında. Bu nedenle geçerli.
  • Portal 3 tamamen boş değil. Bu nedenle geçersiz.
  • Portal 4 3'e 3, tamamen boş ve obsidiyenin sınırında. Bu nedenle geçerli.
  • Portal 5, 3'e 2 birimdir ve çok küçüktür. Bu nedenle geçersiz.
  • Portal 6 sınırın bir bölümünü eksik. Bu nedenle geçersiz.

Meydan okuma

Bu dizgide obsidyen ve boşluk ızgaralarının temsillerini alan ve mevcut geçerli ağ portallarının sayısını basan veya iade eden bir program veya işlev yazın.

  • Giriş, stdin veya dosya veya işlev argümanından olabilir.
  • Girişin her zaman iyi oluşturulduğunu varsayabilirsiniz - yani, yalnızca Xve içeren, en az 1 karakter genişliğinde ve uzunluğunda mükemmel dikdörtgen bir metin ızgarası .. İsteğe bağlı olarak, son satırdan sonra sonunda yeni bir satır olduğunu varsayabilirsiniz.

  • İstenirse, herhangi iki farklı kullanabilir yazdırılabilir ASCII yerine karakterleri Xve ..

  • Obsidiyen, şebekenin sınırlarında olabilir. Sınırların ötesindeki her şey boş olarak kabul edilir.

Örnek giriş - çıkış şöyle olmalıdır 4:

................................................................
...................................XXXXXXXXXXXXXXXXXXXXXXXXX....
..XXXX....XXXX....XXXXXXXXX........X.......................X....
..X..X...X....X..X.........X..XXXX.X.......................X....
..X..X...X....X..X.......X.X..X....X.......................X....
..X..X...X....XXXX.........X..X..X..XXXXXXXXXXXXXXXXXXXXXXXX....
..XXXX....XXXX...XXXXXXXXXXX..X..X.X......................X..XXX
.............X...X....X...X...XXXX.X......................X..X..
.............X...X....X...X........X......................X..X..
..............XXX......XXX........XXXXXXXXXXXXXXXXXXXXXXXX...X..
..................................XX.........................XXX

puanlama

En az bayt olan gönderim kazanır.


Yeni satırların yerine başka bir ASCII karakteri kullanabilir miyim?
Zgarb

@Zgarb Hayır, hala girişin bir ızgara gibi görünmesini istiyorum.
Calvin'in Hobileri

4
Nether portallarının boyutu ne zaman statik 2x3'ten isteğe bağlı daha büyük boyutlara geçti?
Sparr

5
@Sparr SInce 1.7.2 ( güncelleme geçmişine bakın ). Konsol sürümlerinde bunu yapabildiklerinden emin değilim.
Calvin'in Hobileri

4
Kesinlikle + 1 çünkü Minecraft.
Alex A.,

Yanıtlar:


24

Perl, 81 86

Birden fazla regexp kullanmak.

#!perl -p0
$_=map{/.
/;$n="@-"-++$.;/(?=X{$.}..{$n}(X\.{$.}X.{$n}){3,22}.X{$.})/gs}($_)x21

: Bir portal belirli bir genişlik için regexp'in genel olandan çok daha kolaydır portal genişliği ve olduğunu . Regexp , eşleşmelerin üst üste gelebileceği için sıfır genişliğinde ileriye dönük bir iddiaya konulmalıdır . Sonra bu regexp ayarında 21 kez yineleyin ve . Toplam genişlik - olan son eşleşmenin ( ) başlangıç ​​pozisyonunu değerlendirir - 1. ile kullanıldığında başlangıçtaki diğer değişken olarak kullanılır .X{$m}..{$n}(X\.{$m}X.{$n}){3,22}.X{$m}mntotal width - 1 - m(?=...)$n$."@-"/.\n/$.1-p0


2
.Boş hücrelere göre farklı bir karakter kullanıyorsanız bir bayt kaydedebilirsiniz (bu nedenle ondan kaçmak zorunda kalmazsınız).
Martin Ender

62

Regex (.NET lezzet), 182 181 145 132 126 114 104 100 98 97 96 bayt

2D ASCII sanat deseni tanıma? Regex için bir iş gibi geliyor! (Olmaz.)

Bunun, regex başvurularının geçerli programlar olup olmadığına dair tekrar tekrar sonsuz tartışmalar başlatacağını biliyorum, ama bunun yine de APL veya CJam'ı geçeceğinden şüpheliyim, bu yüzden herhangi bir zarar görmüyorum. (Söyleniyor, onlar yapmak için inatçı testi geçmek "Ne bir programlama dilidir?" .)

Bu, eşleştirilecek dize olarak girdiyi alır ve sonuç bulunan eşleşme sayısıdır. O kullandığı _yerine .Ben ikinci kaçmak olurdu, çünkü. Aynı zamanda takip eden bir yeni hat gerektirir.

(X(X){1,21})(?=\D+((?>(?<-2>_)+)_))(?=.((?!\7)(.)*
.*(X\3X|()\1.)(?=(?<-5>.)*(?(5)!)
)){4,23}\7)

RegexHero veya RegexStorm ) ' da canlı olarak test edebilirsiniz . Maçlar, portalların en iyi obsidiyen sıraları olacak. Başarısız olduğu bir test durumu bulabilirseniz, lütfen bana bildirin!

Bu büyücülük nedir?

Aşağıdaki açıklama, .NET'in dengeleme gruplarının temel bir anlayışını varsayar . Asıl amaç, yakalamaların .NET regex'te yığınlar olmasıdır - aynı ad için her yeni yakalama yığına bastırılır, ancak aynı zamanda bu yığınlardan yakalananlar için yakalama sözdizimi ve bir yığıntan yakalayanlar ve yakalayan yakalamalar için sözdizimi de vardır. aynı anda başka birine. Daha eksiksiz bir resim için tüm detayları içermesi gereken Stack Overflow hakkındaki cevabımı inceleyebilirsiniz .

Temel fikir şunun gibi bir deseni eşleştirmektir:

 X{n}..{m}
X_{n}X.{m} |
X_{n}X.{m} |  3 to 22 times
X_{n}X.{m} |
 X{n}..{m} 

Burada n2 ila 22 (dahil) olan. İşin en zor yanı, hepsinin nve hepsinin maynı olması. Gerçek karakterler aynı olmayacağından, sadece bir geri dönüş kullanamayız.

Regex'in \naşağıdaki gibi yazacağım yeni satırları yerleştirmesi gerektiğini unutmayın .

(                     # Open capturing group 1. This will contain the top of a portal, which
                      # I can reuse later to match the bottom (being of the same length).
  X                   # Match a single X.
  (X){1,21}           # Match 1 to 21 X's, and push each separately on the <2> stack. Let's
                      # Call the number of X's captured N-1 (so N is the inner width of the
                      # portal).
)                     # End of group 1. This now contains N X's.
(?=                   # Start a lookahead. The purpose of this lookahead is to capture a 
                      # string of N underscores in group 2, so I can easily use this to match 
                      # the inside rows of the portal later on. I can be sure that such a 
                      # string can always be found for a valid portal (since it cannot have 0 
                      # inner height).
  \D+                 # Skip past a bunch of non-digits - i.e. *any* of the vaild characters
                      # of the input (_, X, \n). This to make sure I search for my N 
                      # underscores anywhere in the remainder of the input.
  (                   # Open capturing group 3. This will contain a portal row.
    (?>               # This is an atomic group. Once the engine hass successfully matched the
                      # contents of this group, it will not go back into the group and try to
                      # backtrack other possible matches for the subpattern.
      (?<-2>_)+       # Match underscores while popping from the <2> stack. This will match as
                      # many underscores as possible (but not more than N-1).
    )                 # End of the atomic group. There are two possible reasons for the
                      # subpattern stopping to match: either the <2> stack is empty, and we've
                      # matched N-1 underscores; or we've run out of underscores, in which 
                      # case we don't know how many underscores we matched (which is not 
                      # good).
    _                 # We simply try to match one more underscore. This ensures that we 
                      # stopped because the <2> stack was empty and that group 3 will contain
                      # exactly N underscores.
  )                   # End of group 3.
)                     # End of the lookahead. We've got what we want in group 2 now, but the
                      # regex engine's "cursor" is still at the end of the portal's top.
(?=                   # Start another lookahead. This ensures that there's actually a valid
                      # portal beneath the top. In theory, this doesn't need to be a 
                      # lookahead - I could just match the entire portal (including the lines
                      # it covers). But matches cannot overlap, so if there were multiple
                      # portals next to each other, this wouldn't return all of them. By 
                      # putting the remainder of the check in a lookahead the actual matches
                      # won't overlap (because the top cannot be shared by two portals).
  .                   # Match either _ or X. This is the character above the portal side.

  (                   # This group (4) is where the real magic happens. It's purpose is to to
                      # count the length of the rest of the current line. Then find a portal
                      # row in the next line, and ensure that it's the same distance from the
                      # end of the line. Rinse and repeat. The tricky thing is that this is a
                      # single loop which matches both inner portal rows, as well as the 
                      # bottom, while making sure that the bottom pattern comes last.

    (?!\7)            # We didn't have a group 7 yet... group 7 is further down the pattern.
                      # It will capture an empty string once the bottom row has been matched.
                      # While the bottom row has not been matched, and nothing has been
                      # captured, the backreference will fail, so the negative lookahead will
                      # pass. But once we have found the bottom row, the backreference will
                      # always match (since it's just an empty string) and so the lookahead
                      # will fail. This means, we cannot repeat group 4 any more after the
                      # bottom has been matched.
    (.)*              # Match all characters until the end of the line, and push each onto
                      # stack <5>.
    \n                # Match a newline to go to the next line.
    .*                # Match as many characters as necessary to search for the next portal
                      # row. This conditions afterwards will ensure that this backtracks to
                      # the right position (if one exists).
    (                 # This group (6) will match either an inner portal row, or the bottom
                      # of the portal.
      X\3X            # Match X, then N underscores, then X - a valid inner portal row.
    |                 # OR
      ()              # Capture an empty string into group 7 to prevent matching further rows.
      \1.             # Use the captured top to match the bottom and another character.
    )
    (?=               # This lookahead makes sure that the row was found at the same 
                      # horizontal position as the top, by checking that the remaining line
                      # is the same length.
      (?<-5>.)*       # Match characters while popping from the <5> stack.
      (?(5)!)\n       # Make sure we've hit end of the line, *and* the <5> stack is empty.
    )
  ){4,23}             # Repeat this 4 to 23 times, to ensure an admissible portal height.
                      # Note that this is one more than the allowed inner height, to account
                      # for the bottom row.
  \7                  # Now in the above repetition there is nothing requiring that we have
                      # actually matched any bottom row - it just ensured we didn't continue
                      # if we had found one. This backreference takes care of that. If no
                      # bottom row was found, nothing was captured into group 7 and this
                      # backreference fails. Otherwise, this backreference contains an empty
                      # string which always matches.
)

C #, 185 bayt

İşte tam bir C # işlevi, sadece bunu geçerli bir giriş yapmak için. .NET düzenli ifadeleri için bir komut satırı "tercüman" yazmamın zamanı geldi ...

static int f(string p){return System.Text.RegularExpressions.Regex.Matches(p,@"(X(X){1,21})(?=\D+((?>(?<-2>_)+)_))(?=.((?!\7)(.)*
.*(X\3X|()\1.)(?=(?<-5>.)*(?(5)!)
)){4,23}\7)").Count;}

5
Hmm, saf bir regex cevabı hakkında ne düşündüğümden emin değilim. Üstleri eşleştirmek, numarayı yazdırmakla aynı değildir. Elbette bir programda regex kullanmak ve eşleşme sayısını yazdırmak iyi olur. Yine de dediğin gibi, muhtemelen dövülecek, o yüzden ben de endişeliyim.
Calvin'in Hobileri,

1
İçin kullanabilirsiniz ^(veya kullanılmayan herhangi bir karakter) (?!).
jimmy23013

@ user23013 Oh, iyi nokta, teşekkür ederim.
Martin Ender


@ user23013 İle 114 var sadece isimsiz grubu kullanılarak, fakat değil içine hat kontrolleri birleştirmektedir.
Martin Ender

11

Python, 219 bayt

def f(s):s=s.split();L=len;R=range;return L([r for r in R(L(s))for a in R(L(s[0]))for w in R(2,23)for h in R(3,min(L(s)+~r,23))if(s[r][a:a+w]==s[r-~h][a:a+w]==w*"X")*all(s[r-~k][a-1:a+w+1]=="X"+"."*w+"X"for k in R(h))])

Java'dan daha iyi, ama oğlanın iç içe geçmiş halkaları ağrıyor. for/inKullanarak hafifçe sıkıştırılması mümkün %sikame ama çok tasarruf olmaz.

Expanded:

def f(s):
  s=s.split()
  L=len
  R=range
  return L([r for r in R(L(s))
              for a in R(L(s[0]))
              for w in R(2,23)
              for h in R(3,min(L(s)+~r,23))
              if(s[r][a:a+w]==s[r-~h][a:a+w]==w*"X")* 
                 all(s[r-~k][a-1:a+w+1]=="X"+"."*w+"X"for k in R(h))])

1
İçgüdülerim, itertools iç içe döngü üretimi büyüsünü denemek.
imallett

7

Java, 304 bayt

Bu normal bir ifadeden çok daha uzun. Basitçe girişteki her olası kareye göre yinelenir. Geçerli bir portalsa, 1 ile bir sayaç artırır. Sonra sayacı döndürür. Bu muhtemelen çok daha fazla golf oynayabilir. Herhangi bir öneriniz açıktır.

int a(String...a){a=a[0].split("\n");int b=0,c=0,d,e,f,g,h,i=a.length,j=a[0].length();for(;c<j;c++)for(d=0;d<i;d++)for(e=c+2;++e<j&e<c+24;)a:for(f=d+3;++f<i&f<d+24;){for(g=c;g<=e;g++)for(h=d;h<=f;h++){if(g==c|g==e&&h==d|h==f)continue;if((g==c|g==e|h==d|h==f)^a[h].charAt(g)>60)continue a;}b++;}return b;}

Girintili'ye:

int a(String...a){
    a=a[0].split("\n");
    int b=0,c=0,d,e,f,g,h,i=a.length,j=a[0].length();
    for(;c<j;c++)
        for(d=0;d<i;d++)
            for(e=c+2;++e<j&e<c+24;)
                a:for(f=d+3;++f<i&f<d+24;){
                    for(g=c;g<=e;g++)
                        for(h=d;h<=f;h++){
                            if(g==c|g==e&&h==d|h==f)
                                continue;
                            if((g==c|g==e|h==d|h==f)^a[h].charAt(g)>60)
                                continue a;
                        }
                    b++;
                }
    return b;
}

Tam program:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class B {

    public static void main(String[] args) throws FileNotFoundException {
        String blocks = new BufferedReader(new FileReader(args[0])).lines().reduce((a,b)->a+"\n"+b).get();
        System.out.println(new B().a(blocks));
    }

    int a(String...a){
        a=a[0].split("\n");
        int b=0,c=0,d,e,f,g,h,i=a.length,j=a[0].length();
        for(;c<j;c++)
            for(d=0;d<i;d++)
                for(e=c+2;++e<j&e<c+24;)
                    a:for(f=d+3;++f<i&f<d+24;){
                        for(g=c;g<=e;g++)
                            for(h=d;h<=f;h++){
                                if(g==c|g==e&&h==d|h==f)
                                    continue;
                                if((g==c|g==e|h==d|h==f)^a[h].charAt(g)>60)
                                    continue a;
                            }
                        b++;
                    }
        return b;
    }

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.