14
\$\begingroup\$

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]
[7]
[]
[]
[14]
\$\endgroup\$
3
  • \$\begingroup\$ 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. \$\endgroup\$
    – msh210
    Commented May 22, 2016 at 6:50
  • \$\begingroup\$ Can we display the result as a matrix and pad with zeroes? \$\endgroup\$
    – Dennis
    Commented May 22, 2016 at 7:16
  • \$\begingroup\$ @Dennis Empty arrays should be kept. The result may be a zero-padded matrix. \$\endgroup\$
    – Sherlock9
    Commented May 23, 2016 at 4:41

11 Answers 11

3
\$\begingroup\$

Haskell, 151 bytes

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]
\$\endgroup\$
1
  • 2
    \$\begingroup\$ 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[]? \$\endgroup\$ Commented May 22, 2016 at 1:09
2
\$\begingroup\$

Pyth, 38 bytes

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

Try it online. Test suite.

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.

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

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)

enter image description here

\$\endgroup\$
1
  • \$\begingroup\$ Ooh, this is clever and pretty. +1 :D \$\endgroup\$
    – Sherlock9
    Commented May 29, 2016 at 11:12
1
\$\begingroup\$

Python 2, 103 102 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'in`N`);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']
\$\endgroup\$
1
\$\begingroup\$

Python 2, 91 90 87 bytes

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

Prints a list of tuples. Test it on Ideone.

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

Dyalog APL, 50 47 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.

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

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.

\$\endgroup\$
1
+500
\$\begingroup\$

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!).

\$\endgroup\$
4
  • \$\begingroup\$ "Do I get a cookie?" Yes, you do. \$\endgroup\$
    – Leaky Nun
    Commented May 27, 2016 at 14:45
  • \$\begingroup\$ Wow, that was unexpected! Ty, @LeakyNun :D \$\endgroup\$
    – fede s.
    Commented May 27, 2016 at 17:41
  • \$\begingroup\$ Wow, I love this! Curse you for using numbers as identifiers! \$\endgroup\$
    – cat
    Commented Jun 22, 2016 at 12:12
  • 1
    \$\begingroup\$ @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! \$\endgroup\$
    – fede s.
    Commented Jun 23, 2016 at 18:41
1
\$\begingroup\$

Jelly, 27 25 bytes

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

Try it online! or verify all test cases.

\$\endgroup\$
6
  • \$\begingroup\$ why is this not-competing \$\endgroup\$
    – Bálint
    Commented May 22, 2016 at 6:42
  • \$\begingroup\$ Because the challenge is from December 2015 and predates the creation of Jelly. \$\endgroup\$
    – Dennis
    Commented May 22, 2016 at 6:43
  • \$\begingroup\$ Oh, thanks for clarification! \$\endgroup\$
    – Bálint
    Commented May 22, 2016 at 7:40
  • \$\begingroup\$ Is that an official rule? I never check the question date against programming language invention date. \$\endgroup\$ Commented May 22, 2016 at 18:19
  • \$\begingroup\$ @ThomasWell Can I ever answer with a language invented after the challenge was posted? \$\endgroup\$
    – Dennis
    Commented May 22, 2016 at 18:55
0
\$\begingroup\$

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))

\$\endgroup\$
0
\$\begingroup\$

J, 63 60 59 58 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
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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