123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- #!/run/current-system/profile/bin/guile \
- -e main -s
- !#
- ;; This is a program that checks to see if a string of numbers has
- ;; repeatitive numbers...
- ;; take any number, if even / 2, if odd * 3 + 1 repeat.
- ;; The goal is to plot the number of steps it takes to produce 1 from 1-100
- ;; gnuplot can plot things via a command line from standard in via
- ;; gnuplot -
- ;; To give gnuplot commands directly in the command line, using the "-persist" option so that the plot remains on the screen afterwards:
- ;; gnuplot -persist -e "set title 'Sine curve'; plot sin(x)"
- ;; To set user-defined variables a and s prior to executing commands from a file:
- ;; gnuplot -e "a=2; s='file.png'" input.gpl
- ;; use these modules to help my process the command line arguments.
- (use-modules (ice-9 getopt-long)
- ;;(use-modules (charting))
- (oop goops)
- ;; (use-modules (fibers))
- (ice-9 textual-ports)) ;;open-output-file
- ;; take a number
- ;; if even / 2
- ;; if odd * 3 + 1
- ;; repeat
- ;; You should end at 1
- ;;(define counter 0)
- ;; Every time you call counter, it returns the next higher positive integer
- ;; (counter #:key #t) resets the value to 0
- (define counter
- (let ((counter 0))
- (lambda* (#:key reset)
- (if reset
- (set! counter 0)
- (begin
- (set! counter (+ counter 1))
- counter)))))
- ;; implement the collatz (3 + 1) algorithm on a number.
- ;; Return the number of steps it takes to turn the number into 1
- (define (collatz n)
- (when (>= n 1) ;; n must be greater than or equal to 1
- (let ((count (counter)))
- (cond
- ((= n 1)
- (counter #:reset #t)
- (- count 1))
- ((even? n)
- ;; (display (string-append "collatz (/ " (number->string n) " 2)\n"))
- (collatz (/ n 2)))
- ((odd? n)
- ;; (display (string-append "collatz (- (* " (number->string n) " 3) 1)\n"))
- (collatz (+ (* n 3) 1)))))))
- ;; return the number with the most iterations required to get to 1
- ;; within the set 0-n. return value is '(number number)
- (define (collatz-set n)
- ;; most iterative number the number that takes the most iterations
- ;; to get to 1. (cdr most-it-number) is the number
- ;; (car (cdr most-it-number)) is the number of iterations
- (let ([most-it-number '(0 0)]
- [iterations 0])
- (let loop ((number n)) ;; loop through the numbers 0-n
- (when (> number 1)
- (set! iterations (collatz number))
- ;; error checking (display number) (display " has ")
- ;; error checking (display iterations) (display " iterations\n")
- ;; if the current number's iterations was more than the last one
- ;; then set most-it-number to the new number
- (when (> iterations
- (car (cdr most-it-number)))
- (set! most-it-number (list number iterations)))
- (loop (- number 1))))
- most-it-number))
- ;; this function will create a gnuplot script to draw a line through a scatter plot
- (define (create-plot-script data-file)
- ;; use a let here instead of all the defines
- (letrec ([script-filename "/tmp/plot.dem"]
- [output-script-port (open-output-file script-filename)])
- (put-string output-script-port "set style fill transparent solid 1 noborder\n")
- (put-string output-script-port "set style circle radius 0.5\n")
- (put-string output-script-port
- (string-append "plot '" data-file "' with circles"))
- (force-output output-script-port)
- (close-port output-script-port)
- script-filename))
- ;; graphs a scatter plot from the set of numbers 2-n
- ;; what's wrong here? and wow functional programming recursively sure makes for consice code!
- (define (graph-collatz-set n)
- ;; number-iterations is the list of numbers and their iterations
- ;; ie: '((2 . 1) (3 . 8) (4 . 2) ...)
- (letrec ([data-filename "/tmp/data.dat"]
- [output-data-port (open-output-file data-filename)]
- [script-filename (create-plot-script data-filename)])
- (let loop ((number 2) (iterations (collatz 2))) ;; loop through the numbers 0-n
- (when (>= n number)
- ;; write to a file
- (put-string output-data-port
- (string-append (number->string number) "\t" (number->string iterations) "\n"))
- ;;(display (string-append "number is " number " iterations is " iterations "\n"))
- (loop (+ number 1) (collatz (+ number 1)))))
- (force-output output-data-port)
- (close-port output-data-port)
- (system (string-append "gnuplot " "-p " script-filename)))
- ;;(delete-file data-filename)
- ;;(delete-file script-filename)
- ;; if guile-charting worked
- ;; (make-scatter-plot
- ;; "3+1 conjecture"
- ;; (list
- ;; (append '("numbers")
- ;; (let loop ((number 2) (iterations (collatz 2))) ;; loop through the numbers 0-n
- ;; (if (>= n number)
- ;; (cons (cons number iterations) (loop (+ number 1) (collatz (+ number 1))))
- ;; '())))))
- )
- (define (main args)
- ;;the option specification tells getopt-long how
- ;; to parse the command line
- (let* ((option-spec '((version (single-char #\v) (value #f))
- (help (single-char #\h) (value #f))
- (graph (single-char #\g) (value #t))
- (number (single-char #\n) (value #t))
- ;; a set of numbers
- (set (single-char #\s) (value #t))
- ))
- ;; tell getopt-long to parse the command line and put the
- ;; data in options
- (options (getopt-long args option-spec))
- ;; was --help or -h used?
- (help-wanted (option-ref options 'help #f))
- (version-wanted (option-ref options 'version #f))
- ;; fixme. This How do I know if graph was wanted?
- (graph-wanted (option-ref options 'graph #f))
- (number-wanted (option-ref options 'number #f))
- (set-wanted (option-ref options 'set #f)))
- (if (or number-wanted version-wanted help-wanted set-wanted graph-wanted)
- (cond
- (version-wanted
- (display "collatz version 0.1\n"))
- (help-wanted
- (display "collatz [options]\n")
- (display "")
- (display "-v --version Display version\n")
- (display "-h, --help Display this help info\n")
- (display "-g, --graph Graph the set of numbers' iterations via gnuplot\n")
- (display " ie: collatz -g 500\n")
- (display "-n, --number Returns the number of iterations required to turn this number to 1\n")
- (display "-s, --set Specify a set of numbers, to which to apply the 3 + 1 formula.\n")
- (display " ie: collatz -s 500 will return the number which requires the most\n")
- (display " iterations in the set of numbers 2-500\n")
- )
- (number-wanted
- (display (collatz (string->number number-wanted)))
- (display "\n"))
- (set-wanted
- (let ((result (collatz-set (string->number set-wanted))))
- (display "In the set of 2-")
- (display set-wanted)
- (display " ")
- (display (car result))
- (display " has the most iterations with ")
- (display (car (cdr result)))
- (display " iterations\n")))
- (graph-wanted
- (graph-collatz-set (string->number graph-wanted)))))))
|