aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-098/tyler-wardhaugh/clojure/README.md14
-rw-r--r--challenge-098/tyler-wardhaugh/clojure/resources/input.txt1
-rw-r--r--challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/core.clj12
-rw-r--r--challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/t1.clj43
-rw-r--r--challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/t2.clj25
-rw-r--r--challenge-098/tyler-wardhaugh/clojure/test/tw/weekly/c98_test.clj18
-rw-r--r--challenge-098/tyler-wardhaugh/lua/README.md8
-rwxr-xr-xchallenge-098/tyler-wardhaugh/lua/ch-1.lua31
-rwxr-xr-xchallenge-098/tyler-wardhaugh/lua/ch-2.lua40
-rwxr-xr-xchallenge-098/tyler-wardhaugh/lua/run.lua9
-rwxr-xr-xchallenge-098/tyler-wardhaugh/lua/test.lua24
l---------challenge-098/tyler-wardhaugh/python/ch-1.py1
l---------challenge-098/tyler-wardhaugh/python/ch-2.py1
-rwxr-xr-xchallenge-098/tyler-wardhaugh/python/ch1.py53
-rwxr-xr-xchallenge-098/tyler-wardhaugh/python/ch2.py48
-rw-r--r--challenge-098/tyler-wardhaugh/python/requirements.txt0
-rwxr-xr-xchallenge-098/tyler-wardhaugh/python/test_ch1.py16
-rwxr-xr-xchallenge-098/tyler-wardhaugh/python/test_ch2.py17
18 files changed, 350 insertions, 11 deletions
diff --git a/challenge-098/tyler-wardhaugh/clojure/README.md b/challenge-098/tyler-wardhaugh/clojure/README.md
index 0e314a09c0..dbeaac833c 100644
--- a/challenge-098/tyler-wardhaugh/clojure/README.md
+++ b/challenge-098/tyler-wardhaugh/clojure/README.md
@@ -1,13 +1,13 @@
-# tw.weekly.c96
+# tw.weekly.c98
-The Weekly Challenge - #096 - Tyler Wardhaugh
+The Weekly Challenge - #098 - Tyler Wardhaugh
## Usage
Run the project directly (shows default output from both tasks):
- $ clojure -M -m tw.weekly.c96.core
+ $ clojure -M -m tw.weekly.c98.core
Run the project's tests (which are samples from the task descriptions):
@@ -15,11 +15,11 @@ Run the project's tests (which are samples from the task descriptions):
Run Task #1 with input
- $ clojure -M -m tw.weekly.c96.t1 S
+ $ clojure -M -m tw.weekly.c98.t1 FILE N
-Run Task #2:
+Run Task #2 with input:
- $ clojure -M -m tw.weekly.c96.t2 S1 S2
+ $ clojure -M -m tw.weekly.c98.t2 NS N
## Project Template
@@ -29,7 +29,7 @@ See [seancorfield/clj-new: Generate new projects based on clj, Boot, or Leininge
## License
-Copyright © 2020 Tyler Wardhaugh
+Copyright © 2021 Tyler Wardhaugh
Distributed under the Eclipse Public License either version 1.0 or (at
your option) any later version.
diff --git a/challenge-098/tyler-wardhaugh/clojure/resources/input.txt b/challenge-098/tyler-wardhaugh/clojure/resources/input.txt
new file mode 100644
index 0000000000..6a537b5b36
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/clojure/resources/input.txt
@@ -0,0 +1 @@
+1234567890 \ No newline at end of file
diff --git a/challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/core.clj b/challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/core.clj
new file mode 100644
index 0000000000..8186db73ab
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/core.clj
@@ -0,0 +1,12 @@
+(ns tw.weekly.c98.core
+ (:require [tw.weekly.c98.t1 :as t1])
+ (:require [tw.weekly.c98.t2 :as t2])
+ (:gen-class))
+
+(defn -main
+ "Run all tasks"
+ [& _]
+ (println "Task #1:")
+ (t1/-main)
+ (println "\nTask #2:")
+ (t2/-main))
diff --git a/challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/t1.clj b/challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/t1.clj
new file mode 100644
index 0000000000..e3ea20d117
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/t1.clj
@@ -0,0 +1,43 @@
+(ns tw.weekly.c98.t1
+ (:import (java.io RandomAccessFile))
+ (:require [clojure.edn :as edn]
+ [clojure.java.io :as io]))
+
+;;;
+; Task description for TASK #1 › Read N-characters
+;;;
+
+(def DEFAULT-INPUT [(-> "input.txt" io/resource io/file) 4])
+(def FILES (atom {}))
+
+(defn readN
+ "read n characters from file and move the pointer to the (n+1)th character"
+ [file n]
+ (let [rdr (get @FILES file (RandomAccessFile. file "r"))
+ bytes (byte-array n)
+ result (.read rdr bytes)]
+ (when (pos? result)
+ (swap! FILES assoc file rdr)
+ (->> bytes
+ (take-while pos?)
+ (map char)
+ (apply str)))))
+
+(defn add-shutdown-hook!
+ "Add a shutdown hook to ensure we close all our file readers."
+ []
+ (.addShutdownHook
+ (Runtime/getRuntime)
+ (Thread. (fn []
+ (doseq [[_ rdr] @FILES]
+ (.close rdr))))))
+
+(defn -main
+ "Run Task 1 using a file F and size S, defaulting to the example
+ given in the task description. Call readN on these values three times
+ and print the result."
+ [& args]
+ (let [F (or (some-> args first io/file) (first DEFAULT-INPUT))
+ S (or (some-> args second edn/read-string) (second DEFAULT-INPUT))]
+ (add-shutdown-hook!)
+ (dotimes [_ 3] (println (readN F S)))))
diff --git a/challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/t2.clj b/challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/t2.clj
new file mode 100644
index 0000000000..9c3fbd3f73
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/clojure/src/tw/weekly/c98/t2.clj
@@ -0,0 +1,25 @@
+(ns tw.weekly.c98.t2
+ (:import java.util.Arrays)
+ (:require [clojure.edn :as edn]))
+
+;;;
+; Task description for TASK #2 › Search Insert Position
+;;;
+
+(def DEFAULT-INPUT [[1 2 3 4] 3])
+
+(defn search-insert-position
+ "Find the search insert position for n into a sorted sequence of integers
+ coll"
+ [coll n]
+ (let [index (Arrays/binarySearch (int-array coll) n)]
+ (if (neg? index)
+ (-> index - dec)
+ index)))
+
+(defn -main
+ "Run Task 2 using a sorted sequence of integers NS and a target N,
+ defaulting to the example given in the task description."
+ [& args]
+ (let [[NS N] (or (some->> args (take 2) (map edn/read-string)) DEFAULT-INPUT)]
+ (println (search-insert-position NS N))))
diff --git a/challenge-098/tyler-wardhaugh/clojure/test/tw/weekly/c98_test.clj b/challenge-098/tyler-wardhaugh/clojure/test/tw/weekly/c98_test.clj
new file mode 100644
index 0000000000..7bbfca2203
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/clojure/test/tw/weekly/c98_test.clj
@@ -0,0 +1,18 @@
+(ns tw.weekly.c98-test
+ (:require [clojure.test :refer [deftest is testing]]
+ [tw.weekly.c98.t1 :refer [readN] :as t1]
+ [tw.weekly.c98.t2 :refer [search-insert-position]]))
+
+(deftest task-1
+ (testing "Task 1, Caesar Cipher"
+ (t1/add-shutdown-hook!)
+ (is (= "1234" (apply readN t1/DEFAULT-INPUT)))
+ (is (= "5678" (apply readN t1/DEFAULT-INPUT)))
+ (is (= "90" (apply readN t1/DEFAULT-INPUT)))))
+
+(deftest task-2
+ (testing "Task 2, Search Insert Position"
+ (is (= 2 (search-insert-position [1 2 3 4] 3)))
+ (is (= 3 (search-insert-position [1 3 5 7] 6)))
+ (is (zero? (search-insert-position [12 14 16 18] 10)))
+ (is (= 4 (search-insert-position [11 13 15 17] 19)))))
diff --git a/challenge-098/tyler-wardhaugh/lua/README.md b/challenge-098/tyler-wardhaugh/lua/README.md
index 27612d81d8..b653496267 100644
--- a/challenge-098/tyler-wardhaugh/lua/README.md
+++ b/challenge-098/tyler-wardhaugh/lua/README.md
@@ -1,17 +1,17 @@
# The Weekly Challenge
-The Weekly Challenge - #097 - Tyler Wardhaugh
+The Weekly Challenge - #098 - Tyler Wardhaugh
## Usage
-Run Task 1:
+Run Task 1 with input:
- $ ./run.lua ch-1 S N
+ $ ./run.lua ch-1 FILE N
Run Task 2:
- $ ./run.lua ch-2 B S
+ $ ./run.lua ch-2
Run the project's tests (all the samples from the task descriptions plus some others):
diff --git a/challenge-098/tyler-wardhaugh/lua/ch-1.lua b/challenge-098/tyler-wardhaugh/lua/ch-1.lua
new file mode 100755
index 0000000000..f3f28177af
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/lua/ch-1.lua
@@ -0,0 +1,31 @@
+#!/usr/bin/env lua
+
+local t1 = {}
+t1.DEFAULT_INPUT = {'../clojure/resources/input.txt', 4}
+t1.FILES = {}
+
+function t1.readN(filename, n)
+ local fp = t1.FILES[filename] or assert(io.open(filename, "r"))
+ local result = fp:read(n)
+ t1.FILES[filename] = fp
+ return result
+end
+
+function t1.run(args)
+ local filename, n
+ if #args > 0 then
+ filename, n = args[1], tonumber(args[2])
+ else
+ filename, n = table.unpack(t1.DEFAULT_INPUT)
+ end
+
+ local result
+ for _=1,3 do
+ result = t1.readN(filename, n)
+ if result ~= nil then
+ print(result)
+ end
+ end
+end
+
+return t1
diff --git a/challenge-098/tyler-wardhaugh/lua/ch-2.lua b/challenge-098/tyler-wardhaugh/lua/ch-2.lua
new file mode 100755
index 0000000000..0a182da10c
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/lua/ch-2.lua
@@ -0,0 +1,40 @@
+local t2 = {}
+t2.DEFAULT_INPUT = {{1, 2, 3, 4}, 3}
+
+function t2.binary_search(coll, n, startp, endp)
+ if endp >= startp then
+ local mid = startp + (endp - startp) // 2
+ local v = coll[mid]
+
+ if v == n then
+ return mid
+ elseif v > n then
+ return t2.binary_search(coll, n, startp, mid - 1)
+ else
+ return t2.binary_search(coll, n, mid + 1, endp)
+ end
+ else
+ return -1 * startp - 1
+ end
+end
+
+function t2.search_insert_position(coll, n)
+ local index = t2.binary_search(coll, n, 1, #coll)
+ -- Lua's tables are 1-indexed, hence we need to account for that in both
+ -- cases, both when the result is negative (meaning the number isn't in the
+ -- list, and when the result is positive, indicating the number was found.
+ if index < 0 then
+ return -1 * index - 2
+ else
+ return index - 1
+ end
+end
+
+function t2.run(_)
+ local ns, n
+ ns, n = table.unpack(t2.DEFAULT_INPUT)
+
+ print(t2.search_insert_position(ns, n))
+end
+
+return t2
diff --git a/challenge-098/tyler-wardhaugh/lua/run.lua b/challenge-098/tyler-wardhaugh/lua/run.lua
new file mode 100755
index 0000000000..c6e7473bee
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/lua/run.lua
@@ -0,0 +1,9 @@
+#!/usr/bin/env lua
+
+local filename = arg[1]
+local run_args = table.move(arg, 2, #arg, 1, {})
+
+io.write(string.format("Running task from '%s' with {%s}:\n",
+ filename, table.concat(run_args, ", ")))
+
+require(filename).run(run_args)
diff --git a/challenge-098/tyler-wardhaugh/lua/test.lua b/challenge-098/tyler-wardhaugh/lua/test.lua
new file mode 100755
index 0000000000..9247faa11e
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/lua/test.lua
@@ -0,0 +1,24 @@
+#!/usr/bin/env lua
+
+require 'busted.runner'()
+
+describe("Task 1, Read N-Characters", function()
+ local t1 = require'ch-1'
+ local input_filename = '../clojure/resources/input.txt'
+ it("produces correct results for the examples", function()
+ assert.are.same("1234", t1.readN(input_filename, 4))
+ assert.are.same("5678", t1.readN(input_filename, 4))
+ assert.are.same("90", t1.readN(input_filename, 4))
+ end)
+end)
+
+
+describe("Task 2, Search Insert Position", function()
+ local t2 = require'ch-2'
+ it("produces correct results for the examples", function()
+ assert.are.same(2, t2.search_insert_position({1, 2, 3, 4}, 3))
+ assert.are.same(3, t2.search_insert_position({1, 3, 5, 7}, 6))
+ assert.are.same(0, t2.search_insert_position({12, 14, 16, 18}, 10))
+ assert.are.same(4, t2.search_insert_position({11, 13, 15, 17}, 19))
+ end)
+end)
diff --git a/challenge-098/tyler-wardhaugh/python/ch-1.py b/challenge-098/tyler-wardhaugh/python/ch-1.py
new file mode 120000
index 0000000000..1737f1abb6
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/python/ch-1.py
@@ -0,0 +1 @@
+ch1.py \ No newline at end of file
diff --git a/challenge-098/tyler-wardhaugh/python/ch-2.py b/challenge-098/tyler-wardhaugh/python/ch-2.py
new file mode 120000
index 0000000000..0b4bcfada1
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/python/ch-2.py
@@ -0,0 +1 @@
+ch2.py \ No newline at end of file
diff --git a/challenge-098/tyler-wardhaugh/python/ch1.py b/challenge-098/tyler-wardhaugh/python/ch1.py
new file mode 100755
index 0000000000..64e2898616
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/python/ch1.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+"""Challenge 98, Task 1"""
+
+import atexit
+import sys
+from pathlib import Path
+
+DEFAULT_INPUT = ('../clojure/resources/input.txt', 4)
+FILES = {}
+
+
+def readN(filename, n):
+ """read n characters from the file specified"""
+ filename = Path(filename)
+ if filename not in FILES:
+ FILES[filename] = filename.open()
+
+ fp = FILES[filename]
+ if fp is not None:
+ result = fp.read(n)
+ if result == '':
+ fp = None
+ return result
+ else:
+ return None
+
+
+@atexit.register
+def shutdown():
+ """close all open file handles"""
+ for fp in FILES.values():
+ try:
+ fp.close()
+ except:
+ pass
+
+
+def main(args=None):
+ """Run the task"""
+ if args is None:
+ args = sys.argv[1:]
+
+ filename, n = args[0:1] if args else DEFAULT_INPUT
+ n = int(n)
+
+ for _ in range(3):
+ chunk = readN(filename, n)
+ if chunk is not None:
+ print(chunk)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/challenge-098/tyler-wardhaugh/python/ch2.py b/challenge-098/tyler-wardhaugh/python/ch2.py
new file mode 100755
index 0000000000..a9ecc56c7f
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/python/ch2.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+"""Challenge 98, Task 2"""
+
+import sys
+
+
+DEFAULT_INPUT = ([1, 2, 3, 4], 3)
+
+
+def binary_search(coll, n, start, end):
+ """Return the index of n if it is present in coll. If it is not present,
+ return -(insertion_point - 1)"""
+
+ if end >= start:
+ mid = start + (end - start) // 2
+ v = coll[mid]
+
+ if v == n:
+ return mid
+ elif v > n:
+ return binary_search(coll, n, start, mid - 1)
+ else:
+ return binary_search(coll, n, mid + 1, end)
+ else:
+ return -1 * start - 1
+
+
+def search_insert_position(coll, n):
+ """Return the index of the given target n if found in the sorted integer
+ array coll"""
+
+ index = binary_search(coll, n, 0, len(coll) - 1)
+ if index < 0:
+ index = -1 * index - 1
+ return index
+
+
+def main(args=None):
+ """Run the task"""
+ if args is None:
+ args = sys.argv[1:]
+
+ ns, n = args[0:1] if args else DEFAULT_INPUT
+ print(search_insert_position(ns, n))
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/challenge-098/tyler-wardhaugh/python/requirements.txt b/challenge-098/tyler-wardhaugh/python/requirements.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/python/requirements.txt
diff --git a/challenge-098/tyler-wardhaugh/python/test_ch1.py b/challenge-098/tyler-wardhaugh/python/test_ch1.py
new file mode 100755
index 0000000000..f4259c9181
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/python/test_ch1.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python3
+
+import unittest
+from ch1 import readN
+
+class TestTask1(unittest.TestCase):
+ input_filename = '../clojure/resources/input.txt'
+
+ def test_example_cases(self):
+ self.assertEqual("1234", readN(self.input_filename, 4))
+ self.assertEqual("5678", readN(self.input_filename, 4))
+ self.assertEqual("90", readN(self.input_filename, 4))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/challenge-098/tyler-wardhaugh/python/test_ch2.py b/challenge-098/tyler-wardhaugh/python/test_ch2.py
new file mode 100755
index 0000000000..5bf46c01f0
--- /dev/null
+++ b/challenge-098/tyler-wardhaugh/python/test_ch2.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python3
+
+import unittest
+from ch2 import search_insert_position
+
+class TestTask2(unittest.TestCase):
+
+
+ def test_example_cases(self):
+ self.assertEqual(2, search_insert_position([1, 2, 3, 4], 3))
+ self.assertEqual(3, search_insert_position([1, 3, 5, 7], 6))
+ self.assertEqual(0, search_insert_position([12, 14, 16, 18], 10))
+ self.assertEqual(4, search_insert_position([11, 13, 15, 17], 19))
+
+
+if __name__ == '__main__':
+ unittest.main()