Najkrótsze okno Pangrammatic

15

Pangram to zdanie lub fragment, który zawiera wszystkie dwadzieścia sześć liter alfabetu, jak pokazano w tym wyzwaniu golfowym . Jednak okno pangramatyczne to pangram w postaci jakiegoś segmentu tekstu, który może kończyć się lub rozpoczynać w połowie słowa, znalezionego gdzieś w większym dziele. Występują one naturalnie wszędzie, będąc odpowiednimi podzbiorami prawdziwych pangramów, więc po prostu sprawdzenie, czy coś zawiera okno pangramatyczne, byłoby nudne, a także wcześniej.

Jesteśmy więc zainteresowani znalezieniem najmniejszego tekstu w danym fragmencie tekstu na podstawie jego długości litery! Oczywiście w możliwie najkrótszym kodzie w bajtach, aby pasował do motywu.

Zasady i wytyczne

  • Odbierz ciąg wejściowy i zwróć ciąg najmniejszego okna pangramatycznego na wejściu, jeśli taki istnieje. Jeśli nie, zwróć wartość logiczną Fałsz lub pusty ciąg.
  • To, czy napis jest oknem pangramatycznym, czy nie, nie uwzględnia wielkości liter i zależy tylko od 26 liter, a nie od znaków interpunkcyjnych, cyfr i innych nieparzystych symboli.
  • Podobnie, długość litery okna pangramatycznego jest całkowitą liczbą wyświetleń liter przypadków, w których występują w nim , a nie tylko liczbą każdego znaku. Zwrócona wartość musi być najmniejsza na podstawie tej liczby. W końcu jesteśmy językoznawcami, a nie programistami.
  • Dane wyjściowe okna pangramatycznego muszą jednak być dokładnym podciągiem wejściowym, zawierającym tę samą wielkość liter i interpunkcję itp.
  • Jeśli istnieje wiele najkrótszych okien pangramatycznych o tej samej długości litery, zwróć dowolne z nich.

Przypadki testowe

'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'
Reecer6
źródło
1
Dlaczego w ostatnim przypadku testowym nie jest The five boxing wizards jump quicklyzwracany?
Niebieski,
1
W drugim przypadku, czy dozwolone jest miejsce poprzedzające Q? Nie dodaje się do liczby liter.
Neil
2
@muddyfish Ponieważ ma 31 liter, podczas gdy oczekiwany wynik ma tylko 26.
Martin Ender
4
Ładne pierwsze pytanie!
Rɪᴋᴇʀ
2
Tak. Nie ma powodu, żeby tak nie było. Biorąc „prawdziwe” minimum w duchu pytania, ale nie jest to konieczne.
Reecer6

Odpowiedzi:

6

Pyth, 20 16 14 bajtów

hol@GNf!-GrT0.:

Wyjaśnienie:

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

Wypróbuj tutaj!

Gdy nie ma poprawnego rozwiązania, program kończy pracę z błędem bez wyjścia na standardowe wyjście.

niebieski
źródło
Wygląda na to, że nie zaktualizowałeś kodu w pierwszym bloku kodu. Wydaje mi się, że !-GrT0jest też krótszy dla stanu filtra. Myślę też, że potrzebujesz, laby sortowanie działało poprawnie.
FryAmTheEggman
Och, źle napisałem, miałem na myśli link. W swoim linku nadal masz l, a bez niego uzyskasz różne wyniki . Uważam, że problemem są powtarzające się litery, ale nie jestem w 100% pewien.
FryAmTheEggman
To ma znaczenie - i dziękuję za optymalizację!
Niebieski
3

Pyth - 22 bajty

\ o / FGITW!

h+ol@GrNZf}GS{rTZ.:z)k

Pakiet testowy .

Maltysen
źródło
2

Rubinowy, 100 bajtów

Zwraca zero, jeśli nie znaleziono okna.

->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}
Wartość tuszu
źródło
2

JavaScript (ES6), 139 138 136 bajtów

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

Zaoszczędź 2 bajty dzięki @Neil!

Zębaty

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>

użytkownik 81655
źródło
Nie można używać [r=l="",...s].map((_,b,a)=>?
Neil
@Neil Dzięki, zawsze zapominam o trzecim parametrze w mapfunkcji.
user81655
Myślę, że @ edc65 może to pobić, połączyłem kod jego rozłożonych podciągów z tym dla jego testera pangram i skończyłem z funkcją 134 bajtów.
Neil
Moje najlepsze jak dotąd to 142
edc65
Niestety nie pomyślałem o tym, aby go zapisać, a mój komputer się zawiesił, więc teraz nie wiem, co miałem; najlepsze, co mogę teraz zrobić, to 138 bajtów.
Neil
2

PowerShell v2 +, 218 bajtów

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

Tak, więc manipulowanie podciągami (nie ma żadnych wbudowanych) nie jest tak naprawdę mocnym kolorem PowerShell ...

Pobieramy dane wejściowe param($a)i ustawiamy nowy pusty hashtable $z. Będzie to nasze przechowywanie kandydujących podciągnięć pangramatycznych.

Używając niewielkiej modyfikacji mojego kodu z Exploded Substrings , konstruujemy wszystkie podciągi wejściowe. Tak, nawet jednoznakowe ciągi znaków interpunkcyjnych. To jest , a nie . ;-)

Wszystkie te podciągi są otoczone parenami i połączone z inną pętlą za pomocą |%{...}. Tymczasowo ustawiamy $yna bieżący podłańcuch, ustawiamy licznik pomocniczy $ji uruchamiamy kolejną pętlę 65..90|%{...}, dogodnie ponad kodami znaków ASCII dla wielkich liter. Każdą wewnętrzną pętlę robimy $ywielkimi literami i wyciągamy .IndexOften konkretny znak. Ponieważ to zwróci, -1jeśli nie zostanie znalezione, my +1wynik przed pomnożeniem go $j. Zapewnia to, że jeśli nie zostanie znaleziony żaden znak, $jbędzie równy zero.

Właśnie o ifto chodzi. Jeśli $jjest niezerowe, oznacza to, że każda litera została znaleziona co najmniej raz w podłańcuchu $y, więc musimy dodać to do naszej puli kandydatów. Robimy to, pobierając $yi -replacezapisując każdą nie-literę niczym, co daje nam długość litery tego podłańcucha. Używamy tego jako indeksu do tablicy mieszającej $zi przechowujemy $ypod tym indeksem. To dziwne, że zastępuje podciągi o tej samej długości literą, które występują „najdalej” w oryginalnym ciągu, ale jest to dozwolone przez reguły, ponieważ martwimy się tylko o długość liter.

Wreszcie musimy uporządkować $zi wyciągnąć najmniejsze. Musimy użyć .GetEnumeratorwywołania, aby posortować obiekty wewnątrz $z , a następnie sortte na Name(tj. Indeks długości od góry), wybierając ten [0](tj. Najkrótszy) i wyprowadzając jego .Value(tj. Podłańcuch). Jeśli żaden taki podłańcuch nie pasuje, spowoduje to wyrzucenie błędu ( Cannot index into a null array) przy próbie indeksowania $zi wyprowadzenie nic, co jest falsey w PowerShell. (trzeci przypadek testowy poniżej ma wyraźną obsadę, [bool]aby to pokazać)

Przypadki testowe

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
AdmBorkBork
źródło
2

Haskell, 180 bajtów

To było trudne, ale naprawdę zabawne bez importu.

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]

Znacznie mniej golfa:

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

Niespodzianka, niespodzianka: jest naprawdę powolna.

Michael Klein
źródło
2

Oracle SQL 11.2, 461 bajtów

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;

Nie grał w golfa

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

sWidok rozgałęzia zasilanie w znakach, a także zwraca położenie każdego znaku.

Widok rekurencyjny vzwraca wszystkie podciągi wejściowe
s jest podłańcuchem
pozycji pierwszego znaku podłańcucha
l pozycji ostatniego znaku dodanego do bieżącego podłańcucha

cWidok zwraca alfabetu, jedną literę na raz

aWidok zwraca alfabet doklejane jako jeden ciąg

SELECT s,f,SUM(SIGN(INSTR(LOWER(s),c))
Zwraca dla każdego podciągu liczbę różnych liter w nim zawartych,
INSTRzwraca pozycję litery w podłańcuchu, 0 jeśli nie występuje
SIGNzwraca 1, jeśli pos> 0, 0 jeśli pos = 0

WHERE x=26
Filtruje podciąg zawierający cały alfabet

TRANSLATE(LOWER(s),' '||a,' ')
Usuwa każdą literę z podłańcucha

LENGTH(s)-NVL(LENGTH(TRANSLATE(LOWER(s),' '||a,' ')
Długość w literach to długość podłańcucha minus długość podciągu bez liter

SELECT MIN(s)KEEP(DENSE_RANK FIRST ORDER BY LENGTH(s)-NVL(LENGTH(TRANSLATE(LOWER(s),' '||a,' ')),0))
Zachowuje tylko podciąg z mniejszą liczbą liter.
Jeśli jest więcej niż jeden, pierwszy zostaje posortowany jako rosnące ciągi znaków

Jeto
źródło
2

Python 3, 171, 167, 163, 157 , 149 bajtów.

Zaoszczędź 4 bajty dzięki DSM.
Zaoszczędź 8 bajtów dzięki 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)))

Zabijanie wymaga sortowania na podstawie liczby liter.

Przypadki testowe:

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.')
Morgan Thrapp
źródło
Nie myśl, że .upper()jest to potrzebne w kluczowej funkcji.
RootTwo
@RootTwo Ups, tak, masz rację. Dzięki.
Morgan Thrapp
1

PowerShell (v4), 198 156 bajtów

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]

Przypadki testowe

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!

Niegolfowane wyjaśnienie oryginału

Jest to zagnieżdżona pętla o brutalnej sile, która sprawia, że ​​okna przesuwne wszystkich rozmiarów:

.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

Dla każdego okna filtruje tylko litery (domyślnie dopasowuje wyrażenie regularne bez rozróżniania wielkości liter), przepuszcza pozostałe znaki przez unikalny filtr, sprawdza, czy w teście pangram jest 26 unikalnych znaków.

Wszystkie okna z pangramami są przekształcane w tryplety (liczba liter łącznie z duplikatami, indeks początkowy, długość okna z interpunkcją) , które są sortowane w celu znalezienia najkrótszej według ogólnej liczby znaków, wybierany jest pierwszy i tworzony jest ciąg wyjściowy .

Istnieje wiele indeksowania poza granicami łańcucha, dla których PowerShell użytecznie zwraca $ null, zamiast zgłaszania wyjątków.

NB nowy 156-bajtowy numer jeden jest tym samym podejściem, ale przepisany, aby korzystać z potoku o wiele więcej.

$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 nie jestem pewien, czy wersja bez golfa działa, ponieważ nie napisałem tego, a potem grałem w golfa, to tylko na wystawę.

TessellatingHeckler
źródło
0

Haskell, 123 bajty

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

Definiuje funkcję h, która zwraca pustą listę, jeśli nie ma okna pangramatycznego lub listy elementów z minimalnym oknem. Przykład użycia:

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

Jak to działa:

          [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!
nimi
źródło