13
\$\begingroup\$

There is a game I like to play. It happens on a grid of finite size (but it's wrapped, like a sphere). On that grid, a random (integer-only) point is selected. Then, I, the user, am prompted for a coordinate input. If my input matches the random point exactly, I am told that I have won. Otherwise, I am told the point-wise distance between my input and the random point. For example, if I guessed (2,2) and the random point was at (4,3), then the distance would be sqrt[(3-2)^2 + (4-2)^2] = sqrt[5].

The game continues until the player arrives at the correct location of the point.


Objective Create a functional version of the game described above. You must create a full program to do so. Here's what your program should do:

  1. Request two inputs: the height and the width of the board. The origin is at the top-left of the board. These inputs will not exceed 1024.
  2. Select a random point on that board; this will be the point to be guessed.
  3. Accept input simulating a turn. The input will be either a space-separated pair of integers or two separate integer inputs. In response to this input, the program will do one of two things:
    1. If the input matches the random point selected, output a message signalling the user's victory. I would suggest "You won!".
    2. Otherwise, output the distance between the user's input point and the random point.
    In either case, you must increment the turn counter.
  4. Once the user has achieved victory, display the number of turns the user took. The program then exits.

Bonuses

Bonuses are applied in the order that they appear in this list

  • -150 bytes if your program takes an input integer D that describes the dimension in which the game takes place. E.g., if D = 3, then you create a random point of 3 integers, take 3 integer inputs, and output the distance between those points.
  • -50% (or +50% if score < 0)if you provide a graphical representation of the board (ASCII or Picture) that shows where the user has previously guessed on the grid of given dimensions and the turn counter. (If you go for the first bonus, then this bonus only applies to the 2D and 1D modes. If you add a 3D graphical output, you get an additional -50%.)
  • -60 bytes if you can provide a gamemode (selected by an input in the beginning; that is, when given 0, perform the regular gamemode; when given 1, perform this gamemode) in which the point moves 1 unit in a random orthogonal direction per turn

More on wrapping

Wrapping occurs only when, in the third bonus, the moving point moves across any of the boundaries; in this case, the moving point is warped to the respective point, like so:

...              ...
..R (move right) R..
...              ...

This wrapping behaviour does not effect the user's guess, asides from the fact that point has changed direction.


Leaderboard

The Stack Snippet at the bottom of this post generates the catalogue from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

# Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

# Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the snippet:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes

<style>body{text-align:left!important}#answer-list{padding:10px;width:290px;float:left}#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}</style><script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script><link rel=stylesheet type=text/css href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><div id=language-list><h2>Shortest Solution by Language</h2><table class=language-list><thead><tr><td>Language<td>User<td>Score<tbody id=languages></table></div><div id=answer-list><h2>Leaderboard</h2><table class=answer-list><thead><tr><td><td>Author<td>Language<td>Size<tbody id=answers></table></div><table style=display:none><tbody id=answer-template><tr><td>{{PLACE}}<td>{{NAME}}<td>{{LANGUAGE}}<td>{{SIZE}}<td><a href={{LINK}}>Link</a></table><table style=display:none><tbody id=language-template><tr><td>{{LANGUAGE}}<td>{{NAME}}<td>{{SIZE}}<td><a href={{LINK}}>Link</a></table><script>function answersUrl(e){return"//api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"//api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var a=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(a="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var r=a.match(SCORE_REG);r?e.push({user:getAuthorName(s),size:+r[2],language:r[1],link:s.share_link}):console.log(a)}),e.sort(function(e,s){var a=e.size,r=s.size;return a-r});var s={},a=1,r=null,n=1;e.forEach(function(e){e.size!=r&&(n=a),r=e.size,++a;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;o=jQuery("<a>"+o+"</a>").text(),s[o]=s[o]||{lang:e.language,lang_raw:o,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang_raw>s.lang_raw?1:e.lang_raw<s.lang_raw?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var QUESTION_ID=62598,ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",OVERRIDE_USER=8478,answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?([-\d]+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;</script>

\$\endgroup\$
  • 7
    \$\begingroup\$ Minor nitpick: you probably mean it wraps like a torus not a sphere. It's impossible to wrap a 2D grid onto a sphere without creating discontinuities. \$\endgroup\$ – Alistair Buxton Nov 2 '15 at 4:50
  • 2
    \$\begingroup\$ Also if the board wraps then there might be a shorter path between guess and target by crossing an edge. \$\endgroup\$ – Alistair Buxton Nov 2 '15 at 5:01
  • 1
    \$\begingroup\$ @NBZ Yes, you can. \$\endgroup\$ – Conor O'Brien Nov 2 '15 at 18:12
  • 1
    \$\begingroup\$ @NBZ 1 unit it a single direction. \$\endgroup\$ – Conor O'Brien Nov 2 '15 at 18:27
  • 2
    \$\begingroup\$ 1. I'm still not sure what the topology is. To help clear things up, if the board is 10x10, the random point is (9,4), and I guess (2,2), is the distance sqrt(13) or sqrt(53)? (Note for future: if you're doing anything weird, don't include randomness because it makes it almost impossible to supply test cases). 2. In the third bonus, should the distance be computed and output before or after the point moves? \$\endgroup\$ – Peter Taylor Nov 2 '15 at 20:19
8
\$\begingroup\$

CJam, -113 -139 -152 -157 -159 bytes

l~]:B:mr{_ea:i~mr0a*W2mr#+*.+B:,.=_[l~].-:mh_p}g],(

The program is 51 bytes long and qualifies for the -150 bytes and -60 bytes bonuses.

The game mode and number of dimensions are read as a command-line argument, the size in each dimension from STDIN. Since the victory message is arbitrary, the program will print 0.0 (distance to goal) to indicate that the game is over.

Test runs

$ cjam game.cjam 0 3; echo
2 2 2
1 1 1
1.4142135623730951
1 1 0
1.7320508075688774
1 0 1
1.0
0 0 1
0.0
4
$ cjam game.cjam 1 3; echo
2 2 2
0 0 0
1.0
0 0 0
0.0
2

How it works

l~]       e# Read a line from STDIN, evaluate it and collect the result.
:B        e# Save the resulting array in B. The result is [B1 ... Bd],
          e# where Bk is the board size in dimension k.
:mr       e# Pseudo-randomly select a non-negative integer below Bk,
          e# for each k between 1 and d.
{         e# Do:
  _       e#   Copy the item on the stack. The original becomes a dummy value
          e#   that will be used to count the number of turns.
  ea      e#   Push the array of command-line arguments.
  :i~     e#   Cast each to integer and dump them on the stack.
          e#   This pushes m (game mode) and d (number of dimensions).
  mr      e#   Pseudo-randomly select a non-negative integer below d.
  0a*     e#   Push an array of that many zeroes.
  W2mr#   e#   Elevate -1 to 0 or 1 (selected pseudo-randomly).
  +       e#   Append the result (1 or -1) to the array of zeroes.
  *       e#   Repeat the array m times.
  .+      e#   Perform vectorized addition to move the point.
  B:,.=   e#   Take the k-th coordinate modulo Bk.
  _[l~]   e#   Push a copy and an evaluated line from STDIN.
  .-:mh   e#   Compute their Euclidean distance.
  _p      e#   Print a copy.
}g        e# While the distance is non-zero, repeat the loop.
],(       e# Get the size of the stack and subtract 1.
          e# This pushes the number of turns.
\$\endgroup\$
  • 2
    \$\begingroup\$ And Dennis has outgolfed everybody. Again. \$\endgroup\$ – Seadrus Nov 2 '15 at 16:58
  • 1
    \$\begingroup\$ You accidentally updated the score to 152 instead of -152, putting you last on the leaderboard \$\endgroup\$ – Moose Nov 3 '15 at 0:20
7
\$\begingroup\$

Pyth, 91 (-150 -60) = -119

VvwaYOvw;JY#IqQ1=dOlY XYd@S[0 @Jd +@Yd?O2_1 1)1)=T[)VYaT^-Nvw2)=ZhZ=b@sT2Iqb0Bb;p"Won in "Z

Old solution: (54-150=-96)

JYVQaYOvw;#=J[)VYaJ^-Nvw2)=ZhZ=b@sJ2Iqb0Bb;p"Won in "Z

All input takes place on a new line.

  • First integer represents the game mode (either 1 or 0)
  • First Second integer D represents the dimensions of play.
  • Next D inputs represent the field size
  • Every D inputs from this point on are guesses

Sample play (hints do not appear in the actual program):

  #Hint: Gamemode (1 or 0)
1
  #Hint: Dimensions
3
  #Hint: X-size
4
  #Hint: Y-size
4
  #Hint: Z-size
4
  #Hint: Guesses
  #Hint:[3, 2, 1]
3
2
2
1.0
  #Hint:[3, 2, 1]
3
2
1
1.0
  #Hint:[2, 2, 1]
2
2
1
1.0
  #Hint:[3, 2, 1]
3
2
1
Won in 4
\$\endgroup\$
  • \$\begingroup\$ Shouldn't the second move win? \$\endgroup\$ – JNF Nov 2 '15 at 13:35
  • \$\begingroup\$ @JNF the point can move in gamemode 1 (-60 bytes bonus) \$\endgroup\$ – Jakube Nov 2 '15 at 13:38
  • \$\begingroup\$ Holy moly, that is some long pyth code. Not really golfed though. For instance I see two spaces, that can be removed. Also: You can use J=YmOvwvw instead of VvwaYOvw;JY, which is 2 bytes shorter. I haven't looked over the other code, but I guess you can also shorten a few things there. \$\endgroup\$ – Jakube Nov 2 '15 at 13:42
  • \$\begingroup\$ @Jakube,I was assuming the hint tells us where the point currently is \$\endgroup\$ – JNF Nov 2 '15 at 13:48
3
\$\begingroup\$

Python 2, 210 - 150 = 60

from random import*
q,r,o=map,raw_input,int
a=q(randrange,q(o,r().split(' ')))
m=q(o,r().split(' '))
t=1
while m!=a:print sum([(c-d)**2for c,d in zip(m,a)])**.5;m=q(o,r().split(' '));t+=1
print'You won in %d'%t

First challenge only so far. Try it online

\$\endgroup\$
3
\$\begingroup\$

Pip, 43 42 bytes - 150 = -108

Takes the board dimensions as command-line arguments (with D implied from the number of args). Takes guesses as space-separated numbers on stdin.

YRR_MgWd:++i&RT$+(y-(q^s))**2Pd"Won in ".i

This code takes heavy advantage of Pip's array-programming features. The array of cmdline args is stored in g. We generate the point to be guessed by mapping the randrange operator RR over g, and yank the resulting list into the y variable. Then comes the main while loop, where the condition is as follows:

d:++i&RT$+(y-(q^s))**2

  ++i&                  Increment i, the guess counter; the result is always > 0, so the
                          short-circuiting & operator evaluates the next expression:
              q         Read a line from stdin
               ^s       Split on spaces
           y-(   )      Subtract from our chosen point itemwise
          (       )**2  Square, itemwise
        $+              Fold on +, summing the list of squares
      RT                Square root
d:                      Assign this distance to d

If the distance was nonzero, the inside of the loop prints it. If it was zero, we've hit the target point; the loop halts, and the program outputs the win message and number of turns.

Example run:

C:\Users\dlosc> pip.py -f guessing.pip 10 5 6 4
5 2 3 2
3.1622776601683795
6 2 3 2
4.123105625617661
3 2 3 2
1.4142135623730951
3 1 3 2
2.23606797749979
3 2 2 2
1.7320508075688772
2 2 3 2
1
2 2 3 1
1.4142135623730951
2 3 3 2
Won in 8
\$\endgroup\$
2
\$\begingroup\$

R, 134 - 150 = -16 bytes

function(...){G=sapply(list(...),sample,1)
C=0
repeat{g=scan()
C=C+1
if(any(G!=g))cat(sqrt(sum((G-g)^2)))else{cat("Won in",C);break}}}
\$\endgroup\$
2
\$\begingroup\$

Haskell, 240 - 150 = 90

import System.Random
r x=randomRIO(0,x-1)
m=map read.words
g=getLine
main=do g;(fmap m g::IO[Int])>>=mapM r>>=b 1
b c v=do i<-fmap(sqrt.fromIntegral.sum.map(^2).zipWith(-)v.m)g;if i==0 then putStrLn$"Won in "++show c else do print i;b(c+1)v
\$\endgroup\$
1
\$\begingroup\$

Dyalog APL, 77 71 - 210 = -139

S F M
P←?S
{P←S|P+(?D)⌽D↑Mׯ1 1[?2]
C+←1
P≢G←⎕:0⊣⎕←.5*⍨+/2*⍨P-G
C}⍣≢C←0

Ok:

Note that this runs in index origin 0 (⎕IO←0) which is default in many APLs.
Takes boolean mode as right argument (M), and dimension sizes as left argument (S).
Number of dimensions is D, which must be set (e.g. D←3) before calling, as per OP).
P←?S goal gets random point in range 1 though each of the dimension bounds
{}⍣≢C←0 repeat the function until the result is different from C, which initially gets 0
?2 random number 0 or 1
¯1 1[] index from list of two numbers
multiply by mode; makes 0 if mode is 0
D↑ pad with 0s to match number of dimensions
(?D)⌽ rotate list randomly (0 through number of dimensions-1)
P+ adjust current goal
S| world-size modulus
P← save new goal point
C+←1 increment counter
P≢G←⎕: input guess, and if it is different from goal point then...
P-G distances in each dimension
2*⍨ squared
+/ sum them
.5*⍨ square-root
⎕← print that
0⊣ return 0 (i.e identical to initial value, so repeat)
C ... else, return the number of guesses (which, being different from 0, stops the looping and returns the last value)

\$\endgroup\$
  • \$\begingroup\$ @Dennis Actually, I broke it when I made it a function, so now it is a program again. I saved as many bytes as "programmity" cost me by switching to index origin 0, which OP allows. \$\endgroup\$ – Adám Nov 2 '15 at 21:24
  • 1
    \$\begingroup\$ OK. Out of curiosity: Which dialect is this? I have no idea what the first line is suppose to do... \$\endgroup\$ – Dennis Nov 2 '15 at 21:32
  • \$\begingroup\$ @Dennis Dyalog. This is a traditional function, the first line is line [0], i.e. the function header, but it looks unusual because it has left-arg fn-name right-arg, but no result. \$\endgroup\$ – Adám Nov 3 '15 at 14:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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