Soundex功能


13

编写最短函数,为仅包含大写字母AZ的姓生成American Soundex代码。您的函数必须产生与所有链接页面的示例一致的输出(如下所示),尽管它不需要也不应删除前缀。输出中的连字符是可选的。玩得开心!

注意:您可能无法使用soundex()包含在PHP或其他编程语言等价物的功能。

例子:

WASHINGTON W-252
LEE L-000
GUTIERREZ G-362
PFISTER P-236 
JACKSON J-250 
TYMCZAK T-522
VANDEUSEN V-532
ASHCRAFT A-261

Answers:


4

Perl,143150个字符

sub f{$_="$_[0]000";/./;$t=$&;s/(?<=.)[HW]//g;s/[BFPV]+/1/g;s/[CGJKQSXZ]+/2/g;s/[DT]+/3/g;s/L+/4/g;s/[MN]+/5/g;s/R+/6/g;s/(?<=.)\D//g;/.(...)/;"$t$1"}

该解决方案只包含一个正则表达式,一个又一个地应用。不幸的是,我没有找到带有循环的简短表示,因此我将所有调用硬编码到脚本中。

相同的版本,但可读性更高:

sub f{
  $_="$_[0]000";        # take first argument and append "000"
  /./;$t=$&;            # save first char to variable $t
  s/(?<=.)[HW]//g;      # remove and H or W but not the first one
  s/[BFPV]+/1/g;        # replace one or more BFPV by 1
  s/[CGJKQSXZ]+/2/g;    # replace one or more CGJKQSXZ by 2
  s/[DT]+/3/g;          # replace one or more DT by 3
  s/L+/4/g;             # replace one or more L by 4
  s/[MN]+/5/g;          # replace one or more MN by 5
  s/R+/6/g;             # replace one or more R by 6
  s/(?<=.)\D//g;        # remove and non-digit from the result but not the first char
  /.(...)/;"$t$1"       # take $t plus the characters 2 to 4 from result
}

编辑1:现在,解决方案以函数形式编写。上一个是从STDIN / STDOUT读/写。解决这个问题花了我七个字符。


2

eTeX,377。

\let\E\expandafter
\def\x#1;#2#3{\def\s##1#2{##1\s#3}\edef\t{\s#1\iffalse#2\fi}\E\x\t;}
\def\a[#1#2]{\if{{\fi\uppercase{\x#1,#2};B1F1P1V1C2G2J2K2Q2S2X2Z2D3T3L4M5N5R6A7E7I7O7U7
    H{}W{}Y{}{11}1{22}2{33}3{44}4{55}5{66}6{{}\toks0\bgroup}!}\E\$\t0000!#1}}
\def\$#1,#2{\if#1#2\relax\E\%\else\E\%\E#2\fi}
\def\%{\catcode`79 \scantokens\bgroup\^}
\def\^#1#2#3#4!#5{\message{#5#1#2#3}\end}
\E\a

运行为etex filename.tex [Ashcraft]


2

Python中,274 285 241 235 225 200 190 183 179 174 166 161

-修复了最后一个子句(H或W为辅音分隔符)。Ashcraft现在具有正确的结果。-在制造小字典-格式化较小(不要求蟒蛇2.6) -简单的字典搜索k -更改元音值从'*'''.append+=[i] -列表理解FTW -删除呼叫upper:d

我不能再打高尔夫球了。其实我做到了 现在我想我不能再打高尔夫球了!又那么做了...

使用转换表:

def f(n):z=n.translate(65*'_'+'#123#12_#22455#12623#1_2#2'+165*'_').replace('_','');return n[0]+(''.join(('',j)[j>'#']for i,j in zip(z[0]+z,z)if i!=j)+'000')[:3]

旧列表理解代码:

x=dict(zip('CGJKQSXZDTLMNRBFPV','2'*8+'3345561111'))
def f(n):z=[x.get(i,'')for i in n if i not in'HW'];return n[0]+(''.join(j for i,j in zip([x.get(n[0])]+z,z)if i!=j)+'000')[:3]

旧代码:

x=dict(zip('CGJKQSXZDTLMNRBFPV','2'*8+'3345561111'))
def f(n):
 e=a=[];k=n[0]in x
 for i in[x.get(i,'')for i in n.upper()if i not in'HW']:
  if i!=a:e+=[i]
  a=i
 return n[0]+(''.join(e)+'000')[k:3+k]

测试:

[f(i) for i in ['WASHINGTON', 'LEE', 'GUTIERREZ', 'PFSTER', 'JACKSON',
                'TYMCZAK', 'VANDEUSEN', 'ASHCRAFT']]

给出:

['W252', 'L000', 'G362', 'P236', 'J250', 'T522', 'V532', 'A261']

如预期的那样。


大。您无需将输入转换为大写;您可以假设它已经是。
PleaseStand 2011年

»“我不能再打高尔夫球了”«这句话很少恰当:-)
Joey

@Joey Python并不是编码高尔夫的最佳语言...如果只有Perl等一流的正则表达式...
JBernardo 2011年

恕我直言,它的标识符过长。通常,我可以使用PowerShell击败Python,但是要理解列表理解是很难的。
乔伊(Joey)

@Joey现在你必须工作多一点使用PowerShell击败的Python:P
JBernardo

2

珀尔110

sub f{$_="$_[0]000";/./;$t=$&;s/(?<=.)[HW]//g;y/A-Z/:123:12_:22455:12623:1_2:2/s;s/(?<=.)\D//g;/.(...)/;$t.$1}

我在翻译表中使用了霍华德的解决方案(y/A-Z/table/s而不是每个s/[ABC]+/N/g


2

J-99

{.,([:-.&' '@":3{.!.0[:(#~1,}.~:}:)^:#,@(;:@]>:@I.@:(e.&>"0 _~)[#~e.))&'BFPV CGJKQSXZ DT L MN R'@}.

测试:

  sndx=: {.,([:-.&' '@":3{.!.0[:(#~1,}.~:}:)^:#,@(;:@]>:@I.@:(e.&>"0 _~)[#~e.))&'BFPV CGJKQSXZ DT L MN R'@}.
  test=: ;: 'JACKSON PFISTER TYMCZAK GUTIERREZ ASHCRAFT ASHCROFT VANDEUSEN ROBERT RUPERT RUBIN WASHINGTON LEE'
  (,. sndx&.>) test


+-------+-------+-------+---------+--------+--------+---------+------+------+-----+----------+----+
|JACKSON|PFISTER|TYMCZAK|GUTIERREZ|ASHCRAFT|ASHCROFT|VANDEUSEN|ROBERT|RUPERT|RUBIN|WASHINGTON|LEE |
+-------+-------+-------+---------+--------+--------+---------+------+------+-----+----------+----+
|J250   |P123   |T520   |G362     |A261    |A261    |V532     |R163  |R163  |R150 |W252      |L000|
+-------+-------+-------+---------+--------+--------+---------+------+------+-----+----------+----+

1

GolfScript(74个字符)

此实现使用具有不可打印字符的魔术字符串。在xxd输出形式中

0000000: 7b2e 313c 5c5b 7b36 3326 2741 4c15 c252  {.1<\[{63&'AL..R
0000010: d056 4c1e 8227 3235 3662 6173 6520 3862  .VL..'256base 8b
0000020: 6173 653d 7d25 7b2e 373d 2432 243d 7b3b  ase=}%{.7=$2$={;
0000030: 7d2a 7d2a 5d31 3e31 2c2d 5b30 2e2e 5d2b  }*}*]1>1,-[0..]+
0000040: 333c 7b2b 7d2f 7d3a 533b                 3<{+}/}:S;

如果不使用基本更改来压缩3位数字的列表,它将是

{.1<\[{63&[1 0 1 2 3 0 1 2 7 0 2 2 4 5 5 0 1 2 6 2 3 0 1 7 2 0 2]=}%{.7=$2$={;}*}*]1>1,-[0..]+3<{+}/}:S;

在线测试

这基本上是一堆无聊的循环,但是有一个有趣的技巧:

.7=$2$=

这是折叠的内部,其目的是处理双字母。具有相同代码的相邻字母将合并为一个单元,即使由H或分隔也是如此W。但这不能通过从字符串中删除所有Hs和Ws来实现,因为(在现实生活中,这不太可能实现,但没有被规范排除)在这种情况下,第一个字母为HW第二个字母为辅音,我们在删除第一个字母时不必消除该辅音。(我添加了一个测试用例WM,应该W500对此进行检查)。

因此,这样我手柄即做折叠,并删除每个字母比所述第一其他(使用折叠的一个方便的副作用)其是等于前一个或等于7,内部代码HW

鉴于ab在栈上,用简单的方式来检查是否a == b || b == 7

.2$=1$7=+

但是,通过使用计算得出的堆栈复制可以节省2个字符:

.7=$

如果b等于7则复制a; 否则它将复制b。因此,通过再与比较a,我们得到保证truthy值,如果b7不管的价值a。(在添加任何学步车之前,GolfScript没有NaN)。


0

PowerShell的150161

第一次尝试,我敢肯定高尔夫还有很多。

filter s{$s=-join$_[1..9]
1..6+'$1','',$_[0]|%{$s=$s-replace('2[bfpv]2[cgjkqsxz]2[dt]2l2[mn]2r2(.)\1+2\D|^.2^'-split2)[++$a],$_}
-join"${s}000"[0..3]}

可以正确使用链接页面和Wikipedia文章中的测试用例:

杰克逊,普菲斯特,蒂姆恰克,古铁雷斯,阿什克拉夫特,阿什克罗夫特,范德森,罗伯特,鲁珀特,鲁宾,华盛顿,李


0

红宝石140

我正在使用Ruby 2.0,但我认为它也应该与早期版本一起使用。

def f s
a=s[i=0]
%w(HW BFPV CGJKQSXZ DT L MN R).each{|x|s.gsub!(/[#{x}]+/){i>0&&$`[0]?i: ''};i+=1}
a+(s[1..-1].gsub(/\D/,'')+'000')[0,3]
end

例:

puts f "PFISTER" => P236


0

APL(83)

{(⊃⍵),,/⍕¨3↑0~⍨1↓K/⍨~K=1⌽K←0,⍨{7|+/' '=S↑⍨⍵⍳⍨S←' BFPV CGJKQSXZ DT L MN R'}¨⍵~'HW'}⍞
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.