将字符串减少为字母的一小段


25

给定一个仅包含小写和大写字母字符和空格([a-zA-Z ])的非空字符串,请将其缩减为从第一个字符开始的字母代码段。

要减少字符串,请从第一个字母字符开始,然后删除其后不是字母下一个字母的每个字符。继续执行此操作,直到到达字符串末尾。

例如codegolf

以开始c,请删除,o因为它不是字母表的下一个字母。
保持d,因为它字母表中的一个字母,并保持e,因为它是一个字母了。
删除gol,然后保留f

您的最后一个片段将是 cdef

规则

  • 应该保持大写,这样CodEgolF会导致CdEF
  • 空格不是字母,因此即使它是字符串的开头,也应始终将其删除
  • 由于减少的性质,输入的第一个字母字符将始终是输出的第一个字符。
  • zZ是字母表的最后一个字母。其后没有字母,字母不会循环。

测试用例

codegolf -> cdef
CodEgolf -> CdEf
 codeolfg -> cdefg
ProgrammingPuzzles -> P
Stack Exchange -> St
The quick red fox jumped over the lazy brown dog -> Tuvw
Zebra -> Z
Abcdegfhijkl -> Abcdef

计分

这是,因此每种语言中最少的字节都是成功的


从倒数第二个测试用例中,我看到如果达到目标,z我们就停下来,对吧?
Xcoder先生

@ Mr.Xcoder正确,请参见“规则”下的最后一点
Skidsdev,

2
请在测试用例的开头添加一个空格。像:<space>codegolf
Xcoder先生

我可以返回输出字母的数组吗?
TheLethalCoder

1
@ Mr.Xcoder是的,您可以
Skidsdev

Answers:


12

JavaScript(ES6),66 79 68 67字节

f=([c,...s],p)=>c?(p?~parseInt(c+p,36)%37:c<'!')?f(s,p):c+f(s,c):''

怎么样?

测试连续字母

因为在JS中将两个字符转换为它们的ASCII代码将是一个相当长的操作,所以我们改用以下公式:

~parseInt(b + a, 36) % 37

假设ab都在in中[a-zA-Z ],则上述表达式等于0且仅当ab是连续字母(即以36为底的连续数字)时,无论字符如何。

例如:

~parseInt("Y" + "x", 36) = ~(36 * parseInt("Y", 36) + parseInt("x", 36))
                         = ~(36 * 34 + 33)
                         = -(36 * 34 + 33 + 1)
                         = -(37 * 34)

格式化和评论

f = ([c,                              // c = current character
         ...s],                       // s = array of remaining characters
                p) =>                 // p = previous matching letter
  c ? (                               // if there's still at least 1 character to process:
      p ?                             //   if p was already defined:
        ~parseInt(c + p, 36) % 37     //     test if p and c are NON-consecutive letters
      :                               //   else:
        c < '!'                       //     test if c is a space character
    ) ?                               //   if the above test passes:
      f(s, p)                         //     ignore c and keep the current value of p
    :                                 //   else:
      c + f(s, c)                     //     append c to the final result and update p to c
  :                                   // else:
    ''                                //   stop recursion

测试用例


7

Python 2,69个字节

lambda s:reduce(lambda x,y:x+y*((ord(y)-ord(x[~0]))%32==1),s.strip())

在线尝试!

字符串的简单还原。当且仅当时,我们简单地连接下一个字符(ord(y)-ord(x[~0]))%32==1。检查非常难看-我敢肯定它可以改进,但是我不确定如何做!


聪明的解决方案!太糟糕了,它是仅限Python 2的:P
Xcoder先生

您可以使用使其与Python 3兼容from functools import*
totalhuman

1
@ThomasWard totallyhuman只是在告诉其他人如何使其与Python 3兼容。顺便说一句,import functools as f并且f.from functools import*确定的更长,甚至使用了一次。有关更多信息,请参见此线程
Xcoder先生

7

Python 3中75 85 84 91 81 77 75个字节

我认为这是Python 3所能达到的。如Sisyphus的提交所示,可以在Python 2中将其缩短几个字节。

  • 编辑: + 10修复错误
  • 编辑: -1通过修复另一个错误
  • 编辑: + 7用于修复另一个错误
  • 编辑: -10字节的@Ruud帮助
  • 编辑: -4个字节,因为OP允许我们输出以换行符分隔的字母
  • 编辑: -2字节感谢@Ruud,回到原始字节数!
s=input().strip();k=0
for i in s:
 if(ord(i)-ord(s[0]))%32==k:k+=1;print(i)

在线尝试!


我有改进的想法,即将在手机上打高尔夫球。
Xcoder先生

2
81个字节。大写字母和小写字母在由32调制时可以方便地匹配
Arfie

@Ruud这些正是我在评论,编辑中谈论的内容。
Xcoder先生


8
我正在等待下降投票者解释其原因。
Xcoder先生


4

Brachylog,15个字节

;ṢxS⊇.ḷ~sẠ∧Sh~h

在线尝试!

这将是10个字节:⊇.ḷ~sẠ&h~h,如果不是因为相当有趣的“字符串可以以空格开头”约束。

说明

;ṢxS               S is the Input with all spaces removed
   S⊇.             The Output is an ordered subset of the Input
     .ḷ            The Output lowercased…
        ~sẠ          …is a substring of "abcdefghijklmnopqrstuvwxyz"
           ∧
            Sh     The first char of S…
              ~h   …is the first char of the Output

由于这是声明性的,因此它也确实很慢。


好吧,至少击败了果冻!而且,从好的方面来说,我认为您真的不能超越这个……
Outgolfer的Erik

3

MATL18 16 15字节

多亏了Xcoder先生指出了一个错误,现已更正

Xz1&)"t@hkd1=?@

输出中的字母由换行符分隔。

在线尝试!验证所有测试用例(为清楚起见,页脚代码在同一行上显示所有输出字母)。

说明

Xz       % Implicitly input a string. Remove spaces
1&)      % Push first character and then the remaining substring
"        % For each
  t      %   Duplicate previous character
  @      %   Push current character
  h      %   Concatenate both characters
  k      %   Convert to lowercase
  d      %   Consecutive difference. Gives a number
  1=     %   Is it 1?
  ?      %   If so
    @    %     Push current char
         %   End (implicit)
         % End (implicit)
         % Display stack (implicit)

您忘记将空格放在字符串的开头时将其删除:空格不是字母,因此即使它是字符串的开头,也应始终将其删除
Xcoder先生

@ Mr.Xcoder谢谢!已更正
Luis Mendo


2

C#(单声道)129个 107 93 91 87字节

s=>{var r=s.Trim()[0]+"";foreach(var c in s)if(r[r.Length-1]%32==~-c%32)r+=c;return r;}

由于@Mr,节省了2个字节。Xcoder。
@jkelm节省了4个字节。

在线尝试!


在领先空间上失败
Skidsdev

@Mayube Woops没看到这个,已修复。
TheLethalCoder

2
91个字节。在类C语言和Python中,(c-1)%32~-c%32
Xcoder先生

1
87字节由于for循环中的检查,您不需要重新分配修剪后的字符串
jkelm

2

PHP,64 + 1字节

while($c=$argn[$i++])$c<A||$n&&($c&_)!=$n||(print$c)&$n=++$c&__;

与管道一起运行-nR在线尝试


除了通常的技巧外,当$c到达时Z,会++$c产生AA
&__保持该长度不变;因此$n将不再匹配$c




2

Pyth,21 20 18字节

ef&qhThQhxGrT0tyr6

在这里尝试。

效率更高的20字节版本:

.U+b?t-CrZ1Creb1kZr6

在这里尝试。

-1感谢Xcoder先生(间接)。


等效:(.U+b?tlrreb1rZ1kZrz6我认为)。那把戏对我有帮助。
Xcoder先生

@ Mr.Xcoder如果相等,我可以使用节省一个字节,.U+b?tlrreb1rZ1kZr6但是不幸的r <str> 6A.strip(),不删除非前导或尾随空格。
暴民埃里克(Erik the Outgolfer)'17年

哦,是的,我没有看到您的解决方案依赖于所有已删除的空格(我的不是)
Xcoder先生

@ Mr.Xcoder嗯,您应该删除所有空格。
暴民埃里克(Erik the Outgolfer)'17年

不,我不应该这样做,因为空格的ASCII值为32,而所有字母都有> 64,因此不会影响功能。我认为这也适用于您的答案。
Xcoder先生

1

Perl 6,51个字节

{S:i:g/\s|(\w){}<([<!before "{chr $0.ord+1}">.]+//}

测试一下

展开:

{  # bare block lambda with implicit parameter $_

  S                          # substitute implicitly on $_, not in-place
  :ignorecase
  :global
  /

    |  \s                    # match any space

    |  (\w)                  # match a word character
       {}                    # make sure $/ is updated (which $0 uses)

       <(                    # ignore everything before this

       [

           <!before "{       # make sure this won't match after this point
             chr $0.ord + 1  # the next ASCII character
           }">

           .                 # any character

       ]+                    # match it at least once

  //                         # remove what matched
}

注意这<!before …>是一个零宽度的断言



1

Japt18 17 16字节

@Shaggy节省了1个字节

x
c
Çc %H¥V%H©V°

在线测试!

当时以为这会短很多,但是...这就是生活...

说明

x    First line: set U to the result.
x    Trim all spaces off of the input. Only necessary to remove leading spaces.

c    Second line: set V to the result.
c    Take the charcode of the first character in U.

 Ç   c %H¥ V%H© V°
UoZ{Zc %H==V%H&&V++}   Final line: output the result.
UoZ{               }   Filter to only the chars in Z where
    Zc                   the charcode of Z
       %H                mod 32
         ==V%H           equals V mod 32.
              &&V++      If true, increment V for the next letter.

至少比我的28个字节的苦难短!:D看来您可以替换rSx
毛茸茸的

1

C#(.NET Core)70 60 + 18字节

-10个字节,感谢TheLethalCoder

a=>{var c=a.Trim()[0];return a.Where(x=>x%32==c%32&&++c>0);}

字节数还包括:

using System.Linq;

在线尝试!

(目前)比TheLethalCoder的字节长1个字节(当前)(不再)了,所以为了娱乐起见。使用LINQ的不同方法。

这利用了C#中的两个类似C的功能-一个字符char变量隐式地表现为与整数相同int,并且&&如果left返回a ,则布尔AND运算符不会执行right操作false。代码说明:

a =>                                  // Take string as input
{
    var c = a.Trim()[0];              // Delete leading spaces and take first letter
    return a.Where(                   // Filter out characters from the string, leaving those that:
               x => x % 32 == c % 32  // it's the next character in alphabet case-insensitive (thanks to modulo 32 - credits to previous answers)
               && ++c > 0             // If it is, go to the subsequent character in alphabet (and this always has to return true)
           );
}

.ToArray()通过返回IEnumerable<char>来删除以保存字节。
TheLethalCoder

@TheLethalCoder对,我只是在挑战下看到了评论。谢谢!
GrzegorzPuławski17年

1

q / kdb +,47个 45字节

解:

{10h$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}

例子:

q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"CodEgolf"
"CdEf"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}" codeolfg"
"cdefg"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"ProgrammingPuzzles"
"P"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"The quick red fox jumped over the lazy brown dog"
"Tuvw"

说明:

利用mod 32现有解决方案中的技巧和收敛功能。遍历字符串,如果结果的最后一个元素(例如,T以“ the red red fox ...” 开头)与当前字符之间的差为1(mod用32 代替'd'),则将其添加到结果(因此采用了为什么last x),然后将所有内容都转换回字符串。

{10h$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x} / the solution
{                                           } / lambda function
                                      trim x  / trim whitespace (leading/trailing)
                                   7h$        / cast string to ASCII (a -> 97)
     ({                         }/)           / converge
                    y-last x                  / y is the next item in the list, x contains results so far
              1=mod[        ;32]              / is the result mod 32 equal to 1
       (x;x,y)                                / if false, return x, if true return x concatenated with y
 10h$                                         / cast back to characters

1

Perl 5,30 +1(-n)= 31个字节

/$b/i&&(print,$b=++$_)for/\S/g

在线尝试!

怎么样?

/$b/i        # check if this letter equals the one in $b, ignore case
&&(print,    # output it if so
$b=++$_)     # store the next character to find
for/\S/g     # Looping over all non-whitespace characters

0

视网膜,76字节

 

^.
$&$&$&¶
{T`@@L@l`@l@l@`..¶
T`l`L`.¶
(.)(.)((¶).*?(\1|\2)|¶.*)
$5$5$5$4

在线尝试!链接包括测试用例。说明:

 

删除空格。

^.
$&$&$&¶

一式三份并插入分隔符。

{T`@@L@l`@l@l@`..¶
T`l`L`.¶

将第二个和第三个字符转换为小写并递增。将后者转换为大写。这些现在是搜索字符。

(.)(.)((¶).*?(\1|\2)|¶.*)
$5$5$5$4

尝试匹配两个搜索字符。如果找到,则将匹配重复三次,从而重新开始下一次搜索的循环。否则,只需删除搜索字符和其余输入。


0

8th,114字节

: z dup n:1+ 32 bor >r "" swap s:+ . ; 
: f s:trim 0 s:@ z ( nip dup 32 bor r@ n:= if rdrop z then ) s:each rdrop ;

说明

: z             \ n -- (r: x)
                \ print letter and save on r-stack OR-bitwised ASCII code of following letter
  dup           \ duplicate item on TOS
  n:1+          \ get ASCII code of the following letter
  32 bor        \ bitwise OR of ASCII code and 32 
  >r            \ save result on r-stack
  "" swap s:+ . \ print letter
;

: f        \ s -- 
  s:trim   \ remove trailing whitespace
  0 s:@    \ get 1st letter
  z        \ print 1st letter and save on r-stack OR-bitwised ASCII code of following letter
  ( nip    \ get rid of index
    dup    \ duplicate item on TOS
    32 bor \ bitwise OR of current ASCII code and 32 
    r@     \ get value stored on r-stack
    n:=    \ compare values to see if letter is printable or not
    if 
      rdrop \ clean r-stack
      z     \ print letter and save on r-stack OR-bitwised ASCII code of following letter
    then 
  ) 
  s:each    \ handle each character in string
  rdrop     \ clean r-stack
;

ok> " The quick red fox jumped over the lazy brown dog" f
Tuvw



0

Pyth,15个字节

eo,}r0NG_xQhNty

测试套件

与所有其他答案不同,它不会将输出粘在一起,它会生成输入的所有子序列,然后命令它们将所需的字符串放在末尾并输出。


我认为您也必须检查输出的首字母是否也是输入的首字母。而且我认为初始订单很重要。
暴民埃里克(Erik the Outgolfer)'17年

@EriktheOutgolfer对不起,您是说答案是错误的吗?我确保在按字母顺序排列的所有子序列中,第一个字符最早出现在输入中的序列是一个排序到末尾的序列。请参见以空格开头的测试用例。
isaacg

您可以补充说明吗?我可能有误解之类的东西
Egg the Outgolfer '17

0

J,局部解

我发布此内容的目的是为了获得反馈和改进的想法。它可以工作,但不能处理大写和空格边缘情况,并且对于J来说已经很久了。

首先是二进角的助动词,它告诉您左侧和右侧参数是否按字母顺序相邻:

g=.(= <:)&(a.&i.)  NB. could save one char with u:

接下来是一个动词,它从第一个元素开始删除属于字母条纹的第一个元素:

f=.({~<^:3@>:@i.&0@(0,~2&(g/\))) ::]

请注意,我们使用Adverse ::如果没有找到非条纹元素(即,如果整个参数是有效的字母条纹),则不变地返回整个参数。

最后,通过应用f直到收敛,给出解决方案:

f^:_ 'codegolf'  NB. => 'cdef'

在线尝试!


以下是的解析版本,f以便于阅读:

           ┌─ ~ ─── {                         
           │                              ┌─ <
           │                       ┌─ ^: ─┴─ 3
           │                 ┌─ @ ─┴─ >:      
       ┌───┤           ┌─ @ ─┴─ i.            
       │   │     ┌─ & ─┴─ 0                   
       │   │     │                            
       │   └─ @ ─┤     ┌─ 0                   
── :: ─┤         │     ├─ ~ ─── ,             
       │         └─────┤                      
       │               │     ┌─ 2             
       │               └─ & ─┴─ \ ─── / ──── g
       └─ ]         

侧面问题:当在SO上显示时,为什么框字符不能完全对齐(它们在我的控制台中工作):

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.