aboutsummaryrefslogtreecommitdiff
path: root/challenge-035/archargelod/nim/ch_1.nim
blob: 660488a451989b21c26006bde3f286e742ea5331 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
import std/[strutils, tables]

const
  MorseDot = "1"
  MorseDash = "111"
  MorseGap = "0"
  MorseCharGap = "00" # CharGap is Gap + Extra 2 zeroes = 3 zeroes total
  MorseWordGap = "0000" # WordGap is Gap + CharGap + Extra 4 zeroes = 7 zeroes total

  CharToMorse = {
    '0': "-----",
    '1': ".----",
    '2': "..---",
    '3': "...--",
    '4': "....-",
    '5': ".....",
    '6': "-....",
    '7': "--...",
    '8': "---..",
    '9': "----.",
    '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': "--..",
    '.': ".-.-.-",
    ',': "--..--",
    '?': "..--..",
    '!': "-.-.--",
    '-': "-....-",
    '/': "-..-.",
    '@': ".--.-.",
    '(': "-.--.",
    ')': "-.--.-",
  }.toTable()

proc normalizeWhitespace(input: string): string =
  var lastCharIsSpace = false
  for c in input:
    if c in Whitespace:
      if lastCharIsSpace:
        continue
      else:
        result.add c
        lastCharIsSpace = true
    else:
      result.add c
      lastCharIsSpace = false

proc toBinaryMorse*(input: string): seq[byte] =
  var binString = ""
  let input = input.strip().normalizeWhitespace()
  for c in input:
    if c == ' ':
      binString.add MorseWordGap
      continue

    let c = c.toLowerAscii()
    if c in CharToMorse:
      let morse = CharToMorse[c]
      for c in morse:
        case c
        of '.': binString.add MorseDot
        of '-': binString.add MorseDash
        else: raiseAssert("Invalid morse character:" & c)
        binString.add MorseGap
      binString.add MorseCharGap

  binString.setLen(binString.len - MorseGap.len - MorseCharGap.len)

  for i in countUp(0, binString.high, 8):
    var section = binString[i..min(i+7, binString.high)]
    if section.len < 8:
      section &= '0'.repeat(8 - section.len)
    result.add cast[byte](parseBinInt(section))

when isMainModule:
  import std/[unittest]

  const
    Test = "	Some test 	sTriNg    "
    Expected = [168'u8, 238, 227, 184, 128, 226, 42, 56, 10, 142, 46, 138, 58, 59, 160]

  suite "Encode binary morse code":
    test "Encode simple message":
      check toBinaryMorse(Test) == Expected
    test "Save message as file for part 2":
      writeFile("message", toBinaryMorse(Test))