Yolları bulun!


10

Bir program veya işlev yazmalısınız.

Giriş bir sayı haritasıdır. Haritayı yeni satır karakterlerine sahip bir dize ( \n) veya 2B dize dizisi olarak almayı seçebilirsiniz .

Tüm haritalar 5 karakterden 5 karakterdir ve karakterler her zaman 0'dan büyük basamaklar veya boşluklardır.

İşte bir harita örneği:

12 45
11233
  233
    1
2 899

Göreviniz, bağlı bileşenleri haritada bulmaktır. Geçerli bir bileşen, en az üç yatay ve / veya dikey ( çapraz olarak değil ) bağlı aynı basamaktan ( boşluk değil ) oluşan bir dizidir . Daha sonra, geçerli bağlı bileşenlerin karakterlerini xs ile değiştirmeniz ve bu sonucu yazdırmanız veya döndürmeniz gerekir.

Dolayısıyla, yukarıdaki örneğin çıktısı şöyle olacaktır:

x2 45
xx2xx
  2xx
    1
2 899

İşte başka bir test örneği (Martin Ender sayesinde):

Input:
2   3
    4
 1  5
111 6
11  7

Output:
2   3
    4
 x  5
xxx 6
xx  7

Bu kod golf bayt kazanır çok kısa kod kazanır!



Yerleşik yapılara izin veriliyor mu?
Ioannes

@Jannes, evet.
Daniel

Yanıtlar:


1

JavaScript (ES6), 171 161 139 137 136 133 132 bayt

f=(a,i=0)=>(F=i=>" "<c&&a[i]===c&&(a[i]=n,1+F(i-1)+F(i+1)+F(i-6)+F(i+6)),n=1,c=a[i],n=F(i)>2?"x":c,c=1,F(i),i>28?a:f(a,++i+(i%6>4)))
<!-- this HTML included just for testing --><textarea rows=5 cols=6 oninput="document.querySelector`pre`.innerHTML=this.value.length==29?f([...this.value]).join``:'invalid input'">12 45&#10;11233&#10;  233&#10;    1&#10;2 899</textarea><br/><pre></pre>

Bu benim Python cevabımın bir çevirisidir. Karakter dizileri olarak G / Ç.

Çok kötü yapmanın etkili bir yolu yok sum...


5

Python 3, 238 237 200 199 192 181 bayt

def f(a,i=0):F=lambda i,n,c:29>i>=0!=" "!=a[i]==c!=n and(a.__setitem__(i,n)or-~sum(F(i+j,n,c)for j in[-1,1,-6,6]));j=i+i//5;F(j,[a[j],"x"][2<F(j,1,a[j])],1);i>23or f(a,i+1);return a

f(a)Girdiyi bir karakter dizisi olarak alan ve değiştirilen aynı diziyi döndüren bir işlevi tanımlar . ( Karakter dizileri varsayılan olarak dize olarak kabul edilebilir. )

Açıklama ile başa çıkıldı

Değiştirilen kod yinelemelidir, ancak aynı şekilde çalışır.

# The main function; fills all continuous nonempty areas of size >= 3 in array
# with x's. Both modifies and returns array.
def findpaths(array):
    # Fills a continuous area of curr_char in array with new_char, starting
    # from index. Returns the number of cells affected.
    def floodfill(index, new_char, curr_char):
        if (0 <= index < 29                   # Check that the position is in bounds
                and (index + 1) % 6 != 0      # Don't fill newlines
                and array[index] != " "       # Don't fill empty cells
                and array[index] == curr_char # Don't fill over other characters
                and curr_char != new_char):   # Don't fill already filled-in cells
            array[index] = new_char # Fill current position
            return (1 # Add neighboring cells' results, plus 1 for this cell
                    + floodfill(index + 1, new_char, curr_char)  # Next char
                    + floodfill(index - 1, new_char, curr_char)  # Previous char
                    + floodfill(index + 6, new_char, curr_char)  # Next line
                    + floodfill(index - 6, new_char, curr_char)) # Previous line
        return 0 # Nothing was filled. The golfed solution returns False here,
                 # but that's coerced to 0 when adding.

    for i in range(25): # Loop through the 25 cells
        i += i // 5 # Accommodate for newlines in input
        curr_char = array[i] # Get the cell's contents
        # Fill the area from the cell with dummies
        area_size = floodfill(i, 1, curr_char)
        # Convert dummies to "x" if area was large enough, back to original otherwise
        fill_char = "x" if 2 < area_size else curr_char
        floodfill(i, fill_char, 1)
    return array

Matematiksel çözümü yenmek için 2 bayt kapalı ...
FlipTack

1
@FlipTack Evet. Bugün olduğunu sanmıyorum, ama bunu JS'ye çeviriyorum ve umut verici görünüyor.
PurkkaKoodari

3

Yakut, 304 bayt

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end
def b2(s,i,c)
  if(0...s.size)===i&&s[i]==c&&!@v[i]
    @v[i]=s[i]='x'
    [1,-1,6,-6].each{|j|b2(s,i+j,c)}
  end
  s
end
def f(s)
  z = s.dup
  ps = ->(i){b(z.dup,i).scan('x').size}
  (0...s.size).each{|i|b(s, i)if ![' ',"\n"].include?(s[i])&&ps.call(i)>2}
  s
end

örnek kullanım:

puts f(File.read("map.txt"))

kod, yol uzunluğunu hesaplamak için 'blot' yöntemini yeniden kullanır.

değişkenler / yöntem:

  • f (s): harita dizesini dönüştürme işlevi, 'x' ile yeni harita döndürür
  • ps (i): harita indeksi i'den yol boyutu (burada x = i% 6, y = i / 6)
  • s: giriş dizesi, "\ n" ile ayrılmış harita çizgileri
  • z: giriş dizesinin kopyası
  • b (s, i): 'blot' işlevi: 'x' haritasını harita dizininden i yollara yazar
  • @v: 'ziyaret edilen' dizi

Daha ayrıntılı bir açıklama yapmaya çalışın:

haritadaki herhangi bir noktadan yolun uzunluğunu bulmak için kullandığımız giriş dizesinin bir kopyasını oluşturun.

z = s.dup

harita indeksini i argüman olarak alan bir 'ps' (yol uzunluğu) anonim fonksiyonu (lambda) tanımlayın. o noktadan itibaren yolun uzunluğunu döndürür. bunu, orijinal haritanın bir kopyasına x'ler eklemek için 'b' (leke) yöntemini çağırarak ve ardından döndürülen dizedeki x sayısını sayarak yapar.

  ps = ->(i){b(z.dup,i).scan('x').size}

aşağıdaki bölüm haritadaki her karakter için tekrarlanır (dizin i, karakter s [i]). i konumundan yol uzunluğu 2'den büyükse ve bir boşluk veya satırsonu karakteri değilse, harita konumu i'de 'b' (leke) işlevini çağırır.

  (0...s.size).each { |i|
     b(s, i) if ![' ',"\n"].include?(s[i]) && ps.call(i) > 2
  }

b (blot) işlevi, harita dizesini ve bir dizini bağımsız değişken olarak alır. @v'yi (ziyaret edilen dizi) başlatır ve b2 yardımcı işlevini çağırır.

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end

b2 işlevi harita dizesini, bir harita konumunu (i) ve geçerli yoldaki (c) bir karakteri alır. basamakların bağlı bölümlerini 'x' karakteri ile değiştirmek için kendini tekrar tekrar çağırır. giriş dizesini döndürür (bu, ps işlevinin dönüş değerinde scan () öğesini çağırabilmesidir).

if if ifadesi, verilen harita konumunun (i) dizenin sınırları (0 ... s.size) içinde olduğunu ve s [i] 'deki karakterin başlangıç ​​karakteri ile aynı olup olmadığını kontrol eder. Ayrıca @v [i], sonsuz yinelemeyi önlemek için kontrol edilir.

if(0...s.size) === i && s[i] == c && !@v[i]

bu, indeks (i) 'deki karakteri' x 'karakteri ile değiştiren bittir. ayrıca bu dizini ziyaret edilmiş olarak işaretler.

@v[i] = s[i] = 'x'

b2 kendini sürekli olarak yolu aramak için çağırır. i + 1 sağdaki bir karakter, i-1 soldaki bir karakter, i + 6 bir satır aşağı (5 basamak + 1 yeni satır = 6 karakter), i-6 bir satır yukarı.

[1,-1,6,-6].each { |j| b2(s, i+j, c) }

1

C (ANSI), 243 233 179 188 bayt

golfed:

#define O o[1][l]
x,n,l,L;r(o,l)char**o;{if(!(l>L|l<0|O<47|O!=x))n++,O++,r(o,l-1),r(o,l+6),r(o,l-6),r(o,l+1),n>2?O='x':O--;}main(g,o)char**o;{for(;(L=30)>l;l++)n=0,x=O,r(o,l);puts(o[1]);}

Ek Açıklamalarla:

#define O o[1][l]
x,n,l,L;      /*-------------------------- Globals*/
r(o,l)char**o;{ /*------------------------ Recursive Function*/
    if(!(l>L|l<0|O<47|O!=x)) /*----------- if this cell is valid(in
                                              range, is a number, is the 
                                              same as the parent number*/
    n++,     /*--------------------------- Increment count*/
    O++,     /*--------------------------- Increment character to mark*/
    r(o,l-1),  /*------------------------- Recurse left*/
    r(o,l+6),  /*------------------------- Recurse down*/
    r(o,l-6),  /*------------------------- Recurse down*/
    r(o,l+1),  /*------------------------- Recurse right*/
    n>2?O='x':O--;  /*---------------------If greater than 3, replace with x, else decrement character*/ 
}          /*----------------------------- Return*/

main(g,o)char**o;{ /*--------------------- Main*/
    for(;l<(L=30);l++){ /*---------------- For entire string and set L*/
        n=0;
        x=O;        /*-------------------- set counter to 0*/
        r(o,l); /*------------------------ Recurse*/
    } /*---------------------------------- End While*/
    puts(o[1]); /*------------------------ Print*/

}

Giriş:

Dizenin başında ve sonunda yeni satır bekliyor.

Örnek Giriş:

./findPaths "
12 45
11233
  233
    1
2 899
"

Örnek Çıktı:

x2 45
xx2xx
  2xx
    1
2 899

Güncelleme

Izgarayı sabitlemek yaklaşık 60 bayt tıraş olmamı sağladı.


Bunu düzeltilmiş bir harita boyutuna değiştirirsem 22 karakter gibi kaydedebilirim - değiştirmek istediğim başka bir şey
bulursam

1

Mathematica, 180 bayt

(f=Flatten@#;p=Partition)[If[Tr[1^VertexComponent[r~Graph~Cases[##&@@p[#,2,1]&/@Join[g=p[r,5],g],{a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ":>a<->b],#]]<3,f[[#]],"x"]&/@(r=Range@25),5]&

Açıklama:

(f=Flatten@#;p=Partition)[
  If[
    Tr[1^VertexComponent[
        r~Graph~Cases[
          ##&@@p[#,2,1]&/@Join[g=p[r,5],g],
          {a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ":>a<->b
        ],
        #
      ]]<3,
    f[[#]],
    "x"
  ]&/@(r=Range@25),
  5
]&

Bir 5x5diziyi kabul eden saf işlev . postfix transpoze operatörünü temsil eden 3 baytlık özel kullanım karakterdirU+F3C7\[Transpose] .

(f=Flatten@#;p=Partition): Giriş listesini düzleştirir ve kaydeder f. Ayarlar p = Partitionve döndürür.

g=p[r,5]: Dizi {{1,2,3,4,5}, ..., {21,22,23,24,25}}(bunun nedeni rayarlandığı için Range@25).

Join[g=p[r,5],g]: öğesinin satır ve sütunlarının listesi g.

p[#,2,1]&: Listeyi çakışma ile #uzunluk alt listelerine ayıran saf işlev ; yani, içindeki bitişik çiftlerin listesi .21#

##&@@p[#,2,1]&: Yukarıdaki gibi aynı a döndürür Sequence.

##&@@p[#,2,1]&/@Join[g=p[r,5],g]: İçindeki gbitişik girişlerin bir listesini almak için satır ve sütunlarının önceki işlevini eşler g. Bağırsak, bunu yapmanın daha kısa bir yolu olduğunu söylüyor.

r~Graph~Cases[...]: 1, ..., 25Kenarları tamsayı olan ve kenarları g, giriş dizisinde aynı karşılık gelen girişlere sahip bitişik girişler arasındaki kenarlar olan grafik (" " )

{a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ": Eşleşen desen {a,b} Öyle f[[a]] == f[[b]](giriş dizisinde aynı değer) ve eşit olmayan" " . Bayt A = f[[a]]kaydetmek için ayarlayın 1.

...:>a<->b: Her eşleşmeyi a'dan b'ye yönlendirilmemiş bir kenarla değiştirin.

VertexComponent: Birinci bağımsız değişkendeki (grafik) ikinci bağımsız değişkenin (bir tepe noktası) bağlı bileşenini döndürür.

Tr[1^VertexComponent[...]]: Bağlı bileşenin boyutu. kaydeder1 baytLength@VertexComponent[...] .

If[Tr[...]<3,f[[#]],"x"]&: Bir girişi alır Saf fonksiyon #içindeg . Bağlı bileşeninin boyutu küçükse 3, girişi girişteki ilgili girişle değiştirin. Aksi takdirde, ile değiştirin "x".

(f=Flatten@#;p=Partition)[...,5]: Ve son olarak sonucu bir 5x5dizi olarak yeniden şekillendirin .


0

Clojure, 188 bayt

Bu oldukça ezici: D

#(apply str(map-indexed(fn[i v](if((set(flatten(for[m(range 30)](let[n(for[p[-1 -6 1 6]:when(=(get %(+ m p)0)((set"123456789")(% m)))](+ m p))](if(< 1(count n))(conj n m)[])))))i)\x v))%))

Buna denir (1D karakter vektörü alır):

(def f #(apply str(...))

(print (str "\n" (f (vec (str "12 45\n"
                              "11233\n"
                              "  233\n"
                              "    1\n"
                              "2 899\n")))))

(print (str "\n" (f (vec (str "2   3\n"
                              "    4\n"
                              " 1  5\n"
                              "111 6\n"
                              "11  7\n")))))

Uungolf için çok tembeldir, ancak temel olarak for[m(range 30)]her bir dizini ziyaret eder ve her dizin için iç let[n(for[p[-1 -6 1 6]...(+ m p))], orta konumla aynı değere (1 - 9) sahip konumları listeleyen 0 ila 4 öğenin bir listesini yapar. Orta parçayla 1'den fazla komşu eşleşirse, tüm bunların bir küme oluşturduğu anlamına gelir, bu nedenle bu konumlar kullanılan sete eklenir (if((set(flatten(...)))i). Setten indeks ibulunursa, o \xzaman yayılır ve orijinal değer başka türlü olur. Bu :when( ... )oldukça ilginç ...

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.