Place a stone on an empty Go board

34

2

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.

Lynn

Posted 2016-08-08T16:24:27.930

Reputation: 55 648

Just to be sure, "the coordinate as an argument" is meant to imply that we cannot take two arguments, like f("G", 14), correct? – FryAmTheEggman – 2016-08-08T16:45:56.010

Correct. ------ – Lynn – 2016-08-08T16:48:51.833

8Congrats on 20k!! – Luis Mendo – 2016-08-08T17:03:32.017

2"This is, historically, to reduce confusion with J and L." But both J and L are on the board??! – Fatalize – 2016-08-08T20:11:13.067

2Yep. Also, of course, the missing letter has probably caused more confusion and surprise than anything… – Lynn – 2016-08-08T20:14:09.230

2@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... – ilkkachu – 2016-08-09T00:38:46.373

@Fatalize Yes, and I is not, so that you can't confuse I with J or I with L. – user253751 – 2016-08-10T01:59:44.437

Answers

9

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

Luis Mendo

Posted 2016-08-08T16:24:27.930

Reputation: 87 464

16

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.

owacoder

Posted 2016-08-08T16:24:27.930

Reputation: 1 556

298 bytes putchar(i%20?i^20*atoi(p+1)+64-*p+(*p>72)?i%6^4|i/20%6^3?46:42:79:10) – orlp – 2016-08-09T02:12:15.693

Thanks. I was looking for a way to reduce that modulo expression. – owacoder – 2016-08-09T12:07:31.020

9

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.

FryAmTheEggman

Posted 2016-08-08T16:24:27.930

Reputation: 16 206

7

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

user58321

Posted 2016-08-08T16:24:27.930

Reputation: 71

4Welcome 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 – Luis Mendo – 2016-08-08T21:14:09.660

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) – Dada – 2016-08-08T21:21:59.107

7

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
}

Jordan

Posted 2016-08-08T16:24:27.930

Reputation: 5 001

I think you can save a byte by doing $><< instead of puts. Not sure, though. – Fund Monica's Lawsuit – 2016-08-10T01:30:12.140

@QPaysTaxes Alas, I'd have to append a newline somewhere, then. – Jordan – 2016-08-10T01:34:52.343

Oh, yep. Never mind – Fund Monica's Lawsuit – 2016-08-10T01:36:02.093

6

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

Sefa

Posted 2016-08-08T16:24:27.930

Reputation: 582

Could you save 9 characters by renaming part to p? – corsiKa – 2016-08-09T22:03:02.457

Tips for golfing in Go. I took the liberty of applying them to your answer myself. – EMBLEM – 2016-08-10T02:49:19.370

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) – Dada – 2016-08-11T19:48:42.310

4

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

Value Ink

Posted 2016-08-08T16:24:27.930

Reputation: 10 608

Can you save bytes by checking if the index mod 6 is 3 instead of hardcoding 3, 9 and 15? – FryAmTheEggman – 2016-08-08T17:10:03.717

@FryAmTheEggman It might, but I've yet to figure out a solution that does so. – Value Ink – 2016-08-08T17:23:12.777

4

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)

KarlKastor

Posted 2016-08-08T16:24:27.930

Reputation: 2 352

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"." – RootTwo – 2016-08-08T21:02:10.947

Also, I think you can use (x>'I') instead of (x[0]>'I') to save 3 more bytes. – RootTwo – 2016-08-08T21:43:50.210

@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. – KarlKastor – 2016-08-08T22:00:32.073

4

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

asibahi

Posted 2016-08-08T16:24:27.930

Reputation: 371

Oh that was the problem. Funny, it is the one thing I didn't look at twice – asibahi – 2016-08-09T18:37:02.387

4

><>, 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.

Sp3000

Posted 2016-08-08T16:24:27.930

Reputation: 58 729

3

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

Neil

Posted 2016-08-08T16:24:27.930

Reputation: 95 035

3

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!

Dada

Posted 2016-08-08T16:24:27.930

Reputation: 8 279

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... – Dom Hastings – 2016-08-10T21:09:26.003

1@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! :) – Dada – 2016-08-10T21:40:56.220

1Damn, 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! – Dom Hastings – 2016-08-11T05:42:45.627

@DomHastings Thanks for the -3 bytes. Maybe something to try with a 1D array, indeed. I'll try it soon – Dada – 2016-08-11T16:46:46.873

3

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!

Leaky Nun

Posted 2016-08-08T16:24:27.930

Reputation: 45 011

2Hey, congrats on your gold badge! – Luis Mendo – 2016-08-08T22:49:32.553

2

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.

AdmBorkBork

Posted 2016-08-08T16:24:27.930

Reputation: 41 581

2

><>, 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 '.'

owacoder

Posted 2016-08-08T16:24:27.930

Reputation: 1 556

1

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

Neil

Posted 2016-08-08T16:24:27.930

Reputation: 95 035

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). – Konijn – 2016-08-09T08:39:06.250

@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. – Neil – 2016-08-09T08:46:31.043

Hmm, indeed array of strings – Konijn – 2016-08-09T08:52:51.333

1

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.....*...
...................
...................
...................
...................
...................
...*.....*.....*...
...................
...................
...................

plannapus

Posted 2016-08-08T16:24:27.930

Reputation: 8 610

1

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.

ATaco

Posted 2016-08-08T16:24:27.930

Reputation: 7 898

1

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

gabe3886

Posted 2016-08-08T16:24:27.930

Reputation: 221