15
\$\begingroup\$

The puzzle is as follows:

Create the traditional 'Guess my Number' game in as little keystrokes as possible. The player should input a guess between and including 1 and 100, and the computer should reply with either + (meaning the player needs to guess higher), - (meaning the player needs to guess lower) or = (meaning the player has guessed the number. The game continues until the player has guessed the number. The number that the computer generates MUST be a random number between and including 1 and 100.

Sample gameplay

50
+
75
-
60
-
55
+
57
=

Happy Golfing!

\$\endgroup\$
5
  • \$\begingroup\$ Whoever can post an answer fastest with the OSK in most OSes gets my vote. That's like, 3 keystrokes to open \$\endgroup\$
    – Bojangles
    Apr 11 '13 at 15:21
  • \$\begingroup\$ @Howard this one is basically a simplified version of the one you found. Not an exact duplicate, though \$\endgroup\$ Apr 11 '13 at 15:41
  • \$\begingroup\$ @JanDvorak, I feel its not a significant enough variant to warrant a different question. \$\endgroup\$
    – zzzzBov
    Apr 11 '13 at 20:30
  • \$\begingroup\$ @zzzzBov how does that work on a puzzle site, this is a slightly different question though I agree it's pretty close. However the other one has an accepted answer. what if people want to work this puzzle but not the other one? \$\endgroup\$
    – Ryan
    Apr 11 '13 at 22:31
  • \$\begingroup\$ @ryan, I don't know how it works on a site such as Code Golf. I fully understand the predicament of posing a challenge similar to an existing one, however in this case, I feel that this one is too similar to the existing one. It's an opinion, and in the end the votes are what will decide whether or not this gets closed or stays open. \$\endgroup\$
    – zzzzBov
    Apr 11 '13 at 22:34

24 Answers 24

10
\$\begingroup\$

Ruby: 63 58 52 49 characters

puts"=-+"[r=$_.to_i<=>n||=1+rand(100)];r==0&&exit

Sample run:

bash-4.2$ ruby -ne 'puts"=-+"[r=$_.to_i<=>n||=1+rand(100)];r==0&&exit'
50
-
25
+
37
+
43
-
40
+
42
=
\$\endgroup\$
5
  • 2
    \$\begingroup\$ A few small improvements: exit if r==0 -> r==0&&exit, and there is no whitespace needed in puts"=-+". \$\endgroup\$
    – primo
    Apr 11 '13 at 19:04
  • \$\begingroup\$ I remembered the && trick just this morning. Seems I'm getting slow. \$\endgroup\$
    – manatwork
    Apr 12 '13 at 7:21
  • \$\begingroup\$ Ups, sorry. I read the code wrong. \$\endgroup\$
    – Howard
    Apr 12 '13 at 10:50
  • \$\begingroup\$ Is 1+$$%100 random enough? \$\endgroup\$
    – Howard
    Apr 12 '13 at 10:59
  • \$\begingroup\$ +1 for 42 as a random number :) \$\endgroup\$
    – tomsmeding
    Apr 14 '13 at 17:31
9
\$\begingroup\$

Python 84 83 characters

import os
a,c=0,ord(os.urandom(1))%100+1
while c-a:a=input();print'=-+'[c!=a:][c>a]
\$\endgroup\$
2
  • \$\begingroup\$ I can not make it work with python 3. Here is my solution import os a,c=0,ord(os.urandom(1))%10+1 while c-a:a=int(input());print("not ok") print("ok") \$\endgroup\$
    – Chau Giang
    Mar 26 at 11:40
  • \$\begingroup\$ Can you please try to run your code? \$\endgroup\$
    – Chau Giang
    Mar 26 at 11:41
6
\$\begingroup\$

JavaScript, 52

for(u=r=1+new Date%100;u=r-prompt(u<0?'-':'+'););'='

Just paste it in the console.

\$\endgroup\$
9
  • \$\begingroup\$ Nice one! Even if skips some of the rules: uses 0..99 interval instead of 1..100 and not displays “=” on success. \$\endgroup\$
    – manatwork
    Apr 11 '13 at 17:39
  • \$\begingroup\$ @manatwork now I guess I can read the rules :) I edited for the 1..100. \$\endgroup\$ Apr 11 '13 at 17:41
  • \$\begingroup\$ @manatwork I edited for the = too. Much less elegant. I'll try later to make it shorter. \$\endgroup\$ Apr 11 '13 at 17:44
  • \$\begingroup\$ You can save 1 character by using a reference to prompt(): first p=prompt, then just p(). But something is wrong with the logic, as the “=” only appears if you guess the number on first try. \$\endgroup\$
    – manatwork
    Apr 11 '13 at 17:50
  • \$\begingroup\$ I must leave for a moment. But this version should work (less user friendly, though). \$\endgroup\$ Apr 11 '13 at 17:59
6
\$\begingroup\$

Perl 57 53 50 (thanks to @manatwork) Characters

$_=qw(= + -)[$^T%100+1<=>$_];print"$_
";exit if/=/

Note You need to invoke with -n option

Alternate version as suggested by @primo

Perl 40 Characters

$_=chr 44-($^T%100+1<=>$_||exit print'=')
\$\endgroup\$
11
  • 1
    \$\begingroup\$ qw(= - +) is shorter than ('=','-','+') \$\endgroup\$
    – manatwork
    Apr 11 '13 at 17:02
  • \$\begingroup\$ @manatwork: I am not a perl expert. Thank you for the advise :-) \$\endgroup\$
    – Abhijit
    Apr 11 '13 at 17:03
  • \$\begingroup\$ You not need while, if is enough. And please change the response logic. \$\endgroup\$
    – manatwork
    Apr 11 '13 at 17:05
  • \$\begingroup\$ @manatwork: I think you can use this answer to post a new one (you deserve it). Once you are done, I will delete it. As I said am not an expert of Perl :-) \$\endgroup\$
    – Abhijit
    Apr 11 '13 at 17:09
  • 2
    \$\begingroup\$ Bit of a re-work, but essentially the same for 41 (actually 40, because ^T can be replaced with character 20), requires -pl: $_=chr 44-($^T%100+1<=>$_||exit print'=') \$\endgroup\$
    – primo
    Apr 11 '13 at 18:25
5
\$\begingroup\$

APL (28)

{'='≠⎕←'+=-'[2+×⎕-⍵]:∇⍵}?100
\$\endgroup\$
1
  • 3
    \$\begingroup\$ I can't read this, but it looks cool. \$\endgroup\$
    – asteri
    Apr 12 '13 at 15:57
3
\$\begingroup\$

Haskell, 128

Won’t be winning any awards, but here it is.

main=fix.(.)(=<<(read<$>getLine)).f=<<(`mod`100).fst.next<$>newStdGen where p=putStrLn;f y r x|x<y=p"+">>r|x>y=p"-">>r|True=p"="

Ungolfed logic and imports:

import Control.Applicative
import Data.Function
import System.Random

main :: IO ()
main = do
  random <- newStdGen
  let number = fst (next random) `mod` 100
  fix $ \loop -> do
    guess <- read <$> getLine
    check number guess loop
  where
    check number guess loop
      | guess < number = do
        putStrLn "+"
        loop
      | guess > number = do
        putStrLn "-"
        loop
      | otherwise = putStrLn "="
\$\endgroup\$
3
\$\begingroup\$

C#: 147 136 Characters

It won't beat most other languages, but here's a C# solution for fun:

var r=new Random().Next(1,100);var g=0;while(g!=r){g=int.Parse(Console.ReadLine());Console.WriteLine(""+g+'\n'+(g<r?'+':g>r?'-':'='));}
\$\endgroup\$
6
  • \$\begingroup\$ Is that a complete C# program source ? \$\endgroup\$ Apr 11 '13 at 20:15
  • \$\begingroup\$ I remember seeing a post on meta about ignoring standard overhead/bloat from languages like C#/Java (can't find the link now). It will copy-paste into LINQPad. \$\endgroup\$
    – Anthony
    Apr 12 '13 at 10:23
  • \$\begingroup\$ If you remove overhead from other, they'll be shorter too. The Go one for example could be reduced to 105 chars. But it would be hard to define a unique line, so I don't think that really makes sense. \$\endgroup\$ Apr 12 '13 at 10:25
  • 1
    \$\begingroup\$ You can trim another 27 by changing your definition, loop handling, and unnecessary echo of the input. int r=new Random().Next(1,100),g=0;while(g!=r){g=int.Parse(Console.ReadLine());Console.WriteLine(g<r?'+':g>r?'-':'=');} \$\endgroup\$ Apr 12 '13 at 19:22
  • \$\begingroup\$ Your code will never choose the number "100", it should be Next(1,101) or Next(100)+1. :) \$\endgroup\$ Aug 10 '13 at 6:05
2
\$\begingroup\$

Clojure (117 characters)

java -jar clojure.jar  -e "(loop[n(int(*(rand 100)))]((get{-1#(prn '+)0#(do(prn '=)(System/exit 0))1#(prn '-)}(compare(eval(read))n)))(recur n))"
50
+
75
+
90
-
86
-
82
=

Clojure (74 characters)

Guessing a real number. Nobody will be patient enought to solve to "=", so nobody notice the missing exit.

java -jar clojure.jar  -e "(loop[n(rand)](prn (get{-1 '+ 0 '= 1 '-}(compare(eval(read))n)))(recur n))"
0.5
+
0.8
-
0.6
+
0.7
+
0.75
-
0.72
+
0.74
+
0.745
+
0.748
-
0.746
-
0.7455
-
...
\$\endgroup\$
2
\$\begingroup\$

R, 89 85 chars

s=sample(1:100,1);while(s!=(a=as.real(readline())))cat(ifelse(a>s,"-","+"));cat("=")
\$\endgroup\$
2
  • 1
    \$\begingroup\$ +1 putting the user guess in the while condition is indeed a good idea! However defining cat as a variable here actually cost you 2 characters: w=cat; (6) + 2 times w are 8 characters while 2 times cat is only 6 characters! :) I think you can also get rid of the curly braces since your while loop now contains only 1 line. \$\endgroup\$
    – plannapus
    Apr 12 '13 at 13:57
  • \$\begingroup\$ @plannapus Good points! The w= made a lot more sense when I was using write, but your way is better. \$\endgroup\$
    – eykanal
    Apr 12 '13 at 14:49
2
\$\begingroup\$

C89 92 90 89 (Thanks to @ugoren) 84 characters running on OS and linked with Linker supporting ASLR

main(c,g){g=g/8%100+1;while(scanf("%d",&c)&&printf("%c\n",g-c?"-+"[c<g]:'=')&&c-g);}
\$\endgroup\$
6
  • \$\begingroup\$ I don't think that will produce very random numbers in many OSes, unless address space randomization is turned on. \$\endgroup\$
    – fluffy
    Apr 11 '13 at 21:05
  • \$\begingroup\$ @fluffy: I already mentioned in my most. And IMHO, all modern OSes except RTOS supports ASLR \$\endgroup\$
    – Abhijit
    Apr 12 '13 at 2:46
  • \$\begingroup\$ main(c,g) would save int. Or maybe main(g,c), assuming the argument vector is randomized by ASLR. \$\endgroup\$
    – ugoren
    Apr 12 '13 at 10:14
  • \$\begingroup\$ However, ASLR will not randomize the low bits.The address of main will always be a multiple of 4 (at least). \$\endgroup\$
    – ugoren
    Apr 12 '13 at 10:15
  • \$\begingroup\$ @ugoren: Yes I agree and so changed my code accordingly. On another context I have not acceoted your edit, cause the particular bahaviour of missing type defaulting to int is not accepted in C99. \$\endgroup\$
    – Abhijit
    Apr 12 '13 at 10:55
1
\$\begingroup\$

K, 69

b:1b;g:1+*1?100;while[b;-1(*$[g<f:"I"$m:0:0;"-";g>f;"+";("=";b:0b)])]

Could definitely be golfed more

k)b:1b;g:1+*1?100;while[b;-1(*$[g<f:"I"$m:0:0;"-";g>f;"+";("=";b:0b)])]
50
+
75
-
60
+
65
-
63
+
64
=
\$\endgroup\$
1
\$\begingroup\$

Go, 152

Golfed :

package main
import(f"fmt";"os")
func main(){
c:=1+os.Getpid()%100
u:=0
for u!=c{
f.Scanf("%d",&u)
s:="="
if u<c{s="+"}else if u>c{s="-"}
f.Println(s)}}

Ungolfed :

package main

import (
    f "fmt"
    "os"
)

func main() {
    c := 1 + os.Getpid()%100
    u := 0
    for u != c {
        f.Scanf("%d", &u)
        s := "="
        if u < c {
            s = "+"
        } else if u > c {
            s = "-"
        }
        f.Println(s)
    }
}

Session :

guess

4

+

88

-

66

+

77

-

71

+

73

+

75

=

Hard to golf when you start any program with package main and a list of imports...

\$\endgroup\$
1
  • 2
    \$\begingroup\$ But real golf has big bags full of heavy clubs. There are even wheels on the bags. What's more they are "imported" for you by your caddy. And you drive around a big, reserved field in electric carts. Let's not even speak about the annual fee. \$\endgroup\$
    – Kaz
    Apr 12 '13 at 3:13
1
\$\begingroup\$

R: 88 characters

r=sample(1:100,1);i=scan(n=1);while(i!=r){cat(ifelse(i<r,"+","-"));i=scan(n=1)};cat("=")

Ex:

> r=sample(1:100,1);i=scan(n=1);while(i!=r){cat(ifelse(i<r,"+","-"));i=scan(n=1)};cat("=")
1: 23
Read 1 item
+
1: 46
Read 1 item
-
1: 35
Read 1 item
-
1: 31
Read 1 item
-
1: 28
Read 1 item
+
1: 30
Read 1 item
-
1: 29
Read 1 item
=
>
\$\endgroup\$
1
  • \$\begingroup\$ Look at my answer; this can be shortened by (1) defining a cat variable and (2) defining i in the while loop. You can also use the quiet option to remove the "Read 1 item" notice, but I don't think you can turn off scan's "1:" prompt. \$\endgroup\$
    – eykanal
    Apr 12 '13 at 12:40
1
\$\begingroup\$

PHP: 95 91 87 73 71 65 chars

<?php $n=rand(1,100);while(@$g!=$n){$g=trim(fgets(STDIN));echo$g==$n?'=':($g>$n?'-':'+')."\n";}
<? for($n=rand(1,100);@$g!=$n?$g=trim(fgets(STDIN)):0;)echo$g==$n?'=':($g>$n?'-':'+')."\n";
<? for($n=rand(1,100);$n!=$g=trim(fgets(STDIN));print(($g>$n?'-':'+')."\n"));echo"=\n";
<? for($n=rand(1,100);$n!=$g=fgets(STDIN);print(($g>$n?'-':'+')."\n"))?>=
<? for($n=rand(1,100);$n!=$g=fgets(STDIN);print($g>$n?'-':'+')."\n")?>=
<?for($n=rand(1,100);$n!=$g=fgets(STDIN);print$g>$n?"-
":"+
")?>=
\$\endgroup\$
3
  • 1
    \$\begingroup\$ 89: <? for($n=rand(1,100);($g=trim(fgets(STDIN)))!=$n;print$g==$n?'=':($g>$n?'-':'+')."\n"); \$\endgroup\$ Apr 12 '13 at 20:17
  • \$\begingroup\$ You don't need to call trim, since 8 == "8\n". That brings it down to 81 characters: <? for($n=rand(1,100);$n!=$g=fgets(STDIN);print(($g>$n?'-':'+')."\n"));echo"=\n"; \$\endgroup\$ Apr 12 '13 at 20:57
  • \$\begingroup\$ You can get it down to 73 characters by exiting PHP mode at the end instead of calling echo: <? for($n=rand(1,100);$n!=$g=fgets(STDIN);print(($g>$n?'-':'+')."\n"))?>= \$\endgroup\$ Apr 12 '13 at 21:51
1
\$\begingroup\$

C: 86 characters

i;main(r){r+=(7*time(0)+3)%100;while(scanf("%d",&i)&&puts(i<r?"+":i>r?"-":"=")&&i-r);}

It is well-behaved, implements a simple LCG and compiles under both Clang (Clang is much more picky than GCC) and GCC.

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

R 70

n=sample(1e2)[1];while(n-(g=scan(n=1)))cat(if(n>g)"+"else"-");cat("=")
\$\endgroup\$
1
\$\begingroup\$

VB.net 146

Dim r,g As Integer:Dim s As String:r=New Random().Next(1,100):Do Until g=r:g=InputBox(s):If g<r Then s="+" Else If r=g Then s="-" Else s="=" Loop

\$\endgroup\$
1
  • \$\begingroup\$ Your code will never choose the number "100", it should be Next(1,101) \$\endgroup\$ Aug 10 '13 at 6:18
1
\$\begingroup\$

Tcl, 96 chars

set n [expr int(rand()*100)+1];while {[gets stdin g]&&$g!=$n} {puts [expr $g<$n?"+":"-"]};puts =

Ok, and now guessing a real number (91 chars):

set n [expr rand()*100+1];while {[gets stdin g]&&$g!=$n} {puts [expr $g<$n?"+":"-"]};puts =

And here a small script to test this: (Solver)

set fd [open "| /usr/local/bin/tclsh hilo.tcl" RDWR]
fconfigure $fd -buffering none
lassign 0\ 100 + -
while 1 {
    puts "-> [set new [expr {(${-} - ${+}) / 2. + ${+}}]]"
    puts $fd $new
    gets $fd in
    puts "<- $in"
    if {$in in {+ -}} {set $in $new} break
}

Change the 2. to 2 for integers.

\$\endgroup\$
0
\$\begingroup\$

Javascript (75 74 chars):

for(n=1+Math.random(a=alert)*100>>0;(g=+prompt())-n;)a('+-'[+(g>n)]);a('=') 
for(n=1+Math.random(a=alert)*100>>0;(g=+prompt())-n;)a(n>g?'+':'-');a('=')

Numbers are actually random

\$\endgroup\$
0
\$\begingroup\$

J: 64 characters

r=.>:?100
while.(t=.{&'<=>'>:*-&r".(1!:1)1)~:'='do.t(1!:2)2 end.t

Doing I/O in J is sort of bulky compared to the rest of the language.

\$\endgroup\$
0
\$\begingroup\$

vbScript 115 110

Randomize:dim n,r,s:r=(Int)((100*Rnd+1)*2):do until(r=n*2):n=inputbox(s):If(n*2>r)Then:s="-":else:s="+":end if:loop

Randomize:dim n,r,s:r=Int(100*Rnd+1)*2:do until r=n*2:n=inputbox(s):If(n*2>r)Then:s="-":else:s="+":end if:loop
\$\endgroup\$
0
\$\begingroup\$

Mathematica 66

n=RandomInteger@100;For[,(i=Input[])!=n,Print@If[n>i,"+","-"]];"="
\$\endgroup\$
0
\$\begingroup\$

GWBASIC, 104

1 RANDOMIZE TIMER:Z=INT(RND*100)+1:WHILE Q<>Z:INPUT Q:IF Q<Z THEN ?"+" ELSE IF Q>Z THEN ?"-"
2 WEND:?"="

(just because I can)

\$\endgroup\$
0
\$\begingroup\$

vba, 95

(immediate window)

randomize:z=int(rnd()*100)+1:while q<>z:q=cint(inputbox(q)):?iif(q<z,"+",iif(q>z,"-","=")):wend
\$\endgroup\$
1
  • \$\begingroup\$ You can use Int instead of CInt. ;-) \$\endgroup\$
    – Gaffi
    Apr 15 '13 at 21:45

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