Tantangan golf kode sederhana: Pola karakter!

22

Dalam tantangan ini, Anda menerima string sebagai input yang berisi string X, Y, dan Z misalnya. "XYZZ". X, Y dan Z mewakili karakter tertentu. Pola ini kemudian dibandingkan dengan input string kedua. Jika pola ada sebagai substring pada input kedua, kembali True, jika tidak, kembali False. Setelah pola ditemukan dalam kata, program berhenti mencari dan kembali True.

Contohnya

Pola: "XXYY"

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

Pola: "XYXYZ"

bananas ---> True (pattern found: nanas)
banana  ---> False (pattern not found)
  • Catatan: Ini bukan input yang sebenarnya. Ini adalah contoh bagaimana program seharusnya bekerja. Program Anda harus menampilkan Trueatau False, atau nilai-nilai Kebenaran / Kepalsuan lainnya.

Informasi penting / bermanfaat lainnya

  • Polanya tidak perlu mengandung X, Y dan Z, itu bisa berisi X dan Y atau bahkan (walaupun agak tidak ada gunanya) hanya X.
  • Polanya tidak boleh kosong, tetapi ini tidak akan digunakan sebagai kasus uji.
  • String pencarian tidak akan kosong, dan akan menjadi huruf kecil.
  • Urutan alfabet X, Y dan Z dalam pola tidak masalah.
  • X, Y dan Z harus berupa karakter unik.
  • Anda dapat menggunakan perpustakaan apa pun yang Anda inginkan.
  • Skor ditentukan oleh ukuran kode , dalam byte. Skor terendah menang.

Semoga berhasil!

notHalfBad
sumber
Polanya bisa apa saja. Saya mungkin seharusnya mengatakan bahwa polanya tidak harus memiliki X, Y, dan Z, bisa saja hanya X dan Y. Pola-pola itu hanya contoh, jadi, merasa bebas untuk membuat sendiri. contoh dengan pola tersebut.
notHalfBad
Apa maksudmu "polanya ada"? Sebagai potongan yang berdekatan? Sebagai substring? Bisakah, katakanlah, X dan Y berarti hal yang sama?
xnor
@ xnor X dan Y harus independen satu sama lain, dan apa yang saya maksud dengan pola yang ada adalah bahwa di mana pun di string ada substring yang cocok dengan pola. Saya akan menambahkan ini ke deskripsi tantangan saya untuk memperjelas.
notHalfBad
3
Terkait (Hal yang sama, tetapi meminta kecocokan yang tepat dari pola, bukan untuk substring.)
Martin Ender
4
Lebih detail: Bisakah polanya kosong? String pencarian? Apakah string pencarian hanya menggunakan huruf kecil? Apakah pola akan menjadi abjad pertama di antara pola yang setara, yaitu menggunakan X pertama kemudian Y kemudian Z?
xnor

Jawaban:

12

Perl 5 , 85 byte

Disimpan 40 byte berkat saran Peter Taylor! (lihat versi lama saya di bawah untuk melihat perbedaannya)

83 byte kode + -plbendera.

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

Cobalah online!

XYXYZ ditransformasikan menjadi ((?!\1).)((?!\1)(?!\2).)\1\2((?!\1)(?!\2)(?!\3).)(yup, beberapa tes tidak mungkin benar, tetapi lebih pendek seperti itu), dan input kedua kemudian diperiksa terhadap regex itu. (lihat penjelasan versi lama saya untuk mendapatkan lebih banyak intuisi tentang cara kerjanya)


Versi saya yang lebih lama:
Terima kasih kepada Arnauld karena menunjukkan kesalahan yang saya buat di versi pertama saya.
113 byte kode + -plbendera, dan -Mre=eval.

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

Cobalah online!

Pada contoh XYXYZ: regex pertama akan mengubah pola menjadi (.) (.) \ 1 \ 2 (.), Dan menambahkan pada akhir tes untuk memeriksa apakah $1, $2dan $3berbeda: jika demikian, $\disetel ke satu. Kemudian, input kedua adalah testis terhadap regex ini, dan $\dicetak secara implisit di akhir.
Regex yang dihasilkan untuk XYXYZ adalah (.)(.)\1\2(.)(?{++$c;$\=1if!grep{$v{$c}{${$_}}++}1..3})^.
(Saya akan menambahkan sedikit detail pada penjelasan ketika saya punya waktu sebentar)

Dada
sumber
Jadi, Menggunakan regex untuk mengubah non-regex ke regex? coolio
Matthew Roh
@Arnauld Memang, terima kasih. (Saya harus membaca tantangan terlalu cepat, buruk saya). Harus menggandakan bytecount untuk memperbaikinya, tetapi berhasil sekarang!
Dada
Bukankah golfier untuk menghasilkan regex seperti (.)((?!\1).)\1\2((?!\1)(?!\2).)?
Peter Taylor
@ Peter Taylor mungkin .. Saya samar-samar memikirkannya, tapi sepertinya lebih sulit (baca lebih lama) untuk menghasilkan .. Saya akan melihat lagi ketika ada waktu.
Dada
@Peter Taylor nevermind, itu akan menjadi 30 byte lebih pendek; Saya akan memperbarui itu sedikit, terima kasih :)
Dada
10

Jelly , 9 byte

=þ
ẆÇ€ċÇ}

Mengembalikan berapa kali polanya ditemukan, bukan nol menjadi benar dan nol menjadi palsu.

Cobalah online!

Bagaimana itu bekerja

ẆÇ€ċÇ}  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
sumber
8

JavaScript (ES6), 94 byte

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>

Bekerja dengan mengubah pola menjadi regexp, misalnya untuk XYXYZmenghasilkan /(.)(?!\1)(.)\1\2(?!\2)(?!\1)(.)/.

Saya melihat perbedaan yang menarik antara PCRE dan JavaScript regexp: di PCRE, \<n>gagal (dan karenanya (?!\<n>)berhasil) sebelum grup tangkap didefinisikan, sementara JavaScript berhasil mencocokkan string kosong (dan karenanya (?!\<n>)gagal).

Neil
sumber
7

Python 2 , 70 byte

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

Cobalah online!

Periksa apakah string cocok dengan pola menggunakan metode dalam jawaban ini . Menggunakan awalan string pencarian yang panjangnya sama dengan pola. Memotong karakter pertama dari string string hingga kecocokan ditemukan, atau Falsejika menjadi kosong


73 byte:

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

Cobalah online

Periksa apakah string cocok dengan pola menggunakan metode dalam jawaban ini . Secara rekursif memeriksa semua substring dengan bercabang untuk menghapus karakter pertama atau terakhir hingga string kosong.

Tidak
sumber
6

Python 3 , 100 byte

l=len
f=lambda p,s:l(p)<=l(s)and(l({*zip(p,s)})==l({*p})==l({s for _,s in{*zip(p,s)}})or f(p,s[1:]))

Cobalah online!

ovs
sumber
4

05AB1E , 19 16 byte

ÙœJv¹y…XYZ‡²åi1q

Cobalah 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.

Akan mengembalikan 1 jika benar, nol jika tidak benar.


Ini bisa 14 byte jika mengembalikan nilai XYZ yang dimungkinkan diizinkan:

05AB1E , 14 byte

ÙœJv¹y…XYZ‡²å—

Cobalah online 2!

Guci Gurita Ajaib
sumber
Dengan asumsi bahwa string yang tidak kosong benar di 05AB1E dan yang kosong adalah palsu, versi kedua Anda harus mematuhi spesifikasi.
Dennis
1
Hasil yang salah pada input "abcd" dan "XYZZ". Anda perlu menambahkan huruf keempat sebagai pengganti default.
GB
@ Dennis: Jika kita menggunakan meta post , satu-satunya nilai kebenaran di 05AB1E adalah 1dan True(yang biasanya merupakan kelemahan untuk tantangan semacam ini), tetapi jika spec tantangan dapat diartikan sebagai memungkinkan kita untuk mendefinisikan kebenaran / kepalsuan untuk tantangan tersebut versi kedua berfungsi seperti yang Anda katakan.
Emigna
@ Emigna Oh, saya tidak menyadarinya.
Dennis
4

Java 7, 177 176 173 byte

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;}

Penjelasan:

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

Kode uji:

Coba di sini.

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"));
  }
}

Keluaran:

true
false
true
true
false
Kevin Cruijssen
sumber
4

PHP, 89 Bytes

Hadiah dari @Christoph dan @Titus

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

PHP, 105 Bytes

Hadiah dari @Christoph

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

PHP, 167 Bytes

[,$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
sumber
1
Anda harus dapat menyimpan 2 byte dengan menggunakan ++$palih-alih ($p+1), meskipun saya belum benar-benar mengujinya.
user59178
1
Tidak bekerja untuk saya: Sandbox . Pokoknya versi kode golfed: [,$a,$b]=$argv;foreach(str_split($a)as$k=>$v)$r.=$k==($p=strpos($a,$v))?"(.)":"\\".++$p;echo preg_match("#$r#",$b);.
Christoph
1
Ambil ini sebagai hadiah: [,$a,$b]=$argv;foreach(str_split($a)as$v)$r.=$x[$v]?"\\$x[$v]":'(.)'.!$x[$v]=++$y;echo preg_match("#$r#",$b);(Perhatikan bahwa Anda harus menyimpan skor lama Anda menggunakan <strike>)
Christoph
1
@Christoph A Hadiah adalah upaya belajar dengan !. Lebih bernilai daripada poin yang bisa saya raih dengan solusi bagus Anda.
Jörg Hülsermann
1
Aku menghitung 109, bukan 108. -3 byte jika Anda tidak copy $argvke $adan $b; -6 byte dengan for(;a&$v=$argv[1][$i++];); -1 byte dengan nama variabel lagi ( memang! : Gunakan $vvbukan $v, $iibukan $i, $rrbukan $r, $yybukan $ydan Anda dapat menggunakan $$vvbukannya $x[$v])
Titus
4

C #, 184 165 155 byte

terima kasih 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;}

solusi mundur, sebagai bonus itu bekerja dengan pola dengan karakter apa pun!

    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
sumber
Saya hanya melihat golf itu terkena logika saya tidak menggunakan, akan segera memperbarui
downrep_nation
2
Pertama-tama, mengapa var s=l==n.Length;? Anda hanya menggunakannya di return s?!s:( di mana !sselalu false), sehingga dapat diubah menjadi return l==n.Length?0>1:. Juga, apa ini: (n[i]!=n[j]||n[i]!=n[j]). Anda memeriksa n[i]!=n[j]dua kali .. Ini akan selalu menjadi true or true/ false or false..: S
Kevin Cruijssen
Pemeriksaan ganda sebenarnya tersisa dari sistem yang lebih besar jika hilang dalam bermain golf, jadi sudah banyak digunakan, saya akan memperbaikinya lebih lanjut. Terima kasih!
downrep_nation
Anda dapat mendekor ulang semua variabel Anda dalam satu barisint l = p.Length,i = 0, j;
aloisdg mengatakan Reinstate Monica
Dapat memindahkan Anda i++dan j--bagian dalam Anda untuk loop. misalnya:for(j=i;j>=0;)if(p[i]==p[j]==(n[i]!=n[j--]))
aloisdg mengatakan Reinstate Monica
3

Ruby, 63 61 byte

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

Alih-alih mencari pola regex, coba ganti 'X', 'Y' dan 'Z' dengan semua cara yang mungkin, dan temukan kecocokan literal.

(Sebenarnya konsep yang sama dengan jawaban 05AB1E carusocomputing)

GB
sumber
2

JavaScript (ES6), 92 89 87 86 byte

Membawa input p(pola) dan s(string) dalam sintaks currying (p)(s). Pengembalian 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)

Diformat dan dikomentari

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'
    )                            //

Uji kasus

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
sumber
0

Mathematica 18 karakter (tidak termasuk string & pola)

StringContainsQ[string,pattern]

Contoh:

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

True

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

True

Vitaliy Kaurov
sumber
Ini tidak valid karena tidak mengambil string dan pola sebagai input string yang diperlukan.
lirtosiast