Skip to content
Advertisement

Decode the Morse code, advanced JS (codewars)

Here is a task:

When transmitting the Morse code, the international standard specifies that:

“Dot” – is 1 time unit long. “Dash” – is 3 time units long. Pause between dots and dashes in a character – is 1 time unit long. Pause between characters inside a word – is 3 time units long. Pause between words – is 7 time units long. However, the standard does not specify how long that “time unit” is. And in fact different operators would transmit at different speed. An amateur person may need a few seconds to transmit a single character, a skilled professional can transmit 60 words per minute, and robotic transmitters may go way faster.

For this kata we assume the message receiving is performed automatically by the hardware that checks the line periodically, and if the line is connected (the key at the remote station is down), 1 is recorded, and if the line is not connected (remote key is up), 0 is recorded. After the message is fully received, it gets to you for decoding as a string containing only symbols 0 and 1.

For example, the message HEY JUDE, that is ···· · −·−− ·−−− ··− −·· · may be received as follows:

1100110011001100000011000000111111001100111111001111110000000000000011001111110011111100111111000000110011001111110000001111110011001100000011

As you may see, this transmission is perfectly accurate according to the standard, and the hardware sampled the line exactly two times per “dot”.

That said, your task is to implement two functions:

Function decodeBits(bits), that should find out the transmission rate of the message, correctly decode the message to dots ., dashes – and spaces (one between characters, three between words) and return those as a string. Note that some extra 0’s may naturally occur at the beginning and the end of a message, make sure to ignore them. Also if you have trouble discerning if the particular sequence of 1’s is a dot or a dash, assume it’s a dot. 2. Function decodeMorse(morseCode), that would take the output of the previous function and return a human-readable string.

Here is my code:

var MORSE_CODE = {
    ".-":"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",
};

var decodeBits = function(bits){

  const trimBits = bits.replace(/(^0+|0+$)/g, '').split('')
  const result = []
  var word = []
  if(trimBits.length > 3){
    trimBits.every((v, i, array) => {
      if(i > 0 && i < array.length - 1){
        return v == array[i-1] ? word.push(v) : result.push(word) && (word = []) && word.push(v)
      }else  if(i == array.length - 1){
        return v == array[i-1] ? word.push(v) && result.push(word) : result.push(word) && result.push([v])
      }else{
        return word.push(v)
      }
    })
    if(result.length === 1){
      return result[0][0] == 1 ? '.'.repeat(result[0].length / 3) : '-'.repeat(result[0].length / 3)
    }else if(result.map((v) => v.join(''))[1].length == 1 && result.length == 3){
      let result1 = result.map((v) => v.join(''))
      return result1.map((v) => v[0] == 1 ? '.' : '   ').join('')

    }else{
      return result.map((v) => v.join('')).map((v) => {
        if(v[0] == 0){
          if(v.length % 2 == 0){
            if(v.length > 6){
              return '       '
            }if(v.length == 6){
              return '   '
            }else{
              return ' '
            }
          }else if(v.length >= 6){
            return '       '
          }else if(v.length === 3){
            return '   '
          }else{
            return String.fromCharCode(32)
          }
        }else if(v[0] == 1){
          if(v.length % 2 == 0 && v.length % 3 != 0){
            return String.fromCharCode(46).repeat(v.length / 2)
          }else if(v.length % 3 == 0){
            return String.fromCharCode(45)
          }else{
            return String.fromCharCode(46)
          }
        }
      }).join('')
    }
  }else{
    
    return trimBits.every((v, i, arr) => v === arr[0]) && trimBits[0] == 1 ? '.' : '..'
  }
}

var decodeMorse = function(morseCode){
  return morseCode.split('       ').map((v) => v.split('   ')).map((v) => v.map((val) => MORSE_CODE[val.replace(/ /g, '')]).join('')).join(' ')
}

decodeMorse(decodeBits('1100110011001100000011000000111111001100111111001111110000000000000011001111110011111100111111000000110011001111110000001111110011001100000011'))// returns 'HEY JUDE'
decodeMorse(decodeBits('1110111')) //returns EE
console.log(decodeMorse(decodeBits('00011100010101010001000000011101110101110001010111000101000111010111010001110101110000000111010101000101110100011101110111000101110111000111010000000101011101000111011101110001110101011100000001011101110111000101011100011101110001011101110100010101000000011101110111000101010111000100010111010000000111000101010100010000000101110101000101110001110111010100011101011101110000000111010100011101110111000111011101000101110101110101110'))) //THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.

The problem is that every time I’m running my code I’ve got the same issues:

Expected: 'A', instead got: 'EE'
Expected: 'M', instead got: 'EE'
Expected: 'E', instead got: 'I'

Expected: 'THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.', instead got: 'T H E Q U I C K B R O W N F O X J U M P S O V E R T H E L A Z Y D O G .'

I’ve tried all of my best and I’ve stacked. Can anybody help me to find the solution here? What am I doing wrong at this code?

For debugging:

decodeMorse(decodeBits('1100110011001100000011000000111111001100111111001111110000000000000011001111110011111100111111000000110011001111110000001111110011001100000011'))// returns 'HEY JUDE'
decodeMorse(decodeBits('1110111')) //returns EE

Updated post! I’m very close. Something wrong with spaces and with single letter.

P.S. The error might be in the decoder logic where I’m trying to resolve what should I push to the array result dash or dot.

Advertisement

Answer

I’ve done this! My first the most interesting task in js. The reason of failure was wrong spaces in condition. I should prevent that spaces can be odd and even number of zeros. Upvote it please. Maybe it will help someone. I’ve spend almost 10 hours to resolve it xD

var MORSE_CODE = {
        ".-":"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",
    };

var decodeBits = function(bits){

  const trimBits = bits.replace(/(^0+|0+$)/g, '').split('')
  const result = []
  var word = []
  if(trimBits.length > 3){
    trimBits.every((v, i, array) => {
      if(i > 0 && i < array.length - 1){
        return v == array[i-1] ? word.push(v) : result.push(word) && (word = []) && word.push(v)
      }else  if(i == array.length - 1){
        return v == array[i-1] ? word.push(v) && result.push(word) : result.push(word) && result.push([v])
      }else{
        return word.push(v)
      }
    })
    if(result.length === 1){
      return result[0][0] == 1 ? '.' : '-'.repeat(result[0].length / 3)
    }else if(result.map((v) => v.join(''))[1].length == 1 && result.length == 3){
      let result1 = result.map((v) => v.join(''))
      return result1.map((v) => v[0] == 1 ? (v.length <= 2 ? '.' : '-') : (v.length >= 1 ? ' ' : '   ')).join('')

    }else{
      return result.map((v) => v.join('')).map((v) => {
        if(v[0] == 0){
          if(v.length % 2 == 0){
            if(v.length > 6){
              return '       '
            }if(v.length == 6){
              return '   '
            }else{
              return ' '
            }
          }else if(v.length == 7){
            return '       '
          }else if(v.length == 3){
            return '   '
          }else if(v.length > 7){
            return '   '.repeat(v.length / 7 - 1)
          }else{
            return ' '
          }
        }else if(v[0] == 1){
          if(v.length % 2 == 0 && v.length % 3 != 0){
            return String.fromCharCode(46).repeat(v.length / 2)
          }else if(v.length % 3 == 0){
            return String.fromCharCode(45)
          }else{
            return String.fromCharCode(46)
          }
        }
      }).join('')
    }
  }else{
    
    return trimBits.every((v, i, arr) => v === arr[0]) && trimBits[0] == 1 ? '.' : '..'
  }
}

var decodeMorse = function(morseCode){
  return morseCode.split('       ').map((v) => v.split('   ')).map((v) => v.map((val) => MORSE_CODE[val.replace(/s/g, '')]).join('')).join(' ')
}

console.log(decodeMorse(decodeBits('1110110111')))
console.log(decodeMorse(decodeBits('00011100010101010001000000011101110101110001010111000101000111010111010001110101110000000111010101000101110100011101110111000101110111000111010000000101011101000111011101110001110101011100000001011101110111000101011100011101110001011101110100010101000000011101110111000101010111000100010111010000000111000101010100010000000101110101000101110001110111010100011101011101110000000111010100011101110111000111011101000101110101110101110')))
console.log(decodeMorse(decodeBits('11111100111111')))
console.log(decodeMorse(decodeBits('1100110011001100000011000000111111001100111111001111110000000000000011001111110011111100111111000000110011001111110000001111110011001100000011')))
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement