Dil Tasarımı: İki Boyutlu Desen Eşleştirme


49

Bu, Fortnightly Mücadelesi # 6 . Tema: Dil Tasarımı

Bu meydan okuma için bir sohbet odası var . Fikirleri tartışmak istiyorsanız gelin ve bize katılın!

Ve şimdi tamamen farklı bir şey...

Bu iki haftada yeni bir meydan okuma türü denemek istiyoruz. Bu zorlukta bir dil tasarlayacaksınız! Desen eşleştirme programlamada çok yaygın bir sorundur ve kod golf için genellikle çok kullanışlıdır. Örneğin, normal ifadeler, bir metin satırındaki bir deseni tespit etmek için kullanılabilir. Bununla birlikte, iki boyutlu kalıpları tanımlamak ve tespit etmek için belirlenmiş herhangi bir yöntem yoktur.

Meydan okuma

Metin bloklarındaki iki boyutlu desenlerin tanımlanmasına izin veren bir desen eşleştirme dili tasarlıyorsunuz. Operasyon modu (dil aksi regex ile ortak hiçbir şeyimiz zorunda değildir rağmen) dilinizin düzenli ifadeler benzer olacaktır:

  • Giriş olarak, dikdörtgen bir metin bloğu alacaksınız. Metnin yalnızca yazdırılabilir ASCII karakterlerinden (0x20 - 0x7E) ve ızgara satırlarını ayırmak için yeni satırlardan (0x0A) oluştuğunu varsayabilirsiniz.
  • Desen açıklamasına göre bir eşleşme, bu metin bloğunun herhangi bir alt kümesi olarak bulunabilirse, bu eşleşme döndürülmeli veya yazdırılmalıdır. Eğer eşleşme dikdörtgen değilse, bir takım ayrılmış karakterli bir dikdörtgen alana döşenmelidir. Birkaç geçerli eşleşme varsa, geri gönderilen eşleşmenin nasıl seçileceğine karar verebilirsiniz (en büyük, en küçük, ilk vb.).

Bazı uygulamalarda, uygulamanızın eşleşmenin yerine bir eşleşme konumunu döndürmesi yararlı olabilir, ancak bu bir gereklilik değildir.

En azından, diliniz bir modeli, girişinin bitişik, dikdörtgen alt bölgesi olarak eşleştirebilmelidir.

Cevabınız içermelidir:

  • Bir açıklama dili.
  • Bir çalışma uygulaması . Bu, bir program veya seçtiğiniz bir dilde bir dizi işlev / sınıf olabilir.
  • Aşağıda verilen örnekleri çözmek için nasıl kullanılabileceğini göstererek dilinizi göstermelisiniz . Dilinizin hepsini eşleştirebilmesi gerekmez, ancak bunlardan en az 8'ini eşleştirebilmelisiniz . Diliniz düşünmediğimiz bir şeyi yapabilirse, onu dahil etmekten çekinmeyin.

Cevabınız mevcut fikirlere dayanıyorsa, sorun değil, ancak lütfen gerektiği yerde kredi verin.

Uzantıları

Yukarıda, geçerli bir başvurunun yerine getirmesi gereken asgari tutar açıklanmaktadır. Bununla birlikte, birkaç genelleme, aşağıdakiler dahil ancak bunlarla sınırlı olmamak üzere, böyle bir örüntü eşleme dilini daha da faydalı hale getirebilir:

  • Deseni bir veya daha fazla kenara kenetleyebilme, böylece tüm giriş bölgesinin belirli bir desene sahip olup olmadığını kontrol edebilme.
  • Tüm maçları sadece bir tane yerine üretiyoruz. Örtüşen eşleşmelerin anlamını seçebilirsiniz.
  • Dikdörtgen olmayan metni girdi olarak almak.
  • Desenlerin dikdörtgen olmayan eşleşmeler belirtmesine izin verme. Böyle bir durumda çıktı, ayrılmış bir karaktere sahip bir dikdörtgene döşenmelidir.
  • Desenlerin deliklerle eşleşmesini belirtmesine izin vermek.
  • Bitişik olmayan eşleşmelere izin vermek, belirli bir uzaklıktaki iki karakter gibi.
  • Dönme ve yansımaların kolay özellikleri.
  • İsteğe bağlı olarak, girişi periyodik olarak bir silindir veya bir torus gibi davranın, böylece zıt kenarlar bitişik sayılır.

puanlama

Bu zorluğun temel amacı, gelecekte potansiyel olarak kullanılabilecek etkili bir 2D desen eşleştirme dili üretmektir. Bu nedenle, "örnekleri çözmek için en kısa birleşik uzunluk" gibi bir puanlama sistemi, genel kullanılabilirlik pahasına belirli işlevlerin zor kodlanmasına yol açacaktır. Bu nedenle, bu mücadelenin en iyi popülerlik yarışması olarak yapılmasına karar verdik . En net oylarla yapılan başvuru kazanır. İnsanların oy kullanma şeklini zorlayamasak da, seçmenlerin ideal olarak araması gerekenler için birkaç kılavuz:

  • Etkileyicilik. Dil, bu soruda sunulan örneklerin ötesinde bile çeşitli sorunları çözebilir mi? Önerilen uzantılardan herhangi birini destekliyor mu?
  • Okunabilirlik. Gösterim ne kadar sezgiseldir (en azından temel sözdizimini bilenler için)?
  • Golfitude. Bu hala CodeGolf.SE. Bu sitenin amaçları doğrultusunda, bir deseni tanımlamak için çok az kod gerektiren eşleşen bir dile sahip olmak elbette güzel olurdu.

Örnek Problemler

Aşağıdaki Yığın Parçacığı, 2 boyutlu bir kalıp eşleştirme dilinin üstesinden gelebilecek 16 örnek sorunu göstermektedir. Her örnek kısa bir problem tanımı içerir ve ardından genellikle bir eşleşmenin bulunamadığı bir giriş örneği ve eşleşmenin bulunamadığı bir örnek (varsa) izlenir.

Yukarıda belirtildiği gibi, dilinizin yalnızca bu problemlerin 8 tanesini çözebilmesi gerekir. Bunun üzerine her şey isteğe bağlıdır, ancak elbette aldığınız oy sayısını artırması gerekir.

(Hayır, bu HTML kodunu okumanıza gerek yok. Tarayıcınız tarafından güzel bir şekilde görüntülenmesini sağlamak için "Kod pasajını çalıştır" düğmesine basın, ardından tam ekran görüntüleyebilirsiniz.)


Bu problemlerde genel bir zaman sınırı var mı? Bunu çözmekle çok ilgileniyorum ama çok meşgulüm, kolayca yapmam 2 hafta alabilir.
Devon Parsons,

7
@DevonParsons Giriş tarihi yoktur.
PhiNotPi

Özellikle bunun için yeni bir etiket yarattığından beri ilginç görünüyor. Bunun için 2 boyutlu bir dil oluşturmak için bonus puanları olması gerektiğini düşünüyorum.
mbomb007

1
@ mbomb007 2 boyutlu bir dil oluşturmak için bonus puanlar var. Oldukça fazla miktarda oy alacağına eminim. ;)
Martin Ender

@ MartinBüttner Nasıl dil oluşturulacağını bile bilmiyorum. Yeni dilinizin kodunu içeren bir Python programı oluşturmak (ve tanımlanmış sözdiziminize göre yorumlamak / çalıştırmak) ve çıktı üretmek kadar basit (bir şey) olabilir mi?
mbomb007

Yanıtlar:


32

SnakeEx

Şimdiye kadar 15/16 sorunları çözdü!

Çevrimiçi tercüman ! - Tam Dil Özelliği - Javascript Source

tercüman ekran görüntüsü

Bu dilin arkasındaki fikir, regex benzeri bir sözdizimi kullanarak metin kontrol karakterleri etrafında hareket eden 'yılanları' tanımlamaktır.

SnakeEx'teki bir program, farklı komut dizileri kullanan yılanlar için bir tanım listesinden oluşur. Yılanlar, SnakeEx'in gücünün çoğunu aldığı tanımları kullanarak diğer yılanları da doğurabilir - dallanma yapılarıyla eşleşebilir ve hatta özyineleme yapabiliriz (bkz. Paren Eşleştirme örneği).

Her program esasen bir dizi regex'e benzeyecek, ancak yılanın yönünü değiştiren biçimin yön komutlarının eklenmesi <dir>ve daha fazla yılan oluşturan formun komutlarının çağrılmasıyla birlikte {label<dir>params}.

Bir giriş noktası için, tercüman ilk tanımı kullanarak sağa hareket ederek bir yılanı yumurtlar.

Son derece özlü değil, ama çok güçlü ve (sanırım) oldukça okunaklı.

Güncellemeler

  • Değişti! mantıklı değil ve eşleşmeleri işaretlemeyecek
  • <!>Colinear'ı çözmek için eklendi
  • Çözülmüş Eşleşen Haçlar
  • Satranç tahtalarını daha az korkunç bir şekilde çözdüm
  • Sınırlı kapatma sözdizimi eklendi %{min,max}
  • Özyineleme örneği eklendi

Çözümler

15 çözüldü, 1 devam ediyor

Yukarıda verilen Çevrimiçi Tercümanı kullanarak bu programları kolayca deneyebilirsiniz!

Problem 1 - Satranç Tahtalarını Bulmak

m:{v<R>2}{h<>1}
v:{c<L>A1}+
h:{c<R>A2}+
c:_?(#_)+#?

Detaylı bir giriş için Problem 3'ten başlayın.

Sorun 2 - Satranç Tahtalarının Doğrulanması

m:{v<R>2}{h<>1}
v:${c<L>A1}+$
h:${c<R>A2}+$
c:$_?(#_)+#?$

Uygun yılanların sınırların dışında sembolü ile kitap $haline getirilmesi, bir programın yalnızca tüm girdiyle eşleşmesini sağlamanın bir yoludur.

Sorun 3 - Basamaklı Dikdörtgen Algılama

m:{c<R>A1}%{2,}
c:[0-9]%{2,}

mYılan hareket doğru, en az 2 yılan yumurtlama ( %{2,}tanım c özelliğini ( "2 sonsuza" anlamına gelen bir kapaktır) c) ve (sağa hareket <R>her yöne mevcut yılan göre olduğu için), daha doğrusu bu durumda aşağı. AParam sadece yumurtlama yılan çağrısından sonra hareket gerektiğini belirten şekerdir. 1Sayı parametreleri "gruplar" yılan koydu - biz dikdörtgenler eşleşmeleri kısıtlamak nasıl parametredir. Aynı gruptaki tüm yılanlar aynı mesafeye gidemediği sürece bir eşleşme sayılmaz.

Problem 4 - Kelime Aramada Kelime Bulma

m:<*>GOLF

Yön komutu <*>, yılanın herhangi bir çapraz veya dikey yönde dönmesi gerektiğini belirtir. Sonra basit regex arar.

Problem 5 - Kare Girdileri Algılama

m:{v<R>1}{h<>1}
v:${c<L>A1}+$
h:${c<R>A1}+$
c:$.+$

Buradaki anahtar $, yalnızca yılan sınır dışındaysa eşleşen özel karakterdir . Yatay bir yılan ve dikey bir tane yarattık; bu yumruların her biri kenar boyunca aktıkça daha fazla yılan doğar ve bunların hepsi aynı gruptadır ve aynı uzunlukta olmalıdır.

Problem 6 - Yaşam Oyunda Planör Bulun

m:<+>[({l1<R>A}{l2<R>A}{l3<R>})({l1<L>A}{l2<L>A}{l3<L>})]
l1:##\.
l2:[(#\.)(\.#)]#
l3:#\.\.

mDört ortogonal yönden ( <+>) herhangi biriyle başlayarak dönüşü gerçekleştirir. Ardından, üç sıra için sağa veya sola bakar ve yansımayı sağlar.

(Boşlukları yalnızca noktalarla değiştirdiğimi unutmayın; çünkü tercümanımda kullanılan HTML textareas arka arkaya birden fazla boşluk içeriyorsa aptalca şeyler yapıyor gibi görünüyor)

Problem 7 - Nether Portal'larını Eşleştir

m:{e<R>A1}{d<R>A1}%{2,22}{e<R>1}
e:~.X%{3,22}~.
d:X\.+X

mBir yılan yumurtlama sağ yılan hamle, sağ kenar kontrol etmek nihayet bir yılan orta sütunları kontrol etmek, 2-22 yılan sol kenarını kontrol ve. ~Operatör kontrol edilmelidir izler ancak çözümün bir parçası olarak işaretlenmiş olmamalı ne olursa olsun gösterir.

Sınırlı kapamalar şimdi bu sorunu tam ve doğru şekilde çözmemize izin veriyor!

Sorun 8 - Minecraft Göğüs Yerleştirme

m:~{s<>}~!{d<+>}\.
s:<+>.<BR>([$\.]<R>)%{3}
d:.<+>CC

Burada !, yalnızca aşağıdaki simge hiçbir şeyle eşleşmiyorsa eşleşirse eşleşen mantıksal bir not ( ) kullanırız . Deklarasyon dbelirli bir yönde çift sandık tespit ettiğinden !{d<+>}, herhangi bir ortogonal yönde çift sandık bulunmadığından emin olur. sGeçerli karenin etrafında küçük bir elmas şeklinde hareket ederek, bu alanlardan en az 3 tanesinin boş ya da tahta dışında olduğunu doğrulayın. Sondaki \.nihayet tüm önceki koşullar başarılı varsayarak kare eşleşir.

Problem 9 - Yatay ve Dikey Hizalama

m:<R>?#~.*#

Yılan misteğe bağlı olarak <R>?sekansı eşleştirmeden önce sağa ( ) döner . .regex'te olduğu gibi bir joker karakterdir.

Sorun 10 - Colinear Noktaları

m:<!>#~.*#~.*#

Yönün eklenmesi ile <!>bunu şimdi çözebiliriz! <!>gibidir, <+>ancak dört yönde dallanma yerine, mümkün olan her yöne dallanır.

Problem 12 - Q harfinden kaçının

m:{h<R>A}%{4}
h:[^Qq]%{4}

Sadece her biri Q harfi olmayan dört karakter araştıran 4 yılan ortaya çıkar.

Sorun 13 - Elmas Madenciliği

m:{tl<RB>1}{tr<RF>1}
tl:X/*{bl<L>1}X
tr:X\\*{br<R>1}X
bl:X\\*X
br:X/*X

Bu çok iyi. mbiri sağa, biri sağa doğru giden iki yılanı yumurtlar. Bunlardan her biri eğik çizgileri bir X'e kadar takip eder, daha sonra bir başka yılanı, geçerli yönüne dik bir açıyla yumurtlar, bu da eğik çizgileri X'in altına doğru takip eder.

Problem 14 - Eşleşen Haçlar

m:{a<R>A}+{b<R>A}+{a<R>A}+
a:{e<>P1}{c<>P2}{e<>P3}
b:{c<>P1}{c<>P2}{c<>P3}
e:\.+
c:#+

Pİggyback parametresini ilk kez kullanıyorum. Normalde yılanlar bağımsızdır, ancak bu parametre ile bir çağrı yaparsanız, çağrı yapan yılan callee ile taşınacaktır. Böylece e2'.' Dizisini, sonra '#' dizisini, sonra '.' Dizisini kontrol edebilir ve hepsinin ayrı çağrılar olmasını sağlayabilirsiniz, böylece onları '1,' 2 've' 3 'olarak gruplayabiliriz. , uzunluklarını uyuşmaya zorlamak.

Problem 15 - Boggle Tahtasında Bir Kelime Eşleştirme

m{I}:<*>p<*>a<*>n<*>a<*>m<*>a

Basit, eğer wordy. Iparametresi büyük / küçük harfe duyarsızlığı belirtir (tanımlarda ve çağrılarda parametreleri belirleyebiliriz). Yılan herhangi bir yöne döner, karakterle eşleşir, tekrar döner, vb.

m{EI}:<*>p<*>a<*>n<*>a<*>m<*>a

Bu, yeniden kullanılmayan karakter sürümüdür. EXclusive parametresi zaten çok feersum en balçık yollar gibi, işaretlenmiş herhangi bir karakter eşleşen gelen yılan yasaklamaktadır.

Problem 16 - Kenarları Sarın

m{W}:{c<R>WA}%{3}
c:###

WParametre o dışı sınırları çalıştırdığında sarmak için yılan verir. Ayrıca var Hve Vsadece yatay veya dikey kaydırma izin vermek.

Ekstra - Labirent Çözücü

m{E}:$(<P>\.)+$

Yürüme tabanının periyodik olduğu ASCII labirentini çözer. <P>Yönü ileri, sol veya sağ (şeker için araçlar [<F><L><R>]).

Ekstra - Paren Eşleştirme

m:\(~{r<>P}\)
r:[^\(\)]*(\({r<>P}\))?[^\(\)]*

Prelude'un nasıl yapılacağını henüz çözemedim, ama işte ilk adım! Burada, ryılanı, aralarında benzersiz bir parantez olmadığını kontrol ederek karşılık gelen parantezleri eşleştirmek için tekrarlı bir şekilde kullanırım .

Ekstra - ASCII Topolojisi: Döngüleri Sayma


Bu dilin sadece eşlemekten ziyade yerine geçmesi için sözdizimi eklemeyi düşünür müsünüz? Codegolf.stackexchange.com/questions/51231/… için bir giriş yazmak için bu zorluğa bazı çözümler kullanmak istiyorum, ancak burada bul ve değiştir işlevinin tek bir çözümü yok. (Cevabımın diline özgü zamanlama kuralları nedeniyle geçerli olmayacağını biliyorum)
Sparr

@Sparr. Kötü bir fikir değil, kesinlikle kod golf için daha yararlı olacaktır. Ne zaman kendim yapacak vaktim olacağından emin değilim, ama aklımda tutacağım.
BMac

3
ayrıca: yön değişikliği sözdizimi kafa karıştırıcıdır. yılan bir karakteri eşleştirdikten sonra ilerlediğinden, yönümün benim için anlamlı olduğu yerin önünde bir karakter değişikliği yapmam gerekiyor gibi görünüyor. örnek: string "ABC \ nDEF" ve ABCF tarafından tanımlanan L şeklindeki tetris parçasını eşleştirmek istiyorum, yılanımı "m: ABC <R> F" olarak yazmak istiyorum ancak "m: AB <R> yazmam gerekiyor CF "yerine. Bunun şartnameye uyduğunu biliyorum ama çok sezgisel buluyorum.
Sparr

Ön sözdizimi için kısmi bir çözümüm var. Tek sorun, bütün girdiyle eşleşmiyorsa eşleşmemesini sağlayamamasıdır: m:{a<>} a:[({n<R>A})({n<R>A}*{l<R>A}{a<>P}{r<R>A})]*{n<R>A}* l:$[^\(\)]*\([^\(\)]*$ r:$[^\(\)]*\)[^\(\)]*$ n:$[^\(\)]+$
TheNumberOne 16:15

21

Kayma, Python 3.4 ( Github wiki , çevrimiçi tercüman )

Feersum'un gönderiminde olduğu gibi, bu aynı zamanda şebekeyi geçme üzerine kuruludur, ancak CarpetPython'un gönderdiği gibi bu da regex'e dayanmaktadır. Her nasılsa orta zeminde kalmayı başardım gibi görünüyor.

Eklemek istediğim birçok uygulanmamış özellik var, bu yüzden ilgili olduğunda zaman kazandığımda ne yapmak istediğimi not ettim.


Güncellemeler

(Ayrıntılı haberler için Github sayfasına bakınız)

  • 5 Nisan 2015 : Slip'in çevrimiçi tercümanı var ! Hala erken aşamalarında, bu yüzden birkaç hata olabilir.

  • 5 Nisan 2015 : Verimlilik güncellemesi! Şimdi nether portalları büyük girdiyi çok daha hızlı yapıyor (2s). Ayrıca çok sayıda sözdizimi değişikliği oldu, bu yüzden wikiyi kontrol ettiğinizden emin olun. Grup numaralandırması da düzeltildi.


Kayma, belirli bir karede başlayan ve başlangıçta sağa bakan bir eşleşme işaretçisine sahiptir. Bir karakter eşleştirildiğinde, işaretçi geçerli yönde ileriye doğru hareket eder (uygulama işleri tam olarak bu sırada yapmaz).

Maç işaretçinin yönü ile belirli bir yönde ayarlanabilir ^<digit>, ^0, ^1, ^2, ..., ^7N, NE, E işaretçisini, ..., K, sırasıyla (saat yönünde olacak).

Aşağıdaki kısayollar da mevcuttur:

  • ^* 8 ortogonal veya çapraz yöne doğru kontrol eder,
  • ^+ tüm dört ortogonal yönü kontrol eder.

(Gelecek planı: keyfi (1, 2)şövalyelerin ayarlanmasına izin verin, örneğin şövalye hareketi için)

Örneğin ( Problem 4 - Kelime aramasında kelime bulma ),

^*GOLF

"GOLF" sözcüğünü arayan 8 ortogonal veya çapraz yöne doğru çalışır. Varsayılan olarak, Slip olası tüm başlangıç ​​karelerini dener ve yinelenenleri filtreleyen her birinden bir sonuç döndürür;

GOLF
O
L
FLOG

yalnızca üst ve alt satırları eşleşerek döndürür (üst satır ve sol sütunda "GOLF" ler aynı kareden başladığından beri). Tüm eşleşmeleri almak için oçakışan eşleme modu kullanılabilir.

Benzer şekilde ( Problem 15 - Boggle panosundaki bir kelimeyi eşleştir ),

p^*a^*n^*a^*m^*a

panamaher seferinde farklı bir yön deneyerek eşleşir . Büyük / iküçük harf duyarlılığı için bayrağı kullanın . Kayma, karakterleri varsayılan olarak yeniden kullanır, ancak bu, ryinelenmeyen bayrakla değiştirilebilir.

(Gelecek planı: her hamleden sonra yön kümelerini otomatik olarak kontrol eden ve yinelemenin ^*gereksiz olduğu bir arama modu değiştiricisi )

Eşleşme işaretçisinin yönü ayrıca <veya >sırasıyla 90 derece sola veya sağa döndürülebilir . Örneğin,

 `#`#< `#<  <`#<`#

desen arar

  #
## 
 ##

aşağıdaki sıraya bakarak:

765
894
123

Bu bize çözmek için izin verir bulma planör - Problem 6 ile

^+(`#`# >`# > `#>`#> |`#`# <`# < `#<`#< | `#`#> `#>  >`#>`#| `#`#< `#<  <`#<`#)

burada bölüm 1 ve 2, planör şekillerini kodlar ve bölüm 3 ve 4, yansıtılan eşdeğerlerini kodlar.

Slip `kaçmak için backtick kullandığını unutmayın . Bunun nedeni, Slip'in dile adını veren başka bir hareket biçiminin olmasıdır - slip komutu. /eşleşme işaretçisini ortogonal olarak sola \kaydırırken eşleştirme işaretçisini ortogonal olarak sağa kaydırır.

Örneğin,

abc   ghi
   def

ile eşleştirilebilir abc\def/ghi.

Özellikle kendi başına kullanışlı olmamakla birlikte, kayma (?| <regex> ), eşleşen bir görünüş gibi davranan sabit grupla birleştirildiğinde daha önemli hale gelir . İçindeki regex eşleştirilir, daha sonra eşleştiricinin konumu ve yönü sabit gruptan önceki durumuna sıfırlanır.

Örneğin,

abc
def
ghi

ile eşleştirilebilir (?|abc)\(?|def)\(?|ghi).

Benzer şekilde, Problem 12 - Q harfinin çözülebildiğinden kaçının

%(\(?|[^qQ]{4})){4}

%ilk \etkinleştirme durdurmak için bir kaymaz komut nerede .

Kayma ayrıca, (?_(<group num>) <regex> )eşleşme uzunluğu, verilen grup numarasıyla aynı uzunluktaysa, içindeki regex ile eşleşen bir uzunluk değeri vardır.

Örneğin, Problem 13 - Elmas madenciliği ile kolayca çözülebilir

^1X(`/*)X>(?_(1)`\*)X>(?_(1)`/*)X>(?_(1)`\*)

ilk önce pırlantanın sol üst tarafıyla eşleşmeye çalışır, sonra diğer üç tarafın aynı uzunlukta olduğunu iddia eder.

( vAyrıntılı çıktı için bayrakla çalıştırın )

Match found in rectangle: (8, 0), (12, 4)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (0, 0), (6, 6)
   X
  / \
 /   \
X     X
 \   /
  \ /
   X

Match found in rectangle: (2, 2), (4, 4)
 X
X X
 X

Match found in rectangle: (10, 2), (14, 6)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (5, 3), (9, 7)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (0, 6), (2, 8)
 X
X X
 X

Bir golfçü alternatifi

^1X(`/*)(X>(?_(1)`\*)X>(?_(1)`/*)){2}

hangi iki taraf ilk tarafla eşleşir.

Diğer sorunların çoğu kayma, sabit gruplar ve uzunluk değerleri kullanılarak çözülebilir:

Problem 14 - Eşleşen haçlar:

(?|(`.+)(`#+)(`.+))(\(?|(?_(2)`.+)(?_(3)`#+)(?_(4)`.+)))*(\(?|(?_(2)`#+)(?_(3)`#+)(?_(4)`#+)))+(\(?|(?_(2)`.+)(?_(3)`#+)(?_(4)`.+)))+

İlk satırda .s ve #s genişliklerini yakaladığınızda, tamamen aşağı kayıyor.

Çıktı:

Match found in rectangle: (0, 1), (5, 5)
.###..
######
######
.###..
.###..

Match found in rectangle: (4, 6), (6, 8)
.#.
###
.#.

Bu, muhtemelen birkaç özyinelemeyle golf oynayabilir, bir kaç böceğin çözülmesini sağladığımda.

Sorun 3 - Bir basamak dikdörtgeni algıla:

(?|`d`d+)(\(?|(?_(1)`d+)))+

İki veya daha fazla basamaktan oluşan bir üst satırla eşleştirin, ardından aşağıdaki her satırın aynı uzunlukta olduğundan emin olun. `deşdeğer bir önceden tanımlanmış karakter sınıfıdır [0-9].

Bunun tüm eşleşmeleri bulduğunu unutmayın .

Problem 7 - Nether portallarını eşleştirin:

(?|.X{2,22}.)\((?|(?_(1)X`.+X))\){3,22}(?_(1).X+.)

orijinal iş parçacığındaki ilk örnek için bu çıktılar :

Match found in rectangle: (2, 1), (5, 5)
XXXX
X..X
X..X
X..X
XXXX

Match found in rectangle: (9, 1), (14, 5)
.XXXX.
X....X
X....X
X....X
.XXXX.

Match found in rectangle: (13, 4), (17, 8)
.XXXX
X...X
X...X
X...X
.XXX.

Son olarak, Slip'in diğer bazı özellikleri arasında:

  • $0, $1, $2, ..., $7kuzey kenarı, kuzey doğu köşesi, doğu kenarı vb. $+kenarı tutturur, herhangi bir kenarı $*tutturur ve herhangi bir kenarı tutturur.
  • $ardından bir küçük harf karakteri, geçerli konumda bir çapa ayarlar; daha sonra $karşılık gelen büyük harf karakteri ile eşleştirilebilir.$a ve $A.
  • # Eşleşme işaretçisinin bir sonraki eşleşmeden sonra ileri hareket etmesini durduran hareketsiz bayrağını değiştirir.
  • ,gibi bir karakterle eşleşir ., ancak bunu tanımadıkça bitişik olmayan eşleşmelere izin vererek çıktıya eklemez(?_()) .

... ve dahası. Bu sayfada listelenecek gerçekten çok fazla var.

Diğer problemler

Problem 1 - Satranç tahtasının bulunması:

(?|`#?(`_`#)+`_?)(?_(1)(?|...+))(\(?_(1)(?|`#?(`_`#)+`_?$a)))+<(?|`#?(`_`#)+`_?)(?_(9)(?|...+))(\(?_(9)(?|`#?(`_`#)+`_?)))+$A

İki satranç tahtası sorunu kesinlikle Slip'in forte'ı değil. Biz üst satır sonra arasında en az uzunluk 3 ve vekilleri olduğundan emin maç #ve _ardından kayma ve sonraki satır maç. Sonunda$a çapa satranç tahtasının sağ altında olmalıdır.

Daha sonra sola döndük $Ave sonunda eşleştiğimizden emin olarak sütunlar için tekrarlayın .

Sorun 2 - Satranç tahtasının doğrulanması:

$7%(\(?|`_?(`#`_)*`#?$2))+$5<%(\(?|`_?(`#`_)*`#?$0))+$3

Önceki problem gibi, her satırın doğru olduğunu kontrol ettikten sonra sola döndürün ve sütunlar için aynısını yapın. Ankrajlar yalnızca tüm tahtanın eşleştiğinden emin olmak için kullanılır.

Problem 9 - Yatay ve dikey hizalama:

>?`#,*`#

İsteğe bağlı mı başvuruyoruz? >döndürme komutunun niceleyicisi, böylece sağa veya aşağıya doğru eşleşiriz. Biz birlikte örnekteki tüm 5 bulmak omodu örtüşen, fakat sadece 4 onsuz beri #.,##ve #.,#aynı pozisyonda başlar.

Problem 10 - Collinear noktaları

^+`#(?|(,*)<(,*))(((?_(2),*)<(?_(3),*),>)+#`#){2}

Bir maç #, o zaman, bazı yatay karakter ve bir dikey karakter daha sonra ikinci kadar tekrar #ve üçüncü kadar tekrar #.

Problem 5 - Kare girişleri tespit etmek:

$7.(.*)>(?_(1).*)$3>((?|.*)\)*

Sol üst köşeyi tutturun ve sağ alt köşeyi tutturmadan önce, üst kenarın sağ kenar ile aynı uzunlukta olup olmadığını kontrol edin. Giriş bunu geçerse, o zaman tüm girişi eşleştirmek için geriye doğru gideriz.

Problem 8 - Minecraft göğüs yerleşimi:

`.^+(($^|(?|`.))>){3}($^|`.|C<(($^|(?|`.))>){3})

pHer maçın pozisyonlarını almak için bayrakla koşun .$^bir sonraki hareketin eşleşme işaretçisini sınırların dışına çıkarması durumunda eşleşen bir bağlantıdır.

İlk önce a ile eşleşelim, sonra .üç .s / sınırla çevrildiğimizi kontrol edin , daha sonra dördüncü çevre karesinin aynı zamanda bir .sınır olduğunu veya tek bir sandık olduğundan emin olun ( çevresindeki kareleri kontrol ederek ).

Sorun 11 - Başlangıç ​​sözdizimini doğrulayın :

$7>%(/(?|[^()]+$4)(?1)?|/(?|[^()]*`([^()]*$4)(?1)?/(?|[^()]*`)[^()]*$4)(?1)?)$1

Birkaç deneme aldı, ama bence bu doğru. Burada PCRE ile aynı sözdizimine sahip özyineleme kullanıyoruz.

Bu yaklaşım, girişin dikdörtgen olmasını gerektirir, ancak bir kez dikdörtgen olmayan eşleştirme elde ettiğimde, bu varsayım gerekli olmayacak.

İşte aynı yaklaşım, daha fazla özyineleme ile golf:

$7>%((/(?|([^()]*)$4)|/(?|(?4)`((?3))(?1)?/(?|(?4)`)(?3)))*)$1

Problem 16 - Kenarların etrafına sarın:

%(\(?|`#{3})){3}

(Not: Ambalajlama henüz çevrimiçi tercümana gönderilmemiştir)

Bu, sarma bayrağını gerektirir w. Teknik olarak %kaymaz için ilk gerekli değildir, ancak daha sonra maç bir kare yüksekliğinden başlayarak sayılır.

Problem EX 1 - Labirent çözücü:

S(^+`.)*^+E

BMac'ın sohbette yaptığı yorumdan kaynaklanan sorun . Kullanım rmaç işaretçi ileri geri gidiş takılıp kalmaması hayır tekrar modu için bayrak.

Problem EX 2 - Yüz tanıma :

(?|O(,*),(?_(2),*)O)(?_(2)(\(?|,))*)\(?|,(?_(2),*)O)(?_(2)(\(?|,))*)\`\(?_(2)`_*)`_(?_(2)`_*)`/

Sadece yüzleri eşleştirdiğimi, herhangi bir temizleme işlemi yapmadığımı unutmayın. Sorunun çalışması için yazdırılabilir bir ASCII ile değiştirilmesi gereken euro sembollerini içerdiğini unutmayın.


Bu karma desen Conway planör
Heimdall

17

PMA / Salyangoz (C ++)

Dili bir salyangozun bir ızgara etrafında hareket etmesi ve komutları yürütmesi olarak görüyorum. Salyangoz, her karenin üzerine ilerleyerek karenin daha sonra eşleştirilememesine neden olan bir sümük izi bırakır. Komut listesinin sonuna gelindiğinde bir eşleşme başarılı olur.

Artık onları takip etmek için öncelikli bir listeye ihtiyacımız olacak kadar operatör var. İşlemler aşağıdaki sırayla çözülür:

  1. Grupların içi ( ) [ ]
  2. Değişim karakteri boyunca bölün |
  3. `Bir grubun solundaki her şeyi bir grup olarak değerlendirin
  4. Kantitatifler [m],[n]ven
  5. İddialar = !
  6. birbirine bağlama

Tercüman C ++ dilinde yazılmıştır. Abisal kaynak kodu burada bulunabilir .

Sorun 4: Kelime Arama

Program

z\G\O\L\F

kelimenin bulunup bulunmadığına ilişkin bir gerçek veya falsey değeri elde etmek için yeterlidir. z(15 mutlak veya bağıl yön komutlarından biri) herhangi bir sekiz yönlü yönde eşleşir. Ardışık çoklu yön komutları birlikte ORed. Örneğin , bunlar sağ, yukarı, sola, aşağı ve herhangi bir çapraz yöne yönelik komutlar olduğu için ruldyneredeyse eşdeğerdir z. Bununla birlikte, talimatlar farklı bir sırayla test edilecektir. Eşleşen ilk karakter, yönünden bağımsız olarak daima salyangozun başladığı karakterdir. \<character> tek bir değişmez karakterle eşleşir.

Varsayılan strateji, kalıbı sola dayalı girişin sınırlayıcı kutusundaki her karede denemek ve eşleşme sayısını çıkarmaktır. Bir boolean değeri 1veya 0gerekliyse, aşağıdaki program kullanılabilir:

?
z\G\O\L\F

Kaynak dosyada en az bir yeni satır varsa, ilk satır girişin dikdörtgen forma dönüştürülmesi için seçenek olarak kabul edilir. ?Opsiyon baskılar 0 veya 1 yerde bir eşleşme olup olmadığına bağlı.

Problem 15: Boggle

Alternatiflemeyi uyguladıktan sonra, Boggle'ı çözmek artık mümkün. Bunun için büyük / küçük harfe duyarlı olmayan bir eşleştirme kullanmak daha iyi olurdu, ancak bunu uygulamak benim en büyük önceliğim değil.

\p|\P)z(\a|\A)z{\n|\N)z{\a|\A}z(\m|\M)z(\a|\A

|1 boyutlu bir regex ile tamamen aynı şekilde çalışır. Gruplama için iki eşleştirme sınırlayıcı çifti vardır, yani ()ve {}. Bir kapatma braketi, aynı tipe en yakın olan ve karşı tipte olan açık grupları kapatacaktır. Örneğin, ardından {({{), en soldaki grup açık kalır. Gördüğünüz gibi, kenarlardaki eşleşmemiş gruplandırma sembolleri dolaylı olarak kapalı. `Şimdi girmeyeceğim başka bir gruplama komutu var.

Problem 8: Minecraft Sandıkları

Program geçerli göğüs yerleşimlerinin sayısını yazdırır. Bu gerçekten golf oynamak zorunda kaldığım ve bayt sayımı (17) birkaç kez düşürdüm.

\.!(o\C)2o(!\Cw)3
  • \. Kelimenin tam anlamıyla bir noktayı eşleşmenin başlangıç ​​noktasında eşleştirir.
  • !(o\C)2!((o\C)2)niceleme, iddiadan daha yüksek önceliğe sahip olduğundan eşittir . tam <atom> <number>olarak tekrarlamak demektir .<atom><number>osalyangozu herhangi bir dikey yönde döndürür. !olumsuz bir iddiadır. Bu nedenle, bu bölüm bitişik bir çift sandığın yokluğunu kontrol eder.
  • o bazı dik yönde döner.
    • (!\Cw)3Csalyangozun önünde olmadığını ve ardından saat yönünün tersine 3 kez döndüğünü iddia eder .

Sorun 2: Satranç tahtasının doğrulanması

&
\#!(o^_)|\_!(o^#

&Seçenek olarak programın çıkışı set 1maçı tüm pozisyonlarda başarılı ve eğer 0aksi. eşdeğerde regex'te ^colmayan bir karakterle eşleşir . Bir bütün olarak, program şu anlama gelir: Girdiyi sınırlayan dikdörtgenin her yerinde, her pozisyonda, Yazdır 1 , olmayan bir karakterin ortogonal olarak bitişik olmayan veya bir karakterin ortogonal olarak bitişik olmayan değil ; aksi halde 0.c[^c]#__#


Sümük izi fikri
boggle

Boggle problemi için güzel bir çözüm. Bunu yaklaşımımla çözemiyorum.
Mantık Şövalye

14

Re2d sınıfı, Python 2

Güncelleme: "9. Hizalama" sorunu eklendi.

Benim yaklaşımım Python re modülünü kullanarak arama ve eşleştirme yapmak. Re2d sınıfı, metni işleme için hazırlar, re işlevlerini yürütür ve sonuçları çıktı için biçimlendirir.

Bunun tamamen yeni bir dil olmadığını unutmayın - ekstra 2D modlar için eklenmiş bayraklarla 2 boyuta yansıtılan standart düzenli ifade dilidir.

Sınıfın şu kullanımları vardır:

re2dobject = Re2d(<horizontal pattern>, [<vertical pattern>], [<flags>])

Her iki desen de standart doğrusal metin RE desenleridir. Dikey bir desen sağlanmazsa, sınıf dikey olarak eşleştirmek için yatay deseni de kullanır. Bayraklar, bazı 2B uzantılarına sahip standart RE bayraklarıdır.

Test yapmak

1. Finding chessboards
Chessboard pattern at (2, 1, 4, 3)

print '\n1. Finding chessboards'
reob1 = Re2d('#(_#)+_?|_(#_)+#?')
found = reob1.search('~______~\n~##_#_#~\n~#_#_##~\n~##_#_#~\n~______~')
print 'Chessboard pattern at', found
assert not reob1.search('#_##\n_#_#\n__#_\n#_#_\n#_#_')

Arama yöntemi bir satranç tahtası deseni buldu ve 4-tuple konumu döndürdü. Tuple x,ymaçın ilk karakteri ve eşleşen alanın pozisyonuna sahiptir width, height. Sadece bir desen verilmiştir, bu yüzden yatay ve dikey dikey eşleştirme .

2. Verifying chessboards
Is chess? True

print '\n2. Verifying chessboards'
reob2 = Re2d('^#(_#)*_?|_(#_)*#?$')
print 'Is chess?', reob2.match('_#_#_#_#\n#_#_#_#_\n_#_#_#_#')
assert not reob2.match('_#_#_#__\n__#_#_#_\n_#_#_#__')

Satranç tahtası, bir boole döndüren eşleştirme yöntemiyle doğrulandı. Not ^ve $başlangıç ve bitiş karakterleri eşleştirmek için gerekli olan bütün metnin .

3. Rectangle of digits
Found: [(0, 1, 5, 3), (1, 1, 4, 3), (2, 1, 3, 3), (3, 1, 2, 3), (0, 2, 5, 2), (1, 2, 4, 2), (2, 2, 3, 2), (3, 2, 2, 2), (6, 3, 2, 2)]
Not found: None

print '\n3. Rectangle of digits'
reob3 = Re2d(r'\d\d+', flags=MULTIFIND)
print 'Found:', reob3.search('hbrewvgr\n18774gwe\n84502vgv\n19844f22\ncrfegc77')
print 'Not found:', reob3.search('uv88wn000\nvgr88vg0w\nv888wrvg7\nvvg88wv77')

Şimdi kullanıyoruz MULTIFIND 2+ basamaklı blok için olası tüm eşleşmeleri döndürmek bayrağı . Yöntem 9 olası eşleşme bulur. Üst üste gelebileceklerini unutmayın.

4. Word search (orthogonal only)
Words: [(0, 0, 4, 1), (0, 3, 4, 1), (3, 3, -4, -1), (3, 2, -4, -1), (3, 0, -4, -1)] [(0, 0, 1, 4), (3, 0, 1, 4), (3, 3, -1, -4), (0, 3, -1, -4)]
Words: ['SNUG', 'WOLF', 'FLOW', 'LORE', 'GUNS'] ['S\nT\nE\nW', 'G\nO\nL\nF', 'F\nL\nO\nG', 'W\nE\nT\nS']
No words: [] []

print '\n4. Word search (orthogonal only)'
words = 'GOLF|GUNS|WOLF|FLOW|LORE|WETS|STEW|FLOG|SNUG'
flags = HORFLIP | VERFLIP | MULTIFIND
reob4a, reob4b = Re2d(words, '.', flags), Re2d('.', words, flags)
matching = 'SNUG\nTEQO\nEROL\nWOLF'
nomatch = 'ABCD\nEFGH\nIJKL\nMNOP'
print 'Words:', reob4a.search(matching), reob4b.search(matching)
print 'Words:', reob4a.findall(matching), reob4b.findall(matching)
print 'No words:', reob4a.findall(nomatch), reob4b.findall(nomatch)

Bu test dikey ve yatay çevirmenin kullanımını gösterir. Bu, ters çevrilen kelimelerin eşleşmesini sağlar. Çapraz kelimeler desteklenmiyor. MULTIFINDBayrak 4 yönde Birden fazla örtüşen eşleşmeleri verir. Findall yöntemi eşleşen kutuları bulmak için arama kullanır ve ardından eşleşen metin bloklarını çıkarır. Aramanın ters yönde eşleşmelerde negatif genişlik ve / veya yükseklik kullandığını unutmayın. Dikey yöndeki kelimelerin yeni satır karakterleri vardır - bu 2B karakter blokları kavramı ile tutarlıdır.

7. Calvins portals
Portals found: [(3, 1, 5, 6)]
Portal not found None

print '\n7. Calvins portals'
reob7 = Re2d(r'X\.{2,22}X|.X{2,22}.', r'X\.{3,22}X|.X{3,22}.', MULTIFIND)
yes = '....X......\n.XXXXXX.XX.\n...X...X...\n.X.X...XXX.\n...X...X.X.\n.XXX...X.X.\nX..XXXXX.X.'
no = 'XX..XXXX\nXX..X..X\nXX..X..X\n..X.X..X\n.X..X.XX'
print 'Portals found:', reob7.search(yes)
print 'Portal not found', reob7.search(no)

Asgari boyut her biri için farklı olduğundan, bu arama her boyut için ayrı desenlere ihtiyaç duyuyordu.

9. Alignment
Found: ['#.,##', '##'] ['#\n.\n,\n.\n#', '#\n,\n.\n#']
Found: [(3, 4, 5, 1), (6, 4, 2, 1)] [(7, 0, 1, 5), (3, 1, 1, 4)]
Not found: None None

print '\n9. Alignment'
reob9a = Re2d(r'#.*#', r'.', MULTIFIND)
reob9b = Re2d(r'.', r'#.*#', MULTIFIND)
matching = '.,.,.,.#.,\n,.,#,.,.,.\n.,.,.,.,.,\n,.,.,.,.,.\n.,.#.,##.,\n,.,.,.,.,.'
nomatch = '.,.#.,.,\n,.,.,.#.\n.,#,.,.,\n,.,.,.,#\n.#.,.,.,\n,.,.#.,.\n#,.,.,.,\n,.,.,#,.'
print 'Found:', reob9a.findall(matching), reob9b.findall(matching)
print 'Found:', reob9a.search(matching), reob9b.search(matching)
print 'Not found:', reob9a.search(nomatch), reob9b.search(nomatch)

Bu 2 arama kümesi 2 dikey ve 2 yatay eşleşme bulur, ancak gömülü bulamaz #.,# dizeyi .

10. Collinear Points (orthogonal only)
Found: [(0, 1, 7, 1)] [(3, 1, 1, 4)]
Not found: None None

print '\n10. Collinear Points (orthogonal only)'
matching = '........\n#..#..#.\n...#....\n#.......\n...#....'
nomatch = '.#..#\n#..#.\n#....\n..#.#'
reob10h = Re2d(r'#.*#.*#', '.')
reob10v = Re2d('.', r'#.*#.*#')
flags = MULTIFIND
print 'Found:', reob10h.search(matching, flags), reob10v.search(matching, flags)
print 'Not found:', reob10h.search(nomatch, flags), reob10v.search(nomatch, flags)

Burada her iki yönde de eşleşmeleri bulmak için 2 arama kullanıyoruz. Birden fazla ortogonal eşleşme bulabilir, ancak bu yaklaşım diyagonal eşleşmeleri desteklemez.

12. Avoid qQ
Found: (2, 2, 4, 4)
Not found: None

print '\n12. Avoid qQ'
reob12 = Re2d('[^qQ]{4,4}')
print 'Found:', reob12.search('bhtklkwt\nqlwQklqw\nvtvlwktv\nkQtwkvkl\nvtwlkvQk\nvnvevwvx')
print 'Not found:', reob12.search('zxvcmn\nxcvncn\nmnQxcv\nxcvmnx\nazvmne')

Bu arama ilk eşleşmeyi bulur.

13. Diamond Mining
.X.
X.X
.X.

.X.
X.X
.X.

..X..
./.\.
X...X
.\./.
\.X..

..X..
./.\.
X...X
.\./.
..X..

.XX.\
//.\.
X...X
.\./.
..X..

...X...
../.\..
./.X.\.
X.X.X.X
.\.X.//
..\./X.
.X.X..\

Diamonds: [(2, 2, 3, 3), (0, 6, 3, 3)] [(8, 0, 5, 5), (10, 2, 5, 5), (5, 3, 5, 5)] [(0, 0, 7, 7)]
Not found: None None None

print '\n13. Diamond Mining'
reob13a = Re2d(r'.X.|X.X', flags=MULTIFIND)
reob13b = Re2d(r'..X..|./.\\.|X...X|.\\./.', flags=MULTIFIND)
reob13c = Re2d(r'...X...|../.\\..|./...\\.|X.....X|.\\.../.|..\\./..', flags=MULTIFIND)
match = '''
...X......X....
../.\..../.\...
./.X.\..X...X..
X.X.X.XX.\./.\.
.\.X.//.\.X...X
..\./X...X.\./.
.X.X..\./...X..
X.X....X.......
.X.............
'''.strip().replace(' ', '')
nomatch = '''
.X......./....
.\....X.......
...X.\.\...X..
..X.\...\.X.\.
...X.X...X.\.X
../X\...\...X.
.X...\.\..X...
..\./.X....X..
...X..../.....
'''.strip().replace(' ', '')
for diamond in reob13a.findall(match)+reob13b.findall(match)+reob13c.findall(match):
    print diamond+'\n'
print 'Diamonds:', reob13a.search(match), reob13b.search(match), reob13c.search(match)
print 'Not found:', reob13a.search(nomatch), reob13b.search(nomatch), reob13c.search(nomatch)

Elmas problemi daha zor. Üç boyut için üç arama nesnesi gerekir. Test setinde altı elmas bulabilir, ancak değişken boyutlu elmaslara ölçeklendirilmez. Bu, elmas problemine yalnızca kısmi bir çözümdür.

Python 2 kodu

import sys
import re

DEBUG = re.DEBUG
IGNORECASE = re.IGNORECASE
LOCALE = re.LOCALE
UNICODE = re.UNICODE
VERBOSE = re.VERBOSE
MULTIFIND = 1<<11
ROTATED = 1<<12     # not implemented
HORFLIP = 1<<13
VERFLIP = 1<<14
WRAPAROUND = 1<<15  # not implemented

class Re2d(object):
    def __init__(self, horpattern, verpattern=None, flags=0):
        self.horpattern = horpattern
        self.verpattern = verpattern if verpattern != None else horpattern
        self.flags = flags

    def checkblock(self, block, flags):
        'Return a position if block matches H and V patterns'
        length = []
        for y in range(len(block)):
            match = re.match(self.horpattern, block[y], flags)
            if match:
                length.append(len(match.group(0)))
            else:
                break
        if not length:
            return None
        width = min(length)
        height = len(length)
        length = []
        for x in range(width):
            column = ''.join(row[x] for row in block[:height])
            match = re.match(self.verpattern, column, flags)
            if match:
                matchlen = len(match.group(0))
                length.append(matchlen)
            else:
                break
        if not length:
            return None
        height = min(length)
        width = len(length)
        # if smaller, verify with RECURSIVE checkblock call:
        if height != len(block) or width != len(block[0]):
            newblock = [row[:width] for row in block[:height]]
            newsize = self.checkblock(newblock, flags)
            return newsize
        return width, height

    def mkviews(self, text, flags):
        'Return views of text block from flip/rotate flags, inc inverse f()'
        # TODO add ROTATED to generate more views
        width = len(text[0])
        height = len(text)
        views = [(text, lambda x,y,w,h: (x,y,w,h))]
        if flags & HORFLIP and flags & VERFLIP:
            flip2text = [row[::-1] for row in text[::-1]]
            flip2func = lambda x,y,w,h: (width-1-x, height-1-y, -w, -h)
            views.append( (flip2text, flip2func) )
        elif flags & HORFLIP:
            hortext = [row[::-1] for row in text]
            horfunc = lambda x,y,w,h: (width-1-x, y, -w, h)
            views.append( (hortext, horfunc) )
        elif flags & VERFLIP:
            vertext = text[::-1]
            verfunc = lambda x,y,w,h: (x, height-1-y, w, -h)
            views.append( (vertext, verfunc) )
        return views

    def searchview(self, textview, flags=0):
        'Return matching textview positions or None'
        result = []
        for y in range(len(textview)):
            testtext = textview[y:]
            for x in range(len(testtext[0])):
                size = self.checkblock([row[x:] for row in testtext], flags)
                if size:
                    found = (x, y, size[0], size[1])
                    if flags & MULTIFIND:
                        result.append(found)
                    else:
                        return found
        return result if result else None

    def search(self, text, flags=0):
        'Return matching text positions or None'
        flags = self.flags | flags
        text = text.split('\n') if type(text) == str else text
        result = []
        for textview, invview in self.mkviews(text, flags):
            found = self.searchview(textview, flags)
            if found:
                if flags & MULTIFIND:
                    result.extend(invview(*f) for f in found)
                else:
                    return invview(*found)
        return result if result else None

    def findall(self, text, flags=0):
        'Return matching text blocks or None'
        flags = self.flags | flags
        strmode = (type(text) == str)
        text = text.split('\n') if type(text) == str else text
        result = []
        positions = self.search(text, flags)
        if not positions:
            return [] if flags & MULTIFIND else None
        if not flags & MULTIFIND:
            positions = [positions]
        for x0,y0,w,h in positions:
            if y0+h >= 0:
                lines = text[y0 : y0+h : cmp(h,0)]
            else:
                lines = text[y0 : : cmp(h,0)]
            if x0+w >= 0:
                block = [row[x0 : x0+w : cmp(w,0)] for row in lines]
            else:
                block = [row[x0 : : cmp(w,0)] for row in lines]
            result.append(block)
        if strmode:
            result = ['\n'.join(rows) for rows in result]
        if flags & MULTIFIND:
            return result
        else:
            return result[0]

    def match(self, text, flags=0):
        'Return True if whole text matches the patterns'
        flags = self.flags | flags
        text = text.split('\n') if type(text) == str else text
        for textview, invview in self.mkviews(text, flags):
            size = self.checkblock(textview, flags)
            if size:
                return True
        return False

Elmas problemi net değilse, elmaslar sadece 0, 1 veya 2 değil, her boyutta olabilir. Düzenleme: Bunu daha net hale getirmek için spesifikasyonları değiştirdim.
PhiNotPi 6'15

Anladım. Re2d'nin bu soruna yalnızca kısmi bir çözümü olduğu cevabını not edeceğim. Değişken boyutlara ölçeklendirilemez. Bu iyi mi?
Mantık Şövalye

Evet, bu iyi.
PhiNotPi

14

Grime , Haskell

Giriş

Kir, Boolean gramerlerine dayanır. . Temel fikir, küçük bileşenlerden dikdörtgen desenler oluşturmak ve giriş matrisinde bulunup bulunmadıklarını kontrol etmektir. Şimdiye kadar Grime sadece dikdörtgen eşleşmeleri destekliyor ve en az 11 problemi az ya da çok zarif bir şekilde çözüyor.

EDIT: Haçlar düzeltildi (hatayı tespit ettiği için DLosc sayesinde) ve elmas madenciliği eklendi.

EDIT2: Slip'in ilham alan karakter sınıfları eklendi. Ayrıca, seçenek bayraklarının sözdizimini de değiştirdi, ifade çözümleyicisini geliştirdi ve Q-olmayan sorunu ekledi.

EDIT3: Uygulanan boyut kısıtlamaları ve Nether portalları sorunu eklendi.

kullanım

Bir Grime programı gramer olarak adlandırılır ve gramer için doğru dosya uzantısı .grbu zorunlu olmasa da olur. Dilbilgisi olarak değerlendirilir

runhaskell grime.hs [options] grammarfile matrixfile

burada matrixfilekarakteri matris içeren bir dosya. Örneğin, rakam gramer olarak değerlendirilir

runhaskell grime.hs digits.gr digit-matrix

Ekstra hız için dosyayı en iyileştirmelerle derlemenizi öneririz:

ghc -O2 grime.hs
./grime digits.gr digit-matrix

Varsayılan olarak, tercüman bulduğu ilk eşleşmeyi yazdırır, ancak bu seçenek bayrakları kullanılarak kontrol edilebilir:

  • -e: sadece tüm matrisle eşleş, 1eşleşmeye ve eşleşmeye yazdırmayacak 0.
  • -n: eşleşme sayısını veya -eayrıca verildiyse matrisin tamamını yazdırabilirsiniz .
  • -a: tüm eşleşmeleri yazdır.
  • -p: aynı zamanda eşleşmelerin konumlarını da formatta yazdırabilirsiniz (x,y,w,h).
  • -s: kibritleri kendileri basmayınız.
  • -d: hata ayıklama bilgisini yazdır.

Seçenekler, herhangi bir satırın önüne ekleyerek ve virgül ekleyerek de dilbilgisi içinde belirtilebilir ,(örnekler için aşağıya bakın).

Sözdizimi ve Anlambilim

Bir Grime dilbilgisi her biri ayrı bir satırda olan bir veya daha fazla tanımdan oluşur . Her biri bir nonterminalin değerini tanımlar ve onlardan birinin adsız üst seviye nonterminali tanımlaması gerekir . Bir tanım sözdizimi ya olduğu N=Eya da Eburada, Nbir büyük harf ve Ebir bir sentezleme .

İfadeler aşağıdaki gibi oluşturulur.

  • Kaçan \herhangi bir 1x1karakter, o karakteri içeren herhangi bir dikdörtgene uyar.
  • . herhangi bir tek karakterle eşleşir.
  • $ bir eşleşir 1x1karakter matrisinin dışındaki dikdörtgenle .
  • _ sıfır genişlik veya yükseklikteki herhangi bir dikdörtgenle eşleşir.
  • Önceden tanımlanmış karakter grupları, digit, uppercase, lowercase, alphabetic, alpha numeric ve symbol'dur.
  • Yeni karakter sınıfları sözdizimi tarafından tanımlanabilir [a-prt-w,d-gu]. Soldaki harfler dahil edilir ve sağdakiler hariç tutulur, bu tam olarak harflerle eşleşir abchijklmnoprtvw. Sol taraf boşsa, tüm karakterleri içerecek şekilde alınır. Sağ taraf boşsa virgül atlanabilir. Karakterler [],-\ile kaçılmalıdır \.
  • Çıkmamış büyük harf harfli değildir ve atanan ifadeyle eşleşir.
  • İfadeler Pve Qifadeler varsa PQ, yalnızca yatay birleştirmeleridir ve üstte olacak şekilde P/Qdikey birleştirmeleridir P.
  • P+Pyatay olarak hizalanmış bir veya daha fazladır ve P/+dikey olarak aynıdır.
  • Boolean işlemleri belirtilir P|Q, P&Qve P!.
  • P?kısaca P|_, P*için P+|_ve P/*için P/+|_.
  • P#eşleşmesini içeren herhangi bir dikdörtgene eşleşir P.
  • P{a-b,c-d}Nerede abcdnegatif olmayan tam sayılardır, bir olan boyut kısıtlaması üzerinde P. Eğer Pbir karakter sınıfı, sonra ifadesi herhangi maçları mxn, yalnızca bu karakterleri içeren dikdörtgen şartıyla marasındadır ave bkapsayıcı ve narasındadır cve dkapsayıcı. Diğer durumlarda, ifade, doğru boyutta ve aynı Pzamanda eşleşen herhangi bir dikdörtgene uyar. Eğer aya catlanmıştır, onlar için alınır 0ve eğer bya datlanmıştır, bunlar sonsuz. Arasında kısa çizgi halinde aveb atlanırsa, aralığın her iki ucu için de aynı sayıyı kullanırız. Eğer bütünc-dkısım ihmal edilir, her iki eksen de kısıtlanır. Netleştirmek için, {-b}eşittir {0-b,0-b}ve {a-,c}eşittir {a-infinity,c-c}.

notlar

Grime A=A!tanımsız davranışlarda olduğu gibi paradoksal tanımlara izin verir . Ancak, çökmelere veya sonsuz döngülere neden olmazlar.

Grime dikdörtgen olmayan girdileri destekler; sıralar sadece sola hizalanır ve boşluklar kullanılarak eşleştirilebilir $.

Gelecekte, aşağıdakileri uygulamak istiyorum:

  • Daha hızlı eşleştirme. Şu anda, tercüman, örneğin, .yalnızca 1x1dikdörtgenlerle eşleşebileceğini dikkate almamaktadır . Bir eşleşme bulana kadar, her bir boyuta ait tüm dikdörtgenleri sırayla dener ve her biri için anında başarısız olur.
  • Kelime arama ve planör zorlukları için döndürme ve yansıtma işlemleri.
  • Boggle yönetim kurulu mücadelesinde yardımcı olacak bağlamları kullanan dikdörtgen olmayan eşleşmeler . Örneğin, alt bağlam ( sağ bağlam ile ) Pv(Q>R)anlamına gelir . L şeklindeki kalıplarla eşleşirPQR

    PPP
    PPP
    QQQRRRR
    QQQRRRR
    QQQRRRR
    

Görevler

Karmaşıklık sırasına göre kabaca verilir.

Rakamların dikdörtgen

d{2-}

Bu basittir: en azından boyuta sahip bir dikdörtgen 2x2.

Q veya Q yok

[,qQ]{4}

Bu neredeyse birincisi kadar basit; Artık daha kısıtlı bir boyuta ve özel bir karakter sınıfına sahibiz.

Yatay ve dikey hizalama

\#.*\#|\#/./*/\#

Şimdi bazı kaçan karakterlerimiz var. Temel olarak, bu bir #veya daha sonra herhangi bir sayıdaki karakterle, sonra #yatay veya dikey olarak eşleşir .

Kare girişleri algıla

S=.|S./+/.+
e,S

Bu dilbilgisi çok basittir, temel olarak bir karenin bir 1x1dikdörtgenin veya sağ köşesinde bir sütunun bulunduğu ve bir satırın dibinde bir satır bulunan daha küçük bir kare olduğunu tanımlar . Ayrıca, etüm giriş doğrulamasını değiştiren üst seviye nonterminal seçeneğine dikkat edin.

Kelime aramada kelime bulma

G=\G
O=\O
L=\L
F=\F
GOLF|FLOG|G/O/L/F|F/L/O/G|G.../.O../..L./...F|...G/..O./.L../F...|F.../.L../..O./...G|...F/..L./.O../G...

Bu korkunç, çünkü Grime'ın dönme veya yansıtma için bir işlemi yok. Pislik eşleşmelerinin yalnızca boyutta olabilir bilmiyor, çünkü aynı zamanda son derece yavaştır 4x1, 1x4ya 4x4.

Planör sorunu da benzer şekilde çözülebilir, ancak bunu yazmak için çok tembelim.

Nether Portalları

.\X+./\X/+\.{2-22,3-22}\X/+/.\X+.

Boyut kısıtlama operatörü ile, bu o kadar da zor değil. Orta kısım, \.{2-22,3-22}herhangi bir dikdörtgenle eşleşiyor. , doğru boyutların ve sonra sadece Xher iki tarafa da s sütunları ekleriz Xve üst ve alt kısımlarında göz ardı edilmiş uçları olan s sıralarını tutarız .

Eşleşen haçlar

E=\.+/+
F=\#+/+
EFE/F/EFE&(E/F/E)F(E/F/E)

Burada sahip olduğumuz şey iki ifadenin bir birleşimidir (mantıksal AND). Terminal olmayan Ebir boş olmayan dikdörtgen maçları .s ve Fbir boş olmayan dikdörtgen #s. Bağlantının sol tarafı, türdeki dikdörtgenlerle eşleşiyor

...####..
...####..
...####..
#########
#########
.....##..
.....##..

zirvede EFEolan yerimiz o zamanF , sonra EFEtekrar. Sağ taraf bunların geçişi ile eşleşir, bu yüzden tam olarak haçları alırız.

Elmas madenciliği

C=./+
T=\X|CTC/\/.+\\
B=\X|\\.+\//CBC
CTC/\X.+\X/CBC

Ninterminal olmayan Cherhangi bir 1xnsütun için bir stenodir . Bir elmasın üst yarısı şununla eşleşir T: ya bir bekar Xya da Ther iki taraftaki bir sütunla çevrili bir diğeridir ve /[something]\altındaki bir sıradır . BBir elmasın tabanını aynı şekilde eşleştirir ve üst seviye nonterminal formun X[something]Xbir üst yarısı ile bir alt yarısı arasındaki sırasını gösterir .

Satranç tahtası bulma

(\#\#|\#/\#|\_\_|\_/\_)#!&[#_]{3-}

Sağ taraf , s ve s'nin [#_]{3-}herhangi bir 3x3veya daha büyük dikdörtgenine karşılık gelirken, sol taraf, iki bitişik s veya s içermediğini garanti eder .#_#_

Satranç tahtalarını doğrulama

e,(\#\#|\#/\#|\_\_|\_/\_)#!&[#_]+/+

Bu, temelde yukarıdaki ile aynıdır, ancak boş olmayan herhangi bir dikdörtgeni eşleştirebiliriz, ancak egirişin tamamını doğrulamak için bayrağı kullanmamız gerekir .

Prelude sözdizimini doğrula

A=[,()]/*
P=A*|P(A/\(/A)P(A/\)/A)P
e,P

Bu muhtemelen şu ana kadarki en ilginç gramer. Uç-olmayan Aiçermeyen herhangi bir sütun ile eşleşen (ya da ), ve Pbazı sayısını ya eşleşen Adaha vardır arasında dışında olan, s, ya da iki eşleşen parantez Ps.


@DLosc Sabit, hatayı bulduğunuz için teşekkürler!
Zgarb

Çalışır \#(.*|./*)\#mı?
bkz:

@Sieg Hizalama için mi? Maalesef hayır, çünkü " #solda bir, sonra herhangi bir satır veya sütunda, sonra #sağda" olarak ayrıştırılacaktı . #S slashları kullanarak sütuna dikey olarak birleştirildiğini belirtmem gerekiyor /.
Zgarb

10

TMARL

Şablon Eşleştirme ve Tanıma Dili

Açıklama

Tercümanım 24K karakter alıyor ( kod parçacıkları karakterleri alıyor mu? ), Bu nedenle tam açıklaması burada bulunabilir .

En iyi bölüm: tercüman Javascript'tedir, yani burada deneyebilirsiniz!

Ve sorunlar için:

# 1 - Satranç Tahtalarını Bulmak

$#_#
a
$_#_
bvacvbS5&(avcS5)G0G2P

&aramaları ekler. Sonunda G2, 3. öğeyi bir eşleşme öğesinde, gerçek eşleşmeyi alır. İlk 2 öğe x ve y koordinatlarıdır (1, 0 değil).

# 3 - Basamaklı Dikdörtgen Algılama

$DD
$DD
S1G2P

Bence bu oldukça basit.

# 4 - Kelime Aramada Kelime Bulma

$GO\LF
a
$G
$*O
$**\L
$***F
S6&(aS6)G0G2P

STüm rotasyonlar arayacaktır bile o kadar argümandır. 4'ten büyüktür çünkü bir sonraki aramaya eklenebilir (tek tek eşlemeler eklenemez).

# 5 - Kare Girdileri Algıla

IL-(IG0L)!P

Bunun tamamen yasal olup olmadığından emin değil, çünkü girdi bir dikdörtgen ise yalnızca kareyi doğru belirler. Girişin ILuzunluğunu ilk satırın uzunluğu ile karşılaştırır IG0Lve tersine çevirir.

# 6 - Bir Hayat Oyununda Planör Bul

$## 
$# #
$# 
a
$ ##
$## 
$  #
bS6&(bMS6)&(aS6)&(aMS6)G0G2P

Sonunda, ayna için bir kullanım!

# 12 - Q harfinden kaçının

$[^Qq]
~4*4S1G2P

S1, çünkü sadece 1 eşleşme gerekli.

Daha zor olanlardan bazılarını yapacağım.

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.