blob: 8dea3158486572e3b9eeeed4982e188cd9727495 (
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
|
#|
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))))
|