Sequence Without Sevens

16

This challenge is based on a drinking game. I advise against alcohol consumption while programming.

In this game, the players count up in turns: the first player says 1, the second says 2 and so on. Here's the twist however: each number that is divisible by 7 or has a 7 in its digits (in base 10) is replaced by another counter. This means 7 is replaced by 1, 14 is replaced by 2, 17 is replaced by 3 and so on. For this "sub-sequence", the same rules apply! 35 would be replaced by 7, which in turn is replaced by 1. This process repeats until the number is "valid".

Here's a visualization of the first 100 numbers in the sequence:

n = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
gets replaced by:
                1                  2        3           4                 5  6                    7     8              9             10    11                   12 13                14          15       16 17 18 19 20 21 22 23 24 25             26       27          28                29 30       
gets replaced by:
                                                                                                  1                                                                                   2                       3           4                                   5           6                            

final sequence:
    1 2 3 4 5 6 1 8 9 10 11 12 13  2 15 16  3 18 19 20  4 22 23 24 25 26  5  6 29 30 31 32 33 34  1 36  8 38 39 40 41  9 43 44 45 46 10 48 11 50 51 52 53 54 55 12 13 58 59 60 61 62  2 64 65 66 15 68 69 16  3 18 19 20  4 22 23 24 25 80 81 82 83 26 85 86  5 88 89 90  6 92 93 94 95 96 29 30 99 100

In the final sequence, no number has a seven in its digits or is divisible by seven.

Input description

  • An integer n (1 <= n <= 7777 or 0 <= n <= 7776)

You may choose whether you use a 0-indexed or 1-indexed input.

Output description

  • The nth number in the sequence

Examples

The examples are 1-indexed. For 0-indexed, subtract one from n.

n   ->   f(n)
1        1
5        5
7        1
35       1
77       23
119      1
278      86
2254     822
2255     2255
7777     3403

Scoring

This is , so shortest answer in bytes wins!

Arfie

Posted 2017-08-23T09:04:31.157

Reputation: 1 230

Question was closed 2017-08-23T13:34:06.587

1Hmm, is test case 278 correct? I get the correct result for each of them, but 278 becomes 86 instead of 5. :S – Kevin Cruijssen – 2017-08-23T09:17:20.337

1@KevinCruijssen You're right, 278 is supposed to be 86. 279 becomes 5. Fixed! – Arfie – 2017-08-23T09:19:38.617

2Related but quite different. – Arnauld – 2017-08-23T09:37:35.427

1I would swear this is a dupe but can't seem to find any. – Erik the Outgolfer – 2017-08-23T10:52:23.073

1@EriktheOutgolfer Actually, I'm sure I've seen this before as well -- not just the one I already mentioned -- but couldn't find it either ... – Arnauld – 2017-08-23T11:44:48.247

@Arnauld Maybe it was deleted or something then. I remember it having something like 1, 2, 3, 4, 5, 6, *1*, 8, 9, ..., 34, ***1***, 36, ... (where stars are what it looked like in markdown) – Erik the Outgolfer – 2017-08-23T11:46:06.150

1

@EriktheOutgolfer Ah! this one, I think (using Google rather than the internal search).

– Arnauld – 2017-08-23T11:55:48.210

3@Arnauld Yep that's an exact dupe...or not? That one asks you to print indefinitely, this one asks you for a specific item...it's somewhat like the "count up forever" question vs. my "count up folks!" question. Very different approaches. – Erik the Outgolfer – 2017-08-23T11:56:27.160

5I think it's similar enough to be a duplicate. We don't need both a "print at least n terms" and a "print the nth term" of every sequence challenge. – mbomb007 – 2017-08-23T13:33:29.913

Answers

7

Java, 122 121 98 97 bytes

int c(int n){int a=0,b=0,c=n;for(;n-->0;c+=a=((--b+"").indexOf(55)&b%7)>>31);return a<0?-b:c(c);}

-23 bytes thanks to @Nevay.
-1 byte thanks to @Neil.

Explanation:

Try it here.

int c(int n){                            // Method with integer as parameter and return-type
  int a=0,                               //  Flag integer
      b=0,                               //  Regular counter
      c=n;                               //  7-counter
  for(;n-->0;                            //  Loop over the input
    c+=                                  //   Append `c` with:
       a=                                //    Set `a` to:
         ((--b+"").indexOf(55)&b&7)      //     If `b` is divisible by or contains 7:
                                         //     (and decrease `b` by 1 in the process)
                                   >>31  //      Bitwise right shift so `a` is either `-1` or `0`
  );                                     //  End of loop
  return a<0?                            //  If `a` is now -1:
    -b                                   //   Return the regular counter `b` (as positive)
   :                                     //  Else:
    c(c);                                //   Recursive call with 7-counter `c` as input
}                                        // End of method

Kevin Cruijssen

Posted 2017-08-23T09:04:31.157

Reputation: 67 575

1102, I think: int c(int n){int q=0,r=1,a=1,b=0;for(;--n>0;b+=q=(++a+"").contains("7")|a%7<1?1:0);return q>0?c(b):a;} – Neil – 2017-08-23T09:59:30.110

198 bytes: int c(int n){int r=1,a=0,b=1;for(;n-->0;r=((--a+"").indexOf(55)&a%7)<0?a:b++);return a<r?c(r):-r;} – Nevay – 2017-08-23T11:09:37.313

Actually my answer is only 98 bytes, once you remove the unused r=1,... – Neil – 2017-08-23T12:06:49.620

6

Python 3, 77 bytes

g=lambda a:a%7<1or'7'in str(a)
f=lambda a:g(a)and f(sum(map(g,range(a))))or a

Try it online!

Leaky Nun

Posted 2017-08-23T09:04:31.157

Reputation: 45 011

3Does this not work in Python 2? Then you could do '7'in\a`` instead of '7'in str(a) – Arfie – 2017-08-23T09:23:50.900

4@Ruud Leaky doesn't like Python 2. – Mr. Xcoder – 2017-08-23T09:49:04.203

4Shouldn't this be 23 bytes?! – Shaggy – 2017-08-23T11:16:57.260

2@Shaggy Huh? Why? – Erik the Outgolfer – 2017-08-23T11:32:30.007

@EriktheOutgolfer (took me 2 hours to figure it out) because f(77) = 23 – Leaky Nun – 2017-08-23T13:55:25.127

5

JavaScript (ES6), 72 69 bytes

f=
n=>[...a=Array(n)].reduce(_=>a[++i]=i%7>7*/7/.test(i)?i:a[++j],i=j=0)
<input type=number min=1 oninput=o.textContent=f(+this.value)><pre id=o>

Edit: Saved 3 bytes thanks to @Shaggy.

Neil

Posted 2017-08-23T09:04:31.157

Reputation: 95 035

69 bytes: n=>[...a=Array(n)].reduce(_=>a[++i]=i%7>7*/7/.test(i)?i:a[++j],i=j=0) – Shaggy – 2017-08-23T10:33:38.937

@Shaggy I can't believe I forgot to use reduce... hangs head in shame – Neil – 2017-08-23T11:27:35.173

3

JavaScript, 79 75 bytes

2 bytes saved thanks to Shaggy

f=a=>(z=a=>a%7<1|/7/.test(a))(a)?f([...Array(a)].reduce(a=>a+z(b++),b=0)):a

Try it online!

user72349

Posted 2017-08-23T09:04:31.157

Reputation:

Just finished golfing mine down ... and then spotted you beat me to the identical solution. :\ – Shaggy – 2017-08-23T09:55:49.983

75 bytes: f=a=>(z=a=>a%7<1|/7/.test(a))(a)?f([...Array(a)].reduce(a=>a+z(b++),b=0)):a – Shaggy – 2017-08-23T10:00:13.927

@Shaggy. I actually had tried using reduce, but before I rearranged variables, so it had turned out that it was longer. I forgot to recheck it again. Thanks. – None – 2017-08-23T10:05:08.503

2

Röda, 65 bytes

f a{f#[seq(1,a)|[1]if g _]if g a else[a]}g a{[a%7<1 or"7"in`$a`]}

Try it online!

A port of Leaky Nun's Python answer.

fergusq

Posted 2017-08-23T09:04:31.157

Reputation: 4 867

2

05AB1E, 26 23 bytes

LÐ7Ösε7å}~_*[¤0Ê#D_O£]¤

Try it online!

Explanation

L                         # push range [1 ... n]
 Ð                        # triplicate
  7Ö                      # check if number in one copy for equality to 0 after mod by 7
    sε7å}                 # check each number in one copy if they contain 7
         ~_               # OR these 2 lists and invert
           *              # multiply with the range, 
                          # giving a list with 0s where the numbers need to be replaced
            [¤0Ê#    ]    # loop until the last number in the list is not 0
                 D        # duplicate the list
                  _       # invert it, 
                          # giving a list with 1s for the numbers that need to be replaced
                   O      # sum
                    £     # take these many elements from the list
                      ¤   # RESULT: push the last element of the list

Previous 26 byte solutions

>GNN7ÖN7å~Dˆ[_#¯s£OÐ7Ös7å~ 
>G1UN[Ð7Ös7å~XiDˆ}_#¯s£O0U

Emigna

Posted 2017-08-23T09:04:31.157

Reputation: 50 798

2

C (gcc), 104 98 95 bytes

-6 bytes by getting rid of sprintf+index and looking manually for a 7 in an integer's digits
-3 bytes using the deprecated POSIX bzero instead of memset

A function writing the result in the global variable r. Usage: l(<int>)

Result is 1-indexed.

r,o[9];b(i,s){for(r=s=++o[i];s&&s%10^7;s/=10);r%7&&!s?:b(i+1);}l(f){for(bzero(o,36);f--;b(0));}

Try it online!

Explanation:

/*
  r = value of the nth element
  o = array of counters (o[0] == main counter)
 */
r,o[9];

// Recursive function, "i" is the counter index 
// "s" is used to determine if an int contain a 7 digit
b(i,s){
  /*
    1. Increases the value of the counter
    2. Stores the result into r and s
    3. Divide s by 10 until it is equal to 0 or its remainder is 7
   */ 
  for(r=s=++o[i];s&&s%10^7;s/=10);

  /*
    if:
      r%7 (r modulo 7) AND it contains no 7 digit
    then:
      nothing
    else:
      calls b with the next counter index
   */
  r%7&&!s?:b(i+1);
}

// Main function: initializes counters and plays
// the sequence until the nth member is calculated
l(f){
  for(bzero(o,36);f--;b(0));
}

scottinet

Posted 2017-08-23T09:04:31.157

Reputation: 981

Finally, this is not the longest solution anymore. Sorry, Java. – scottinet – 2017-08-24T07:40:17.910

2

Mathematica, 57 bytes

Last[i=1;If[DigitCount[#,10,7]>0||7∣#,i++,#]&~Array~#]&

JungHwan Min

Posted 2017-08-23T09:04:31.157

Reputation: 13 290

2

Pyth, 36 bytes

L?!hbbhx.f|/`Z`7!%Z7b)b;WnyyQyQ=yQ;Q

Fixed completely, but is now an unholy mess of letters and can certainly be golfed quite a bit.

1-indexed

Dave

Posted 2017-08-23T09:04:31.157

Reputation: 432

Fixed, I put the h in front of the Q instead of G /)_- – Dave – 2017-08-23T14:18:46.743

It should work now... – Dave – 2017-08-23T14:53:13.250

I missed copy-pasting the leading L to define the lambda – Dave – 2017-08-23T15:06:57.993

Nice work! Looks good now! – Emigna – 2017-08-23T15:30:11.780

Thanks! Still needs some work though... – Dave – 2017-08-23T15:31:30.713

1

J, 52 bytes

i=:('7'&e.@":+.0=7&|)"0
f=:]`(#@}.@I.@:i@i.@>:)@.i^:_

Result is 1-indexed. Using it is pretty straightforward:

f 7777

Try it online!

Gregory Higley

Posted 2017-08-23T09:04:31.157

Reputation: 395

1

Perl 5, 52 + 1 (-p) = 53 bytes

map{$s=0;do{$\=++$c[$s++]}until$\!~/7/&&$\%7}1..$_}{

Try it online!

How?

@c is an array of counters. $c[0] holds the main counter that determines which element we're working on. Each successive element holds another counter that is only accessed when the previous one contains a 7 or is divisible by 7.

map              # Loop to find the appropriate element
  $s=0;          # reset index of counters
  do{            # looping through the counters
    $\=++c[$s++] # increment the counter and the index; $\ is our output variable
  }until         # don't quit until
       $\!~/7/   # the result has no 7s
       &&$\%7    # and is indivisble by 7
}1..$_           # do this until the input is reached
}{  # close the implicit loop created by the -p flag and force output of $\

# Perl 5, 64 + 1 (-p) = 65 bytes

while($c[0]<$_){$s=0;do{$\=++$c[$s++]}while($\=~/7/||$\%7==0)}}{

Try it online!

Xcali

Posted 2017-08-23T09:04:31.157

Reputation: 7 671