Decoder Kode Morse di Perl

Saya mencoba untuk belajar sendiri Perl dan saya telah berjuang... Tadi malam saya membuat program untuk menghitung rata-rata sekumpulan angka yang diberikan pengguna untuk mempelajari tentang daftar dan masukan pengguna jadi hari ini saya pikir saya akan melakukannya decoder Kode Morse untuk mempelajari tentang Hash. Saya telah membaca buku yang saya beli dan buku itu tidak menjelaskan hash dengan baik... sebenarnya tidak menjelaskan banyak hal dengan baik. Bantuan apa pun akan dihargai!

Bagaimanapun, saya ingin menulis sebuah program yang menerjemahkan kode morse yang dimasukkan pengguna. Jadi pengguna akan memasukkan:

-.-.
.-
-
...
!
.-.
..-
.-..
.

Tanda seru menandakan kata yang terpisah. Pesan ini akan mengembalikan "Aturan Kucing" kepada pengguna. Di bawah ini adalah kode yang saya miliki sejauh ini... Ingat.. Saya telah memprogram di Perl kurang dari 24 jam haha.

Kode:

  use 5.010;




my %morsecode=(
    '.-'    =>'A',  '-...'  =>'B',  '-.-.'  =>'C',  '-..'   =>'D',
    '.' =>'E',  '..-.'  =>'F',  '--.'   =>'G',  '....'  =>'H',
    '..'    =>'I',  '.---'  =>'J',  '-.-'   =>'K',  '.-..'  =>'L',
    '--'    =>'M',  '-.'    =>'N',  '---'   =>'O',  '.--.'  =>'P',
    '--.-'  =>'Q',  '.-.'   =>'R',  '...'   =>'S',  '-' =>'T',
    '..-'   =>'U',  '...-'  =>'V',  '.--'   =>'W',  '-..-'  =>'X',
    '-.--'  =>'Y',  '--..'  =>'Z',  '.----' =>'1',  '..---' =>'2',
    '...--' =>'3',  '....-' =>'4',  '.....' =>'5',  '-....' =>'6',
    '--...' =>'7',  '---..' =>'8',  '----.' =>'9',  '-----' =>'0',
    '.-.-.-'=>'.',  '--..--'=>',',  '---...'=>':',  '..--..'=>'?',
    '.----.'=>'\'', '-...-' =>'-',  '-..-.' =>'/',  '.-..-.'=>'\"'
);

my @k = keys %morsecode;
my @v = values %morsecode;

say "Enter a message in morse code separated by a line. Use the exclamation point (!) to separate words. Hit Control+D to signal the end of input.";
my @message = <STDIN>;
chomp @message;

my $decodedMessage = encode(@message);


sub encode {
    foreach @_ {
    if (@_ == @k) {
        return @k;

#This is where I am confused... I am going to have to add the values to an array, but I don't really know how to go about it.


        }
    else if(@_ == '!') {return ' '}
    else
    {
    return 'Input is not valid';
    }
    }
}

person JLott    schedule 25.01.2013    source sumber
comment
Saya sarankan untuk melihat tizag.com/perlT/perlarrays.php dan tizag.com/perlT/perlhashes.php. Atau tutorial array/hash lainnya yang Anda temukan di Google dalam hal ini. Semoga beruntung.   -  person dutt    schedule 26.01.2013
comment
Terima kasih! Saya menghargainya!   -  person JLott    schedule 26.01.2013
comment
Titik awal yang baik: Situs web Pelajari Perl, Buku Perl modern, Mempelajari buku Perl, juga ini akan membantu dengan hash   -  person Craig Treptow    schedule 26.01.2013
comment
Selain itu, sangat disarankan untuk memasukkan use warnings; dan use strict; di semua kode Anda untuk membantu menemukan kesalahan.   -  person Craig Treptow    schedule 26.01.2013
comment
Sebelum Anda melakukan hal lain, letakkan use strict; dan use warnings; di bagian atas skrip Anda. Mereka membantu, meskipun Anda mungkin tidak akan menyukainya pada awalnya. Omong-omong, pilihan proyek pertama yang layak untuk mempelajari tentang hash.   -  person William    schedule 26.01.2013
comment
@k dan @v tidak ada gunanya. Sub Anda juga harus diberi nama decode bukan encode.   -  person Brad Gilbert    schedule 26.01.2013
comment
Terima kasih atas bantuan Anda semua! Ini sangat membantu dalam mempelajari banyak dasar-dasar yang berguna.   -  person JLott    schedule 26.01.2013


Jawaban (3)


Kode Anda mengandung dua kesalahan sintaksis: foreach memerlukan daftar untuk mengulanginya; ini artinya orang tua. Tidak seperti C dan bahasa lainnya, Perl tidak mendukung else if (...). Sebagai gantinya, gunakan elsif (...).

Lalu ada beberapa kesalahan semantik: Nilai iterasi saat ini disimpan di $_. Array @_ berisi argumen panggilan ke fungsi Anda.

Perl membandingkan string dan angka secara berbeda:

Strings Numbers
eq      ==
lt      <
gt      >
le      <=
ge      >=
ne      !=
cmp     <=>

Gunakan operator yang benar untuk tugas yang ada, dalam hal ini, operator berserabut.

(Kode Anda @_ == @k melakukan sesuatu, yaitu menggunakan array dalam konteks numerik. Ini menghasilkan jumlah elemen, yang kemudian dibandingkan. @_ == '!' sungguh aneh.)


Yang sebenarnya ingin Anda lakukan adalah memetakan nilai yang dimasukkan ke daftar karakter. Hash Anda mendefinisikan pemetaan ini, tetapi kami ingin menerapkannya. Perl memiliki fungsi map, cara kerjanya seperti itu

@out_list = map { ACTION } @in_list;

Di dalam blok tindakan, nilai saat ini tersedia sebagai $_.

Kita ingin tindakan kita mencari nilai yang sesuai dalam hash, atau menyertakan pesan kesalahan jika tidak ada pemetaan untuk string input:

my @letters = map { $morsecode{$_} // "<unknown code $_>" } @message;

Ini mengasumsikan ! terdaftar sebagai spasi di hash kode morse.

Kami kemudian membuat satu string dari huruf-huruf ini dengan joining dengan string kosong:

my $translated_message = join "", @letters;

Dan jangan lupa untuk mencetak hasilnya!


Kode lengkapnya:

#!/usr/bin/perl
use strict; use warnings; use 5.012;

my %morsecode=(
  '.-'    =>'A',  '-...'  =>'B',  '-.-.'  =>'C',  '-..'   =>'D',
  '.'     =>'E',  '..-.'  =>'F',  '--.'   =>'G',  '....'  =>'H',
  '..'    =>'I',  '.---'  =>'J',  '-.-'   =>'K',  '.-..'  =>'L',
  '--'    =>'M',  '-.'    =>'N',  '---'   =>'O',  '.--.'  =>'P',
  '--.-'  =>'Q',  '.-.'   =>'R',  '...'   =>'S',  '-'     =>'T',
  '..-'   =>'U',  '...-'  =>'V',  '.--'   =>'W',  '-..-'  =>'X',
  '-.--'  =>'Y',  '--..'  =>'Z',  '.----' =>'1',  '..---' =>'2',
  '...--' =>'3',  '....-' =>'4',  '.....' =>'5',  '-....' =>'6',
  '--...' =>'7',  '---..' =>'8',  '----.' =>'9',  '-----' =>'0',
  '.-.-.-'=>'.',  '--..--'=>',',  '---...'=>':',  '..--..'=>'?',
  '.----.'=>'\'', '-...-' =>'-',  '-..-.' =>'/',  '.-..-.'=>'"',
  '!'     =>' ',
);

say "Please type in your morse message:";
my @codes = <>;
chomp @codes;

my $message = join "", map { $morsecode{$_} // "<unknown code $_>" } @codes;

say "You said:";
say $message;

Ini menghasilkan keluaran yang diinginkan.

person amon    schedule 25.01.2013
comment
Ini menghasilkan keluaran yang diinginkan ... jika setiap karakter berada pada baris terpisah? - person mob; 26.01.2013
comment
@mob Ini mematuhi format input yang ditentukan oleh OP. Outputnya tidak berisi baris baru. - person amon; 26.01.2013
comment
Bagus! Belajar lebih dari yang saya harapkan. Penjelasan yang bagus. - person JLott; 26.01.2013

Ada banyak manfaat dalam mempelajari bagaimana dan mengapa, tapi inilah alasannya:

sub encode {
  my $output;
  foreach my $symbol (@_) {
    my $letter = $morsecode{$symbol};
    die "Don't know how to decode $symbol" unless defined $letter;
    $output .= $letter
  }
  return $output;
}

atau bahkan hanya sub encode { join '', map $morsecode{$_}, @_ } jika Anda tidak terlalu khawatir dengan pemeriksaan kesalahan. @k dan @v tidak diperlukan untuk apa pun.

person hobbs    schedule 25.01.2013

Mencari nilai dalam hash adalah pekerjaan yang sangat intens, sebaiknya Anda hanya menggunakan hash terbalik. Anda dapat dengan mudah membalikkan hash dengan fungsi terbalik di Perl. Selain itu, saat melihat kode Anda, saya telah melihat bahwa Anda dapat memasukkan input huruf kecil. Namun saat mencari hash pada kunci, ini peka huruf besar-kecil. Jadi, Anda perlu huruf besar masukan Anda. Selain itu, saya tidak terlalu menyukai cara "mengakhiri" STDIN. Kata/tanda keluar akan lebih baik dan lebih bersih.

Saya mengambil kode Anda

my %morsecode=(
    '.-'    =>'A',  '-...'  =>'B',  '-.-.'  =>'C',  '-..'   =>'D',
    '.' =>'E',  '..-.'  =>'F',  '--.'   =>'G',  '....'  =>'H',
    '..'    =>'I',  '.---'  =>'J',  '-.-'   =>'K',  '.-..'  =>'L',
    '--'    =>'M',  '-.'    =>'N',  '---'   =>'O',  '.--.'  =>'P',
    '--.-'  =>'Q',  '.-.'   =>'R',  '...'   =>'S',  '-' =>'T',
    '..-'   =>'U',  '...-'  =>'V',  '.--'   =>'W',  '-..-'  =>'X',
    '-.--'  =>'Y',  '--..'  =>'Z',  '.----' =>'1',  '..---' =>'2',
    '...--' =>'3',  '....-' =>'4',  '.....' =>'5',  '-....' =>'6',
    '--...' =>'7',  '---..' =>'8',  '----.' =>'9',  '-----' =>'0',
    '.-.-.-'=>'.',  '--..--'=>',',  '---...'=>':',  '..--..'=>'?',
    '.----.'=>'\'', '-...-' =>'-',  '-..-.' =>'/',  '.-..-.'=>'\"'
);
my %reversemorse = reverse %morsecode;
print "Enter a message\n";
chomp (my $message = <STDIN>);
print &encode($message);

sub encode{
    my $origmsg = shift(@_);
    my @letters = split('',$origmsg);
    my $morse = '';
    foreach $l(@letters)
    {
        $morse .= $reversemorse{uc($l)}." ";
    }    
    return $morse;
}
person Tom    schedule 25.01.2013