最短的语法窗口


15

连字符是包含所有26个字母的句子或摘录,如本代码高尔夫球挑战中所示。但是,语法窗口是某种文本片段形式的语法,可能在一个较大的作品中的某个地方出现或终止于单词的一半。这些自然地随处可见,是真正的Pangram的适当子集,因此只需验证某物是否包含Pangrammatic窗口就很无聊,而且之前也已完成。

因此,我们有兴趣根据字母长度找到给定文本中最小的文本!当然,以最短的代码(以字节为单位)以适合主题。

规则与准则

  • 接收一个字符串作为输入,如果存在,则返回输入中最小的语法窗口的字符串。如果没有,则返回布尔False或空字符串。
  • 字符串是否为语法窗口不区分大小写,仅取决于26个字母,而不取决于任何标点符号,数字或其他奇数符号。
  • 同样,语法窗口的字母长度是单独出现在其中的字母出现的总数,而不仅仅是每个字符的数量。基于此计数,返回值必须最小。毕竟,我们是语言学家,而不是程序员。
  • 但是,语法化窗口的输出必须是输入的精确子字符串,包含相同的大小写和标点符号等。
  • 如果存在多个具有相同字母长度的最短的语法窗口,则返回其中任何一个。

测试用例

'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 '16

Answers:


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

Ruby,100字节

如果找不到窗口,则返回nil。

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

感谢@Neil,节省了2个字节!

缩进

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函数中的第三个参数。
user81655 '16

我认为@ edc65可以克服这个问题,我将他爆炸的子字符串的代码与他的pangram测试器的代码合并在一起,最后得到一个134字节的函数。
尼尔

到目前为止,我最好的成绩是142
edc65 '16

遗憾的是,我没有想到要保存它,并且我的电脑崩溃了,所以现在我不知道自己拥有什么。我现在能做的最好的是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中的代码进行少量修改,我们构造了输入的所有子字符串。是的,甚至是仅一个字符标点的子字符串。这是,不是。;-)

所有这些子字符串都封装在parens中,并使用传递到另一个循环中|%{...}。我们临时设置$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

s视图将输入拆分为字符,并返回每个字符的位置。

递归视图v返回输入
的每个子字符串s是子字符串
f 子字符串第一个字符
的位置l末尾字符添加到当前子字符串的位置

c视图返回字母,一个字母在同一时间

a视图返回连接为单个字符串的字母

SELECT s,f,SUM(SIGN(INSTR(LOWER(s),c))
对于每个子字符串,
INSTR返回其中存在的不同字母的数量,返回子字符串中字母的pos;如果不存在,则
SIGN返回0;如果pos> 0,则返回1;如果pos = 0,则返回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

Python 3中,171,167,163,157,149个字节。

DSM节省了4个字节。
借助RootTwo,节省了8个字节。

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 '16

@RootTwo糟糕,是的,您是对的。谢谢。
摩根·塔普

1

PowerShell(v4),198156字节

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个唯一字符作为pangram测试。

所有带有pangram的窗口都将变成三元组包含重复字符的字母数,起始索引,包含标点的窗口长度),将其排序以找到总字符数最短的字符,选择第一个,然后从中构建输出字符串。

字符串范围之外有很多索引,PowerShell会为该索引有效地返回$ null,而不是抛出异常。

注意 新的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 ''
}

注意 不确定非高尔夫版本是否有效,因为我没有写过然后打高尔夫,这只是为了说明。


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!
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.