ฟังก์ชั่น Soundex


13

เขียนฟังก์ชันที่สั้นที่สุดเพื่อสร้างรหัส American Soundexสำหรับนามสกุลที่มีตัวอักษรตัวพิมพ์ใหญ่ AZ เท่านั้น ฟังก์ชั่นของคุณจะต้องสร้างผลลัพธ์ที่สอดคล้องกับตัวอย่างของหน้าที่เชื่อมโยง (ที่ระบุด้านล่าง) แม้ว่ามันจะไม่จำเป็นและไม่ควรลบคำนำหน้า ยัติภังค์ในผลลัพธ์เป็นตัวเลือก มีความสุข!

หมายเหตุ:คุณไม่สามารถใช้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

คำตอบ:


4

Perl, 143 150 ตัวอักษร

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 ตอนนี้มีผลลัพธ์ที่ถูกต้อง - ทำให้ dict เล็กลง - การสร้างมีขนาดเล็ก (ไม่จำเป็นต้องใช้ python 2.6) - การค้นหา dict ที่ง่ายขึ้น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

»ฉันเล่นกอล์ฟไม่ได้อีกต่อไป«คำเหล่านี้ไม่ค่อยเหมาะสม :-)
Joey

@Joey งูใหญ่ไม่ได้เป็นภาษาที่ดีที่สุดสำหรับการเล่นกอล์ฟรหัส ... ถ้าเพียง แต่มันมี regex ชั้นแรกเป็น Perl ...
JBernardo

มันทนทุกข์ทรมานจากตัวระบุยาวเกินไป imho ปกติฉันจะสามารถเอาชนะ Python ได้ด้วย PowerShell แต่ List comprehension นั้นยากที่จะเอาชนะ
Joey

@ Joey ตอนนี้คุณจะต้องทำงานเพิ่มอีกนิดหน่อยเพื่อเอาชนะ Python ด้วย PowerShell: P
JBernardo

2

Perl, 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}

ฉันใช้โซลูชันของ Howard กับตารางแปลของฉัน ( 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 และ s ทั้งหมดออกWจากสตริงเพราะใน (ที่ไม่น่าจะเกิดขึ้นจริงในชีวิตจริง แต่ไม่ได้ตัดออกโดยสเป็ค) ว่าตัวอักษรตัวแรกเป็นHหรือWอักษรตัวที่สองเป็นพยัญชนะ เราไม่จำเป็นต้องกำจัดพยัญชนะตัวนั้นเมื่อเราลบอักษรตัวแรก (ฉันได้เพิ่มกรณีทดสอบWMที่ควรให้W500ในการตรวจสอบนี้)

ดังนั้นผมจับทางที่จะทำพับและลบตัวอักษรแต่ละตัวอื่น ๆ กว่าครั้งแรก (สะดวกผลข้างเคียงของการใช้เท่า) ซึ่งเป็นทั้งเท่ากับหนึ่งก่อนหน้านี้หรือเท่ากับ7รหัสภายในและHW

ป.ร. ให้ไว้aและbในกองซ้อนวิธีที่ไร้เดียงสาเพื่อตรวจสอบว่าa == b || b == 7จะเป็น

.2$=1$7=+

แต่มีการบันทึก 2 อักขระโดยใช้การคัดลอกจากสแต็กที่คำนวณ:

.7=$

หากbมีค่าเท่ากับ7มันก็อปปี้a; bมิฉะนั้นมันสำเนา ดังนั้นแล้วเมื่อเทียบกับaที่เราได้รับค่า truthy รับประกันถ้าbเป็นโดยไม่คำนึงถึงความคุ้มค่าของ7 a(ก่อนที่คนเดินเท้าจะชั่งน้ำหนัก GolfScript จะไม่มี NaNs)


0

PowerShell, 150 161

ลองครั้งแรกและฉันแน่ใจว่าสามารถตีกอล์ฟได้อีกเล็กน้อย

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:

แจ็กสัน, Pfister, Tymczak, Gutierrez, Ashcraft, Ashcroft, VanDeusen, Robert, Rupert, Rubin, วอชิงตัน, ลี


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


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.