28
\$\begingroup\$

Background

You are working for some board-game manufacturer and need to produce wooden tiles with the numbers from 0 to n engraved on them for some game. However, without further ado, some tiles would become indistinguishable, e.g., 6 and 9. To avoid this, you have to equip numbers that can be confused with others (and only those) with a disambiguating dot, e.g., you would have tiles like 9. or 6089..

Unfortunately, you need to use some old, yet programmable wood-engraving device for this, whose interface is so broken that you have to encode every character of the program by hand in an unspeakably tedious process. Fortunately the device understands every existing programming language. Thus you are looking for the shortest program that prints such tiles.

Actual task

Write the shortest program that:

  • Takes a positive integer n as input. How the input is read is up to you.
  • Prints each of the numbers from 0 to n (0 and n included) exactly once in an order of your choice, separated by a single whitespace character (including newline). The numbers are to be printed without leading zeros.
  • Appends a dot (.) to every number that turns into another, valid number upon rotation by π (180 °), even if that number is larger than n. Your typeface’s 0 and 8 are rotation-symmetric and the 9 is a rotated 6. The 2 and 5 are distinct upon rotation; the 1 is not rotation-symmetric. Numbers with leading zeros are not valid.

Examples

Each of the following numbers has to be printed exactly this way:

  • 2
  • 4
  • 5
  • 6.
  • 8
  • 9.
  • 16
  • 60
  • 66.
  • 68.
  • 69
  • 906
  • 909.
  • 8088.
  • 9806.
  • 9886
  • 9889.
\$\endgroup\$
7
  • \$\begingroup\$ Shouldn't the 60 be 60.? \$\endgroup\$
    – red-X
    Commented Dec 29, 2014 at 15:39
  • 3
    \$\begingroup\$ @red-X "Numbers with leading zeros are not valid." \$\endgroup\$
    – Sp3000
    Commented Dec 29, 2014 at 15:41
  • \$\begingroup\$ clarify "valid number", does it include only numbers from 0 to n? that is, does 6 need a dot if there's no 9 in the tileset? (thematically, it doesn't actually, and no board game or dice would put a dot on the 6 if 6 was the highest number) \$\endgroup\$
    – Sparr
    Commented Dec 30, 2014 at 2:47
  • 2
    \$\begingroup\$ @rationalis: There is a standard loophole for this. (Also, this wouldn’t make sense thematically, as you have to teach that machine that language.) Either way, I added an existing. \$\endgroup\$
    – Wrzlprmft
    Commented Dec 30, 2014 at 8:56
  • 2
    \$\begingroup\$ @rationalis What generally happens is that only language versions existing prior to the posting of the challenge are eligible to be the winning program. Versions made after can still post for fun, but should specify in their post that they are not contending. So yes you can define such a language, but it'd be ineligible and most likely not well received due to being a standard loophole (as above). \$\endgroup\$
    – Sp3000
    Commented Dec 30, 2014 at 9:31

23 Answers 23

9
\$\begingroup\$

CJam, 46 44 43 42 bytes

l~),{_A%g1$s_6890s-!\_69s_W%erW%=!&&'.*N}/

I think there's some room for improvement.

Test it here.

Explanation

l~),{_A%g1$s_6890s-!\_69s_W%erW%=!&&'.*N}/
l~                                         "Read an eval input.";
  ),                                       "Get range from 0 to n.";
    {                                   }/ "For each...";
     _                                     "Get a copy of the integer.";
      A%g                                  "Ends with digit other than 0?";
         1$s_                              "Get another copy, convert to string, get a copy.";
             0689s-!                       "Contains rotation-safe digits?";
                    \                      "Swap with other copy.";
                     _                     "Get another copy.";
                      69s_W%er             "Swap 6 and 9.";
                              W%           "Reverse.";
                                =!         "Is different from original?";
                                  &&       "AND all three conditions.";
                                    '.*    "If true, push a period (else, an empty string).";
                                       N   "Push a newline.";
\$\endgroup\$
9
  • \$\begingroup\$ What does this return when the input is 8? (I pasted the code in Input and then clicked on the Run button, but an error was called.) \$\endgroup\$
    – DavidC
    Commented Dec 29, 2014 at 14:59
  • \$\begingroup\$ @DavidCarraher put the code in "Code" and n in Input. \$\endgroup\$ Commented Dec 29, 2014 at 15:18
  • \$\begingroup\$ input 98, your program puts a dot next to 66, which is incorrect. \$\endgroup\$
    – Sparr
    Commented Dec 30, 2014 at 2:46
  • 3
    \$\begingroup\$ @Sparr You should wait for the OP to answer your question before saying an answer is invalid. His statement: "Each of the following numbers has to be printed exactly this way" seems to contradict your interpretation. \$\endgroup\$ Commented Dec 30, 2014 at 4:13
  • \$\begingroup\$ I like the beauty of CJam explanations. \$\endgroup\$
    – user344
    Commented Dec 30, 2014 at 10:55
8
\$\begingroup\$

CJam, 46 45 43 42 bytes

ri){Is___69`96`erW%=!\6809`-!&IA%g&'.*N}fI

I think it can be golfed a little more.

Takes n from STDIN.

Try it online here

\$\endgroup\$
5
\$\begingroup\$

Pyth - 34 38

VhQJ`N+J*\.&nJX_J`69`96&eN!-J"0689

I must give thanks to @Sp3000 for helping me remove 4 bytes. I originally had an additional check &@JK which made sure there was a 6 or 9 in the number, but after perusing the answers before posting, I read his answer and noticed that my identical translation and reversal already took care of that.

Also thanks to @isaacg for pointing out that strings are iterables, and you can use set operations on them. Also for making the current code ;)

Explanation:

                                    : (implicit) Q=eval(input())
VhQ                                 : for N in range(Q+1):
   J`N                              : J=str(N)
      +J*\.                         : J + "." * ...
           &nJX_J`69`96             : J!=translate(reversed(J),"69","96") and...
                       &eN          : N%10 and...
                          !-J"0689  : not(setwise_difference(J, "0689"))
\$\endgroup\$
4
  • \$\begingroup\$ I don't think you need to use lists of integers for K and J - just use strings instead. Switching K to <backtick>69 and J to <backtick>N saves a few characters, as does inlining K in the resulting program. Shortest I could get under that technique was VhQJ``N+J*\.&nJX_J``69``96&eN!-J"0689, 34 characters. (Two backticks are really one.) \$\endgroup\$
    – isaacg
    Commented Dec 30, 2014 at 10:56
  • \$\begingroup\$ @isaacg Thanks for the tip! I think for some reason I forgot that making a string of numbers was really short in pyth by using `. Anyway, you can write a code block with backticks by escaping them with \. For example: hell`o wo`rld \$\endgroup\$ Commented Dec 30, 2014 at 15:02
  • \$\begingroup\$ In the explanation, you appear to have an extra _, before the `96. \$\endgroup\$
    – isaacg
    Commented Dec 30, 2014 at 19:25
  • \$\begingroup\$ @isaacg Thanks, fixed \$\endgroup\$ Commented Dec 30, 2014 at 20:14
5
\$\begingroup\$

APL 66

∊' ',¨{a←⌽'0.....9.86'[⎕D⍳b←⍕⍵]⋄'.'∊a:b⋄('0'=⊃a)∨⍵=⍎a:b⋄b,'.'}¨0,⍳

Explanation:

¨0,⍳           applies the function to each number 0-n
a←⌽'0.....9.86'[⎕D⍳b←⍕⍵] inverts 6s and 9s, leaving 8s and 0s, and replacing other numbers with dots. Reverses vector after substitution.
'.'∊a          if there is a dot in the number....
('0'=⊃a)       .. or if the number starts with 0...
⍵=⍎a           or if the (inverted) number is the same as original
:b             then print the original number
b,'.'          else print a dot in the end
∊' ',¨        Finally to give the result in the asked format i add a single space after each result and join them all 

Try it on tryapl.org

Note that in the online interpreter the ⍎ function doesn't work so i had to substitute it with 2⊃⎕VFI which does the same in this case, executes and returns the number, given a string.

\$\endgroup\$
4
  • \$\begingroup\$ Looks wrong: 60, 69, 90, and 96 must not have dots. \$\endgroup\$
    – ngn
    Commented Dec 29, 2014 at 17:36
  • \$\begingroup\$ Thanks @ngn, I corrected it, I think it works correctly now. \$\endgroup\$ Commented Dec 29, 2014 at 19:25
  • 3
    \$\begingroup\$ Well done :) Instead of ⊃,/ or ,/ you can use an at the front. \$\endgroup\$
    – ngn
    Commented Dec 29, 2014 at 21:23
  • \$\begingroup\$ Oh right! I don't usually work in ml1 so i forget about the ∊. \$\endgroup\$ Commented Dec 29, 2014 at 22:32
4
\$\begingroup\$

Perl 5, 53 bytes

say$_,"."x(!/[1-57]|0$/&&reverse!=y/96/69/r)for 0..<>

Online demo.

Uses the Perl 5.10+ say feature, so needs to be run with perl -M5.010 (or perl -E) to enable it. (See this meta thread.) Reads input from stdin, prints to stdout.

\$\endgroup\$
4
\$\begingroup\$

Python 2, 130 116 113 bytes

def f(n):S=`n`;n and f(n-1);print S+"."*all([n%10,set(S)<=set("0689"),(u""+S[::-1]).translate({54:57,57:54})!=S])

Defines a function f which prints the numbers to STDOUT, in ascending order.

This time I thought I'd take a leaf out of @feersum's book with .translate :)

Expanded:

def f(n):
 S=`n`        
 n and f(n-1)                                      # Recurse if not 0                                     
 print S+"."*all([n%10,                            # Not divisible by 10
                  set(S)<=set("0689"),             # Consists of 0689
                  (u""+S[::-1]).translate
                  ({54:57,57:54})!=S])             # When rotated is not itself

Previous solution:

def f(n):S=`n`;print S+"."*all([n%10,set(S)<=set("0689"),eval("S[::-1]"+".replace('%s','%s')"*3%tuple("6a96a9"))!=S]);n and f(n-1)

Thanks to @xnor for showing me the .replace trick some time ago.

\$\endgroup\$
3
  • \$\begingroup\$ You can use (u''+S[::-1]) instead of unicode(S[::-1]). Also, if you swap the print and the recursive call, numbers will come out in increasing order. \$\endgroup\$
    – ngn
    Commented Dec 29, 2014 at 22:08
  • \$\begingroup\$ @ngn Ah thanks, I didn't think u""+ would actually work \$\endgroup\$
    – Sp3000
    Commented Dec 30, 2014 at 0:13
  • \$\begingroup\$ See I think this should be smaller, for example it's not your fault that print is rightfully print, not "p" say, but if you were to write "p=print" and not have count as bytes in your "official" submission it'd shorten it! \$\endgroup\$
    – Alec Teal
    Commented Dec 30, 2014 at 12:14
4
\$\begingroup\$

C#, 343 309 characters

Way too long, but anyway:

namespace System.Linq{class C{static void Main(){int n=int.Parse(Console.ReadLine());for(int i=0;i<=n;i++){var b=i+"";var c=b.Replace("6","9");Console.Write(b+(b.All(x=>x=='0'|x=='8'|x=='6'|x=='9')&!b.EndsWith("0")&!(b.Count(x=>x=='6')==b.Count(x=>x=='9')&new String(c.Reverse().ToArray())==c)?". ":" "));}}}}

How does it work? To add a period to the number, it must match the following requirements:

  • Consists only of 0, 8, 6 and 9.
  • Does not end with a zero.
  • Is not the same number when you rotate it:
    • If a number has an equal amount of 6s and 9s, and
    • if c = the number with all 6s replaces with 9s,
    • and reversed c == c,
    • then: the rotated number is the same as the number itself.

The numbers are separated by a space.

Code with indentation:

namespace System.Linq
{
    class C
    {
        static void Main()
        {
            int n = int.Parse(Console.ReadLine());
            for (int i = 0; i <= n; i++)
            {
                var b = i + "";
                var c = b.Replace("6", "9");
                Console.Write(b +
                    (b.All(x => x == '0' | x == '8' | x == '6' | x == '9') &
                    !b.EndsWith("0") &
                    !(b.Count(x => x == '6') == b.Count(x => x == '9') &
                    new String(c.Reverse().ToArray()) == c) ? ". " : " "));
            }
        }
    }
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ My answer is longer ;) I appear to be bowling on the golf course. \$\endgroup\$ Commented Dec 30, 2014 at 5:05
  • 1
    \$\begingroup\$ What about 8808? It doesn't have any 6s or 9s, but is 8088 when rotated. \$\endgroup\$ Commented Dec 31, 2014 at 16:30
  • 1
    \$\begingroup\$ @El'endiaStarman Thanks a lot! While fixing my submission, I actually saved characters :) \$\endgroup\$
    – ProgramFOX
    Commented Dec 31, 2014 at 16:44
4
\$\begingroup\$

M (MUMPS) - 72 70

R n F i=0:1:n W !,i S r=$TR($RE(i),69,96) W:r=+r*r'=i*'$TR(i,0689) "."

Most built-in commands and functions in M have abbreviated versions. I've used the full names below.

READ n - Read a string from the keyboard and store it in n.

FOR i=0:1:n - Loop from zero to n, incrementing i by 1 each time. (The remainder of the line constitutes the body of the loop.)

WRITE !,i - Print a newline followed by the value of i.

SET r=$TRANSLATE($REVERSE(i),69,96)) - Reverse i, replace nines with sixes and sixes with nines, and store that in r.

WRITE:r=+r*r'=i*'$TRANSLATE(i,0689) "."

  • : - Denotes a postconditional expression, so the WRITE command is only executed if r=+r*r'=i*'$TRANSLATE(i,0689) evaluates to a truthy value.
  • r=+r - Check that r doesn't have a leading zero. The unary + operator converts a string to a number, which strips leading zeroes if there are any.
  • * - Multiplication operator. M has no order of operations; all binary operators are evaluated in the order they appear from left to right.
  • r'=i - Check that i isn't the same as it's flipped version r.
  • '$TRANSLATE(i,0689) - Remove all zeros, sixes, eights, and nines from i, and check that there's nothing left. (' is the logical negation operator.)
  • "." - Finally the argument to the WRITE command (a literal string).

Edit: Made it a little shorter by abusing the multiplication operator. Previous version:

R n F i=0:1:n W !,i S r=$TR($RE(i),69,96) I '$TR(i,0689),i'=r,r=+r W "."
\$\endgroup\$
3
\$\begingroup\$

APL, 53 characters

∊{⍵,'. '↓⍨∨/(3≡⊃i)(5∊i),⍵≡'9608x'[i←⌽'6908'⍳⍵]}∘⍕¨0,⍳

0,⍳N        numbers 0..N
{...}∘⍕¨    format each number as a string and do the thing in curly braces
                inside the braces ⍵ is the current string
'6908'⍳⍵    encode '6' as 1, '9' as 2, '0' as 3, '8' as 4, and all others as 5
⌽           reverse
'9608x'[A]  use each element of A as an index in '9608x':
                effectively: swap '9'←→'6', preserve '08', mask other digits
⍵≡          does it match the original string?
                this is the first boolean condition, two more to come
5∊i         did we have a digit other than '0689'?
3≡⊃i        is the first of i (that is, the last of ⍵) a '0' (encoded as 3)?
∨/          disjunction ("or") over the three conditions, returns 0 or 1
'. '↓⍨      drop 0 or 1 elements from the beginning of the string '. '
⍵,          prepend ⍵
∊           flatten the results to obtain a single output string
\$\endgroup\$
0
3
\$\begingroup\$

C# 205 209

C# doesn't have to be so long...
more or less, a port of my JavaScript answer

class P{static void Main(string[]a){for(int n=int.Parse(a[0]);n>=0;--n){string p="",u=n+p;int e=n%10;foreach(var d in u)p=(d<56?d!=54?d>48?e=0:0:9:120-d-d)+p;System.Console.WriteLine(e!=0&p!=u?u+".":u);}}}

Ungolfed

class P 
{
    static void Main(string[] a)
    {
        for (int n = int.Parse(a[0]); n >= 0; --n)
        {
            string p = "", u = n + p;
            int e = n % 10;
            foreach (var d in u) p = (d < 56 ? d != 54 ? d > 48 ? e = 0 : 0 : 9 : 120 - d - d) + p;
            System.Console.WriteLine(e != 0 & p != u ? u + "." : u);
        }
    }
}
\$\endgroup\$
2
\$\begingroup\$

Ruby, 81

?0.upto(*$*){|x|puts x.reverse.tr('69','96')!=x&&x=~/^[0689]+$/&&/0$/!~x ?x+?.:x}

Input is taken from the command line.

Generates a list of Strings from 0 to n. It loops trough them and prints them. It appends a dot if all conditions are satisfied:

  • reversing the number and replacing the 6s with 9s doesn't yield the original
  • the number only consists of the digits 0, 6, 8 and 9
  • the number doesn't end with 0
\$\endgroup\$
2
\$\begingroup\$

sed, 467

Longer than C#...

I pretty much completed this when @edc65 pointed out that answers need to process numbers 0-n and not just n. Adding the sed code to increment 0-n adds a LOT more code, as this task is ill-suited to arithmetic-less sed.

:l
/^[0689]*$/{
h
s/$/:/
:x
s/([0-9]):(.*)/:\2\1/
tx
s/://
y/69/96/
G
/^([0-9]+)\n\1/be
s/^[^0].*/&./
:e
s/.*\n//
}
p
s/\.//
s/[0-9]/<&/g
s/0//g;s/1/_/g;s/2/__/g;s/3/___/g;s/4/____/g;s/5/_____/g
s/6/______/g;s/7/_______/g;s/8/________/g;s/9/_________/g
:t
s/_</<__________/
tt
s/<//g
s/_//
:b
s/__________/</g
s/<([0-9]*)$/<0\1/
s/_________/9/;s/________/8/;s/_______/7/;s/______/6/
s/_____/5/;s/____/4/;s/___/3/;s/__/2/;s/_/1/
s/</_/g
tb
s/^$/0/
/^0$/by
bl
:y
c\
0
p

As per the OP, ordering doesn't matter, so we work downwards from n to 0.

Output:

$ sed -rnf rotproof.sed <<< 100 | grep "\."
99.
98.
89.
86.
68.
66.
9.
6.
$ 
\$\endgroup\$
2
\$\begingroup\$

bc, 158

After doing this purely in sed using all string and regex operations with no native arithmetic, I was curious to see how this would look the other way around, i.e. all arithmetic and logic operations and no string/regex:

for(i=read();i+1;r=0){p=1
for(x=i;x;x/=A){d=x%A
if(x==i&&!d)p=0
if(d==6||d==9)d=F-d else if(d%8)p=0
r=r*A+d}
if(r==i)p=0
print i--
if(p)print "."
print "\n"}

Output is sorted in descending order.

Output:

$ bc rotproof.bc <<< 100 | grep "\."
99.
98.
89.
86.
68.
66.
9.
6.
$ 
\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6) 101 104 106 109

A function with n as argument, output via console.log
Edit using %10 to test for leading 0
Edit 2 for reorganization, I don't need array comprehension after all
Edit 3 modified (again) the check for leading 0

F=n=>{
   for(;e=~n;console.log(e*l&&p-n?n+'.':n),--n)
     for(d of(p='')+n)p=(l=d<8?d-6?-d?e=0:0:9:24-d-d)+p
}

Ungolfed and easier to test

F=n=>
{
  o = '';
  for( ; ~n; --n) // loop on n decreasing to 0 (~n is 0 when n==-1)
  {
    e = ~n; // init to a nonzero value, zero will mark 'invalid digit'
    p = ''; // build rotated number in p
    for(d of '' + n)
    {
      // l is the current digit, on exit will be the first digit of p
      l = d < 8 ?
            d != 6 ?
              d != 0 ?
                e = 0 // invalid char found, no matter what
                : 0 
              : 9 // 6 become 9
            : 24 - d - d; // calc 8 => 8, 9 => 6
      p = l + p;
    }       
    // e==0 if invalid char, l==0 if leading 0
    o += ' ' + ( e * l && p-n ? n+'.' : n);
  }
  console.log(o);
}

F(100)

Output

100 99. 98. 97 96 95 94 93 92 91 90 89. 88 87 86. 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68. 67 66. 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9. 8 7 6. 5 4 3 2 1 0
\$\endgroup\$
4
  • \$\begingroup\$ Is there a name for the construction with the for loop within brackets []? I am looking for a documentation, because I only knew this from python so far. \$\endgroup\$
    – flawr
    Commented Dec 29, 2014 at 18:08
  • 1
    \$\begingroup\$ I think you can save a lot on newlines here. \$\endgroup\$
    – britishtea
    Commented Dec 29, 2014 at 18:14
  • 1
    \$\begingroup\$ @britishtea newlines and indentation added for readability and not counted. It's a single line \$\endgroup\$
    – edc65
    Commented Dec 29, 2014 at 19:42
  • 1
    \$\begingroup\$ @flawr developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… \$\endgroup\$
    – edc65
    Commented Dec 29, 2014 at 19:44
1
\$\begingroup\$

Bash + coreutils, 105

for((i=0;i<=$1;i++));{
[ ${i//[0689]/} ]||[ $i = `rev<<<$i|tr 69 96` ]||((!${i: -1}))||d=.
echo $i$d
d=
}

Test:

$ ./rotproof.sh 100 | grep "\."
6.
9.
66.
68.
86.
89.
98.
99.
$ 
\$\endgroup\$
0
1
\$\begingroup\$

AWK: 120

{a[a[6]=9]=6;a[8]=8;for(j=a[0]=0;j<=$0;++j){r="";for(i=j;i;i=int(i/10))r=r a[i%10];print(j~/[^0689]|0$/||j==r)?j:j"."}}

Read the n value from stdin.

Test:

C:\AWK>gawk -f revnum.awk|grep \.
100
^Z
6.
9.
66.
68.
86.
89.
98.
99.

\$\endgroup\$
1
\$\begingroup\$

Rebol - 195

for n 0 do input 1[b: copy a: form n d: c: 0 parse reverse a[any[m:"6"(change m"9"++ c)|"9"(change m"6"++ c)|"0"|"8"| skip(++ d)]]print rejoin [b either all[d = 0 c > 0 a != b a/1 != #"0"]"."{}]]

Ungolfed + some annotations:

for n 0 do input 1 [
    b: copy a: form n
    d: c: 0

    ; reverse number and rotate "6" & "9"
    ; and do some counts (c when "6" or "9" and d when != "0689")
    parse reverse a [
        any [
            m:
              "6" (change m "9" ++ c)
            | "9" (change m "6" ++ c)
            | "0"
            | "8"
            | skip (++ d)
        ]
    ]

    print rejoin [
        b either all [
            d = 0               ; only has 0689 digits
            c > 0               ; must have at least one "6" or "9"
            a != b              ; not same when reversed
            a/1 != #"0"         ; does not "end" with zero
        ]
        "." {}                  ; if ALL then print "." else blank {}
    ]
]
\$\endgroup\$
1
\$\begingroup\$

Python - 152

for i in range(input()+1):print`i`+("."*all([j in"0689"for j in`i`])and`i`[-1]!="0"and`i`!=`i`.replace("9","x").replace("6","9").replace("x","6")[::-1])
\$\endgroup\$
9
  • \$\begingroup\$ +1. Looking good... If you want to learn some tricks for getting it shorter there is another answer in python 2 which uses translate instead of replace, and in the edit history it also has a way of combining those 3 replaces into 1 which might come in handy for future questions... \$\endgroup\$ Commented Dec 30, 2014 at 1:58
  • 2
    \$\begingroup\$ Nice progress! In addition to the above here's some more golfs: "."if a[i]else"" -> "."*a[i], int(raw_input()) -> input() (which is really just eval(raw_input())) \$\endgroup\$
    – Sp3000
    Commented Dec 30, 2014 at 3:45
  • \$\begingroup\$ Some golfes: (1) In Python 2, you can replace str(i) with `i`. (2) You use a only once, so why assign it to a variable. \$\endgroup\$
    – Wrzlprmft
    Commented Jan 1, 2015 at 10:25
  • \$\begingroup\$ I'll use your second suggestion, but I use str(i) several times. Which one can I replace with i? \$\endgroup\$
    – KSFT
    Commented Jan 1, 2015 at 15:12
  • 1
    \$\begingroup\$ Not i, but i with backticks, which is synonymous to repr(i). You can use it instead of str(i) everywhere, although if you have str(i) around that many times it might be shorter to assign it to a variable and use that in addition to using backticks. (i.e. x=`i`; (do stuff with x)) \$\endgroup\$
    – Sp3000
    Commented Jan 1, 2015 at 15:48
1
\$\begingroup\$

JavaScript - 168 129 119 113 111 108

F=n=>{for(;~n;n--){r='';for(c of""+n)r=(c-6?c-9?c:6:9)+r;console.log(r-n&&!/[1-57]/.test(r)&&n%10?n+".":n)}}

4 5 6. 8 9. 16 60 66. 68. 69 906 909. 6090 9806. 9886 9889.

Or readable version:

F=n=>{for(;~n;n--){
    r='';for(c of ""+n)r=(c-6?c-9?c:6:9)+r; // rotate
    console.log( // output, new-line is added
        // original number, and
        // append dot only if number is different than its rotated version and no un-rotatable digit is present and there is no zero at the end
        r-n && !/[1-57]/.test(r) && n%10
           ?n+".":n
    )}}

I am not very happy with the regex, any ideas?

Edit: Learned neat trick with ~ and for (... of ...) from @edc65
Edit2: Reorganized conditions
Edit3: applied suggestions by @edc65

\$\endgroup\$
9
  • \$\begingroup\$ Bad pupil :) i=n+"";for(c of i) => for(c of i=n+"") save 2 bytes \$\endgroup\$
    – edc65
    Commented Dec 30, 2014 at 20:28
  • \$\begingroup\$ ...and c==6?A:B => c!=6=>B:A => c-6?B:A \$\endgroup\$
    – edc65
    Commented Dec 30, 2014 at 20:30
  • \$\begingroup\$ also, usually Regexp.test(String) can be used instead of String.match(Regexp), 1 byte shorter. \$\endgroup\$
    – edc65
    Commented Dec 30, 2014 at 20:34
  • \$\begingroup\$ 6 bytes is total, thanks :) for(c of i=n+"") is quite logical when I see it, but I wouldn't think of it. c-6?B:A God forbid I ever put this into production code \$\endgroup\$
    – zabalajka
    Commented Dec 31, 2014 at 11:15
  • \$\begingroup\$ Idea about the regexp: you need to check for 1 invalid char, not 1 ore more, so '+' is not needed.If you fiddle with your console.log expression you can save 8 bytes ... but then I think your answer would be too short \$\endgroup\$
    – edc65
    Commented Dec 31, 2014 at 13:57
1
\$\begingroup\$

05AB1E, 38 37 30 29 bytes

ÝεÐSUT%ĀiŽR!XåPiÐ69‡RÊi'.«]»

Try it online.

Explanation:

Ý                # Inclusive 0-based range: [0, (implicit) input]
 ε               # Map each integer to:
  Ð              #  Triplicate the current integer
  SU             #  Convert it to a list of digits, and pop and store it in variable `X`
    T%Āi         #  If the current integer contains no trailing zeros
    ŽR!XåPi      #  And if the current integer only consists of the digits [0689]
    Ð69‡RÊi     #  And if the current integer is not the same when its 6s and 9s
                 #  are swapped and then the total is reversed
             '.« #   Concat a '.'
                 #  Implicit else: use the top of the stack (the duplicate current integer)
]                # Close all three ifs and the map
 »               # Join the resulting list by newlines (and output implicitly)

Additional explanation for some parts:

T%Āi       # Check if the integer contains no trailing zeros:
T          #  Push 10 (T is a builtin for 10)
 %         #  Modulo
  Ā        #  Trutified: 0 remains 0 (falsey), everything else becomes 1 (truthy)
           #   i.e. 12 % 10 → 2 → 1 (truthy)
           #   i.e. 68 % 10 → 8 → 1 (truthy)
           #   i.e. 70 % 10 → 0 → 0 (falsey) (70 remains as is)
           #   i.e. 609 % 10 → 9 → 1 (truthy)
           #   i.e. 808 % 10 → 8 → 1 (truthy)

ŽR!XåPi    # Check if the integer only consists of the digits 0, 6, 8 and/or 9:
ŽR!        #  Push 6890 (Ž is a builtin for 2-char compressed integers, where R! is 6890)
   X       #  Push variable `X` (the list of digits)
    å      #  Check for each of these digits if they're in "6890"
     P     #  Take the product of that list
           #   i.e. [1,2] → [0,0] → 0 (falsey) (12 remains as is)
           #   i.e. [6,8] → [1,1] → 1 (truthy)
           #   i.e. [6,0,9] → [1,1,1] → 1 (truthy)
           #   i.e. [8,0,8] → [1,1,1] → 1 (truthy)

Ð69‡RÊi   # Check if the integer with 6s and 9s swapped and then reversed isn't unchanged:
Ð          #  Triplicate the integer
 69        #  Push 69
   Â       #  Bifurcate (short for Duplicate & Reverse)
    ‡      #  Transliterate (in `a` replace all characters `b` with characters `c`)
     R     #  Reverse
      Ê    #  Check for inequality
           #   i.e. 68 → "68" → "98" → "89" → 68 != "89" → 1 (truthy) (68 becomes "68.")
           #   i.e. 609 → "609" → "906" → "609" → 609 != "609" → 0 (falsey) (609 remains as is)
           #   i.e. 808 → "808" → "808" → "808" → 808 != "808" → 0 (falsey) (808 remains as is)
\$\endgroup\$
0
\$\begingroup\$

Perl - 84

for(0..$ARGV[0]){s/6/x/g;s/9/6/g;s/x/9/g;printf"$_%s\n",$_=~/^[0689]+[689]$/?".":""}
\$\endgroup\$
0
\$\begingroup\$

Powershell, 111 102 bytes

param($s)$s+'.'*!($s-match'[1-57]|0$|'+-join$(switch -r($s[($s.Length-1)..0]){'0|8'{$_}'6'{9}'9'{6}}))

Explained test script:

$f = {

param($s)           # input string
$l=$s.Length        # length of the string
$c=$s[($l-1)..0]    # chars of the string in the reversed order
$d=switch -r($c){   # do switch with regex cases for each char
    '0|8'{$_}       # returns the current char if it equal to 8 or 0
    '6'{9}          # returns 9 if the current char is 6
    '9'{6}          # returns 6 if the current char is 9
}                   # returns array of new chars (contains 0,6,8,9 only)
$s+'.'*!(            # returns s. Add '.' if not...
    $s-match'[1-57]|0$|'+-join$d
                    # $s contains chars 1,2,3,4,5,7 or
                    # ends with 0 or
                    # equal to string of $d
)

}

@(
    ,('2'    ,'2'   )
    ,('4'    ,'4'   )
    ,('5'    ,'5'   )
    ,('6.'   ,'6'   )
    ,('7'    ,'7'   )
    ,('9.'   ,'9'   )
    ,('16'   ,'16'  )
    ,('60'   ,'60'  )
    ,('66.'  ,'66'  )
    ,('68.'  ,'68'  )
    ,('69'   ,'69'  )
    ,('906'  ,'906' )
    ,('909.' ,'909' )
    ,('8088.','8088')
    ,('9806.','9806')
    ,('9886' ,'9886')
    ,('9889.','9889')
) | % {
    $e,$s = $_
    $r = &$f $s
    "$($r-in$e): $r"
}

Output:

True: 2
True: 4
True: 5
True: 6.
True: 7
True: 9.
True: 16
True: 60
True: 66.
True: 68.
True: 69
True: 906
True: 909.
True: 8088.
True: 9806.
True: 9886
True: 9889.
\$\endgroup\$
0
\$\begingroup\$

Stax, 27 bytes

Ç▒≈♣▌╬"÷╜─B↓«âpø←╚S☼ì>♫è;&╛

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

0p      print 0 with no line break
F       for each [1 .. n] execute the rest of the program, where n is the input
  zP    print a newline
  q     peek and print the iterating variable without newline
  A%!C  modulo 10, and cancel iteration if zero (this cancels for multiples of 10)
  _$cc  convert iterating value to string and duplicate it twice on the stack
  7R6-$ construct the string "123457"
  |&C   if the character intersection is truthy, cancel the iteration
  r     reverse string
  69$:t map 6 and 9 characters to each other
  =C    if this rotated string is equal to the original, cancel iteration
        print "." with no newline 
        (this comment precedes the instruction because it's an unterminated literal)
  ".

Run this one

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.