Jendela Pangrammatik Terpendek


15

Pangram adalah kalimat atau kutipan yang berisi semua dua puluh enam huruf alfabet, seperti yang ditunjukkan dalam tantangan golf kode ini . Namun, jendela pangrammatic adalah pangram dalam bentuk beberapa segmen teks, yang mungkin berakhir atau dimulai setengah kata, ditemukan di suatu tempat dalam karya yang lebih besar. Ini secara alami terjadi di mana-mana, menjadi himpunan bagian yang tepat dari pangram sejati, jadi hanya memverifikasi jika sesuatu yang berisi jendela pangrammatik akan membosankan dan juga sebelumnya dilakukan.

Jadi, kami tertarik untuk menemukan yang terkecil di bagian teks yang diberikan berdasarkan panjang hurufnya! Dalam kode sesingkat mungkin dalam byte, tentu saja, agar sesuai dengan tema.

Aturan dan Pedoman

  • Terima string sebagai input dan kembalikan string jendela pangrammatic terkecil di input jika ada. Jika tidak ada, kembalikan Boolean False atau string kosong.
  • Apakah string adalah jendela pangrammatik atau tidak, tidak peka huruf besar-kecil dan hanya tergantung pada 26 huruf, bukan tanda baca atau angka atau simbol aneh lainnya.
  • Demikian pula, panjang huruf jendela pangrammatik adalah jumlah total berapa banyak penampilan huruf terjadi di dalamnya saja, dan bukan hanya jumlah setiap karakter. Nilai yang dikembalikan harus terkecil berdasarkan jumlah ini. Bagaimanapun, kita adalah ahli bahasa, bukan programmer.
  • Akan tetapi, output dari jendela pangrammatik harus merupakan substring yang tepat dari input, yang mengandung huruf besar dan tanda baca yang sama, dll.
  • Jika ada beberapa jendela pangrammatik terpendek dengan panjang huruf yang sama, kembalikan salah satunya.

Uji Kasus

'This isn't a pangram.'
==> False

'Everyone knows about that infamous Quick-Brown-Fox (the one who jumped over some lazy ignoramus of a dog so many years ago).'
==> 'Quick-Brown-Fox (the one who jumped over some lazy ig'

'"The five boxing wizards jump quickly." stated Johnny, before beginning to recite the alphabet with a bunch of semicolons in the middle. "ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ!" he shouted to the heavens.'
==> 'ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ'

1
Untuk kasus uji terakhir, mengapa tidak The five boxing wizards jump quicklydikembalikan?
Biru

1
Untuk kasus kedua, apakah Anda mengizinkan ruang sebelum Q? Itu tidak menambah jumlah surat.
Neil

2
@muddyfish Karena memiliki 31 huruf, sedangkan output yang diharapkan hanya 26.
Martin Ender

4
Pertanyaan pertama yang bagus!
R

2
Ya. Tidak ada alasan yang seharusnya. Mengambil minimum "benar" dalam semangat pertanyaan, tetapi itu tidak perlu.
Reecer6

Jawaban:


6

Pyth, 20 16 14 byte

hol@GNf!-GrT0.:

Penjelasan:

             .: - substrings of input()
      f!-GrT0   - filter to ones which contain the alphabet
 ol@GN          - sort by number of alphabetical chars
h               - ^[0]

      f!-GrT0   - filter(lambda T:V, substrings)
          rT0   -    T.lower()
        -G      -   alphabet-^
       !        -  not ^

 o              - sort(^, lambda N:V)
   @GN          -   filter_presence(alphabet, N)
  l             -  len(^)

Coba di sini!

Ketika tidak ada solusi yang benar, program keluar dengan kesalahan tanpa output ke stdout.


Tampaknya Anda belum memperbarui kode di blok kode pertama. !-GrT0Saya percaya juga lebih pendek untuk kondisi filter. Saya juga berpikir Anda perlu luntuk membuat pekerjaan semacam itu dengan benar.
FryAmTheEggman

Oh, saya salah bicara, maksud saya tautannya. Di tautan Anda, Anda masih memiliki l, dan tanpa itu Anda mendapatkan hasil yang berbeda . Saya percaya masalahnya adalah surat yang diulang, tapi saya tidak 100% yakin.
FryAmTheEggman

Jadi itu penting - dan terima kasih untuk optimasi!
Biru


2

Ruby, 100 byte

Mengembalikan nil jika tidak ada jendela yang ditemukan.

->s{r=0..s.size
(r.map{|i|s[i,r.find{|j|(?a..?z).all?{|c|s[i,j]=~/#{c}/i}}||0]}-['']).min_by &:size}

2

JavaScript (ES6), 139 138 136 byte

s=>[r=l="",...s].map((_,b,a)=>a.map((c,i)=>i>b&&(t+=c,z=parseInt(c,36))>9&&(v++,n+=!m[z],m[z]=n<26||l&&v>l||(r=t,l=v)),t=m=[],v=n=0))&&r

Disimpan 2 byte berkat @Neil!

Bertakuk

var solution =

s=>
  [r=l="",...s].map((_,b,a)=> // b = index of start of window to check
    a.map((c,i)=>
      i>b&&(
        t+=c,
        z=parseInt(c,36)
      )>9&&(
        v++,
        n+=!m[z],
        m[z]=
          n<26||
          v>l&&l||(
            r=t,
            l=v
          )
      ),
      t=m=[],
      v=n=0
    )
  )
  &&r
<textarea cols="70" rows="6" id="input">Everyone knows about that infamous Quick-Brown-Fox (the one who jumped over some lazy ignoramus of a dog so many years ago).</textarea><br /><button onclick="result.textContent=solution(input.value)">Go</button><pre id="result"></pre>


Bisakah kamu tidak menggunakan [r=l="",...s].map((_,b,a)=>?
Neil

@Neil Terima kasih, saya selalu lupa tentang parameter ketiga dalam mapfungsi.
user81655

Saya pikir @ edc65 dapat mengalahkan ini, saya menggabungkan kode untuk substring yang meledak dengan itu untuk tester pangram dan berakhir dengan fungsi 134 byte.
Neil

Sejauh ini yang terbaik adalah 142
edc65

Sayangnya saya tidak berpikir untuk menyimpannya dan PC saya crash jadi sekarang saya tidak tahu apa yang saya miliki; yang terbaik yang bisa saya lakukan sekarang adalah 138 byte.
Neil

2

PowerShell v2 +, 218 byte

param($a)$z=@{};(0..($b=$a.length-1)|%{($i=$_)..$b|%{-join$a[$i..$_]}})|%{$y=$_;$j=1;65..90|%{$j*=$y.ToUpper().IndexOf([char]$_)+1};if($j){$z[($y-replace'[^A-Za-z]').Length]=$y}}
($z.GetEnumerator()|sort Name)[0].Value

Ya, manipulasi substring (tidak ada built-in) tidak benar-benar setelan kuat PowerShell ...

Kami mengambil input param($a)dan menetapkan hashtable kosong yang baru $z. Ini akan menjadi tempat penyimpanan kami untuk substring pangrammatic kandidat.

Menggunakan sedikit modifikasi pada kode saya dari Exploded Substrings , kami membangun semua substring dari input. Yap, bahkan substring hanya tanda baca satu karakter. Ini adalah , bukan . ;-)

Semua substring tersebut dienkapsulasi dalam parens dan disalurkan ke loop lain dengan |%{...}. Kami sementara mengatur $yuntuk substring kami saat ini, mengatur counter helper $j, dan memulai loop lain 65..90|%{...}, dengan mudah di atas kode karakter ASCII untuk huruf kapital. Setiap loop batin, kita ambil $y, buat semuanya huruf besar, dan tarik .IndexOfkarakter khusus itu. Karena ini akan kembali -1jika tidak ditemukan, kami +1hasil sebelum mengalikannya menjadi $j. Ini memastikan bahwa jika satu karakter tidak ditemukan, $jakan sama dengan nol.

Itulah tepatnya iftentang semua itu. Jika $jtidak nol, itu berarti bahwa setiap huruf ditemukan setidaknya satu kali dalam substring $y, jadi kita perlu menambahkannya ke kumpulan kandidat kami. Kami melakukannya dengan mengambil $ydan -replacememasukkan setiap non-huruf tanpa apa-apa, yang membuat kami sepanjang huruf dari substring itu. Kami menggunakannya sebagai indeks ke hashtable $zdan menyimpan $ydi indeks itu. Ini memiliki kekhasan menimpa substring dengan panjang huruf yang sama dengan yang terjadi "paling jauh" dalam string asli, tetapi itu diizinkan oleh aturan, karena kami hanya peduli tentang panjang huruf.

Akhirnya, kita perlu memilah $zdan menarik keluar yang terkecil. Kita harus menggunakan .GetEnumeratorpanggilan untuk mengurutkan objek di dalam $z , lalu sortyang di Name(yaitu, indeks panjang dari atas), memilih yang [0]ke-1 (yaitu, yang terpendek), dan mengeluarkan .Value(yaitu, substring). Jika tidak ada substring yang cocok, ini akan melemparkan kesalahan ( Cannot index into a null array) ketika mencoba untuk mengindeks $z, dan tidak menghasilkan apa-apa, yang merupakan kesalahan dalam PowerShell. (test case ketiga di bawah ini memiliki pemeran eksplisit [bool]untuk menunjukkan ini)

Uji Kasus

PS C:\Tools\Scripts> .\golfing\shortest-pangrammatic-window.ps1 '"The five boxing wizards jump quickly." stated Johnny, before beginning to recite the alphabet with a bunch of semicolons in the middle. "ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ!" he shouted to the heavens.'
ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ!" 

PS C:\Tools\Scripts> .\golfing\shortest-pangrammatic-window.ps1 'Everyone knows about that infamous Quick-Brown-Fox (the one who jumped over some lazy ignoramus of a dog so many years ago).'
Quick-Brown-Fox (the one who jumped over some lazy ig

PS C:\Tools\Scripts> [bool](.\golfing\shortest-pangrammatic-window.ps1 "This isn't a pangram.")
Cannot index into a null array.
At C:\Tools\Scripts\golfing\shortest-pangrammatic-window.ps1:2 char:1
+ ($z.GetEnumerator()|sort Name)[0].Value
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

False

2

Haskell, 180 byte

Ini sulit, tetapi sangat menyenangkan tanpa impor.

l=['a'..'z']
u=['A'..'Z']
f&[]=[];f&x=x:f&f x
g#h=(.g).h.g
f x|v<-[y|y<-(tail&)=<<(init&x),and$zipWith((`elem`y)#(||))l u]=last$[]:[z|z<-v,all((length.filter(`elem`l++u))#(<=)$z)v]

Apalagi golf:

lowerCase = ['a'..'z']
upperCase = ['A'..'Z']

f & x = takeWhile (not . null) $ iterate f x

(#) = flip on

subStrings x = (tail &) =<< (init & x)

pangram p = and $ zipWith ((`elem` p) # (||)) lowerCase upperCase

leqLetters x y = (length . filter (`elem` lowerCase ++ upperCase)) # (<=)

fewestLetters xs = [ x | x <- xs, all (leqLetters x) xs]

safeHead [] = ""
safeHead xs = head xs

f x = safeHead . fewestLetters . filter pangram . subStrings

Kejutan, kejutan: ini sangat lambat.


2

Oracle SQL 11.2, 461 byte

WITH s AS (SELECT SUBSTR(:1,LEVEL,1)c,LEVEL p FROM DUAL CONNECT BY LEVEL<=LENGTH(:1)),v(s,f,l)AS(SELECT c,p,p FROM s UNION ALL SELECT s||c,f,p FROM v,s WHERE p=l+1),c AS(SELECT CHR(96+LEVEL)c FROM DUAL CONNECT BY LEVEL<27),a AS(SELECT LISTAGG(c)WITHIN GROUP(ORDER BY 1) a FROM c)SELECT MIN(s)KEEP(DENSE_RANK FIRST ORDER BY LENGTH(s)-NVL(LENGTH(TRANSLATE(LOWER(s),' '||a,' ')),0))FROM(SELECT s,f,SUM(SIGN(INSTR(LOWER(s),c)))x FROM v,c GROUP BY s,f),a WHERE x=26;

Tidak bermain golf

WITH s AS (SELECT SUBSTR(:1,LEVEL,1)c,LEVEL p FROM DUAL CONNECT BY LEVEL<=LENGTH(:1))
,v(s,f,l) AS
(
  SELECT c,p,p FROM s
  UNION ALL
  SELECT s||c,f,p FROM v,s WHERE p=l+1 
)
,c AS(SELECT CHR(96+LEVEL)c FROM DUAL CONNECT BY LEVEL<27)
,a AS(SELECT LISTAGG(c)WITHIN GROUP(ORDER BY 1) a FROM c)
SELECT MIN(s)KEEP(DENSE_RANK FIRST ORDER BY LENGTH(s)-NVL(LENGTH(TRANSLATE(LOWER(s),' '||a,' ')),0))
FROM(SELECT s,f,SUM(SIGN(INSTR(LOWER(s),c)))x FROM v,c GROUP BY s,f),a
WHERE x=26

Itu s tampilan membagi masukan dalam karakter dan juga mengembalikan posisi masing-masing karakter.

Tampilan rekursif vmengembalikan setiap substring dari input
s adalah substring
f posisi karakter pertama dari substring
l posisi karakter terakhir ditambahkan ke substring saat ini

Itu c tampilan mengembalikan alfabet, satu huruf pada suatu waktu

The atampilan mengembalikan alfabet bersambung sebagai satu string

SELECT s,f,SUM(SIGN(INSTR(LOWER(s),c))
Pengembalian untuk setiap substring jumlah huruf berbeda yang ada di dalamnya
INSTRmengembalikan posisi huruf dalam substring, 0 jika tidak ada
SIGNmengembalikan 1 jika pos> 0, 0 jika pos = 0

WHERE x=26
Memfilter substring yang berisi seluruh alfabet

TRANSLATE(LOWER(s),' '||a,' ')
Menghapus setiap huruf dari substring

LENGTH(s)-NVL(LENGTH(TRANSLATE(LOWER(s),' '||a,' ')
Panjang dalam huruf adalah panjang substring dikurangi panjang subtring tanpa huruf

SELECT MIN(s)KEEP(DENSE_RANK FIRST ORDER BY LENGTH(s)-NVL(LENGTH(TRANSLATE(LOWER(s),' '||a,' ')),0))
Hanya menyimpan substring dengan jumlah huruf yang lebih kecil.
Jika ada lebih dari satu, yang pertama, diurutkan sebagai string naik, disimpan


2

Python 3, 171, 167, 163, 157 , 149 byte.

Disimpan 4 byte berkat DSM.
Disimpan 8 byte berkat RootTwo.

lambda x,r=range:min([x[i:j]for i in r(len(x))for j in r(len(x))if{*map(chr,r(65,91))}<={*x[i:j].upper()}]or' ',key=lambda y:sum(map(str.isalpha,y)))

Harus mengurutkan berdasarkan jumlah surat membunuh saya.

Kasus uji:

assert f("This isn't a pangram.") == ' '
assert f("Everyone knows about that infamous Quick-Brown-Fox (the one who jumped over some lazy ignoramus of a dog so many years ago).") == ' Quick-Brown-Fox (the one who jumped over some lazy ig', f("Everyone knows about that infamous Quick-Brown-Fox (the one who jumped over some lazy ignoramus of a dog so many years ago).")
assert f('"The five boxing wizards jump quickly." stated Johnny, before beginning to recite the alphabet with a bunch of semicolons in the middle. "ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ!" he shouted to the heavens.') == '. "ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ', f('"The five boxing wizards jump quickly." stated Johnny, before beginning to recite the alphabet with a bunch of semicolons in the middle. "ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ!" he shouted to the heavens.')

Jangan pikir .upper()dibutuhkan dalam fungsi kunci.
RootTwo

@ BootTwo Ups, ya, Anda benar. Terima kasih.
Morgan Thrapp

1

PowerShell (v4), 198 156 byte

param($s)
-join(@(1..($y=$s.Length)|%{$w=$_
0..$y|%{(,@($s[$_..($_+$w)]))}}|?{($_-match'[a-z]'|sort -U).Count-eq26}|sort -Pr {($_-match'[a-z]').count})[0])


# Previous 198 byte golf
$a,$b,$c=@(1..($s="$args").Length|%{$w=$_
0..($s.Length-$w)|%{if((($t=$s[$_..($_+$w)]-match'[a-z]')|sort -u).Count-eq26){(,@($t.Length,$_,$w))}}}|sort -pr{$_[0]})[0]
(-join($s[$b..($b+$c)]),'')[!$a]

Uji Kasus

PS C:\> .\PangramWindow.ps1 "This isn't a pangram."


PS C:\> .\PangramWindow.ps1 'Everyone knows about that infamous Quick-Brown-Fox (the one who jumped over some lazy ignoramus of a dog so many years ago).'
Quick-Brown-Fox (the one who jumped over some lazy ig

PS C:\> .\PangramWindow.ps1 '"The five boxing wizards jump quickly." stated Johnny, before beginning to recite the alphabet with a bunch of semicolons in the middle. "ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ!" he shouted to the heavens.'
ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ!

Penjelasan asli dari aslinya

Ini adalah loop bersarang yang kuat yang membuat jendela geser dari semua ukuran:

.SubString(0, 1) -> slide window over the string
.SubString(0, 2) -> slide window over the string
..
.SubString(0, string.Length) -> slide window over the string

Untuk setiap jendela, ini memfilter hanya huruf (pencocokan regex case sensitif secara default), menjalankan karakter yang tersisa melalui filter unik, memeriksa apakah ada 26 karakter unik sebagai tes pangram.

Semua jendela dengan pangram diubah menjadi kembar tiga dari (jumlah huruf termasuk dupes, indeks mulai, panjang jendela termasuk tanda baca) , yang disortir untuk menemukan yang terpendek berdasarkan jumlah karakter keseluruhan, yang pertama diambil, dan string keluaran dibangun dari itu .

Ada banyak pengindeksan di luar batas string, yang PowerShell bermanfaat mengembalikan $ null, alih-alih melemparkan pengecualian.

NB. yang baru 156 byte adalah pendekatan yang sama, tetapi ditulis ulang untuk menggunakan pipa lebih banyak.

$string = "$args"

# increasing window widths, outer loop
$allPangramWindows =  foreach ($windowWidth in 1..$string.Length) {

    # sliding windows over string, inner loop
    0..($string.Length - $windowWidth) | ForEach {

        # slice window out of string, returns a char array
        $tmp = $string[$_..($_+$windowWidth)]

        # filter the char array to drop not-letters
        $tmp = $tmp -match '[a-z]'

        # Drop duplicate letters
        $tmpNoDupes = $tmp | sort -Unique

        # If we're left with a 26 character array, this is a pangrammatic window. Output
        # a PowerShell-style tuple of count of letters, start index, width.
        if($tmpNoDupes.Count -eq 26){
            (,@($tmp.Length,$_,$windowWidth))
        }
    }
}

# Force the result into an array (to handle no-results), sort it
# by the first element (num of letters in the window, total)
$allPangramWindows = @( $allPangramWindows | sort -Property {$_[0]} )

# take element 0, a window with the fewest letters
$windowCharCount, $windowStart, $WindowEnd = $allPangramWindows[0]

# uses the results to find the original string with punctuation and whitespace
if ($windowLen) {
    $string[$windowStart..($windowStart + $windowLen)] -join ''
}

NB. tidak yakin versi ungolfed bekerja, karena saya tidak menulis itu maka golf, itu hanya untuk penjelasan.


0

Haskell, 123 byte

import Data.Lists
import Data.Char
h x=take 1$sortOn((1<$).filter isAlpha)[e|e<-powerslice x,['a'..'z']\\map toLower e==""]

Menentukan fungsi h, yang mengembalikan daftar kosong jika tidak ada jendela pangrammatic atau daftar satu elemen dengan jendela minimum. Contoh penggunaan:

*Main>  h "'The five boxing wizards jump quickly.' stated Johnny, before beginning to recite the alphabet with a bunch of semicolons in the middle. 'ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ!' he shouted to the heavens."
[". 'ABCDEFGHI;;;;;;;;;;;;;;;JKLMNOPQRSTUVWXYZ"]

Bagaimana itu bekerja:

          [e|e<-powerslice x                  ]  -- for all continuous subsequences
                                                 -- e of the input  
                ,['a'..'z']\\map toLower e==""   -- keep those where the list
                                                 -- difference with all letters is
                                                 -- empty, i.e. every letter appears
                                                 -- at least once
    sortOn((1<$).filter isAlpha)                 -- sort all remaining lists on
                                                 -- their length after removing all
                                                 -- non-letters -> (1<$) see below
take 1                                           -- take the first, i.e. the minimum


calculating the length of a list: we're not interested in the length itself, but
in the relative order of the length. (1<$) replaces each element in a list with
the number 1, e.g. "abc" -> "111", "abcd" -> "1111", etc. Such '1'-strings have
the same order as the length of the original list. One byte saved!
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.