11
\$\begingroup\$

Revised formatting and instructions

Given a list of moves for a Cracker Barrel peg board game, or as @Steveverrill stated, Peg Triangle Solitaire:

Game 1        Game 2         Game 3
1:  0 ,-1, -1   C, -1, -1     4, -1, -1  #starting point
2:  3, 1, 0     3, 7, C       B, 7, 4    #jump_from, jump_over, jump_to
3:  A, 6, 3     0, 1, 3       D, C, B
4:  8, 4, 1     6, 3, 1       5, 8, C
5:  B, 7, 4     5, 2, 0       1, 4, 8
6:  2, 4, 7     C, 8, 5       E, 9, 5
7:  D, C, B     A, B, C       6, 3, 1
8:  9, 5, 2     D, C, B       2, 5, 9
9:  1, 3, 6     9, 5, 2       B, C, D
10: 0, 2, 5     1, 4, 8       9, 8, 7
11: 6, 7, 8     0, 2, 5       0, 1, 3
12: 5, 8, C     5, 8, C       3, 7, C
13: B, C, D     B, C, D       D, C, B
14: E, D, C     E, D, C       A, B, C

Here is your task

  • Write a program that takes a list of moves, each move has three arguments which are slots on the board (jump_from, jump_over, jump_to). Move the peg from jump_from to jump_to and remove jump_over. (If that is unclear then read the instructions linked at the top)
  • Print the board for each move
    • The direction of the move a.k.a. the arrow
    • The slot jumped from a.k.a. the *
    • The slot jumped to (if peg 3 was in slot 3, and jumped to slot 0, then print a 3 in slot 0)
    • print a . for any empty slots

How to play

-If you don't understand these rules then there is a link at the top.

I've provided three different games that result in one peg remaining. The idea of the game is to start with one peg missing in the board and remove pegs until there is one left. A move is jumping over a peg into an empty slot and removing the peg you jumped over. Valid moves are diagonals and horizontal moves only. Example (assume slots 1, 2, 3, and 6 are open):

8 over 4 to 1 is valid

8 over 7 to 6 is valid

8 over 7 or 4 to 3 is invalid

B over 7 and 4 is invalid

Your output should look like the following. Each board printed is one move

(Use hex instead of decimal since printing the board in decimal causes the last row to be too wide)

This is Game 1 from the move set at the top

       / 0 \        #This is the board with all slots filled
      / 1 2 \       
     / 3 4 5 \      
    / 6 7 8 9 \     
   / A B C D E \ 

       / * \        #Move 1: remove the first peg which is 0
      / 1 2 \       
     / 3 4 5 \      
    / 6 7 8 9 \     
   / A B C D E \    

       / 3 \        #Move 2: Move peg 3 from slot 3 over slot 1 to slot 0
      / ↗ 2 \       Remove peg 1 from slot 1
     / * 4 5 \      
    / 6 7 8 9 \     
   / A B C D E \    

       / 3 \        #Move 3
      / . 2 \       
     / A 4 5 \      
    / ↗ 7 8 9 \     
   / * B C D E \    

       / 3 \        #Move 4
      / 8 2 \       
     / A ↖ 5 \      
    / . 7 * 9 \     
   / . B C D E \    

       / 3 \        #Move 5
      / 8 2 \       
     / A B 5 \      
    / . ↗ . 9 \     
   / . * C D E \    

       / 3 \        #Move 6
      / 8 * \       
     / A ↙ 5 \      
    / . 2 . 9 \     
   / . . C D E \    

       / 3 \       #Move 7
      / 8 . \       
     / A . 5 \      
    / . 2 . 9 \     
   / . D ← * E \    

       / 3 \        #Move 8
      / 8 9 \       
     / A . ↖ \      
    / . 2 . * \     
   / . D . . E \    

       / 3 \        #Move 9:
      / * 9 \       Move peg 8 from slot 1 over slot 3 to slot 6
     / ↙ . . \      Remove peg A
    / 8 2 . . \     
   / . D . . E \    

       / * \        #Move 10
      / . ↘ \       
     / . . 3 \      
    / 8 2 . . \     
   / . D . . E \    

       / . \        #Move 11
      / . . \       
     / . . 3 \      
    / * → 8 . \     
   / . D . . E \    

       / . \        #Move 12
      / . . \       
     / . . * \      
    / . . ↙ . \     
   / . D 3 . E \    

       / . \        #Move 13
      / . . \       
     / . . . \      
    / . . . . \     
   / . * → D E \    

       / . \        #Move 14
      / . . \       
     / . . . \      
    / . . . . \     
   / . . E ← * \   

The * represents the most recent peg removed. That is why the board starts with a * at slot 0 instead of a 0. . represents an empty slot. The slots stay in the same position but the pegs are numbered and move around so for the very last move peg E moves from slot E over peg/slot D to slot C

The direction of the move is the unicode characters u2190 through u2199

This is code golf so lowest number of bytes wins. Good Luck!

If something is unclear don't hesitate to ask. I will do my best to clarify.

\$\endgroup\$
11
  • 3
    \$\begingroup\$ I don't understand your representation of the board. There is no "0" peg at the beginning, but after the first jump, a "0" peg appears. So I thought maybe you are just numbering the positions, but then somehow a 3 ended up on the bottom row, which means the pegs are moving around. Can you explain your output? \$\endgroup\$
    – Rainbolt
    Commented Jul 20, 2015 at 13:16
  • \$\begingroup\$ @Rainbolt You were confused for good reason. I had my output screwed up but I think I fixed it and if not hopefully enough to be understood. I also added some clarification near the end \$\endgroup\$ Commented Jul 20, 2015 at 13:29
  • 2
    \$\begingroup\$ You've explained the meaning of the * and ., but the non-ASCII symbols are not mentioned. Are they required in the output? \$\endgroup\$ Commented Jul 20, 2015 at 13:54
  • \$\begingroup\$ That's the direction of the move which is required. I have that at the top but I'll make it more clear \$\endgroup\$ Commented Jul 20, 2015 at 13:57
  • 3
    \$\begingroup\$ We don't have Cracker Barrel restaurants outside the US. I've added a link to a website with the rules (it seems the name of the game is in fact peg triangle solitaire) but I think you should describe them also. \$\endgroup\$ Commented Jul 20, 2015 at 18:07

1 Answer 1

10
+50
\$\begingroup\$

Ruby -pa, 181 bytes

$_=b||=+-s=(1..5).map{|i|"/ #{[*:A6310[-i]..?E][0,i]*' '} \\".center 13}*$/+$/
f,o,t=$F.map{|i|s=~/#{i}/}
b.tr!(a='→↙↘*↖↗←',?.)?(b[t],b[o]=b[f],a[(o-f)/7]):$><<b
b[f]=?*

Try it online!

The score would be 169 if counted by characters. It's unfortunate that the arrow characters are 3 bytes each, but using them directly is shorter than every method I tried for generating their codepoints (which are irregularly spaced).

Explanation

The board, stored as a multiline string, is padded out to a rectangular grid with leading and trailing spaces on each line. Let \$f\$ and \$o\$ be the indices within this string of the slots being jumped from and over, respectively. Then the following table describes all jumps, independent of the specific slots involved:

Direction \$o-f\$ \$\left\lfloor(o-f)/7\right\rfloor\$
\$\phantom{1}{-2}\$ \$-1\$
\$\phantom{-1}2\$ \$\phantom{-{}}0\$
\$-15\$ \$-3\$
\$-13\$ \$-2\$
\$\phantom{-{}}15\$ \$\phantom{-{}}2\$
\$\phantom{-{}}13\$ \$\phantom{-{}}1\$

Conveniently, we see that \$\left\lfloor(o-f)/7\right\rfloor\$ yields a unique value between \$-3\$ and \$2\$ for each jump direction, ideal for indexing into a string (a) containing the arrow characters.

Flags

-p: Loop through the code for every line of input and implicitly print the contents of $_ at the end of each iteration.

-a: Form the array $F by splitting the input on spaces.

Line by line
$_=b||=+-s=(1..5).map{|i|"/ #{[*:A6310[-i]..?E][0,i]*' '} \\".center 13}*$/+$/

Two boards are saved: s is the starting configuration (all slots filled) whereas b (shadowed by $_) is the current configuration. For each line \$i\in[1,5]\$ in s, slot numbers are generated by taking the first \$i\$ elements of a character range beginning with 0, 1, 3, 6, or A and always ending with E. Each line is padded with leading and trailing spaces (.center 13), the lines are joined by newlines (*$/), and a trailing newline is appended (+$/).

On the first iteration only, s is cloned into b (b||=+-s). $_ is set equal to b so that the board will be printed at the end of each iteration. Since b and $_ point to the same string object, all subsequent operations on b affect $_ too.

f,o,t=$F.map{|i|s=~/#{i}/}

Map the input slot numbers to indices in s, saving the results in f (jump_from), o (jump_over), and t (jump_to). The mapping is as follows: 0 → 6, 1 → 19, 2 → 21, 3 → 32, 4 → 34, 5 → 36, 6 → 45, 7 → 47, 8 → 49, 9 → 51, A → 58, B → 60, C → 62, D → 64, E → 66.

b.tr!(a='→↙↘*↖↗←',?.)?(b[t],b[o]=b[f],a[(o-f)/7]):$><<b

In b, replace the * and arrow character from the previous jump with .. The shouty .tr! modifies b in place, returning nil (falsey) on the first move (no previous jump so no replacements performed) and b (truthy) on all other moves. If it is the first move, print the board with all slots filled ($><<b). Otherwise, update the jump_to slot with the peg from the jump_from slot and set the jump_over slot to the appropriate arrow character by indexing into a as described above.

b[f]=?*

Set the jump_from slot to *, after which the board is implicitly printed.

\$\endgroup\$

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