Sprawdź, czy istnieje ruch w grze Bejeweled / match 3

20

tło

W Bejeweled i podobnych grach gracz musi zamienić dowolne dwa sąsiednie klejnoty (bez przekątnych) w siatce klejnotów 8x8, aby dopasować trzy tego samego koloru z rzędu. Klejnoty można dopasowywać poziomo lub pionowo. Rozgrywka trwa, dopóki nie będzie żadnego ruchu, który można wykonać, co spowoduje trzy z rzędu, w którym to momencie gra się kończy.

Zadanie

Celem jest napisanie programu, który określa, czy gra w Bejeweled jeszcze się nie skończyła. Innymi słowy, musi sprawdzić, czy możliwy jest ruch, który daje co najmniej trzy z rzędu. Mogą być więcej niż trzy klejnoty z rzędu i nadal jest to prawidłowy ruch.

Wejście

Twój program musi zaakceptować za pomocą standardowego wejścia reprezentację 8x8 siatki Bejeweled. Każdy z siedmiu kolorów klejnotów będzie reprezentowany przez cyfrę od 1 do 7. Każda linia będzie zawierać jeden wiersz i wprowadzonych zostanie 8 linii, każda składająca się z 8 cyfr. Zobacz przykłady. Możesz założyć, że dane wejściowe będą zawsze zgodne z tym formatem i nigdy nie będą już zawierać trzech z rzędu.

Wynik

Program musi następnie wyprowadzić (na standardowe wyjście) yeslub w nozależności od tego, czy istnieje co najmniej jeden prawidłowy ruch, który spowodowałby trzy lub więcej klejnotów z rzędu. Twój program nie może wypisywać niczego poza pojedynczą instancją jednego yeslub jednego no.

Zasady

Twój program nie może używać żadnych zewnętrznych plików ani zasobów, argumentów wiersza poleceń ani wymagać określonej nazwy pliku. Program z najmniejszą liczbą bajtów w kodzie źródłowym wygrywa.

Przykłady

Wejście:

12314131
13224145
54762673
61716653
61341144
23453774
27645426
75575656

Wynik: yes

Wejście:

35261546
76421754
15743271
62135642
35617653
64565476
54427254
15635465

Wynik: no

Zobacz odpowiedź MT0 poniżej na dodatkowe przypadki testowe.

bdr9
źródło
Czy to tylko wiersze, czy też kolumny.
TheDoctor
@ TheDoctor Columns też. Kiedy używam wyrażenia „trzy z rzędu”, mam na myśli, że muszą być one ustawione w linii w kierunku poziomym lub pionowym.
bdr9
@ bdr9 możesz edytować to w
John Dvorak
@JanDvorak Gotowe.
bdr9
Może także chcieć edytować, jeśli dozwolone jest 4+ z rzędu.
Justin

Odpowiedzi:

12

Oryginalne rozwiązanie: JavaScript - 261 255 228 227 179 153 znaków

/(\d)(\1(\d|.{6}|.{9})|(\d|.{6}|.{9})\1|.{7}\1(.|.{9})|(.|.{9})\1.{7}|(.{7,9}|.{17})\1.{8}|.{8}\1(.{7,9}|.{17}))\1/.test(s.replace(/\n/g,'A'))?'yes':'no'

Zakładając, że łańcuch do testu jest w zmiennej s(aby to funkcja fnastępnie dodać f=s=>do początku kodu lub, inaczej, aby pobierać dane z wiersza następnie zastąpić sz prompt()).

Dane wyjściowe są przesyłane do konsoli.

3 rd rozwiązanie: JavaScript (ECMAScript 6): - 178 znaków

p=x=>parseInt(x,36);for(t="2313ab1b8a2a78188h9haj9j8iaiir9r",i=v=0;s[i];i++)for(j=0;t[j];v|=s[i]==s[i+a]&s[i]==s[i+b]&i%9<8&(b>3|(i+b-a)%9<8))a=p(t[j++]),b=p(t[j++]);v?'yes':'no'

Wziąłem 2 nd rozwiązanie, poniżej, (który używa wyrażeń regularnych do sprawdzania znaków w niektórych konfiguracjach) i przerobiony go po prostu sprawdzić ciąg dla identycznych znaków w tych samych konfiguracjach bez użycia wyrażeń regularnych.

Ciąg Base-36 "2313ab1b8a2a78188h9haj9j8iaiir9r"daje par przesunięć, by sprawdzić - czyli pary 23wyników w czeku, jeśli I th znak jest identyczny z (i + 2) th charakteru i (i + 3) th charakteru (odpowiednik wyrażenia regularnego (.).\1\1- z pewnymi dodatkowymi kontrolami, aby upewnić się, że nieidentyczny znak nie jest znakiem nowej linii).

2 II rozwiązanie: JavaScript (ECMAScript 6) - 204 znaków

p=x=>parseInt(x,18);g=a=>a?a>1?"(.|\\n){"+a+"}":".":"";f=(x,a,b)=>RegExp("(.)"+g(a)+"\\1"+g(b)+"\\1").test(x);for(t="10907160789879h8",i=v=0;t[i];v|=f(s,x,y)||f(s,y,x))x=p(t[i++]),y=p(t[i++]);v?'yes':'no'

Buduje wiele wyrażeń regularnych (więcej szczegółów poniżej) przy użyciu par wartości pobranych z ciągu Base-18 10907160789879h8i wykonuje ORwszystkie testy. Aby jeszcze bardziej to zmniejszyć, możesz zauważyć, że wyrażenia regularne występują w parach, gdzie jedno jest „odwrotnością” drugiego (ignorując wyrażenia regularne dla 3-z rzędu poziomo i pionowo, ponieważ OP wskazuje, że nigdy nie będą obecne - jeśli chcesz dodać te testy z powrotem w dołączeniu 0088do ciągu Base-18).

Wyjaśnienie

Zacznij od 16 wyrażeń regularnych obejmujących wszystkie możliwe konfiguracje prawidłowych ruchów:

REs=[
    /(\d)\1\1/,                 // 3-in-a-row horizontally
    /(\d).\1\1/,                // 3-in-a-row horizontally after left-most shifts right
    /(\d)\1.\1/,                // 3-in-a-row horizontally after right-most shifts left
    /(\d)(?:.|\n){9}\1\1/,  // 3-in-a-row horizontally after left-most shifts down
    /(\d)(?:.|\n){7}\1.\1/, // 3-in-a-row horizontally after middle shifts down
    /(\d)(?:.|\n){6}\1\1/,  // 3-in-a-row horizontally after right-most shifts down
    /(\d)\1(?:.|\n){6}\1/,  // 3-in-a-row horizontally after left-most shifts up
    /(\d).\1(?:.|\n){7}\1/, // 3-in-a-row horizontally after middle shifts up
    /(\d)\1(?:.|\n){9}\1/,  // 3-in-a-row horizontally after right-most shifts up
    /(\d)(?:.|\n){7,9}\1(?:.|\n){8}\1/, // 3-in-a-row vertically (with optional top shifting left or right)
    /(\d)(?:.|\n){7}\1(?:.|\n){9}\1/,   // 3-in-a-row vertically after middle shifts right
    /(\d)(?:.|\n){9}\1(?:.|\n){7}\1/,   // 3-in-a-row vertically after middle shifts left
    /(\d)(?:.|\n){8}\1(?:.|\n){7}\1/,   // 3-in-a-row vertically after bottom shifts right
    /(\d)(?:.|\n){8}\1(?:.|\n){9}\1/,   // 3-in-a-row vertically after bottom shifts left
    /(\d)(?:.|\n){17}\1(?:.|\n){8}\1/,  // 3-in-a-row vertically after top shifts down
    /(\d)(?:.|\n){8}\1(?:.|\n){17}\1/,  // 3-in-a-row vertically after bottom shifts up
];

( Uwaga: regexs do 3 w jednej linii w poziomie 0 ( TH ) i pionowo (część 9 TH ) mają znaczenia jak wskazuje PO, że środki do dopasowania ich nie będzie obecny. )

Testowanie każdego z tych danych wejściowych określi, czy można znaleźć prawidłowy ruch tej konfiguracji.

Jednak wyrażenia regularne można łączyć, aby uzyskać następujące 6:

/(\d)(?:.|(?:.|\n){9}|(?:.|\n){6})?\1\1/            // Tests 0,1,3,5
/(\d)\1(?:.|(?:.|\n){9}|(?:.|\n){6})?\1/            // Tests 0,2,6,8
/(\d)(?:.|\n){7}\1(?:.|(?:.|\n){9})\1/              // Tests 4,10
/(\d)(?:.|(?:.|\n){9})\1(?:.|\n){7}\1/              // Tests 7,11
/(\d)(?:(?:.|\n){7,9}|(?:.|\n){17})\1(?:.|\n){8}\1/ // Tests 9,14
/(\d)(?:.|\n){8}\1(?:(?:.|\n){7,9}|(?:.|\n){17})\1/ // Tests 9a,12,13,15

Można je następnie połączyć w jedno wyrażenie regularne:

/(\d)(?:.|(?:.|\n){9}|(?:.|\n){6})?\1\1|(\d)\2(?:.|(?:.|\n){9}|(?:.|\n){6})?\2|(\d)(?:.|\n){7}\3(?:.|(?:.|\n){9})\3|(\d)(?:.|(?:.|\n){9})\4(?:.|\n){7}\4|(\d)(?:(?:.|\n){7,9}|(?:.|\n){17})\5(?:.|\n){8}\5|(\d)(?:.|\n){8}\6(?:(?:.|\n){7,9}|(?:.|\n){17})\6/

Który po prostu musi zostać przetestowany względem danych wejściowych.

Przypadki testowe

Niektóre przypadki testowe, które inne osoby mogą uznać za przydatne (nie są zgodne z formatem wejściowym polegającym na stosowaniu tylko cyfr 1-7, ale można to łatwo poprawić i jest to tylko siatka 8x4 - ponieważ jest to minimum wymagane do testu wszystkich prawidłowych danych wejściowych ).

W formacie mapy z ciągu wejściowego, do którego pasuje 16 wyrażeń regularnych powyżej.

Tests={
    "12345678\n34567812\n56781234\n78123456": -1, // No Match
    "12345678\n34969912\n56781234\n78123456": 1,    // 3-in-a-row horizontally after left-most shifts right 
    "12345678\n34567812\n59989234\n78123456": 2,    // 3-in-a-row horizontally after right-most shifts left
    "12345978\n34567899\n56781234\n78123456": 3,    // 3-in-a-row horizontally after left-most shifts down
    "12345978\n34569892\n56781234\n78123456": 4,    // 3-in-a-row horizontally after middle shifts down
    "12345678\n34967812\n99781234\n78123456": 5,    // 3-in-a-row horizontally after right-most shifts down
    "12399678\n34967812\n56781234\n78123456": 6,    // 3-in-a-row horizontally after left-most shifts up
    "12345678\n34597912\n56789234\n78123456": 7,    // 3-in-a-row horizontally after middle shifts up
    "12345998\n34567819\n56781234\n78123456": 8,    // 3-in-a-row horizontally after right-most shifts up
    "12945678\n34597812\n56791234\n78123456": 9,    // 3-in-a-row vertically after top shifts right
    "12349678\n34597812\n56791234\n78123456": 9,    // 3-in-a-row vertically after top shifts left
    "12345978\n34569812\n56781934\n78123456": 10,   // 3-in-a-row vertically after middle shifts right
    "92345678\n39567812\n96781234\n78123456": 11,   // 3-in-a-row vertically after middle shifts left
    "12945678\n34967812\n59781234\n78123456": 12,   // 3-in-a-row vertically after bottom shifts right
    "12349678\n34569812\n56781934\n78123456": 13,   // 3-in-a-row vertically after bottom shifts left
    "12395678\n34567812\n56791234\n78193456": 14,   // 3-in-a-row vertically after top shifts down
    "12345698\n34567892\n56781234\n78123496": 15,   // 3-in-a-row vertically after bottom shifts up
    "12345678\n34567899\n96781234\n78123456": -1,   // No match - Matches (.)\1.\1 but not 3 in a row
    "12345679\n99567812\n56781234\n78123456": -1,   // No match - Matches (.).\1\1 but not 3 in a row
};

Edytuj 1

Zamień \ds na .- zapisuje 6 znaków.

Edytuj 2

Wymień (?:.|\n)się [\s\S]i usuwane dodatkowych grup spoza przechwytywanie i zaktualizowanych odniesień tyłu (jak sugeruje m-Buettner ) i dodano w tak / nie wyjście.

Edytuj 3

  • Dodano rozwiązanie ECMAScript 6 w celu zbudowania poszczególnych wyrażeń regularnych z ciągu Base-18.
  • Usunięto testy dla 3-z rzędu poziomo (zgodnie z sugestią m-buettner ).

Edytuj 4

Dodano kolejne (krótsze) rozwiązanie i dwa kolejne niepasujące przypadki testowe.

Edytuj 5

  • Skrócono oryginalne rozwiązanie, zastępując znaki nowej linii znakiem nienumerycznym (jak sugeruje VadimR ).

Edytuj 6

  • Skrócono oryginalne rozwiązanie poprzez połączenie bitów wyrażenia regularnego (jak sugeruje VadimR ).
MT0
źródło
1
Fajne rozwiązanie! Nie pomyślałbym, że regex może zadziałać. Podaj ?'yes':'no'liczbę swoich znaków dla uczciwości, ponieważ jest to zgodne z wymogami i wszyscy inni go używają.
bdr9
Dzięki za dodatkowe przypadki testowe, dodałem link do twojej odpowiedzi, aby inni mogli je zobaczyć.
bdr9
Whoa. +1 za regex
DankMemes
H-mm, brak modyfikatora w JS dla .dopasowania dowolnego znaku, w tym nowego wiersza? W przypadku Perla łączone wyrażenie regularne ma zaledwie 129 bajtów (co jest leniwe, skompilowałem z Regexp :: Assemble ), więc cały program Perla ma około 150 bajtów.
user2846289
1
@VadimR Dzięki ale można pójść jeszcze dalej, zastępując .{8}|.{9}z .{8,9}i .{7}|.{8}z.{7,8}
MT0
3

Python 383

Tylko jedna * linia Pythona!

a=[list(l)for l in raw_input().split('\n')];z=any;e=enumerate;c=lambda b:z(all(p==b[y+v][x+u]for(u,v)in o)for y,r in e(b[:-2])for x,p in e(r[:-2])for o in [[(0,1),(0,2)],[(1,0),(2,0)]]);print z(c([[q if(i,j)==(m,n)else a[m][n]if(i,j)==(y+1,x+1)else p for j,p in e(r)]for i,r in e(a)])for y,t in e(a[1:-1])for x,q in e(t[1:-1])for n,m in((x+u,y+v)for u,v in[(1,0),(1,2),(0,1),(2,1)]))

* Cóż, z średnikami, ale w pythonie wciąż nie jest to trywialne (jednowierszowe python są fajne! )

KSab
źródło
3
Zagłosowano za niezrozumiałe rozumienie :)
Alexander-Brett
2

Node.js - Naiwne rozwiązanie - 905 bajtów

Cóż, jeszcze nie ma odpowiedzi, więc opublikuję naprawdę naiwne rozwiązanie w Node.js

Przechodzi przez każdy możliwy ruch, a następnie testuje powstałą planszę, aby sprawdzić, czy są 3 z rzędu.

Gra w golfa (z kompilatorem zamykającym google) (niektóre tam hacky rzeczy, takie jak! 0 i! 1; nawet nie jestem pewien, co zrobił z moją zamianą XOR)

Array.prototype.a=function(){for(var f=[],d=0;d<this.length;d++)f[d]=this[d].a?this[d].a():this[d];return f};for(var a=[],b=0;8>b;b++)a[b]=[];for(b=2;b<process.argv.length;b++)for(var c=process.argv[b].split(""),e=0;e<c.length;e++)a[b-2][e]=parseInt(c[e],10);function h(){for(var d=l,f=0;f<d.length-2;f++)for(var g=0;g<d[f].length-2;g++){var k=d[f][g];if(k==d[f+1][g]&&k==d[f+2][g]||k==d[f][g+1]&&k==d[f][g+2])return!0}return!1}function m(){console.log("yes");process.exit()}for(b=0;b<a.length;b++)for(e=0;e<a[b].length;e++){var l=a.a();0!=b&&(l[b-1][e]^=l[b][e],l[b][e]^=l[b-1][e],l[b-1][e]^=l[b][e],h()&&m(),l=a.a());b!=a.length-1&&(l[b+1][e]^=l[b][e],l[b][e]^=l[b+1][e],l[b+1][e]^=l[b][e],h()&&m(),l=a.a());0!=e&&(l[b][e-1]^=l[b][e],l[b][e]^=l[b][e-1],l[b][e-1]^=l[b][e],h()&&m(),l=a.a());e!=a[b].length-1&&(l[b][e+1]^=l[b][e],l[b][e]^=l[b][e+1],l[b][e+1]^=l[b][e],h()&&m(),l=a.a())}console.log("no");

Pamiętaj, że napisałem to wszystko na telefonie komórkowym i nie mam czasu na testowanie ani nic takiego. Skomentuj, jeśli zobaczysz jakieś błędy, sprawdzę to później.

Wersja do gry w golfa dla ludzi

// set it up
Array.prototype.clone = function() {
    var arr = [];
    for( var i = 0; i < this.length; i++ ) {
        if( this[i].clone ) {
             arr[i] = this[i].clone();
        } else {
             arr[i] = this[i];
        }
    }
};
var board=[];
for(var i=0;i<8;i++)board[i]=[];
for(var i=2;i<process.argv.length;i++){
    var row=process.argv[i].split("");
    for(var j=0;j<row.length;j++)board[i-2][j]=parseInt(row[j], 10);
}
// function to test
function testBoard(arr){
    for(var i=0;i<arr.length-2;i++){
        for(var j=0;j<arr[i].length-2;j++){
            var val=arr[i][j];
            if(val==arr[i+1][j] && val==arr[i+2][j])return true;
            if(val==arr[i][j+1] && val==arr[i][j+2])return true;
        }
    }
    return false;
}
// functions to exit
function yay(){console.log("yes");process.exit();}
function nay(){console.log("no");}
// super slow naive solution time
for(var i=0;i<board.length;i++){
    for(var j=0;j<board[i].length;j++){
        var newboard=board.clone();
        if(i!=0){
            newboard[i-1][j]=newboard[i-1][j]^newboard[i][j];// whoa, it's a
            newboard[i][j]=newboard[i-1][j]^newboard[i][j];  // cool algorithm
            newboard[i-1][j]=newboard[i-1][j]^newboard[i][j];// at least this 
                                                             // isn't all naive
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
        if(i!=board.length-1){
            newboard[i+1][j]=newboard[i+1][j]^newboard[i][j];
            newboard[i][j]=newboard[i+1][j]^newboard[i][j];
            newboard[i+1][j]=newboard[i+1][j]^newboard[i][j];
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
        if(j!=0){
            newboard[i][j-1]=newboard[i][j-1]^newboard[i][j];
            newboard[i][j]=newboard[i][j-1]^newboard[i][j];
            newboard[i][j-1]=newboard[i][j-1]^newboard[i][j];
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
        if(j!=board[i].length-1){
            newboard[i][j+1]=newboard[i][j+1]^newboard[i][j];
            newboard[i][j]=newboard[i][j+1]^newboard[i][j];
            newboard[i][j+1]=newboard[i][j+1]^newboard[i][j];
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
    }
}
nay();
DankMemes
źródło
Hah właściwie przegapiłem pierwszy post o 10 minut.
Trochę
Ach, dokładnie ta sama metoda, której użyłem (naiwny, ale mały kod!). +1 za bycie znacznie bardziej opisowym niż ja
KSab
Zastanawiam się, czy istnieje bardziej wydajny algorytm ...
DankMemes
2

Perl, 114 96 95 93 92 87 86 85 bajtów

Obejmuje + dla -a0p

Uruchom z wejściem na STDIN:

bejeweled.pl
12314131
13224145
54762673
61716653
61341144
23453774
27645426
75575656
^D

bejeweled.pl:

#!/usr/bin/perl -a0p
$i/s%.%chop$F[$i++&7]%eg>3|/(.)((.|\H{6}|\H{9})\1|\H{7}\1.)\1/||redo;$_=$1?yes:n.o

Łączy to jednokierunkowe rozwiązanie regex z obrotami

Wyjaśnienie:

W tym rozwiązaniu będę wielokrotnie obracać i wykonywać następujące 4 testy:

/(.).\1\1/,      // 3-in-a-row horizontally after left-most shifts right
/(.)\C{9}\1\1/,  // 3-in-a-row horizontally after left-most shifts down
/(.)\C{7}\1.\1/, // 3-in-a-row horizontally after middle shifts down
/(.)\C{6}\1\1/,  // 3-in-a-row horizontally after right-most shifts down

Gdzie \Cjest „dowolny znak” (w przeciwieństwie do .tego zawiera znak nowej linii). Tyle że \Cjest przestarzałe i prowadzi do ostrzeżeń, więc \Hzamiast tego używam (spacji poziome), co jest wystarczająco dobre, aby przechwycić wszystkie cyfry i znak nowej linii.

Po 4 obrotach wykona wszystkie 16 niezbędnych testów

-p                            Read lines from STDIN, print $_ at the end
-0                            No line ending => slurp ALL of STDIN
-a                            Split $_ into @F. Since there are no spaces
                              on the rows this means each element of @F is
                              1 row

    s%.%chop$F[$i++&7]%eg     Replace each row by the removed last column
                              This is therefore a left rotation. Very short
                              but at the cost of using @F. To make sure that
                              @F gets refilled from $_ each time I won't be
                              able to use while, until, eval or do$0 for the
                              loops but have to use redo. That costs a few
                              bytes but less than having to do my own split
$i/                      >3   The previous regex replacement always
                              returns 64 and each time through the loop $i is
                              increased by 64. So if this division reaches
                              4 all rotations have been done

/(.)((.|\H{6}|\H{9})\1|\H{7}\1.)\1/ This is the 4 regexes mentioned above
  ||redo                      Stop the loop if the regex matches or we
                              rotated 4 times
$_=$1?yes:n.o                If the regex matched $1 will be one of the
                              color digits (which cannot be 0) and this will
                              assign "yes" to $_. If the regex didn't match
                              in 4 times $1 will get its value from the last
                              succesful regex in scope which will be the one
                              from the rotation, but that one doesn't have
                              any () so $1 will be unset. So in case there
                              is no move $_ will be set to "no" (which needs
                              to be constructed because "no" is a keyword)
Ton Hospel
źródło
1

Python3, 314B

import itertools as T,copy
r=[]
K=range(8)
J=[list(input())for w in K]
P=T.product
f=lambda A:["yes"for b in[A[m][n:]for m,n in P(K,K[:6])]if b[0]==b[1]==b[2]]
for i,j,x in P(K,K,[0,1]):
 t=j+1-x
 if i+x<8and t<8:B=copy.deepcopy(J);B[i][j],B[i+x][t]=B[i+x][t],B[i][j];r+=f(B)+f(list(zip(*B)))
r+=["no"]
print(r[0])

Zmień 8, 5 w linii 6 i 8s w linii 9, aby obsługiwać dowolnie duże rozmiary wejściowe; nie obchodzi też, jaka jest każda wartość, więc możesz ją karmić:

absdefgh
sdkljahs
lsdfjasd
fjdhsdas
dkjhfasd
sdfhaskd
sdkfhkas
weriuwqe

i wróci yes.

Adnotacje

import itertools as T,copy 
            # itertools.product is going to save us lots of for loops
r=[]        # result
K=range(8)  # we can use range(8) everywhere, so this saves more than the usual R=range
J=[list(input())for w in K] 
            # input handling: keep everything as a length-1 string to avoid map(int,input())
P=T.product
f=lambda A:["yes"for b in[A[m][n:]for m,n in P(K,K[:6])]if b[0]==b[1]==b[2]] 
            # check the condition horiontally only. K[:6] is the same as range(5)
            # A[m][n:n+3] would be neater, but not actually needed
for i,j,x in P(K,K,[0,1]): 
            # <3 itertools.product! 3 for-loops without it.
            # NB we're only going right and downwards
 t=j+1-x
 if i+x<8and t<8: 
            # don't want out-of-bounds errors at the edges
  B=copy.deepcopy(J) 
            # preserve the reference array
  B[i][j],B[i+x][t]=B[i+x][t],B[i][j] 
            # do the switch
  r+=f(B)+f(list(zip(*B))) 
            # do the test. you could end up with lots of 'yes's in r.
            # zip(*B) takes the transpose, so that f checks the columns too
r+=["no"]   # happens to ensure that r is nonempty
print(r[0]) # only prints no if r was empty before the last line
Alexander-Brett
źródło
1

GNU sed 255 + 2 = 257B

Myślałem, że to nie będzie tak dobre jak Python, ale teraz: - / Dzisiaj nie miałem dostępu do Internetu, więc zająłem się rozwiązywaniem tego problemu w sed :). Musi zostać wywołany z opcją -r, tj. sed -rf command.sed < inputWięc dodałem 2 do mojego wyniku.

:a
$!N
s/\n/ /g
ta
:b
/^((\w)(\w\2\2|\2\w\2|\w\2\w* \w\2|\2\w* \w\w\2|\w* (\2\w* \w* \2|\w* \2\w* \2|\w\2\2|\w\2\w* \2|\2\w* \w\2|\w\2\w* \w\2))|\w((\w)(\w* \6\w\6|\6\w* \6|\w* (\6\w \w\6|\w\6\w* \6|\6\w* \6))|\w(\w)\w* \9\9))/c\yes
s/\w(\w*)/\1/g
tb
c\no

Jak to działa:

  1. Przeczytaj siatkę w jednym wierszu znaków rozdzielonych spacjami
  2. Użyj wyrażenia regularnego motherload, aby dowiedzieć się, czy w pierwszej kolumnie jest dopasowanie * - jeśli tak, zamień całą linię na „tak” (zakończenie programu)
  3. Zdejmij pierwszy znak z każdej kolumny i dostań 2, jeśli tak zrobiliśmy
  4. Jeśli nie (linia jest pusta) zamień całą linię na „nie”
Alexander-Brett
źródło
1

Ruby, 201 bajtów

Byłem rozczarowany, że nie widziałem żadnych rozwiązań tego wielkiego wyzwania, które nie używają wyrażenia regularnego ani brutalnej siły (chociaż są świetne), więc napisałem jedno. Wymaga wejścia na STDIN.

Podstawowy bitowy algorytm arytmetyczny pochodzi z tej fantastycznej odpowiedzi na Game Development Stack Exchange autorstwa @leander.

s=$<.read
$><<(?1..?9).any?{|n|a=[0]*19
s.scan(n){i=$`.size
a[i/9+1]+=2**(i%9)
a[i%9+10]+=2**(i/9)}
a.each_cons(3).any?{|x,y,z|q=y&y<<1
l=q<<1
q>>=2
y&(l<<1|q>>1)|(q|l|(y&y<<2)>>1)&(x|z)>0}}?"yes":"no"

Ruby lambda, 181 bajtów

Tu jest jak lambda, które pobiera ciąg i powraca truealbo false:

->s{(?1..?9).any?{|n|a=[0]*19
s.scan(n){i=$`.size
a[i/9+1]+=2**(i%9)
a[i%9+10]+=2**(i/9)}
a.each_cons(3).any?{|x,y,z|q=y&y<<1
l=q<<1
q>>=2
y&(l<<1|q>>1)|(q|l|(y&y<<2)>>1)&(x|z)>0}}}

Zobacz na repl.it: https://repl.it/ColJ/2

Nie golf i wyjaśnienia

->s{
  (?1..?9).any? {|n|
    a = [0] * 19

    s.scan(n) {
      i = $`.size
      a[i/9+1] += 2**(i%9)
      a[i%9+10] += 2**(i/9)
    }

    a.each_cons(3).any? {|x,y,z|
      q = y & y << 1
      l = q << 1
      q >>= 2
      y & (l << 1 | q >> 1) |
        (q | l | (y & y << 2) >> 1) &
        (x | z) > 0
    }
  }
}

Kod iteruje cyfry od „1” do „9.” Każda iteracja ma dwa odrębne kroki:

Pierwszym krokiem jest transformacja planszy, którą można zobaczyć w s.scan(n)bloku w niepoddanym golfie kodzie. Przekształca tablicę w tablicę 8 liczb całkowitych, po jednej dla każdego wiersza, traktując pasujące cyfry jako 1, a wszystkie pozostałe jako 0 w ciągu binarnym. Na przykład weź wiersz 12231123. W pierwszej iteracji stanie się to ciągiem binarnym 10001100(wszystkie 1-sza stają się - er, stay - 1s, a wszystkie inne cyfry stają się 0), co jest liczbą dziesiętną 140. W drugiej iteracji ten sam wiersz staje się 01100010(wszystkie 2s stają się 2s i wszystkie pozostałe cyfry stają się zerami) lub dziesiętnymi 98.

Jednocześnie wykonuje drugą transformację, która jest taka sama jak pierwsza, ale z płytką obróconą o 90 stopni. To pozwala nam używać tej samej logiki do dopasowywania poziomego jak pionowego. Dla uproszczenia łączy dwie deski w jedną długą z zerą na początku, środkową (aby oddzielić dwie deski) i końcem do wypełnienia.

Drugim krokiem jest poszukiwanie możliwych dopasowań, które można zobaczyć w each_cons(3).any?bloku. Przekształcone wiersze (które są teraz 8-bitowymi liczbami całkowitymi) są rejestrowane w (nakładających się) grupach trzech wierszy ( x , y , z ) za pomocą arytmetyki bitowej. Każda grupa jest sprawdzana, aby sprawdzić, czy dopasowanie można wykonać w rzędzie y , poprzez przesunięcie elementu w rzędzie y lub przez przesunięcie elementu na y z x lub z . Ponieważ przed i za rzędami zarówno oryginalnej, jak i obróconej planszy występuje zerowy „rząd”, nie musimy sprawdzać, czy znajdujemy się w pierwszym czy ostatnim rzędzie planszy.

Jeśli nie znaleziono żadnych dopasowań, przechodzi do następnej iteracji.

Jordania
źródło