projecteuler_problem8

 4th April 2024 at 1:55pm

I already had some notes to tackle this problem; but it has definitely been a while.

It seems like an overly long solution, but it really is just parsing the input, defining a procedure to get sliding windows, and then iterating over the input and finding the highest number.

At some point, I was trying to implement a 0-value skipper, but it seemed overkill for the simplicity of the problem. Maybe with much longer inputs and interval widths it would have been worth it.

(import test)
(import slice)
(import (only srfi-1
			  list-index))
(import (only srfi-13
			  string-join))

(define INPUT-FILE "input8")

; Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?

; At first, it is necessary to build the list of integers from a file
; -> List[Integer]
(define (build-input-list-of-integers)
  (map (lambda (ch) 
         (- (char->integer ch) 48))
	   (string->list (string-join (with-input-from-file INPUT-FILE (lambda () (read-lines))) ""))))

(let ((res (build-input-list-of-integers)))
  (test "creates a list"#t (list? res))
  (test "it is a list of integers" #t (integer? (car res)))
  (test "of the appropriate length" 1000 (length res)))

(define NBRS (build-input-list-of-integers))

; NOTE this function seems a bit pointless; just a wrapper over `slice`
; gets a vector of numbers starting at `start` and ending at `end - 1`
; `start` and `end` are indices of the vector
; List[Integer] Integer Integer -> List[Integer]
(define (get-sliding-window arr start end)
  (slice arr start end))

(test "no-length slicing is empty" '() (get-sliding-window NBRS 0 0))
(test "out-of-bounds slicing above vector is empty" '() (get-sliding-window NBRS 1001 1003))
(test "out-of-bounds slicing including vector is the whole vector" NBRS (get-sliding-window NBRS 0 1003))
(test "length of vector is correct" 3 (length (get-sliding-window NBRS 0 3)))
(test "content of vector is correct" '(7 3 1) (get-sliding-window NBRS 0 3))

; given that we can slice, it is a matter of iterating over the full vector
; List[Integer] Integer Integer Integer Integer Integer -> Integer
(define (get-n-wide-max arr arr-len start end n max-value)
  (if (>= start arr-len)
	max-value
	(let ((new-prod (foldr (lambda (x y) (* x y)) 1 (get-sliding-window arr start end))))
	  (if (> new-prod max-value)
		(get-n-wide-max arr arr-len (+ start 1) (+ end 1) n new-prod)
		(get-n-wide-max arr arr-len (+ start 1) (+ end 1) n max-value)))))

(test "can reproduce example" 5832 (get-n-wide-max NBRS (length NBRS) 0 4 4 0))

(define (solve-problem-8)
  (get-n-wide-max NBRS (length NBRS) 0 13 13 0))
(print (solve-problem-8))