# The game of Sevens! Who said what?

The game of Sevens is played as follows: n players sit in a circle, and start counting up from 1, passing to the left (or from player A to player B).

When a number p that has a 7 in it OR is divisible by 7 is reached, then the player who spoke the number p-1, after the next player says p, must say p+1 and the order of people speaking reverses. For example, if player B speaks 6, player C says 7, B says 8, and player A says 9.

Note: For those who want to play in real life, if a person forgets a number (or in the version where sevens are not said, accidentally says a seven), they are eliminated from the circle, but we will omit this detail from this challenge.

The challenge itself is to print which numbers each player should say in a perfect game of Sevens up to an input m for an input n players.

As an example, where five people, A, B, C, D, and E, are to play till they reach 30. They play in this manner

A: 1 6 8 13    15 19       23    30
B: 2 7*  12    16 18       24
C: 3     11    17*         25
D: 4     10          21*   26 28*
E: 5      9 14*      20 22 27*29


where sevens are marked with *. Note that at 27 and 28, we're reversing twice, and play continues "as normal" from D to E.

Please note that the output does not have to be in the above format. I simply printed it that way for some clarity.

Rules

• The input is two integers in any order, m representing the last number to say, n representing the number of players.

• The output can be several arrays or several strings, one for each player. If you use strings, you do not have to use separators (though, if you could add some in your code tests, we would appreciate the readability). If you can actually print them in a circle somehow, that is acceptable as well, and it would be pretty cool too.

• The output does not have to designate which players are which (it's fairly obvious that the first player is the one who says 1), though if the output isn't sorted for whatever reason, you should make clear which player is speaking which set of numbers. Omitting players who do not say anything is also allowed if you make it clear which players are speaking. I will add some more examples of possible outputs below.

• This is code golf, so the smallest number of bytes wins.

As always, if the problem is unclear, please let me know. Good luck and good golfing!

Examples

>>> sevens_string(30, 5, " ")
'1 6 8 13 15 19 23 30'
'2 7 12 16 18 24'
'3 11 17 25'
'4 10 21 26 28'
'5 9 14 20 22 27 29'
>>> sevens_string(42, 5)
'16813151923303539'
'27121618243140'
'31117253241'
'410212628333742'
'591420222729343638'
>>> sevens_array(20, 3)
[1, 4, 7, 10, 13, 15, 19]
[2, 5, 9, 12, 16, 18]
[3, 6, 8, 11, 14, 17, 20]
>>> sevens_array(18, 10)
[1, 13, 15]
[2, 12, 16, 18]
[3, 11, 17]
[4, 10]
[5, 9]
[6, 8]

[]
[]


• I think a more useful output for purposes of visualizing the game play would be a list of players in order of play. (E.g. with 4 players and a max of 15, that'd be 1 2 3 4 1 2 3 2 1 4 3 2 1 4 1.) I'm not saying that's better or worse in terms of he challenge: just that it'd be more useful in the real world. May 22 '16 at 6:50
• Can we display the result as a matrix and pad with zeroes? May 22 '16 at 7:16
• @Dennis Empty arrays should be kept. The result may be a zero-padded matrix. May 23 '16 at 4:41

# Pyth, 38 bytes

Jm[)EA,01VQa@JZ=hG=+Z=W|}\7G!%G7H_H;J


Basically a port of my Python answer; there's probably a better way. Takes as input the number to count up to n and the number of players p on separate lines, outputs the result as a two-dimensional array.

s n|elem '7'(show n)||mod n 7==0=(0-)|0<1=id
a=scanl1(+)$map($1)$scanl(.)id$map s[1..]
f m n=mapM_ print[[x+1|x<-[0..m-1],mod(a!!x-1)n==i]|i<-[0..n-1]]

*Main> f 30 5
[1,6,8,13,15,19,23,30]
[2,7,12,16,18,24]
[3,11,17,25]
[4,10,21,26,28]
[5,9,14,20,22,27,29]

• How about mod n 7<1 instead of mod n 7==0 and s<\$>[1..] instead of map s[1..]? Also, why not print[] instead of mapM_ print[]? May 22 '16 at 1:09

# Python 3, 155 bytes

from turtle import*
def f(m,n,i=0,r=20,d=360):
k=n
while i<m:i+=1;fd(r);write(i);bk(r);e='7'[:i%7]in str(i);d*=1-2*e;k=~-e*(1-k)%n;r+=(k<1)*15;rt(d/n)


Uses turtle graphics to print in a circle such that numbers spoken by the same player are on the same radius. The radius of the circle is increased when the direction is reversed, or when the sequence wraps around the circle, so previous numbers aren't overwritten.

Sample output for f(22,6) • Ooh, this is clever and pretty. +1 :D May 29 '16 at 11:12

# Python 2, 103102 101 bytes

def S(n,p):
P=0;D=N=1;O=['']*p
while n:O[P%p]+=N;D*=1-2*(N%7<1or'7'inN);N+=1;P+=D;n-=1
print O


Defines a function S(n,p) that takes the number to count to n and the number of players p and prints the result as an array of strings.

>>> S(42,5)
['16813151923303539', '27121618243140', '31117253241', '410212628333742','591420222729343638']


# Python 2, 9190 87 bytes

def f(m,n):a=d=i=0;r=[()]*n;exec"i+=1;r[a%n]+=i,;d^='7'[:i%7]ini;a+=1-2*d;"*m;print r


Prints a list of tuples. Test it on Ideone.

# Jelly, 27 25 bytes (non-competing)

D;Æf7e
R’Ç€^\ḤC+\_'R}⁹ḍT€

• why is this not-competing May 22 '16 at 6:42
• Because the challenge is from December 2015 and predates the creation of Jelly. May 22 '16 at 6:43
• Oh, thanks for clarification! May 22 '16 at 7:40
• Is that an official rule? I never check the question date against programming language invention date. May 22 '16 at 18:19
• May 22 '16 at 18:55

# Dyalog APL, 5047 35 bytes

{,⌸⍵|+\0,¯1*+\{0=7|⍵×~7∊⍎¨⍕⍵}¨⍳⍺-1}


This displays the numbers each player said as a table, where the first column enumerates the players. Rows are padded with 0s to the same length, and rows without numbers are omitted.

### Verification

      f ← {,⌸⍵|+\0,¯1*+\{0=7|⍵×~7∊⍎¨⍕⍵}¨⍳⍺-1}
30 f 5
0 1  6  8 13 15 19 23 30
1 2  7 12 16 18 24  0  0
2 3 11 17 25  0  0  0  0
3 4 10 21 26 28  0  0  0
4 5  9 14 20 22 27 29  0
42 f 5
0 1  6  8 13 15 19 23 30 35 39
1 2  7 12 16 18 24 31 40  0  0
2 3 11 17 25 32 41  0  0  0  0
3 4 10 21 26 28 33 37 42  0  0
4 5  9 14 20 22 27 29 34 36 38
20 f 3
0 1 4 7 10 13 15 19
1 2 5 9 12 16 18  0
2 3 6 8 11 14 17 20
14 f 10
0  1 13
1  2 12
2  3 11
3  4 10
4  5  9
5  6  8
6  7  0
9 14  0


Note that, in the last example, 7 and 8 are omitted since those players haven't said anything yet.

## Ruby, 81

->n,m{g=[""]*n
k=j=0
i=1
m.times{g[j%n]+=w="#{k+=1}"
j+=i=k%7<1||w[/7/]?-i :i}
g}


Pretty straightforward implementation. Returns an ugly glommed string (you can add a space to make it "#{k+=1} " for... well, a spaced string). I wonder if there's a more mathematical algorithm out there.

# Factor 172

I managed to do it longer than Haskell, and as readable as APL! Do I get a cookie?

[| l! n! | 1 0 0 :> ( p! x! z! ) n iota [ 1vector ] map <circular> n! l iota [ 1 + z! z 7 mod 0 = 55 z 10 >base in? or -1 and 1 or p * p! z x n nth push x p + x! ] each n ]


It's a quotation (anonymous function) that outputs a circular sequence of vectors. Each vector starts with the number of player, and then the numbers that correspond to that player.

30 5 [| l! n! | 1 0 0 :> ( p! x! z! ) n iota [ 1vector ] map <circular> n! l iota [ 1 + z! z 7 mod 0 = 55 z 10 >base in? or -1 and 1 or p * p! z x n nth push x p + x! ] each n ] call

Outputs:
T{ circular
{ seq
{
V{ 0 1 6 8 13 15 19 23 30 }
V{ 1 2 7 12 16 18 24 }
V{ 2 3 11 17 25 }
V{ 3 4 10 21 26 28 }
V{ 4 5 9 14 20 22 27 29 }
}      ^ Note: first val is player number starting at 0
}
}


I started with this:

: game-of-7 ( last-num num-players -- {players:={numbers}} )
1 1 set ! increment
0 2 set ! current-index
iota [ drop V{ } clone ] map <circular>
swap iota
[ 1 + ! iotas go 0 to n-1
dup [ 7 mod 0 = ] [ 10 >base 55 swap in? ] bi or
[ 1 get -1 * 1 set ] when
over 2 get swap nth push
2 get 1 get + 2 set
] each ;


which is not good factor code, but a lot more clear (yes, I'm using numbers as variable names there, don't look at me like that!).

• "Do I get a cookie?" Yes, you do. May 27 '16 at 14:45
• Wow, that was unexpected! Ty, @LeakyNun :D May 27 '16 at 17:41
• Wow, I love this! Curse you for using numbers as identifiers!
– cat
Jun 22 '16 at 12:12
• @cat i actually like it in a perverse way :P But locals solve the length issue of SYMBOL: a lot better: one letter names, and getting rid of set and get! Jun 23 '16 at 18:41

# JavaScript (ES6) 100

Returning result as a string array, no separators

(m,n)=>(d=>{for(r=[],p=i=0;i++<m;d=i%7&&!~(i+'').search(7)?d:n-d,p=(p+d)%n)r[p]=(r[p]||'')+i})(1)||r


Or more readable, for 3 bytes more, returning result as an array of arrays

(m,n)=>(d=>{for(r=[],p=i=0;i++<m;d=i%7&&!~(i+'').search(7)?d:n-d,p=(p+d)%n)r[p]=[...r[p]||[],i]})(1)||r


Test Using the new wonderful console feature of the Stack Snippets

S=(m,n)=>(d=>{for(r=[],p=i=0;i++<m;d=i%7&&!~(i+'').search(7)?d:n-d,p=(p+d)%n)r[p]=(r[p]||'')+i})(1)||r

A=(m,n)=>(d=>{for(r=[],p=i=0;i++<m;d=i%7&&!~(i+'').search(7)?d:n-d,p=(p+d)%n)r[p]=[...r[p]||[],i]})(1)||r

console.log(S(42,5))
console.log(A(20,3))

# J, 63605958 56 bytes

4 :'>:@I.(i.y)=/y|+/\0,_1^+/\(7 e."1 q:,.10#.inv])}.i.x'


### Verification

   f =: 4 :'>:@I.(i.y)=/y|+/\0,_1^+/\(7 e."1 q:,.10#.inv])}.i.x'
30 f 5
1  6  8 13 15 19 23 30
2  7 12 16 18 24  0  0
3 11 17 25  0  0  0  0
4 10 21 26 28  0  0  0
5  9 14 20 22 27 29  0
42 f 5
1  6  8 13 15 19 23 30 35 39
2  7 12 16 18 24 31 40  0  0
3 11 17 25 32 41  0  0  0  0
4 10 21 26 28 33 37 42  0  0
5  9 14 20 22 27 29 34 36 38
20 f 3
1 4 7 10 13 15 19
2 5 9 12 16 18  0
3 6 8 11 14 17 20
14 f 10
1 13
2 12
3 11
4 10
5  9
6  8
7  0
0  0
0  0
14  0
`