When I was a child I used to play a variation ofSnap to stake soccer trading cards.
"Game" is an overstatement because the only role of the players is to secretly prepare their starting piles. As the game starts there are no choices other than just perform the game algorithm.
Rules
There is no maximum number of players and they all start with a fixed number of cards.
Players in turn play the top card of their piles on a common pile (initially empty).
If the current player has no cards, the common pile bottom card will be played.
When a player happens to play an equal card to that on top of the common pile:
- This player will take the common pile and append it face-down to his own pile. (Players' piles are face-down but the common pile is face-up, so the pair of equal cards should end up at the bottom)
- Anyone with no cards is out of the game.
- This player has to resume the game replenish the common pile with their top card as usual.
The game ends in one of three scenarios:
- one player has all the cards (they win)
- all the cards are in the common pile, the next player rotates it but doesn't form a pair (the common pile can't be taken)
- one previous state of the game reoccurs (the game gets stuck in a loop)
Step by step game examples
1) Initial configuration: "abba abca" p1 p2 common pile 1 abba abca 2 bba abca a 3 bba bca aa 4 TAKES 5 bba bcaaa 6 bba caaa b 7 ba caaa bb 8 TAKES 9 babb caaa10 abb caaa b11 abb aaa bc12 bb aaa bca13 bb aa bcaa14 TAKES15 bb aabcaa16 bb abcaa a17 b abcaa ab18 b bcaa aba19 bcaa abab20 caa ababb21 OUT TAKES22 caaababb============ p2 wins ============2) Initial configuration: "abba acab" p1 p2 common pile 1 abba acab 2 bba acab a 3 bba cab aa 4 TAKES 5 bba cabaa 6 bba abaa c 7 ba abaa cb 8 ba baa cba 9 a baa cbab 10 a aa cbabb 11 TAKES 12 a aacbabb 13 a acbabb a 14 acbabb aa 15 TAKES 16 aa acbabb 17 a acbabb a 18 a cbabb aa 19 TAKES 20 a cbabbaa 21 a babbaa c 22 babbaa ca 23 abbaa cab 24 abbaa abc 25 bbaa abca 26 bbaa bcaa 27 TAKES 28 bcaa bbaa 29 caa bbaa b 30 caa baa bb 31 TAKES 32 caa baabb 33 caa aabb b 34 aa aabb bc 35 aa abb bca 36 a abb bcaa 37 TAKES 38 abcaa abb 39 bcaa abb a 40 bcaa bb aa 41 TAKES 42 bcaa bbaa 43 bcaa baa b 44 caa baa bb 45 TAKES 46 caabb baa 47 aabb baa c 48 aabb aa cb 49 abb aa cba 50 abb a cbaa 51 TAKES 52 abb acbaa 53 abb cbaa a 54 bb cbaa aa 55 TAKES 56 bbaa cbaa 57 baa cbaa b 58 baa baa bc 59 aa baa bcb 60 aa aa bcbb 61 TAKES 62 aa aabcbb 63 aa abcbb a 64 a abcbb aa 65 TAKES 66 aaa abcbb 67 aa abcbb a 68 aa bcbb aa 69 TAKES 70 aa bcbbaa 71 aa cbbaa b 72 a cbbaa ba 73 a bbaa bac 74 bbaa baca 75 baa bacab 76 baa acabb 77 TAKES 78 acabb baa 79 cabb baa a 80 cabb aa ab 81 abb aa abc 82 abb a abca 83 bb a abcaa 84 TAKES 85 bbabcaa a 86 babcaa a b 87 babcaa ba 88 abcaa bab 89 abcaa abb 90 TAKES 91 abcaa abb 92 abcaa bb a 93 bcaa bb aa 94 TAKES 95 bcaaaa bb 96 caaaa bb b 97 caaaa b bb 98 TAKES 99 caaaa bbb100 caaaa bb b101 aaaa bb bc102 aaaa b bcb103 aaa b bcba104 aaa bcbab105 aa bcbaba106 aa cbabab107 a cbababa108 a bababac109 bababaca110 ababacab // common pile can't be taken============ p1, p2 in game ============3) Initial configuration: "bdad acbc abba" p1 p2 p3 common pile 1 bdad acbc abba 2 dad acbc abba b 3 dad cbc abba ba 4 dad cbc bba baa 5 TAKES 6 dad cbc bbabaa 7 dad cbc babaa b 8 ad cbc babaa bd 9 ad bc babaa bdc10 ad bc abaa bdcb11 d bc abaa bdcba12 d c abaa bdcbab13 d c baa bdcbaba14 c baa bdcbabad15 baa bdcbabadc16 aa bdcbabadcb17 aa dcbabadcbb18 TAKES OUT19 dcbabadcbb aa20 cbabadcbb aa d21 cbabadcbb a da22 babadcbb a dac23 babadcbb daca24 abadcbb dacab25 abadcbb acabd26 badcbb acabda27 badcbb cabdaa28 TAKES29 badcbb cabdaa30 badcbb abdaa c31 adcbb abdaa cb32 adcbb bdaa cba33 dcbb bdaa cbaa34 TAKES35 dcbbcbaa bdaa36 cbbcbaa bdaa d37 cbbcbaa daa db38 bbcbaa daa dbc39 bbcbaa aa dbcd40 bcbaa aa dbcdb41 bcbaa a dbcdba42 cbaa a dbcdbab43 cbaa dbcdbaba44 baa dbcdbabac45 baa bcdbabacd46 aa bcdbabacdb47 aa cdbabacdbb48 TAKES49 aa cdbabacdbb50 aa dbabacdbb c51 a dbabacdbb ca52 a babacdbb cad53 babacdbb cada54 abacdbb cadab55 abacdbb adabc56 bacdbb adabca57 bacdbb dabcaa58 TAKES59 dabcaa bacdbb60 abcaa bacdbb d61 abcaa acdbb db62 bcaa acdbb dba63 bcaa cdbb dbaa64 TAKES65 bcaa cdbbdbaa66 bcaa dbbdbaa c67 caa dbbdbaa cb68 caa bbdbaa cbd69 aa bbdbaa cbdc70 aa bdbaa cbdcb71 a bdbaa cbdcba72 a dbaa cbdcbab73 dbaa cbdcbaba74 baa cbdcbabad75 baa bdcbabadc76 aa bdcbabadcb77 aa dcbabadcbb78 TAKES79 dcbabadcbb aa // loop (line 19)============ p1, p3 in game ============N.B. game states are inviduated by piles configuration and current player. As you can see in example2) lines 28, 42 are not the same game state.
Input
A list of players' piles (top to bottom) as:
- an array of strings
["code", "golf", "fold"], or - a matrix of positive integers
[[1,2,3,4],[5,2,6,7],[7,2,6,3]]
Players order is implied by piles order.
Output
A number indicating the player who wins or a list of numbers for the players who reach the end of the game.
You decide whether players are 0 or 1 indexed.
- This iscode-golf.
I/O Examples (1-indexed players):
"abca abba" -> 1"abba abca" -> 2"abba acab" -> 1 2"bdad acbc abba" -> 1 3"fizz buzz" -> 2"robinhooda ndlittlejo hnwalkingt hroughthef orestlaugh ingbackand forthatwha ttheothero nehastosay" -> 9- 2\$\begingroup\$"If the current player has no cards they will rotate the common pile placing on top the card at the bottom." was not entirely clear to me until working through the second and third example games, perhaps a better wording would be "If the current player has no cards they will play the card from the bottom of the common pile"?\$\endgroup\$Jonathan Allan– Jonathan Allan2021-09-05 13:22:25 +00:00CommentedSep 5, 2021 at 13:22
- 4\$\begingroup\$Although I have already completed the challenge, I faced some difficulties and misunderstandings along the way. To make the challenge clearer for future viewers, maybe change wordings to be more precise? For instance it was not entirely clear that the player who takes the pile gets another turn. Perhapsanyone with no cards is out of the game. The player who took the pile has to then replenish the pile with one card is better because I was not sure who "they" was.\$\endgroup\$ophact– ophact2021-09-05 13:30:24 +00:00CommentedSep 5, 2021 at 13:30
- 1\$\begingroup\$@Domenico the edit is for inclusion, it's true that in my generation girls would have been de facto excluded from soccer card games or would have to argue to be let in (or because they weren't interested), but the world is a-changing!\$\endgroup\$Kaddath– Kaddath2021-09-06 08:04:11 +00:00CommentedSep 6, 2021 at 8:04
- 1\$\begingroup\$@Kaddath Oh, I didn't realize it. I'm Italian and we always use implied subject, so I perceived those "he" as required transparent links to "the player", avoid of gender meanings. Also didn't know of singular they. Anyway just blindly change all the "he" into "they" can upset the sense, as it did. I'll rephrase the whole thing.\$\endgroup\$Domenico– Domenico2021-09-06 12:29:21 +00:00CommentedSep 6, 2021 at 12:29
- 1\$\begingroup\$@Domenico Yes I didn't understand too the first time i read it in a question, I'm french and it would be weird for us to use plural for this\$\endgroup\$Kaddath– Kaddath2021-09-06 12:51:32 +00:00CommentedSep 6, 2021 at 12:51
3 Answers3
JavaScript (Node.js),483 426 bytes
-57 bytes thanks to @emanresu A
Takes a list of strings as input and indexes from 0.
a=>{a=a.map(p=>[...p]);e=[];t=[];o=[];i=0;g=a.length;m=n=>(n%g+g)%g;r=_=>[...a.keys()].filter(x=>!d(x));d=x=>o.includes(x);q=_=>JSON.stringify([o,i,a,e]);for(;;){if(!d(i)&&(l=e.length==e.unshift(a[i].shift(t.push(q()))||e.pop())&&!a.filter(p=>p[0])[0],(e[0]==e[1]&&e[1]&&(i=m(i-1,a[i].push(...e.reverse())),e=[],o.push(...a.flatMap((p,j)=>p[0]||d(j)?e:j))+1==g)||l)))return l?r():r()[0];if(t.includes(q(i=m(i+1))))return r()}}Unminified
(a) => { a = a.map((p) => [...p]); e = []; t = []; o = []; i = 0; g = a.length; m = (n) => ((n % g) + g) % g; r = (_) => [...a.keys()].filter((x) => !d(x)); d = (x) => o.includes(x); q = (_) => JSON.stringify([o, i, a, e]); for (;;) { if ( !d(i) && ((l = e.length == e.unshift(a[i].shift(t.push(q())) || e.pop()) && !a.filter((p) => p[0])[0]), (e[0] == e[1] && e[1] && ((i = m(i - 1, a[i].push(...e.reverse()))), (e = []), o.push(...a.flatMap((p, j) => (p[0] || d(j) ? e : j))) + 1 == g)) || l) ) return l ? r() : r()[0]; if (t.includes(q((i = m(i + 1))))) return r(); }};- 2\$\begingroup\$Golfed some bytes off for you\$\endgroup\$emanresu A– emanresu A2021-09-05 01:09:32 +00:00CommentedSep 5, 2021 at 1:09
Python 3.8 (pre-release), 378 bytes
def f(s,p='',G=[],V=sorted,E=enumerate): O=V(p.join(s)) while 1: for i,S in E(s): if S:p+=S[0];s[i]=S[1:] elif""==S:p=p[1:]+p[0] if s[i]!=0<1<len(p)!=p[-2]==p[-1]:s[i]+=p;s=[P or 0for P in s];p=s[i][0];s[i]=s[i][1:] C=s+[p,i] if any(a and O==V(a)for a in s)or(O==V(p)*all(a!=b for a,b in zip(p,p[1:]+p[0])))or C in G:return[i for i,S in E(s)if S!=0] G+=[C]Wow, was this a pain to write.
Takes in a list of strings, outputs a list of 0-indexed numbers. My code can be slightly changed to output a single value if a single player wins, but I see no rule preventing me from outputting as my code does.
Explanation
Stores game states inG. Astate here is the list of strings followed by the pile and the number indicating whose turn it is (evidently, whose turn it is does make a difference). If the current state has been seen before, we break by setting T to 1. (breaks from the inner loop then from the outer loop)
For each iteration, if S is truthy (current string) we append its first letter to the pile and remove it froms[i]. IfS is empty string, we rotate the pile.
A zero indicates that the player is out; we ignore such cases. If the last two characters ofp are the same, we append the entire pile to the end ofs[i] and reset it, before resuming the game in the same iteration.
The two other checks for the endgame are:
- if any of the sorted strings in
smatch the sortedO, or - if the sorted pile equals sorted
Oand there are no neighboring pairs in the pile (end and beginning count as a pair).
To get the list of "in" players, we simply output all indices corresponding to a nonzero entry ins.
Any tips for shortening the code will be greatly appreciated. Thanks to @ovs for-28 -35 bytes!
- \$\begingroup\$If you move the return statement where
T=1;breakcurrently is, you don't need any breaks orT, which saves a few bytes. Andchained comparisons can probably save a few bytes as well\$\endgroup\$ovs– ovs2021-09-05 12:40:59 +00:00CommentedSep 5, 2021 at 12:40 - \$\begingroup\$@ovs thanks for the first tip! Not sure where I could use the chained comparisons though.\$\endgroup\$ophact– ophact2021-09-05 13:05:06 +00:00CommentedSep 5, 2021 at 13:05
- \$\begingroup\$
s[i]!=0and len(p)>1and p[-2]==p[-1]->s[i]!=0<1<len(p)!=p[-2]==p[-1]. And in the lastifyou might be able to replaceO==sorted(p)and all(...)with(O==sorted(p)*all(...).\$\endgroup\$ovs– ovs2021-09-05 13:10:18 +00:00CommentedSep 5, 2021 at 13:10 - \$\begingroup\$I'm glad you liked it, is this one of your first challenges? Anyway, yes, a state of the game includes the current player, as you can se in the example 2) lines 28, 42 have the same piles configuration but the game doesn't end up in a loop. Unfortunately in that example the outcome is the same as would be in a simulation that wrongly detects a loop. If you want you can help me find a test case that differentiates it\$\endgroup\$Domenico– Domenico2021-09-05 15:58:07 +00:00CommentedSep 5, 2021 at 15:58
- \$\begingroup\$@Domenico You can just write a comment next to it saying "was seen before, but different player's turn" or something similar.\$\endgroup\$ophact– ophact2021-09-05 16:04:21 +00:00CommentedSep 5, 2021 at 16:04
Perl 5, 209 bytes
sub{(@p,$i,$_,%s,@o)=pop=~/\w+/g;while((@w=grep$p[$_-1],1..@p)>1||y///c and!$s{$i,@p,@o}++){if(!$o[$i]&&($p[$i]=~s,.,,||s,.,,)&&($_.=$&)=~s/.*(.)\1$//){$p[$i].=$&;$p[$_]or$o[$_]=1for 0..$#p;next}$i=++$i%@p}@w}Explore related questions
See similar questions with these tags.

