fannkuch.scm 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. ;; fannkuch benchmark for The Computer Language Shootout
  2. ;; Written by Dima Dorfman, 2004
  3. ;; Slightly improved by Sven Hartrumpf, 2005-2006
  4. ;;
  5. ;; Ever-so-slightly tweaked for MzScheme by Brent Fulgham
  6. ;; Converted to Kawa by Per Bothner
  7. (define (vector-reverse-slice! (v :: int[]) (i :: int) (j :: int)) :: void
  8. (let loop ((j :: int (- j 1))) ; exclude position j
  9. (if (< i j)
  10. (let ((t (v i)))
  11. (set! (v i) (v j))
  12. (set! (v j) t)
  13. (set! i (+ i 1))
  14. (loop (- j 1))))))
  15. (define (count-flips pi::int[] pt::int[]) :: int
  16. (do ((i :: int 0 (+ i 1)))
  17. ((= i pi:length))
  18. (set! (pt i) (pi i)))
  19. (do ((i :: int 0 (+ i 1)))
  20. ((= (pt 0) 0) i)
  21. (vector-reverse-slice! pt 0 (+ (pt 0) 1))))
  22. (define (fannkuch (n :: int)) :: int
  23. (let ((pi (int[] length: n))
  24. (pt (int[] length: n))
  25. (r :: int n)
  26. (count (int[] length: n)))
  27. (do ((i :: int 0 (+ i 1))) ((= i n))
  28. (set! (pi i) i))
  29. (let loop ((flips :: int 0)
  30. (perms :: int 0))
  31. (cond ((< perms 30)
  32. (do ((i :: int 0 (+ i 1)))
  33. ((>= i n))
  34. (format #t "~d" (+ (pi i) 1)))
  35. (newline)))
  36. (do ()
  37. ((= r 1))
  38. (set! (count (- r 1)) r)
  39. (set! r (- r 1)))
  40. (let* ((flips1 (count-flips pi pt))
  41. (flips2 (if (> flips1 flips) flips1 flips)))
  42. (let ((result :: int
  43. (let loop2 ()
  44. (if (= r n)
  45. flips2
  46. (let ((perm0 (pi 0)))
  47. (do ((i :: int 0))
  48. ((>= i r))
  49. (let ((j (+ i 1)))
  50. (set! (pi i) (pi j))
  51. (set! i j)))
  52. (set! (pi r) perm0)
  53. (set! (count r) (- (count r) 1))
  54. (cond ((<= (count r) 0)
  55. (set! r (+ r 1))
  56. (loop2))
  57. (else
  58. -1)))))))
  59. (if (>= result 0) result
  60. (loop flips2 (+ perms 1)))
  61. )))))
  62. (define args (cdr (command-line)))
  63. (if (< (length args) 1)
  64. (begin (display "An argument is required") (newline) 2)
  65. (let ((n (string->number (car args))))
  66. (if (not (integer? n))
  67. (format #t "An integer is required~%")
  68. (format #t "Pfannkuchen(~S) = ~s~%" n (fannkuch n)))))