Расшифровка азбуки Морзе, продвинутый JS (codewars)

Вот задача:

При передаче азбуки Морзе международный стандарт указывает, что:

Точка – имеет длину 1 единицу времени. Тире – это 3 единицы времени. Пауза между точками и тире в символе – 1 единица времени. Пауза между символами внутри слова – 3 единицы времени. Пауза между словами – 7 единиц времени. Однако в стандарте не указывается, какова продолжительность этой единицы времени. И на самом деле разные операторы будут передавать с разной скоростью. Любителю может потребоваться несколько секунд для передачи одного символа, опытный профессионал может передать 60 слов в минуту, а роботизированные передатчики могут работать намного быстрее.

Для этого ката мы предполагаем, что получение сообщения выполняется автоматически оборудованием, которое периодически проверяет линию, и если линия подключена (ключ на удаленной станции не работает), записывается 1, а если линия не подключена (удаленная клавиша вверху), записывается 0. После того, как сообщение полностью получено, оно попадает к вам для декодирования в виде строки, содержащей только символы 0 и 1.

Например, сообщение HEY JUDE, то есть ···· · −·−− ··−−− ··− −·· · может быть получено следующим образом:

1100110011001100000011000000111111001100111111001111110000000000000011001111110011111100111111000000110011001111110000001111110011001100000011

Как вы можете видеть, эта передача совершенно точна в соответствии со стандартом, и аппаратное обеспечение сэмплирует линию ровно два раза на точку.

Тем не менее, ваша задача состоит в том, чтобы реализовать две функции:

Функция decodeBits(bits), которая должна определить скорость передачи сообщения, корректно расшифровать сообщение до точек, тире и пробелов (один между символами, три между словами) и вернуть их в виде строки. Обратите внимание, что в начале и в конце сообщения могут естественным образом встречаться дополнительные 0, обязательно игнорируйте их. Кроме того, если у вас возникли проблемы с определением, является ли конкретная последовательность единиц точкой или тире, предположите, что это точка. 2. Функция decodeMorse(morseCode), которая берет вывод предыдущей функции и возвращает удобочитаемую строку.

Вот мой код:

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.

Проблема в том, что каждый раз, когда я запускаю свой код, у меня возникают одни и те же проблемы:

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 .'

Я старался изо всех сил, и я сложил. Может ли кто-нибудь помочь мне найти решение здесь? Что я делаю неправильно в этом коде?

Для отладки:

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

Обновленный пост! Я очень близко. Что-то не так с пробелами и с одной буквой.

P.S. Ошибка может быть в логике декодера, когда я пытаюсь решить, что я должен поместить в массив result тире или точки.


person Morani    schedule 04.01.2021    source источник
comment
Прямо сейчас код не делает то, что вы говорите, потому что вы не включили определение для MORSE_CODE...   -  person Heretic Monkey    schedule 04.01.2021
comment
Я исправлю это сейчас   -  person Morani    schedule 04.01.2021
comment
Похоже, вы используете every для побочных эффектов; вы должны либо что-то делать с выводом (логическое значение, указывающее, удовлетворяет ли каждый элемент массива условию), либо использовать forEach для простой итерации без значимого возвращаемого значения. Я бы также посоветовал не быть таким умным в коде этой функции. При первом прочтении непонятно, что будет делать return v == array[i - 1] ? word.push(v) : result.push(word) && (word = []) && word.push(v). Я обнаружил, что если у меня возникают проблемы с кодом, первое, что я делаю, это убеждаюсь, что могу прочитать его вслух и понять смысл.   -  person Heretic Monkey    schedule 04.01.2021
comment
Этот фрагмент кода работает хорошо (просто поверьте мне :)). Ошибка где-то в логике декодирования, где я пытаюсь просмотреть массив return result.map((v) => v.join('')).map((v)... и где-то что-то упускаю.   -  person Morani    schedule 04.01.2021
comment
Я думаю, что я упускаю, в чем проблема. Можете ли вы отредактировать фрагмент, чтобы включить пример ввода, который возвращает неверный вывод? Например, что дает вам эти ошибки Expected: '...' вместо got: '...'?   -  person Heretic Monkey    schedule 04.01.2021
comment
if (result.map((v) ‹-- почему вы используете карту в if?   -  person epascarello    schedule 04.01.2021
comment
Есть ли причина, по которой вы тестируете это: decodeMorse(decodeBits('1110111')) // возвращает EE, поскольку двоичная строка не та, которую вы ожидаете получить.   -  person A Haworth    schedule 04.01.2021
comment
Ага. Например: decodeMorse(decodeBits('110111')) должно вернуть A, но возвращает EE. Я исправляю это прямо сейчас.   -  person Morani    schedule 04.01.2021
comment
@Morani 1110111 должен быть M, скорость = 1, строка (пауза) строка, 111, 0, 111. Другой возможной скорости нет, потому что одиночный 0 может быть сгенерирован только при скорости = 1   -  person xanatos    schedule 04.01.2021


Ответы (1)


Я сделал это! Моя первая интереснейшая задача в js. Причиной сбоя были неправильные пробелы в условии. Я должен предотвратить, что пробелы могут быть нечетными и четными нулями. Проголосуйте, пожалуйста. Может быть, это поможет кому-то. Я потратил почти 10 часов, чтобы решить это 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')))

person Morani    schedule 04.01.2021
comment
Почему K 1110110111, а не 111010111? - person xanatos; 04.01.2021
comment
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) } этот код проверяет его. А задание вы можете прочитать ниже. - person Morani; 04.01.2021
comment
Я не спрашиваю, почему код это принимает. Я спрашиваю с человеческой точки зрения, почему K, то есть -.-, то есть 111 0 1 0 111, принимается как 1110110111, то есть с двумя единицами вместо точки. - person xanatos; 05.01.2021