มอร์สถอดรหัสกอล์ฟ


24

ฉันตื่นตระหนกกับความเกลียดชังของช่องว่างที่เพิ่มมากขึ้นและคำตอบนี้เป็นแรงบันดาลใจให้ฉันเพื่อให้แน่ใจว่ารหัสมอร์สนั้นปลอดภัยจากการกำจัดช่องว่างที่ร้ายกาจนี้

ดังนั้นงานของคุณคือการสร้างโปรแกรมที่สามารถแปลรหัสมอร์สได้สำเร็จเมื่อมีการลบช่องว่างทั้งหมด

รหัสมอร์ส

กฎ:

  1. อินพุตจะเป็นสตริงที่ประกอบด้วยเส้นประและจุด (ASCII 2D และ 2E) เอาท์พุทไม่ได้กำหนดไว้สำหรับการป้อนข้อมูลที่มีตัวละครอื่น ๆ อย่าลังเลที่จะใช้วิธีการใด ๆ ที่สะดวกในการเลือกภาษาของคุณเพื่อรับอินพุต (stdin, ไฟล์ข้อความ คุณสามารถสมมติว่าการป้อนรหัสมอร์สประกอบด้วยตัวอักษร AZ เท่านั้นและไม่จำเป็นต้องใช้หมายเลขที่ตรงกันหรือเครื่องหมายวรรคตอน

  2. ผลลัพธ์ควรมีเฉพาะคำที่อยู่ในไฟล์พจนานุกรมนี้ (อีกครั้งอย่าลังเลที่จะใช้วิธีการที่สะดวกในการเข้าถึงไฟล์พจนานุกรม) การถอดรหัสที่ถูกต้องทั้งหมดควรส่งออกไปยัง stdout และต้องใช้จุดและขีดกลางในอินพุต คำที่ตรงกันแต่ละคำในผลลัพธ์ควรคั่นด้วยช่องว่างและแต่ละการถอดรหัสที่เป็นไปได้ควรคั่นด้วยการขึ้นบรรทัดใหม่ คุณสามารถใช้ตัวพิมพ์ใหญ่ตัวพิมพ์เล็กหรือตัวพิมพ์เล็กได้ตามต้องการ

  3. ข้อ จำกัด ทั้งหมดเกี่ยวกับช่องโหว่มาตรฐานมีข้อยกเว้นหนึ่งข้อตามที่ระบุไว้ข้างต้นคุณสามารถเข้าถึงไฟล์พจนานุกรมที่อ้างถึงในข้อกำหนด 2 ผ่านการเชื่อมต่ออินเทอร์เน็ตหากคุณต้องการ การย่อ URL เป็นที่ยอมรับฉันเชื่อว่าgoo.gl/46I35Zน่าจะสั้นที่สุด

  4. นี่คือรหัสกอล์ฟรหัสที่สั้นที่สุดชนะ

หมายเหตุ: การโพสต์ไฟล์พจนานุกรมบน Pastebin เปลี่ยนการจบบรรทัดทั้งหมดเป็นลำดับสไตล์ 0A 0E ของ Windows โปรแกรมของคุณสามารถสันนิษฐานว่าลงท้ายด้วยบรรทัด 0A เท่านั้น, 0E เท่านั้นหรือ 0A 0E

กรณีทดสอบ:

การป้อนข้อมูล:

...... ... .. ----. ----- ... -..- ..

ผลลัพธ์ต้องมี:

สวัสดีชาวโลก

การป้อนข้อมูล:

... . ----- ----- .... ... - .. - .. ... --- - ... .... ... - ... .. ----- ... -. ---.-....-

ผลลัพธ์ต้องมี:

ปริศนาการเขียนโปรแกรมและรหัสกอล์ฟ

การป้อนข้อมูล:

-..... - ... ... - .. -.. .... --- --- .... ---- .. -.- --.. --- -. --- .... ... ... - ...... ... ... --- --- ..-- ---

ผลลัพธ์ต้องมี:

สุนัขจิ้งจอกสีน้ำตาลอย่างรวดเร็วกระโดดข้ามสุนัขขี้เกียจ


3
คุณจะบอกได้อย่างไรระหว่างAN (.- -.)และEG (. --.)?
seequ

2
@Sieg - การส่งออกจะต้องมีการถอดรหัสที่ถูกต้องทั้งสอง
Comintern

1
@Dennis - อ่าาา ... ฉันจะพนันได้ว่า Pastebin หรือเบราว์เซอร์ของฉันทำอย่างนั้น ไฟล์ต้นฉบับของฉันไม่มีไฟล์เหล่านั้น คุณสามารถเปลี่ยนตัวคั่นบรรทัดเป็นระบบที่เหมาะสมไม่มีการเปลี่ยนแปลงอื่น ๆ ฉันจะแก้ไขเป็นคำถามเมื่อฉันไม่ได้ใช้โทรศัพท์
องค์การคอมมิวนิสต์สากล

2
@Falko นั่นเป็นพฤติกรรมที่ถูกต้อง โปรดทราบว่าปัญหาแจ้งว่าผลลัพธ์ของคุณจะต้องมี "hello world" ไม่ใช่ว่าจะถูก จำกัด มันควรจะพิมพ์ decodings ที่ถูกต้องทั้งหมด
ฮอบส์

2
(เกือบกวีจริงๆ)
ฮอบส์

คำตอบ:


5

ทับทิม, 210

(1..(g=gets).size).map{|x|puts IO.read(?d).split.repeated_permutation(x).select{|p|p.join.gsub(/./,Hash[(?a..?z).zip"(;=/%513':07*)29@-+&,4.<>?".bytes.map{|b|('%b'%(b-35))[1,7].tr'01','.-'}])==g}.map{|r|r*' '}}

หากมีการฝึกซ้อมเช่น "over-golfing" ฉันสงสัยว่าฉันได้เข้าร่วมในครั้งนี้ วิธีนี้สร้างอาร์เรย์ของอาร์เรย์เรียงสับเปลี่ยนของคำในพจนานุกรมทั้งหมดตั้งแต่ความยาว 1 จนถึงความยาวของอินพุต เนื่องจาก "a" เป็นคำที่สั้นที่สุดในไฟล์พจนานุกรมและรหัสของมันมีความยาวสองตัวอักษรมันก็เพียงพอแล้วที่จะสร้างการเรียงสับเปลี่ยนของความยาวสูงสุดถึงครึ่งหนึ่งของขนาดอินพุต แต่การเพิ่ม/2นั้นเท่ากับการ verbosity ในโดเมนนี้ ดังนั้นฉันจึงงด

เมื่ออาร์เรย์การเปลี่ยนแปลงได้ถูกสร้างขึ้น ( NB : มันมีความยาว 45404 104ในกรณีของอินพุตตัวอย่าง pangrammatic) แต่ละอาร์เรย์การเปลี่ยนแปลงจะถูกต่อกันและตัวอักษรของมันจะถูกแทนที่ด้วยรหัสมอร์สแทนผ่าน(Regexp, Hash)ตัวแปรที่สะดวกกว่า#gsubวิธี; เราพบการถอดรหัสที่ถูกต้องหากสตริงนี้เท่ากับอินพุต

พจนานุกรมถูกอ่าน (หลายครั้ง) จากไฟล์ชื่อ "d" และอินพุตจะต้องไม่มีบรรทัดใหม่

ตัวอย่างการเรียกใช้ (ด้วยพจนานุกรมที่จะให้โอกาสในการต่อสู้กับโปรแกรมสิ้นสุดก่อนที่ความร้อนจากจักรวาล):

$ cat d
puzzles
and
code
dummy
golf
programming
$ echo -n .--..-.-----..-..-----..-.--..--...---..--...-.......--.-..-.-.----...--.---.-....-. | ruby morse.rb
programming puzzles and code golf
^C

5

Haskell, 296 ตัวอักษร

  • ไฟล์พจนานุกรม: ต้องเป็นไฟล์ข้อความชื่อ "d"
  • อินพุต: stdin อาจมีการขึ้นบรรทัดใหม่ แต่ไม่มีช่องว่างภายใน
main=do f<-readFile"d";getLine>>=mapM(putStrLn.unwords).(words f&)
i!""=[i]
(i:j)!(p:q)|i==p=j!q
_!_=[]
_&""=[[]]
d&i=do
w<-d
j<-i!(w>>=((replicate 97"X"++words".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --..")!!).fromEnum)
n<-d&j
[w:n]

คำอธิบายองค์ประกอบ:

  • mainอ่านพจนานุกรมอ่าน stdin ดำเนินการ&และจัดรูปแบบผลลัพธ์&ด้วยช่องว่างที่เหมาะสม
  • (replicate 97"X"++words".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --..")!!)(นิพจน์ภายในคำจำกัดความของ&) เป็นรายการที่มีดัชนีเป็นรหัสตัวอักษร (97 คือรหัสของ'a') และค่าเป็นลำดับมอร์ส
  • !(ฟังก์ชั่นชื่อเป็นตัวดำเนินการมัด) ตรงกับสตริงกับคำนำหน้า; หากคำนำหน้ามีอยู่ก็จะส่งคืนส่วนที่เหลือในรายการองค์ประกอบเดียว (ประสบความสำเร็จในรายการ monad) มิฉะนั้นรายการที่ว่างเปล่า (ความล้มเหลวในรายการ monad)
  • &ใช้รายการ monad สำหรับการดำเนินการ "nondeterministic" มัน

    1. เลือกรายการของd(คำพจนานุกรม)
    2. การใช้งาน!เพื่อให้ตรงกับรูปแบบมอร์สของคำว่า ( w>>=((…)!!).fromEnumซึ่งเทียบเท่ากับconcatMap (((…)!!) . fromEnum) w) กับสายป้อนi,
    3. เรียกตัวเอง ( d&j) เพื่อให้ตรงกับส่วนที่เหลือของสตริงและ
    4. ส่งคืนผลลัพธ์ที่เป็นไปได้ในรายการคำw:nในรายการ monad [w:n](ซึ่งสั้นกว่าที่เป็นรูปธรรมเทียบเท่าreturn (w:n))

    โปรดทราบว่าทุกบรรทัดหลังจากบรรทัด 6 เป็นส่วนหนึ่งของdoนิพจน์ที่เริ่มต้นในบรรทัดที่ 6 สิ่งนี้ใช้จำนวนอักขระเท่ากับการใช้เครื่องหมายอัฒภาคในบรรทัดเดียว แต่สามารถอ่านได้มากกว่าแม้ว่าคุณจะทำได้เพียงครั้งเดียวในโปรแกรม

โปรแกรมนี้ช้ามาก มันสามารถทำได้เร็วขึ้น (และอีกต่อไปเล็กน้อย) ได้อย่างง่ายดายโดยการจัดเก็บคำที่ไม่น่าสนใจถัดจากต้นฉบับในรายการแทนที่จะคำนวณใหม่ในการจับคู่แต่ละรูปแบบ สิ่งที่ต้องทำต่อไปจะมีการจัดเก็บคำในต้นไม้ไบนารีคีย์สัญลักษณ์มอร์ส (2 Ary Trie ) เพื่อหลีกเลี่ยงการพยายามที่สาขาที่ไม่จำเป็น

มันอาจจะทำให้สั้นลงเล็กน้อยหากแฟ้มพจนานุกรมไม่ได้มีสัญลักษณ์ที่ไม่ได้ใช้เช่น "-" ที่ช่วยให้การกำจัดของreplicate 97"X"++ในความโปรดปรานของการทำก่อน.(-97+)!!


ลูกชายเจ้ากรรมนั่นฉลาด +1 ถึงคุณ
Alexander Craggs

1
คุณรู้หรือไม่ว่า(+(-97))สามารถเขียนใหม่เป็น(-97+)?
ภูมิใจ haskeller

คุณควรลบคำจำกัดความที่สามของ h และเพิ่ม|0<1=[]ไปที่คำจำกัดความที่สอง
haskeller ภาคภูมิใจ

2
ใช้interactและชนะ 12 ตัวอักษร interact$unlines.map unwords.(words f&)
gxtaillon

1
คุณควรจะแทนที่concatMapด้วย>>=
ภูมิใจ haskeller

3

Python - 363 345

รหัส:

D,P='-.';U,N='-.-','.-.'
def s(b,i):
 if i=='':print b
 for w in open('d').read().split():
  C=''.join([dict(zip('abcdefghijklmnopqrstuvwxyz-\'23',[P+D,D+3*P,U+P,'-..',P,D+N,'--.',4*P,2*P,P+3*D,U,N+P,2*D,D+P,D*3,'.--.',D+U,N,P*3,D,'..-',3*P+D,'.--','-..-',U+D,'--..']+['']*4))[c]for c in w]);L=len(C)
  if i[:L]==C:s(b+' '+w,i[L:])
s('',input())

คำอธิบาย:

พจนานุกรมจะต้องจัดเก็บเป็นไฟล์ข้อความธรรมดาชื่อ "d"

D, P, UและNเป็นเพียงบางส่วนตัวแปรช่วยสำหรับคำนิยามสั้นของตารางการค้นหามอร์ส

s(i)เป็นฟังก์ชันเวียนที่พิมพ์ส่วนข้อความที่แปลก่อนหน้านี้pและแต่ละคำแปลที่ถูกต้องของส่วนที่เหลือรหัสi: ถ้าiเป็นที่ว่างเปล่าเรามาถึงจุดสิ้นสุดของรหัสนั้นbมีการแปลทั้งทำให้เราเพียงแค่printมัน มิฉะนั้นเราจะตรวจสอบแต่ละคำwในพจนานุกรมdแปลเป็นรหัสมอร์สCและหากรหัสที่เหลือiเริ่มต้นด้วยCเราเพิ่มคำwลงในจุดเริ่มต้นที่แปลbแล้วและเรียกใช้ฟังก์ชันsซ้ำในส่วนที่เหลือ

หมายเหตุเกี่ยวกับประสิทธิภาพ:

นี่เป็นเวอร์ชั่นช้า แต่เล่นกอล์ฟ โดยเฉพาะอย่างยิ่งการโหลดพจนานุกรมและการสร้างตารางการค้นหามอร์ส ( dict(zip(...))) ในแต่ละการวนซ้ำ (เพื่อหลีกเลี่ยงตัวแปรเพิ่มเติม) ค่าใช้จ่ายจำนวนมาก และจะมีประสิทธิภาพมากขึ้นในการแปลคำทั้งหมดในไฟล์พจนานุกรมล่วงหน้าหนึ่งครั้งและไม่ใช่ในการเรียกซ้ำตามความต้องการแต่ละครั้ง ความคิดเหล่านี้นำไปสู่รุ่นต่อไปมี 40 ตัวอักษรมากขึ้น แต่ที่สำคัญความเร็วขึ้น:

d=open('d').read().split()
D,P='-.';U,N='-.-','.-.'
M=dict(zip('abcdefghijklmnopqrstuvwxyz-\'23',[P+D,D+3*P,U+P,'-..',P,D+N,'--.',4*P,2*P,P+3*D,U,N+P,2*D,D+P,D*3,'.--.',D+U,N,P*3,D,'..-',3*P+D,'.--','-..-',U+D,'--..']+['']*4))
T=[''.join([M[c]for c in w])for w in d]
def s(b,i):
 if i=='':print b
 for j,w in enumerate(d):
  C=T[j];L=len(C)
  if i[:L]==C:s(b+' '+w,i[L:])
s('',input())

คุณสามารถบันทึก 2 ตัวอักษรโดยการแทนที่ด้วย.startswith(C) [:len(C)]==C
Greg Hewgill

ว้าวขอบคุณ! มันค่อนข้างแปลกเพราะการโหลดทั้งพจนานุกรมในการเรียกซ้ำแต่ละครั้งช่วยประหยัดอักขระและทำให้อัลกอริทึมช้าลงอีกครั้ง
Falko

@ GregHewgill: ใช่นั่นคือสิ่งที่ฉันทำในตอนแรก ฉันเพิ่งแก้ไขคำตอบของฉันเพื่อแก้ไขทั้งสองเวอร์ชัน
Falko

1
คุณสามารถสร้างผลลัพธ์ที่น่าสนใจ (คำที่ยาวกว่า) ได้เร็วขึ้นโดยการเรียงลำดับพจนานุกรมโดยลดความยาวของคำลง d=sorted(open('d').read().split(),key=len,reverse=1)หรือทำสิ่งนั้นจากภายนอกด้วยการจัดเรียงพจนานุกรมของคุณล่วงหน้า
Greg Hewgill

Heck ถ้าคุณสามารถฟอร์แมตไฟล์พจนานุกรมรูปแบบที่เป็นที่ precalculated หลามพจนานุกรมและM=eval(open('d').read()):)
เกร็ก Hewgill

3

Perl (5.10+) 293 ตัวอักษร

ควรบันทึกไฟล์พจนานุกรมเป็น "d" (และควรอยู่ในรูปแบบ unix หากคุณไม่ต้องการ CR ระหว่างคำ) ใส่มอร์สใน stdin โดยไม่ขึ้นบรรทัดใหม่ (ใช้echo -n)

open D,d;chomp(@w=<D>);@m{a..z}=map{substr(sprintf("%b",-61+ord),1)=~y/01/.-/r}
'BUWI?OKMATJQDCLSZGE@FNHVXY'=~/./g;%w=map{$_,qr#^\Q@{[s/./$m{$&}/reg]}#}@w;
@a=[$i=<>];while(@a){say join$",@{$$_[1]}for grep!$$_[0],@a;
@a=map{$x=$_;map{$$x[0]=~$w{$_}?[substr($$x[0],$+[0]),[@{$$x[1]},$_]]:()}@w}@a}

(แบ่งบรรทัดสำหรับการจัดรูปแบบเท่านั้น)

รหัสไม่ได้รับการตอบกลับ:

# Read the word list
open my $dictionary, '<', 'd';
chomp(my @words = <$dictionary>);

# Define morse characters
my %morse;
@morse{'a' .. 'z'} = map {
  $n = ord($_) - 61;
  $bits = sprintf "%b", $n;
  $bits =~ tr/01/.-/;
  substr $bits, 1;
} split //, 'BUWI?OKMATJQDCLSZGE@FNHVXY';

# Make a hash of words to regexes that match their morse representation
my %morse_words = map {
  my $morse_word = s/./$morse{$_}/reg;
  ($_ => qr/^\Q$morse_word/)
} @words;

# Read the input
my $input = <>;

# Initialize the state
my @candidates = ({ remaining => $input, words => [] });

while (@candidates) {
  # Print matches
  for my $solution (grep { $_->{remaining} eq '' } @candidates) {
    say join " ", @{ $solution->{words} }; 
  } 
  # Generate new solutions
  @candidates = map {
    my $candidate = $_;
    map {
      $candidate->{remaining} =~ $morse_words{$_}
        ? {
          remaining => substr( $candidate->{remaining}, $+[0] ),
          words => [ @{ $candidate->{words} }, $_ ],
        }
        : ()
    } @words
  } @candidates;
}

วิธีการทำงาน:

สัญลักษณ์รหัสมอร์สจะถูกจัดเก็บโดยการเปลี่ยน "." และ "-" เป็นเลขฐานสอง 0 และ 1, การเตรียม "1" (เพื่อให้จุดนำไม่ถูก gobbled ขึ้น), แปลงเลขฐานสองเป็นทศนิยมแล้วเข้ารหัสอักขระด้วยค่า 61 สูงกว่า (ซึ่งทำให้ฉันทั้งหมด ตัวอักษรที่พิมพ์ได้และไม่มีสิ่งใดที่ต้องการแบ็กสแลช)

ฉันคิดว่านี่เป็นปัญหาการแบ่งพาร์ติชันและสร้างโซลูชันขึ้นมา สำหรับแต่ละคำในพจนานุกรมมันจะสร้างอ็อบเจกต์ regex ที่จะจับคู่ (และจับ) คำว่ามอร์สแบบ spaceless ที่เป็นตัวแทนของคำที่จุดเริ่มต้นของสตริง จากนั้นจะเริ่มต้นค้นหาแบบกว้างโดยการสร้างรัฐที่ไม่มีคำที่ตรงกันและมีอินพุตทั้งหมดเป็น "อินพุตที่เหลือ" จากนั้นจะขยายแต่ละรัฐโดยค้นหาคำที่ตรงกับจุดเริ่มต้นของอินพุตที่เหลือและสร้างสถานะใหม่ที่เพิ่มคำลงในคำที่ตรงกันและลบมอร์สออกจากอินพุตที่เหลือ รัฐที่ไม่มีการป้อนข้อมูลที่เหลือจะประสบความสำเร็จและมีรายการคำที่พิมพ์ รัฐที่ไม่สามารถจับคู่คำใด ๆ (รวมถึงคำที่ประสบความสำเร็จ) ไม่สร้างสถานะลูก

โปรดทราบว่าในเวอร์ชันที่ไม่ได้รับการแต่งอเมริกานั้นจะมีการแฮชเพื่อให้สามารถอ่านได้ ในเวอร์ชั่น golfed พวกเขากำลังอาร์เรย์ (สำหรับรหัสที่สั้นลงและใช้หน่วยความจำน้อยกว่า); slot [0]เป็นอินพุตที่เหลือและสล็อต[1]เป็นคำที่ตรงกัน

ความเห็น

นี่ช้ามาก ฉันสงสัยว่ามีวิธีแก้ปัญหาหรือไม่ ฉันพยายามสร้างโดยใช้ Marpa (ตัวแยกวิเคราะห์ Earley ที่มีความสามารถในการแยกวิเคราะห์หลายรายการสำหรับสตริงอินพุตเดียว) แต่หน่วยความจำไม่เพียงพอที่จะสร้างไวยากรณ์ บางทีถ้าฉันใช้ API ระดับต่ำกว่าแทนที่จะป้อน BNF ...


ถ้าฉันจะเพิ่มความต้องการเช่นเดียวกับเควินเรด (ขึ้นบรรทัดใหม่ในการป้อนข้อมูลไม่ได้) ผมสามารถบันทึก 7 chomp()ตัวอักษรโดยการเอา ฉันควร?
ฮอบส์

"ใช้วิธีใดก็ได้อย่างสะดวกสบาย"
Comintern

โกนหนวด 2 ไบต์กับแทนord ord$_โกน 1 ไบต์พูดjoin$"แทนjoin" "
Zaid

2

Haskell - 418

ปัญหา decoing นี้สามารถแก้ไขได้อย่างมีประสิทธิภาพโดยการเขียนโปรแกรมแบบไดนามิก ฉันรู้ว่านี่เป็น codegolf แต่ฉันชอบรหัสที่รวดเร็ว

บอกว่าเรามีสายป้อนsแล้วเราสร้างอาร์เรย์dp, คือรายการผลการถอดรหัสที่ถูกต้องของอักขระย่อยdp[i] s[:i]สำหรับแต่ละคำwในพจนานุกรมแรกที่เราเข้ารหัสมันmwแล้วเราสามารถคำนวณเป็นส่วนหนึ่งของdp[i]จากถ้าdp[i - length(mw)] s[i - length(mw):i] == mwความซับซ้อนเวลาของอาคารคือdp O({count of words} {length of s} {max word length})ในที่สุดdp[length(s)]องค์ประกอบสุดท้ายคือสิ่งที่เราต้องการ

ในความเป็นจริงเราไม่จำเป็นต้องจัดเก็บการถอดรหัสทั้งหมดไว้เป็นองค์ประกอบของแต่ละdp[i]รายการ สิ่งที่เราต้องการคือคำที่ถอดรหัสล่าสุด ทำให้การดำเนินการเร็วขึ้นมาก ใช้เวลาน้อยกว่า 2 วินาทีในการทำเคส "hello world" บนแล็ปท็อป i3 ของฉัน สำหรับกรณีอื่น ๆ ที่โพสต์ในคำถามโปรแกรมจะไม่เสร็จสมบูรณ์เนื่องจากมีเอาต์พุตมากเกินไป

การใช้เทคนิคการเขียนโปรแกรมแบบไดนามิกที่เราสามารถคำนวณจำนวน decodings คุณสามารถค้นหารหัสที่นี่ ผล:

input: ......-...-..---.-----.-..-..-..
count: 403856

input: .--..-.-----..-..-----..-.--..--...---..--...-.......--.-..-.-.----...--.---.-....-.
count: 2889424682038128

input: -.....--.-..-..-.-.-.--....-.---.---...-.----..-.---..---.--....---...-..-.-......-...---..-.---..-----.
count: 4986181473975221635

Ungolfed

import Control.Monad

morseTable :: [(Char, String)]
morseTable = zip ['a'..'z'] $ words ".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --.."

wordToMorse :: String -> Maybe String
wordToMorse xs = return . concat =<< mapM (`lookup` morseTable) xs

slice :: (Int, Int) -> [a] -> [a]
slice (start, end) = take (end - start) . drop start

decode :: String -> String -> IO ()
decode dict s = trace (length s) [] where
  dict' = [(w, maybe "x" id . wordToMorse $ w) | w <- lines dict]
  dp = flip map [0..length s] $ \i -> [(j, w) |
        (w, mw) <- dict', let j = i - length mw, j >= 0 && mw == slice (j, i) s]

  trace :: Int -> [String] -> IO ()
  trace 0 prefix = putStrLn . unwords $ prefix
  trace i prefix = sequence_ [trace j (w:prefix) | (j, w) <- dp !! i]

main :: IO ()
main = do
  ws <- readFile "wordlist.txt"
  decode ws =<< getLine

แข็งแรงเล่นกอล์ฟ

import Control.Monad
l=length
t=zip['a'..]$words".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --.."
h s=return.concat=<<mapM(`lookup`t)s
f d s=g(l s)[]where g 0 p=putStrLn.unwords$p;g i p=sequence_[g j(w:p)|(j,w)<-map(\i->[(j,w)|(w,m)<-[(w,maybe"x"id.h$w)|w<-lines d],let j=i-l m,j>=0&&m==(take(i-j).drop j$s)])[0..l s]!!i]
main=do d<-readFile"d";f d=<<getLine

ดีใจที่ได้เห็นโซลูชันที่มีประสิทธิภาพพอสมควร ตอนนี้ผมก็ต้องเข้าใจว่ามัน :)
ฮอบส์

2

PHP, 234 226 ไบต์

function f($s,$r=""){$s?:print"$r
";foreach(file(d)as$w){for($i=+$m="";$p=@strpos(__etianmsurwdkgohvf_l_pjbxcyzq,$w[$i++]);)$m.=strtr(substr(decbin($p),1),10,"-.");0!==strpos($s,$m)?:g(substr($s,strlen($m)),$r.trim($w)." ");}}

dฟังก์ชันเวียนใช้พจนานุกรมจากไฟล์ชื่อ
ล้มเหลวสำหรับทุกคำในพจนานุกรมที่มีตัวอักษรที่ไม่ใช่

คุณสามารถใช้ชื่อไฟล์ใด ๆ ถ้าคุณdefine ("d","<filename>");ก่อนที่จะเรียกฟังก์ชั่น

เพิ่ม 2 หรือ 3 ไบต์สำหรับการดำเนินการได้เร็วขึ้น:
ลบ$s?:print"$r\n";แทรก$s!=$m?ก่อน0!==และก่อนที่จะ:print$r.$w ;}}

ทำให้พังถล่ม

function f($s,$r="")
{
    $s?:print"$r\n";            // if input is empty, print result
    foreach(file(d)as$w)        // loop through words
    {
        // translate to morse:
        for($i=+$m="";              // init morse to empty string, $i to 0
                                        // loop while character is in the string
            $p=@strpos(__etianmsurwdkgohvf_l_pjbxcyzq,$w[$i++])
        ;)
            $m.=                        // 4. append to word morse code
                strtr(
                    substr(
                        decbin($p)      // 1: convert position to base 2
                    ,1)                 // 2: substr: remove leading `1`
                ,10,"-.")               // 3. strtr: dot for 0, dash for 1
            ;
        0!==strpos($s,$m)           // if $s starts with $m
            ?:f(                        // recurse
                substr($s,strlen($m)),  // with rest of $s as input
                $r.trim($w)." "         // and $r + word + space as result
            )
        ;
    }
}

1

Groovy 377 337

r=[:];t={x='',p=''->r[s[0]]=p+x;s=s.substring(1);if(p.size()<3){t('.',p+x);t('-',p+x)}};s='-eishvuf-arl-wpjtndbxkcymgzqo--';t()
m=('d'as File).readLines().groupBy{it.collect{r.get(it,0)}.join()}
f={it,h=[]->it.size().times{i->k=it[0..i]
if(k in m){m[k].each{j->f(it.substring(i+1),h+[j])}}}
if(it.empty){println h.join(' ')}}
f(args[0])

หมายเหตุ

Dict dจะต้องไฟล์ชื่อ สตริงมอร์สถูกส่งผ่านโดยบรรทัดคำสั่ง เช่น:

% groovy morse.groovy ......-...-..---.-----.-..-..-.. | grep 'hello world'
hello world

สำหรับ "การบีบอัดรหัสมอร์ส" ฉันใช้ต้นไม้ไบนารี

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