34
\$\begingroup\$

See also: Make a move on a Go board.

Task

Go is a board game where two players (Black and White) place stones on the intersections of grid lines on a 19×19 board. Black moves first — for example, on D4:

       go coordinates

In this challenge, you must take a Go board coordinate like D4 as input, and output an ASCII representation of a board with the first move played at the given point.

Note that there is no column I. This is, historically, to reduce confusion with J and L.

This output consists of 19 lines, each containing 19 characters. The point with the stone on it is marked O. Empty points on the board are shown as ., except for the nine star points (at D4, D10, D16, K4, K10, K16, Q4, Q10, and Q16), which are marked *.

For example, given F5 as an input, your answer’s output must be:

...................
...................
...................
...*.....*.....*...
...................
...................
...................
...................
...................
...*.....*.....*...
...................
...................
...................
...................
.....O.............
...*.....*.....*...
...................
...................
...................

And given Q16 as input, your output must be:

...................
...................
...................
...*.....*.....O...
...................
...................
...................
...................
...................
...*.....*.....*...
...................
...................
...................
...................
...................
...*.....*.....*...
...................
...................
...................

Rules

  • You may write a function that takes the coordinate as an argument, or a program that reads the coordinate from the command line or from STDIN.

  • You may choose to accept input either in lower-case or upper-case, but your answer doesn’t need to handle both.

  • The input is always a single string like a1 or T19, never a string + number or two strings.

  • If you write a full program, your answer must be printed to STDOUT as a string, optionally followed by a trailing newline. If your answer is a function, you may print to STDOUT, or return a string, or return an array/list of strings (rows), or return a two-dimensional array or nested list of characters.

  • This is . The shortest answer in bytes wins.

\$\endgroup\$
7
  • \$\begingroup\$ Just to be sure, "the coordinate as an argument" is meant to imply that we cannot take two arguments, like f("G", 14), correct? \$\endgroup\$ Commented Aug 8, 2016 at 16:45
  • 8
    \$\begingroup\$ Congrats on 20k!! \$\endgroup\$
    – Luis Mendo
    Commented Aug 8, 2016 at 17:03
  • 2
    \$\begingroup\$ "This is, historically, to reduce confusion with J and L." But both J and L are on the board??! \$\endgroup\$
    – Fatalize
    Commented Aug 8, 2016 at 20:11
  • 2
    \$\begingroup\$ Yep. Also, of course, the missing letter has probably caused more confusion and surprise than anything… \$\endgroup\$
    – lynn
    Commented Aug 8, 2016 at 20:14
  • 2
    \$\begingroup\$ @Fatalize, J and L look quite distinct since the lower parts turn in separate directions. As with j and l, one descends, the other goes up. But i and j are a bit similar, and so are i, l and I... \$\endgroup\$
    – ilkkachu
    Commented Aug 9, 2016 at 0:38

19 Answers 19

16
\$\begingroup\$

C, 212 195 193 181 171 132 103 98 bytes

Saved 1 byte thanks to @FryAmTheEggman, 5 bytes thanks to @orlp

Call f() with the position to play (must be capitalized), and it prints out the resulting board.

i;f(char*p){for(i=380;i--;)putchar(i%20?i^20*atoi(p+1)+64-*p+(*p>72)?i%6^4|i/20%6^3?46:42:79:10);}

Try it on ideone.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ 98 bytes putchar(i%20?i^20*atoi(p+1)+64-*p+(*p>72)?i%6^4|i/20%6^3?46:42:79:10) \$\endgroup\$
    – orlp
    Commented Aug 9, 2016 at 2:12
  • \$\begingroup\$ Thanks. I was looking for a way to reduce that modulo expression. \$\endgroup\$
    – owacoder
    Commented Aug 9, 2016 at 12:07
9
\$\begingroup\$

MATL, 33 bytes

'*O.'19: 6\4=&*Hj1&)Uw64-t8>-&(P)

Try it online!

Explanation

'*O.'    % Push string with needed characters. Will be indexed into
19:      % Push numeric vector [1 2 ... 19]
6\4=     % 1 for values that equal 4 mod 6, 0 for the rest
&*       % Multiply by transposed version of itself with broadcast. This gives
         % the 19×19 board with 0 instead of '.' and 1 instead of '*'
H        % Push 2. This will correspond to 'O' (stone)
j        % Input string, such as 'Q16'
1&)      % Split into its first char ('Q') and then the rest ('16')
U        % Convert to number (16)
w        % Swap, to move 'Q' to top
64-      % Subtract 64. Thus 'A' gives 1, 'B' gives 2 etc
t8>-     % Duplicate. Subtract 1 if it exceeds 8. This corrects for missing 'I'
&(       % Fill a 2 at coordinates given by the number and the letter
P        % Flip upside down, because matrix coordinates start up, not down
)        % Index the string '*O.' with the 19×19 array containing 0,1,2.
         % Implicitly display
\$\endgroup\$
9
\$\begingroup\$

C (gcc), 132 128 109

i;m;f(char*s){for(i=380;i--;putchar(m?m^84-*s+(*s>73)|(i/20+1)^atoi(s+1)?m%6^4|i/20%6^3?46:42:79:10))m=i%20;}

Ideone

A function that prints the board to STDOUT. Requires the letter coordinate to be capital. Printing in one loop seems to be slightly shorter than the previous nested loop approach.

\$\endgroup\$
7
\$\begingroup\$

MATLAB, 135 bytes

A first attempt, nothing clever, just to see how much better others can do:

function go(a)
b=repmat('.',19);
b(4:6:end,4:6:end)='*';
a=sscanf(a,'%c%d');
a(1)=a(1)-64;
if a(1)>8
a(1)=a(1)-1;
end
b(20-a(2),a(1))='0'

Usage:

go('T19')
\$\endgroup\$
2
  • 4
    \$\begingroup\$ Welcome to PPCG! Some suggestions for reducing bytes: use a function name with 1 char (or a script with a=input('');); remove newlines; change '*' to 42 and '0' to 48; replace end by 19; subtract the logical value directly instead of the if branch. In fact, you can replace the last fiive lines by b(20-a(2),a(1)-64-(a(1)>8))=48 \$\endgroup\$
    – Luis Mendo
    Commented Aug 8, 2016 at 21:14
  • \$\begingroup\$ Hi and welcome to PPCG. If I'm not mistaken, your code is 137 bytes long and not 135. (I guess it doesn't matter a lot, but I just wanted to let you know) \$\endgroup\$
    – Dada
    Commented Aug 8, 2016 at 21:21
7
\$\begingroup\$

Ruby, 93 91 bytes

Takes input on the command line, e.g. $ ruby script.rb Q16.

19.downto(1){|c|puts ([*?A..?T]-[?I]).map{|d|d+c.to_s==$*[0]??O:"DKQ"[d]&&c%6==4??*:?.}*""}

Test it on repl.it (wrapped in a lambda there since repl.it doesn't take command line arguments: https://repl.it/CkvT/1

Ungolfed

19.downto(1) do |row|
  puts ([*?A..?T] - [?I]).map {|column|
    if column + row.to_s == ARGV[0]
      "O"
    elsif "DKQ"[column] && row % 6 == 4
      "*"
    else
      "."
    end
  }.join
}
\$\endgroup\$
3
  • \$\begingroup\$ I think you can save a byte by doing $><< instead of puts . Not sure, though. \$\endgroup\$
    – anon
    Commented Aug 10, 2016 at 1:30
  • \$\begingroup\$ @QPaysTaxes Alas, I'd have to append a newline somewhere, then. \$\endgroup\$
    – Jordan
    Commented Aug 10, 2016 at 1:34
  • \$\begingroup\$ Oh, yep. Never mind \$\endgroup\$
    – anon
    Commented Aug 10, 2016 at 1:36
6
\$\begingroup\$

Go, 319 286 bytes

import(."strconv"
."strings")
func g(c string)(s string){p:=SplitN(c,"",2)
n,_:=Atoi(p[1])
for i:=19;i>0;i--{
for j:= 'a';j<'t';j++{
if j=='i'{
}else if n==i&&ContainsRune(p[0],j){s+="o"
}else if((i==4||i==10||i==16)&&(j=='d'||j=='k'||j=='q')){s+="*"
}else{s+="."}}
s+="\n"}
return}

Probably golfable quit a bit, i'm a begginner

\$\endgroup\$
3
  • \$\begingroup\$ Could you save 9 characters by renaming part to p? \$\endgroup\$
    – corsiKa
    Commented Aug 9, 2016 at 22:03
  • \$\begingroup\$ Tips for golfing in Go. I took the liberty of applying them to your answer myself. \$\endgroup\$
    – EMBLEM
    Commented Aug 10, 2016 at 2:49
  • \$\begingroup\$ Did you notice that the comment "+1 for choice of language" has more upvotes than the post itself ? (it happens that comments have more upvotes, but for such a comment, that's rather unexpected) \$\endgroup\$
    – Dada
    Commented Aug 11, 2016 at 19:48
4
\$\begingroup\$

Ruby, 130 128 121 + 3 (-n flag) = 124 bytes

Switched -p to -n because puts b is one byte shorter than $_=b*$/

~/(.)(.+)/
b=(1..19).map{?.*19}
(a=3,9,15).map{|i|a.map{|j|b[i][j]=?*}}
b[19-$2.to_i][([*?A..?T]-[?I]).index$1]=?o
puts b
\$\endgroup\$
2
  • \$\begingroup\$ Can you save bytes by checking if the index mod 6 is 3 instead of hardcoding 3, 9 and 15? \$\endgroup\$ Commented Aug 8, 2016 at 17:10
  • \$\begingroup\$ @FryAmTheEggman It might, but I've yet to figure out a solution that does so. \$\endgroup\$
    – Value Ink
    Commented Aug 8, 2016 at 17:23
4
\$\begingroup\$

Python, 148 145 136 130 121 119 116 Bytes

-3 Bytes thanks to @RootTwo

lambda x,r=range(19):[[".*o"[[i%6==j%6==3,2][j==ord(x[0])-(x>"I")-65and-~i==int(x[1:])]]for j in r]for i in r[::-1]]

anonymous lambda function, takes input of the form "A1" (big letters) and outputs a list of lists of chars (len==1 strings in Python)

\$\endgroup\$
3
  • \$\begingroup\$ Save 8 bytes by using ".*oo"[2*(j==ord(x[0])-(x[0]>"I")-65and int(x[1:])==i+1)+(i%6==j%6==3)] instead of the "o"if...else"*"if...else"." \$\endgroup\$
    – RootTwo
    Commented Aug 8, 2016 at 21:02
  • \$\begingroup\$ Also, I think you can use (x>'I') instead of (x[0]>'I') to save 3 more bytes. \$\endgroup\$
    – RootTwo
    Commented Aug 8, 2016 at 21:43
  • \$\begingroup\$ @RootTwo Thanks, the first suggestion is no longer useful, since I've since found a even shorter solution. The second one now seems obvious and makes me question why i haven't thought of this earlier. \$\endgroup\$
    – KarlKastor
    Commented Aug 8, 2016 at 22:00
4
\$\begingroup\$

><>, 98 96 bytes

'_U'i-:b)-0\
+*a$%cv?(0:i<
{*+{4*\+
+4gf-o>1-:?!;:{:}=3*&::aa+%::0=2*&+&6%1-}-aa+,6%{*9=&
=9^^

Note that there is an 0x14 in the first row after the first ', and an 0x19 between the 9 and the first ^ of the last line. Try it online!

The input is mapped so that A-T become 1-19 (with 0 denoting an imaginary "newline" column) and the integer row number is decremented by 1. The program does a loop from 379 down to 0, choosing a char from the bottom row as it goes (offset by 15, to account for the fact that you can't enter a literal newline in the codebox). Newlines are checked via i % 20 == 0, and star points are checked by ((i%20-1)%6)*((i/20)%6) == 9.

\$\endgroup\$
4
\$\begingroup\$

F#, 241 237 225 216 214 211 bytes

let G(c:string)=for k=1 to 380 do printf(if k%20=0 then"\n"elif"_ABCDEFGHJKLMNOPQRST".IndexOf c.[0]=k%20&&19-k/20=int(c.Substring 1)then"o"elif(k%20=4||k%20=10||k%20=16)&&(k/20=3||k/20=9||k/20=15)then"*"else".")

Tricky one this one ... I wonder if it can be made shorter.

Edit: fixed a bug, added numbers some places removed numbers in others, somehow ended up with the same count. Might try shuffling numbers around later Done.

Edit2: saved more bytes by spelling out one of the conditionals, counter intuitively.

Edit3: Fixed another bug: should work now for pieces on the last rank and managed to save two bytes while I am at it, somehow.

Try it online

\$\endgroup\$
1
  • \$\begingroup\$ Oh that was the problem. Funny, it is the one thing I didn't look at twice \$\endgroup\$
    – asibahi
    Commented Aug 9, 2016 at 18:37
3
\$\begingroup\$

Retina, 134 129 122 bytes

11 bytes thanks to Martin Ender, and for inspiration of 1 more.

S2=`
[K-S]
1$&
T`xL`d9d
.+
$*
$
aaab
a
bbbcbb
b|c
¶$0
c
ddd.
d
...*..
b
19$*.
1(1)*¶1(1)*¶((?<-2>.+¶)*(?<-1>.)*).
$3O
O^$`

Try it online!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Hey, congrats on your gold badge! \$\endgroup\$
    – Luis Mendo
    Commented Aug 8, 2016 at 22:49
3
\$\begingroup\$

Perl, 132 bytes

-3 bytes thanks to @Dom Hastings

@v=eval"[('.')x19],"x19;@{$v[$_]}[@t]=("*")x3for@t=(3,9,15);pop=~/\d+/;$v[19-$&][($t=ord$`)-65-($t>73)]=O;map{say}map{join"",@$_}@v;

Takes command line input. Needs -M5.010 tu run. For instance :

$ cat go_board.pl
@v=eval"[('.')x19],"x19;@{$v[$_]}[@t]=("*")x3for@t=(3,9,15);pop=~/\d+/;$v[19-$&][($t=ord$`)-65-($t>73)]=O;map{say}map{join"",@$_}@v;
$ perl -M5.010 go_board.pl Q16

I think this could be shorter, but I couldn't figure out how... please let me know if you do!

\$\endgroup\$
4
  • \$\begingroup\$ Nice use of more magic variables again! I haven't tested this properly but I think you can save a few more with @v=([(".")x18])x18; to initialise the list... There might even be a better way than that, but I'm not at a terminal right now! I think you can replace the @{...} expansion with dereferencing arrows too: $v[$_]->[@t] again untested though! Also I hope you don't mind me suggesting code changes... \$\endgroup\$ Commented Aug 10, 2016 at 21:09
  • 1
    \$\begingroup\$ @DomHastings Of course I don't mind, on the contrary, I'd rather encourage you to suggest improvements! @v=([(".")x19])x19 doesn't work (I tried it before btw), because it create only one arrayref and it copy 19 times the ref, not the array (so in the end you only have 1 line duplicated 19 times). Replacing @{..} as you suggested doesn't seem to work either. I'm guessing that's because I'm working on a slice and not only one element. If you have any other suggestion, feel free to suggest! :) \$\endgroup\$
    – Dada
    Commented Aug 10, 2016 at 21:40
  • 1
    \$\begingroup\$ Damn, of course it'd be the same... I've managed to use eval for -3 though: @v=eval"[('*')x19],"x19;. And you're 100% correct with the arrayref... Is is maybe possible to use a 1D array and work out the index in that though? Might play with this more later! \$\endgroup\$ Commented Aug 11, 2016 at 5:42
  • \$\begingroup\$ @DomHastings Thanks for the -3 bytes. Maybe something to try with a 1D array, indeed. I'll try it soon \$\endgroup\$
    – Dada
    Commented Aug 11, 2016 at 16:46
3
\$\begingroup\$

Batch, 322 310 308 bytes

@echo off
set/pi=
set/aa=0,b=1,c=2,d=3,e=4,f=5,g=6,h=7,j=8,k=9,l=10,m=11,n=12,o=13,p=14,q=15,r=16,s=17,t=18,x=%i:~1%-1,y=%i:~,1%,z=y+1
for /l %%r in (18,-1,0)do call:l %%r
exit/b
:l
set s=...*.....*.....*...
call set t=%%s:~%1,1%%
if %x%==%1 call set s=%%s:~,%y%%%o%%s:~%z%%%
call echo %%s:.*=.%t%%%

Explanation: Starts by prompting for the stone on stdin. Then, sets variables for each possible column, so that it can evaluate the first character of the stone as a variable to get the y coordinate. Subtracts 1 from the x coordinate because it's 1-indexed and we want 0-indexed and also computes z=y+1 as it will need that later. Then, loops r from 18 down to 0 for each row. Takes the string ...*.....*.....*... and extracts the character at the rth position for later. On the xth row, the yth character is replaced with an o. Finally, the .*s are replaced with a . plus the previously extracted character; this is a no-op on rows 4, 10 and 16 but this is the shortest way to achieve that. (I have to use .* because replacing * is apparently illegal in Batch.)

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

PowerShell v2+, 157 152 bytes

$x,$y=[char[]]$args[0];$a=,0*19;0..18|%{$a[$_]=,'.'*19};3,9,15|%{$i=$_;3,9,15|%{$a[$_][$i]='*'}};$a[-join$y-1][$x-65-($x-gt73)]='O';$a[18..0]|%{-join$_}

(I think I ran into some sort of weird glitch with the comma-operator, so the array construction is a bit longer than it should be)

Takes input as an uppercase string via $args[0], casts it as a char-array, stores the first letter into $x and the remaining letters into $y. This effectively splits the input into letter/number.

We then construct our multidimensional array $a. We pre-populate an array of size 19 with 0s using the comma-operator. We then loop 0..18 to make each element $a[$_] equal instead an array of periods, again using the comma operator. (NB - In theory, this should be able to be condensed to $a=,(,'.'*19)*19, but that doesn't seem to work right with the indexing assignment ... I wound up getting whole columns set to *)

Next, we loop twice over 3,9,15 to set the corresponding elements to *. We then index into it in the right spot to set the stone O. To do so, we subtract 65 from $x (i.e, ASCII "A" is 65, and we're zero-indexed), and subtracts an additional one using a Boolean-to-int cast if $x is bigger than 73 (i.e., ASCII "I").

Now, our output is reversed (i.e., the upper-left would be A1), so we need to reverse the array with $a[18..0]. Finally, we output each line -joined together to form a string.

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

><>, 124 bytes

Uses the exact same approach as my C answer. Input must be a capital letter followed by a decimal number.

88*i:&-&'I')+0 v
*a&-'0'v!?)0:i&<+
+**2a&~/*a'&'&
:;!?:-1<o'O'v!?=&:&
{*?!v'*'o63.>:6%4=}:a4*+'x'%aa*)
*2a:/  av?%
.37o<'.'<

Try it online!

Explanation:

88*i:&-&'I')+0 v         'Push 64-<first input char>+(<first input char> > 'I')
*a&-'0'v!?)0:i&<+        'Set register to 0, parse decimal integer into register.
+**2a&~/*a'&'&           'Pop the -1 (EOF) from stack, multiply register by 20.
                         'Add result of first line to register.
                         'Push 380 onto stack.
:;!?:-1<o'O'v!?=&:&      'Main loop, while top of stack is not 0.
                         'Subtract 1 from top of stack (loop counter)
                         'If current index is the playing piece index, print 'O'
{*?!v'*'o63.>:6%4=}:a4*+'x'%aa*) 
                         'If (index%6)=4 and (index+40)%120>100, print '*'
*2a:/  av?%              'If (index%20)=0, print newline
.37o<'.'<                'Otherwise, print '.'
\$\endgroup\$
1
\$\begingroup\$

JavaScript, 138 bytes

s=>[...t="...*.....*.....*..."].map((c,i)=>t.replace(/\*/g,c).replace(/./g,(c,j)=>x-j|19-i-s.slice(1)?c:'o'),x=parseInt(s[0],36)*.944-9|0)

Returns an array of strings. Explanation:

s=>[...                         Parameter
 t="...*.....*.....*..."        Pattern of lines 4, 10 and 16
].map((c,i)=>                   Loop 19 times
 t.replace(/\*/g,c)             Change the `*` to `.` on other lines
  .replace(/./g,(c,j)=>         Loop over each character
   x-j|19-i-s.slice(1)?c:'o'),  Change to o at the appropriate position
 x=parseInt(s[0],36)*.944-9|0)  Compute the column number from the letter
\$\endgroup\$
3
  • \$\begingroup\$ An array of strings is not matching the required output, just join. Also it places the o in the wrong row and the wrong column for D5 (first test case). \$\endgroup\$
    – Konijn
    Commented Aug 9, 2016 at 8:39
  • \$\begingroup\$ @tomdemuyt An array of strings is allowed as a return value. However, it's possible that I got my rows and columns mixed up, so I'll double-check. \$\endgroup\$
    – Neil
    Commented Aug 9, 2016 at 8:46
  • \$\begingroup\$ Hmm, indeed array of strings \$\endgroup\$
    – Konijn
    Commented Aug 9, 2016 at 8:52
1
\$\begingroup\$

R, 169 161 bytes

f=function(p){S=substr;N=rep(".",114);N[61+6*0:2]="*";M=matrix(N,19,19);M[(S(p,2,3):1)[1],which(LETTERS[-9]==S(p,1,1))]="O";for(i in 19:1)cat(M[i,],"\n",sep="")}

With indents and newlines:

f=function(p){
    S=substr
    N=rep(".",114) # 6 lines of dots
    N[61+6*0:2]="*" # Place the hoshis
    M=matrix(N,19,19) # Make the 19x19 board using vector recycling
    M[(S(p,2,3):1)[1],  #grab and force coerce the row number to integer
      which(LETTERS[-9]==S(p,1,1))]="O" #Place the first stone
    for(i in 19:1) cat(M[i,],"\n",sep="")
}

Usage:

> f("A19")
O..................
...................
...................
...*.....*.....*...
...................
...................
...................
...................
...................
...*.....*.....*...
...................
...................
...................
...................
...................
...*.....*.....*...
...................
...................
...................
> f("D4")
...................
...................
...................
...*.....*.....*...
...................
...................
...................
...................
...................
...*.....*.....*...
...................
...................
...................
...................
...................
...O.....*.....*...
...................
...................
...................
> f("K10")
...................
...................
...................
...*.....*.....*...
...................
...................
...................
...................
...................
...*.....O.....*...
...................
...................
...................
...................
...................
...*.....*.....*...
...................
...................
...................
\$\endgroup\$
1
\$\begingroup\$

Lua, 187 Bytes

function g(i)i:gsub("(%a+)(%d+)",function(a,b)q=string.byte(a)-64 r=b+0 end)for x=1,19 do s=""for y=1,19 do s=s..(x+y*19==r+q*19 and"o"or(x-4)%6+(y-4)%6==0 and"*"or"-")end print(s)end end

I don't feel too bad about 187 for this particular project. Lua still comes out as very clunky for Golfing, but I'm pretty proud of how far I can go with it.

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

PHP, 280 268 263 261 255 218 216 bytes

<?php $a=ucfirst($argv[1]);$x=substr($a,0,1);$y=substr($a,1);$s=['DKQ',4,16,10];$i=85;while(64<$i--){$j=0;while($j++<20){echo($x==chr($i)&&$y==$j)?'O':((strpos($s[0],chr($i))>-1&&in_array($j,$s))?'*':'.');}echo"\n";}

My first golf.

Usage:
Save as a PHP file and call it by php filename.php coordinate e.g. php go.php k13

\$\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.