#!/usr/bin/env racket
#lang racket
;; メッセージ
(define *message* (hasheq 'opening "Guess the number!"
'prompt "Please input your guess."
'failure "Failed to read line"
'guess "You guessed: "
#t "Too small!"
#f "Too big!"
'win "You win!"))
;; 環境
(struct World (guess secret-number ordering) #:transparent)
;; 初期化
(define (init mx)
(println (hash-ref *message* 'opening))
(World +inf.0 (random 1 (add1 mx)) null))
;; Read
(define (input prompt)
(display prompt)
(string->number (read-line)))
;; Eval
(define (world-go x env)
(match-let (((World guess secret-number ordering) env))
(if (= x secret-number)
(World x secret-number (< x secret-number)))))
;; Print
(define (print env)
(printf "~a~a~%~a~%"
(hash-ref *message* 'guess)
(World-guess env)
(hash-ref *message* (World-ordering env)))
env)
;; Main関数(REPL)
(module+ main
(let loop ((w (init 100)))
(with-handlers ((symbol?
(lambda (key)
(printf "~a~%" (hash
-ref
*message
* key
)) (exn:fail:contract?
(lambda (e)
(printf "~a~%" (hash
-ref
*message
* 'failure)) (loop w))))
(loop (print(world-go (input (hash-ref *message* 'prompt)) w))))))
IyEvdXNyL2Jpbi9lbnYgcmFja2V0CiNsYW5nIHJhY2tldAoKOzsg44Oh44OD44K744O844K4CihkZWZpbmUgKm1lc3NhZ2UqIChoYXNoZXEgJ29wZW5pbmcgIkd1ZXNzIHRoZSBudW1iZXIhIgogICAgICAgICAgICAgICAgICAgICAgICAgICdwcm9tcHQgIlBsZWFzZSBpbnB1dCB5b3VyIGd1ZXNzLiIKICAgICAgICAgICAgICAgICAgICAgICAgICAnZmFpbHVyZSAiRmFpbGVkIHRvIHJlYWQgbGluZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAnZ3Vlc3MgIllvdSBndWVzc2VkOiAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgI3QgIlRvbyBzbWFsbCEiCiAgICAgICAgICAgICAgICAgICAgICAgICAgI2YgIlRvbyBiaWchIgogICAgICAgICAgICAgICAgICAgICAgICAgICd3aW4gIllvdSB3aW4hIikpCgo7OyDnkrDlooMKKHN0cnVjdCBXb3JsZCAoZ3Vlc3Mgc2VjcmV0LW51bWJlciBvcmRlcmluZykgIzp0cmFuc3BhcmVudCkKCjs7IOWIneacn+WMlgooZGVmaW5lIChpbml0IG14KQogIChwcmludGxuIChoYXNoLXJlZiAqbWVzc2FnZSogJ29wZW5pbmcpKQogIChXb3JsZCAraW5mLjAgKHJhbmRvbSAxIChhZGQxIG14KSkgbnVsbCkpCgo7OyBSZWFkCihkZWZpbmUgKGlucHV0IHByb21wdCkKICAoZGlzcGxheSBwcm9tcHQpCiAgKHN0cmluZy0+bnVtYmVyIChyZWFkLWxpbmUpKSkKCjs7IEV2YWwKKGRlZmluZSAod29ybGQtZ28geCBlbnYpCiAgKG1hdGNoLWxldCAoKChXb3JsZCBndWVzcyBzZWNyZXQtbnVtYmVyIG9yZGVyaW5nKSBlbnYpKQogICAgKGlmICg9IHggc2VjcmV0LW51bWJlcikKICAgICAgICAocmFpc2UgJ3dpbiAjdCkKICAgICAgICAoV29ybGQgeCBzZWNyZXQtbnVtYmVyICg8IHggc2VjcmV0LW51bWJlcikpKSkpCgo7OyBQcmludAooZGVmaW5lIChwcmludCBlbnYpCiAgKHByaW50ZiAifmF+YX4lfmF+JSIKICAgICAgICAgIChoYXNoLXJlZiAqbWVzc2FnZSogJ2d1ZXNzKQogICAgICAgICAgKFdvcmxkLWd1ZXNzIGVudikKICAgICAgICAgIChoYXNoLXJlZiAqbWVzc2FnZSogKFdvcmxkLW9yZGVyaW5nIGVudikpKQogIGVudikKCjs7IE1haW7plqLmlbAoUkVQTCkKKG1vZHVsZSsgbWFpbgogIChsZXQgbG9vcCAoKHcgKGluaXQgMTAwKSkpCiAgICAod2l0aC1oYW5kbGVycyAoKHN5bWJvbD8KICAgICAgICAgICAgICAgICAgICAgKGxhbWJkYSAoa2V5KQogICAgICAgICAgICAgICAgICAgICAgIChwcmludGYgIn5hfiUiIChoYXNoLXJlZiAqbWVzc2FnZSoga2V5KSkKICAgICAgICAgICAgICAgICAgICAgICAoZXhpdCkpKQogICAgICAgICAgICAgICAgICAgIChleG46ZmFpbDpjb250cmFjdD8KICAgICAgICAgICAgICAgICAgICAgKGxhbWJkYSAoZSkKICAgICAgICAgICAgICAgICAgICAgICAocHJpbnRmICJ+YX4lIiAoaGFzaC1yZWYgKm1lc3NhZ2UqICdmYWlsdXJlKSkKICAgICAgICAgICAgICAgICAgICAgICAobG9vcCB3KSkpKQogICAgICAobG9vcCAocHJpbnQod29ybGQtZ28gKGlucHV0IChoYXNoLXJlZiAqbWVzc2FnZSogJ3Byb21wdCkpIHcpKSkpKSkK