Soundex-Funktion

13

Schreiben Sie die kürzeste Funktion, um den American Soundex-Code für einen Nachnamen zu generieren, der nur die Großbuchstaben AZ enthält. Ihre Funktion muss eine Ausgabe erzeugen, die mit allen Beispielen der verknüpften Seite (siehe unten) konsistent ist, obwohl Präfixe nicht entfernt werden müssen und sollten. Bindestriche in der Ausgabe sind optional. Habe Spaß!

Hinweis: Sie können nicht die Verwendung soundex()Funktion in PHP oder Entsprechungen in anderen Programmiersprachen enthalten.

Die Beispiele:

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

Antworten:

4

Perl, 143 150 Zeichen

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

Diese Lösung enthält nur reguläre Ausdrücke, die nacheinander angewendet werden. Leider habe ich keine kürzere Darstellung mit einer Schleife gefunden, sodass ich alle Aufrufe im Skript fest codiert habe.

Dieselbe Version, aber etwas besser lesbar:

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
}

Edit 1: Jetzt wird die Lösung in Form einer Funktion geschrieben. Die vorherige war das Lesen / Schreiben von / nach STDIN / STDOUT. Es hat mich sieben Charaktere gekostet, das zu umgehen.

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

Führen Sie so etex filename.tex [Ashcraft].

Bruno Le Floch
quelle
2

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

- Die letzte Klausel (H oder W als Konsonantentrennzeichen) wurde korrigiert. Ashcraft hat jetzt das richtige Ergebnis. - Dikt verkleinern - Formatieren ist kleiner (benötigt kein Python 2.6) - Einfachere Diktsuche nach k - Geänderter Vokalwert von '*'nach ''und .appendnach +=[i] - Listenverständnis FTW - Entfernter Aufruf an upper: D

Ich kann nicht weiter Golf spielen. Eigentlich habe ich getan. Jetzt glaube ich, dass ich nicht weiter Golf spielen kann! Schon wieder getan...

Verwenden der Übersetzungstabelle:

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]

Alter Listenverständniscode:

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]

Alter Code:

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]

Prüfung:

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

Gibt:

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

Wie erwartet.

JBernardo
quelle
Groß. Sie müssen die Eingabe nicht in Großbuchstaben konvertieren. Sie können davon ausgehen, dass es bereits ist.
PleaseStand
»Ich kann nicht weiter Golf spielen« diese Worte sind selten angebracht :-)
Joey
@ Joey Python ist nicht die beste Sprache für Code-Golf ... Wenn es nur erstklassigen Regex als Perl hätte ...
JBernardo
Es leidet unter zu langen Bezeichnern mehr, imho. Normalerweise kann ich Python mit PowerShell schlagen, aber das Listenverständnis ist schwierig zu übertreffen.
Joey
@Joey Jetzt musst du ein bisschen mehr arbeiten, um Python mit PowerShell zu schlagen: 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}

Ich verwende Howards Lösung mit meiner Übersetzungstabelle ( y/A-Z/table/sanstelle von jeder s/[ABC]+/N/g)

JBernardo
quelle
2

J - 99

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

Testen:

  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|
+-------+-------+-------+---------+--------+--------+---------+------+------+-----+----------+----+
isawdrones
quelle
1

GolfScript (74 Zeichen)

Diese Implementierung verwendet eine magische Zeichenfolge mit nicht druckbaren Zeichen. In xxdAusgabeform ist es

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;

Ohne die Basisänderungen zum Komprimieren einer Liste von 3-Bit-Zahlen wäre dies der Fall

{.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;

Online-Test

Es ist im Grunde ein Haufen langweiliger Loops, aber es gibt einen interessanten Trick:

.7=$2$=

Dies ist innerhalb einer Falte, deren Zweck es ist, Doppelbuchstaben zu behandeln. Benachbarte Buchstaben mit demselben Code werden zu einer Einheit zusammengefasst, auch wenn sie durch ein Hoder ein getrennt sind W. Dies kann jedoch nicht einfach durch Entfernen aller Hs und Ws aus der Zeichenfolge implementiert werden , da in dem (im wirklichen Leben zwar unwahrscheinlichen, aber nicht von der Spezifikation ausgeschlossenen) Fall, dass der erste Buchstabe ein Konsonant ist, Hoder Wder zweite Buchstabe ein Konsonant ist Wir müssen uns diesem Konsonanten nicht entziehen, wenn wir den ersten Buchstaben entfernen. (Ich habe einen Testfall hinzugefügt, WMder es geben sollte, W500um dies zu überprüfen).

Die Art und Weise, wie ich damit umgehe, besteht darin, einen Falz auszuführen und jeden Buchstaben außer dem ersten zu löschen (ein praktischer Nebeneffekt bei der Verwendung von Falz), der entweder gleich dem vorherigen oder gleich 7dem internen Code für Hund ist W.

Gegeben aund bauf dem Stapel, der naive Weg, um zu überprüfen, ob a == b || b == 7wäre

.2$=1$7=+

Es werden jedoch 2 Zeichen gespeichert, wenn eine berechnete Kopie des Stapels verwendet wird:

.7=$

Wenn bist gleich 7dann kopiert es a; sonst kopiert es b. Beim Vergleich mit erhalten awir also einen garantierten Wahrheitswert, wenn bdieser 7unabhängig vom Wert von war a. (Bevor Pedanten einwiegen, hat GolfScript keine NaNs).

Peter Taylor
quelle
0

PowerShell, 150 161

Versuchen Sie es zuerst und ich bin mir sicher, dass es noch viel mehr Möglichkeiten zum Golfen gibt.

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

Funktioniert korrekt mit den Testfällen von der verlinkten Seite und dem Wikipedia-Artikel:

Jackson, Pfister, Tymczak, Gutierrez, Ashcraft, Ashcroft, VanDeusen, Robert, Rupert, Rubin, Washington, Lee

Joey
quelle
0

Rubin 140

Ich benutze Ruby 2.0, aber ich denke, es sollte auch mit früheren Versionen funktionieren.

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

Beispiel:

puts f "PFISTER" => P236

daniero
quelle
0

APL (83)

{(⊃⍵),,/⍕¨3↑0~⍨1↓K/⍨~K=1⌽K←0,⍨{7|+/' '=S↑⍨⍵⍳⍨S←' BFPV CGJKQSXZ DT L MN R'}¨⍵~'HW'}⍞
Marinus
quelle