Upside Up
May 27, 2011
This is an easy exercise for a lazy late-spring Friday afternoon. We take 0, 1, 6, 8 and 9 as the possible upside up digits:
(define (upside-up d)
(case d ((0) 0) ((1) 1) ((6) 9) ((8) 8) ((9) 6) (else #f)))
Then we map over the digits of the input, report #f
if any have no upside, then recombine and check if the number is the same as its upside up reversal:
(define (upside-up? n)
(let ((ds (map upside-up (digits n))))
(if (member #f ds) #f
(= (undigits (reverse ds)) n))))
The next upside up number after 1961 is 6009, and there are 39 upside up numbers less than ten thousand:
> (let loop ((n 1962))
(if (upside-up? n) n
(loop (+ n 1))))
6009
> (length (filter upside-up? (range 10000)))
39
We used range
, filter
, digits
, and undigits
from the Standard Prelude. You can run the program at http://programmingpraxis.codepad.org/VYkXm2GM.
[…] today’s Programming Praxis exercise, our task is to write a function to determine if a number remains the […]
My Haskell solution (see http://bonsaicode.wordpress.com/2011/05/27/programming-praxis-upside-up/ for a version with comments):
My Python solution:
I went through at least 3 different versions of
is_upside_up
, making my solution less complicated each time; the first version was an imperative-style mess!My Try in REXX
/*
First No. > 1691 = 1881
there are 12 upside up numbers between 1 and 10000
*/
and the Swap-Routine
Sorry, copied confusing tries, this should be it:
My solution is pretty similar to Graham’s:
An inelegant solution to show them all for validation:
print [i for i in range(10000) if set(str(i)).issubset(‘01689’) and str(i)[::-1].replace(‘6′,’x’).replace(‘9′,’6’).replace(‘x’,’9′)==str(i)]
;;; Common Lisp:
;; 5 and 2 are clearly symetrical, as any 2¢ pocket calculator will
;; show you:
;;
;; _ _
;; |_ _|
;; _| |_
;;
;; But since the concensus seems to be to ignore them:
(defparameter *symetric-digits*
#((#\0) (#\1) () () () () (#\9) () (#\8) (#\6))
“A vector indexed by digits, containing lists of symetrical digits.”)
(defun upside-down-digit-p (a b)
(member a (aref *symetric-digits* (digit-char-p b))))
(defun upside-down-number-p (n &optional (base 10.))
(loop
:with digits = (format nil “~VR” base n)
:with last-index = (1- (length digits))
:for i :from 0 :to (truncate (length digits) 2)
:always (upside-down-digit-p (aref digits i) (aref digits (- last-index i)))))
(defun programming-praxis-2011-05-27 ()
(loop
:with first-upside-down = nil
:with count = 0
:for n :from 1962 :below 10000
:do (when (upside-down-number-p n)
(unless first-upside-down
(setf first-upside-down n))
(incf count))
:finally (return (values first-upside-down count))))
(programming-praxis-2011-05-27)
–> 6009
15
Cheating a bit by looking at the Python programs, but here’s one in Ruby …
Another variant using python:
[…] 출처: https://programmingpraxis.com/2011/05/27/upside-up/ […]
Factor Programming language
( scratchpad ) 10000 iota [ upside-up? ] filter length .
39
For grins, here’s a Erlang implementation. I’m new to Erlang, so I’m sure there are other, better, ways to do it.
I don’t understand why, sometimes, even though submission went good, the comment won’t show up…
;; Scheme
(define (upside-char=? x y)
(let ((yy (assoc x
'((#\0 #\0) (#\1 #\1) (#\2 #\5) (#\5 #\2) (#\6 #\9)
(#\8 #\8) (#\2 #\5)))))
(and yy (char=? y (cadr yy)))))
;
(define (upside-down? n)
(let* ((s (number->string n))
(l (string-length s)))
(let loop ((i 0) (j (1- l)))
(if (< i j)
(and
(upside-char=? (string-ref s i)
(string-ref s j))
(loop (1+ i) (1- j)))
(or (and (member (string-ref s i) '(#\0 #\1 #\8)) #t)
(> i j))))))
I went with building upside up numbers instead of looping 10,000 times and checking each one
//C# Solution.
for (int i = 1961; i x == ‘1’ ||x == ‘6’ || x == ‘8’ ||x == ‘9’ ||x == ‘0’);
foreach (var item in j)
{
topupNo += item;
}
if (topupNo == i.ToString())
{
Console.WriteLine(i.ToString());
}
}
//C# Solution
. for (int i = 1961; i <= 10000; i++) {
string topupNo = string.Empty; var j = i.ToString().Replace("6", "T").Replace("9",
"6").Replace("T", "9").Reverse().Where(x => x == '1' ||x == '6' || x == '8' ||x
== '9' ||x == '0');
foreach (var item in j) { topupNo += item; }
if (topupNo == i.ToString()) { Console.WriteLine(i.ToString()); } }
Just cause there isn’t a version in Go yet.. It’s simple, but gets the job done: