Two Simple Tasks
January 5, 2021
The first task is a simple loop:
(define (f limit)
(let loop ((n 1) (m 5))
(when (<= n limit)
(display n) (newline)
(loop (* n m) (/ 10 m)))))
> (f 10000) 1 5 10 50 100 500 1000 5000 10000
The second task is easy enough to work by hand, since there are only 81 possibilities from 110 to 990. Or you can do the algebra. But we solve the problem with a list comprehension:
> (list-of n
(n range 110 1000 11)
(= (sum (map square (digits n))) (/ n 11)))
(550 803)
You can run the program at https://ideone.com/eUnbyO.
I felt like generalizing the first problem a bit and am including my
solution in standard R7RS Scheme below, along with a simple solution
to the second one as well. Happy 2021 to all!
(import (scheme base) (scheme write) (only (srfi 1) circular-list every) (srfi 8)) (define-syntax assert (syntax-rules () ((_ pred ...) (unless (and pred ...) (display "Failed assertion: ") (display '(pred ...)) (newline) (error "assertion failure"))))) (define (multi-geometric-progression-fold kons knil init multipliers limit) (assert (number? init) (pair? multipliers) (every number? multipliers)) (let f ((seed knil) (term init) (muls (apply circular-list multipliers))) (if (>= term limit) seed (f (kons term seed) (* term (car muls)) (cdr muls))))) (assert (equal? '(1000 500 100 50 10 5 1) (multi-geometric-progression-fold cons '() 1 '(5 2) 1001))) (assert (equal? '(1008 1008 252 252 84 84 21 21 7) (multi-geometric-progression-fold cons '() 7 '(3 1 4 1) 2001))) (assert (equal? '(10000 5000 1000 500 100 50 10 5 1) (multi-geometric-progression-fold cons '() 1 '(5 2) 10001))) (define (digits n) (if (zero? n) '(0) (let f ((n n) (digits '())) (if (zero? n) digits (receive (quot rem) (floor/ n 10) (f quot (cons rem digits))))))) (define (q2) (let f ((n 110) (m 10) ; n/11 = m (r '())) (if (> n 999) (reverse r) (f (+ n 11) (+ m 1) (if (= m (apply + (map square (digits n)))) (cons n r) r))))) (assert (equal? '(550 803) (q2)))(defun 5-1-sequence (limit) (cons 1 (loop :for f := t :then (not f) :for n := 5 :then (* (if f 5 2) n) :while (< n limit) :collect n))) (assert (equalp (5-1-sequence 100001) '(1 5 10 50 100 500 1000 5000 10000 50000 100000))) (defun print-5-1-sequence (limit) (let ((*print-right-margin* 72)) (pprint (5-1-sequence limit))) (values)) (print-5-1-sequence 10000001) ;; (1 5 10 50 100 500 1000 5000 10000 50000 100000 500000 1000000 5000000 ;; 10000000) (defun find-numbers (min max such-as) (loop :for i :from min :to max :when (funcall such-as i) :collect i)) (defun square (x) (* x x)) (assert (equalp (find-numbers 0 999 (lambda (n) (let ((a (truncate n 100)) (b (mod (truncate n 10) 10)) (c (mod n 10))) (= (/ n 11) (+ (square a) (square b) (square c)))))) '(0 550 803)))Such a good way to start the new coding year :-) Here is my take on this drill using Julia 1.5.2: https://pastebin.com/AjpJg1Hn. Cheers
Here’s a solution to the first task in x86-64 assembly using Linux system calls.
Example usage:
Here’s a solution to the second task in x86-64 assembly using Linux system calls.
Example usage:
A Lua solution for the first task.
function print_seq(N) local i = 1 while true do if i <= N then print(i) else break end i = i*5 if i <= N then print(i) else break end i = i*2 end end print_seq(500)Lua solution for the first task using mutual tail calls.
function print_seq1(i, N) if i <= N then print(i) print_seq5(5*i, N) end end function print_seq5(i, N) if i <= N then print(i) print_seq1(2*i, N) end end print_seq1(1, 500)Lua solution for the second task. Brute force stepping through all the numbers from 100 to 999 rather than just multiples of 11. This allows interpreting n/11 as floor division (see commented line), giving more solutions.
for d0 = 0, 9 do for d1 = 0, 9 do for d2 = 1, 9 do n = d2*100 + d1*10 + d0 --m = math.floor(n/11) m = n / 11 sumsq = d2^2 + d1^2 + d0^2 if m == sumsq then print(n, sumsq) end end end endA response for “Two Simple Tasks”, written in Racket:
(define (print-comma-sep-list data) (let loop ([str "~a"] [li data]) (cond [(empty? li) (printf ".\n")] [else (printf str (first li)) (loop ", ~a" (rest li))]))) (define (simp-task-1 lim) (let loop ([mult 1] [seed 1] [ans '()]) (let ((val (* mult seed))) (if (<= val lim) (loop (if (equal? seed 5) (* mult 10) mult) (if (equal? seed 1) 5 1) (cons val ans)) (print-comma-sep-list (reverse ans)))))) (define (simp-task-2) (for ([i (in-range 100 1000)]) (cond [(equal? (/ i 11) (foldl (lambda (s v) (+ (expt (string->number (list->string (list s))) 2) v)) 0 (string->list (number->string i)))) (printf "~a\n" i)])))And here are the results:
I’m trying to learn JavaScript. So here are my answers written in JS and run with node…
var start = [“1”, “50”]
function addzero(t) {
return [t[0] += ‘0’, t[1] += ‘0’]
}
let max = 1000000
for (var i = 0; i < 10; i++) {
var r = addzero(start)
if (r[0] > max || r[1] > max) return
console.log(r.shift(),r.shift())
}
// prax1.js
for (let i = 100; i < 1000; i++) {
let d = i.toString().split(”)
let dig = d.map(Number)
let sum = dig[0] * dig[0] + dig[1]* dig[1] + dig[2] * dig[2]
if (i/11 == sum) console.log(i/11, dig, sum)
}
% node prax1.js
50 [ 5, 5, 0 ] 50
73 [ 8, 0, 3 ] 73