简体   繁体   中英

Convert input string into Morse Code with Clojure

I am trying to develop a converter that takes an input string and converts it into morse code through a Morse Library map, while also respecting functional programming rules. Sorry for any clarification issues, I am new to Stack Overflow

(ns clojureassignment.core
  (:gen-class))
(require '[clojure.string :as str])

;this function is where the converter is developed

(defn  morse->ASCI
  [x]
  

  (def morse_Library {: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 "--.."
                      :0 "-----":1 ".----":2 "..---":3 "...--":4 "....-":5 "....."
                      :6 "-....":7 "--...":8 "---..":9 "----."})
 

  (let [stringVector  (str/upper-case(seq x))]         ;divide the string into a sequence of characters

;trying to create iteration of the input where it checks if its value is found in the morse library

    (doseq [[stringVector] (morse_Library)]       
      (if (= stringVector (morse_Library)
           (do  (println(str (key morse_Library))))
             (do  (println("characters not found"))))
             )))
    
  (print (str/upper-case stringVector))


    )








  (defn -main
    [& args]

    (println "ASCII to Morse Converter.")
    (println "Make sure to include whitespaces after each ASCII character. Add String")


    (def stringInput (read-line))

    (println stringInput )

    (morse->ASCI stringInput)


  


    )



  (-main)

I tried to create a "doseq" iteration where it checks if the value is found in the map.

Good things:

  • using a map for your morse translation; maps are also functions and make it easy to write a transformation like this

Not so good things:

  • don't def inside other def :s - it's used to define namespace global things and it is not like var or auto or whatever you know from other languages
  • don't use keywords as map keys, if you don't plan to use them like that; Clojure takes pretty much anything as key. So in your case use chars
  • don't seq and then upper-case - wrong order - this will give you the .toString() from a sequence of characters otherwise
  • don't name things all the same ( stringVector )
  • doseq is for side-effects; you don't want your morse-code function to do side-effects (you maybe want to print it later); in functional programming you shift your side-effects to the edges - this way your code becomes easier to test and reason about
  • you pretty much never need :gen-class
  • use the correct way to require in the namespace
  • Clojure prefers snake-case over camelCase

(random rant: if you are using tutorialpoint (I assume this from several things going wrong here and having them seen there) to learn Clojure: do yourself a favour and look for another resource; as of now they don't teach idiomatic Clojure!

Make your transformation a pure function:

  • upper-case the input
  • make a seq from it (this now is a sequence of chars ) - but you don't actually have to do this, because the next step will take care of it
  • map the look-up-table with your designated fallback over each char
  • join the result

This will look something like this:

(def morse {\A ".-" ,,, })

(->> input
     (str/upper-case)
     (map #(morse % "???"))
     (str/join))
;; preparation of morse map
(ns morse
  (:require [clojure.string :as str]))

;; I stole morse dictionary from some python code in:
;; https://www.geeksforgeeks.org/morse-code-translator-python/

(def s "{ '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':'-----', ', ':'--..--', '.':'.-.-.-',
                    '?':'..--..', '/':'-..-.', '-':'-....-',
                    '(':'-.--.', ')':'-.--.-'}")

;; and transformed it using clojure to a clojure map:
(def m (read-string (str/replace 
                     (str/replace 
                      (str/replace 
                       (str/replace s
                                    "\n" "") 
                       "                    " " ")
                      ":" " ")
                     "'" "\"")))
;; now `m` contains the string-to-morse map

The actual answer starts here:

;; convert any text string to a morse string:
(defn string-to-morse [s]
  (str/join " "
            (map #(get m (str/upper-case %)) (str/split s #""))))

;; and this function can transform the output back to text:
(defn morse-to-string [morse-string]
  (let [ms (zipmap (vals m) (keys m))]
    (str/join (map #(get (zipmap (vals m) (keys m)) % " ") 
                   (str/split morse-string #" ")))))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM