2D Labirent Eksi 1D


27

Bu zorluk, 2D labirentlerini 1D labirentlerine dönüştürmekle ilgilidir.

genel bakış

+-+-+-+-+-+-+   +-+-+-+-+-+-+                    graph {
| |   |     |   |A|   |    B|   A         B        A -- D
+ + + + +-+-+   + + + + +-+-+    \        |        C -- D
|   | |     |   |   | |     |     \       |        D -- E
+-+-+ +-+-+ +   +-+-+ +-+-+ +      \      |        E -- F
|           |   |C   D E   F|   C---D-E---F        E -- G
+-+-+-+ +-+ +   +-+-+-+ +-+ +         |   |        B -- F
|         | |   |      G  | |     .---G   |        F -- J
+ +-+-+-+ + +   + +-+-+-+ + +   .'   /    |        G -- H
| |       | |   |H|I      |J|   H I-'     J        G -- I
+-+-+-+-+-+-+   +-+-+-+-+-+-+     (ascii)        } // (graphviz dot)       
   Figure 1       Figure 2                 Figure 3

Bu zorluğun amaçları doğrultusunda, geleneksel bir 2D labirent, aşağıdakilerin hepsinin tuttuğu kafes noktalarından oluşan dikdörtgen bir labirenttir:

  • Kapalı (dış kenar duvarlarla birbirine bağlanmış).
  • Tüm kafes noktaları duvarlara bağlanır
  • Bağlandı (her iki boşluk için X ve Y, aralarında bir yol var)
  • Asikliktir (geri izlemeden X'ten X'e geri hiçbir alan yoktur)

Şekil 1, geleneksel bir 2D labirenti göstermektedir. Bu labirentlerin üç ilgi alanı vardır:

  • Çıkmazlar - sadece bir uygun yolun olduğu yerler
  • Koridorlar - Kullanılabilir iki yolun olduğu yerler
  • Karar noktaları - üç veya dört kullanılabilir yolun olduğu yerler

Böyle labirentlerin her biri için, ölü uçların ve karar noktalarının düğüm olduğu bir grafik oluşturabilir ve her iki düğüm arasında bir koridor boyunca bir yolla bağlanan bir kenar vardır. Şekil 2, etiketli düğümlerle aynı labirenti göstermektedir ve Şekil 3, labirentin grafiğini (ASCII ve Graphviz nokta notasyonunda) göstermektedir.

1D labirentine

1D labirentler, çiftler halinde gelen ve bir harf (her iki durumda da) kullanılarak tanımlanmış çözgü noktalarını içerir. Şekil 4, bir 1D labirent örneğini göstermektedir. Bu, aksi halde Şekil 5'de gösterildiği gibi 1 yüksekliğinde bir 2D labirent ile aynıdır. Özellikle Şekil 5'te, +soldan sağa dönüşümlü olarak işaretlenen kafes nokta konumlarını not edin ; 1D labirentte, en soldaki duvarla başlayan diğer her karakter de bir kafes noktasıdır.

                                 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  D|  D E|G E F|  F  |  G  |    |  D|  D E|G E F|  F  |  G  |
                                 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            Figure 4                         Figure 5

Bu labirentte gezinmek için kurallar aşağıdaki gibidir. Her hareket ileri ( >) veya geri ( <) olarak gösterilebilir. Burada ileri ve geri varsayılan olarak sezgisel mekansal farkındalığımızla aynı anlama gelir; ileri, hemen sağa, hemen sola geri gider.

Çözgü noktaları, asimetrik olarak komşularla bağlantıyı değiştiren yerleri temsil eder. Bir komşundan bir çözgü noktasına geliyorsanız, iki çözgü noktasının konumu değiştirilir; Eğer bir warp noktasından komşuya geliyorsanız, bunlar değiştirilmez. Örneğin, Şekil 6'da 1'den geriye doğru hareket etmek sizi 2'ye getirir (1, G'nin komşusu olduğundan ve biz komşumuzdan hareket ediyoruz, 2 ve @ noktaları değiştirilir). 2'den (G noktası) ileri doğru hareket etmek sizi 3'e getirir (burada, bir warp noktasından başlıyoruz, bu yüzden takas yok). Aynı şekilde, 3'ten geriye doğru hareket etmek sizi @ konumuna getirir.

        54 2367    89^   @1
|  D|  D E|G E F|  F  |  G  |
                     Y     X
          Figure 6

Şekil 6 aynı zamanda, hareket sırasını kullanarak X'den Y'ye bir örnek navigasyon göstermektedir <<>><>>>>>. Bu hamleler, sizi 123456789^sırasıyla bu sırayla etiketlenmiş noktalara getirir . Bir sonraki bölümdeki kod pasajını kullanarak kendinizi keşfetmekten çekinmeyin.

2D'yi 1D'ye dönüştürme

Bir 1D labirent verildiğinde, her düğümün bir çıkmaz veya bir çözgü noktası çifti olduğu ve bir koridor boyunca bağlanmış herhangi iki düğüm arasında kenarların bulunduğu bir grafik oluşturabilir. Bu grafik 1D ve 2D labirentlerini karşılaştırmamıza izin veriyor.

Örneğin, Şekil 4'teki 1D labirenti, Şekil 1'deki aynı labirenttir. Bir grafik oluşturmak için bu etiketleri kullanarak, Şekil 7'nin grafiği sadece Şekil 3'tür. Şekil 8, bu grafiğin oluşturulmasının bir kopyasını göstermektedir.

|  D|  D E|G E F|  F  |  G  |
 A   C           B   J H   I 
          Figure 7

|  D|  D E|G E F|  F  |  G  |
+ + + + + + + + + + + + + + + <- lattice points
|A  |C    |     |B   J|H   I| <- dead ends
|A D|C D E|G E F|B F J|H G I| <- all nodes (dead ends+warp points); i.e.:
                                 "where each end is either a dead end
                                  or a warp point pair"; note that each
                                  pair of warp points is the same node.
|A-D|C-D-E|G-E-F|B-F-J|H-G-I| <- corridors; note each is a connection, since
  1   2 3   4 5   6 7   8 9      "edges exist between any two nodes
                                  connected along a corridor"
   graph {                 graph {                 
     A -- D  // 1 <---->     A -- D                
     C -- D  // 2 <---->     C -- D                
     D -- E  // 3 <---->     D -- E                
     G -- E  // 4 <---->     E -- G                
     E -- F  // 5 <---->     E -- F                
     B -- F  // 6 <---->     B -- F                
     F -- J  // 7 <---->     F -- J                
     H -- G  // 8 <---->     G -- H                
     G -- I  // 9 <---->     G -- I                
   }                ^      }
    Built from      |      From Figure 3
     1D maze         `-> isomorphic mappings
                Figure 8

(Her grafiğin etiketlerinin ve düzeninin yapay olarak çizim amacıyla hizalanması için seçildiğini unutmayın; genel olarak bunun bir grafik izomorfizma problemi olduğunu söyleyin ).

1 sn labirentinin mekaniğini ve 1D labirenti, denklik grafiğini ve 2B labirent arasındaki bağlantıyı görselleştirmek için aşağıdaki kod parçası sağlanmıştır.

Bu snippet'te 1D labirentinde gezinirken, dokunduğunuz son iki düğüm vurgulanır. Aynı düğümler denklik grafiğinde ve 2B labirentte aynı şekilde vurgulanır.


Genel olarak, herhangi bir geleneksel 2D labirent için bu türden eşdeğer bir 1D labirent oluşturulabilir. Biraz daha karmaşık bir örnek, Şekil 9:

+-+-+-+-+-+-+   +-+-+-+-+-+-+                   graph {
| |   |   | |   |A|   |   |B|   A         B       A -- D
+ + + + + + +   + + + + + + +    \       /        C -- D
|   | | |   |   |   | | |   |     \     /         D -- E
+-+-+ + +-+-+   +-+-+ + +-+-+      \   /          B -- E
|           |   |C   D E    |   C---D-E           E -- F
+-+-+-+ +-+ +   +-+-+-+ +-+ +         |\          E -- I
|         | |   |      F  | |     .---F \         F -- G
+ +-+-+-+ + +   + +-+-+-+ + +   .'   /   \        G -- H
| |       | |   |G|H      |I|   G H-'     I       H -- I
+-+-+-+-+-+-+   +-+-+-+-+-+-+     (ascii)       } // (graphviz dot)
   Figure 9       Figure 10             Figure 11

|  D|  D E  |F E  |  F  |       |  D|  D E  |F E  |  F  |
                                 A   C     I     B G   H
      Figure 12                       Figure 13

Bu labirent dört yollu bir düğüme sahiptir (Şekil 10'da E). Şekil 11, grafiğini göstermektedir. Şekil 12, eşdeğer bir 1D labirenttir; ve Şekil 13, Şekil 11 ile karşılaştırılmak üzere çıkmazlar için etiketlere sahip aynı labirenti göstermektedir.

Meydan okuma

Giriş olarak 2D Labirent verildiğinde, 2D labirenti çözgü noktalarıyla 1D labirentine dönüştüren bir fonksiyon veya program yazın. Çözgü noktaları, her durumda 52 harften herhangi birini kullanabilir.

Girdi garantileri (bunlardan herhangi biri girişte karşılanmazsa, başa çıkmak zorunda kalmazsınız):

  • Giriş labirentine bağlı (yani, herhangi bir noktadan diğerine her zaman gidebilirsiniz).
  • Giriş labirenti kapalı.
  • Giriş labirent dikdörtgendir.
  • Tüm kafes noktaları kullanır +.
  • Aynı sıradaki kafes noktaları arasındaki tüm duvarlar |
  • Kafes arasındaki tüm duvarlar aynı kolon kullanımında işaret eder -.
  • Tüm alanlar bir yolun parçasıdır (ve hepsi labirentin içindedir).
  • Yolların hepsi boşluktur (bu her zaman geleneksel olacak, çözgü olmayan)
  • Yollar tam olarak bir boşluk genişliğindedir.
  • Labirent, kafes üzerindeki bağlantı noktaları ile oluşturulmuştur.
  • Labirentin grafiğinde toplam 52'den fazla düğüm yoktur (yani çıkmazlar artı karar noktaları).

Çıkış biçimi:

  1. Çıktınız bir 1D labirent gösteren tek bir satır olmalıdır .
  2. Çıktınızın başında / sonunda boşluk bulunmamalıdır; Bunun dışında takip eden bir satırsonu iyi.
  3. İlk karakter ve daha sonra diğer her karakter kafes noktalarıdır.
  4. Tüm duvarlar kafes noktalarında olmalıdır; ve aralarındaki tüm çözgü noktaları.
  5. 1D labirentinizin grafiği 2B labirentin grafiğine eşdeğer olmalıdır.
  6. 1D labirentleriniz kompakt olmalıdır; kafes olmayan tüm noktalar çıkmaz (duvarlara bitişik) veya çözgü noktaları olmalıdır.
  7. Sadece harfler çıktınıza çözgü noktaları olmalıdır. Her çözgü noktası çizgide tam olarak iki kez oluşur.

Örnek:

|  D|  D E|G E F|  F  |  G  | <- (1,2) The single line output
+ + + + + + + + + + + + + + + <- lattice point spacing... (3) 
                                 (4,6) lattice points are all walls or spaces
                                 (5) See Figure 8
                                 (7) D, E, F, G appear twice; no other labels

Bu kod golfü. Kazanan en az bayt ile doğru kaçamak olmayan teslim olduğunu.

Test yapmak

Önemsiz labirent için çok sayıda doğru çıktı olduğundan, bu zorluğun test sonuçları yoktur.

Bununla birlikte, C ++ 'ta bir denetleyici oluşturdum (bu denetleyici, her iki çözümü de bir grafik kurallaştırma yoluyla çizer ).

Ayrıca, doğru biçimlendirmeyi göstermeye yardımcı olacak birkaç örnek:

örnek 1

+-+-+-+-+-+-+
| |   |     |
+ + + + +-+-+
|   | |     |
+-+-+ +-+-+ +
|           |
+-+-+-+ +-+ +
|         | |
+ +-+-+-+ + +
| |       | |
+-+-+-+-+-+-+
->
|  D|  D E|G E F|  F  |  G  |

Örnek 2

+-+-+-+-+-+-+
| |   |   | |
+ + + + + + +
|   | | |   |
+-+-+ + +-+-+
|           |
+-+-+-+ +-+ +
|         | |
+ +-+-+-+ + +
| |       | |
+-+-+-+-+-+-+
->
|  D|  D E  |F E  |  F  |

Burada daha fazla örnek bulunabilir .


1
1D labirentlerinin açıklamasının çok net olduğunu sanmıyorum ... Belki daha küçük / basit bir örnek eklemek yardımcı olacaktır.
mbomb007

Bu oldukça havalı. Evet bu yardımcı olur.
mbomb007

İnteraktif betiğiniz yardımcı olsa da, zor bir problem. Ben de atladım. Bu konuda anladığım kadarıyla hala en iyisi.
mbomb007

1D labirent açıklaması kabataslak. Bir 1D labirentindeki dikey çubuk karakterlerinin geçemediğiniz duvarlar olduğunu anlamak için şekil 7'ye kadar okumak zorunda kaldım.
edc65

1
1d labirenti olan örnek 1, her bir harf çiftinin bir merdiven olduğu 2d labirentine yığılmış: gist.github.com/sparr/36d6355cc4c785a27b12157666169082
Sparr

Yanıtlar:


3

İtonlu Python 2 , 492 369 bayt

import igraph,string
def f(s):
 C=s.find('\n')/2;N=' ';g=igraph.Graph(0,[(i,i+j)for i in range(len(s)/(4*C+4)*C)for j in(1,C)if s[(i/C*2+1)*(2*C+2)+i%C*2+2*j+j/C*3]==N]);V=g.vs;g.d=g.degree;O='';V(_d=1)[N]=N;V(_d_gt=2)[N]=list(string.ascii_letters)
 while g.es:
    v=V(_d=1)[0];O+='|'+v[N]
    while g.d(v):w=v.neighbors()[0];g-=(v,w);v=w;O+=N+v[N]if v[N]else''
 print O+'|'

(Beşinci ve altıncı satırların her biri bir sekmeyle başlar, StackExchange'in gösterdiği gibi dört boşlukla değil.)

  • Bazı aritmetiklerin yeniden düzenlenmesi için altı bayt kaydedildi
  • Zip yerine bir dilim kullanarak yedi bayt kaydedildi
  • Kullanılarak Kaydedilen üç bayt g+=tuple(v.neighbors())yerineg.add_edge(*v.neighbors())
  • Kullanılarak Kaydedilen yedi bayt g-=g.es[g.incident(v)]yerineg.delete_edges(g.incident(v))
  • Onbir bayt takma adı kaydedildi g.d=g.degree
  • 52 bayttan (!) Tasarruf sağladı, tüm koridorları 2. derece köşeleri komşuları arasında bir kenar ile değiştirerek kesip attıran bir halka ortadan kalktı. Bunun yerine, çıkış döngüsü sadece bu köşeleri görmezden gelir.
  • Adları atarken, igraph'ın sağlanan yinelemenin çok uzun olup olmadığını umursamadığını fark eden 13 bayt kaydedildi
  • RSatır sayısı için bir değişken içermeyen dört bayt kaydedildi , hesaplamayı tek kullanım noktasına getirdi
  • İkinci düzey girintiyi boşluklar yerine sekmelere çevirerek iki bayt kaydedildi
  • Kaydedilen altı bayt yeniden düzenleyerek 2*(i%C)için i%C*2, 2*(i/C)için i/C*2, ve (C-1)*jiçinj*C-j
  • Adlandırılmış dört bayt adlandırma N='n'
  • Bir karakterin, yalnızca geçerli karakterlerin göründüğü varsayımıyla <'-'değil ==' ', yerine boşluk olup olmadığını belirleyerek bir bayt kaydedildi .
  • Sonra köşe niteliğini adlandırabilirsiniz gerçekleştirilen ' 'yerine 'n've yeniden kullanımını Nkaynağında iki değişmez alanlar için, ve ==Nyerine <'-'beş daha bayt tasarruf

Biraz ungolfed versiyonu izler. Temel fikir, ilk önce tüm labirent köşelerinde (sıfır dizine eklendiğinde tek satır ve sütun bulunan noktalar) bir grafik oluşturmaktır. Aşağıdaki karakter boşluksa, aynı köşede bir tepe noktasından diğerine bir kenar vardır. ve değil |. Aşağıdaki satırdaki karşılık gelen karakter bir boşluk ise, tepe noktasının hemen altında bir kenar vardır -.

Bu grafiği oluşturduktan sonra, herhangi bir yaprağı seçeriz ve art arda bitişik köşeleri takip eder, koridor değilse isimlerini yazarız ve sıkışana kadar kullanılan kenarları sileriz. Sonra başka bir yaprak alırız ve tüm kenarlar kaybolana kadar devam ederiz.

import string
import igraph
def f(s):
  C = s.find('\n')/2 # number of maze vertices in each row
  R = len(s)/(4*C+4) # number of rows
  def strpos(r, c):
    """Index of the vertex at row r, col c in the newline-delimited string s"""
    return (2*r+1)*(2*C+2) + 2*c + 1
  def vertpos(i):
    """Index of the i-th vertex in s"""
    return strpos(i/C, i%C)
  g = igraph.Graph(edges=[(i, i+(C if j else 1))
                          for i in range(R*C)
                          for j in (0, 1)
                          if s[vertpos(i)+(2*C+2 if j else 1)] == ' '])
  V = g.vs # the graph's vertex sequence
  O = ''
  V(_degree=1)['n'] = ' ' # All leaves are named space
  W = V(_degree_gt=2) # All warp points...
  W['n'] = list(string.ascii_letters[:len(W)]) # ...are named successive letters
  while g.es: # while any edges remain...
    v = V(_degree=1)[0] # find a leaf
    O += '|'+v['n'] # start a new 'block'
    while v.degree():
      w = v.neighbors()[0] # pick a neighbor
      g -= (v, w) # delete that edge
      v = w
      if v['n']: # If it's a dead end or warp point...
        O += ' '+v['n'] # ...write out the new neighbor
  print O+'|'

Beş örnek labirentine ait sonuçları görebilirsiniz . (Ne yazık ki, igraphÇevrimiçi Deneyin'de kullanılamıyor; bu sonuçlar SageMathCloud'dan dışa aktarıldı .)


4

Haskell - 481 405 387 bayt

import Data.List
s&t=elemIndices s t
l=last
c!(x:y:z)=l$(y:c)!(x:z):do{[x:p,q]<-mapM([id,reverse]<*>)[[x],[y]];x&[l q];[[]!((q++p):c++z)]}
c![x]=x:[]!c
c!z=z
main=interact(\m->let{g=' '&m;
u=(\\[k|k<-g,length(v>>=(k&))==2])<$>[]!v;
v=[[x,y]|x<-g,y<-g,elem(y-x-1)[0,head$'\n'&m]];
}in '|':(u>>=(++"|").init.(>>=(:" ").toEnum.((+)<*>(+65).(*32).(`div`26)).l.(-1:).(&(nub$u>>=init.tail)))))

Bu, labirentte bulunan, dizedeki dizine göre numaralandırılmış boşlukların bir listesini oluşturur ve bitişik boşlukların tüm çiftlerini bulmak için kullanır. Daha sonra çiftleri, ilk / son elemanları eşleştirmeye dayanarak daha uzun nokta dizileri halinde birleştirir ve koridorları kaldırır, böylece her bir sekans 1D labirentinde bir oda olur. Ardından diziler, en az bir odanın (çözgü noktaları) içindeki noktaların karşılık gelen harflerle ve geri kalan kısımların boşluklarla değiştirilmesiyle bir dizgeye dönüştürülür.

2D labirent, STDIN'den okunur ve 1D labirent, STDOUT'a yazdırılır.

Düzenleme: 62 tarafından Azaltılmış değiştirerek başka 14 şeyler bir grup yeniden düzenleyerek ve algoritmasını biraz değiştirerek ve bayt chrile toEnumLaikoni tarafından önerildiği gibi.

Düzenleme 2: Mantıksallaştırmayı basitleştirerek 13 bayt daha kaydedin (!), liste deseni şekerini kullanarak 3'ü ve >>=uyumlulaştırmak için 2'yi kullanın u.


Desen korumalarından önce yeni hatlara ve boşluklara ihtiyacınız olmadığını düşünüyorum, örneğin o(x:p)q|x==last q=[q++p]|1>0=[], çalışması da gerekir.
Laikoni

Ayrıca toEnumyerine çalışmalı chr, sonra import Data.Charbırakılabilir.
Laikoni

Ve son olarak, zorluk bir program veya işlev istediğinde, main=interact(\m->...)bununla hemen değiştirebilirsiniz f m=.... Bu sizin için bir anlam ifade ediyorsa, python cevabını yenmek için yeterli olmalıdır.
Laikoni
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.