Matriste Yılan Bulma


32

Meydan okuma

İkili bir matris ve bir ikili dize verildiğinde, bu ikili dizginin matristeki herhangi bir noktada başlayıp, ikili dizgiyi oluşturmak için sonraki herhangi bir noktada herhangi bir yönde hareket edip edemeyeceğini belirleyin. Diğer bir deyişle, mat, matrisin içinde katlanmış halde bulunabilir mi?

Tel yalnızca 90 derece veya 180 derece katlanabilir (kenar bağlantıları; Manhattan Mesafe 1) ve herhangi bir noktada kendiliğinden üst üste gelemez.

Örnek

Aşağıdaki örneği ele alalım:

Matrix:

010101
111011
011010
011011

Snake: 0111111100101

Bu bir truthy test durumudur. Yılanın aşağıdaki konumda katlandığını görebiliriz:

0-1 0 1 0 1
  |
1 1 1-0 1 1
  | | |   |
0 1 1 0-1-0
  | |
0 1-1 0 1 1

kurallar

  • Standart Loopholes Uygula
  • Dize uzunluğunu ve matrisin genişliğini ve yüksekliğini isterseniz girdi olarak alabilirsiniz.
  • İkili matrisi ve ikili diziyi çok satırlı bir dize / dizi dizisi / newline birleştirilmiş dize / başka bir birleştirilmiş dize ve bir dize olarak alabilirsiniz.
  • Boyutları birkaç argüman yerine düz bir dizi olarak alabilirsiniz.
  • Programınız 5 x 5'lik bir matris için, bir dakikanın altında 10 metreye kadar olan herhangi bir dizeyle bitmelidir.

Sınırlamalar

  • Matris mutlaka kare değildir
  • Dize boş olmayacak
  • Dize uzunluğu-1 olabilir
  • Dize mevcut olandan daha fazla kare içermez (yani, len(string) <= width(matrix) * height(matrix)

Test Kılıfları

Truthy

01010
10101
01010
10101
01010

0101010101010101010101010



01110
01100
10010
10110
01101

011111000110100



0

0



10
01

1010



100
010
001

100010001

Falsy

00000
00000
00000
00000
00000

1



10101
01010
10101
01010
10101

11



100
010
001

111



10001
01010
00100
01010
10001

1000100010001000101010100


4
Veya: İkili Boggle! Ayrıca birkaç test davası daha ekleyebilir misiniz?
Jonah

1
Bu bağlamda düz, keskin ve yuvarlak ne anlama gelir? Kare, genişlik ve yüksekliğin eşit olamayacağı veya dizinin pürüzlü olabileceği anlamına gelmiyor mu?
Tahg

Dünyada yuvarlak bir dizi nedir
Conor O'Brien

Yanıtlar:


13

Python 2 , 275 271 264 249 bayt

  • Bir dilimleme işlemi ( ) -1ile değiştirerek Hve kaldırarak dört bayt kurtardı [:].
  • Halvard Hummel sayesinde yedi bayt kurtarıldı ; başka bir dilimleme işleminin ( [:]) kaldırılması , ziyaret edilen bir girişe değer v not in "01"( S=S[1:];M[y][x]=H;-> S=M[y][x]=S[1:];) vermek için çoklu hedef atamasının kullanılması ve / / eğer varsa üçlüden basit bir mantıksal ya da ( any(...)if S else 1-> not S or any(...)) geçmek .
  • Eğer biraz sizin tanımı genişletmek durumunda truthy ve Falsey , bu izin verebilir 257 bayt uzunluğunda bir çözüm . ZeroDivisionErrorYılan bulunduğunda bir istisna ( ) oluşturur ve bulunacak bir []yılan olmadığında ( iki ayrı davranış olan boş bir liste ( ) döndürür .
  • User202729 sayesinde on dört bayt kaydedildi ; iki dizi derin kopya golf
  • Bir bayt kaydedildi; golfed not S oriçin S<[1]or~ S==[]or.
lambda M,S,w,h:any(H(eval(`M`),S,w,h,x,y)for y in range(h)for x in range(w)if S[0]==M[y][x])
def H(M,S,w,h,x,y):S=M[y][x]=S[1:];return S<[1]or any(H(eval(`M`),S,w,h,x+X,y+Y)for X,Y in[(~0,0),(1,0),(0,~0),(0,1)]if~0<x+X<w>0<=y+Y<h!=S[0]==M[y+Y][x+X])

Çevrimiçi deneyin!

açıklama

Matrisde iki boyutlu bir dizi listesi (ya "0"da "1") olarak alan Lambda işlevi, bir boyutlu bir liste olarak yılan ve matris boyutları iki tamsayı olarak alınmıştır.
Lambda işlevi, yılanın ilk öğesiyle eşleşen girdiler için matrisi arar. Bulunan her eşleşme için, Hmatrisin derin bir kopyasını, yılanın kopyasını, matris boyutlarını ve eşleşmenin konumunu gösterir.

Ne zaman Hdenir, bu kaldırır S'ilk giriş ve setleri daha başka bir şey verilen konumun matris girişi "0", "1". Eğer Suzunluk sıfırsa, döndürür True; özyinelemeli olarak çağırdığı gibi, yılan matris içinde bir yerde bulundu.
Eğer Suzunluk sıfır değilse, dört kardinal doğrultuda dolaşır, bu pozisyonun matriste olup olmadığını test eder, matrisi karşılaştırır 'elemanını o pozisyondaki ilk eleman ile karşılaştırır Sve - eşleşirse - özyinelemeli olarak çağırır.
H's dönüş değerleri yığın çerçeveleri kadar huni, her zaman en az bir fonksiyonun olası bir yılan bulup bulmadığını kontrol eder.

Biçimli Çıktı

Yılan sürünenlerin (eğer varsa) yolunun çıktısını almak için programımı artırdım. Soru ile aynı ASCII çıktı tasarımını kullanır. TIO bağlantısı .



1
@HalvardHummel Teşekkürler; özellikle gereksiz dilimleme işlemini tespit etmek için.
Jonathan Frech

@ user202729 Sence m[:]for~> m*1for? Çalışabilir.
Jonathan Frech

@ user202729 Teşekkürler, bağlantılı uç bunun derin bir kopyaya ihtiyacı olduğunu düşündüğüm için çalıştı.
Jonathan Frech

9

JavaScript (ES6), 138 134

@ Neil'inkinden çok farklı değil, ama başka ne olabilir?

Giriş: çok satırlı dizge olarak matris, ikili dizge, genişlik (yeni satır sayılmaz)

Not: özyinelemeli fonksiyondaki mantık rbir kaç bayttan tasarruf etmek için biraz ters

(m,s,w)=>[...m].some((c,p,m,r=(p,o)=>s[m[p]=r,o]&&([~w,-~w,1,-1].every(d=>m[d+=p]!=s[o]||r(d,o+1))&&(m[p]=s[o-1])))=>c==s[0]&&!r(p,1))

Daha az golf oynadı

(m,s,w)=>(
  m=[...m],
  r= (p, o) => 
    (m[p] = -w, s[o])
    && (
         [~w, -~w, 1, -1].every( d =>
            m[d+=p] != s[o] || r(d, o+1)
         )
         && (m[p]=s[o-1])
    ),
  m.some((c,p) =>c == s[0] && !r(p,1))
)

Ölçek

var F=
(m,s,w)=>[...m].some((c,p,m,r=(p,o)=>s[m[p]=r,o]&&([~w,-~w,1,-1].every(d=>m[d+=p]!=s[o]||r(d,o+1))&&(m[p]=s[o-1])))=>c==s[0]&&!r(p,1))

// this slightly modified version tracks the path
var Mark=
(m,s,w)=>(m=[...m]).some((c,p,m,r=(p,o)=>s[m[p]=-o,o]&&([~w,-~w,1,-1].every(d=>m[d+=p]!=s[o]||r(d,o+1))&&(m[p]=s[o-1])))=>c==s[0]&&!r(p,1))
?m.map((c,p)=>c<-1?'.───│┘└.│┐┌.│'[((m[p-1]-c)**2<2)+((m[p+1]-c)**2<2)*2+((m[p+~w]-c)**2<2)*4+((m[p-~w]-c)**2<2)*8]:c<0?'*':c).join``:''

function go()
{
  O.textContent =F(M.value, S.value, M.value.search('\n'))+'\n\n'
  +Mark(M.value, S.value, M.value.search('\n'))
}

go()
#M {width:100px; height:100px }
<textarea id=M>010101
111011
011010
011011</textarea><br>
<input id=S value='0111111100101' oninput='go()'>
<button onclick='go()'>go</button>
<pre id=O></pre>


6

JavaScript (ES6), 149 bayt

(m,s,w)=>[...m].some((c,i)=>c==s[0]&&g(m,s,i),g=(m,s,i)=>!(s=s.slice(1))||[~w,-1,1,-~w].some(o=>m[o+=i]==s[0]&&g(m.slice(0,i)+' '+m.slice(i+1),s,o)))

Matrisi, yeni satırlarla ayrılmış bir dize, yılanı bir dize olarak ve genişliği (tam sayı olarak) alır. Loosely @ JonathanFrech'in cevabına dayanıyor.


4

Mathematica, 180 156 141 153 138 136 104 bayt

MemberQ[#|Table[""<>Part[Join@@#,p],{x,1##4},{y,1##4},{p,FindPath[GridGraph@{##4},x,y,#3,All]}],#2,All]&

Örnek giriş

[{{"1","1","1","1","1"},{"0","0","0","0","0"}},"10011001",8,5,2]

açıklama

  1. GridGraph@{##4}a, Graphboyutlara sahip kenarlar tarafından birbirine bağlanmış bitişik köşe ile köşe bir kafes için bir amacı {##4}olup, - {#4,#5}ya da {width,height}.
  2. Biz yineleme üzerinde, tüm başlangıç köşe x(numaralı 1için 1##4 = width*height), her bitiş köşe yve tüm yollar pen uzunluğunun #3gelen xiçin y.
  3. Bu yolların her biri ""<>Part[Join@@#,p]için matrisin karşılık gelen karakterlerini çıkarır ve bunları bir dizgeye yerleştirir.
  4. Ayrıca, karakterlerinin hepsi içinde bulunabilecek uzunluktaki 1 dizeleri olan matrisin kendisini de ekliyoruz.
  5. Bu dizgilerden birinin eşleşip eşleşmediğini sher seviyede araştırıp aramadığımızı görüyoruz çünkü bu çok boyutlu bir liste oluşturduk.

Not: Yerine #3göre {#3-1}de FindPathsadece tam doğru uzunlukta yollarını bulmak böylece, hız açısından büyük bir gelişme olduğunu - ancak 4 daha bayt mal olur.


-24 bayt: girdilerin boyutlarını almak

-15 bayt: kullanarak StringPartve StringJoindüzgün

+12 bayt: uzunluk-1 davasının düzeltilmesi

-15 bayt: ...

-2 bayt: dizi olarak girdi olarak matrisin boyutunun alınması

-32 bayt: Tableyol üzerinde yinelemek için kullanmak kullanmaktan kaçınmamızı sağlar Functionve kullanmak MemberQ[...,s,All], uzunluğu 1 olan yılanlarla uğraşırken matrisi masanın üzerine yapıştırmamıza izin verir.


3

C # (.NET Core) , 346 341 336 302 297 bayt

(m,h,w,s,l)=>{for(int y=0;y<h;y++)for(int x=0;x<w;x++)if(N(x,y,l-1))return 0<1;return 1<0;bool N(int x,int y,int p){if(p<0)return 0<1;if(y<0|x<0|y==h|x==w||m[y,x]>1||s[p]!=m[y,x])return 1<0;int g=m[y,x];m[y,x]=2;if(N(x,y-1,--p)||N(x-1,y,p)||N(x,y+1,p)||N(x+1,y,p))return 0<1;m[y,x]=g;return 1<0;}}

Çevrimiçi deneyin!

pArtış golf tarafından kaydedilen 5 bayt

Yılan boyu alarak ve kuyruğundan başlayarak ve gereksiz bir alanı kaldırarak 5 bayt tasarruf

34 bayt, mücadeleyi doğru okuyarak ve matrisin yüksekliğini ve genişliğini alabileceğimi görünce kurtarıldı

5 bayt kaydedildi, tek eleman test durumu başarısız oldu ve düzeltme faydalı oldu.

Ungolfed

(m,h,w,s,l)=>{
    // Go through every potential starting point
    for(int y=0; y<h; y++)
        for(int x=0; x<w; x++)
            if(N(x,y,l-1)) // start the recursive steps
                return 0<1; // return true if N returns true, otherwise check the next element

    return 1<0; // return false as the snake doesn't fit into the matrix

    // C#7 local function in a Func
    bool N(int x, int y, int p)
    {
        // if there is no more snake to fit return true
        if(p<0)
            return 0<1;

        // if m element has part of the snake or 
        // snake part doesn't match matrix element then return false
        if(y<0 | x<0 | y==h | x==w || m[y,x]>1 || s[p] != m[y,x])
            return 1<0;

        // hold the current matrix element
        int g=m[y,x];
        // set the current matrix element to 2 to indicate it has a part of the snake
        m[y,x]=2;

        // check each of the four neighbours and recurse down that neighbour 
        // except if they are outside the matrix
        if(N(x,y-1,--p) ||
           N(x-1,y,p) ||
           N(x,y+1,p) ||
           N(x+1,y,p))
               return 0<1; // return true if remainder of the snake fits into the matrix

        // if snake doesn't fit then set the matrix element as not having part of the snake
        m[y,x]=g;
        // return false to indicate this neighbour direction doesn't fit the snake
        return 1<0; 
    }
}

Gereksiz tüm boşlukları kaldırmak bir golf oyunu olacaktır ...
Jonathan Frech

if(...)return true;-> return ...;.
Jonathan Frech

@JonathanFrech Anlaştık, ancak geri alma şansım olana kadar başkalarının daha kolay okumalarını sağlamak için öyle bıraktım (yarın bazen).
Ayb4btu

@JonathanFrech Çalışmıyor b[y,x], bir noktada sıfırlanması gerekiyor. (Ayrıca cevabımdaki isminizi yanlış yazdığım için de üzgünüm.)
Neil

Demek istediğim if(N(x,y,0)>0)return 0<1;; ilk görünüşü return.
Jonathan Frech

1

Kotlin , 413 bayt

var x:(Array<Array<Char>>,String)->Boolean={b,s->fun f(s:String,x:Int,y:Int):Boolean{if(b[x][y]!=s[0])
return 0>1
if(s.length<2)
return 1>0
val v=b[x][y]
b[x][y]='Z'
try{return(-1..1).map{x+it}.flatMap{t->(-1..1).map{y+it}.map{t to it}}.filter{(X,Y)->(x-X)*(x-X)+(y-Y)*(y-Y)==1&&X in b.indices&&Y in b[0].indices&&f(s.substring(1),X,Y)}.any()}finally{b[x][y]=v}}
b.indices.any{x->(0..b[0].size-1).any{f(s,x,it)}}}

Beautified

var x: (Array<Array<Char>>, String) -> Boolean = { b, s ->
    fun f(s: String, x: Int, y: Int): Boolean {
        if (b[x][y] != s[0])
            return 0 > 1
        if (s.length < 2)
            return 1 > 0
        val v = b[x][y]
        b[x][y] = 'Z'
        try {
            return (-1..1).map{ x + it }
                    .flatMap { t -> (-1..1).map{y+it}.map { t to it } }
                    .filter { (X, Y) ->
                        (x - X)*(x - X) + (y - Y)*(y - Y) == 1 &&
                                X in b.indices && Y in b[0].indices &&
                                f(s.substring(1), X, Y) }
                    .any()
        } finally {
            b[x][y] = v
        }
    }
    b.indices.any { x -> (0..b[0].size - 1).any { f(s, x, it) } }
}

Ölçek

var x:(Array<Array<Char>>,String)->Boolean={b,s->fun f(s:String,x:Int,y:Int):Boolean{if(b[x][y]!=s[0])
return 0>1
if(s.length<2)
return 1>0
val v=b[x][y]
b[x][y]='Z'
try{return(-1..1).map{x+it}.flatMap{t->(-1..1).map{y+it}.map{t to it}}.filter{(X,Y)->(x-X)*(x-X)+(y-Y)*(y-Y)==1&&X in b.indices&&Y in b[0].indices&&f(s.substring(1),X,Y)}.any()}finally{b[x][y]=v}}
b.indices.any{x->(0..b[0].size-1).any{f(s,x,it)}}}

data class Test(val board: String, val snake: String, val output: Boolean)

val tests = listOf(
        Test("""01010
            |10101
            |01010
            |10101
            |01010""", "0101010101010101010101010", true),
        Test("""01110
            |01100
            |10010
            |10110
            |01101""", "011111000110100", true),
        Test("""0""", "0", true),
        Test("""10
            |01""", "1010", true),
        Test("""100
            |010
            |001""", "100010001", true),
        Test("""00000
            |00000
            |00000
            |00000
            |00000""", "1", false),
        Test("""10101
            |01010
            |10101
            |01010
            |10101""", "11", false),
        Test("""100
            |010
            |001""", "111", false),
        Test("""10001
            |01010
            |00100
            |01010
            |10001""", "1000100010001000101010100", false)
)

fun main(args: Array<String>) {
    tests.filter {(board, snake, expected) ->
        val boardR = board.trimMargin().lines().map { it.toCharArray().toTypedArray() }.toTypedArray()
        val result = x(boardR, snake)
        result != expected
    }.forEach { throw AssertionError(it) }
    println("Test Passed")
}
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.