Sorry for reviving an old thread. As someone who did a lot of programming 
competition in the past, I can totally see why IO in Racket is difficult. As 
mark.engelberg said, the goal is to solve as many problems as possible. After 
the competition is over, it's over. No one is going to care about 
maintainability or good coding practice if it makes coding slower. For this 
reason, I wouldn't use parsack if possible. While elegant, there's too much to 
write which is a waste of time.

Luckily, major programming competitions (say, Facebook Hacker Cup, Google Code 
Jam, early IOI, ACM-ICPC, etc.) usually have simple input format. Data are 
usually separated by spaces. Rarely spaces matter. rom gcb says that the input 
is:

  3
  [04, foo, 03.5]
  [05, bar, 04.6]
  [06, fun, 05.7]

but in these competitions, the input is more likely to be:

  3
  04 foo 03.5
  05 bar 04.6
  06 fun 05.7

What really gets in the way is that strings in the input could be something 
that Racket's (read) doesn't recognize. As an example, a string might be #asd. 
This would cause (read) to error "read: bad syntax `#a'".

Indeed, using (read-line) along with regex would solve the problem. The 
downside is that it requires a lot of writing and is heavily task-dependent. 
What I want is a uniform way to extract data easily like scanf.

I write the following module for this purpose. It's a lot of code, so it would 
be useless in closed competitions like ACM-ICPC. However, for online 
competitions like FB Hacker Cup, I find it pretty useful.


#lang racket

(provide (all-defined-out))

(define read-next
  (let ([buffer #f])    
    (lambda (#:to-eol [to-eol #f])
      (define (more!) (set! buffer (read-line)) (read-next #:to-eol to-eol))
      (match buffer
        [(? string?)
         (cond
           [to-eol (let ([ret buffer]) (set! buffer #f) ret)]
           [else
            (set! buffer (string-trim buffer #:right? #f))
            (match (regexp-match #px"\\S+" buffer)
              [(list ret) (set! buffer (regexp-replace #px"^\\S+" buffer "")) 
ret]
              [#f (more!)])])]
        [_ (more!)]))))

(define (%list n typ) (thunk (for/list ([_ n]) (typ))))
(define (%gets) (read-next #:to-eol #t))
(define (%num) (string->number (read-next)))
(define (%str) (read-next))
(define-syntax-rule (scan [v m] ...) (begin (define v (m)) ...))

(module+ test
  (require rackunit)
  (parameterize
      ([current-input-port
        (open-input-string
         (string-append "    2  3  \n"
                        "1    2    3\n"
                        "   4   5   6            \n"
                        "   \n"
                        "  \n"
                        " \n"
                        "\n"
                        "     '\"has-quotes\"' blah blah "))])
    (scan [n %num]
          [m %num]
          [matrix (%list n (%list m %num))]
          [trailing-spaces %gets]
          [str-with-quotes %str]
          [line-with-space %gets])
    (check-equal? n 2)
    (check-equal? m 3)
    (check-equal? matrix (list (list 1 2 3) (list 4 5 6)))
    (check-equal? trailing-spaces "            ")
    (check-equal? str-with-quotes "'\"has-quotes\"'")
    (check-equal? line-with-space " blah blah ")))



For example, https://code.google.com/codejam/contest/6254486/dashboard#s=p1 can 
be solved as follows:

(scan [n %num])
(for ([i n])
  (scan [s %str])
  (define simp (regexp-replaces s '([#px"\\++" "+"] [#px"\\-+" "-"])))
  (define len (string-length simp))
  (printf "Case #~a: ~a\n"
          (add1 i)
          (match (list (string-ref simp 0) (even? len))
            [(or (list #\+ #t) (list #\- #f)) len]
            [(or (list #\+ #f) (list #\- #t)) (sub1 len)])))

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to