4
\$\begingroup\$

Searching for rotatable numbers, like: 68089

Rotatable 68089

If you consider numbers upside-down,

  • 6 looks like 9,
  • 8 looks like 8,
  • 9 looks like 6 and
  • 0 looks like 0.

The others digits (1, 2, 3, 4, 5 and 7 ) look like nothing...

I wonder how many number could be rotatable between 0 and 1000! The answer is definitively 11: 0, 8, 69, 88, 96, 609, 689, 808, 888, 906 and 986

Well I imagine a tool able to display all rotatable numbers, between two boundaries...

The tool may be run in any way you want, whith two boundaries as argument or standard input. Then must return all rotatable numbers between this two boundaries.

About duplicate

If the other question: Numbers with Rotational Symmetry look something similar, they are not!!: 1) Not same bunch of digits, 2) not same behaviour and 3) search in between two boundaries...

And as Jonathan Allan's comment pointed out. Not same question, not same ways for reaching answer. Here are other interesting way for doing this!!

Sample:

Input:

0 1000

Output:

0 8 69 88 96 609 689 808 888 906 986

Or input:

8000 80000

Output:

8008 8698 8888 8968 9006 9696 9886 9966 60009 60809 66099 66899 68089 68889 69069 69869
  • No matter on output format (on one or multiple lines).

  • Only numbers must be accepted.

  • Of course, except 0 himself, a number could not begin by 0.

  • This is , so shorter answer (in bytes) win!

Leaderboard

var QUESTION_ID=251079;
var OVERRIDE_USER=9424;
var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;function answersUrl(d){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+d+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(d,e){return"https://api.stackexchange.com/2.2/answers/"+e.join(";")+"/comments?page="+d+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(d){answers.push.apply(answers,d.items),answers_hash=[],answer_ids=[],d.items.forEach(function(e){e.comments=[];var f=+e.share_link.match(/\d+/);answer_ids.push(f),answers_hash[f]=e}),d.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(d){d.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),d.has_more?getComments():more_answers?getAnswers():process()}})}getAnswers();var SCORE_REG=function(){var d=String.raw`h\d`,e=String.raw`\-?\d+\.?\d*`,f=String.raw`[^\n<>]*`,g=String.raw`<s>${f}</s>|<strike>${f}</strike>|<del>${f}</del>`,h=String.raw`[^\n\d<>]*`,j=String.raw`<[^\n<>]+>`;return new RegExp(String.raw`<${d}>`+String.raw`\s*([^\n,]*[^\s,]),.*?`+String.raw`(${e})`+String.raw`(?=`+String.raw`${h}`+String.raw`(?:(?:${g}|${j})${h})*`+String.raw`</${d}>`+String.raw`)`)}(),OVERRIDE_REG=/^Override\s*header:\s*/i;function getAuthorName(d){return d.owner.display_name}function process(){var d=[];answers.forEach(function(n){var o=n.body;n.comments.forEach(function(q){OVERRIDE_REG.test(q.body)&&(o="<h1>"+q.body.replace(OVERRIDE_REG,"")+"</h1>")});var p=o.match(SCORE_REG);p&&d.push({user:getAuthorName(n),size:+p[2],language:p[1],link:n.share_link})}),d.sort(function(n,o){var p=n.size,q=o.size;return p-q});var e={},f=1,g=null,h=1;d.forEach(function(n){n.size!=g&&(h=f),g=n.size,++f;var o=jQuery("#answer-template").html();o=o.replace("{{PLACE}}",h+".").replace("{{NAME}}",n.user).replace("{{LANGUAGE}}",n.language).replace("{{SIZE}}",n.size).replace("{{LINK}}",n.link),o=jQuery(o),jQuery("#answers").append(o);var p=n.language;p=jQuery("<i>"+n.language+"</i>").text().toLowerCase(),e[p]=e[p]||{lang:n.language,user:n.user,size:n.size,link:n.link,uniq:p}});var j=[];for(var k in e)e.hasOwnProperty(k)&&j.push(e[k]);j.sort(function(n,o){return n.uniq>o.uniq?1:n.uniq<o.uniq?-1:0});for(var l=0;l<j.length;++l){var m=jQuery("#language-template").html(),k=j[l];m=m.replace("{{LANGUAGE}}",k.lang).replace("{{NAME}}",k.user).replace("{{SIZE}}",k.size).replace("{{LINK}}",k.link),m=jQuery(m),jQuery("#languages").append(m)}}
body{text-align:left!important}#answer-list{padding:10px;float:left}#language-list{padding:10px;float:left}table thead{font-weight:700}table td{padding:5px}
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Sites/codegolf/primary.css?v=f52df912b654"> <div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td><a href="{{LINK}}">{{SIZE}}</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td><a href="{{LINK}}">{{SIZE}}</a></td></tr></tbody> </table> 

\$\endgroup\$
10
  • 2
    \$\begingroup\$ Why is your example for rotatable numbers between 0 and 1000 equal to 0 8 69 88 96 609 689 808 888 906 986 but in the example output it is 0 6 8 66 88 606 666 686 808 868 888? I have no idea what you are asking for. \$\endgroup\$
    – chunes
    Aug 14 at 13:11
  • \$\begingroup\$ g808 is also not a number \$\endgroup\$
    – pxeger
    Aug 14 at 13:13
  • \$\begingroup\$ Related. \$\endgroup\$
    – Wheat Wizard
    Aug 14 at 13:56
  • 1
    \$\begingroup\$ @JonathanAllan Yes, there was an error (wrong cut'n paste) in my post. I'm sorry for that! \$\endgroup\$ Aug 14 at 15:32
  • 2
    \$\begingroup\$ @Community Is it really a duplicate if a different method can be used which is terser? - Compare my Jelly solution to Denis' on the other post, porting that approach will cost more bytes here and vice versa I believe. (I do see that many answers probably use the same approach in both though.) \$\endgroup\$ Aug 14 at 23:22

5 Answers 5

5
\$\begingroup\$

Jelly, 15 bytes

Seems a little longer than I imagine is possible

rD‘×Ṛ$fƑʋƇ“¢FQ‘

A dyadic Link that accepts the two bounds and yields the rotatable numbers

Try it online!

How?

Identifies rotatable mirrored pairs of digits by adding one to each and multiplying them together. The only results which are any of \$1\$, \$70\$, or \$81\$ are the valid pairs:

(Digit+1)(Mirror+1) 0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9 10
1 2 4 6 8 10 12 14 16 18 20
2 3 6 9 12 15 18 21 24 27 30
3 4 8 12 16 20 24 28 32 36 40
4 5 10 15 20 25 30 35 40 45 50
5 6 12 18 24 30 36 42 48 54 60
6 7 14 21 28 35 42 49 56 63 70
7 8 16 24 32 40 48 56 64 72 80
8 9 18 27 36 45 54 63 72 81 90
9 10 20 30 40 50 60 70 80 90 100
rD‘×Ṛ$fƑʋƇ“¢FQ‘ - Link: integer, A; integer B
r               - inclusive range -> [A..B]
          “¢FQ‘ - list of code page indices -> [1,70,81]
         Ƈ      - keep those of [A..B] for which:
        ʋ       -   last four links as a dyad - f(N, M=[1,70,81]):
 D              -     to decimal digits   e.g. N=6089 -> [ 6, 0, 8, 9]
  ‘             -     increment                          [ 7, 1, 9,10]
     $          -     last two links as a monad:
    Ṛ           -       reverse                          [10, 9, 1, 7]
   ×            -       multiply (vectorises)            [70, 9, 9,70]
       Ƒ        -     is invariant under?:
      f         -       filter keep if in M              [70, 70] -> nope

We could shift down by four instead of up by one before multiplying and then only the valid pairs will give \$10\$ or \$16\$ but I think it's the same byte count:

rD_4×Ṛ$fƑʋƇ“½Ñ‘
\$\endgroup\$
1
  • 1
    \$\begingroup\$ @downvoter - why is this not useful or unclear? I personally think it's pretty good and very clear so any feedback would be appreciated! \$\endgroup\$ Aug 15 at 17:40
4
\$\begingroup\$

Vyxal, 15 bytes

ṡ'»ƛ∪&»FS‛69*Ṙ=

Try it Online!

Takes end boundary then start boundary

Explained

ṡ'»ƛ∪&»FS‛69*Ṙ=
ṡ'               # From the range(start, end + 1), keep only items where:
  »ƛ∪&»FS        #  Removing the numbers 1, 2, 3, 4, 5 and 7
         ‛69*    #  Ring translated by the string 69 (6 becomes 9 and 9 becomes 6)
             Ṙ=  #  And reversed equals the original item
\$\endgroup\$
4
\$\begingroup\$

Factor + flip-text, 57 bytes

[ [a,b] [ unparse dup flip-text "5"""replace = ] filter ]

Attempt This Online!

Factor's ᵷuᴉddᴉʃɟ-ʇxǝʇ vocabulary considers 5 to be the same as itself when upside down, so I had to remove the 5's before checking for equality.

\$\endgroup\$
3
\$\begingroup\$

Raku, 53 bytes

{grep {.trans(~6890123457=>~9860):d eq .flip},$^a..$^b}

Try it online!

Treats the number as a string, transliterates the rotatable numbers to their counterparts and deletes the rest, and tests that that string is equal to the reverse of the input string.

\$\endgroup\$
3
\$\begingroup\$

Regex (ECMAScript or better) m, 165 159 164 152 bytes

(?=((x{8}$|(?=.*?(?=(((x*)\5{8}(?=\5$))+x$))(x*)\6{99})(?=(\3x)(?:\7{5}(\7\7|\3{3}|xxx))(?!\3)(x*)\9{9}$)(?=(x*(?=\6|$))(|\6{6}x{9})\9$)\10)*$)
(?!x\1))

Try it online!

Takes its input in unary, as the lengths of two strings of xs delimited by a newline (high end of range first, then low end of range). Returns its result as the list of matches' \1 captures (each is also a string of xs whose length is the value).

This is adapted from my solution to Numbers with Rotational Symmetry, which is a version of this, with 1 also treated as a rotationally-symmetric numeral. As described in that post, it's impossible for ECMAScript regex to match this sequence in decimal (it can't even match anbn), but it's possible in unary.

The multiline flag is used so that $, which occurs many times in the regex, can be used instead of \b or (?=¶), where is the delimiter (which needs to be a newline to take advantage of this m flag trick, but could be any non-word-character otherwise).

The regex works by looping the following logic:

  1. Carve away both the leading and trailing digit if they are an allowed pair, or (for single-digit values) an allowed single digit.
  2. Prevent the value sent to the next iteration from having any leading zeroes, since the regex operates on numbers, not strings, so any leading zeroes would be stripped. If it has a leading zero, add \$6\$ to the leading digit and \$9\$ to the trailing digit. If both were zero, meaning that inward up to that point, the input is symmetric, the modified number will now have a \$6\$ on the left and a \$9\$ on the right, preserving the trait of symmetry. If the trailing digit was nonzero (meaning the input is not a rotationally symmetric number), adding one of \$69, 609, 6009, ...\$ is guaranteed not to change it to one that is symmetric, because for example \$6009\$ could only be added to any number in the range \$0001\$ to \$0999\$ with a nonzero last digit, which can only yield a number in the range \$6010\$ to \$7008\$ with a last digit other than \$9\$, none of which are rotationally symmetric. This allows us to golf off 13 bytes, due to not needing the trailing zero check (?=(x{10})*$). (This would not work with adding one of \$88, 808, 8008, ...\$ even though (\6x){8} is shorter than \6{6}x{9}, because \$88+8=96\$, \$808+098=906\$, \$8008+0998=9006\$, etc.)
(?=                          # Wrap the entire test in a lookahead so that after
                             # matching, the position will only advance one
                             # character forward for the next test.
    (                        # \1 = tail = the number to be tested
        (
            x{8}$                # If tail==8, let tail=0 and end the loop
        |
            # Assert tail >= 10; find \3 = the largest power of 10 that is <= tail
            (?=
                .*?              # Decrease tail by the minimum necessary to satisfy
                                 # the following assertion:
                (?=
                    # Assert tail is a power of 10 >= 10; \3 = tail
                    (((x*)\5{8}(?=\5$))+x$)
                )
                (x*)\6{99}       # \6 = floor(tail / 100)
            )

            # Require tail is of the form 8.*8, 6.*9, or 9.*6
            (?=
                (\3x)            # \7 = \3 + 1
                (?:
                    \7{5}
                    (
                        \7\7     # 8.*8
                    |
                        \3{3}    # 9.*6
                    |
                        xxx      # 6.*9
                    )
                )
                (?!\3)
                (x*)\9{9}$       # Assert tail is divisible by 10;
                                 # \9 = tail / 10 == floor((N % \3) / 10)
            )

            # Set tail = \9, but if \9 is of the form 0.*0, the next iteration would
            # not be able to see its leading zero, so change it to the form 6.*9 in
            # that case, otherwise leave it unchanged. If \9 is of the form 0.*[1-9],
            # don't go to the next iteration.
            (?=
                (                # \10 = tool to make tail = \9 or \9 + \6*6 + 9
                    x*
                    # Assert that the leading digit of tail is not 0, unless tail==0
                    (?=
                        \6       # Assert that the leading digit of tail is not 0
                    |            # or
                        $        # Assert that tail==0
                    )
                )
                # Iff necessary to satisfy the above, tail += \6*6 + 9
                (
                |
                    \6{6}x{9}
                )
                \9$              # tail = \9
            )
            \10                  # tail = \9 or \9 + \6*6 + 9
        )*                       # Execute the above loop as many times as possible,
                                 # with a minimum of zero iterations.
        $                        # Assert tail==0
    )
    ¶                        # tail = low end of range
    (?!x\1)                  # Assert \1 ≥ tail
)

Regex (ECMAScript 2018 or better), 173 167 172 160 bytes

(?=((x{8}$|(?=.*?(?=(((x*)\5{8}(?=\5$))+x$))(x*)\6{99})(?=(\3x)(?:\7{5}(\7\7|\3{3}|xxx))(?!\3)(x*)\9{9}$)(?=(x*(?=\6|$))(|\6{6}x{9})\9$)\10)*$)(?<=(?<!x\1),.*))

Attempt This Online!

Takes its input in order of {low end of range, high end of range}, with a comma delimiter. Otherwise the same as the above.

("ECMAScript 2018 or better" includes just two other engines: .NET and Pythonregex, but I haven't made test harnesses in them for this type of regex yet.)

The part of this regex that differs from the one above:

(?=
    (                        # \1 = tail = the number to be tested
    )
    (?<=
        (?<!x\1)             # Assert \1 ≥ head
        ,.*                  # head = low end of range; assert \1 was captured
                             # from inside high end of range
    )
)
\$\endgroup\$

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