16
\$\begingroup\$

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!

\$\endgroup\$
  • 1
    \$\begingroup\$ Hmm, is test case 278 correct? I get the correct result for each of them, but 278 becomes 86 instead of 5. :S \$\endgroup\$ – Kevin Cruijssen Aug 23 '17 at 9:17
  • 1
    \$\begingroup\$ @KevinCruijssen You're right, 278 is supposed to be 86. 279 becomes 5. Fixed! \$\endgroup\$ – Arfie Aug 23 '17 at 9:19
  • 2
    \$\begingroup\$ Related but quite different. \$\endgroup\$ – Arnauld Aug 23 '17 at 9:37
  • 3
    \$\begingroup\$ @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. \$\endgroup\$ – Erik the Outgolfer Aug 23 '17 at 11:56
  • 5
    \$\begingroup\$ I 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. \$\endgroup\$ – mbomb007 Aug 23 '17 at 13:33

11 Answers 11

7
\$\begingroup\$

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
\$\endgroup\$
6
\$\begingroup\$

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!

\$\endgroup\$
  • 3
    \$\begingroup\$ Does this not work in Python 2? Then you could do '7'in`a` instead of '7'in str(a) \$\endgroup\$ – Arfie Aug 23 '17 at 9:23
  • 4
    \$\begingroup\$ @Ruud Leaky doesn't like Python 2. \$\endgroup\$ – Mr. Xcoder Aug 23 '17 at 9:49
  • 4
    \$\begingroup\$ Shouldn't this be 23 bytes?! \$\endgroup\$ – Shaggy Aug 23 '17 at 11:16
  • 2
    \$\begingroup\$ @Shaggy Huh? Why? \$\endgroup\$ – Erik the Outgolfer Aug 23 '17 at 11:32
  • \$\begingroup\$ @EriktheOutgolfer (took me 2 hours to figure it out) because f(77) = 23 \$\endgroup\$ – Leaky Nun Aug 23 '17 at 13:55
5
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ 69 bytes: n=>[...a=Array(n)].reduce(_=>a[++i]=i%7>7*/7/.test(i)?i:a[++j],i=j=0) \$\endgroup\$ – Shaggy Aug 23 '17 at 10:33
  • \$\begingroup\$ @Shaggy I can't believe I forgot to use reduce... hangs head in shame \$\endgroup\$ – Neil Aug 23 '17 at 11:27
3
\$\begingroup\$

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!

\$\endgroup\$
  • \$\begingroup\$ Just finished golfing mine down ... and then spotted you beat me to the identical solution. :\ \$\endgroup\$ – Shaggy Aug 23 '17 at 9:55
  • \$\begingroup\$ 75 bytes: f=a=>(z=a=>a%7<1|/7/.test(a))(a)?f([...Array(a)].reduce(a=>a+z(b++),b=0)):a \$\endgroup\$ – Shaggy Aug 23 '17 at 10:00
  • \$\begingroup\$ @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. \$\endgroup\$ – user72349 Aug 23 '17 at 10:05
2
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

Mathematica, 57 bytes

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

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
\$\endgroup\$
2
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ Fixed, I put the h in front of the Q instead of G /)_- \$\endgroup\$ – Dave Aug 23 '17 at 14:18
  • \$\begingroup\$ It should work now... \$\endgroup\$ – Dave Aug 23 '17 at 14:53
  • \$\begingroup\$ I missed copy-pasting the leading L to define the lambda \$\endgroup\$ – Dave Aug 23 '17 at 15:06
  • \$\begingroup\$ Nice work! Looks good now! \$\endgroup\$ – Emigna Aug 23 '17 at 15:30
  • \$\begingroup\$ Thanks! Still needs some work though... \$\endgroup\$ – Dave Aug 23 '17 at 15:31
2
\$\begingroup\$

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));
}
\$\endgroup\$
  • \$\begingroup\$ Finally, this is not the longest solution anymore. Sorry, Java. \$\endgroup\$ – scottinet Aug 24 '17 at 7:40
1
\$\begingroup\$

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!

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

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!

\$\endgroup\$

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