summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2022-11-19 13:00:30 -0500
committerBen Sima <ben@bsima.me>2022-11-19 13:00:30 -0500
commit6100600fbf7d86218a71d735b2c08a61a520c02a (patch)
tree7dd9429cfbc9b8c63bb803045831484b8e1c0fff
parent49f60c2f36202fcdceb99e0ddf656681afa902d1 (diff)
add northwoods testHEADmaster
-rw-r--r--.gitignore3
-rw-r--r--northwoods/.envrc1
-rw-r--r--northwoods/guile.scm100
-rw-r--r--northwoods/shell.nix5
4 files changed, 108 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index d38ad60..545278e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
client_session_key.aes
.stack-work
-state/ \ No newline at end of file
+state/
+.direnv
diff --git a/northwoods/.envrc b/northwoods/.envrc
new file mode 100644
index 0000000..1d953f4
--- /dev/null
+++ b/northwoods/.envrc
@@ -0,0 +1 @@
+use nix
diff --git a/northwoods/guile.scm b/northwoods/guile.scm
new file mode 100644
index 0000000..8dea315
--- /dev/null
+++ b/northwoods/guile.scm
@@ -0,0 +1,100 @@
+#|
+Babysitter Kata
+
+Background
+----------
+This kata simulates a babysitter working and getting paid for one night. The rules are pretty straight forward:
+
+The babysitter
+- starts no earlier than 5:00PM
+- leaves no later than 4:00AM
+- gets paid $12/hour from start-time to bedtime
+- gets paid $8/hour from bedtime to midnight
+- gets paid $16/hour from midnight to end of job
+- gets paid for full hours (no fractional hours)
+
+
+Feature:
+As a babysitter
+In order to get paid for 1 night of work
+I want to calculate my nightly charge
+|#
+
+;; doing this in guile scheme because they said i could use any language, and if
+;; i'm gonna be writing code on saturday morning its gonna be lisp :P
+
+(import (only (rnrs base) assert))
+
+(define +max+ 4) ;; can't work longer than 4am
+(define +start+ 5) ;; can't start before 5pm
+
+;; times are represented as a pair of (hours . minutes)
+(define (h time) (car time))
+(define (m time) (cdr time))
+
+;; if hour is > 1 && < +max+, add 12h to account for midnight rollover
+;; (always call this on end time)
+(define (handle-midnight time)
+ (if (and (>= (h time) 1) (<= (h time) +max+))
+ `(,(+ 12 (h time)) . ,(m time))
+ time))
+
+;; round-* functions return just the hour for simplicity, but ideally these
+;; would operate on a <time> object that has + and - methods defined
+
+(define (round-down time) (h time))
+
+(define (round-up time)
+ (if (> (m time) 0)
+ (+ (h time) 1)
+ (h time)))
+
+;; lookup table for pay rates
+(define (payrate s)
+ (case s
+ ((prebed) 12) ;; before baby is asleep
+ ((postbed) 8) ;; after baby is asleep
+ ((postmidnight) 16) ;; from midnight until 4am or end of job
+ (else #f) ;; bad input, blowup
+ ))
+
+;; better way to do this would be with contracts, or parsing, or objects, but
+;; base scheme doesn't have these so whatever
+(define (valid-inputs? start end bedtime)
+ (and (pair? start)
+ (pair? end)
+ (pair? bedtime)
+ (or (>= (h start) +start+)
+ (error "cannot start before 5pm"))
+ (or (<= (h (handle-midnight end)) (h (handle-midnight `(,+max+ . 00))))
+ (error "working hours must be between 5pm-4am (+start+ and +max+)"))))
+
+;; after validating and conforming the data, the core of the program is just
+;; bucket the hours by payrate and sum them up
+(define (charge start end bedtime)
+ (if (valid-inputs? start end bedtime)
+ (let ((hours-prebed (- (round-up bedtime) (round-down start)))
+ (hours-postbed (- 12 (round-up bedtime)))
+ (hours-postmidnight (- (round-up (handle-midnight end)) 12)))
+ (+ (* (payrate 'prebed) hours-prebed)
+ (* (payrate 'postbed) hours-postbed)
+ (* (payrate 'postmidnight) hours-postmidnight)))
+ #f))
+
+;; simple tests
+(define (test)
+ ;; happy path
+ ;; 3*12 + 4*8 + 3*12 = 116
+ (assert (= 116
+ (charge
+ '(5 . 34)
+ '(2 . 45) ;; late night!
+ '(8 . 00))))
+ ;; 12*4 + 8*2 + 16*0 = 64
+ (assert (= 64
+ (charge
+ '(6 . 00)
+ '(11 . 30) ;; this is more my style
+ '(9 . 15))))
+ ;; test bad inputs
+ (assert (equal? #f (charge '(60 . 60) "string" 1234))))
diff --git a/northwoods/shell.nix b/northwoods/shell.nix
new file mode 100644
index 0000000..cae47b1
--- /dev/null
+++ b/northwoods/shell.nix
@@ -0,0 +1,5 @@
+with import <nixpkgs> {};
+mkShell {
+ name = "guile env";
+ buildInputs = [ pkgs.guile_3_0 ];
+}