You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
aoc-racket/2017/d14/main.rkt

64 lines
2.5 KiB
Racket

6 years ago
#lang reader "../aoc-lang.rkt"
6 years ago
(require racket/sequence sugar/list)
6 years ago
(provide (rename-out [#%mb #%module-begin]))
(define-macro (#%mb (STARS) (STR) ...)
#`(#%module-begin
6 years ago
(time ((if (eq? 'STARS ') one-star two-star) (format "~a" 'STR))) ...))
(define (knot-hashes str)
(for/list ([i (in-range 128)])
(knot-hash (format "~a-~a" str i))))
6 years ago
(define (one-star str)
6 years ago
(for*/sum ([kh (in-list (knot-hashes str))]
[int (in-list (kh->ints kh))])
int))
6 years ago
6 years ago
(define (two-star str)
6 years ago
(define vec (for*/vector ([kh (in-list (knot-hashes str))]
[int (in-list (kh->ints kh))])
(if (= int 1) 'used 'empty)))
6 years ago
(define (at-left-edge? idx) (= (modulo idx 128) 0))
(define (at-right-edge? idx) (= (modulo idx 128) 127))
(for/fold ([region 0])
([(val idx) (in-indexed vec)]
#:unless (number? val))
(let loop ([idx idx])
(cond
6 years ago
[(and (<= 0 idx (sub1 (vector-length vec))) (eq? (vector-ref vec idx) 'used))
6 years ago
(vector-set! vec idx region)
(unless (at-left-edge? idx) (loop (sub1 idx)))
(unless (at-right-edge? idx) (loop (add1 idx)))
6 years ago
(loop (+ idx 128))
(loop (- idx 128))
6 years ago
(add1 region)]
[else region]))))
6 years ago
(define (kh->ints kh)
(for*/list ([c (in-string kh)]
[num (in-value (string->number (string c) 16))]
[c (in-string (~r num #:base 2 #:min-width 4 #:pad-string "0"))])
6 years ago
(if (char=? c #\1) 1 0)))
6 years ago
(define (knot-hash seed-str [range-in 256])
(define ascii-chars (map char->integer (string->list seed-str)))
(define nums (reverse-segments range-in (append ascii-chars '(17 31 73 47 23)) #:reps 64))
(define dense-hash (for/list ([vals (in-slice 16 nums)])
(apply bitwise-xor vals)))
(string-append* (for/list ([num (in-list dense-hash)])
(~r num #:base 16 #:min-width 2 #:pad-string "0"))))
(define (reverse-segments range-in lens #:reps [reps 1])
(define vec (list->vector (range range-in)))
(for*/fold ([current-position 0]
[skip-size 0])
([rep (in-range reps)]
[len (in-list lens)])
(define posns (for/list ([i (in-range len)])
(modulo (+ current-position i) range-in)))
6 years ago
(for ([val (in-list (map (λ (posn) (vector-ref vec posn)) posns))]
6 years ago
[posn (in-list (reverse posns))])
(vector-set! vec posn val))
(values (+ current-position len skip-size) (add1 skip-size)))
(vector->list vec))