aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-027/archargelod/README1
-rwxr-xr-xchallenge-027/archargelod/nim/ch_1.nim40
-rwxr-xr-xchallenge-027/archargelod/nim/ch_2.nim59
-rw-r--r--challenge-028/archargelod/README1
-rwxr-xr-xchallenge-028/archargelod/nim/ch_1.nim17
-rwxr-xr-xchallenge-028/archargelod/nim/ch_2.nim23
-rw-r--r--challenge-029/archargelod/README1
-rwxr-xr-xchallenge-029/archargelod/nim/ch_1.nim26
-rwxr-xr-xchallenge-029/archargelod/nim/ch_2.nim38
-rw-r--r--challenge-030/archargelod/README1
-rwxr-xr-xchallenge-030/archargelod/nim/ch_1.nim11
-rwxr-xr-xchallenge-030/archargelod/nim/ch_2.nim44
-rw-r--r--challenge-031/archargelod/README1
-rwxr-xr-xchallenge-031/archargelod/nim/ch_1.nim17
-rw-r--r--challenge-032/archargelod/README1
-rwxr-xr-xchallenge-032/archargelod/nim/ch_1.nim37
-rwxr-xr-xchallenge-032/archargelod/nim/ch_2.nim23
-rw-r--r--challenge-033/archargelod/README1
-rwxr-xr-xchallenge-033/archargelod/nim/ch_1.nim20
-rwxr-xr-xchallenge-033/archargelod/nim/ch_2.nim22
-rw-r--r--challenge-034/archargelod/README1
-rwxr-xr-xchallenge-034/archargelod/nim/ch_1.nim20
-rwxr-xr-xchallenge-034/archargelod/nim/ch_2.nim24
-rw-r--r--challenge-035/archargelod/README1
-rwxr-xr-xchallenge-035/archargelod/nim/ch_1.nim110
-rwxr-xr-xchallenge-035/archargelod/nim/ch_2.nim109
-rw-r--r--challenge-036/archargelod/README1
-rwxr-xr-xchallenge-036/archargelod/nim/ch_1.nim47
-rwxr-xr-xchallenge-036/archargelod/nim/ch_2.nim56
-rw-r--r--challenge-037/archargelod/README1
-rwxr-xr-xchallenge-037/archargelod/nim/ch_1.nim37
-rwxr-xr-xchallenge-037/archargelod/nim/ch_2.nim84
-rw-r--r--challenge-038/archargelod/README1
-rwxr-xr-xchallenge-038/archargelod/nim/ch_1.nim47
-rwxr-xr-xchallenge-038/archargelod/nim/ch_2.nim86
-rw-r--r--challenge-039/archargelod/README1
-rwxr-xr-xchallenge-039/archargelod/nim/ch_1.nim47
-rwxr-xr-xchallenge-039/archargelod/nim/ch_2.nim54
-rw-r--r--challenge-040/archargelod/README1
-rwxr-xr-xchallenge-040/archargelod/nim/ch_1.nim33
-rwxr-xr-xchallenge-040/archargelod/nim/ch_2.nim26
-rwxr-xr-xchallenge-259/archargelod/nim/ch_1.nim32
-rwxr-xr-xchallenge-259/archargelod/nim/ch_2.nim96
43 files changed, 1299 insertions, 0 deletions
diff --git a/challenge-027/archargelod/README b/challenge-027/archargelod/README
new file mode 100644
index 0000000000..6cd57e1074
--- /dev/null
+++ b/challenge-027/archargelod/README
@@ -0,0 +1 @@
+Solution by archargelod
diff --git a/challenge-027/archargelod/nim/ch_1.nim b/challenge-027/archargelod/nim/ch_1.nim
new file mode 100755
index 0000000000..15e65d5812
--- /dev/null
+++ b/challenge-027/archargelod/nim/ch_1.nim
@@ -0,0 +1,40 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/options
+
+type
+ Point = tuple[x, y: float]
+ Line = (Point, Point)
+
+func getIntersection(l1, l2: Line): Option[Point] =
+ ## can't handle co-linear lines
+ let
+ ix: Line =
+ ((l1[1].x - l1[0].x, l1[1].y - l1[0].y), (l2[1].x - l2[0].x, l2[1].y - l2[0].y))
+ s: float =
+ (-ix[0].y * (l1[0].x - l2[0].x) + ix[0].x * (l1[0].y - l2[0].y)) /
+ (-ix[1].x * ix[0].y + ix[0].x * ix[1].y)
+ t: float =
+ (ix[1].x * (l1[0].y - l2[0].y) - ix[1].y * (l1[0].x - l2[0].x)) /
+ (-ix[1].x * ix[0].y + ix[0].x * ix[1].y)
+
+ if s >= 0 and s <= 1 and t >= 0 and t <= 1:
+ # Collision detected
+ return some((l1[0].x + (t * ix[0].x), l1[0].y + (t * ix[0].y)))
+
+ none(Point)
+
+when isMainModule:
+ import std/unittest
+
+ const
+ TestLines = [
+ ((0.0, 0.0), (10.0, 10.0)), ((10.0, 0.0), (0.0, 10.0)),
+ ((0.0, 0.0), (10.0, 10.0)), ((10.0, 0.0), (6.0, 4.0)),
+ ]
+ Expected = [some(Point (5.0, 5.0)), none(Point)]
+
+ suite "Intersection of two lines":
+ test "intersection detected":
+ check getIntersection(TestLines[0], TestLines[1]) == Expected[0]
+ test "no intersection":
+ check getIntersection(TestLines[2], TestLines[3]) == Expected[1]
diff --git a/challenge-027/archargelod/nim/ch_2.nim b/challenge-027/archargelod/nim/ch_2.nim
new file mode 100755
index 0000000000..2cd2eec204
--- /dev/null
+++ b/challenge-027/archargelod/nim/ch_2.nim
@@ -0,0 +1,59 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+type Hist*[T] = object
+ # object fields without `*` are private and can't be accesed
+ h_val: T
+ h_history: seq[T]
+
+func initHist*[T](value: T): Hist[T] =
+ Hist[T](h_val: value)
+
+func `history`*[T](obj: Hist[T]): seq[T] =
+ ## getter for previous values of a historical type
+ obj.h_history
+
+func `val`*[T](obj: Hist[T]): T =
+ ## getter for current value of a historical type
+ obj.h_val
+
+func `val=`*[T](obj: var Hist[T], value: T) =
+ ## setter for value of a historical type
+ if obj.h_val != value:
+ obj.h_history.add obj.h_val
+ obj.h_val = value
+
+func `clearHistory`*[T](obj: var Hist[T]) =
+ ## clear previous values of a historical type
+ obj.h_history.setLen(0)
+
+func `$`*[T](obj: Hist[T]): string =
+ $obj.h_val
+
+when isMainModule:
+ import std/unittest
+
+ suite "Historical values":
+ test "basic example":
+ var x = initHist[int](10)
+ x.val = 20
+ x.val = x.val - 5
+
+ check x.val == 15
+ check x.history == [10, 20]
+
+ test "history doesn't change if value didn't change":
+ var x = initHist[int](69)
+ x.val = 69
+ x.val = 420
+ x.val = 420
+
+ check x.val == 420
+ check x.history == [69]
+
+ test "clearHistory clears the history":
+ var x = initHist[int](42)
+ x.val = x.val + 1
+ x.clearHistory()
+ x.val = 133
+
+ check x.val == 133
+ check x.history == [43]
diff --git a/challenge-028/archargelod/README b/challenge-028/archargelod/README
new file mode 100644
index 0000000000..6cd57e1074
--- /dev/null
+++ b/challenge-028/archargelod/README
@@ -0,0 +1 @@
+Solution by archargelod
diff --git a/challenge-028/archargelod/nim/ch_1.nim b/challenge-028/archargelod/nim/ch_1.nim
new file mode 100755
index 0000000000..d2d316087d
--- /dev/null
+++ b/challenge-028/archargelod/nim/ch_1.nim
@@ -0,0 +1,17 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/[mimetypes, os]
+
+proc contentsVerbose(filename: string): string =
+ if not fileExists(filename):
+ raise newException(IOError, "'" & filename & "' does not exist.")
+
+ let
+ db = newMimetypes()
+ (_, name, ext) = filename.splitFile()
+ # couldn't think of other way to check contents without reading the file ¯\_(0_0)_/¯
+ mimetype = db.getMimetype(ext, "data")
+
+ "The file '" & name & ext & "' is of type '" & mimetype & "'."
+
+when isMainModule:
+ echo contentsVerbose("/usr/share/mime/image/gif.xml")
diff --git a/challenge-028/archargelod/nim/ch_2.nim b/challenge-028/archargelod/nim/ch_2.nim
new file mode 100755
index 0000000000..fede825f37
--- /dev/null
+++ b/challenge-028/archargelod/nim/ch_2.nim
@@ -0,0 +1,23 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/[times, strutils]
+
+const
+ Dg_On = "•"
+ Dg_Off = "·"
+
+proc displayBinaryClock*() =
+ var columns: array[6, array[4, bool]]
+
+ for colId, decDigit in format(now(), "HHmmss"):
+ for bitId, bit in (decDigit.ord - '0'.ord).toBin(4):
+ if bit == '1':
+ columns[colId][bitId] = true
+
+ for y in columns[0].low .. columns[0].high:
+ for x in columns.low .. columns.high:
+ stdout.write if columns[x][y]: Dg_On else: Dg_Off
+ stdout.write '\n'
+ stdout.flushFile()
+
+when isMainModule:
+ displayBinaryClock()
diff --git a/challenge-029/archargelod/README b/challenge-029/archargelod/README
new file mode 100644
index 0000000000..6cd57e1074
--- /dev/null
+++ b/challenge-029/archargelod/README
@@ -0,0 +1 @@
+Solution by archargelod
diff --git a/challenge-029/archargelod/nim/ch_1.nim b/challenge-029/archargelod/nim/ch_1.nim
new file mode 100755
index 0000000000..6a21d7795b
--- /dev/null
+++ b/challenge-029/archargelod/nim/ch_1.nim
@@ -0,0 +1,26 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/[parseutils, strutils]
+
+proc expandBraces(input: string): string =
+ let start = input.skipUntil('{')
+ let finish = start + input.skipUntil('}', start)
+
+ let (before, after) = (input[0..<start], input[finish+1..^1])
+ for middle in input[start+1..<finish].split(','):
+ result.add before & middle & after & '\n'
+
+when isMainModule:
+ import std/unittest
+
+ const
+ Test = "Perl {Daily,Weekly,Monthly,Yearly} Challenge"
+ Expected = """
+Perl Daily Challenge
+Perl Weekly Challenge
+Perl Monthly Challenge
+Perl Yearly Challenge
+"""
+
+ suite "Brace expansion":
+ test "":
+ check Test.expandBraces() == Expected
diff --git a/challenge-029/archargelod/nim/ch_2.nim b/challenge-029/archargelod/nim/ch_2.nim
new file mode 100755
index 0000000000..7f52f5c6dd
--- /dev/null
+++ b/challenge-029/archargelod/nim/ch_2.nim
@@ -0,0 +1,38 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+
+# we can add C code directly to Nim source file with emit pragma
+{.emit: """
+ char* hello_world() {
+ return "Hello, World!";
+ }
+""".}
+
+# this is a thin wrapper over C function with a new name
+proc hello_C: cstring {.importc: "hello_world".}
+
+# https://www.gnu.org/software/libc/manual/html_node/Obfuscating-Data.html
+proc memfrob(mem: pointer, length: csize_t): pointer {.importc.}
+
+# a proper wrapper
+proc obfuscate*[T: char | byte](arr: var openarray[T]) =
+ ## Reversibly obfuscates data. Each byte is bitwise xor-ed
+ ## with the binary pattern 00101010 (hexadecimal 0x2A)
+ discard memfrob(arr.addr, csize_t(arr.len))
+
+when isMainModule:
+ import std/unittest
+
+ const
+ Greeting = "Hello, World!"
+ Plain = "abcdefgh"
+ Obfuscated = "KHINOLMB"
+
+ suite "Calling C functions":
+ test "Custom C function":
+ check hello_C() == Greeting
+ test "GNU libc (glibc) function":
+ var a = Plain
+ a.obfuscate()
+ check a == Obfuscated
+ a.obfuscate()
+ check a == Plain
diff --git a/challenge-030/archargelod/README b/challenge-030/archargelod/README
new file mode 100644
index 0000000000..6cd57e1074
--- /dev/null
+++ b/challenge-030/archargelod/README
@@ -0,0 +1 @@
+Solution by archargelod
diff --git a/challenge-030/archargelod/nim/ch_1.nim b/challenge-030/archargelod/nim/ch_1.nim
new file mode 100755
index 0000000000..f81c8d6381
--- /dev/null
+++ b/challenge-030/archargelod/nim/ch_1.nim
@@ -0,0 +1,11 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/times
+
+proc main() =
+ for year in 2019..2100:
+ let weekDay = getDayOfWeek(31, mDec, year)
+ let day = 31 - (weekDay.ord + 1) mod 7
+ echo day, " ", mDec, " ", year, " is Sunday"
+
+when isMainModule:
+ main()
diff --git a/challenge-030/archargelod/nim/ch_2.nim b/challenge-030/archargelod/nim/ch_2.nim
new file mode 100755
index 0000000000..69c01c6a55
--- /dev/null
+++ b/challenge-030/archargelod/nim/ch_2.nim
@@ -0,0 +1,44 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+
+proc sorted(a: array[3, int]): array[3, int] =
+ result = a
+ if result[1] < result[0]:
+ swap(result[1], result[0])
+
+ if result[2] < result[1]:
+ swap(result[2], result[1])
+ if result[1] < result[0]:
+ swap(result[1], result[0])
+
+proc possibleSeriesOf3(val: int): seq[array[3, int]] =
+ for n1 in countUp(2, val, 2):
+ var n = [n1, val - n1, 0]
+ while n[1] > n[2]:
+ inc n[2]
+ dec n[1]
+ let newSeries = n.sorted()
+ if newSeries notin result:
+ result.add newSeries
+
+when isMainModule:
+ import std/unittest
+
+ const
+ Expected = [
+ [1, 2, 9],
+ [2, 2, 8],
+ [2, 3, 7],
+ [2, 4, 6],
+ [2, 5, 5],
+ [1, 4, 7],
+ [3, 4, 5],
+ [4, 4, 4],
+ [1, 5, 6],
+ [3, 3, 6],
+ [1, 3, 8],
+ [1, 1, 10],
+ ]
+
+ suite "Sums of 3 numbers equal to 12":
+ test "12 possible series":
+ check possibleSeriesOf3(12) == Expected
diff --git a/challenge-031/archargelod/README b/challenge-031/archargelod/README
new file mode 100644
index 0000000000..6cd57e1074
--- /dev/null
+++ b/challenge-031/archargelod/README
@@ -0,0 +1 @@
+Solution by archargelod
diff --git a/challenge-031/archargelod/nim/ch_1.nim b/challenge-031/archargelod/nim/ch_1.nim
new file mode 100755
index 0000000000..44186b3e54
--- /dev/null
+++ b/challenge-031/archargelod/nim/ch_1.nim
@@ -0,0 +1,17 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+
+proc isDivisionByZero(num, denom: int): bool =
+ num / denom == Inf
+
+when isMainModule:
+ import std/unittest
+
+ const
+ Test = [(15, 0), (15, 5)]
+ Expected = [true, false]
+
+ suite "Division by zero":
+ test "Example 1":
+ check isDivisionByZero(Test[0][0], Test[0][1]) == Expected[0]
+ test "Example 2":
+ check isDivisionByZero(Test[1][0], Test[1][1]) == Expected[1]
diff --git a/challenge-032/archargelod/README b/challenge-032/archargelod/README
new file mode 100644
index 0000000000..6cd57e1074
--- /dev/null
+++ b/challenge-032/archargelod/README
@@ -0,0 +1 @@
+Solution by archargelod
diff --git a/challenge-032/archargelod/nim/ch_1.nim b/challenge-032/archargelod/nim/ch_1.nim
new file mode 100755
index 0000000000..70d030f3e2
--- /dev/null
+++ b/challenge-032/archargelod/nim/ch_1.nim
@@ -0,0 +1,37 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/[parseutils, tables]
+
+proc countUniqLines(input: string): CountTable[string] =
+ var index = 0
+ while index < input.len:
+ let lineLength = input.skipUntil('\n', index)
+ let line = input[index ..< index+lineLength]
+ result.inc(line)
+
+ index += lineLength + 1
+
+when isMainModule:
+ import std/unittest
+
+ const
+ Expected = {"apple": 3, "banana": 1, "cherry": 2}
+ Test = """
+apple
+banana
+apple
+cherry
+cherry
+apple"""
+
+ template checkTable(table, tuples: typed) =
+ for (val, cnt) in tuples:
+ check table[val] == cnt
+
+ when defined(csv):
+ for val, cnt in countUniqLines(Test):
+ echo val, ',', cnt
+ else:
+ suite "Count instances":
+ test "Example 1":
+ checkTable(countUniqLines(Test), Expected)
+
diff --git a/challenge-032/archargelod/nim/ch_2.nim b/challenge-032/archargelod/nim/ch_2.nim
new file mode 100755
index 0000000000..ecdc9c099b
--- /dev/null
+++ b/challenge-032/archargelod/nim/ch_2.nim
@@ -0,0 +1,23 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/[strutils]
+
+proc barGraph(valuePairs: openarray[(string, int)], magnitude = 1): string =
+ const minOffset = 8
+ for (label, value) in valuePairs:
+ let offset = ' '.repeat(max(0, minOffset - label.len))
+ result &= label & offset & " | " & '#'.repeat(value * magnitude) & '\n'
+
+when isMainModule:
+ import std/unittest
+
+ const
+ Test = {"apple": 3, "banana": 1, "cherry": 2}
+ Expected = """
+apple | ############
+banana | ####
+cherry | ########
+"""
+
+ suite "ASCII bar chart":
+ test "Example 1":
+ check barGraph(Test, 4) == Expected
diff --git a/challenge-033/archargelod/README b/challenge-033/archargelod/README
new file mode 100644
index 0000000000..6cd57e1074
--- /dev/null
+++ b/challenge-033/archargelod/README
@@ -0,0 +1 @@
+Solution by archargelod
diff --git a/challenge-033/archargelod/nim/ch_1.nim b/challenge-033/archargelod/nim/ch_1.nim
new file mode 100755
index 0000000000..211e001742
--- /dev/null
+++ b/challenge-033/archargelod/nim/ch_1.nim
@@ -0,0 +1,20 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/[strutils, tables, streams]
+
+proc countLetters(filename: string): CountTable[char] =
+ let f = newFileStream(filename)
+ defer:
+ f.close()
+ while not f.atEnd():
+ let c = f.readChar()
+ if c in Letters:
+ result.inc(c)
+
+proc main =
+ var counts = countLetters("/usr/share/dict/words")
+ counts.sort()
+ for c, cnt in counts:
+ echo c, ": ", cnt
+
+when isMainModule:
+ main()
diff --git a/challenge-033/archargelod/nim/ch_2.nim b/challenge-033/archargelod/nim/ch_2.nim
new file mode 100755
index 0000000000..f93e0e00d3
--- /dev/null
+++ b/challenge-033/archargelod/nim/ch_2.nim
@@ -0,0 +1,22 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/[strutils, strformat]
+
+proc printMultiplicationTable(max: Positive) =
+ # header
+ stdout.write " x|"
+ for i in 1..max: stdout.write &"{i:4}"
+ stdout.write '\n'
+ echo "---+", '-'.repeat(max*4)
+ # body
+ for i in 1..max:
+ stdout.write &"{i:3}|"
+ for j in 1..max:
+ if j < i:
+ stdout.write ' '.repeat(4)
+ else:
+ stdout.write &"{i*j:4}"
+
+ stdout.write '\n'
+
+when isMainModule:
+ printMultiplicationTable(11)
diff --git a/challenge-034/archargelod/README b/challenge-034/archargelod/README
new file mode 100644
index 0000000000..6cd57e1074
--- /dev/null
+++ b/challenge-034/archargelod/README
@@ -0,0 +1 @@
+Solution by archargelod
diff --git a/challenge-034/archargelod/nim/ch_1.nim b/challenge-034/archargelod/nim/ch_1.nim
new file mode 100755
index 0000000000..4598f9e0ee
--- /dev/null
+++ b/challenge-034/archargelod/nim/ch_1.nim
@@ -0,0 +1,20 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+
+when isMainModule:
+ import std/unittest
+
+ const
+ Test = "Write a program that demonstrates using hash slices and/or array slices."
+ Expected = "Here's a program that demonstrates using the array slices."
+
+ suite "Hash and/or array slices":
+ test "Example 1":
+ var res = Test
+ res[0..4] = "Here's"
+ res[41..58] = "the"
+ check res == Expected
+ test "Example 2":
+ let res = "Here's" & Test[5..39] & "the" & Test[58..^1]
+ check res == Expected
+
+
diff --git a/challenge-034/archargelod/nim/ch_2.nim b/challenge-034/archargelod/nim/ch_2.nim
new file mode 100755
index 0000000000..7ce993f04e
--- /dev/null
+++ b/challenge-034/archargelod/nim/ch_2.nim
@@ -0,0 +1,24 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/tables
+
+var Procedures = {
+ "-h": func(): int = 0,
+ "-g": func(): int = 1,
+}.toTable
+
+proc dispatch(s: string): int =
+ Procedures[s]()
+
+when isMainModule:
+ import std/[unittest, random]
+
+ const
+ Test = ["-h", "-g"]
+ Expected = [1, 0]
+
+ suite "Dispatch table":
+ test "Execute function from table at runtime":
+ check dispatch(Test[rand(1)]) == Expected[0]
+ test "Execute different function from table at runtime":
+ check dispatch(Test[rand(1)]) == Expected[1]
+
diff --git a/challenge-035/archargelod/README b/challenge-035/archargelod/README
new file mode 100644
index 0000000000..6cd57e1074
--- /dev/null
+++ b/challenge-035/archargelod/README
@@ -0,0 +1 @@
+Solution by archargelod
diff --git a/challenge-035/archargelod/nim/ch_1.nim b/challenge-035/archargelod/nim/ch_1.nim
new file mode 100755
index 0000000000..660488a451
--- /dev/null
+++ b/challenge-035/archargelod/nim/ch_1.nim
@@ -0,0 +1,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))
diff --git a/challenge-035/archargelod/nim/ch_2.nim b/challenge-035/archargelod/nim/ch_2.nim
new file mode 100755
index 0000000000..a09460359f
--- /dev/null
+++ b/challenge-035/archargelod/nim/ch_2.nim
@@ -0,0 +1,109 @@
+#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off
+import std/[strutils, tables, parseutils, streams]
+
+const
+ MorseToChar = {
+ "-----" : '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 parseBinaryMorse(data: openarray[byte]): string =
+ var binString = ""
+ for b in data:
+ binString &= cast[int](b).toBin(8)
+ binString = binString.strip(chars = {'0'}) # might be unnecessary
+
+ var morseWord = ""
+
+ var ind = 0
+ while ind < binString.len:
+ let tokenLength = binString.skipUntil('0', ind)
+ case tokenLength
+ of 1:
+ morseWord.add '.'
+ of 3:
+ morseWord.add '-'
+ else:
+ raise newException(ValueError, "Incorrectly formatted binary data")
+
+ let gapLength = binString.skipUntil('1', ind + tokenLength)
+ case gapLength
+ of 0: # last character
+ result.add MorseToChar[morseWord]
+ of 1: discard
+ of 3:
+ result.add MorseToChar[morseWord]
+ morseWord.setLen(0)
+ of 7:
+ result.add MorseToChar[morseWord]
+ result.add ' '
+ morseWord.setLen(0)
+ else:
+ raise newException(ValueError, "Incorrectly formatted binary data")
+
+ ind += tokenLength + gapLength
+
+proc readBinaryMorse(filename: string): string =
+ var buffer: seq[byte]
+ var f = newFileStream("message")
+ while not f.atEnd:
+ buffer.add f.readUint8()
+ f.close
+ parseBinaryMorse(buffer)
+
+when isMainModule:
+ import std/[unittest]