From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Joshua Branson Newsgroups: gmane.lisp.guile.user Subject: I wrote a 3+1 guile program, feedback welcome Date: Wed, 07 Nov 2018 10:14:06 -0500 Message-ID: <87efbwc43l.fsf@fastmail.com> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: blaine.gmane.org 1541603604 15555 195.159.176.226 (7 Nov 2018 15:13:24 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 7 Nov 2018 15:13:24 +0000 (UTC) To: guile-user@gnu.org Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Wed Nov 07 16:13:20 2018 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gKPWB-0003vy-8G for guile-user@m.gmane.org; Wed, 07 Nov 2018 16:13:19 +0100 Original-Received: from localhost ([::1]:48895 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gKPYH-0006zt-LD for guile-user@m.gmane.org; Wed, 07 Nov 2018 10:15:29 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:32971) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gKPXw-0006zk-64 for guile-user@gnu.org; Wed, 07 Nov 2018 10:15:09 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gKPXp-0003qa-Q7 for guile-user@gnu.org; Wed, 07 Nov 2018 10:15:08 -0500 Original-Received: from out5-smtp.messagingengine.com ([66.111.4.29]:52719) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gKPXp-0003bY-Hi for guile-user@gnu.org; Wed, 07 Nov 2018 10:15:01 -0500 Original-Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 3551521E8D for ; Wed, 7 Nov 2018 10:14:54 -0500 (EST) Original-Received: from mailfrontend2 ([10.202.2.163]) by compute6.internal (MEProxy); Wed, 07 Nov 2018 10:14:54 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fastmail.com; h= from:to:subject:date:message-id:mime-version:content-type; s= fm1; bh=CveXsrm3+g2hqkZJ5BeR5Sp4ghwQSKT/ZlTNaVhwezs=; b=KQW2Ot04 u5Ac0ljlzOcEDmvzESRl9TV9fURrS10wKcRnoixO1T2/ygmO3R4kQCu5E0dQ0QUh WWWlMfsvOgDmuc9wFMS95kf0lHVjyLWfVNRHHnwjCNoB1xYOOwNwDrlZAgCljeeR Xa4n/o1QPpiO6aIYVNmrt1oG4kJfNTqqPHHYI0dH/TT9e2l0+AUoMRwnVgmP+cTs LAvrZmN+1PjHUWZkZptV/XRQR/DMNRtdtSlEiIs1sp6R1ZlTRNWMewBpagUCQJSa pePSf6/ch5wBBSKufJBO7OjZgZQI+wAUvNa2iAHttSMf+nctEfGgD9EfvpzF3cWE GgE9/oN3+/daRg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-type:date:from:message-id :mime-version:subject:to:x-me-proxy:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; bh=CveXsrm3+g2hqkZJ5BeR5Sp4ghwQS KT/ZlTNaVhwezs=; b=wQPsAeEjC9R7aje2ZrU8tHclbf5F4wHFObPVfecrO0Emr 17zKqUOw3MojuKPnV4ApAoJwp/4pZFI7RhpggiRFCI3lT5fhSRlLwiwEJ3tSpPrE BnvD6jNzV1+rXsLWQ3FGpEM7564n2ZT2Yq1CyoKMQCffCjyh9cTMGPqpijQTbXYQ aYLeMjf+gFPhBxG6ALVJedu8q4GN3Jldq4TsAlyJr7WynSxQzMy5qXky3hXfZ36n kErI6XHORyuI4+6WB/UKX6wSUxQst93RCDk0lSkiAP28pKZsiZpOFJxAsYc2ahvn QhgE6gD84GwlfXHthm/wsN58LZTh43C2WXjAMLf/w== X-ME-Sender: X-ME-Proxy: Original-Received: from dobby (unknown [72.12.220.132]) by mail.messagingengine.com (Postfix) with ESMTPA id B321B1030D for ; Wed, 7 Nov 2018 10:14:53 -0500 (EST) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 66.111.4.29 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Original-Sender: "guile-user" Xref: news.gmane.org gmane.lisp.guile.user:14970 Archived-At: --=-=-= Content-Type: text/plain Hello, I spent a week or two working on the 3+1 problem. The 3+1 problem is a fun number theory conjecture. It states that there exists a procedure for turning all positive whole integers into 1. The procedure is: If the number is even, then divide it by two. If the number is odd, multiply by 3 and add 1. repeat. I decided to write a program to graph the number of iterations it takes for the set of numbers 2-n to reach 1. It uses ice-9 getopt-long, so the usual --help and --version work. It uses gnuplot, because I couldn't get guile-charting to work. If anyone has enough free time to comment on the state of this program, or any tips about how to make it better, etc. that would be most helpful. Thanks, Joshua --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=collatz.scm Content-Description: collatz.scm #!/usr/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)) (use-modules (oop goops)) ;; (use-modules (fibers)) (use-modules (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))))) ;; playing with fibers ;; (run-fibers ;; (spawn-fiber ;; (lambda () ;; (display ;; (let loop (n 10) ;; (if (> n 0) ;; (cons n (cons loop (- n 1))) ;; '()))) ;; ) ;; (spawn-fiber ;; (lambda () ;; (display ;; (let loop (n 20) ;; (if (> n 10) ;; (cons n (cons loop (- n 1))) ;; '()))))))) ;; 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))))))) --=-=-=--