Найкоротше Панграматичне вікно


15

Панграма - це речення або уривок, який містить усі двадцять шість букв алфавіту, як показано в цьому кодовому виклику для гольфу . Однак вікно панграматики - це панграма у вигляді деякого відрізка тексту, який може закінчуватися або починатися на півдорозі слова, знайдений десь у межах більшого твору. Вони, природно, зустрічаються скрізь, будучи належними підмножинами справжніх панограм, тому просто перевірка, чи щось містить панграматичне вікно, буде нудною, а також це було зроблено раніше.

Отже, нам цікаво знайти найменший з них у даному фрагменті тексту, виходячи з його довжини букви! У найкоротшій мірі код у байтах, звичайно, підходити під тему.

Правила та вказівки

  • Отримайте рядок як вхідний і поверніть рядок найменшого панграматичного вікна на вході, якщо такий є. Якщо цього немає, поверніть або булеву помилку, або порожню рядок.
  • Незалежно від того, чи є рядок панграматичним вікном, він не відрізняється від регістру і залежить лише від 26 букв, а не будь-яких пунктуаційних чи цифр чи інших непарних символів.
  • Аналогічним чином , pangrammatic вікна довжина листа загальне число , як багато появ букв відбувається лише в ньому, а не просто кількість кожного символу. Повернене значення має бути найменшим на основі цього підрахунку. Зрештою, ми лінгвісти, а не програмісти.
  • Вихід з панграматичного вікна повинен, однак, бути точним підрядком вводу, що містить ту саму велику літери і розділові знаки тощо.
  • Якщо є кілька найкоротших панграматичних вікон однакової довжини літери, поверніть будь-яке з них.

Випробування

'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
Для останнього тестового випадку, чому його не The five boxing wizards jump quicklyповертають?
Синій

1
У другому випадку вам дозволено простір, що передує Q? Він не додається до числа літер.
Ніл

2
@muddyfish Оскільки він має 31 лист, тоді як очікуваний вихід має лише 26.
Мартін Ендер

4
Приємне перше запитання!
Rɪᴋᴇʀ

2
Так. Причин цього не повинно бути. Взяти "справжній" мінімум у дусі питання, але це не обов'язково.
Reecer6

Відповіді:


6

Pyth, 20 16 14 байт

hol@GNf!-GrT0.:

Пояснення:

             .: - 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(^)

Спробуйте тут!

Коли немає правильного рішення, програма виходить із помилкою, без виводу для stdout.


Здається, ви не оновили код у першому блоці коду. Також !-GrT0я вважаю, що це коротше для фільтру. Я також думаю, що вам потрібно lзробити так, щоб сортування працювало належним чином.
FryAmTheEggman

О, я пропустив помилку, я мав на увазі посилання. У вашому посиланні ви все ще є l, і без нього ви отримуєте різні результати . Я вважаю, що проблема - це повторні листи, але я не впевнений на 100%.
FryAmTheEggman

Тож має значення - і дякую за оптимізацію!
Синій


2

Рубін, 100 байт

Повертає нуль, якщо не знайдено вікна.

->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 байт

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

Збережено 2 байти завдяки @Neil!

Відступ

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>


Не можете використовувати [r=l="",...s].map((_,b,a)=>?
Ніл

@Neil Спасибі, я завжди забуваю про третій параметр у mapфункції.
користувач81655

Я думаю, що @ edc65 може це перемогти, але я об'єднав код для його підірваних підрядів з тим для його тестера панграми і закінчив функцію 134 байти.
Ніл

Мій найкращий - 142 досі
edc65

На жаль, я не думав її врятувати, і мій ПК зазнав аварії, тому зараз я не знаю, що мав; найкраще, що я можу зробити зараз - це 138 байт.
Ніл

2

PowerShell v2 +, 218 байт

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

Так, маніпуляція з підрядками (тут немає вбудованих) насправді не є сильним костюмом PowerShell ...

Ми беремо введення param($a)та встановлюємо новий порожній хештель $z. Це буде наше зберігання кандидатських панграматичних підрядків.

Використовуючи незначну модифікацію мого коду з Exploded Substrings , ми конструюємо всі підрядки вводу. Так, навіть односимвольні пунктуаційні підряди. Це , не . ;-)

Усі ці підрядки інкапсульовані в паренах і переведені в інший цикл |%{...}. Ми тимчасово встановлюємо $yпоточну підрядку, встановлюємо помічник лічильника $jі запускаємо ще один цикл 65..90|%{...}, зручно за допомогою символьних кодів ASCII для великих літер. Кожну внутрішню петлю, яку ми беремо $y, робимо її все велику, і витягуємо саме .IndexOfту особливість. Оскільки це повернеться, -1якщо його не буде знайдено, ми отримаємо +1результат перед тим, як помножити його на $j. Це гарантує, що якщо будь-який один символ не знайдеться, $jдорівнює нулю.

Це саме те, про що ifйдеться. Якщо $jце не нуль, це означає, що кожну букву знайдено хоча б один раз у підрядку $y, тому нам потрібно додати це до нашого пулу кандидатів. Ми робимо це, беручи $yі використовуючи -replaceкожну не-букву ні з чим, що дає нам довжину літери цієї підрядки. Ми використовуємо це як індекс у хешбелі $zта зберіганні$y в цьому індексі. У цьому є вигадка щодо перезапису підрядків тієї ж довжини літери з тією, що трапляється "найдальше" в початковому рядку, але це дозволено правилами, оскільки нас хвилює лише довжина літер.

Нарешті нам потрібно розібратися $zі витягнути найменше. Ми повинні використовувати.GetEnumerator виклик для того, щоб сортувати об'єкти всередині $z , потім sortті, на яких Name(тобто індекс довжини зверху), вибравши [0]го (тобто найкоротший) і вивести його .Value(тобто підрядку). Якщо така підстрока не підходить, це призведе до помилки ( Cannot index into a null array), коли вона намагається індексувати $z, і нічого не виводить, що є фальсиєю в PowerShell. (третій тестовий випадок нижче має чіткий склад, [bool]щоб показати це)

Випробування

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 байт

Це було важко, але по-справжньому весело без імпорту.

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]

Набагато менше гольфу:

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

Сюрприз, сюрприз: це справді повільно.


2

Oracle SQL 11.2, 461 байт

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;

Без гольфу

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

The sВид розщеплюється на вході в символах , а також повертає позицію кожного символу.

Рекурсивний вигляд vповертає кожну підрядку входу
s - підрядку
f позиції першого символу підрядки
l положення останнього символу, доданого до поточної підрядки

The cВид повертає алфавіт, одну букву в той час ,

aВид повертає алфавіт зчіплюються у вигляді одного рядка

SELECT s,f,SUM(SIGN(INSTR(LOWER(s),c))
Повертає для кожної підрядки кількість наявних у ній різних літер,
INSTRповертає позицію букви в підрядку, 0 якщо немає,
SIGNповертає 1, якщо pos> 0, 0 якщо pos = 0

WHERE x=26
Фільтрує підрядку, що містить увесь алфавіт

TRANSLATE(LOWER(s),' '||a,' ')
Видаляє кожну букву з підрядка

LENGTH(s)-NVL(LENGTH(TRANSLATE(LOWER(s),' '||a,' ')
Довжина літер - це довжина підрядки мінус довжина підрядки без літер

SELECT MIN(s)KEEP(DENSE_RANK FIRST ORDER BY LENGTH(s)-NVL(LENGTH(TRANSLATE(LOWER(s),' '||a,' ')),0))
Зберігає лише підрядку з меншим числом літер.
Якщо їх більше, зберігається перша, відсортована як висхідний рядок


2

Пітон 3, 171, 167, 163, 157 , 149 байт.

Збережено 4 байти завдяки DSM.
Збережено 8 байт завдяки 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)))

Моє впорядкування залежно від кількості букв вбиває мене.

Тестові приклади:

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

Не думаю, що .upper()це потрібно в ключовій функції.
RootTwo

@RootTwo На жаль, так, ти маєш рацію. Спасибі.
Морган Трапп

1

PowerShell (v4), 198 156 байт

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]

Випробування

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!

Необурене пояснення оригіналу

Це вкладений цикл з грубою силою, який робить розсувні вікна всіх розмірів:

.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

Для кожного вікна він фільтрує лише літери (за замовчуванням невідчутне значення регексу за замовчуванням), запускає решта символів через унікальний фільтр, перевіряє, чи є 26 унікальних символів як тест панграми.

Усі вікна з панграмами перетворюються на трійки (кількість букв, включаючи дупи, індекс запуску, довжина вікна, включаючи пунктуацію) , які сортуються, щоб знайти найкоротший за загальним підрахунком символів, вибирається перше, а вихідна рядок будується з цього .

Поза межею рядка є багато індексування, для якого PowerShell корисно повертає $ null, замість того, щоб викидати винятки.

NB. новий 156 байт - той самий підхід, але переписаний для використання конвеєра набагато більше.

$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. не впевнений, що версія без вогків працює, тому що я не писав, що тоді гольф, це лише для експозиції.


0

Haskell, 123 байти

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

Визначає функцію h, яка повертає порожній список, якщо немає панграматичного вікна або одного списку елементів із мінімальним вікном. Приклад використання:

*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"]

Як це працює:

          [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!
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.