Proste wyzwanie golfowe: Wzory postaci!

22

W tym wyzwaniu otrzymujesz ciąg wejściowy zawierający ciąg znaków X, Y i Z, np. „XYZZ”. X, Y i Z reprezentują określoną postać. Ten wzór jest następnie porównywany z drugim ciągiem wejściowym. Jeśli wzorzec istnieje jako podłańcuch na drugim wejściu, zwróć True, w przeciwnym razie zwróć False. Po znalezieniu wzorca w słowie program przestaje wyszukiwać i wraca True.

Przykłady

Wzór: „XXYY”

succeed ---> True (pattern found: ccee)
success ---> False (pattern not matched)
balloon ---> True (pattern found: lloo)

Wzór: „XYXYZ”

bananas ---> True (pattern found: nanas)
banana  ---> False (pattern not found)
  • Uwaga: To nie jest rzeczywiste wejście. To jest przykład działania programu. Twój program powinien wypisać Truelub Falselub inne wartości Truthy / Falsy.

Inne ważne / przydatne informacje

  • Wzorzec nie musi zawierać X, Y i Z, może zawierać X i Y, a nawet (choć nieco bezcelowo) tylko X.
  • Wzorzec nie może być pusty, ale nie zostanie użyty jako przypadek testowy.
  • Wyszukiwany ciąg nie będzie pusty i będzie pisany małymi literami.
  • Kolejność alfabetyczna X, Y i Z we wzorze nie ma znaczenia.
  • X, Y i Z muszą być unikalnymi znakami.
  • Możesz użyć dowolnej biblioteki.
  • Wynik zależy od wielkości kodu , w bajtach. Najniższy wynik wygrywa.

Powodzenia!

notHalfBad
źródło
Wzór może być dowolny. Prawdopodobnie powinienem wspomnieć, że wzór nie musi mieć X, Y i Z, może mieć tylko X i Y. Te wzory są jednak tylko przykładami, więc możesz wymyślić własne przykłady z tymi wzorami.
notHalfBad
Co masz na myśli mówiąc, że „wzór istnieje”? Jako ciągły kawałek? Jako podciąg? Czy, powiedzmy, X i Y mogą oznaczać to samo?
xnor
@ xnor X i Y muszą być od siebie niezależne, a rozumiem przez istniejący wzorzec, że gdziekolwiek w ciągu znajduje się podciąg pasujący do wzorca. Dodam je do opisu wyzwania w celu wyjaśnienia.
notHalfBad
3
Związane z. (To samo, ale prosi o dokładne dopasowanie wzorca, a nie o podciągi).
Martin Ender
4
Więcej informacji: Czy wzór może być pusty? Wyszukiwany ciąg? Czy w ciągu wyszukiwania będą używane tylko małe litery? Czy wzorzec będzie alfabetycznie pierwszy spośród równoważnych wzorców, tj. Najpierw użyje X, a następnie Y, a następnie Z?
xnor

Odpowiedzi:

12

Perl 5 , 85 bajtów

Zaoszczędzono 40 bajtów dzięki sugestii Petera Taylora! (zobacz moją starszą wersję poniżej, aby zobaczyć różnice)

83 bajty kodu + -plflaga.

s/./$h{$&}?"\\$h{$&}":($h{$&}=$.,join("",map"(?!\\$_)",1..$.++)."(.)")/ge;$_=<>=~$_

Wypróbuj online!

XYXYZ jest przekształcany w ((?!\1).)((?!\1)(?!\2).)\1\2((?!\1)(?!\2)(?!\3).)(tak, niektóre testy nie mogą być prawdziwe, ale w ten sposób są krótsze), a następnie drugie wejście jest sprawdzane pod kątem tego wyrażenia regularnego. (zobacz wyjaśnienia mojej starszej wersji, aby uzyskać więcej intuicji, jak to działa)


Moja starsza wersja:
Podziękowania dla Arnaulda za wskazanie błędu, który popełniłem w mojej pierwszej wersji.
113 bajtów kodu + -plflagi i -Mre=eval.

s/./$h{$&}?"\\$h{$&}":($h{$&}=++$i,"(.)")/ge;$_.='(?{++$c;$\=1if!grep$v{$c}{${$_}}++,1..'.(keys%h).'})^';<>=~$_}{

Wypróbuj online!

Na przykład XYXYZ: (.) (.) (.) Pierwszy regex będzie przekształcić wzór do \ 1 \ 2 i dodać na końcu badania, aby sprawdzić, czy $1, $2i $3są różne: jeśli tak, to $\jest ustawiona na jeden. Następnie drugie wejście jest testowane względem tego wyrażenia regularnego i $\jest domyślnie drukowane na końcu.
Wyrażenie regularne wygenerowane dla XYXYZ to (.)(.)\1\2(.)(?{++$c;$\=1if!grep{$v{$c}{${$_}}++}1..3})^.
(Dodam trochę więcej szczegółów do wyjaśnień, kiedy będę miał chwilę)

Dada
źródło
Tak więc, używając wyrażenia regularnego, aby zmienić wyrażenie nie-wyrażeniowe na wyrażenie regularne? coolio
Matthew Roh
@Arnauld Rzeczywiście, dzięki. (Musiałem zbyt szybko przeczytać wyzwanie, moje złe). Musiałem podwoić liczbę bajtów, aby to naprawić, ale teraz działa!
Dada
Czy nie byłoby bardziej golfowe generowanie wyrażenia regularnego (.)((?!\1).)\1\2((?!\1)(?!\2).)?
Peter Taylor
@Peter Taylor może .. Niejasno o tym myślałem, ale wydawało mi się trudniejsze (więcej czytać) do wygenerowania. Spojrzę jeszcze raz, kiedy będę miał chwilę.
Dada
@Peter Taylor nieważne, będzie o 30 bajtów krótszy; Za chwilę to zaktualizuję, dziękuję :)
Dada
10

Galaretka , 9 bajtów

=þ
ẆÇ€ċÇ}

Zwraca liczbę przypadków znalezienia wzorca, przy czym niezerowe oznacza prawdę, a zero - fałsz.

Wypróbuj online!

Jak to działa

ẆÇ€ċÇ}  Main link. Left argument: s (string). Right argument: p (pattern)

Ẇ       Window; generate all substrings of s.
 ǀ     Map the helper link over the substrings.
    Ç}  Apply the helper link to p.
   ċ    Count the number of times the right result appears in the left result.


=þ      Helper link. Argument: t (string)

=þ      Compare all characters of t for equality with all characters of t, yielding
        a square matrix of Booleans.
Dennis
źródło
8

JavaScript (ES6), 94 bajty

f=
(p,s)=>s.match(p.replace(/./g,c=>m[c]||(t=r,r=`(?!\\${++g})`+r,m[c]=`\\`+g,t),g=m=[],r=`(.)`))
<div oninput=o.textContent=!!f(p.value,s.value)><input id=p placeholder=Pattern><input id=s placeholder=String><span id=o>

Działa poprzez przekształcenie wzorca w wyrażenie regularne, np. Do XYXYZgenerowania /(.)(?!\1)(.)\1\2(?!\2)(?!\1)(.)/.

Zauważam ciekawe rozróżnienie między wyrażeniami regularnymi PCRE i JavaScript: w PCRE \<n>nie udaje się (i dlatego się (?!\<n>)udaje) przed zdefiniowaniem grupy przechwytywania, podczas gdy JavaScript z powodzeniem dopasowuje pusty ciąg (i dlatego się (?!\<n>)nie udaje).

Neil
źródło
7

Python 2 , 70 bajtów

f=lambda p,s:s>''and(map(s.find,s[:len(p)])==map(p.find,p))|f(p,s[1:])

Wypróbuj online!

Sprawdza, czy łańcuch pasuje do wzorca przy użyciu metody opisanej w tej odpowiedzi . Używa prefiksu szukanego ciągu, którego długość jest równa wzorowi. Odcina pierwszy znak ciągu znaków, dopóki nie zostanie znalezione dopasowanie lub Falsestanie się puste


73 bajty:

f=lambda p,s:s>''and(map(s.find,s)==map(p.find,p))|f(p,s[1:])|f(p,s[:-1])

Wypróbuj online

Sprawdza, czy łańcuch pasuje do wzorca przy użyciu metody opisanej w tej odpowiedzi . Rekurencyjnie sprawdza wszystkie podciągi, rozgałęziając się w celu usunięcia pierwszego lub ostatniego znaku, aż łańcuch będzie pusty.

xnor
źródło
4

05AB1E , 19 16 bajtów

ÙœJv¹y…XYZ‡²åi1q

Wypróbuj online!


ÙœJ              # Get powerset of all unique characters in string.
   v             # Loop through each...
    ¹            # Push input word.
     y           # Push current set of letters in powerset.
      …XYZ‡      # Replace each of the 3 letters in the original word with XYZ.
           ²å    # Check if second input is in this string, push 1 if it is.
             i1q # If 1, push 1 and quit.

Zwróci 1, jeśli prawda, zero, jeśli nie prawda.


Może to być 14 bajtów, jeśli dozwolone jest zwracanie możliwych wartości XYZ:

05AB1E , 14 bajtów

ÙœJv¹y…XYZ‡²å—

Wypróbuj online 2!

Urna Magicznej Ośmiornicy
źródło
Zakładając, że niepusty łańcuch jest prawdziwy w 05AB1E i że pusty jest fałszem, twoja druga wersja powinna być zgodna ze specyfikacją.
Dennis
1
Błędny wynik na wejściach „abcd” i „XYZZ”. Musisz dodać czwartą literę jako podstawienie domyślne.
GB
@Dennis: Jeśli przejdziemy do meta postu, jedynymi prawdziwymi wartościami w 05AB1E są 1i True(co jest zwykle wadą dla tego rodzaju wyzwań), ale jeśli specyfikacja wyzwania może być interpretowana jako pozwalająca nam zdefiniować prawdę / fałsz dla wyzwania druga wersja działa tak, jak mówisz.
Emigna,
@Emigna Och, nie byłem tego świadomy.
Dennis
4

Java 7, 177 176 173 bajtów

Object c(String p,String s){int i=p.length();if(s.length()<i)return 0>1;for(;i-->0;)if(p.indexOf(p.charAt(i))!=s.indexOf(s.charAt(i)))return c(p,s.substring(1));return 1>0;}

Wyjaśnienie:

Object c(String p, String s){                             // Method with two String parameters and Object return-type
  int i = p.length();                                     //  Index that starts at the length of the pattern
  if(s.length() < i)                                      //  If the length of the input is smaller than the length of the pattern
    return 0>1;//false                                    //   Simply return false
  for(;i-->0;)                                            //  Loop from 0 to length_of_pattern
    if(p.indexOf(p.charAt(i)) != s.indexOf(s.charAt(i)))  //   If the index of the characters of the pattern and input aren't matching
     return c(p, s.substring(1));                         //    Return the recursive-call of pattern and input minus the first character
                                                          //  End of loop (implicit / single-line body)
  return 1>0;//true                                       //  If every index of the characters are matching: return true
}                                                         // End of method

Kod testowy:

Wypróbuj tutaj.

class M{
  static Object c(String p,String s){int i=p.length();if(s.length()<i)return 0>1;for(;i-->0;)if(p.indexOf(p.charAt(i))!=s.indexOf(s.charAt(i)))return c(p,s.substring(1));return 1>0;}

  public static void main(String[] a){
    System.out.println(c("XXYY", "succeed"));
    System.out.println(c("XXYY", "success"));
    System.out.println(c("XXYY", "balloon"));

    System.out.println(c("XYXYZ", "bananas"));
    System.out.println(c("XYXYZ", "banana"));
  }
}

Wydajność:

true
false
true
true
false
Kevin Cruijssen
źródło
4

PHP, 89 bajtów

Prezent od @Christoph i @Titus

for(;$v=$argv[1][$i++];)$r.=$$v?"\\".$$v:"(.)".!$$v=++$j;echo preg_match("#$r#",$argv[2]);

PHP, 105 bajtów

Prezent od @Christoph

foreach(str_split($argv[1])as$v)$r.=$x[$v]?"\\$x[$v]":"(.)".!$x[$v]=++$y;echo preg_match("#$r#",$argv[2]);

PHP, 167 bajtów

[,$a,$b]=$argv;foreach($s=str_split($a)as$v)$r[]=$k++>strpos($a,$v)?"\\".(1+array_search($v,array_keys(array_count_values($s)))):"(.)";echo preg_match(_.join($r)._,$b);
Jörg Hülsermann
źródło
1
Powinieneś być w stanie zaoszczędzić 2 bajty, używając ++$pzamiast ($p+1), chociaż tak naprawdę go nie testowałem.
user59178
1
Nie działa dla mnie: piaskownica . Zresztą golfed wersji kodu: [,$a,$b]=$argv;foreach(str_split($a)as$k=>$v)$r.=$k==($p=strpos($a,$v))?"(.)":"\\".++$p;echo preg_match("#$r#",$b);.
Christoph
1
Weź to jako prezent: [,$a,$b]=$argv;foreach(str_split($a)as$v)$r.=$x[$v]?"\\$x[$v]":'(.)'.!$x[$v]=++$y;echo preg_match("#$r#",$b);(Pamiętaj, że powinieneś zachować swoje stare wyniki <strike>)
Christoph
1
@Christoph A Gift był wysiłkiem naukowym związanym z !. To jest bardziej warte niż punkty, do których mógłbym dotrzeć z twoim fajnym rozwiązaniem.
Jörg Hülsermann
1
Liczę 109, a nie 108. -3 bajty, jeśli nie kopiujesz $argvdo $ai $b; -6 bajtów z for(;a&$v=$argv[1][$i++];); -1 bajt z dłuższymi nazwami zmiennych ( naprawdę! Use $vvzamiast $v, $iizamiast $i, $rrzamiast $r, $yyzamiast $ymożna użyć $$vvzamiast $x[$v])
Titus
4

C #, 184 165 155 bajtów

dzięki aloisdg!

bool c(string p,string n){for(int l=p.Length,i=0,j;i<l;i++)for(j=i;j>=0;)if(p[i]==p[j]==(n[i]!=n[j--]))return l!=n.Length&&c(p,n.Substring(1));return 2>1;}

rozwiązanie cofania, jako bonus działa ze wzorem z dowolnymi postaciami!

    public static bool c(string p,string n)
    {
        for (int l = p.Length, i = 0, j; i < l; i++)
            for (j = i; j >= 0;)
                if (p[i]==p[j]==(n[i]!=n[j--]))
                    return l != n.Length && c(p,n.Substring(1));
        return 2>1;
    }
downrep_nation
źródło
Właśnie zauważyłem, że
grałem w golfa, ujawniłem
2
Po pierwsze, dlaczego var s=l==n.Length;? Używasz go tylko w return s?!s:(gdzie !sjest zawsze false), więc możesz go zmienić na return l==n.Length?0>1:. Także, co to jest: (n[i]!=n[j]||n[i]!=n[j]). Sprawdzasz n[i]!=n[j]dwa razy .. Zawsze będzie true or true/ false or false..: S
Kevin Cruijssen
Podwójne sprawdzenie faktycznie pozostało z większego systemu, który zniknął podczas gry w golfa, więc użyto go dużo, idę go ulepszyć. Dzięki!
downrep_nation
Możesz dekalować wszystkie zmienne w jednym wierszuint l = p.Length,i = 0, j;
aloisdg mówi: Przywróć Monikę
Może przenieść twoją i++i twoją j--wewnątrz pętli for. na przykład:for(j=i;j>=0;)if(p[i]==p[j]==(n[i]!=n[j--]))
aloisdg mówi Przywróć Monikę
3

Rubin, 63 61 bajtów

->a,b{a.chars.permutation.any?{|w|a.tr((w|[])*'','XYZW')[b]}}

Zamiast szukać wzorca wyrażenia regularnego, po prostu spróbuj podstawić „X”, „Y” i „Z” na wszystkie możliwe sposoby i znaleźć dosłowne dopasowanie.

(Właściwie to ta sama koncepcja, co odpowiedź 05AB1E firmy carusocomputing)

GB
źródło
2

JavaScript (ES6), 92 89 87 86 bajtów

Pobiera dane wejściowe p(wzorzec) i s(ciąg) w składni curry (p)(s). Zwraca 0/ 1.

p=>g=s=>s&&g(s.slice(1))|[...p].every((C,i,x)=>C==(x[c=s[i]]=x[c]||'XYZ'[c&&j++]),j=0)

Sformatowane i skomentowane

p =>                             // main function: takes pattern p as input, returns g
  g = s =>                       // g = recursive function: takes string s as input
    s &&                         // if s is not empty:
      g(s.slice(1))              //   do a recursive call, starting at the next character
    |                            // merge the result with this iteration
    [...p].every((C, i, x) =>    // for each character C at position i in p:
      C ==                       //   check whether C is matching the next expected
      (                          //   character, which is either:
        x[c = s[i]] = x[c] ||    //   - a substitution character already associated to s[i]
        'XYZ'[c && j++]          //   - the next substitution character ('X', 'Y' or 'Z')
      ),                         //   - undefined if c = s[i] doesn't exist or j > 2
      j = 0                      //   initialize j = pointer in 'XYZ'
    )                            //

Przypadki testowe

let f =

p=>g=s=>s&&g(s.slice(1))|[...p].every((C,i,x)=>C==(x[c=s[i]]=x[c]||'XYZ'[c&&j++]),j=0)

console.log(f("XXYY")("succeed"))   // 1
console.log(f("XXYY")("success"))   // 0
console.log(f("XXYY")("balloon"))   // 1
console.log(f("XYXYZ")("bananas"))  // 1
console.log(f("XYXYZ")("banana"))   // 0

Arnauld
źródło
0

Matematyka 18 znaków (nie licząc łańcucha i wzoru)

StringContainsQ[string,pattern]

Przykłady:

StringContainsQ["succeed", x_ ~~ x_ ~~ y_ ~~ y_]

True

StringContainsQ["bananas", x_ ~~ y_ ~~ x_ ~~ y_ ~~ z_]

True

Witalij Kaurow
źródło
Jest to nieprawidłowe, ponieważ nie przyjmuje ciągu i wzorca jako danych wejściowych ciągu, jeśli jest to wymagane.
lirtosiast