summaryrefslogtreecommitdiff
path: root/password-philosophy/pp.scm
blob: b1d92d787fea2cdf957bf36e634c345cde061646 (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
(define-module (pp)
  #:use-module (srfi srfi-1)
  #:export (pp
	    parse-line
	    count-occurrences
	    valid-password-p1?
	    valid-password-p2?))

(define (pp str p1?)
  (count (lambda (x) x)
	 (map (lambda (line)
		(let ((parsed (parse-line line)))
		  (if p1?
		      (valid-password-p1? (car parsed)
					  (cadr parsed)
					  (caddr parsed))
		      (valid-password-p2? (car parsed)
					  (cadr parsed)
					  (caddr parsed)))))
	      (string-split
	       (string-trim-both str char-set:whitespace)
	       #\newline))))

(define (parse-line str)
  "Parses a line of the puzzle format
into a workable datastructure:
(passwd (char (min max)))"
  (let* ((fields (string-split str char-set:whitespace))
	 (range (map string->number (string-split (car fields) #\-)))
	 (char (string-ref (cadr fields) 0))
	 (passwd (caddr fields)))
    (list passwd
	  char
	  (cons (car range)
		(cadr range)))))

(define (valid-password-p2? passwd char range)
  "Wrapper for valid-password-p1?.
Prepares the input by indexing RANGE
into PASSWD, setting that as the new
PASSWD, and setting RANGE to (1 . 1)

Note the original problem specifies
that strings are NOT zero-indexed!"
  (valid-password-p1? (string (string-ref passwd (1- (car range)))
			      (string-ref passwd (1- (cdr range))))
		      char
		      '(1 . 1)))

(define (valid-password-p1? passwd char range)
  "Given PASSWD, checks that CHAR appears
within RANGE number of times. RANGE is a
cons pair."
  (let ((occurrences (count-occurrences passwd char)))
    (and (>= occurrences (car range))
	 (>= (cdr range) occurrences))))

(define (count-occurrences str char)
  "Returns the number of times CHR
appears in STR."
  (string-length (string-filter char str)))